1 /* $NetBSD: tspld.c,v 1.8 2005/06/30 17:03:53 drochner 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.8 2005/06/30 17:03:53 drochner 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 *, 67 const locdesc_t *, void *)); 68 int tspld_print __P((void *, const char *)); 69 70 struct tspld_softc { 71 struct device sc_dev; 72 bus_space_tag_t sc_iot; 73 bus_space_handle_t sc_wdogfeed_ioh; 74 bus_space_handle_t sc_wdogctrl_ioh; 75 struct sysmon_wdog sc_wdog; 76 unsigned const char * sc_com2mode; 77 unsigned const char * sc_model; 78 unsigned char sc_pldrev[4]; 79 uint32_t sc_rs485; 80 uint32_t sc_adc; 81 uint32_t sc_jp[6]; 82 uint32_t sc_blaster_present; 83 uint32_t sc_blaster_boot; 84 }; 85 86 CFATTACH_DECL(tspld, sizeof(struct tspld_softc), 87 tspldmatch, tspldattach, NULL, NULL); 88 89 void tspld_callback __P((struct device *)); 90 91 int 92 tspldmatch(parent, match, aux) 93 struct device *parent; 94 struct cfdata *match; 95 void *aux; 96 { 97 98 return 1; 99 } 100 101 void 102 tspldattach(parent, self, aux) 103 struct device *parent, *self; 104 void *aux; 105 { 106 int i, rev, features, jp, model; 107 struct tspld_softc *sc = (struct tspld_softc *)self; 108 bus_space_handle_t ioh; 109 const struct sysctlnode *node; 110 111 if (sysctl_createv(NULL, 0, NULL, NULL, 112 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", 113 NULL, NULL, 0, NULL, 0, 114 CTL_HW, CTL_EOL) != 0) { 115 printf("%s: could not create sysctl\n", 116 sc->sc_dev.dv_xname); 117 return; 118 } 119 if (sysctl_createv(NULL, 0, NULL, &node, 120 0, CTLTYPE_NODE, "tspld", 121 NULL, 122 NULL, 0, NULL, 0, 123 CTL_HW, CTL_CREATE, CTL_EOL) != 0) { 124 printf("%s: could not create sysctl\n", 125 sc->sc_dev.dv_xname); 126 return; 127 } 128 129 sc->sc_iot = &ep93xx_bs_tag; 130 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_MODEL, 2, 0, 131 &ioh); 132 model = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7; 133 sc->sc_model = (model ? "TS-7250" : "TS-7200"); 134 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 135 0, CTLTYPE_STRING, "boardmodel", 136 SYSCTL_DESCR("Technologic Systems board model"), 137 NULL, 0, __UNCONST(sc->sc_model), 0, 138 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 139 != 0) { 140 printf("%s: could not create sysctl\n", 141 sc->sc_dev.dv_xname); 142 return; 143 } 144 bus_space_unmap(sc->sc_iot, ioh, 2); 145 146 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_PLDREV, 2, 0, 147 &ioh); 148 rev = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7; 149 rev = 'A' + rev - 1; 150 sc->sc_pldrev[0] = rev; 151 sc->sc_pldrev[1] = 0; 152 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 153 0, CTLTYPE_STRING, "pldrev", 154 SYSCTL_DESCR("CPLD revision"), 155 NULL, 0, sc->sc_pldrev, 0, 156 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 157 != 0) { 158 printf("%s: could not create sysctl\n", 159 sc->sc_dev.dv_xname); 160 return; 161 } 162 bus_space_unmap(sc->sc_iot, ioh, 2); 163 164 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_FEATURES, 2, 0, 165 &ioh); 166 features = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x7; 167 bus_space_unmap(sc->sc_iot, ioh, 2); 168 169 bus_space_map(sc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_STATUS1, 1, 0, 170 &ioh); 171 i = bus_space_read_1(sc->sc_iot, ioh, 0) & 0x1f; 172 jp = (~((i & 0x18) >> 1) & 0xc) | (i & 0x3); 173 bus_space_unmap(sc->sc_iot, ioh, 1); 174 175 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 176 0, CTLTYPE_INT, "blaster_present", 177 SYSCTL_DESCR("Whether or not a TS-9420/TS-9202 blaster board is connected"), 178 NULL, 0, &sc->sc_blaster_present, 0, 179 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 180 != 0) { 181 printf("%s: could not create sysctl\n", 182 sc->sc_dev.dv_xname); 183 return; 184 } 185 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 186 0, CTLTYPE_INT, "blaster_boot", 187 SYSCTL_DESCR("Whether or not a blast board was used to boot"), 188 NULL, 0, &sc->sc_blaster_boot, 0, 189 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 190 != 0) { 191 printf("%s: could not create sysctl\n", 192 sc->sc_dev.dv_xname); 193 return; 194 } 195 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_STATUS2, 2, 0, 196 &ioh); 197 i = bus_space_read_2(sc->sc_iot, ioh, 0) & 0x1; 198 sc->sc_blaster_boot = sc->sc_blaster_present = 0; 199 if (i & 0x2) 200 sc->sc_blaster_boot = 1; 201 if (i & 0x4) 202 sc->sc_blaster_present = 1; 203 jp |= (i << 4); 204 bus_space_unmap(sc->sc_iot, ioh, 1); 205 206 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 207 0, CTLTYPE_INT, "rs485_avail", 208 SYSCTL_DESCR("RS485 level driver for COM2 available"), 209 NULL, 0, &sc->sc_rs485, 0, 210 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 211 != 0) { 212 printf("%s: could not create sysctl\n", 213 sc->sc_dev.dv_xname); 214 return; 215 } 216 sc->sc_com2mode = "rs232"; 217 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 218 0, CTLTYPE_STRING, "com2_mode", 219 SYSCTL_DESCR("line driver type for COM2"), 220 NULL, 0, __UNCONST(sc->sc_com2mode), 0, 221 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 222 != 0) { 223 printf("%s: could not create sysctl\n", 224 sc->sc_dev.dv_xname); 225 return; 226 } 227 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 228 0, CTLTYPE_INT, "max197adc_avail", 229 SYSCTL_DESCR("Maxim 197 Analog to Digital Converter available"), 230 NULL, 0, &sc->sc_adc, 0, 231 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 232 != 0) { 233 printf("%s: could not create sysctl\n", 234 sc->sc_dev.dv_xname); 235 return; 236 } 237 printf(": Technologic Systems %s rev %c, features 0x%x", 238 sc->sc_model, rev, features); 239 sc->sc_adc = sc->sc_rs485 = 0; 240 if (features == 0x1) { 241 printf("<MAX197-ADC>"); 242 sc->sc_adc = 1; 243 } else if (features == 0x2) { 244 printf("<RS485>"); 245 sc->sc_rs485 = 1; 246 } else if (features == 0x3) { 247 printf("<MAX197-ADC,RS485>"); 248 sc->sc_adc = sc->sc_rs485 = 1; 249 } 250 printf("\n"); 251 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 252 0, CTLTYPE_INT, "jp1", 253 SYSCTL_DESCR("onboard jumper setting"), 254 NULL, 0, &sc->sc_jp[0], 0, 255 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 256 != 0) { 257 printf("%s: could not create sysctl\n", 258 sc->sc_dev.dv_xname); 259 return; 260 } 261 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 262 0, CTLTYPE_INT, "jp2", 263 SYSCTL_DESCR("onboard jumper setting"), 264 NULL, 0, &sc->sc_jp[1], 0, 265 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 266 != 0) { 267 printf("%s: could not create sysctl\n", 268 sc->sc_dev.dv_xname); 269 return; 270 } 271 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 272 0, CTLTYPE_INT, "jp3", 273 SYSCTL_DESCR("onboard jumper setting"), 274 NULL, 0, &sc->sc_jp[2], 0, 275 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 276 != 0) { 277 printf("%s: could not create sysctl\n", 278 sc->sc_dev.dv_xname); 279 return; 280 } 281 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 282 0, CTLTYPE_INT, "jp4", 283 SYSCTL_DESCR("onboard jumper setting"), 284 NULL, 0, &sc->sc_jp[3], 0, 285 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 286 != 0) { 287 printf("%s: could not create sysctl\n", 288 sc->sc_dev.dv_xname); 289 return; 290 } 291 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 292 0, CTLTYPE_INT, "jp5", 293 SYSCTL_DESCR("onboard jumper setting"), 294 NULL, 0, &sc->sc_jp[4], 0, 295 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 296 != 0) { 297 printf("%s: could not create sysctl\n", 298 sc->sc_dev.dv_xname); 299 return; 300 } 301 if ((i = sysctl_createv(NULL, 0, NULL, NULL, 302 0, CTLTYPE_INT, "jp6", 303 SYSCTL_DESCR("onboard jumper setting"), 304 NULL, 0, &sc->sc_jp[5], 0, 305 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 306 != 0) { 307 printf("%s: could not create sysctl\n", 308 sc->sc_dev.dv_xname); 309 return; 310 } 311 printf("%s: jumpers 0x%x", sc->sc_dev.dv_xname, jp); 312 if (jp) { 313 printf("<"); 314 for(i = 0; i < 5; i++) { 315 if (jp & (1 << i)) { 316 sc->sc_jp[i + 1] = 1; 317 printf("JP%d", i + 2); 318 jp &= ~(1 << i); 319 if (jp) printf(","); 320 } else { 321 sc->sc_jp[i + 2] = 0; 322 } 323 } 324 printf(">"); 325 } 326 printf("\n"); 327 328 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_WDOGCTRL, 2, 0, 329 &sc->sc_wdogctrl_ioh); 330 bus_space_map(sc->sc_iot, TS7XXX_IO16_HWBASE + TS7XXX_WDOGFEED, 2, 0, 331 &sc->sc_wdogfeed_ioh); 332 333 sc->sc_wdog.smw_name = sc->sc_dev.dv_xname; 334 sc->sc_wdog.smw_cookie = sc; 335 sc->sc_wdog.smw_setmode = tspld_wdog_setmode; 336 sc->sc_wdog.smw_tickle = tspld_wdog_tickle; 337 sc->sc_wdog.smw_period = 8; 338 sysmon_wdog_register(&sc->sc_wdog); 339 tspld_wdog_setmode(&sc->sc_wdog); 340 341 342 /* Set the on board peripherals bus callback */ 343 config_defer(self, tspld_callback); 344 } 345 346 int 347 tspld_search(parent, cf, ldesc, aux) 348 struct device *parent; 349 struct cfdata *cf; 350 const locdesc_t *ldesc; 351 void *aux; 352 { 353 struct tspld_softc *sc = (struct tspld_softc *)parent; 354 struct tspld_attach_args sa; 355 356 sa.ta_iot = sc->sc_iot; 357 358 if (config_match(parent, cf, &sa) > 0) 359 config_attach(parent, cf, &sa, tspld_print); 360 361 return (0); 362 } 363 364 int 365 tspld_print(aux, name) 366 void *aux; 367 const char *name; 368 { 369 370 return (UNCONF); 371 } 372 373 void 374 tspld_callback(self) 375 struct device *self; 376 { 377 #if NISA > 0 378 extern void isa_bs_mallocok(void); 379 struct isabus_attach_args iba; 380 381 /* 382 * Attach the ISA bus behind this bridge. 383 */ 384 memset(&iba, 0, sizeof(iba)); 385 iba.iba_iot = &isa_io_bs_tag; 386 iba.iba_memt = &isa_mem_bs_tag; 387 isa_bs_mallocok(); 388 config_found_ia(self, "isabus", &iba, isabusprint); 389 #endif 390 /* 391 * Attach each devices 392 */ 393 config_search_ia(tspld_search, self, "tspldbus", NULL); 394 395 } 396 397 static int 398 tspld_wdog_tickle(smw) 399 struct sysmon_wdog *smw; 400 { 401 struct tspld_softc *sc = (struct tspld_softc *)smw->smw_cookie; 402 403 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5); 404 return 0; 405 } 406 407 static int 408 tspld_wdog_setmode(smw) 409 struct sysmon_wdog *smw; 410 { 411 int i, ret = 0; 412 struct tspld_softc *sc = (struct tspld_softc *)smw->smw_cookie; 413 414 i = disable_interrupts(I32_bit|F32_bit); 415 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 416 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5); 417 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 0); 418 } else { 419 bus_space_write_2(sc->sc_iot, sc->sc_wdogfeed_ioh, 0, 0x5); 420 switch (smw->smw_period) { 421 case 1: 422 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 423 0x3); 424 break; 425 case 2: 426 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 427 0x5); 428 break; 429 case 4: 430 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 431 0x6); 432 break; 433 case 8: 434 bus_space_write_2(sc->sc_iot, sc->sc_wdogctrl_ioh, 0, 435 0x7); 436 break; 437 default: 438 ret = EINVAL; 439 } 440 } 441 restore_interrupts(i); 442 return ret; 443 } 444