[BACK]Return to zaurus_ssp.c CVS log [TXT][DIR] Up to [local] / sys / arch / zaurus / dev

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