/* $NetBSD: iomd.c,v 1.24 2022/09/27 06:36:42 skrll Exp $ */ /* * Copyright (c) 1996-1997 Mark Brinicombe. * Copyright (c) 1997 Causality Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Mark Brinicombe. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * RiscBSD kernel project * * iomd.c * * Probing and configuration for the IOMD * * Created : 10/10/95 * Updated : 18/03/01 for rpckbd as part of the wscons project */ #include __KERNEL_RCSID(0, "$NetBSD: iomd.c,v 1.24 2022/09/27 06:36:42 skrll Exp $"); #include #include #include #include #include #include #include #include #include #include #include "iomd.h" /* * IOMD device. * * This probes and attaches the top level IOMD device. * It then configures any children of the IOMD device. */ /* * IOMD softc structure. * * Contains the device node, bus space tag, handle and address * and the IOMD id. */ struct iomd_softc { device_t sc_dev; /* device node */ bus_space_tag_t sc_iot; /* bus tag */ bus_space_handle_t sc_ioh; /* bus handle */ int sc_id; /* IOMD 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; /* following flag is used in iomd_irq.s ... has to be cleaned up one day ! */ uint32_t arm7500_ioc_found = 0; /* Declare prototypes */ /* * int iomdprint(void *aux, const char *name) * * print configuration info for children */ static int iomdprint(void *aux, const char *name) { /* union iomd_attach_args *ia = aux;*/ return QUIET; } /* * int iomdmatch(device_t parent, cfdata_t cf, void *aux) * * Just return ok for this if it is device 0 */ static int iomdmatch(device_t parent, cfdata_t cf, void *aux) { if (iomd_found) return 0; return 1; } /* * void iomdattach(device_t parent, device_t dev, void *aux) * * Map the IOMD and identify it. * Then configure the child devices based on the IOMD ID. */ static void iomdattach(device_t parent, device_t self, void *aux) { struct iomd_softc *sc = device_private(self); /* struct mainbus_attach_args *mb = aux;*/ int refresh; #if 0 int i, tmp; #endif union iomd_attach_args ia; bus_space_tag_t iot; bus_space_handle_t ioh; /* There can be only 1 IOMD. */ iomd_found = 1; sc->sc_dev = self; iot = sc->sc_iot = &iomd_bs_tag; /* Map the IOMD */ if (bus_space_map(iot, (int) iomd_base, IOMD_SIZE, 0, &ioh)) panic("%s: Cannot map registers", device_xname(self)); sc->sc_ioh = ioh; /* Get the ID */ sc->sc_id = bus_space_read_1(iot, ioh, IOMD_ID0) | (bus_space_read_1(iot, ioh, IOMD_ID1) << 8); aprint_normal(": "); /* Identify it and get the DRAM refresh rate */ 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; /* just in case */ break; } aprint_normal("version %d\n", bus_space_read_1(iot, ioh, IOMD_VERSION)); /* Report the DRAM refresh rate */ 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 /* * No point in reporting this as it may get changed when devices are * attached */ 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 /* Set up the external DMA channels */ /* XXX - this should be machine dependent not IOMD dependent */ switch (sc->sc_id) { case ARM7500_IOC_ID: case ARM7500FE_IOC_ID: break; case RPC600_IOMD_ID: /* DMA channels 2 & 3 are external */ bus_space_write_1(iot, ioh, IOMD_DMAEXT, 0x0c); break; } /* Configure the child devices */ /* Attach clock device */ 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); /* Attach kbd device when configured */ 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); /* Attach iic device */ 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: /* Attach opms device */ 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: /* Attach (ws)qms device */ 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; } } /* End of iomd.c */