]>
Commit | Line | Data |
---|---|---|
09aac75e SL |
1 | /* |
2 | * Xilinx SPI driver | |
3 | * | |
4 | * supports 8 bit SPI transfers only, with or w/o FIFO | |
5 | * | |
6 | * based on bfin_spi.c, by way of altera_spi.c | |
7 | * Copyright (c) 2005-2008 Analog Devices Inc. | |
8 | * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw> | |
9 | * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca> | |
10 | * Copyright (c) 2012 Stephan Linz <linz@li-pro.net> | |
11 | * | |
e7b1e452 | 12 | * SPDX-License-Identifier: GPL-2.0+ |
09aac75e SL |
13 | * |
14 | * [0]: http://www.xilinx.com/support/documentation | |
15 | * | |
16 | * [S]: [0]/ip_documentation/xps_spi.pdf | |
17 | * [0]/ip_documentation/axi_spi_ds742.pdf | |
18 | */ | |
19 | #include <config.h> | |
20 | #include <common.h> | |
21 | #include <malloc.h> | |
22 | #include <spi.h> | |
23 | ||
f93542a8 JT |
24 | /* |
25 | * Xilinx SPI Register Definition | |
26 | * | |
27 | * [1]: [0]/ip_documentation/xps_spi.pdf | |
28 | * page 8, Register Descriptions | |
29 | * [2]: [0]/ip_documentation/axi_spi_ds742.pdf | |
30 | * page 7, Register Overview Table | |
31 | */ | |
32 | struct xilinx_spi_reg { | |
33 | u32 __space0__[7]; | |
34 | u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */ | |
35 | u32 ipisr; /* IP Interrupt Status Register (IPISR) */ | |
36 | u32 __space1__; | |
37 | u32 ipier; /* IP Interrupt Enable Register (IPIER) */ | |
38 | u32 __space2__[5]; | |
39 | u32 srr; /* Softare Reset Register (SRR) */ | |
40 | u32 __space3__[7]; | |
41 | u32 spicr; /* SPI Control Register (SPICR) */ | |
42 | u32 spisr; /* SPI Status Register (SPISR) */ | |
43 | u32 spidtr; /* SPI Data Transmit Register (SPIDTR) */ | |
44 | u32 spidrr; /* SPI Data Receive Register (SPIDRR) */ | |
45 | u32 spissr; /* SPI Slave Select Register (SPISSR) */ | |
46 | u32 spitfor; /* SPI Transmit FIFO Occupancy Register (SPITFOR) */ | |
47 | u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */ | |
48 | }; | |
49 | ||
50 | /* Device Global Interrupt Enable Register (dgier), [1] p15, [2] p15 */ | |
51 | #define DGIER_GIE (1 << 31) | |
52 | ||
53 | /* IP Interrupt Status Register (ipisr), [1] p15, [2] p15 */ | |
54 | #define IPISR_DRR_NOT_EMPTY (1 << 8) | |
55 | #define IPISR_SLAVE_SELECT (1 << 7) | |
56 | #define IPISR_TXF_HALF_EMPTY (1 << 6) | |
57 | #define IPISR_DRR_OVERRUN (1 << 5) | |
58 | #define IPISR_DRR_FULL (1 << 4) | |
59 | #define IPISR_DTR_UNDERRUN (1 << 3) | |
60 | #define IPISR_DTR_EMPTY (1 << 2) | |
61 | #define IPISR_SLAVE_MODF (1 << 1) | |
62 | #define IPISR_MODF (1 << 0) | |
63 | ||
64 | /* IP Interrupt Enable Register (ipier), [1] p17, [2] p18 */ | |
65 | #define IPIER_DRR_NOT_EMPTY (1 << 8) | |
66 | #define IPIER_SLAVE_SELECT (1 << 7) | |
67 | #define IPIER_TXF_HALF_EMPTY (1 << 6) | |
68 | #define IPIER_DRR_OVERRUN (1 << 5) | |
69 | #define IPIER_DRR_FULL (1 << 4) | |
70 | #define IPIER_DTR_UNDERRUN (1 << 3) | |
71 | #define IPIER_DTR_EMPTY (1 << 2) | |
72 | #define IPIER_SLAVE_MODF (1 << 1) | |
73 | #define IPIER_MODF (1 << 0) | |
74 | ||
75 | /* Softare Reset Register (srr), [1] p9, [2] p8 */ | |
76 | #define SRR_RESET_CODE 0x0000000A | |
77 | ||
78 | /* SPI Control Register (spicr), [1] p9, [2] p8 */ | |
79 | #define SPICR_LSB_FIRST (1 << 9) | |
80 | #define SPICR_MASTER_INHIBIT (1 << 8) | |
81 | #define SPICR_MANUAL_SS (1 << 7) | |
82 | #define SPICR_RXFIFO_RESEST (1 << 6) | |
83 | #define SPICR_TXFIFO_RESEST (1 << 5) | |
84 | #define SPICR_CPHA (1 << 4) | |
85 | #define SPICR_CPOL (1 << 3) | |
86 | #define SPICR_MASTER_MODE (1 << 2) | |
87 | #define SPICR_SPE (1 << 1) | |
88 | #define SPICR_LOOP (1 << 0) | |
89 | ||
90 | /* SPI Status Register (spisr), [1] p11, [2] p10 */ | |
91 | #define SPISR_SLAVE_MODE_SELECT (1 << 5) | |
92 | #define SPISR_MODF (1 << 4) | |
93 | #define SPISR_TX_FULL (1 << 3) | |
94 | #define SPISR_TX_EMPTY (1 << 2) | |
95 | #define SPISR_RX_FULL (1 << 1) | |
96 | #define SPISR_RX_EMPTY (1 << 0) | |
97 | ||
98 | /* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */ | |
99 | #define SPIDTR_8BIT_MASK (0xff << 0) | |
100 | #define SPIDTR_16BIT_MASK (0xffff << 0) | |
101 | #define SPIDTR_32BIT_MASK (0xffffffff << 0) | |
102 | ||
103 | /* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */ | |
104 | #define SPIDRR_8BIT_MASK (0xff << 0) | |
105 | #define SPIDRR_16BIT_MASK (0xffff << 0) | |
106 | #define SPIDRR_32BIT_MASK (0xffffffff << 0) | |
107 | ||
108 | /* SPI Slave Select Register (spissr), [1] p13, [2] p13 */ | |
109 | #define SPISSR_MASK(cs) (1 << (cs)) | |
110 | #define SPISSR_ACT(cs) ~SPISSR_MASK(cs) | |
111 | #define SPISSR_OFF ~0UL | |
112 | ||
113 | /* SPI Transmit FIFO Occupancy Register (spitfor), [1] p13, [2] p14 */ | |
114 | #define SPITFOR_OCYVAL_POS 0 | |
115 | #define SPITFOR_OCYVAL_MASK (0xf << SPITFOR_OCYVAL_POS) | |
116 | ||
117 | /* SPI Receive FIFO Occupancy Register (spirfor), [1] p14, [2] p14 */ | |
118 | #define SPIRFOR_OCYVAL_POS 0 | |
119 | #define SPIRFOR_OCYVAL_MASK (0xf << SPIRFOR_OCYVAL_POS) | |
120 | ||
121 | /* SPI Software Reset Register (ssr) */ | |
122 | #define SPISSR_RESET_VALUE 0x0a | |
123 | ||
124 | struct xilinx_spi_slave { | |
125 | struct spi_slave slave; | |
126 | struct xilinx_spi_reg *regs; | |
127 | unsigned int freq; | |
128 | unsigned int mode; | |
129 | }; | |
130 | ||
131 | static inline struct xilinx_spi_slave *to_xilinx_spi_slave( | |
132 | struct spi_slave *slave) | |
133 | { | |
134 | return container_of(slave, struct xilinx_spi_slave, slave); | |
135 | } | |
09aac75e SL |
136 | |
137 | #ifndef CONFIG_SYS_XILINX_SPI_LIST | |
138 | #define CONFIG_SYS_XILINX_SPI_LIST { CONFIG_SYS_SPI_BASE } | |
139 | #endif | |
140 | ||
141 | #ifndef CONFIG_XILINX_SPI_IDLE_VAL | |
142 | #define CONFIG_XILINX_SPI_IDLE_VAL 0xff | |
143 | #endif | |
144 | ||
145 | #define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | \ | |
146 | SPICR_MASTER_MODE | \ | |
147 | SPICR_SPE) | |
148 | ||
149 | #define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | \ | |
150 | SPICR_MANUAL_SS) | |
151 | ||
152 | #define XILSPI_MAX_XFER_BITS 8 | |
153 | ||
154 | static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST; | |
155 | ||
156 | __attribute__((weak)) | |
157 | int spi_cs_is_valid(unsigned int bus, unsigned int cs) | |
158 | { | |
159 | return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32; | |
160 | } | |
161 | ||
162 | __attribute__((weak)) | |
163 | void spi_cs_activate(struct spi_slave *slave) | |
164 | { | |
165 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
166 | ||
167 | writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr); | |
168 | } | |
169 | ||
170 | __attribute__((weak)) | |
171 | void spi_cs_deactivate(struct spi_slave *slave) | |
172 | { | |
173 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
174 | ||
175 | writel(SPISSR_OFF, &xilspi->regs->spissr); | |
176 | } | |
177 | ||
178 | void spi_init(void) | |
179 | { | |
180 | /* do nothing */ | |
181 | } | |
182 | ||
183 | void spi_set_speed(struct spi_slave *slave, uint hz) | |
184 | { | |
185 | /* xilinx spi core does not support programmable speed */ | |
186 | } | |
187 | ||
188 | struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, | |
189 | unsigned int max_hz, unsigned int mode) | |
190 | { | |
191 | struct xilinx_spi_slave *xilspi; | |
09aac75e SL |
192 | |
193 | if (!spi_cs_is_valid(bus, cs)) { | |
194 | printf("XILSPI error: %s: unsupported bus %d / cs %d\n", | |
195 | __func__, bus, cs); | |
196 | return NULL; | |
197 | } | |
198 | ||
d3504fee | 199 | xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs); |
09aac75e SL |
200 | if (!xilspi) { |
201 | printf("XILSPI error: %s: malloc of SPI structure failed\n", | |
202 | __func__); | |
203 | return NULL; | |
204 | } | |
09aac75e SL |
205 | xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus]; |
206 | xilspi->freq = max_hz; | |
207 | xilspi->mode = mode; | |
208 | debug("%s: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", __func__, | |
209 | bus, cs, xilspi->regs, xilspi->mode, xilspi->freq); | |
210 | ||
85e9c65f JW |
211 | writel(SPISSR_RESET_VALUE, &xilspi->regs->srr); |
212 | ||
09aac75e SL |
213 | return &xilspi->slave; |
214 | } | |
215 | ||
216 | void spi_free_slave(struct spi_slave *slave) | |
217 | { | |
218 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
219 | ||
220 | free(xilspi); | |
221 | } | |
222 | ||
223 | int spi_claim_bus(struct spi_slave *slave) | |
224 | { | |
225 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
226 | u32 spicr; | |
227 | ||
228 | debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); | |
229 | writel(SPISSR_OFF, &xilspi->regs->spissr); | |
230 | ||
231 | spicr = XILSPI_SPICR_DFLT_ON; | |
232 | if (xilspi->mode & SPI_LSB_FIRST) | |
233 | spicr |= SPICR_LSB_FIRST; | |
234 | if (xilspi->mode & SPI_CPHA) | |
235 | spicr |= SPICR_CPHA; | |
236 | if (xilspi->mode & SPI_CPOL) | |
237 | spicr |= SPICR_CPOL; | |
238 | if (xilspi->mode & SPI_LOOP) | |
239 | spicr |= SPICR_LOOP; | |
240 | ||
241 | writel(spicr, &xilspi->regs->spicr); | |
242 | return 0; | |
243 | } | |
244 | ||
245 | void spi_release_bus(struct spi_slave *slave) | |
246 | { | |
247 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
248 | ||
249 | debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); | |
250 | writel(SPISSR_OFF, &xilspi->regs->spissr); | |
251 | writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr); | |
252 | } | |
253 | ||
254 | int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, | |
255 | void *din, unsigned long flags) | |
256 | { | |
257 | struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); | |
258 | /* assume spi core configured to do 8 bit transfers */ | |
259 | unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS; | |
260 | const unsigned char *txp = dout; | |
261 | unsigned char *rxp = din; | |
262 | unsigned rxecount = 17; /* max. 16 elements in FIFO, leftover 1 */ | |
999c39a4 | 263 | unsigned global_timeout; |
09aac75e SL |
264 | |
265 | debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__, | |
266 | slave->bus, slave->cs, bitlen, bytes, flags); | |
267 | if (bitlen == 0) | |
268 | goto done; | |
269 | ||
270 | if (bitlen % XILSPI_MAX_XFER_BITS) { | |
271 | printf("XILSPI warning: %s: Not a multiple of %d bits\n", | |
272 | __func__, XILSPI_MAX_XFER_BITS); | |
273 | flags |= SPI_XFER_END; | |
274 | goto done; | |
275 | } | |
276 | ||
277 | /* empty read buffer */ | |
278 | while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) { | |
279 | readl(&xilspi->regs->spidrr); | |
280 | rxecount--; | |
281 | } | |
282 | ||
283 | if (!rxecount) { | |
284 | printf("XILSPI error: %s: Rx buffer not empty\n", __func__); | |
285 | return -1; | |
286 | } | |
287 | ||
288 | if (flags & SPI_XFER_BEGIN) | |
289 | spi_cs_activate(slave); | |
290 | ||
999c39a4 MS |
291 | /* at least 1usec or greater, leftover 1 */ |
292 | global_timeout = xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 : | |
09aac75e SL |
293 | (XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1; |
294 | ||
999c39a4 MS |
295 | while (bytes--) { |
296 | unsigned timeout = global_timeout; | |
09aac75e SL |
297 | /* get Tx element from data out buffer and count up */ |
298 | unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL; | |
299 | debug("%s: tx:%x ", __func__, d); | |
300 | ||
301 | /* write out and wait for processing (receive data) */ | |
302 | writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr); | |
303 | while (timeout && readl(&xilspi->regs->spisr) | |
304 | & SPISR_RX_EMPTY) { | |
305 | timeout--; | |
306 | udelay(1); | |
307 | } | |
308 | ||
309 | if (!timeout) { | |
310 | printf("XILSPI error: %s: Xfer timeout\n", __func__); | |
311 | return -1; | |
312 | } | |
313 | ||
314 | /* read Rx element and push into data in buffer */ | |
315 | d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK; | |
316 | if (rxp) | |
317 | *rxp++ = d; | |
318 | debug("rx:%x\n", d); | |
319 | } | |
320 | ||
321 | done: | |
322 | if (flags & SPI_XFER_END) | |
323 | spi_cs_deactivate(slave); | |
324 | ||
325 | return 0; | |
326 | } |