Annotation of sys/arch/zaurus/dev/zaurus_ssp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: zaurus_ssp.c,v 1.6 2005/04/08 21:58:49 uwe Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/param.h>
! 20: #include <sys/systm.h>
! 21: #include <sys/device.h>
! 22:
! 23: #include <machine/bus.h>
! 24:
! 25: #include <arm/xscale/pxa2x0reg.h>
! 26: #include <arm/xscale/pxa2x0var.h>
! 27: #include <arm/xscale/pxa2x0_gpio.h>
! 28:
! 29: #include <zaurus/dev/zaurus_sspvar.h>
! 30:
! 31: #define GPIO_ADS7846_CS_C3000 14 /* SSP SFRM */
! 32: #define GPIO_MAX1111_CS_C3000 20
! 33: #define GPIO_TG_CS_C3000 53
! 34:
! 35: #define SSCR0_ADS7846_C3000 0x06ab
! 36: #define SSCR0_LZ9JG18 0x01ab
! 37: #define SSCR0_MAX1111 0x0387
! 38:
! 39: struct zssp_softc {
! 40: struct device sc_dev;
! 41: bus_space_tag_t sc_iot;
! 42: bus_space_handle_t sc_ioh;
! 43: };
! 44:
! 45: int zssp_match(struct device *, void *, void *);
! 46: void zssp_attach(struct device *, struct device *, void *);
! 47: void zssp_init(void);
! 48: void zssp_powerhook(int, void *);
! 49:
! 50: int zssp_read_max1111(u_int32_t);
! 51: u_int32_t zssp_read_ads7846(u_int32_t);
! 52: void zssp_write_lz9jg18(u_int32_t);
! 53:
! 54: struct cfattach zssp_ca = {
! 55: sizeof (struct zssp_softc), zssp_match, zssp_attach
! 56: };
! 57:
! 58: struct cfdriver zssp_cd = {
! 59: NULL, "zssp", DV_DULL
! 60: };
! 61:
! 62: int
! 63: zssp_match(struct device *parent, void *match, void *aux)
! 64: {
! 65: return 1;
! 66: }
! 67:
! 68: void
! 69: zssp_attach(struct device *parent, struct device *self, void *aux)
! 70: {
! 71: struct zssp_softc *sc = (struct zssp_softc *)self;
! 72:
! 73: sc->sc_iot = &pxa2x0_bs_tag;
! 74: if (bus_space_map(sc->sc_iot, PXA2X0_SSP1_BASE, PXA2X0_SSP_SIZE,
! 75: 0, &sc->sc_ioh)) {
! 76: printf(": can't map bus space\n");
! 77: return;
! 78: }
! 79:
! 80: printf("\n");
! 81:
! 82: if (powerhook_establish(zssp_powerhook, sc) == NULL)
! 83: printf("%s: can't establish power hook\n",
! 84: sc->sc_dev.dv_xname);
! 85:
! 86: zssp_init();
! 87: }
! 88:
! 89: /*
! 90: * Initialize the dedicated SSP unit and disable all chip selects.
! 91: * This function is called with interrupts disabled.
! 92: */
! 93: void
! 94: zssp_init(void)
! 95: {
! 96: struct zssp_softc *sc;
! 97:
! 98: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
! 99: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 100:
! 101: pxa2x0_clkman_config(CKEN_SSP, 1);
! 102:
! 103: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_LZ9JG18);
! 104: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR1, 0);
! 105:
! 106: pxa2x0_gpio_set_function(GPIO_ADS7846_CS_C3000, GPIO_OUT|GPIO_SET);
! 107: pxa2x0_gpio_set_function(GPIO_MAX1111_CS_C3000, GPIO_OUT|GPIO_SET);
! 108: pxa2x0_gpio_set_function(GPIO_TG_CS_C3000, GPIO_OUT|GPIO_SET);
! 109: }
! 110:
! 111: void
! 112: zssp_powerhook(int why, void *arg)
! 113: {
! 114: int s;
! 115:
! 116: if (why == PWR_RESUME) {
! 117: s = splhigh();
! 118: zssp_init();
! 119: splx(s);
! 120: }
! 121: }
! 122:
! 123: /*
! 124: * Transmit a single data word to one of the ICs, keep the chip selected
! 125: * afterwards, and don't wait for data to be returned in SSDR. Interrupts
! 126: * must be held off until zssp_ic_stop() gets called.
! 127: */
! 128: void
! 129: zssp_ic_start(int ic, u_int32_t data)
! 130: {
! 131: struct zssp_softc *sc;
! 132:
! 133: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
! 134: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 135:
! 136: /* disable other ICs */
! 137: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
! 138: if (ic != ZSSP_IC_ADS7846)
! 139: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
! 140: if (ic != ZSSP_IC_LZ9JG18)
! 141: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 142: if (ic != ZSSP_IC_MAX1111)
! 143: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
! 144:
! 145: /* activate the chosen one */
! 146: switch (ic) {
! 147: case ZSSP_IC_ADS7846:
! 148: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
! 149: SSCR0_ADS7846_C3000);
! 150: pxa2x0_gpio_clear_bit(GPIO_ADS7846_CS_C3000);
! 151: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, data);
! 152: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 153: & SSSR_TNF) != SSSR_TNF)
! 154: /* poll */;
! 155: break;
! 156: case ZSSP_IC_LZ9JG18:
! 157: pxa2x0_gpio_clear_bit(GPIO_TG_CS_C3000);
! 158: break;
! 159: case ZSSP_IC_MAX1111:
! 160: pxa2x0_gpio_clear_bit(GPIO_MAX1111_CS_C3000);
! 161: break;
! 162: }
! 163: }
! 164:
! 165: /*
! 166: * Read the last value from SSDR and deactivate all chip-selects.
! 167: */
! 168: u_int32_t
! 169: zssp_ic_stop(int ic)
! 170: {
! 171: struct zssp_softc *sc;
! 172: u_int32_t rv;
! 173:
! 174: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
! 175: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 176:
! 177: switch (ic) {
! 178: case ZSSP_IC_ADS7846:
! 179: /* read result of last command */
! 180: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 181: & SSSR_RNE) != SSSR_RNE)
! 182: /* poll */;
! 183: rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
! 184: break;
! 185: case ZSSP_IC_LZ9JG18:
! 186: case ZSSP_IC_MAX1111:
! 187: /* last value received is irrelevant or undefined */
! 188: default:
! 189: rv = 0;
! 190: break;
! 191: }
! 192:
! 193: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
! 194: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 195: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
! 196:
! 197: return (rv);
! 198: }
! 199:
! 200: /*
! 201: * Activate one of the chip-select lines, transmit one word value in
! 202: * each direction, and deactivate the chip-select again.
! 203: */
! 204: u_int32_t
! 205: zssp_ic_send(int ic, u_int32_t data)
! 206: {
! 207:
! 208: switch (ic) {
! 209: case ZSSP_IC_MAX1111:
! 210: return (zssp_read_max1111(data));
! 211: case ZSSP_IC_ADS7846:
! 212: return (zssp_read_ads7846(data));
! 213: case ZSSP_IC_LZ9JG18:
! 214: zssp_write_lz9jg18(data);
! 215: return 0;
! 216: default:
! 217: printf("zssp_ic_send: invalid IC %d\n", ic);
! 218: return 0;
! 219: }
! 220: }
! 221:
! 222: int
! 223: zssp_read_max1111(u_int32_t cmd)
! 224: {
! 225: struct zssp_softc *sc;
! 226: int voltage[2];
! 227: int i;
! 228: int s;
! 229:
! 230: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
! 231: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 232:
! 233: s = splhigh();
! 234:
! 235: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
! 236: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_MAX1111);
! 237:
! 238: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 239: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
! 240: pxa2x0_gpio_clear_bit(GPIO_MAX1111_CS_C3000);
! 241:
! 242: delay(1);
! 243:
! 244: /* Send the command word and read a dummy word back. */
! 245: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
! 246: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 247: & SSSR_TNF) != SSSR_TNF)
! 248: /* poll */;
! 249: /* XXX is this delay necessary? */
! 250: delay(1);
! 251: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 252: & SSSR_RNE) != SSSR_RNE)
! 253: /* poll */;
! 254: i = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
! 255:
! 256: for (i = 0; i < 2; i++) {
! 257: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, 0);
! 258: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 259: & SSSR_TNF) != SSSR_TNF)
! 260: /* poll */;
! 261: /* XXX again, is this delay necessary? */
! 262: delay(1);
! 263: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 264: & SSSR_RNE) != SSSR_RNE)
! 265: /* poll */;
! 266: voltage[i] = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
! 267: SSP_SSDR);
! 268: }
! 269:
! 270: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 271: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
! 272: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
! 273:
! 274: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
! 275:
! 276: /* XXX no idea what this means, but it's what Linux would do. */
! 277: if ((voltage[0] & 0xc0) != 0 || (voltage[1] & 0x3f) != 0)
! 278: voltage[0] = -1;
! 279: else
! 280: voltage[0] = ((voltage[0] << 2) & 0xfc) |
! 281: ((voltage[1] >> 6) & 0x03);
! 282:
! 283: splx(s);
! 284: return voltage[0];
! 285: }
! 286:
! 287: /* XXX - only does CS_ADS7846 */
! 288: u_int32_t
! 289: zssp_read_ads7846(u_int32_t cmd)
! 290: {
! 291: struct zssp_softc *sc;
! 292:
! 293: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 294: unsigned int cr0;
! 295: int s;
! 296: u_int32_t val;
! 297:
! 298: if (zssp_cd.cd_ndevs < 1 || zssp_cd.cd_devs[0] == NULL) {
! 299: printf("zssp_read_ads7846: not configured\n");
! 300: return 0;
! 301: }
! 302: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
! 303:
! 304: s = splhigh();
! 305: if (1) {
! 306: cr0 = SSCR0_ADS7846_C3000;
! 307: } else {
! 308: cr0 = 0x00ab;
! 309: }
! 310: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
! 311: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, cr0);
! 312:
! 313: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 314: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
! 315: pxa2x0_gpio_clear_bit(GPIO_ADS7846_CS_C3000);
! 316:
! 317: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
! 318:
! 319: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 320: & SSSR_TNF) != SSSR_TNF)
! 321: /* poll */;
! 322:
! 323: delay(1);
! 324:
! 325: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
! 326: & SSSR_RNE) != SSSR_RNE)
! 327: /* poll */;
! 328:
! 329: val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
! 330:
! 331: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000); /* deselect */
! 332:
! 333: splx(s);
! 334:
! 335: return val;
! 336: }
! 337:
! 338: void
! 339: zssp_write_lz9jg18(u_int32_t data)
! 340: {
! 341: int s;
! 342: int sclk_pin, sclk_fn;
! 343: int sfrm_pin, sfrm_fn;
! 344: int txd_pin, txd_fn;
! 345: int rxd_pin, rxd_fn;
! 346: int i;
! 347:
! 348: /* XXX this creates a DAC command from a backlight duty value. */
! 349: data = 0x40 | (data & 0x1f);
! 350:
! 351: if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) {
! 352: /* C3000 */
! 353: sclk_pin = 19;
! 354: sfrm_pin = 14;
! 355: txd_pin = 87;
! 356: rxd_pin = 86;
! 357: } else {
! 358: sclk_pin = 23;
! 359: sfrm_pin = 24;
! 360: txd_pin = 25;
! 361: rxd_pin = 26;
! 362: }
! 363:
! 364: s = splhigh();
! 365:
! 366: sclk_fn = pxa2x0_gpio_get_function(sclk_pin);
! 367: sfrm_fn = pxa2x0_gpio_get_function(sfrm_pin);
! 368: txd_fn = pxa2x0_gpio_get_function(txd_pin);
! 369: rxd_fn = pxa2x0_gpio_get_function(rxd_pin);
! 370:
! 371: pxa2x0_gpio_set_function(sfrm_pin, GPIO_OUT | GPIO_SET);
! 372: pxa2x0_gpio_set_function(sclk_pin, GPIO_OUT | GPIO_CLR);
! 373: pxa2x0_gpio_set_function(txd_pin, GPIO_OUT | GPIO_CLR);
! 374: pxa2x0_gpio_set_function(rxd_pin, GPIO_IN);
! 375:
! 376: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
! 377: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
! 378: pxa2x0_gpio_clear_bit(GPIO_TG_CS_C3000);
! 379:
! 380: delay(10);
! 381:
! 382: for (i = 0; i < 8; i++) {
! 383: if (data & 0x80)
! 384: pxa2x0_gpio_set_bit(txd_pin);
! 385: else
! 386: pxa2x0_gpio_clear_bit(txd_pin);
! 387: delay(10);
! 388: pxa2x0_gpio_set_bit(sclk_pin);
! 389: delay(10);
! 390: pxa2x0_gpio_clear_bit(sclk_pin);
! 391: delay(10);
! 392: data <<= 1;
! 393: }
! 394:
! 395: pxa2x0_gpio_clear_bit(txd_pin);
! 396: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
! 397:
! 398: pxa2x0_gpio_set_function(sclk_pin, sclk_fn);
! 399: pxa2x0_gpio_set_function(sfrm_pin, sfrm_fn);
! 400: pxa2x0_gpio_set_function(txd_pin, txd_fn);
! 401: pxa2x0_gpio_set_function(rxd_pin, rxd_fn);
! 402:
! 403: splx(s);
! 404: }
CVSweb