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