[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

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