1 1.9 chs /* $NetBSD: vrled.c,v 1.9 2012/10/27 17:17:56 chs Exp $ */ 2 1.1 sato 3 1.1 sato /* 4 1.1 sato * Copyright (c) 2000 SATO Kazumi. All rights reserved. 5 1.1 sato * 6 1.1 sato * Redistribution and use in source and binary forms, with or without 7 1.1 sato * modification, are permitted provided that the following conditions 8 1.1 sato * are met: 9 1.1 sato * 1. Redistributions of source code must retain the above copyright 10 1.1 sato * notice, this list of conditions and the following disclaimer. 11 1.1 sato * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 sato * notice, this list of conditions and the following disclaimer in the 13 1.1 sato * documentation and/or other materials provided with the distribution. 14 1.1 sato * 15 1.1 sato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 1.1 sato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 1.1 sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 1.1 sato * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 sato * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 sato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 1.1 sato * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 sato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 sato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 sato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 sato * SUCH DAMAGE. 26 1.1 sato */ 27 1.7 lukem 28 1.7 lukem #include <sys/cdefs.h> 29 1.9 chs __KERNEL_RCSID(0, "$NetBSD: vrled.c,v 1.9 2012/10/27 17:17:56 chs Exp $"); 30 1.1 sato 31 1.1 sato #include <sys/param.h> 32 1.1 sato #include <sys/systm.h> 33 1.1 sato #include <sys/device.h> 34 1.1 sato #include <sys/reboot.h> 35 1.1 sato 36 1.1 sato #include <machine/bus.h> 37 1.1 sato #include <machine/config_hook.h> 38 1.1 sato 39 1.4 takemura #include <hpcmips/vr/vripif.h> 40 1.1 sato #include <hpcmips/vr/vrledvar.h> 41 1.1 sato #include <hpcmips/vr/vrledreg.h> 42 1.1 sato 43 1.1 sato 44 1.1 sato #ifdef VRLEDDEBUG 45 1.1 sato #ifndef VRLEDDEBUG_CONF 46 1.1 sato #define VRLEDDEBUG_CONF 0 47 1.1 sato #endif /* VRLEDDEBUG_CONF */ 48 1.1 sato int vrleddebug = VRLEDDEBUG_CONF; 49 1.1 sato #define DPRINTF(arg) if (vrleddebug) printf arg; 50 1.1 sato #define VPRINTF(arg) if (bootverbose||vrleddebug) printf arg; 51 1.1 sato #else /* VRLEDDEBUG */ 52 1.1 sato #define DPRINTF(arg) 53 1.1 sato #define VPRINTF(arg) if (bootverbose) printf arg; 54 1.1 sato #endif /* VRLEDDEBUG */ 55 1.1 sato 56 1.9 chs static int vrledmatch(device_t, cfdata_t, void *); 57 1.9 chs static void vrledattach(device_t, device_t, void *); 58 1.1 sato 59 1.3 uch static void vrled_write(struct vrled_softc *, int, unsigned short); 60 1.3 uch static unsigned short vrled_read(struct vrled_softc *, int); 61 1.1 sato 62 1.3 uch static void vrled_stop(struct vrled_softc *); 63 1.3 uch static void vrled_on(struct vrled_softc *); 64 1.3 uch static void vrled_blink(struct vrled_softc *); 65 1.3 uch static void vrled_flash(struct vrled_softc *); 66 1.3 uch static void vrled_change_state(struct vrled_softc *); 67 1.3 uch static int vrled_event(void *, int, long, void *); 68 1.1 sato 69 1.3 uch int vrled_intr(void *); 70 1.1 sato 71 1.9 chs CFATTACH_DECL_NEW(vrled, sizeof(struct vrled_softc), 72 1.6 thorpej vrledmatch, vrledattach, NULL, NULL); 73 1.1 sato 74 1.1 sato struct vrled_softc *this_led; 75 1.1 sato 76 1.1 sato static inline void 77 1.3 uch vrled_write(struct vrled_softc *sc, int port, unsigned short val) 78 1.1 sato { 79 1.3 uch 80 1.1 sato bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 81 1.1 sato } 82 1.1 sato 83 1.1 sato static inline unsigned short 84 1.3 uch vrled_read(struct vrled_softc *sc, int port) 85 1.1 sato { 86 1.3 uch 87 1.3 uch return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 88 1.1 sato } 89 1.1 sato 90 1.1 sato static int 91 1.9 chs vrledmatch(device_t parent, cfdata_t cf, void *aux) 92 1.1 sato { 93 1.3 uch 94 1.3 uch return (1); 95 1.1 sato } 96 1.1 sato 97 1.1 sato static void 98 1.9 chs vrledattach(device_t parent, device_t self, void *aux) 99 1.1 sato { 100 1.9 chs struct vrled_softc *sc = device_private(self); 101 1.1 sato struct vrip_attach_args *va = aux; 102 1.1 sato 103 1.1 sato bus_space_tag_t iot = va->va_iot; 104 1.1 sato bus_space_handle_t ioh; 105 1.1 sato 106 1.1 sato if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 107 1.1 sato printf(": can't map bus space\n"); 108 1.1 sato return; 109 1.1 sato } 110 1.1 sato 111 1.1 sato sc->sc_iot = iot; 112 1.1 sato sc->sc_ioh = ioh; 113 1.1 sato 114 1.1 sato if (!(sc->sc_handler = 115 1.4 takemura vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 116 1.3 uch vrled_intr, sc))) { 117 1.1 sato printf (": can't map interrupt line.\n"); 118 1.1 sato return; 119 1.1 sato } 120 1.1 sato 121 1.1 sato printf("\n"); 122 1.1 sato /* clear interrupt status */ 123 1.1 sato vrled_write(sc, LEDINT_REG_W, LEDINT_ALL); 124 1.1 sato 125 1.1 sato /* basic setup */ 126 1.1 sato sc->sc_state_cnt = 1; 127 1.1 sato vrled_write(sc, LEDASTC_REG_W, 1); /* 1time */ 128 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 129 1.1 sato vrled_stop(sc); 130 1.1 sato 131 1.2 sato sc->sc_hook = config_hook(CONFIG_HOOK_SET, 132 1.3 uch CONFIG_HOOK_LED, CONFIG_HOOK_SHARE, vrled_event, sc); 133 1.3 uch 134 1.1 sato this_led = sc; 135 1.1 sato } 136 1.1 sato 137 1.1 sato 138 1.1 sato /* 139 1.1 sato * LED interrupt handler. 140 1.1 sato * 141 1.1 sato */ 142 1.1 sato int 143 1.3 uch vrled_intr(void *arg) 144 1.1 sato { 145 1.1 sato struct vrled_softc *sc = arg; 146 1.1 sato unsigned int intstat; 147 1.1 sato 148 1.1 sato intstat = vrled_read(sc, LEDINT_REG_W); 149 1.1 sato /* clear interrupt status */ 150 1.1 sato vrled_write(sc, LEDINT_REG_W, intstat); 151 1.1 sato if (intstat&LEDINT_AUTOSTOP) { 152 1.1 sato vrled_change_state(sc); 153 1.1 sato } 154 1.3 uch return (0); 155 1.1 sato } 156 1.1 sato 157 1.1 sato /* 158 1.1 sato * LED turn OFF 159 1.1 sato * 160 1.1 sato */ 161 1.1 sato void 162 1.3 uch vrled_stop(struct vrled_softc *sc) 163 1.1 sato { 164 1.1 sato vrled_write(sc, LEDHTS_REG_W, LEDHTS_DIV16SEC); 165 1.1 sato vrled_write(sc, LEDLTS_REG_W, LEDLTS_4SEC); 166 1.1 sato vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 167 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 168 1.1 sato 169 1.1 sato sc->sc_state = LEDOFF; 170 1.1 sato sc->sc_next = LEDOFF; 171 1.1 sato } 172 1.1 sato 173 1.1 sato /* 174 1.1 sato * LED turn ON 175 1.1 sato * 176 1.1 sato */ 177 1.1 sato void 178 1.3 uch vrled_on(struct vrled_softc *sc) 179 1.1 sato { 180 1.1 sato vrled_write(sc, LEDHTS_REG_W, LEDHTS_SEC); 181 1.1 sato vrled_write(sc, LEDLTS_REG_W, LEDLTS_DIV16SEC); 182 1.1 sato vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 183 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 184 1.1 sato 185 1.1 sato sc->sc_state = LEDON; 186 1.1 sato sc->sc_next = LEDON; 187 1.1 sato } 188 1.1 sato 189 1.1 sato /* 190 1.1 sato * LED blink 191 1.1 sato * 192 1.1 sato */ 193 1.1 sato void 194 1.3 uch vrled_blink(struct vrled_softc *sc) 195 1.1 sato { 196 1.1 sato int ledhts; 197 1.1 sato int ledlts; 198 1.1 sato 199 1.1 sato switch (sc->sc_next) { 200 1.1 sato case LED1SB: 201 1.1 sato ledhts = LEDHTS_DIV2SEC; 202 1.1 sato ledlts = LEDLTS_DIV2SEC; 203 1.1 sato break; 204 1.1 sato case LED2SB: 205 1.1 sato ledhts = LEDHTS_SEC; 206 1.1 sato ledlts = LEDLTS_SEC; 207 1.1 sato break; 208 1.1 sato default: 209 1.1 sato vrled_stop(sc); 210 1.1 sato return; 211 1.1 sato } 212 1.1 sato 213 1.1 sato vrled_write(sc, LEDHTS_REG_W, ledhts); 214 1.1 sato vrled_write(sc, LEDLTS_REG_W, ledlts); 215 1.1 sato vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 216 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 217 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 218 1.1 sato 219 1.1 sato sc->sc_state = sc->sc_next; 220 1.1 sato } 221 1.1 sato 222 1.1 sato /* 223 1.1 sato * LED flash once 224 1.1 sato * 225 1.1 sato */ 226 1.1 sato void 227 1.3 uch vrled_flash(struct vrled_softc *sc) 228 1.1 sato { 229 1.1 sato int ledhts; 230 1.1 sato int ledlts; 231 1.1 sato 232 1.1 sato switch (sc->sc_next) { 233 1.1 sato case LED8DIVF: 234 1.1 sato ledhts = LEDHTS_DIV16SEC; 235 1.1 sato ledlts = LEDLTS_DIV16SEC; 236 1.1 sato break; 237 1.1 sato case LED4DIVF: 238 1.1 sato ledhts = LEDHTS_DIV8SEC; 239 1.1 sato ledlts = LEDLTS_DIV8SEC; 240 1.1 sato break; 241 1.1 sato case LED2DIVF: 242 1.1 sato ledhts = LEDHTS_DIV4SEC; 243 1.1 sato ledlts = LEDLTS_DIV4SEC; 244 1.1 sato break; 245 1.1 sato case LED1SF: 246 1.1 sato ledhts = LEDHTS_DIV2SEC; 247 1.1 sato ledlts = LEDLTS_DIV2SEC; 248 1.1 sato break; 249 1.1 sato default: 250 1.1 sato vrled_stop(sc); 251 1.1 sato return; 252 1.1 sato } 253 1.1 sato 254 1.1 sato vrled_write(sc, LEDHTS_REG_W, ledhts); 255 1.1 sato vrled_write(sc, LEDLTS_REG_W, ledlts); 256 1.1 sato vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 257 1.1 sato vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 258 1.1 sato 259 1.1 sato sc->sc_state = sc->sc_next; 260 1.1 sato sc->sc_next = LEDOFF; 261 1.1 sato sc->sc_state_cnt = 1; 262 1.1 sato } 263 1.1 sato 264 1.1 sato /* 265 1.1 sato * Change LED state 266 1.1 sato * 267 1.1 sato */ 268 1.1 sato void 269 1.3 uch vrled_change_state(struct vrled_softc *sc) 270 1.1 sato { 271 1.1 sato 272 1.1 sato switch (sc->sc_next) { 273 1.1 sato case LEDOFF: 274 1.1 sato vrled_stop(sc); 275 1.1 sato break; 276 1.1 sato case LEDON: 277 1.1 sato vrled_on(sc); 278 1.1 sato break; 279 1.1 sato case LED1SB: 280 1.1 sato case LED2SB: 281 1.1 sato vrled_blink(sc); 282 1.1 sato break; 283 1.1 sato case LED8DIVF: 284 1.1 sato case LED4DIVF: 285 1.1 sato case LED2DIVF: 286 1.1 sato case LED1SF: 287 1.1 sato vrled_flash(sc); 288 1.1 sato break; 289 1.1 sato default: 290 1.1 sato vrled_stop(sc); 291 1.1 sato break; 292 1.1 sato } 293 1.1 sato } 294 1.1 sato 295 1.1 sato /* 296 1.1 sato * Set LED state 297 1.1 sato * 298 1.1 sato */ 299 1.1 sato void 300 1.3 uch vrled_set_state(struct vrled_softc *sc, vrled_status state) 301 1.1 sato { 302 1.1 sato 303 1.1 sato int ledstate; 304 1.1 sato 305 1.1 sato ledstate = vrled_read(sc, LEDCNT_REG_W); 306 1.1 sato if (ledstate&LEDCNT_BLINK) { /* currently processing */ 307 1.1 sato if (sc->sc_next == state) 308 1.1 sato sc->sc_state_cnt++; 309 1.1 sato switch (sc->sc_next) { 310 1.1 sato case LEDOFF: 311 1.1 sato case LEDON: 312 1.1 sato sc->sc_next = state; 313 1.1 sato break; 314 1.1 sato case LED8DIVF: 315 1.1 sato case LED4DIVF: 316 1.1 sato case LED2DIVF: 317 1.1 sato case LED1SF: 318 1.1 sato switch (state) { 319 1.1 sato case LEDOFF: 320 1.1 sato case LED8DIVF: 321 1.1 sato case LED4DIVF: 322 1.1 sato case LED2DIVF: 323 1.1 sato case LED1SF: 324 1.1 sato sc->sc_next = state; 325 1.1 sato break; 326 1.1 sato default: 327 1.1 sato break; 328 1.1 sato } 329 1.1 sato break; 330 1.1 sato case LED1SB: 331 1.1 sato case LED2SB: 332 1.1 sato switch (state) { 333 1.1 sato case LEDOFF: 334 1.1 sato case LEDON: 335 1.1 sato case LED1SB: 336 1.1 sato case LED2SB: 337 1.1 sato sc->sc_next = state; 338 1.1 sato break; 339 1.1 sato default: 340 1.1 sato break; 341 1.1 sato } 342 1.1 sato break; 343 1.1 sato default: 344 1.1 sato sc->sc_next = LEDOFF; 345 1.1 sato break; 346 1.1 sato } 347 1.1 sato return; 348 1.1 sato } 349 1.1 sato sc->sc_next = state; 350 1.1 sato vrled_change_state(sc); 351 1.1 sato } 352 1.1 sato 353 1.1 sato /* 354 1.1 sato * LED config hook events 355 1.1 sato * 356 1.1 sato */ 357 1.1 sato int 358 1.3 uch vrled_event(void *ctx, int type, long id, void *msg) 359 1.1 sato { 360 1.1 sato struct vrled_softc *sc = (struct vrled_softc *)ctx; 361 1.2 sato int why =*(int *)msg; 362 1.1 sato 363 1.2 sato if (type != CONFIG_HOOK_SET 364 1.3 uch || id != CONFIG_HOOK_LED) 365 1.3 uch return (1); 366 1.2 sato if (msg == NULL) 367 1.3 uch return (1); 368 1.1 sato 369 1.1 sato switch (why) { 370 1.2 sato case CONFIG_HOOK_LED_OFF: 371 1.1 sato vrled_set_state(sc, LEDOFF); 372 1.1 sato break; 373 1.2 sato case CONFIG_HOOK_LED_ON: 374 1.1 sato vrled_set_state(sc, LEDON); 375 1.1 sato break; 376 1.2 sato case CONFIG_HOOK_LED_FLASH: 377 1.1 sato vrled_set_state(sc, LED8DIVF); 378 1.1 sato break; 379 1.2 sato case CONFIG_HOOK_LED_FLASH2: 380 1.1 sato vrled_set_state(sc, LED4DIVF); 381 1.1 sato break; 382 1.2 sato case CONFIG_HOOK_LED_FLASH5: 383 1.1 sato vrled_set_state(sc, LED2DIVF); 384 1.1 sato break; 385 1.2 sato case CONFIG_HOOK_LED_BLINK: 386 1.1 sato vrled_set_state(sc, LED1SB); 387 1.1 sato break; 388 1.2 sato case CONFIG_HOOK_LED_BLINK2: 389 1.1 sato vrled_set_state(sc, LED2SB); 390 1.1 sato break; 391 1.1 sato default: 392 1.1 sato vrled_set_state(sc, LEDOFF); 393 1.1 sato } 394 1.1 sato return (0); 395 1.1 sato } 396 1.1 sato 397 1.1 sato /* end */ 398