]>
Commit | Line | Data |
---|---|---|
59d06122 RR |
1 | /* |
2 | * Freescale Coldfire Queued SPI driver | |
3 | * | |
4 | * NOTE: | |
5 | * This driver is written to transfer 8 bit at-a-time and uses the dedicated | |
6 | * SPI slave select pins as bit-banged GPIO to work with spi_flash subsystem. | |
7 | * | |
59d06122 RR |
8 | * Copyright (C) 2011 Ruggedcom, Inc. |
9 | * Richard Retanubun ([email protected]) | |
10 | * | |
1a459660 | 11 | * SPDX-License-Identifier: GPL-2.0+ |
59d06122 RR |
12 | */ |
13 | ||
14 | #include <common.h> | |
15 | #include <malloc.h> | |
16 | #include <spi.h> | |
17 | #include <asm/immap.h> | |
18 | #include <asm/io.h> | |
19 | ||
20 | DECLARE_GLOBAL_DATA_PTR; | |
21 | ||
a46988f1 | 22 | #define to_cf_qspi_slave(s) container_of(s, struct cf_qspi_slave, slave) |
59d06122 RR |
23 | |
24 | struct cf_qspi_slave { | |
25 | struct spi_slave slave; /* Specific bus:cs ID for each device */ | |
26 | qspi_t *regs; /* Pointer to SPI controller registers */ | |
27 | u16 qmr; /* QMR: Queued Mode Register */ | |
28 | u16 qwr; /* QWR: Queued Wrap Register */ | |
29 | u16 qcr; /* QCR: Queued Command Ram */ | |
30 | }; | |
31 | ||
32 | /* Register write wrapper functions */ | |
33 | static void write_qmr(volatile qspi_t *qspi, u16 val) { qspi->mr = val; } | |
34 | static void write_qdlyr(volatile qspi_t *qspi, u16 val) { qspi->dlyr = val; } | |
35 | static void write_qwr(volatile qspi_t *qspi, u16 val) { qspi->wr = val; } | |
36 | static void write_qir(volatile qspi_t *qspi, u16 val) { qspi->ir = val; } | |
37 | static void write_qar(volatile qspi_t *qspi, u16 val) { qspi->ar = val; } | |
38 | static void write_qdr(volatile qspi_t *qspi, u16 val) { qspi->dr = val; } | |
39 | /* Register read wrapper functions */ | |
40 | static u16 read_qdlyr(volatile qspi_t *qspi) { return qspi->dlyr; } | |
41 | static u16 read_qwr(volatile qspi_t *qspi) { return qspi->wr; } | |
42 | static u16 read_qir(volatile qspi_t *qspi) { return qspi->ir; } | |
43 | static u16 read_qdr(volatile qspi_t *qspi) { return qspi->dr; } | |
44 | ||
45 | /* These call points may be different for each ColdFire CPU */ | |
46 | extern void cfspi_port_conf(void); | |
47 | static void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high); | |
48 | static void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high); | |
49 | ||
50 | int spi_claim_bus(struct spi_slave *slave) | |
51 | { | |
52 | return 0; | |
53 | } | |
54 | void spi_release_bus(struct spi_slave *slave) | |
55 | { | |
56 | } | |
57 | ||
58 | __attribute__((weak)) | |
59 | void spi_init(void) | |
60 | { | |
61 | cfspi_port_conf(); | |
62 | } | |
63 | ||
64 | __attribute__((weak)) | |
65 | void spi_cs_activate(struct spi_slave *slave) | |
66 | { | |
67 | struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
68 | ||
69 | cfspi_cs_activate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV)); | |
70 | } | |
71 | ||
72 | __attribute__((weak)) | |
73 | void spi_cs_deactivate(struct spi_slave *slave) | |
74 | { | |
75 | struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
76 | ||
77 | cfspi_cs_deactivate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV)); | |
78 | } | |
79 | ||
80 | __attribute__((weak)) | |
81 | int spi_cs_is_valid(unsigned int bus, unsigned int cs) | |
82 | { | |
83 | /* Only 1 bus and 4 chipselect per controller */ | |
84 | if (bus == 0 && (cs >= 0 && cs < 4)) | |
85 | return 1; | |
86 | else | |
87 | return 0; | |
88 | } | |
89 | ||
90 | void spi_free_slave(struct spi_slave *slave) | |
91 | { | |
92 | struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
93 | ||
94 | free(dev); | |
95 | } | |
96 | ||
97 | /* Translate information given by spi_setup_slave to members of cf_qspi_slave */ | |
98 | struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, | |
99 | unsigned int max_hz, unsigned int mode) | |
100 | { | |
101 | struct cf_qspi_slave *dev = NULL; | |
102 | ||
103 | if (!spi_cs_is_valid(bus, cs)) | |
104 | return NULL; | |
105 | ||
d3504fee | 106 | dev = spi_alloc_slave(struct cf_qspi_slave, bus, cs); |
59d06122 RR |
107 | if (!dev) |
108 | return NULL; | |
109 | ||
110 | /* Initialize to known value */ | |
59d06122 RR |
111 | dev->regs = (qspi_t *)MMAP_QSPI; |
112 | dev->qmr = 0; | |
113 | dev->qwr = 0; | |
114 | dev->qcr = 0; | |
115 | ||
116 | ||
117 | /* Map max_hz to QMR[BAUD] */ | |
118 | if (max_hz == 0) /* Go as fast as possible */ | |
119 | dev->qmr = 2u; | |
120 | else /* Get the closest baud rate */ | |
121 | dev->qmr = clamp(((gd->bus_clk >> 2) + max_hz - 1)/max_hz, | |
8aa5f1d9 | 122 | 2lu, 255lu); |
59d06122 RR |
123 | |
124 | /* Map mode to QMR[CPOL] and QMR[CPHA] */ | |
125 | if (mode & SPI_CPOL) | |
126 | dev->qmr |= QSPI_QMR_CPOL; | |
127 | ||
128 | if (mode & SPI_CPHA) | |
129 | dev->qmr |= QSPI_QMR_CPHA; | |
130 | ||
131 | /* Hardcode bit length to 8 bit per transter */ | |
132 | dev->qmr |= QSPI_QMR_BITS_8; | |
133 | ||
134 | /* Set QMR[MSTR] to enable QSPI as master */ | |
135 | dev->qmr |= QSPI_QMR_MSTR; | |
136 | ||
137 | /* | |
138 | * Set QCR and QWR to default values for spi flash operation. | |
139 | * If more custom QCR and QRW are needed, overload mode variable | |
140 | */ | |
141 | dev->qcr = (QSPI_QDR_CONT | QSPI_QDR_BITSE); | |
142 | ||
143 | if (!(mode & SPI_CS_HIGH)) | |
144 | dev->qwr |= QSPI_QWR_CSIV; | |
145 | ||
146 | return &dev->slave; | |
147 | } | |
148 | ||
149 | /* Transfer 8 bit at a time */ | |
150 | int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, | |
151 | void *din, unsigned long flags) | |
152 | { | |
153 | struct cf_qspi_slave *dev = to_cf_qspi_slave(slave); | |
154 | volatile qspi_t *qspi = dev->regs; | |
155 | u8 *txbuf = (u8 *)dout; | |
156 | u8 *rxbuf = (u8 *)din; | |
0cb8394f | 157 | u32 count = DIV_ROUND_UP(bitlen, 8); |
59d06122 RR |
158 | u32 n, i = 0; |
159 | ||
160 | /* Sanitize arguments */ | |
161 | if (slave == NULL) { | |
162 | printf("%s: NULL slave ptr\n", __func__); | |
163 | return -1; | |
164 | } | |
165 | ||
166 | if (flags & SPI_XFER_BEGIN) | |
167 | spi_cs_activate(slave); | |
168 | ||
169 | /* There is something to send, lets process it. spi_xfer is also called | |
170 | * just to toggle chip select, so bitlen of 0 is valid */ | |
171 | if (count > 0) { | |
172 | /* | |
173 | * NOTE: Since chip select is driven as a bit-bang-ed GPIO | |
174 | * using spi_cs_activate() and spi_cs_deactivate(), | |
175 | * the chip select settings inside the controller | |
176 | * (i.e. QCR[CONT] and QWR[CSIV]) are moot. The bits are set to | |
177 | * keep the controller settings consistent with the actual | |
178 | * operation of the bus. | |
179 | */ | |
180 | ||
181 | /* Write the slave device's settings for the controller.*/ | |
182 | write_qmr(qspi, dev->qmr); | |
183 | write_qwr(qspi, dev->qwr); | |
184 | ||
185 | /* Limit transfer to 16 at a time */ | |
186 | n = min(count, 16u); | |
187 | do { | |
188 | /* Setup queue end point */ | |
189 | write_qwr(qspi, ((read_qwr(qspi) & QSPI_QWR_ENDQP_MASK) | |
190 | | QSPI_QWR_ENDQP((n-1)))); | |
191 | ||
192 | /* Write Command RAM */ | |
193 | write_qar(qspi, QSPI_QAR_CMD); | |
194 | for (i = 0; i < n; ++i) | |
195 | write_qdr(qspi, dev->qcr); | |
196 | ||
197 | /* Write TxBuf, if none given, fill with ZEROes */ | |
198 | write_qar(qspi, QSPI_QAR_TRANS); | |
199 | if (txbuf) { | |
200 | for (i = 0; i < n; ++i) | |
201 | write_qdr(qspi, *txbuf++); | |
202 | } else { | |
203 | for (i = 0; i < n; ++i) | |
204 | write_qdr(qspi, 0); | |
205 | } | |
206 | ||
207 | /* Clear QIR[SPIF] by writing a 1 to it */ | |
208 | write_qir(qspi, read_qir(qspi) | QSPI_QIR_SPIF); | |
209 | /* Set QDLYR[SPE] to start sending */ | |
210 | write_qdlyr(qspi, read_qdlyr(qspi) | QSPI_QDLYR_SPE); | |
211 | ||
212 | /* Poll QIR[SPIF] for transfer completion */ | |
213 | while ((read_qir(qspi) & QSPI_QIR_SPIF) != 1) | |
214 | udelay(1); | |
215 | ||
216 | /* If given read RxBuf, load data to it */ | |
217 | if (rxbuf) { | |
218 | write_qar(qspi, QSPI_QAR_RECV); | |
219 | for (i = 0; i < n; ++i) | |
220 | *rxbuf++ = read_qdr(qspi); | |
221 | } | |
222 | ||
223 | /* Decrement count */ | |
224 | count -= n; | |
225 | } while (count); | |
226 | } | |
227 | ||
228 | if (flags & SPI_XFER_END) | |
229 | spi_cs_deactivate(slave); | |
230 | ||
231 | return 0; | |
232 | } | |
233 | ||
234 | /* Each MCF CPU may have different pin assignments for chip selects. */ | |
235 | #if defined(CONFIG_M5271) | |
236 | /* Assert chip select, val = [1|0] , dir = out, mode = GPIO */ | |
237 | void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high) | |
238 | { | |
239 | debug("%s: bus %d cs %d cs_active_high %d\n", | |
240 | __func__, bus, cs, cs_active_high); | |
241 | ||
242 | switch (cs) { | |
243 | case 0: /* QSPI_CS[0] = PQSPI[3] */ | |
244 | if (cs_active_high) | |
245 | mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08); | |
246 | else | |
247 | mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7); | |
248 | ||
249 | mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
250 | mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x08); | |
251 | ||
252 | mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
253 | mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF); | |
254 | break; | |
255 | case 1: /* QSPI_CS[1] = PQSPI[4] */ | |
256 | if (cs_active_high) | |
257 | mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10); | |
258 | else | |
259 | mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF); | |
260 | ||
261 | mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
262 | mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x10); | |
263 | ||
264 | mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
265 | mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F); | |
266 | break; | |
267 | case 2: /* QSPI_CS[2] = PTIMER[7] */ | |
268 | if (cs_active_high) | |
269 | mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80); | |
270 | else | |
271 | mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F); | |
272 | ||
273 | mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
274 | mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x80); | |
275 | ||
276 | mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
277 | mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF); | |
278 | break; | |
279 | case 3: /* QSPI_CS[3] = PTIMER[3] */ | |
280 | if (cs_active_high) | |
281 | mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08); | |
282 | else | |
283 | mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7); | |
284 | ||
285 | mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
286 | mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x08); | |
287 | ||
288 | mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
289 | mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F); | |
290 | break; | |
291 | } | |
292 | } | |
293 | ||
294 | /* Deassert chip select, val = [1|0], dir = in, mode = GPIO | |
295 | * direction set as IN to undrive the pin, external pullup/pulldown will bring | |
296 | * bus to deassert state. | |
297 | */ | |
298 | void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high) | |
299 | { | |
300 | debug("%s: bus %d cs %d cs_active_high %d\n", | |
301 | __func__, bus, cs, cs_active_high); | |
302 | ||
303 | switch (cs) { | |
304 | case 0: /* QSPI_CS[0] = PQSPI[3] */ | |
305 | if (cs_active_high) | |
306 | mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7); | |
307 | else | |
308 | mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08); | |
309 | ||
310 | mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
311 | mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xF7); | |
312 | ||
313 | mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
314 | mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF); | |
315 | break; | |
316 | case 1: /* QSPI_CS[1] = PQSPI[4] */ | |
317 | if (cs_active_high) | |
318 | mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF); | |
319 | else | |
320 | mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10); | |
321 | ||
322 | mbar_writeByte(MCF_GPIO_PDDR_QSPI, | |
323 | mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xEF); | |
324 | ||
325 | mbar_writeByte(MCF_GPIO_PAR_QSPI, | |
326 | mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F); | |
327 | break; | |
328 | case 2: /* QSPI_CS[2] = PTIMER[7] */ | |
329 | if (cs_active_high) | |
330 | mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F); | |
331 | else | |
332 | mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80); | |
333 | ||
334 | mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
335 | mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0x7F); | |
336 | ||
337 | mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
338 | mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF); | |
339 | break; | |
340 | case 3: /* QSPI_CS[3] = PTIMER[3] */ | |
341 | if (cs_active_high) | |
342 | mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7); | |
343 | else | |
344 | mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08); | |
345 | ||
346 | mbar_writeByte(MCF_GPIO_PDDR_TIMER, | |
347 | mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0xF7); | |
348 | ||
349 | mbar_writeShort(MCF_GPIO_PAR_TIMER, | |
350 | mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F); | |
351 | break; | |
352 | } | |
353 | } | |
354 | #endif /* CONFIG_M5271 */ |