#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: iomd.c,v 1.24 2022/09/27 06:36:42 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <arm/iomd/iomdreg.h>
#include <arm/iomd/iomdvar.h>
#include "iomd.h"
struct iomd_softc {
device_t sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
int sc_id;
};
static int iomdmatch(device_t parent, cfdata_t cf, void *aux);
static void iomdattach(device_t parent, device_t self, void *aux);
static int iomdprint(void *aux, const char *iomdbus);
CFATTACH_DECL_NEW(iomd, sizeof(struct iomd_softc),
iomdmatch, iomdattach, NULL, NULL);
extern struct bus_space iomd_bs_tag;
int iomd_found;
uint32_t iomd_base = IOMD_BASE;
uint32_t arm7500_ioc_found = 0;
static int
iomdprint(void *aux, const char *name)
{
return QUIET;
}
static int
iomdmatch(device_t parent, cfdata_t cf, void *aux)
{
if (iomd_found)
return 0;
return 1;
}
static void
iomdattach(device_t parent, device_t self, void *aux)
{
struct iomd_softc *sc = device_private(self);
int refresh;
#if 0
int i, tmp;
#endif
union iomd_attach_args ia;
bus_space_tag_t iot;
bus_space_handle_t ioh;
iomd_found = 1;
sc->sc_dev = self;
iot = sc->sc_iot = &iomd_bs_tag;
if (bus_space_map(iot, (int) iomd_base, IOMD_SIZE, 0, &ioh))
panic("%s: Cannot map registers", device_xname(self));
sc->sc_ioh = ioh;
sc->sc_id = bus_space_read_1(iot, ioh, IOMD_ID0)
| (bus_space_read_1(iot, ioh, IOMD_ID1) << 8);
aprint_normal(": ");
switch (sc->sc_id) {
case ARM7500_IOC_ID:
aprint_normal("ARM7500 IOMD ");
refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
arm7500_ioc_found = 1;
break;
case ARM7500FE_IOC_ID:
aprint_normal("ARM7500FE IOMD ");
refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
arm7500_ioc_found = 1;
break;
case RPC600_IOMD_ID:
aprint_normal("IOMD20 ");
refresh = bus_space_read_1(iot, ioh, IOMD_VREFCR) & 0x09;
arm7500_ioc_found = 0;
break;
default:
aprint_normal("Unknown IOMD ID=%04x ", sc->sc_id);
refresh = -1;
arm7500_ioc_found = 0;
break;
}
aprint_normal("version %d\n", bus_space_read_1(iot, ioh, IOMD_VERSION));
aprint_normal("%s: ", device_xname(self));
aprint_normal("DRAM refresh=");
switch (refresh) {
case 0x0:
aprint_normal("off");
break;
case 0x1:
aprint_normal("16us");
break;
case 0x2:
aprint_normal("32us");
break;
case 0x4:
aprint_normal("64us");
break;
case 0x8:
aprint_normal("128us");
break;
default:
aprint_normal("unknown [%02x]", refresh);
break;
}
aprint_normal("\n");
#if 0
tmp = bus_space_read_1(iot, ioh, IOMD_IOTCR);
aprint_normal("%s: I/O timings: combo %c, NPCCS1/2 %c", device_xname(self),
'A' + ((tmp >>2) & 3), 'A' + (tmp & 3));
tmp = bus_space_read_1(iot, ioh, IOMD_ECTCR);
aprint_normal(", EASI ");
for (i = 0; i < 8; i++, tmp >>= 1)
aprint_normal("%c", 'A' + ((tmp & 1) << 2));
tmp = bus_space_read_1(iot, ioh, IOMD_DMATCR);
aprint_normal(", DMA ");
for (i = 0; i < 4; i++, tmp >>= 2)
aprint_normal("%c", 'A' + (tmp & 3));
aprint_normal("\n");
#endif
switch (sc->sc_id) {
case ARM7500_IOC_ID:
case ARM7500FE_IOC_ID:
break;
case RPC600_IOMD_ID:
bus_space_write_1(iot, ioh, IOMD_DMAEXT, 0x0c);
break;
}
ia.ia_clk.ca_name = "clk";
ia.ia_clk.ca_iot = iot;
ia.ia_clk.ca_ioh = ioh;
config_found(self, &ia, iomdprint, CFARGS_NONE);
if (bus_space_subregion(iot, ioh, IOMD_KBDDAT, 8, &ia.ia_kbd.ka_ioh))
panic("%s: Cannot map kbd registers", device_xname(self));
ia.ia_kbd.ka_name = "kbd";
ia.ia_kbd.ka_iot = iot;
ia.ia_kbd.ka_rxirq = IRQ_KBDRX;
ia.ia_kbd.ka_txirq = IRQ_KBDTX;
config_found(self, &ia, iomdprint, CFARGS_NONE);
if (bus_space_subregion(iot, ioh, IOMD_IOCR, 4, &ia.ia_iic.ia_ioh))
panic("%s: Cannot map iic registers", device_xname(self));
ia.ia_iic.ia_name = "iic";
ia.ia_iic.ia_iot = iot;
ia.ia_iic.ia_irq = -1;
config_found(self, &ia, iomdprint, CFARGS_NONE);
switch (sc->sc_id) {
case ARM7500_IOC_ID:
case ARM7500FE_IOC_ID:
if (bus_space_subregion(iot, ioh, IOMD_MSDATA, 8,
&ia.ia_opms.pa_ioh))
panic("%s: Cannot map opms registers", device_xname(self));
ia.ia_opms.pa_name = "opms";
ia.ia_opms.pa_iot = iot;
ia.ia_opms.pa_irq = IRQ_MSDRX;
config_found(self, &ia, iomdprint, CFARGS_NONE);
break;
case RPC600_IOMD_ID:
if (bus_space_subregion(iot, ioh, IOMD_MOUSEX, 8,
&ia.ia_qms.qa_ioh))
panic("%s: Cannot map qms registers", device_xname(self));
if (bus_space_map(iot, IO_MOUSE_BUTTONS, 4, 0, &ia.ia_qms.qa_ioh_but))
panic("%s: Cannot map registers", device_xname(self));
ia.ia_qms.qa_name = "qms";
ia.ia_qms.qa_iot = iot;
ia.ia_qms.qa_irq = IRQ_VSYNC;
config_found(self, &ia, iomdprint, CFARGS_NONE);
break;
}
}