tspld.c revision 1.5 1 /* $NetBSD: tspld.c,v 1.5 2005/02/24 03:52:22 joff Exp $ */
2
3 /*-
4 * Copyright (c) 2004 Jesse Off
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: tspld.c,v 1.5 2005/02/24 03:52:22 joff Exp $");
39
40 #include <sys/param.h>
41 #include <sys/sysctl.h>
42 #include <sys/systm.h>
43 #include <sys/device.h>
44 #include <sys/wdog.h>
45
46 #include <machine/bus.h>
47 #include <machine/cpu.h>
48 #include <machine/autoconf.h>
49 #include "isa.h"
50 #if NISA > 0
51 #include <dev/isa/isavar.h>
52 #include <machine/isa_machdep.h>
53 #endif
54
55 #include <evbarm/tsarm/tsarmreg.h>
56 #include <evbarm/tsarm/tspldvar.h>
57 #include <arm/ep93xx/ep93xxvar.h>
58 #include <arm/arm32/machdep.h>
59 #include <arm/cpufunc.h>
60 #include <dev/sysmon/sysmonvar.h>
61
62 int tspldmatch __P((struct device *, struct cfdata *, void *));
63 void tspldattach __P((struct device *, struct device *, void *));
64 static int tspld_wdog_setmode __P((struct sysmon_wdog *));
65 static int tspld_wdog_tickle __P((struct sysmon_wdog *));
66 int tspld_search __P((struct device *, struct cfdata *, void *));
67 int tspld_print __P((void *, const char *));
68
69 struct tspld_softc {
70 struct device sc_dev;
71 bus_space_tag_t sc_iot;
72 bus_space_handle_t sc_wdogfeed_ioh;
73 bus_space_handle_t sc_wdogctrl_ioh;
74 struct sysmon_wdog sc_wdog;
75 unsigned char * sc_com2mode;
76 unsigned char * sc_model;
77 unsigned char sc_pldrev[4];
78 uint32_t sc_rs485;
79 uint32_t sc_adc;
80 uint32_t sc_jp[6];
81 uint32_t sc_blaster_present;
82 uint32_t sc_blaster_boot;
83 };
84
85 CFATTACH_DECL(tspld, sizeof(struct tspld_softc),
86 tspldmatch, tspldattach, NULL, NULL);
87
88 void tspld_callback __P((struct device *));
89
90 int
91 tspldmatch(parent, match, aux)
92 struct device *parent;
93 struct cfdata *match;
94 void *aux;
95 {
96
97 return 1;
98 }
99
100 void
101 tspldattach(parent, self, aux)
102 struct device *parent, *self;
103 void *aux;
104 {
105 int i, rev, features, jp, model;
106 struct tspld_softc *sc = (struct tspld_softc *)self;
107 bus_space_handle_t ioh;
108 struct sysctlnode *node;
109
110 if (sysctl_createv(NULL, 0, NULL, NULL,
111 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
112 NULL, NULL, 0, NULL, 0,
113 CTL_HW, CTL_EOL) != 0) {
114 printf("%s: could not create sysctl\n",
115 sc->sc_dev.dv_xname);
116 return;
117 }
118 if (sysctl_createv(NULL, 0, NULL, &node,
119 0, CTLTYPE_NODE, "tspld",
120 NULL,
121 NULL, 0, NULL, 0,
122 CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
123 printf("%s: could not create sysctl\n",
124 sc->sc_dev.dv_xname);
125 return;
126 }
127
128 sc->sc_iot = &ep93xx_bs_tag;
129 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_MODEL, 2, 0,
130 &ioh);
131 model = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7;
132 sc->sc_model = (model ? "TS-7250" : "TS-7200");
133 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
134 0, CTLTYPE_STRING, "boardmodel",
135 SYSCTL_DESCR("Technologic Systems board model"),
136 NULL, 0, sc->sc_model, 0,
137 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
138 != 0) {
139 printf("%s: could not create sysctl\n",
140 sc->sc_dev.dv_xname);
141 return;
142 }
143 bus_space_unmap(sc->sc_iot, ioh, 2);
144
145 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_PLDREV, 2, 0,
146 &ioh);
147 rev = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7;
148 rev = 'A' + rev - 1;
149 sc->sc_pldrev[0] = rev;
150 sc->sc_pldrev[1] = 0;
151 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
152 0, CTLTYPE_STRING, "pldrev",
153 SYSCTL_DESCR("CPLD revision"),
154 NULL, 0, sc->sc_pldrev, 0,
155 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
156 != 0) {
157 printf("%s: could not create sysctl\n",
158 sc->sc_dev.dv_xname);
159 return;
160 }
161 bus_space_unmap(sc->sc_iot, ioh, 2);
162
163 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_FEATURES, 2, 0,
164 &ioh);
165 features = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7;
166 bus_space_unmap(sc->sc_iot, ioh, 2);
167
168 bus_space_map(sc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_STATUS1, 1, 0,
169 &ioh);
170 i = bus_space_read_1(sc->sc_iot, ioh, 0) & 0x1f;
171 jp = (~((i & 0x18) >> 1) & 0xc) | (i & 0x3);
172 bus_space_unmap(sc->sc_iot, ioh, 1);
173
174 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
175 0, CTLTYPE_INT, "blaster_present",
176 SYSCTL_DESCR("Whether or not a TS-9420/TS-9202 blaster board is connected"),
177 NULL, 0, &sc->sc_blaster_present, 0,
178 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
179 != 0) {
180 printf("%s: could not create sysctl\n",
181 sc->sc_dev.dv_xname);
182 return;
183 }
184 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
185 0, CTLTYPE_INT, "blaster_boot",
186 SYSCTL_DESCR("Whether or not a blast board was used to boot"),
187 NULL, 0, &sc->sc_blaster_boot, 0,
188 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
189 != 0) {
190 printf("%s: could not create sysctl\n",
191 sc->sc_dev.dv_xname);
192 return;
193 }
194 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_STATUS2, 2, 0,
195 &ioh);
196 i = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x1;
197 sc->sc_blaster_boot = sc->sc_blaster_present = 0;
198 if (i & 0x2)
199 sc->sc_blaster_boot = 1;
200 if (i & 0x4)
201 sc->sc_blaster_present = 1;
202 jp |= (i << 4);
203 bus_space_unmap(sc->sc_iot, ioh, 1);
204
205 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
206 0, CTLTYPE_INT, "rs485_avail",
207 SYSCTL_DESCR("RS485 level driver for COM2 available"),
208 NULL, 0, &sc->sc_rs485, 0,
209 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
210 != 0) {
211 printf("%s: could not create sysctl\n",
212 sc->sc_dev.dv_xname);
213 return;
214 }
215 sc->sc_com2mode = "rs232";
216 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
217 0, CTLTYPE_STRING, "com2_mode",
218 SYSCTL_DESCR("line driver type for COM2"),
219 NULL, 0, sc->sc_com2mode, 0,
220 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
221 != 0) {
222 printf("%s: could not create sysctl\n",
223 sc->sc_dev.dv_xname);
224 return;
225 }
226 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
227 0, CTLTYPE_INT, "max197adc_avail",
228 SYSCTL_DESCR("Maxim 197 Analog to Digital Converter available"),
229 NULL, 0, &sc->sc_adc, 0,
230 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
231 != 0) {
232 printf("%s: could not create sysctl\n",
233 sc->sc_dev.dv_xname);
234 return;
235 }
236 printf(": Technologic Systems %s rev %c, features 0x%x",
237 sc->sc_model, rev, features);
238 sc->sc_adc = sc->sc_rs485 = 0;
239 if (features == 0x1) {
240 printf("<MAX197-ADC>");
241 sc->sc_adc = 1;
242 } else if (features == 0x2) {
243 printf("<RS485>");
244 sc->sc_rs485 = 1;
245 } else if (features == 0x3) {
246 printf("<MAX197-ADC,RS485>");
247 sc->sc_adc = sc->sc_rs485 = 1;
248 }
249 printf("\n");
250 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
251 0, CTLTYPE_INT, "jp1",
252 SYSCTL_DESCR("onboard jumper setting"),
253 NULL, 0, &sc->sc_jp[0], 0,
254 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
255 != 0) {
256 printf("%s: could not create sysctl\n",
257 sc->sc_dev.dv_xname);
258 return;
259 }
260 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
261 0, CTLTYPE_INT, "jp2",
262 SYSCTL_DESCR("onboard jumper setting"),
263 NULL, 0, &sc->sc_jp[1], 0,
264 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
265 != 0) {
266 printf("%s: could not create sysctl\n",
267 sc->sc_dev.dv_xname);
268 return;
269 }
270 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
271 0, CTLTYPE_INT, "jp3",
272 SYSCTL_DESCR("onboard jumper setting"),
273 NULL, 0, &sc->sc_jp[2], 0,
274 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
275 != 0) {
276 printf("%s: could not create sysctl\n",
277 sc->sc_dev.dv_xname);
278 return;
279 }
280 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
281 0, CTLTYPE_INT, "jp4",
282 SYSCTL_DESCR("onboard jumper setting"),
283 NULL, 0, &sc->sc_jp[3], 0,
284 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
285 != 0) {
286 printf("%s: could not create sysctl\n",
287 sc->sc_dev.dv_xname);
288 return;
289 }
290 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
291 0, CTLTYPE_INT, "jp5",
292 SYSCTL_DESCR("onboard jumper setting"),
293 NULL, 0, &sc->sc_jp[4], 0,
294 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
295 != 0) {
296 printf("%s: could not create sysctl\n",
297 sc->sc_dev.dv_xname);
298 return;
299 }
300 if ((i = sysctl_createv(NULL, 0, NULL, NULL,
301 0, CTLTYPE_INT, "jp6",
302 SYSCTL_DESCR("onboard jumper setting"),
303 NULL, 0, &sc->sc_jp[5], 0,
304 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
305 != 0) {
306 printf("%s: could not create sysctl\n",
307 sc->sc_dev.dv_xname);
308 return;
309 }
310 printf("%s: jumpers 0x%x", sc->sc_dev.dv_xname, jp);
311 if (jp) {
312 printf("<");
313 for(i = 0; i < 5; i++) {
314 if (jp & (1 << i)) {
315 sc->sc_jp[i + 1] = 1;
316 printf("JP%d", i + 2);
317 jp &= ~(1 << i);
318 if (jp) printf(",");
319 } else {
320 sc->sc_jp[i + 2] = 0;
321 }
322 }
323 printf(">");
324 }
325 printf("\n");
326
327 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_WDOGCTRL, 2, 0,
328 &sc->sc_wdogctrl_ioh);
329 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_WDOGFEED, 2, 0,
330 &sc->sc_wdogfeed_ioh);
331
332 sc->sc_wdog.smw_name = sc->sc_dev.dv_xname;
333 sc->sc_wdog.smw_cookie = sc;
334 sc->sc_wdog.smw_setmode = tspld_wdog_setmode;
335 sc->sc_wdog.smw_tickle = tspld_wdog_tickle;
336 sc->sc_wdog.smw_period = 8;
337 sysmon_wdog_register(&sc->sc_wdog);
338 tspld_wdog_setmode(&sc->sc_wdog);
339
340
341 /* Set the on board peripherals bus callback */
342 config_defer(self, tspld_callback);
343 }
344
345 int
346 tspld_search(parent, cf, aux)
347 struct device *parent;
348 struct cfdata *cf;
349 void *aux;
350 {
351 struct tspld_softc *sc = (struct tspld_softc *)parent;
352 struct tspld_attach_args sa;
353
354 sa.ta_iot = sc->sc_iot;
355
356 if (config_match(parent, cf, &sa) > 0)
357 config_attach(parent, cf, &sa, tspld_print);
358
359 return (0);
360 }
361
362 int
363 tspld_print(aux, name)
364 void *aux;
365 const char *name;
366 {
367
368 return (UNCONF);
369 }
370
371 void
372 tspld_callback(self)
373 struct device *self;
374 {
375 #if NISA > 0
376 extern void isa_bs_mallocok(void);
377 struct isabus_attach_args iba;
378
379 /*
380 * Attach the ISA bus behind this bridge.
381 */
382 memset(&iba, 0, sizeof(iba));
383 iba.iba_iot = &isa_io_bs_tag;
384 iba.iba_memt = &isa_mem_bs_tag;
385 isa_bs_mallocok();
386 config_found_ia(self, "isabus", &iba, isabusprint);
387 #endif
388 /*
389 * Attach each devices
390 */
391 config_search(tspld_search, self, NULL);
392
393 }
394
395 static int
396 tspld_wdog_tickle(smw)
397 struct sysmon_wdog *smw;
398 {
399 struct tspld_softc *sc = (struct tspld_softc *)smw->smw_cookie;
400
401 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5);
402 return 0;
403 }
404
405 static int
406 tspld_wdog_setmode(smw)
407 struct sysmon_wdog *smw;
408 {
409 int i, ret = 0;
410 struct tspld_softc *sc = (struct tspld_softc *)smw->smw_cookie;
411
412 i = disable_interrupts(I32_bit|F32_bit);
413 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
414 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5);
415 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 0);
416 } else {
417 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5);
418 switch (smw->smw_period) {
419 case 1:
420 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0,
421 0x3);
422 break;
423 case 2:
424 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0,
425 0x5);
426 break;
427 case 4:
428 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0,
429 0x6);
430 break;
431 case 8:
432 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0,
433 0x7);
434 break;
435 default:
436 ret = EINVAL;
437 }
438 }
439 restore_interrupts(i);
440 return ret;
441 }
442