iomd.c revision 1.1 1 /* $NetBSD: iomd.c,v 1.1 2001/10/05 22:27:40 reinoud 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/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/conf.h>
49 #include <sys/malloc.h>
50 #include <sys/device.h>
51 #include <machine/bus.h>
52 #include <machine/cpu.h>
53 #include <machine/irqhandler.h>
54 #include <arm/iomd/iomdreg.h>
55 #include <arm/iomd/iomdvar.h>
56
57 #include "iomd.h"
58
59 /*
60 * IOMD device.
61 *
62 * This probes and attaches the top level IOMD device.
63 * It then configures any children of the IOMD device.
64 */
65
66 /*
67 * IOMD softc structure.
68 *
69 * Contains the device node, bus space tag, handle and address
70 * and the IOMD id.
71 */
72
73 struct iomd_softc {
74 struct device sc_dev; /* device node */
75 bus_space_tag_t sc_iot; /* bus tag */
76 bus_space_handle_t sc_ioh; /* bus handle */
77 int sc_id; /* IOMD id */
78 };
79
80 static int iomdmatch __P((struct device *parent, struct cfdata *cf,
81 void *aux));
82 static void iomdattach __P((struct device *parent, struct device *self,
83 void *aux));
84 static int iomdprint __P((void *aux, const char *iomdbus));
85
86 struct cfattach iomd_ca = {
87 sizeof(struct iomd_softc), iomdmatch, iomdattach
88 };
89
90 extern struct bus_space iomd_bs_tag;
91
92 int iomd_found;
93 u_int32_t iomd_base = IOMD_BASE;
94
95 /* following flag is used in iomd_irq.s ... has to be cleaned up one day ! */
96 u_int32_t arm7500_ioc_found = 0;
97
98
99 /* Declare prototypes */
100
101 /*
102 * int iomdprint(void *aux, const char *name)
103 *
104 * print configuration info for children
105 */
106
107 static int
108 iomdprint(aux, name)
109 void *aux;
110 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
123 static int
124 iomdmatch(parent, cf, aux)
125 struct device *parent;
126 struct cfdata *cf;
127 void *aux;
128 {
129 if (iomd_found)
130 return 0;
131 return 1;
132 }
133
134
135 /*
136 * void iomdattach(struct device *parent, struct device *dev, void *aux)
137 *
138 * Map the IOMD and identify it.
139 * Then configure the child devices based on the IOMD ID.
140 */
141
142 static void
143 iomdattach(parent, self, aux)
144 struct device *parent;
145 struct device *self;
146 void *aux;
147 {
148 struct iomd_softc *sc = (struct iomd_softc *)self;
149 /* struct mainbus_attach_args *mb = aux;*/
150 int refresh;
151 #if 0
152 int dma_time;
153 int combo_time;
154 int loop;
155 #endif
156 union iomd_attach_args ia;
157 bus_space_tag_t iot;
158 bus_space_handle_t ioh;
159
160 /* There can be only 1 IOMD. */
161 iomd_found = 1;
162
163 iot = sc->sc_iot = &iomd_bs_tag;
164
165 /* Map the IOMD */
166 if (bus_space_map(iot, (int) iomd_base, IOMD_SIZE, 0, &ioh))
167 panic("%s: Cannot map registers\n", self->dv_xname);
168
169 sc->sc_ioh = ioh;
170
171 /* Get the ID */
172 sc->sc_id = bus_space_read_1(iot, ioh, IOMD_ID0)
173 | (bus_space_read_1(iot, ioh, IOMD_ID1) << 8);
174 printf(": ");
175
176 /* Identify it and get the DRAM refresh rate */
177 switch (sc->sc_id) {
178 case ARM7500_IOC_ID:
179 printf("ARM7500 IOMD ");
180 refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
181 arm7500_ioc_found = 1;
182 break;
183 case ARM7500FE_IOC_ID:
184 printf("ARM7500FE IOMD ");
185 refresh = bus_space_read_1(iot, ioh, IOMD_REFCR) & 0x0f;
186 arm7500_ioc_found = 1;
187 break;
188 case RPC600_IOMD_ID:
189 printf("IOMD20 ");
190 refresh = bus_space_read_1(iot, ioh, IOMD_VREFCR) & 0x09;
191 arm7500_ioc_found = 0;
192 break;
193 default:
194 printf("Unknown IOMD ID=%04x ", sc->sc_id);
195 refresh = -1;
196 arm7500_ioc_found = 0; /* just in case */
197 break;
198 }
199 printf("version %d\n", bus_space_read_1(iot, ioh, IOMD_VERSION));
200
201 /* Report the DRAM refresh rate */
202 printf("%s: ", self->dv_xname);
203 printf("DRAM refresh=");
204 switch (refresh) {
205 case 0x0:
206 printf("off");
207 break;
208 case 0x1:
209 printf("16us");
210 break;
211 case 0x2:
212 printf("32us");
213 break;
214 case 0x4:
215 printf("64us");
216 break;
217 case 0x8:
218 printf("128us");
219 break;
220 default:
221 printf("unknown [%02x]", refresh);
222 break;
223 }
224
225 #if 0
226 /*
227 * No point in reporting this as it may get changed when devices are
228 * attached
229 */
230 dma_time = ReadByte(IOMD_DMATCR);
231 printf(", dma cycle types=");
232 for (loop = 0; loop < 4; ++loop,dma_time = dma_time >> 2)
233 printf("%c", 'A' + (dma_time & 3));
234
235 combo_time = ReadByte(IOMD_IOTCR);
236 printf(", combo cycle type=%c", 'A' + ((combo_time >> 2) & 3));
237 #endif
238 printf("\n");
239
240 /* Set up the external DMA channels */
241 /* XXX - this should be machine dependant not IOMD dependant */
242 switch (sc->sc_id) {
243 case ARM7500_IOC_ID:
244 case ARM7500FE_IOC_ID:
245 break;
246 case RPC600_IOMD_ID:
247 /* DMA channels 2 & 3 are external */
248 bus_space_write_1(iot, ioh, IOMD_DMAEXT, 0x0c);
249 break;
250 }
251
252 /* Configure the child devices */
253
254 /* Attach clock device */
255
256 ia.ia_clk.ca_name = "clk";
257 ia.ia_clk.ca_iot = iot;
258 ia.ia_clk.ca_ioh = ioh;
259 config_found(self, &ia, iomdprint);
260
261 /* Attach kbd device when configured */
262 if (bus_space_subregion(iot, ioh, IOMD_KBDDAT, 8, &ia.ia_kbd.ka_ioh))
263 panic("%s: Cannot map kbd registers\n", self->dv_xname);
264 ia.ia_kbd.ka_name = "kbd";
265 ia.ia_kbd.ka_iot = iot;
266 ia.ia_kbd.ka_rxirq = IRQ_KBDRX;
267 ia.ia_kbd.ka_txirq = IRQ_KBDTX;
268 config_found(self, &ia, iomdprint);
269
270 /* Attach rpckbc device when configured */
271 ia.ia_kbd.ka_name = "rpckbd";
272 ia.ia_kbd.ka_rxirq = IRQ_KBDRX;
273 ia.ia_kbd.ka_txirq = IRQ_KBDTX;
274 config_found(self, &ia, iomdprint);
275
276 /* Attach iic device */
277
278 if (bus_space_subregion(iot, ioh, IOMD_IOCR, 4, &ia.ia_iic.ia_ioh))
279 panic("%s: Cannot map iic registers\n", self->dv_xname);
280 ia.ia_iic.ia_name = "iic";
281 ia.ia_iic.ia_iot = iot;
282 ia.ia_iic.ia_irq = -1;
283 config_found(self, &ia, iomdprint);
284
285 switch (sc->sc_id) {
286 case ARM7500_IOC_ID:
287 case ARM7500FE_IOC_ID:
288 /* Attach pms device */
289
290 if (bus_space_subregion(iot, ioh, IOMD_MSDATA, 8, &ia.ia_pms.pa_ioh))
291 panic("%s: Cannot map pms registers\n", self->dv_xname);
292 ia.ia_pms.pa_name = "pms";
293 ia.ia_pms.pa_iot = iot;
294 ia.ia_pms.pa_irq = IRQ_MSDRX;
295 config_found(self, &ia, iomdprint);
296 break;
297 case RPC600_IOMD_ID:
298 /* Attach (ws)qms device */
299
300 if (bus_space_subregion(iot, ioh, IOMD_MOUSEX, 8, &ia.ia_qms.qa_ioh))
301 panic("%s: Cannot map qms registers\n", self->dv_xname);
302
303 if (bus_space_map(iot, IO_MOUSE_BUTTONS, 4, 0, &ia.ia_qms.qa_ioh_but))
304 panic("%s: Cannot map registers\n", self->dv_xname);
305 ia.ia_qms.qa_name = "qms";
306 ia.ia_qms.qa_iot = iot;
307 ia.ia_qms.qa_irq = IRQ_VSYNC;
308 config_found(self, &ia, iomdprint);
309
310 ia.ia_qms.qa_name = "wsqms";
311 config_found(self, &ia, iomdprint);
312 break;
313 }
314 }
315
316 /* End of iomd.c */
317