xref: /netbsd-src/sys/arch/arm/iomd/iomd.c (revision f82ca6eefb335bf699131a4ebe4cc00c8911db8a)
1*f82ca6eeSskrll /*	$NetBSD: iomd.c,v 1.24 2022/09/27 06:36:42 skrll Exp $	*/
27d4a1addSreinoud 
37d4a1addSreinoud /*
47d4a1addSreinoud  * Copyright (c) 1996-1997 Mark Brinicombe.
57d4a1addSreinoud  * Copyright (c) 1997 Causality Limited
67d4a1addSreinoud  * All rights reserved.
77d4a1addSreinoud  *
87d4a1addSreinoud  * Redistribution and use in source and binary forms, with or without
97d4a1addSreinoud  * modification, are permitted provided that the following conditions
107d4a1addSreinoud  * are met:
117d4a1addSreinoud  * 1. Redistributions of source code must retain the above copyright
127d4a1addSreinoud  *    notice, this list of conditions and the following disclaimer.
137d4a1addSreinoud  * 2. Redistributions in binary form must reproduce the above copyright
147d4a1addSreinoud  *    notice, this list of conditions and the following disclaimer in the
157d4a1addSreinoud  *    documentation and/or other materials provided with the distribution.
167d4a1addSreinoud  * 3. All advertising materials mentioning features or use of this software
177d4a1addSreinoud  *    must display the following acknowledgement:
187d4a1addSreinoud  *	This product includes software developed by Mark Brinicombe.
197d4a1addSreinoud  * 4. The name of the company nor the name of the author may be used to
207d4a1addSreinoud  *    endorse or promote products derived from this software without specific
217d4a1addSreinoud  *    prior written permission.
227d4a1addSreinoud  *
237d4a1addSreinoud  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
247d4a1addSreinoud  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
257d4a1addSreinoud  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
267d4a1addSreinoud  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
277d4a1addSreinoud  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
287d4a1addSreinoud  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
297d4a1addSreinoud  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
307d4a1addSreinoud  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
317d4a1addSreinoud  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
327d4a1addSreinoud  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
337d4a1addSreinoud  * SUCH DAMAGE.
347d4a1addSreinoud  *
357d4a1addSreinoud  * RiscBSD kernel project
367d4a1addSreinoud  *
377d4a1addSreinoud  * iomd.c
387d4a1addSreinoud  *
397d4a1addSreinoud  * Probing and configuration for the IOMD
407d4a1addSreinoud  *
417d4a1addSreinoud  * Created      : 10/10/95
427d4a1addSreinoud  * Updated	: 18/03/01 for rpckbd as part of the wscons project
437d4a1addSreinoud  */
447d4a1addSreinoud 
4508716eaeSlukem #include <sys/cdefs.h>
46*f82ca6eeSskrll __KERNEL_RCSID(0, "$NetBSD: iomd.c,v 1.24 2022/09/27 06:36:42 skrll Exp $");
4708716eaeSlukem 
487d4a1addSreinoud #include <sys/param.h>
497d4a1addSreinoud #include <sys/systm.h>
507d4a1addSreinoud #include <sys/kernel.h>
517d4a1addSreinoud #include <sys/conf.h>
527d4a1addSreinoud #include <sys/device.h>
53ed9977b1Sdyoung #include <sys/bus.h>
547d4a1addSreinoud #include <machine/cpu.h>
5528466919Sthorpej #include <machine/intr.h>
567d4a1addSreinoud #include <arm/iomd/iomdreg.h>
577d4a1addSreinoud #include <arm/iomd/iomdvar.h>
587d4a1addSreinoud 
597d4a1addSreinoud #include "iomd.h"
607d4a1addSreinoud 
617d4a1addSreinoud /*
627d4a1addSreinoud  * IOMD device.
637d4a1addSreinoud  *
647d4a1addSreinoud  * This probes and attaches the top level IOMD device.
657d4a1addSreinoud  * It then configures any children of the IOMD device.
667d4a1addSreinoud  */
677d4a1addSreinoud 
687d4a1addSreinoud /*
697d4a1addSreinoud  * IOMD softc structure.
707d4a1addSreinoud  *
717d4a1addSreinoud  * Contains the device node, bus space tag, handle and address
727d4a1addSreinoud  * and the IOMD id.
737d4a1addSreinoud  */
747d4a1addSreinoud 
757d4a1addSreinoud struct iomd_softc {
76e0f866efSskrll 	device_t 		sc_dev;	/* device node */
777d4a1addSreinoud 	bus_space_tag_t		sc_iot;	/* bus tag */
787d4a1addSreinoud 	bus_space_handle_t	sc_ioh;	/* bus handle */
797d4a1addSreinoud 	int			sc_id;	/* IOMD id */
807d4a1addSreinoud };
817d4a1addSreinoud 
82e0f866efSskrll static int iomdmatch(device_t parent, cfdata_t cf, void *aux);
83e0f866efSskrll static void iomdattach(device_t parent, device_t self, void *aux);
84758ec341Sbjh21 static int iomdprint(void *aux, const char *iomdbus);
857d4a1addSreinoud 
86e0f866efSskrll CFATTACH_DECL_NEW(iomd, sizeof(struct iomd_softc),
87bd5bb465Sthorpej     iomdmatch, iomdattach, NULL, NULL);
887d4a1addSreinoud 
897d4a1addSreinoud extern struct bus_space iomd_bs_tag;
907d4a1addSreinoud 
917d4a1addSreinoud int       iomd_found;
929ea87d7dSskrll uint32_t iomd_base = IOMD_BASE;
937d4a1addSreinoud 
947d4a1addSreinoud /* following flag is used in iomd_irq.s ... has to be cleaned up one day ! */
959ea87d7dSskrll uint32_t arm7500_ioc_found = 0;
967d4a1addSreinoud 
977d4a1addSreinoud 
987d4a1addSreinoud /* Declare prototypes */
997d4a1addSreinoud 
1007d4a1addSreinoud /*
1017d4a1addSreinoud  * int iomdprint(void *aux, const char *name)
1027d4a1addSreinoud  *
1037d4a1addSreinoud  * print configuration info for children
1047d4a1addSreinoud  */
1057d4a1addSreinoud 
1067d4a1addSreinoud static int
iomdprint(void * aux,const char * name)107758ec341Sbjh21 iomdprint(void *aux, const char *name)
1087d4a1addSreinoud {
1097d4a1addSreinoud /*	union iomd_attach_args *ia = aux;*/
1107d4a1addSreinoud 
111758ec341Sbjh21 	return QUIET;
1127d4a1addSreinoud }
1137d4a1addSreinoud 
1147d4a1addSreinoud /*
115e0f866efSskrll  * int iomdmatch(device_t parent, cfdata_t cf, void *aux)
1167d4a1addSreinoud  *
1177d4a1addSreinoud  * Just return ok for this if it is device 0
1187d4a1addSreinoud  */
1197d4a1addSreinoud 
1207d4a1addSreinoud static int
iomdmatch(device_t parent,cfdata_t cf,void * aux)121e0f866efSskrll iomdmatch(device_t parent, cfdata_t cf, void *aux)
1227d4a1addSreinoud {
123758ec341Sbjh21 
1247d4a1addSreinoud 	if (iomd_found)
1257d4a1addSreinoud 		return 0;
1267d4a1addSreinoud 	return 1;
1277d4a1addSreinoud }
1287d4a1addSreinoud 
1297d4a1addSreinoud 
1307d4a1addSreinoud /*
131e0f866efSskrll  * void iomdattach(device_t parent, device_t dev, void *aux)
1327d4a1addSreinoud  *
1337d4a1addSreinoud  * Map the IOMD and identify it.
1347d4a1addSreinoud  * Then configure the child devices based on the IOMD ID.
1357d4a1addSreinoud  */
1367d4a1addSreinoud 
1377d4a1addSreinoud static void
iomdattach(device_t parent,device_t self,void * aux)138e0f866efSskrll iomdattach(device_t parent, device_t self, void *aux)
1397d4a1addSreinoud {
140e0f866efSskrll 	struct iomd_softc *sc = device_private(self);
1417d4a1addSreinoud /*	struct mainbus_attach_args *mb = aux;*/
1427d4a1addSreinoud 	int refresh;
1437d4a1addSreinoud #if 0
144bd4a91a8Sbjh21 	int i, tmp;
1457d4a1addSreinoud #endif
1467d4a1addSreinoud 	union iomd_attach_args ia;
1477d4a1addSreinoud 	bus_space_tag_t iot;
1487d4a1addSreinoud 	bus_space_handle_t ioh;
1497d4a1addSreinoud 
1507d4a1addSreinoud 	/* There can be only 1 IOMD. */
1517d4a1addSreinoud 	iomd_found = 1;
1527d4a1addSreinoud 
153e0f866efSskrll 	sc->sc_dev = self;
1547d4a1addSreinoud 	iot = sc->sc_iot = &iomd_bs_tag;
1557d4a1addSreinoud 
1567d4a1addSreinoud 	/* Map the IOMD */
1577d4a1addSreinoud 	if (bus_space_map(iot, (int) iomd_base, IOMD_SIZE, 0, &ioh))
158bb9f3ca9Sskrll 		panic("%s: Cannot map registers", device_xname(self));
1597d4a1addSreinoud 
1607d4a1addSreinoud 	sc->sc_ioh = ioh;
1617d4a1addSreinoud 
1627d4a1addSreinoud 	/* Get the ID */
1637d4a1addSreinoud 	sc->sc_id = bus_space_read_1(iot, ioh, IOMD_ID0)
1647d4a1addSreinoud 		  | (bus_space_read_1(iot, ioh, IOMD_ID1) << 8);
165e0f866efSskrll 	aprint_normal(": ");
1667d4a1addSreinoud 
1677d4a1addSreinoud 	/* Identify it and get the DRAM refresh rate */
1687d4a1addSreinoud 	switch (sc->sc_id) {
1697d4a1addSreinoud 	case ARM7500_IOC_ID:
170e0f866efSskrll 		aprint_normal("ARM7500 IOMD ");
1717d4a1addSreinoud 		refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
1727d4a1addSreinoud 		arm7500_ioc_found = 1;
1737d4a1addSreinoud 		break;
1747d4a1addSreinoud 	case ARM7500FE_IOC_ID:
175e0f866efSskrll 		aprint_normal("ARM7500FE IOMD ");
1767d4a1addSreinoud 		refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
1777d4a1addSreinoud 		arm7500_ioc_found = 1;
1787d4a1addSreinoud 		break;
1797d4a1addSreinoud 	case RPC600_IOMD_ID:
180e0f866efSskrll 		aprint_normal("IOMD20 ");
1817d4a1addSreinoud 		refresh = bus_space_read_1(iot, ioh, IOMD_VREFCR) & 0x09;
1827d4a1addSreinoud 		arm7500_ioc_found = 0;
1837d4a1addSreinoud 		break;
1847d4a1addSreinoud 	default:
185e0f866efSskrll 		aprint_normal("Unknown IOMD ID=%04x ", sc->sc_id);
1867d4a1addSreinoud 		refresh = -1;
1877d4a1addSreinoud 		arm7500_ioc_found = 0;		/* just in case */
1887d4a1addSreinoud 		break;
1897d4a1addSreinoud 	}
190e0f866efSskrll 	aprint_normal("version %d\n", bus_space_read_1(iot, ioh, IOMD_VERSION));
1917d4a1addSreinoud 
1927d4a1addSreinoud 	/* Report the DRAM refresh rate */
193bb9f3ca9Sskrll 	aprint_normal("%s: ", device_xname(self));
194e0f866efSskrll 	aprint_normal("DRAM refresh=");
1957d4a1addSreinoud 	switch (refresh) {
1967d4a1addSreinoud 	case 0x0:
197e0f866efSskrll 		aprint_normal("off");
1987d4a1addSreinoud 		break;
1997d4a1addSreinoud 	case 0x1:
200e0f866efSskrll 		aprint_normal("16us");
2017d4a1addSreinoud 		break;
2027d4a1addSreinoud 	case 0x2:
203e0f866efSskrll 		aprint_normal("32us");
2047d4a1addSreinoud 		break;
2057d4a1addSreinoud 	case 0x4:
206e0f866efSskrll 		aprint_normal("64us");
2077d4a1addSreinoud 		break;
2087d4a1addSreinoud 	case 0x8:
209e0f866efSskrll 		aprint_normal("128us");
2107d4a1addSreinoud 		break;
2117d4a1addSreinoud 	default:
212e0f866efSskrll 		aprint_normal("unknown [%02x]", refresh);
2137d4a1addSreinoud 		break;
2147d4a1addSreinoud 	}
2157d4a1addSreinoud 
216e0f866efSskrll 	aprint_normal("\n");
2177d4a1addSreinoud #if 0
2187d4a1addSreinoud 	/*
2197d4a1addSreinoud 	 * No point in reporting this as it may get changed when devices are
2207d4a1addSreinoud 	 * attached
2217d4a1addSreinoud 	 */
222bd4a91a8Sbjh21 	tmp = bus_space_read_1(iot, ioh, IOMD_IOTCR);
223bb9f3ca9Sskrll 	aprint_normal("%s: I/O timings: combo %c, NPCCS1/2 %c", device_xname(self),
224bd4a91a8Sbjh21 	    'A' + ((tmp >>2) & 3), 'A' + (tmp & 3));
225bd4a91a8Sbjh21 	tmp = bus_space_read_1(iot, ioh, IOMD_ECTCR);
226e0f866efSskrll 	aprint_normal(", EASI ");
227bd4a91a8Sbjh21 	for (i = 0; i < 8; i++, tmp >>= 1)
228e0f866efSskrll 		aprint_normal("%c", 'A' + ((tmp & 1) << 2));
229bd4a91a8Sbjh21 	tmp = bus_space_read_1(iot, ioh, IOMD_DMATCR);
230e0f866efSskrll 	aprint_normal(", DMA ");
231bd4a91a8Sbjh21 	for (i = 0; i < 4; i++, tmp >>= 2)
232e0f866efSskrll 		aprint_normal("%c", 'A' + (tmp & 3));
233e0f866efSskrll 	aprint_normal("\n");
234bd4a91a8Sbjh21 #endif
2357d4a1addSreinoud 
2367d4a1addSreinoud 	/* Set up the external DMA channels */
2374cbd24b2Swiz 	/* XXX - this should be machine dependent not IOMD dependent */
2387d4a1addSreinoud 	switch (sc->sc_id) {
2397d4a1addSreinoud 	case ARM7500_IOC_ID:
2407d4a1addSreinoud 	case ARM7500FE_IOC_ID:
2417d4a1addSreinoud 		break;
2427d4a1addSreinoud 	case RPC600_IOMD_ID:
2437d4a1addSreinoud 		/* DMA channels 2 & 3 are external */
2447d4a1addSreinoud 		bus_space_write_1(iot, ioh, IOMD_DMAEXT, 0x0c);
2457d4a1addSreinoud 		break;
2467d4a1addSreinoud    	}
2477d4a1addSreinoud 
2487d4a1addSreinoud 	/* Configure the child devices */
2497d4a1addSreinoud 
2507d4a1addSreinoud 	/* Attach clock device */
2517d4a1addSreinoud 
2527d4a1addSreinoud 	ia.ia_clk.ca_name = "clk";
2537d4a1addSreinoud 	ia.ia_clk.ca_iot = iot;
2547d4a1addSreinoud 	ia.ia_clk.ca_ioh = ioh;
255c7fb772bSthorpej 	config_found(self, &ia, iomdprint, CFARGS_NONE);
2567d4a1addSreinoud 
2577d4a1addSreinoud 	/* Attach kbd device when configured */
258df8ccd8dSbjh21 	if (bus_space_subregion(iot, ioh, IOMD_KBDDAT, 8, &ia.ia_kbd.ka_ioh))
259bb9f3ca9Sskrll 		panic("%s: Cannot map kbd registers", device_xname(self));
2607d4a1addSreinoud 	ia.ia_kbd.ka_name = "kbd";
2617d4a1addSreinoud 	ia.ia_kbd.ka_iot = iot;
2627d4a1addSreinoud 	ia.ia_kbd.ka_rxirq = IRQ_KBDRX;
2637d4a1addSreinoud 	ia.ia_kbd.ka_txirq = IRQ_KBDTX;
264c7fb772bSthorpej 	config_found(self, &ia, iomdprint, CFARGS_NONE);
2657d4a1addSreinoud 
2667d4a1addSreinoud 	/* Attach iic device */
2677d4a1addSreinoud 
268df8ccd8dSbjh21 	if (bus_space_subregion(iot, ioh, IOMD_IOCR, 4, &ia.ia_iic.ia_ioh))
269bb9f3ca9Sskrll 		panic("%s: Cannot map iic registers", device_xname(self));
2707d4a1addSreinoud 	ia.ia_iic.ia_name = "iic";
2717d4a1addSreinoud 	ia.ia_iic.ia_iot = iot;
2727d4a1addSreinoud 	ia.ia_iic.ia_irq = -1;
273c7fb772bSthorpej 	config_found(self, &ia, iomdprint, CFARGS_NONE);
2747d4a1addSreinoud 
2757d4a1addSreinoud 	switch (sc->sc_id) {
2767d4a1addSreinoud 	case ARM7500_IOC_ID:
2777d4a1addSreinoud 	case ARM7500FE_IOC_ID:
278d79f4782Swiz 		/* Attach opms device */
2797d4a1addSreinoud 
280df8ccd8dSbjh21 		if (bus_space_subregion(iot, ioh, IOMD_MSDATA, 8,
281ed4b80b1Sbjh21 			&ia.ia_opms.pa_ioh))
282bb9f3ca9Sskrll 			panic("%s: Cannot map opms registers", device_xname(self));
283d79f4782Swiz 		ia.ia_opms.pa_name = "opms";
284d79f4782Swiz 		ia.ia_opms.pa_iot = iot;
285d79f4782Swiz 		ia.ia_opms.pa_irq = IRQ_MSDRX;
286c7fb772bSthorpej 		config_found(self, &ia, iomdprint, CFARGS_NONE);
2877d4a1addSreinoud 		break;
2887d4a1addSreinoud 	case RPC600_IOMD_ID:
2897d4a1addSreinoud 		/* Attach (ws)qms device */
2907d4a1addSreinoud 
291df8ccd8dSbjh21 		if (bus_space_subregion(iot, ioh, IOMD_MOUSEX, 8,
292ed4b80b1Sbjh21 			&ia.ia_qms.qa_ioh))
293bb9f3ca9Sskrll 			panic("%s: Cannot map qms registers", device_xname(self));
2947d4a1addSreinoud 
2957d4a1addSreinoud 		if (bus_space_map(iot, IO_MOUSE_BUTTONS, 4, 0, &ia.ia_qms.qa_ioh_but))
296bb9f3ca9Sskrll 			panic("%s: Cannot map registers", device_xname(self));
2977d4a1addSreinoud 		ia.ia_qms.qa_name = "qms";
2987d4a1addSreinoud 		ia.ia_qms.qa_iot = iot;
2997d4a1addSreinoud 		ia.ia_qms.qa_irq = IRQ_VSYNC;
300c7fb772bSthorpej 		config_found(self, &ia, iomdprint, CFARGS_NONE);
3017d4a1addSreinoud 		break;
3027d4a1addSreinoud 	}
3037d4a1addSreinoud }
3047d4a1addSreinoud 
3057d4a1addSreinoud /* End of iomd.c */
306