1 /* $NetBSD: scoop.c,v 1.13 2014/09/23 14:49:46 nonaka Exp $ */ 2 /* $OpenBSD: zaurus_scoop.c,v 1.12 2005/11/17 05:26:31 uwe Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: scoop.c,v 1.13 2014/09/23 14:49:46 nonaka Exp $"); 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 #include <sys/conf.h> 27 #include <sys/gpio.h> 28 #include <sys/bus.h> 29 30 #include <arm/xscale/pxa2x0var.h> 31 32 #include <zaurus/zaurus/zaurus_reg.h> 33 #include <zaurus/zaurus/zaurus_var.h> 34 35 #include <zaurus/dev/scoopreg.h> 36 #include <zaurus/dev/scoopvar.h> 37 38 #include "ioconf.h" 39 40 struct scoop_softc { 41 device_t sc_dev; 42 43 bus_space_tag_t sc_iot; 44 bus_space_handle_t sc_ioh; 45 46 uint16_t sc_gpwr; /* GPIO state before suspend */ 47 }; 48 49 static int scoopmatch(device_t, cfdata_t, void *); 50 static void scoopattach(device_t, device_t, void *); 51 52 CFATTACH_DECL_NEW(scoop, sizeof(struct scoop_softc), 53 scoopmatch, scoopattach, NULL, NULL); 54 55 #if 0 56 static int scoop_gpio_pin_read(struct scoop_softc *, int); 57 #endif 58 static void scoop_gpio_pin_write(struct scoop_softc *, int, int); 59 static void scoop_gpio_pin_ctl(struct scoop_softc *, int, int); 60 61 static struct scoop_softc *backlight_sc; 62 static uint8_t backlight_on_init = 1; 63 static uint8_t backlight_cont_init = 0; 64 65 enum scoop_card { 66 SD_CARD, 67 CF_CARD /* socket 0 (external) */ 68 }; 69 70 static void scoop0_set_card_power(enum scoop_card card, int new_cpr); 71 72 static int 73 scoopmatch(device_t parent, cfdata_t cf, void *aux) 74 { 75 76 /* 77 * Only C3000-like models are known to have two SCOOPs. 78 */ 79 if (ZAURUS_ISC3000) 80 return (cf->cf_unit < 2); 81 return (cf->cf_unit == 0); 82 } 83 84 static void 85 scoopattach(device_t parent, device_t self, void *aux) 86 { 87 struct scoop_softc *sc = device_private(self); 88 struct pxaip_attach_args *pxa = aux; 89 bus_addr_t addr; 90 bus_size_t size; 91 92 sc->sc_dev = self; 93 sc->sc_iot = pxa->pxa_iot; 94 95 aprint_normal(": PCMCIA/GPIO controller\n"); 96 aprint_naive("\n"); 97 98 if (pxa->pxa_addr != -1) 99 addr = pxa->pxa_addr; 100 else if (device_unit(sc->sc_dev) == 0) 101 addr = C3000_SCOOP0_BASE; 102 else 103 addr = C3000_SCOOP1_BASE; 104 105 size = pxa->pxa_size < SCOOP_SIZE ? SCOOP_SIZE : pxa->pxa_size; 106 107 if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) { 108 aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); 109 return; 110 } 111 112 if (ZAURUS_ISC3000 && device_unit(sc->sc_dev) == 1) { 113 scoop_gpio_pin_ctl(sc, SCOOP1_AKIN_PULLUP, GPIO_PIN_OUTPUT); 114 scoop_gpio_pin_write(sc, SCOOP1_AKIN_PULLUP, GPIO_PIN_LOW); 115 backlight_sc = sc; 116 scoop_set_backlight(backlight_on_init, backlight_cont_init); 117 } else if (ZAURUS_ISC860) { 118 scoop_gpio_pin_ctl(sc, SCOOP0_AKIN_PULLUP, GPIO_PIN_OUTPUT); 119 scoop_gpio_pin_write(sc, SCOOP0_AKIN_PULLUP, GPIO_PIN_LOW); 120 backlight_sc = sc; 121 scoop_set_backlight(backlight_on_init, backlight_cont_init); 122 } 123 } 124 125 #if 0 126 static int 127 scoop_gpio_pin_read(struct scoop_softc *sc, int pin) 128 { 129 uint16_t bit = (1 << pin); 130 uint16_t rv; 131 132 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR); 133 return (rv & bit) ? 1 : 0; 134 } 135 #endif 136 137 static void 138 scoop_gpio_pin_write(struct scoop_softc *sc, int pin, int level) 139 { 140 uint16_t bit = (1 << pin); 141 uint16_t rv; 142 143 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR); 144 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 145 (level == GPIO_PIN_LOW) ? (rv & ~bit) : (rv | bit)); 146 } 147 148 static void 149 scoop_gpio_pin_ctl(struct scoop_softc *sc, int pin, int flags) 150 { 151 uint16_t bit = (1 << pin); 152 uint16_t rv; 153 154 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPCR); 155 switch (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 156 case GPIO_PIN_INPUT: 157 rv &= ~bit; 158 break; 159 case GPIO_PIN_OUTPUT: 160 rv |= bit; 161 break; 162 } 163 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPCR, rv); 164 } 165 166 /* 167 * Turn the LCD background light and contrast signal on or off. 168 */ 169 void 170 scoop_set_backlight(int on, int cont) 171 { 172 struct scoop_softc *sc = backlight_sc; 173 174 if (sc == NULL) { 175 backlight_cont_init = cont; 176 backlight_on_init = on; 177 } else { 178 if (ZAURUS_ISC3000) { 179 scoop_gpio_pin_write(sc, SCOOP1_BACKLIGHT_CONT, !cont); 180 scoop_gpio_pin_write(sc, SCOOP1_BACKLIGHT_ON, on); 181 } else if (ZAURUS_ISC860) { 182 scoop_gpio_pin_write(sc, SCOOP0_BACKLIGHT_CONT, cont); 183 } 184 } 185 } 186 187 /* 188 * Turn the infrared LED on or off (must be on while transmitting). 189 */ 190 void 191 scoop_set_irled(int on) 192 { 193 struct scoop_softc *sc; 194 195 sc = device_lookup_private(&scoop_cd, 1); 196 if (sc != NULL) { 197 /* IR_ON is inverted */ 198 scoop_gpio_pin_write(sc, SCOOP1_IR_ON, !on); 199 } 200 } 201 202 /* 203 * Turn the green and orange LEDs on or off. If the orange LED is on, 204 * then it is wired to indicate if A/C is connected. The green LED has 205 * no such predefined function. 206 */ 207 void 208 scoop_led_set(int led, int on) 209 { 210 struct scoop_softc *sc; 211 212 sc = device_lookup_private(&scoop_cd, 0); 213 if (sc != NULL) { 214 if ((led & SCOOP_LED_GREEN) != 0) { 215 scoop_gpio_pin_write(sc, SCOOP0_LED_GREEN, on); 216 } 217 if (scoop_cd.cd_ndevs > 1 && (led & SCOOP_LED_ORANGE) != 0) { 218 scoop_gpio_pin_write(sc, SCOOP0_LED_ORANGE_C3000, on); 219 } 220 } 221 } 222 223 /* 224 * Enable or disable the headphone output connection. 225 */ 226 void 227 scoop_set_headphone(int on) 228 { 229 struct scoop_softc *sc; 230 231 sc = device_lookup_private(&scoop_cd, 0); 232 if (sc == NULL) 233 return; 234 235 scoop_gpio_pin_ctl(sc, SCOOP0_MUTE_L, GPIO_PIN_OUTPUT); 236 scoop_gpio_pin_ctl(sc, SCOOP0_MUTE_R, GPIO_PIN_OUTPUT); 237 238 if (on) { 239 scoop_gpio_pin_write(sc, SCOOP0_MUTE_L, GPIO_PIN_HIGH); 240 scoop_gpio_pin_write(sc, SCOOP0_MUTE_R, GPIO_PIN_HIGH); 241 } else { 242 scoop_gpio_pin_write(sc, SCOOP0_MUTE_L, GPIO_PIN_LOW); 243 scoop_gpio_pin_write(sc, SCOOP0_MUTE_R, GPIO_PIN_LOW); 244 } 245 } 246 247 /* 248 * Enable or disable the speaker output connection. 249 */ 250 void 251 scoop_set_speaker(int onoff) 252 { 253 struct scoop_softc *sc; 254 255 if (!ZAURUS_ISC860) 256 return; 257 258 sc = device_lookup_private(&scoop_cd, 0); 259 if (sc == NULL) 260 return; 261 262 scoop_gpio_pin_ctl(sc, SCOOP0_AMP_ON, GPIO_PIN_OUTPUT); 263 if (onoff) { 264 scoop_gpio_pin_write(sc, SCOOP0_AMP_ON, GPIO_PIN_HIGH); 265 } else { 266 scoop_gpio_pin_write(sc, SCOOP0_AMP_ON, GPIO_PIN_LOW); 267 } 268 } 269 270 /* 271 * Enable or disable the mic bias 272 */ 273 void 274 scoop_set_mic_bias(int onoff) 275 { 276 struct scoop_softc *sc0; 277 struct scoop_softc *sc1; 278 279 sc0 = device_lookup_private(&scoop_cd, 0); 280 sc1 = device_lookup_private(&scoop_cd, 1); 281 282 if (sc1 != NULL) { 283 scoop_gpio_pin_write(sc1, SCOOP1_MIC_BIAS, onoff); 284 } else if (sc0 != NULL) { 285 scoop_gpio_pin_write(sc0, SCOOP0_MIC_BIAS, onoff); 286 } 287 } 288 289 /* 290 * Turn on pullup resistor while not reading the remote control. 291 */ 292 void 293 scoop_akin_pullup(int enable) 294 { 295 struct scoop_softc *sc0; 296 struct scoop_softc *sc1; 297 298 sc0 = device_lookup_private(&scoop_cd, 0); 299 sc1 = device_lookup_private(&scoop_cd, 1); 300 301 if (sc1 != NULL) { 302 scoop_gpio_pin_write(sc1, SCOOP1_AKIN_PULLUP, enable); 303 } else if (sc0 != NULL) { 304 scoop_gpio_pin_write(sc0, SCOOP0_AKIN_PULLUP, enable); 305 } 306 } 307 308 void 309 scoop_battery_temp_adc(int enable) 310 { 311 struct scoop_softc *sc; 312 313 sc = device_lookup_private(&scoop_cd, 0); 314 315 if (sc != NULL) { 316 scoop_gpio_pin_write(sc, SCOOP0_ADC_TEMP_ON_C3000, enable); 317 } 318 } 319 320 void 321 scoop_charge_battery(int enable, int voltage_high) 322 { 323 struct scoop_softc *sc; 324 325 if (ZAURUS_ISC860) 326 return; 327 328 sc = device_lookup_private(&scoop_cd, 0); 329 330 if (sc != NULL) { 331 scoop_gpio_pin_write(sc, SCOOP0_JK_B_C3000, voltage_high); 332 scoop_gpio_pin_write(sc, SCOOP0_CHARGE_OFF_C3000, !enable); 333 } 334 } 335 336 void 337 scoop_discharge_battery(int enable) 338 { 339 struct scoop_softc *sc; 340 341 if (ZAURUS_ISC860) 342 return; 343 344 sc = device_lookup_private(&scoop_cd, 0); 345 346 if (sc != NULL) { 347 scoop_gpio_pin_write(sc, SCOOP0_JK_A_C3000, enable); 348 } 349 } 350 351 /* 352 * Enable or disable 3.3V power to the SD/MMC card slot. 353 */ 354 void 355 scoop_set_sdmmc_power(int on) 356 { 357 358 scoop0_set_card_power(SD_CARD, on ? SCP_CPR_SD_3V : SCP_CPR_OFF); 359 } 360 361 /* 362 * The Card Power Register of the first SCOOP unit controls the power 363 * for the first CompactFlash slot and the SD/MMC card slot as well. 364 */ 365 void 366 scoop0_set_card_power(enum scoop_card card, int new_cpr) 367 { 368 struct scoop_softc *sc; 369 bus_space_tag_t iot; 370 bus_space_handle_t ioh; 371 uint16_t cpr; 372 373 if (ZAURUS_ISC860) 374 return; 375 376 sc = device_lookup_private(&scoop_cd, 0); 377 if (sc == NULL) 378 return; 379 380 iot = sc->sc_iot; 381 ioh = sc->sc_ioh; 382 383 cpr = bus_space_read_2(iot, ioh, SCOOP_CPR); 384 if (new_cpr & SCP_CPR_VOLTAGE_MSK) { 385 if (card == CF_CARD) 386 cpr |= SCP_CPR_5V; 387 else if (card == SD_CARD) 388 cpr |= SCP_CPR_SD_3V; 389 390 scoop_gpio_pin_write(sc, SCOOP0_CF_POWER_C3000, 1); 391 if (!ISSET(cpr, SCP_CPR_5V) && !ISSET(cpr, SCP_CPR_SD_3V)) 392 delay(5000); 393 bus_space_write_2(iot, ioh, SCOOP_CPR, cpr | new_cpr); 394 } else { 395 if (card == CF_CARD) 396 cpr &= ~SCP_CPR_5V; 397 else if (card == SD_CARD) 398 cpr &= ~SCP_CPR_SD_3V; 399 400 if (!ISSET(cpr, SCP_CPR_5V) && !ISSET(cpr, SCP_CPR_SD_3V)) { 401 bus_space_write_2(iot, ioh, SCOOP_CPR, SCP_CPR_OFF); 402 delay(1000); 403 scoop_gpio_pin_write(sc, SCOOP0_CF_POWER_C3000, 0); 404 } else 405 bus_space_write_2(iot, ioh, SCOOP_CPR, cpr | new_cpr); 406 } 407 } 408 409 void 410 scoop_check_mcr(void) 411 { 412 struct scoop_softc *sc0, *sc1, *sc; 413 uint16_t v; 414 415 sc0 = device_lookup_private(&scoop_cd, 0); 416 sc1 = device_lookup_private(&scoop_cd, 1); 417 418 /* C3000 */ 419 if (sc1 != NULL) { 420 sc = sc0; 421 v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR); 422 if ((v & 0x100) == 0) { 423 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR, 424 0x0101); 425 } 426 427 sc = sc1; 428 v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR); 429 if ((v & 0x100) == 0) { 430 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR, 431 0x0101); 432 } 433 } 434 } 435 436 void 437 scoop_suspend(void) 438 { 439 struct scoop_softc *sc, *sc0, *sc1; 440 uint32_t rv; 441 442 if (ZAURUS_ISC860) 443 return; 444 445 sc0 = device_lookup_private(&scoop_cd, 0); 446 sc1 = device_lookup_private(&scoop_cd, 1); 447 448 if (sc0 != NULL) { 449 sc = sc0; 450 sc->sc_gpwr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 451 SCOOP_GPWR); 452 /* C3000 */ 453 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 454 sc->sc_gpwr & ~((1<<SCOOP0_MUTE_L) | (1<<SCOOP0_MUTE_R) | 455 (1<<SCOOP0_JK_A_C3000) | (1<<SCOOP0_ADC_TEMP_ON_C3000) | 456 (1<<SCOOP0_LED_GREEN))); 457 } 458 459 /* C3000 */ 460 if (sc1 != NULL) { 461 sc = sc1; 462 sc->sc_gpwr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 463 SCOOP_GPWR); 464 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 465 sc->sc_gpwr & ~((1<<SCOOP1_RESERVED_4) | 466 (1<<SCOOP1_RESERVED_5) | (1<<SCOOP1_RESERVED_6) | 467 (1<<SCOOP1_BACKLIGHT_CONT) | (1<<SCOOP1_BACKLIGHT_ON) | 468 (1<<SCOOP1_MIC_BIAS))); 469 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR); 470 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 471 rv | ((1<<SCOOP1_IR_ON) | (1<<SCOOP1_RESERVED_3))); 472 } 473 } 474 475 void 476 scoop_resume(void) 477 { 478 struct scoop_softc *sc, *sc0, *sc1; 479 480 sc0 = device_lookup_private(&scoop_cd, 0); 481 sc1 = device_lookup_private(&scoop_cd, 1); 482 483 if (sc0 != NULL) { 484 sc = sc0; 485 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 486 sc->sc_gpwr); 487 } 488 489 if (sc1 != NULL) { 490 sc = sc1; 491 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 492 sc->sc_gpwr); 493 } 494 } 495