#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mfp.c,v 1.34 2026/05/19 21:18:11 andvar Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/autoconf.h>
#include <arch/x68k/dev/intiovar.h>
#include <arch/x68k/dev/mfp.h>
static int mfp_match(device_t, cfdata_t, void *);
static void mfp_attach(device_t, device_t, void *);
static int mfp_search(device_t, cfdata_t, const int *, void *);
static void mfp_init(void);
static void mfp_calibrate_delay(void);
CFATTACH_DECL_NEW(mfp, sizeof(struct mfp_softc),
mfp_match, mfp_attach, NULL, NULL);
static int mfp_attached;
static int
mfp_match(device_t parent, cfdata_t cf, void *aux)
{
struct intio_attach_args *ia = aux;
if (strcmp(ia->ia_name, "mfp") != 0)
return 0;
if (mfp_attached)
return (0);
if (ia->ia_addr == INTIOCF_ADDR_DEFAULT)
ia->ia_addr = MFP_ADDR;
if (ia->ia_intr == INTIOCF_INTR_DEFAULT)
ia->ia_addr = MFP_INTR;
if (ia->ia_addr != MFP_ADDR)
return (0);
if (ia->ia_intr != MFP_INTR)
return (0);
return (1);
}
static void
mfp_attach(device_t parent, device_t self, void *aux)
{
struct mfp_softc *sc = device_private(self);
struct intio_attach_args *ia = aux;
int r __diagused;
aprint_normal("\n");
mfp_attached = 1;
sc->sc_bst = ia->ia_bst;
sc->sc_intr = ia->ia_intr;
ia->ia_size = 0x30;
r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE);
#ifdef DIAGNOSTIC
if (r)
panic("IO map for MFP corruption??");
#endif
bus_space_map(ia->ia_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht);
config_search(self, NULL,
CFARGS(.search = mfp_search));
}
static int
mfp_search(device_t parent, cfdata_t cf, const int *loc, void *aux)
{
if (config_probe(parent, cf, __UNCONST(cf->cf_name)))
config_attach(parent, cf, __UNCONST(cf->cf_name), NULL,
CFARGS_NONE);
return 0;
}
void
mfp_config_console(void)
{
mfp_init();
mfp_calibrate_delay();
}
static void
mfp_init(void)
{
mfp_set_vr(MFP_INTR);
mfp_set_iera(0);
mfp_set_ierb(0);
mfp_send_usart(0x41);
mfp_set_tacr(MFP_TIMERA_RESET | MFP_TIMERA_STOP);
mfp_set_tbcr(MFP_TIMERB_RESET | MFP_TIMERB_STOP);
mfp_set_tcdcr(0);
}
extern int delay_divisor;
static void
mfp_calibrate_delay(void)
{
for (delay_divisor = delay_divisor_est(delay_calibration_weight(16));
delay_divisor > 0; delay_divisor--) {
mfp_set_tcdr(255-0);
mfp_set_tcdcr(0x70);
delay(10000);
mfp_set_tcdcr(0);
if ((255 - mfp_get_tcdr()) > 200)
break;
}
}
void
mfp_wait_for_hsync(void)
{
while (mfp_get_gpip() & MFP_GPIP_HSYNC)
__asm("nop");
while (!(mfp_get_gpip() & MFP_GPIP_HSYNC))
__asm("nop");
}
int
mfp_send_usart(int command)
{
while (!(mfp_get_tsr() & MFP_TSR_BE));
mfp_set_udr(command);
return 0;
}
int
mfp_receive_usart(void)
{
while (!(mfp_get_rsr() & MFP_RSR_BF))
__asm("nop");
return mfp_get_udr();
}