1 /* $NetBSD: scoop.c,v 1.12 2012/10/27 17:18:14 chs 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.12 2012/10/27 17:18:14 chs 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 mic bias 249 */ 250 void 251 scoop_set_mic_bias(int onoff) 252 { 253 struct scoop_softc *sc1; 254 255 sc1 = device_lookup_private(&scoop_cd, 1); 256 if (sc1 != NULL) 257 scoop_gpio_pin_write(sc1, SCOOP1_MIC_BIAS, onoff); 258 } 259 260 /* 261 * Turn on pullup resistor while not reading the remote control. 262 */ 263 void 264 scoop_akin_pullup(int enable) 265 { 266 struct scoop_softc *sc0; 267 struct scoop_softc *sc1; 268 269 sc0 = device_lookup_private(&scoop_cd, 0); 270 sc1 = device_lookup_private(&scoop_cd, 1); 271 272 if (sc1 != NULL) { 273 scoop_gpio_pin_write(sc1, SCOOP1_AKIN_PULLUP, enable); 274 } else if (sc0 != NULL) { 275 scoop_gpio_pin_write(sc0, SCOOP0_AKIN_PULLUP, enable); 276 } 277 } 278 279 void 280 scoop_battery_temp_adc(int enable) 281 { 282 struct scoop_softc *sc; 283 284 sc = device_lookup_private(&scoop_cd, 0); 285 286 if (sc != NULL) { 287 scoop_gpio_pin_write(sc, SCOOP0_ADC_TEMP_ON_C3000, enable); 288 } 289 } 290 291 void 292 scoop_charge_battery(int enable, int voltage_high) 293 { 294 struct scoop_softc *sc; 295 296 if (ZAURUS_ISC860) 297 return; 298 299 sc = device_lookup_private(&scoop_cd, 0); 300 301 if (sc != NULL) { 302 scoop_gpio_pin_write(sc, SCOOP0_JK_B_C3000, voltage_high); 303 scoop_gpio_pin_write(sc, SCOOP0_CHARGE_OFF_C3000, !enable); 304 } 305 } 306 307 void 308 scoop_discharge_battery(int enable) 309 { 310 struct scoop_softc *sc; 311 312 if (ZAURUS_ISC860) 313 return; 314 315 sc = device_lookup_private(&scoop_cd, 0); 316 317 if (sc != NULL) { 318 scoop_gpio_pin_write(sc, SCOOP0_JK_A_C3000, enable); 319 } 320 } 321 322 /* 323 * Enable or disable 3.3V power to the SD/MMC card slot. 324 */ 325 void 326 scoop_set_sdmmc_power(int on) 327 { 328 329 scoop0_set_card_power(SD_CARD, on ? SCP_CPR_SD_3V : SCP_CPR_OFF); 330 } 331 332 /* 333 * The Card Power Register of the first SCOOP unit controls the power 334 * for the first CompactFlash slot and the SD/MMC card slot as well. 335 */ 336 void 337 scoop0_set_card_power(enum scoop_card card, int new_cpr) 338 { 339 struct scoop_softc *sc; 340 bus_space_tag_t iot; 341 bus_space_handle_t ioh; 342 uint16_t cpr; 343 344 if (ZAURUS_ISC860) 345 return; 346 347 sc = device_lookup_private(&scoop_cd, 0); 348 if (sc == NULL) 349 return; 350 351 iot = sc->sc_iot; 352 ioh = sc->sc_ioh; 353 354 cpr = bus_space_read_2(iot, ioh, SCOOP_CPR); 355 if (new_cpr & SCP_CPR_VOLTAGE_MSK) { 356 if (card == CF_CARD) 357 cpr |= SCP_CPR_5V; 358 else if (card == SD_CARD) 359 cpr |= SCP_CPR_SD_3V; 360 361 scoop_gpio_pin_write(sc, SCOOP0_CF_POWER_C3000, 1); 362 if (!ISSET(cpr, SCP_CPR_5V) && !ISSET(cpr, SCP_CPR_SD_3V)) 363 delay(5000); 364 bus_space_write_2(iot, ioh, SCOOP_CPR, cpr | new_cpr); 365 } else { 366 if (card == CF_CARD) 367 cpr &= ~SCP_CPR_5V; 368 else if (card == SD_CARD) 369 cpr &= ~SCP_CPR_SD_3V; 370 371 if (!ISSET(cpr, SCP_CPR_5V) && !ISSET(cpr, SCP_CPR_SD_3V)) { 372 bus_space_write_2(iot, ioh, SCOOP_CPR, SCP_CPR_OFF); 373 delay(1000); 374 scoop_gpio_pin_write(sc, SCOOP0_CF_POWER_C3000, 0); 375 } else 376 bus_space_write_2(iot, ioh, SCOOP_CPR, cpr | new_cpr); 377 } 378 } 379 380 void 381 scoop_check_mcr(void) 382 { 383 struct scoop_softc *sc0, *sc1, *sc; 384 uint16_t v; 385 386 sc0 = device_lookup_private(&scoop_cd, 0); 387 sc1 = device_lookup_private(&scoop_cd, 1); 388 389 /* C3000 */ 390 if (sc1 != NULL) { 391 sc = sc0; 392 v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR); 393 if ((v & 0x100) == 0) { 394 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR, 395 0x0101); 396 } 397 398 sc = sc1; 399 v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR); 400 if ((v & 0x100) == 0) { 401 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_MCR, 402 0x0101); 403 } 404 } 405 } 406 407 void 408 scoop_suspend(void) 409 { 410 struct scoop_softc *sc, *sc0, *sc1; 411 uint32_t rv; 412 413 if (ZAURUS_ISC860) 414 return; 415 416 sc0 = device_lookup_private(&scoop_cd, 0); 417 sc1 = device_lookup_private(&scoop_cd, 1); 418 419 if (sc0 != NULL) { 420 sc = sc0; 421 sc->sc_gpwr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 422 SCOOP_GPWR); 423 /* C3000 */ 424 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 425 sc->sc_gpwr & ~((1<<SCOOP0_MUTE_L) | (1<<SCOOP0_MUTE_R) | 426 (1<<SCOOP0_JK_A_C3000) | (1<<SCOOP0_ADC_TEMP_ON_C3000) | 427 (1<<SCOOP0_LED_GREEN))); 428 } 429 430 /* C3000 */ 431 if (sc1 != NULL) { 432 sc = sc1; 433 sc->sc_gpwr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 434 SCOOP_GPWR); 435 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 436 sc->sc_gpwr & ~((1<<SCOOP1_RESERVED_4) | 437 (1<<SCOOP1_RESERVED_5) | (1<<SCOOP1_RESERVED_6) | 438 (1<<SCOOP1_BACKLIGHT_CONT) | (1<<SCOOP1_BACKLIGHT_ON) | 439 (1<<SCOOP1_MIC_BIAS))); 440 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR); 441 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 442 rv | ((1<<SCOOP1_IR_ON) | (1<<SCOOP1_RESERVED_3))); 443 } 444 } 445 446 void 447 scoop_resume(void) 448 { 449 struct scoop_softc *sc, *sc0, *sc1; 450 451 sc0 = device_lookup_private(&scoop_cd, 0); 452 sc1 = device_lookup_private(&scoop_cd, 1); 453 454 if (sc0 != NULL) { 455 sc = sc0; 456 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 457 sc->sc_gpwr); 458 } 459 460 if (sc1 != NULL) { 461 sc = sc1; 462 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCOOP_GPWR, 463 sc->sc_gpwr); 464 } 465 } 466