[BACK]Return to sa11x0_ssp.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / sa11x0

Annotation of sys/arch/arm/sa11x0/sa11x0_ssp.c, Revision 1.1

1.1     ! nbrk        1: /*     $Id$    */
        !             2: /*
        !             3:  * StrongARM 11[01]0 Synchronous Serial Port.
        !             4:  * Actually it can operate using different serial protocols,
        !             5:  * but we are interested in Motorola SPI for now.
        !             6:  */
        !             7: #include <sys/param.h>
        !             8: #include <sys/systm.h>
        !             9: #include <sys/device.h>
        !            10: #include <sys/proc.h>
        !            11: #include <sys/conf.h>
        !            12: #include <sys/endian.h>
        !            13:
        !            14: #include <dev/spivar.h>
        !            15:
        !            16: #include <machine/bus.h>
        !            17:
        !            18: #include <arm/sa11x0/sa11x0_reg.h>
        !            19: #include <arm/sa11x0/sa11x0_var.h>
        !            20: #include <arm/sa11x0/sa11x0_gpioreg.h>
        !            21: #include <arm/sa11x0/sa11x0_sspreg.h>
        !            22:
        !            23: #define INVERTBITS(x)                                                   \
        !            24:         do {                                                            \
        !            25:                 (x) = ((((x) & 0xf0) >> 4) | (((x) & 0x0f) << 4));      \
        !            26:                 (x) = ((((x) & 0xcc) >> 2) | (((x) & 0x33) << 2));      \
        !            27:                 (x) = ((((x) & 0xaa) >> 1) | (((x) & 0x55) << 1));      \
        !            28:         } while (0)
        !            29:
        !            30: struct sassp_softc {
        !            31:        struct device   sc_dev;
        !            32:
        !            33:        bus_space_tag_t sc_iot;
        !            34:        bus_space_handle_t      sc_ioh;
        !            35:        /* XXX ioh for gpioc */
        !            36:        bus_space_handle_t      sc_gpioch;
        !            37:
        !            38:        struct spi_bus  sc_bus;
        !            39:        int     sc_active;
        !            40: };
        !            41:
        !            42: /*
        !            43:  * Prototypes.
        !            44:  */
        !            45: int    sassp_match(struct device *parent, void *cf, void *aux);
        !            46: void   sassp_attach(struct device *parent, struct device *self, void *aux);
        !            47: int            sassp_shift_1(void *arg, uint8_t data);
        !            48: #if 0
        !            49: uint16_t       sassp_shift_2(void *arg, uint16_t data);
        !            50: uint32_t       sassp_shift_4(void *arg, uint32_t data);
        !            51: #endif
        !            52: int    sassp_acquire(void *arg);
        !            53: void   sassp_release(void *arg);
        !            54:
        !            55: /*
        !            56:  * Autoconf glue.
        !            57:  */
        !            58: struct cfattach        sassp_ca = {
        !            59:        sizeof(struct sassp_softc), sassp_match, sassp_attach, NULL, NULL
        !            60: };
        !            61:
        !            62: struct cfdriver        sassp_cd = {
        !            63:        NULL,
        !            64:        "sassp",
        !            65:        DV_DULL
        !            66: };
        !            67:
        !            68:
        !            69: int
        !            70: sassp_match(struct device *parent, void *cf, void *aux)
        !            71: {
        !            72:        struct saip_attach_args *saa = aux;
        !            73:
        !            74:        if (saa->sai_addr == SASSP_BASE)
        !            75:                return (1);
        !            76:
        !            77:        return (0);
        !            78: }
        !            79:
        !            80: void
        !            81: sassp_attach(struct device *parent, struct device *self, void *aux)
        !            82: {
        !            83:        struct sassp_softc *sc = (struct sassp_softc *)self;
        !            84:        struct saip_attach_args *saa = aux;
        !            85:        struct spibus_attach_args       sba;
        !            86:
        !            87:        sc->sc_iot = saa->sai_iot;
        !            88:
        !            89:        if (bus_space_map(sc->sc_iot, saa->sai_addr, SASSP_NPORTS, 0, &sc->sc_ioh)) {
        !            90:                printf(": can't map i/o space\n");
        !            91:                return;
        !            92:        }
        !            93:
        !            94:        if (bus_space_map(sc->sc_iot, SAGPIO_BASE, SAGPIO_NPORTS, 0, &sc->sc_gpioch)) {
        !            95:                printf(": can't map gpio i/o space\n");
        !            96:                return;
        !            97:        }
        !            98:
        !            99:        printf(": SA-11x0 SSP/MCP txfifo %d rxfifo %d\n", SASSP_TXFIFOLEN, SASSP_RXFIFOLEN);
        !           100:
        !           101: #if 0
        !           102:        /* Force into SPI @460800 */
        !           103:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SASSP_CR0, 0x07 /* DSS */ | CR0_SSE | 0x03 /* SCR */ );
        !           104:
        !           105:        /* Read back rate */
        !           106:        sc->sc_bus.bus_speed = 3686400 /
        !           107:                (2 *( (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SASSP_CR0) & CR0_SCR_MASK) + 1 ));
        !           108:
        !           109:        /* Set polarity and phase */
        !           110:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SASSP_CR1, CR1_SPO | CR1_SPH);
        !           111:
        !           112:        printf("%s: configured to SPI mode at speed %ld\n", sc->sc_dev.dv_xname, sc->sc_bus.bus_speed);
        !           113: #endif
        !           114:        /*
        !           115:         * Attach SPI bus.
        !           116:         */
        !           117:        sc->sc_bus.bus_cookie = sc;
        !           118:        sc->sc_bus.bus_shift_1 = sassp_shift_1;
        !           119:        sc->sc_bus.bus_acquire = sassp_acquire;
        !           120:        sc->sc_bus.bus_release = sassp_release;
        !           121:
        !           122:        /* attach args */
        !           123:        sba.sba_bus = &sc->sc_bus;
        !           124:
        !           125:        config_found(&sc->sc_dev, &sba, spibus_print);
        !           126:
        !           127:        return;
        !           128: }
        !           129:
        !           130: int
        !           131: sassp_shift_1(void *arg, uint8_t data)
        !           132: {
        !           133:        /*
        !           134:         * Shift a byte on a SPI bus.
        !           135:         */
        !           136:        struct sassp_softc *sc = arg;
        !           137:        uint32_t        timeo;
        !           138:
        !           139:        /*
        !           140:         * Caller should already bother about locks..
        !           141:         */
        !           142:
        !           143:        /* wait for TX fifo to drain a bit if it's full */
        !           144:        while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SASSP_SR) & SR_TNF) == 0)
        !           145:                ;
        !           146:
        !           147:        /* wait for low on GPIO 10 */
        !           148:        timeo = 400000;
        !           149:        while (timeo--) {
        !           150:                if ( (bus_space_read_4(sc->sc_iot, sc->sc_gpioch, SAGPIO_PLR) & (1 << 10)) == 0)
        !           151:                        break;
        !           152:
        !           153:                if (timeo == 0) {
        !           154:                        printf("%s: SSP tx timeout\n", sc->sc_dev.dv_xname);
        !           155:                        return(-1);
        !           156:                }
        !           157:        }
        !           158:
        !           159:        /* invert data before sending */
        !           160:        INVERTBITS(data);
        !           161:
        !           162:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, SASSP_DR, (uint16_t)(data << 8));
        !           163:
        !           164:        /* wait for RX fifo become not empty */
        !           165:        timeo = 400000;
        !           166:        while ( ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SASSP_SR) & SR_RNE) == 0) && timeo--)
        !           167:                ;
        !           168:        if (timeo == 0)
        !           169:                printf("%s: WARNING, rx fifo empty after timeout\n", sc->sc_dev.dv_xname);
        !           170:
        !           171:        /* read bottom of rx fifo */
        !           172:        data = (uint8_t)bus_space_read_4(sc->sc_iot, sc->sc_ioh, SASSP_DR);
        !           173:
        !           174:        /* invert received data */
        !           175:        INVERTBITS(data);
        !           176:
        !           177:        return(data);
        !           178: }
        !           179:
        !           180: int
        !           181: sassp_acquire(void *arg)
        !           182: {
        !           183:        /*
        !           184:         * Wake up slave by setting GPIO 25 low.
        !           185:         */
        !           186:        struct sassp_softc *sc = arg;
        !           187: #if 0
        !           188:        uint32_t        plmask;
        !           189: #endif
        !           190:        /* check if this bus is already acquired */
        !           191:        if (sc->sc_active) {
        !           192:                printf("%s: WARNING, trying to acquire locked bus\n", sc->sc_dev.dv_xname);
        !           193:                return(1);
        !           194:        }
        !           195: #if 0
        !           196:        /*
        !           197:         * Modify Pin Level register.
        !           198:         */
        !           199:        plmask = bus_space_read_4(sc->sc_iot, sc->sc_gpioch, 0x0c /* XXX SAGPIO_PCR */);
        !           200:        plmask |= 1 << 25;
        !           201:        bus_space_write_4(sc->sc_iot, sc->sc_gpioch, 0x0c, plmask);
        !           202: #endif
        !           203:        sc->sc_active = 1;
        !           204:
        !           205:        return(0);
        !           206: }
        !           207:
        !           208: void
        !           209: sassp_release(void *arg)
        !           210: {
        !           211:        /*
        !           212:         * Release bus by bringing GPIO 25 back to high.
        !           213:         */
        !           214:        struct sassp_softc *sc = arg;
        !           215: #if 0
        !           216:        uint32_t        plmask;
        !           217:
        !           218:        plmask = bus_space_read_4(sc->sc_iot, sc->sc_gpioch, 0x08 /* XXX SAGPIO_PSR */);
        !           219:        plmask |= (1 << 25);
        !           220:        bus_space_write_4(sc->sc_iot, sc->sc_gpioch, 0x08, plmask);
        !           221: #endif
        !           222:        sc->sc_active = 0;
        !           223: }
        !           224:

CVSweb