iomd.c revision 1.18
1/*	$NetBSD: iomd.c,v 1.18 2012/05/10 09:56:27 skrll Exp $	*/
2
3/*
4 * Copyright (c) 1996-1997 Mark Brinicombe.
5 * Copyright (c) 1997 Causality Limited
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Mark Brinicombe.
19 * 4. The name of the company nor the name of the author may be used to
20 *    endorse or promote products derived from this software without specific
21 *    prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * RiscBSD kernel project
36 *
37 * iomd.c
38 *
39 * Probing and configuration for the IOMD
40 *
41 * Created      : 10/10/95
42 * Updated	: 18/03/01 for rpckbd as part of the wscons project
43 */
44
45#include <sys/cdefs.h>
46__KERNEL_RCSID(0, "$NetBSD: iomd.c,v 1.18 2012/05/10 09:56:27 skrll Exp $");
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#include <sys/conf.h>
52#include <sys/malloc.h>
53#include <sys/device.h>
54#include <sys/bus.h>
55#include <machine/cpu.h>
56#include <machine/intr.h>
57#include <arm/iomd/iomdreg.h>
58#include <arm/iomd/iomdvar.h>
59
60#include "iomd.h"
61
62/*
63 * IOMD device.
64 *
65 * This probes and attaches the top level IOMD device.
66 * It then configures any children of the IOMD device.
67 */
68
69/*
70 * IOMD softc structure.
71 *
72 * Contains the device node, bus space tag, handle and address
73 * and the IOMD id.
74 */
75
76struct iomd_softc {
77	struct device 		sc_dev;	/* device node */
78	bus_space_tag_t		sc_iot;	/* bus tag */
79	bus_space_handle_t	sc_ioh;	/* bus handle */
80	int			sc_id;	/* IOMD id */
81};
82
83static int iomdmatch(struct device *parent, struct cfdata *cf,
84                             void *aux);
85static void iomdattach(struct device *parent, struct device *self,
86                             void *aux);
87static int iomdprint(void *aux, const char *iomdbus);
88
89CFATTACH_DECL(iomd, sizeof(struct iomd_softc),
90    iomdmatch, iomdattach, NULL, NULL);
91
92extern struct bus_space iomd_bs_tag;
93
94int       iomd_found;
95uint32_t iomd_base = IOMD_BASE;
96
97/* following flag is used in iomd_irq.s ... has to be cleaned up one day ! */
98uint32_t arm7500_ioc_found = 0;
99
100
101/* Declare prototypes */
102
103/*
104 * int iomdprint(void *aux, const char *name)
105 *
106 * print configuration info for children
107 */
108
109static int
110iomdprint(void *aux, const char *name)
111{
112/*	union iomd_attach_args *ia = aux;*/
113
114	return QUIET;
115}
116
117/*
118 * int iomdmatch(struct device *parent, struct cfdata *cf, void *aux)
119 *
120 * Just return ok for this if it is device 0
121 */
122
123static int
124iomdmatch(struct device *parent, struct cfdata *cf, void *aux)
125{
126
127	if (iomd_found)
128		return 0;
129	return 1;
130}
131
132
133/*
134 * void iomdattach(struct device *parent, struct device *dev, void *aux)
135 *
136 * Map the IOMD and identify it.
137 * Then configure the child devices based on the IOMD ID.
138 */
139
140static void
141iomdattach(struct device *parent, struct device *self, void *aux)
142{
143	struct iomd_softc *sc = (struct iomd_softc *)self;
144/*	struct mainbus_attach_args *mb = aux;*/
145	int refresh;
146#if 0
147	int i, tmp;
148#endif
149	union iomd_attach_args ia;
150	bus_space_tag_t iot;
151	bus_space_handle_t ioh;
152
153	/* There can be only 1 IOMD. */
154	iomd_found = 1;
155
156	iot = sc->sc_iot = &iomd_bs_tag;
157
158	/* Map the IOMD */
159	if (bus_space_map(iot, (int) iomd_base, IOMD_SIZE, 0, &ioh))
160		panic("%s: Cannot map registers", self->dv_xname);
161
162	sc->sc_ioh = ioh;
163
164	/* Get the ID */
165	sc->sc_id = bus_space_read_1(iot, ioh, IOMD_ID0)
166		  | (bus_space_read_1(iot, ioh, IOMD_ID1) << 8);
167	printf(": ");
168
169	/* Identify it and get the DRAM refresh rate */
170	switch (sc->sc_id) {
171	case ARM7500_IOC_ID:
172		printf("ARM7500 IOMD ");
173		refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
174		arm7500_ioc_found = 1;
175		break;
176	case ARM7500FE_IOC_ID:
177		printf("ARM7500FE IOMD ");
178		refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
179		arm7500_ioc_found = 1;
180		break;
181	case RPC600_IOMD_ID:
182		printf("IOMD20 ");
183		refresh = bus_space_read_1(iot, ioh, IOMD_VREFCR) & 0x09;
184		arm7500_ioc_found = 0;
185		break;
186	default:
187		printf("Unknown IOMD ID=%04x ", sc->sc_id);
188		refresh = -1;
189		arm7500_ioc_found = 0;		/* just in case */
190		break;
191	}
192	printf("version %d\n", bus_space_read_1(iot, ioh, IOMD_VERSION));
193
194	/* Report the DRAM refresh rate */
195	printf("%s: ", self->dv_xname);
196	printf("DRAM refresh=");
197	switch (refresh) {
198	case 0x0:
199		printf("off");
200		break;
201	case 0x1:
202		printf("16us");
203		break;
204	case 0x2:
205		printf("32us");
206		break;
207	case 0x4:
208		printf("64us");
209		break;
210	case 0x8:
211		printf("128us");
212		break;
213	default:
214		printf("unknown [%02x]", refresh);
215		break;
216	}
217
218	printf("\n");
219#if 0
220	/*
221	 * No point in reporting this as it may get changed when devices are
222	 * attached
223	 */
224	tmp = bus_space_read_1(iot, ioh, IOMD_IOTCR);
225	printf("%s: I/O timings: combo %c, NPCCS1/2 %c", self->dv_xname,
226	    'A' + ((tmp >>2) & 3), 'A' + (tmp & 3));
227	tmp = bus_space_read_1(iot, ioh, IOMD_ECTCR);
228	printf(", EASI ");
229	for (i = 0; i < 8; i++, tmp >>= 1)
230		printf("%c", 'A' + ((tmp & 1) << 2));
231	tmp = bus_space_read_1(iot, ioh, IOMD_DMATCR);
232	printf(", DMA ");
233	for (i = 0; i < 4; i++, tmp >>= 2)
234		printf("%c", 'A' + (tmp & 3));
235	printf("\n");
236#endif
237
238	/* Set up the external DMA channels */
239	/* XXX - this should be machine dependent not IOMD dependent */
240	switch (sc->sc_id) {
241	case ARM7500_IOC_ID:
242	case ARM7500FE_IOC_ID:
243		break;
244	case RPC600_IOMD_ID:
245		/* DMA channels 2 & 3 are external */
246		bus_space_write_1(iot, ioh, IOMD_DMAEXT, 0x0c);
247		break;
248   	}
249
250	/* Configure the child devices */
251
252	/* Attach clock device */
253
254	ia.ia_clk.ca_name = "clk";
255	ia.ia_clk.ca_iot = iot;
256	ia.ia_clk.ca_ioh = ioh;
257	config_found(self, &ia, iomdprint);
258
259	/* Attach kbd device when configured */
260	if (bus_space_subregion(iot, ioh, IOMD_KBDDAT, 8, &ia.ia_kbd.ka_ioh))
261		panic("%s: Cannot map kbd registers", self->dv_xname);
262	ia.ia_kbd.ka_name = "kbd";
263	ia.ia_kbd.ka_iot = iot;
264	ia.ia_kbd.ka_rxirq = IRQ_KBDRX;
265	ia.ia_kbd.ka_txirq = IRQ_KBDTX;
266	config_found(self, &ia, iomdprint);
267
268	/* Attach iic device */
269
270	if (bus_space_subregion(iot, ioh, IOMD_IOCR, 4, &ia.ia_iic.ia_ioh))
271		panic("%s: Cannot map iic registers", self->dv_xname);
272	ia.ia_iic.ia_name = "iic";
273	ia.ia_iic.ia_iot = iot;
274	ia.ia_iic.ia_irq = -1;
275	config_found(self, &ia, iomdprint);
276
277	switch (sc->sc_id) {
278	case ARM7500_IOC_ID:
279	case ARM7500FE_IOC_ID:
280		/* Attach opms device */
281
282		if (bus_space_subregion(iot, ioh, IOMD_MSDATA, 8,
283			&ia.ia_opms.pa_ioh))
284			panic("%s: Cannot map opms registers", self->dv_xname);
285		ia.ia_opms.pa_name = "opms";
286		ia.ia_opms.pa_iot = iot;
287		ia.ia_opms.pa_irq = IRQ_MSDRX;
288		config_found(self, &ia, iomdprint);
289		break;
290	case RPC600_IOMD_ID:
291		/* Attach (ws)qms device */
292
293		if (bus_space_subregion(iot, ioh, IOMD_MOUSEX, 8,
294			&ia.ia_qms.qa_ioh))
295			panic("%s: Cannot map qms registers", self->dv_xname);
296
297		if (bus_space_map(iot, IO_MOUSE_BUTTONS, 4, 0, &ia.ia_qms.qa_ioh_but))
298			panic("%s: Cannot map registers", self->dv_xname);
299		ia.ia_qms.qa_name = "qms";
300		ia.ia_qms.qa_iot = iot;
301		ia.ia_qms.qa_irq = IRQ_VSYNC;
302		config_found(self, &ia, iomdprint);
303		break;
304	}
305}
306
307/* End of iomd.c */
308