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