diff options
Diffstat (limited to 'drivers/spi/spi-bfin-v3.c')
-rw-r--r-- | drivers/spi/spi-bfin-v3.c | 965 |
1 files changed, 965 insertions, 0 deletions
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c new file mode 100644 index 000000000000..e4394ebf08f3 --- /dev/null +++ b/drivers/spi/spi-bfin-v3.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * Analog Devices SPI3 controller driver | ||
3 | * | ||
4 | * Copyright (c) 2013 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | #include <linux/types.h> | ||
30 | |||
31 | #include <asm/bfin_spi3.h> | ||
32 | #include <asm/cacheflush.h> | ||
33 | #include <asm/dma.h> | ||
34 | #include <asm/portmux.h> | ||
35 | |||
36 | enum bfin_spi_state { | ||
37 | START_STATE, | ||
38 | RUNNING_STATE, | ||
39 | DONE_STATE, | ||
40 | ERROR_STATE | ||
41 | }; | ||
42 | |||
43 | struct bfin_spi_master; | ||
44 | |||
45 | struct bfin_spi_transfer_ops { | ||
46 | void (*write) (struct bfin_spi_master *); | ||
47 | void (*read) (struct bfin_spi_master *); | ||
48 | void (*duplex) (struct bfin_spi_master *); | ||
49 | }; | ||
50 | |||
51 | /* runtime info for spi master */ | ||
52 | struct bfin_spi_master { | ||
53 | /* SPI framework hookup */ | ||
54 | struct spi_master *master; | ||
55 | |||
56 | /* Regs base of SPI controller */ | ||
57 | struct bfin_spi_regs __iomem *regs; | ||
58 | |||
59 | /* Pin request list */ | ||
60 | u16 *pin_req; | ||
61 | |||
62 | /* Message Transfer pump */ | ||
63 | struct tasklet_struct pump_transfers; | ||
64 | |||
65 | /* Current message transfer state info */ | ||
66 | struct spi_message *cur_msg; | ||
67 | struct spi_transfer *cur_transfer; | ||
68 | struct bfin_spi_device *cur_chip; | ||
69 | unsigned transfer_len; | ||
70 | |||
71 | /* transfer buffer */ | ||
72 | void *tx; | ||
73 | void *tx_end; | ||
74 | void *rx; | ||
75 | void *rx_end; | ||
76 | |||
77 | /* dma info */ | ||
78 | unsigned int tx_dma; | ||
79 | unsigned int rx_dma; | ||
80 | dma_addr_t tx_dma_addr; | ||
81 | dma_addr_t rx_dma_addr; | ||
82 | unsigned long dummy_buffer; /* used in unidirectional transfer */ | ||
83 | unsigned long tx_dma_size; | ||
84 | unsigned long rx_dma_size; | ||
85 | int tx_num; | ||
86 | int rx_num; | ||
87 | |||
88 | /* store register value for suspend/resume */ | ||
89 | u32 control; | ||
90 | u32 ssel; | ||
91 | |||
92 | unsigned long sclk; | ||
93 | enum bfin_spi_state state; | ||
94 | |||
95 | const struct bfin_spi_transfer_ops *ops; | ||
96 | }; | ||
97 | |||
98 | struct bfin_spi_device { | ||
99 | u32 control; | ||
100 | u32 clock; | ||
101 | u32 ssel; | ||
102 | |||
103 | u8 cs; | ||
104 | u16 cs_chg_udelay; /* Some devices require > 255usec delay */ | ||
105 | u32 cs_gpio; | ||
106 | u32 tx_dummy_val; /* tx value for rx only transfer */ | ||
107 | bool enable_dma; | ||
108 | const struct bfin_spi_transfer_ops *ops; | ||
109 | }; | ||
110 | |||
111 | static void bfin_spi_enable(struct bfin_spi_master *drv_data) | ||
112 | { | ||
113 | bfin_write_or(&drv_data->regs->control, SPI_CTL_EN); | ||
114 | } | ||
115 | |||
116 | static void bfin_spi_disable(struct bfin_spi_master *drv_data) | ||
117 | { | ||
118 | bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); | ||
119 | } | ||
120 | |||
121 | /* Caculate the SPI_CLOCK register value based on input HZ */ | ||
122 | static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz) | ||
123 | { | ||
124 | u32 spi_clock = sclk / speed_hz; | ||
125 | |||
126 | if (spi_clock) | ||
127 | spi_clock--; | ||
128 | return spi_clock; | ||
129 | } | ||
130 | |||
131 | static int bfin_spi_flush(struct bfin_spi_master *drv_data) | ||
132 | { | ||
133 | unsigned long limit = loops_per_jiffy << 1; | ||
134 | |||
135 | /* wait for stop and clear stat */ | ||
136 | while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit) | ||
137 | cpu_relax(); | ||
138 | |||
139 | bfin_write(&drv_data->regs->status, 0xFFFFFFFF); | ||
140 | |||
141 | return limit; | ||
142 | } | ||
143 | |||
144 | /* Chip select operation functions for cs_change flag */ | ||
145 | static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip) | ||
146 | { | ||
147 | if (likely(chip->cs < MAX_CTRL_CS)) | ||
148 | bfin_write_and(&drv_data->regs->ssel, ~chip->ssel); | ||
149 | else | ||
150 | gpio_set_value(chip->cs_gpio, 0); | ||
151 | } | ||
152 | |||
153 | static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data, | ||
154 | struct bfin_spi_device *chip) | ||
155 | { | ||
156 | if (likely(chip->cs < MAX_CTRL_CS)) | ||
157 | bfin_write_or(&drv_data->regs->ssel, chip->ssel); | ||
158 | else | ||
159 | gpio_set_value(chip->cs_gpio, 1); | ||
160 | |||
161 | /* Move delay here for consistency */ | ||
162 | if (chip->cs_chg_udelay) | ||
163 | udelay(chip->cs_chg_udelay); | ||
164 | } | ||
165 | |||
166 | /* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ | ||
167 | static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data, | ||
168 | struct bfin_spi_device *chip) | ||
169 | { | ||
170 | if (chip->cs < MAX_CTRL_CS) | ||
171 | bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8); | ||
172 | } | ||
173 | |||
174 | static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data, | ||
175 | struct bfin_spi_device *chip) | ||
176 | { | ||
177 | if (chip->cs < MAX_CTRL_CS) | ||
178 | bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8)); | ||
179 | } | ||
180 | |||
181 | /* stop controller and re-config current chip*/ | ||
182 | static void bfin_spi_restore_state(struct bfin_spi_master *drv_data) | ||
183 | { | ||
184 | struct bfin_spi_device *chip = drv_data->cur_chip; | ||
185 | |||
186 | /* Clear status and disable clock */ | ||
187 | bfin_write(&drv_data->regs->status, 0xFFFFFFFF); | ||
188 | bfin_write(&drv_data->regs->rx_control, 0x0); | ||
189 | bfin_write(&drv_data->regs->tx_control, 0x0); | ||
190 | bfin_spi_disable(drv_data); | ||
191 | |||
192 | SSYNC(); | ||
193 | |||
194 | /* Load the registers */ | ||
195 | bfin_write(&drv_data->regs->control, chip->control); | ||
196 | bfin_write(&drv_data->regs->clock, chip->clock); | ||
197 | |||
198 | bfin_spi_enable(drv_data); | ||
199 | drv_data->tx_num = drv_data->rx_num = 0; | ||
200 | /* we always choose tx transfer initiate */ | ||
201 | bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN); | ||
202 | bfin_write(&drv_data->regs->tx_control, | ||
203 | SPI_TXCTL_TEN | SPI_TXCTL_TTI); | ||
204 | bfin_spi_cs_active(drv_data, chip); | ||
205 | } | ||
206 | |||
207 | /* discard invalid rx data and empty rfifo */ | ||
208 | static inline void dummy_read(struct bfin_spi_master *drv_data) | ||
209 | { | ||
210 | while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)) | ||
211 | bfin_read(&drv_data->regs->rfifo); | ||
212 | } | ||
213 | |||
214 | static void bfin_spi_u8_write(struct bfin_spi_master *drv_data) | ||
215 | { | ||
216 | dummy_read(drv_data); | ||
217 | while (drv_data->tx < drv_data->tx_end) { | ||
218 | bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); | ||
219 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
220 | cpu_relax(); | ||
221 | bfin_read(&drv_data->regs->rfifo); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void bfin_spi_u8_read(struct bfin_spi_master *drv_data) | ||
226 | { | ||
227 | u32 tx_val = drv_data->cur_chip->tx_dummy_val; | ||
228 | |||
229 | dummy_read(drv_data); | ||
230 | while (drv_data->rx < drv_data->rx_end) { | ||
231 | bfin_write(&drv_data->regs->tfifo, tx_val); | ||
232 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
233 | cpu_relax(); | ||
234 | *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data) | ||
239 | { | ||
240 | dummy_read(drv_data); | ||
241 | while (drv_data->rx < drv_data->rx_end) { | ||
242 | bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); | ||
243 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
244 | cpu_relax(); | ||
245 | *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { | ||
250 | .write = bfin_spi_u8_write, | ||
251 | .read = bfin_spi_u8_read, | ||
252 | .duplex = bfin_spi_u8_duplex, | ||
253 | }; | ||
254 | |||
255 | static void bfin_spi_u16_write(struct bfin_spi_master *drv_data) | ||
256 | { | ||
257 | dummy_read(drv_data); | ||
258 | while (drv_data->tx < drv_data->tx_end) { | ||
259 | bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); | ||
260 | drv_data->tx += 2; | ||
261 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
262 | cpu_relax(); | ||
263 | bfin_read(&drv_data->regs->rfifo); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void bfin_spi_u16_read(struct bfin_spi_master *drv_data) | ||
268 | { | ||
269 | u32 tx_val = drv_data->cur_chip->tx_dummy_val; | ||
270 | |||
271 | dummy_read(drv_data); | ||
272 | while (drv_data->rx < drv_data->rx_end) { | ||
273 | bfin_write(&drv_data->regs->tfifo, tx_val); | ||
274 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
275 | cpu_relax(); | ||
276 | *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); | ||
277 | drv_data->rx += 2; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data) | ||
282 | { | ||
283 | dummy_read(drv_data); | ||
284 | while (drv_data->rx < drv_data->rx_end) { | ||
285 | bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); | ||
286 | drv_data->tx += 2; | ||
287 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
288 | cpu_relax(); | ||
289 | *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); | ||
290 | drv_data->rx += 2; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { | ||
295 | .write = bfin_spi_u16_write, | ||
296 | .read = bfin_spi_u16_read, | ||
297 | .duplex = bfin_spi_u16_duplex, | ||
298 | }; | ||
299 | |||
300 | static void bfin_spi_u32_write(struct bfin_spi_master *drv_data) | ||
301 | { | ||
302 | dummy_read(drv_data); | ||
303 | while (drv_data->tx < drv_data->tx_end) { | ||
304 | bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); | ||
305 | drv_data->tx += 4; | ||
306 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
307 | cpu_relax(); | ||
308 | bfin_read(&drv_data->regs->rfifo); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static void bfin_spi_u32_read(struct bfin_spi_master *drv_data) | ||
313 | { | ||
314 | u32 tx_val = drv_data->cur_chip->tx_dummy_val; | ||
315 | |||
316 | dummy_read(drv_data); | ||
317 | while (drv_data->rx < drv_data->rx_end) { | ||
318 | bfin_write(&drv_data->regs->tfifo, tx_val); | ||
319 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
320 | cpu_relax(); | ||
321 | *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); | ||
322 | drv_data->rx += 4; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data) | ||
327 | { | ||
328 | dummy_read(drv_data); | ||
329 | while (drv_data->rx < drv_data->rx_end) { | ||
330 | bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); | ||
331 | drv_data->tx += 4; | ||
332 | while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) | ||
333 | cpu_relax(); | ||
334 | *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); | ||
335 | drv_data->rx += 4; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { | ||
340 | .write = bfin_spi_u32_write, | ||
341 | .read = bfin_spi_u32_read, | ||
342 | .duplex = bfin_spi_u32_duplex, | ||
343 | }; | ||
344 | |||
345 | |||
346 | /* test if there is more transfer to be done */ | ||
347 | static void bfin_spi_next_transfer(struct bfin_spi_master *drv) | ||
348 | { | ||
349 | struct spi_message *msg = drv->cur_msg; | ||
350 | struct spi_transfer *t = drv->cur_transfer; | ||
351 | |||
352 | /* Move to next transfer */ | ||
353 | if (t->transfer_list.next != &msg->transfers) { | ||
354 | drv->cur_transfer = list_entry(t->transfer_list.next, | ||
355 | struct spi_transfer, transfer_list); | ||
356 | drv->state = RUNNING_STATE; | ||
357 | } else { | ||
358 | drv->state = DONE_STATE; | ||
359 | drv->cur_transfer = NULL; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static void bfin_spi_giveback(struct bfin_spi_master *drv_data) | ||
364 | { | ||
365 | struct bfin_spi_device *chip = drv_data->cur_chip; | ||
366 | |||
367 | bfin_spi_cs_deactive(drv_data, chip); | ||
368 | spi_finalize_current_message(drv_data->master); | ||
369 | } | ||
370 | |||
371 | static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) | ||
372 | { | ||
373 | struct spi_transfer *t = drv->cur_transfer; | ||
374 | u32 cr, cr_width; | ||
375 | |||
376 | if (t->tx_buf) { | ||
377 | drv->tx = (void *)t->tx_buf; | ||
378 | drv->tx_end = drv->tx + t->len; | ||
379 | } else { | ||
380 | drv->tx = NULL; | ||
381 | } | ||
382 | |||
383 | if (t->rx_buf) { | ||
384 | drv->rx = t->rx_buf; | ||
385 | drv->rx_end = drv->rx + t->len; | ||
386 | } else { | ||
387 | drv->rx = NULL; | ||
388 | } | ||
389 | |||
390 | drv->transfer_len = t->len; | ||
391 | |||
392 | /* bits per word setup */ | ||
393 | switch (t->bits_per_word) { | ||
394 | case 8: | ||
395 | cr_width = SPI_CTL_SIZE08; | ||
396 | drv->ops = &bfin_bfin_spi_transfer_ops_u8; | ||
397 | break; | ||
398 | case 16: | ||
399 | cr_width = SPI_CTL_SIZE16; | ||
400 | drv->ops = &bfin_bfin_spi_transfer_ops_u16; | ||
401 | break; | ||
402 | case 32: | ||
403 | cr_width = SPI_CTL_SIZE32; | ||
404 | drv->ops = &bfin_bfin_spi_transfer_ops_u32; | ||
405 | break; | ||
406 | default: | ||
407 | return -EINVAL; | ||
408 | } | ||
409 | cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE; | ||
410 | cr |= cr_width; | ||
411 | bfin_write(&drv->regs->control, cr); | ||
412 | |||
413 | /* speed setup */ | ||
414 | bfin_write(&drv->regs->clock, | ||
415 | hz_to_spi_clock(drv->sclk, t->speed_hz)); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) | ||
420 | { | ||
421 | struct spi_transfer *t = drv_data->cur_transfer; | ||
422 | struct spi_message *msg = drv_data->cur_msg; | ||
423 | struct bfin_spi_device *chip = drv_data->cur_chip; | ||
424 | u32 dma_config; | ||
425 | unsigned long word_count, word_size; | ||
426 | void *tx_buf, *rx_buf; | ||
427 | |||
428 | switch (t->bits_per_word) { | ||
429 | case 8: | ||
430 | dma_config = WDSIZE_8 | PSIZE_8; | ||
431 | word_count = drv_data->transfer_len; | ||
432 | word_size = 1; | ||
433 | break; | ||
434 | case 16: | ||
435 | dma_config = WDSIZE_16 | PSIZE_16; | ||
436 | word_count = drv_data->transfer_len / 2; | ||
437 | word_size = 2; | ||
438 | break; | ||
439 | default: | ||
440 | dma_config = WDSIZE_32 | PSIZE_32; | ||
441 | word_count = drv_data->transfer_len / 4; | ||
442 | word_size = 4; | ||
443 | break; | ||
444 | } | ||
445 | |||
446 | if (!drv_data->rx) { | ||
447 | tx_buf = drv_data->tx; | ||
448 | rx_buf = &drv_data->dummy_buffer; | ||
449 | drv_data->tx_dma_size = drv_data->transfer_len; | ||
450 | drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer); | ||
451 | set_dma_x_modify(drv_data->tx_dma, word_size); | ||
452 | set_dma_x_modify(drv_data->rx_dma, 0); | ||
453 | } else if (!drv_data->tx) { | ||
454 | drv_data->dummy_buffer = chip->tx_dummy_val; | ||
455 | tx_buf = &drv_data->dummy_buffer; | ||
456 | rx_buf = drv_data->rx; | ||
457 | drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer); | ||
458 | drv_data->rx_dma_size = drv_data->transfer_len; | ||
459 | set_dma_x_modify(drv_data->tx_dma, 0); | ||
460 | set_dma_x_modify(drv_data->rx_dma, word_size); | ||
461 | } else { | ||
462 | tx_buf = drv_data->tx; | ||
463 | rx_buf = drv_data->rx; | ||
464 | drv_data->tx_dma_size = drv_data->rx_dma_size | ||
465 | = drv_data->transfer_len; | ||
466 | set_dma_x_modify(drv_data->tx_dma, word_size); | ||
467 | set_dma_x_modify(drv_data->rx_dma, word_size); | ||
468 | } | ||
469 | |||
470 | drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev, | ||
471 | (void *)tx_buf, | ||
472 | drv_data->tx_dma_size, | ||
473 | DMA_TO_DEVICE); | ||
474 | if (dma_mapping_error(&msg->spi->dev, | ||
475 | drv_data->tx_dma_addr)) | ||
476 | return -ENOMEM; | ||
477 | |||
478 | drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev, | ||
479 | (void *)rx_buf, | ||
480 | drv_data->rx_dma_size, | ||
481 | DMA_FROM_DEVICE); | ||
482 | if (dma_mapping_error(&msg->spi->dev, | ||
483 | drv_data->rx_dma_addr)) { | ||
484 | dma_unmap_single(&msg->spi->dev, | ||
485 | drv_data->tx_dma_addr, | ||
486 | drv_data->tx_dma_size, | ||
487 | DMA_TO_DEVICE); | ||
488 | return -ENOMEM; | ||
489 | } | ||
490 | |||
491 | dummy_read(drv_data); | ||
492 | set_dma_x_count(drv_data->tx_dma, word_count); | ||
493 | set_dma_x_count(drv_data->rx_dma, word_count); | ||
494 | set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr); | ||
495 | set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr); | ||
496 | dma_config |= DMAFLOW_STOP | RESTART | DI_EN; | ||
497 | set_dma_config(drv_data->tx_dma, dma_config); | ||
498 | set_dma_config(drv_data->rx_dma, dma_config | WNR); | ||
499 | enable_dma(drv_data->tx_dma); | ||
500 | enable_dma(drv_data->rx_dma); | ||
501 | SSYNC(); | ||
502 | |||
503 | bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); | ||
504 | SSYNC(); | ||
505 | bfin_write(&drv_data->regs->tx_control, | ||
506 | SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) | ||
512 | { | ||
513 | struct spi_message *msg = drv_data->cur_msg; | ||
514 | |||
515 | if (!drv_data->rx) { | ||
516 | /* write only half duplex */ | ||
517 | drv_data->ops->write(drv_data); | ||
518 | if (drv_data->tx != drv_data->tx_end) | ||
519 | return -EIO; | ||
520 | } else if (!drv_data->tx) { | ||
521 | /* read only half duplex */ | ||
522 | drv_data->ops->read(drv_data); | ||
523 | if (drv_data->rx != drv_data->rx_end) | ||
524 | return -EIO; | ||
525 | } else { | ||
526 | /* full duplex mode */ | ||
527 | drv_data->ops->duplex(drv_data); | ||
528 | if (drv_data->tx != drv_data->tx_end) | ||
529 | return -EIO; | ||
530 | } | ||
531 | |||
532 | if (!bfin_spi_flush(drv_data)) | ||
533 | return -EIO; | ||
534 | msg->actual_length += drv_data->transfer_len; | ||
535 | tasklet_schedule(&drv_data->pump_transfers); | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static void bfin_spi_pump_transfers(unsigned long data) | ||
540 | { | ||
541 | struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; | ||
542 | struct spi_message *msg = NULL; | ||
543 | struct spi_transfer *t = NULL; | ||
544 | struct bfin_spi_device *chip = NULL; | ||
545 | int ret; | ||
546 | |||
547 | /* Get current state information */ | ||
548 | msg = drv_data->cur_msg; | ||
549 | t = drv_data->cur_transfer; | ||
550 | chip = drv_data->cur_chip; | ||
551 | |||
552 | /* Handle for abort */ | ||
553 | if (drv_data->state == ERROR_STATE) { | ||
554 | msg->status = -EIO; | ||
555 | bfin_spi_giveback(drv_data); | ||
556 | return; | ||
557 | } | ||
558 | |||
559 | if (drv_data->state == RUNNING_STATE) { | ||
560 | if (t->delay_usecs) | ||
561 | udelay(t->delay_usecs); | ||
562 | if (t->cs_change) | ||
563 | bfin_spi_cs_deactive(drv_data, chip); | ||
564 | bfin_spi_next_transfer(drv_data); | ||
565 | t = drv_data->cur_transfer; | ||
566 | } | ||
567 | /* Handle end of message */ | ||
568 | if (drv_data->state == DONE_STATE) { | ||
569 | msg->status = 0; | ||
570 | bfin_spi_giveback(drv_data); | ||
571 | return; | ||
572 | } | ||
573 | |||
574 | if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) { | ||
575 | /* Schedule next transfer tasklet */ | ||
576 | tasklet_schedule(&drv_data->pump_transfers); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | ret = bfin_spi_setup_transfer(drv_data); | ||
581 | if (ret) { | ||
582 | msg->status = ret; | ||
583 | bfin_spi_giveback(drv_data); | ||
584 | } | ||
585 | |||
586 | bfin_write(&drv_data->regs->status, 0xFFFFFFFF); | ||
587 | bfin_spi_cs_active(drv_data, chip); | ||
588 | drv_data->state = RUNNING_STATE; | ||
589 | |||
590 | if (chip->enable_dma) | ||
591 | ret = bfin_spi_dma_xfer(drv_data); | ||
592 | else | ||
593 | ret = bfin_spi_pio_xfer(drv_data); | ||
594 | if (ret) { | ||
595 | msg->status = ret; | ||
596 | bfin_spi_giveback(drv_data); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | static int bfin_spi_transfer_one_message(struct spi_master *master, | ||
601 | struct spi_message *m) | ||
602 | { | ||
603 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | ||
604 | |||
605 | drv_data->cur_msg = m; | ||
606 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | ||
607 | bfin_spi_restore_state(drv_data); | ||
608 | |||
609 | drv_data->state = START_STATE; | ||
610 | drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, | ||
611 | struct spi_transfer, transfer_list); | ||
612 | |||
613 | tasklet_schedule(&drv_data->pump_transfers); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | #define MAX_SPI_SSEL 7 | ||
618 | |||
619 | static const u16 ssel[][MAX_SPI_SSEL] = { | ||
620 | {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, | ||
621 | P_SPI0_SSEL4, P_SPI0_SSEL5, | ||
622 | P_SPI0_SSEL6, P_SPI0_SSEL7}, | ||
623 | |||
624 | {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, | ||
625 | P_SPI1_SSEL4, P_SPI1_SSEL5, | ||
626 | P_SPI1_SSEL6, P_SPI1_SSEL7}, | ||
627 | |||
628 | {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, | ||
629 | P_SPI2_SSEL4, P_SPI2_SSEL5, | ||
630 | P_SPI2_SSEL6, P_SPI2_SSEL7}, | ||
631 | }; | ||
632 | |||
633 | static int bfin_spi_setup(struct spi_device *spi) | ||
634 | { | ||
635 | struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); | ||
636 | struct bfin_spi_device *chip = spi_get_ctldata(spi); | ||
637 | u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; | ||
638 | int ret = -EINVAL; | ||
639 | |||
640 | if (!chip) { | ||
641 | struct bfin_spi3_chip *chip_info = spi->controller_data; | ||
642 | |||
643 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
644 | if (!chip) { | ||
645 | dev_err(&spi->dev, "can not allocate chip data\n"); | ||
646 | return -ENOMEM; | ||
647 | } | ||
648 | if (chip_info) { | ||
649 | if (chip_info->control & ~bfin_ctl_reg) { | ||
650 | dev_err(&spi->dev, | ||
651 | "do not set bits that the SPI framework manages\n"); | ||
652 | goto error; | ||
653 | } | ||
654 | chip->control = chip_info->control; | ||
655 | chip->cs_chg_udelay = chip_info->cs_chg_udelay; | ||
656 | chip->tx_dummy_val = chip_info->tx_dummy_val; | ||
657 | chip->enable_dma = chip_info->enable_dma; | ||
658 | } | ||
659 | chip->cs = spi->chip_select; | ||
660 | if (chip->cs < MAX_CTRL_CS) { | ||
661 | chip->ssel = (1 << chip->cs) << 8; | ||
662 | ret = peripheral_request(ssel[spi->master->bus_num] | ||
663 | [chip->cs-1], dev_name(&spi->dev)); | ||
664 | if (ret) { | ||
665 | dev_err(&spi->dev, "peripheral_request() error\n"); | ||
666 | goto error; | ||
667 | } | ||
668 | } else { | ||
669 | chip->cs_gpio = chip->cs - MAX_CTRL_CS; | ||
670 | ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH, | ||
671 | dev_name(&spi->dev)); | ||
672 | if (ret) { | ||
673 | dev_err(&spi->dev, "gpio_request_one() error\n"); | ||
674 | goto error; | ||
675 | } | ||
676 | } | ||
677 | spi_set_ctldata(spi, chip); | ||
678 | } | ||
679 | |||
680 | /* force a default base state */ | ||
681 | chip->control &= bfin_ctl_reg; | ||
682 | |||
683 | if (spi->mode & SPI_CPOL) | ||
684 | chip->control |= SPI_CTL_CPOL; | ||
685 | if (spi->mode & SPI_CPHA) | ||
686 | chip->control |= SPI_CTL_CPHA; | ||
687 | if (spi->mode & SPI_LSB_FIRST) | ||
688 | chip->control |= SPI_CTL_LSBF; | ||
689 | chip->control |= SPI_CTL_MSTR; | ||
690 | /* we choose software to controll cs */ | ||
691 | chip->control &= ~SPI_CTL_ASSEL; | ||
692 | |||
693 | chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); | ||
694 | |||
695 | bfin_spi_cs_enable(drv_data, chip); | ||
696 | bfin_spi_cs_deactive(drv_data, chip); | ||
697 | |||
698 | return 0; | ||
699 | error: | ||
700 | if (chip) { | ||
701 | kfree(chip); | ||
702 | spi_set_ctldata(spi, NULL); | ||
703 | } | ||
704 | |||
705 | return ret; | ||
706 | } | ||
707 | |||
708 | static void bfin_spi_cleanup(struct spi_device *spi) | ||
709 | { | ||
710 | struct bfin_spi_device *chip = spi_get_ctldata(spi); | ||
711 | struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); | ||
712 | |||
713 | if (!chip) | ||
714 | return; | ||
715 | |||
716 | if (chip->cs < MAX_CTRL_CS) { | ||
717 | peripheral_free(ssel[spi->master->bus_num] | ||
718 | [chip->cs-1]); | ||
719 | bfin_spi_cs_disable(drv_data, chip); | ||
720 | } else { | ||
721 | gpio_free(chip->cs_gpio); | ||
722 | } | ||
723 | |||
724 | kfree(chip); | ||
725 | spi_set_ctldata(spi, NULL); | ||
726 | } | ||
727 | |||
728 | static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) | ||
729 | { | ||
730 | struct bfin_spi_master *drv_data = dev_id; | ||
731 | u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); | ||
732 | |||
733 | clear_dma_irqstat(drv_data->tx_dma); | ||
734 | if (dma_stat & DMA_DONE) { | ||
735 | drv_data->tx_num++; | ||
736 | } else { | ||
737 | dev_err(&drv_data->master->dev, | ||
738 | "spi tx dma error: %d\n", dma_stat); | ||
739 | if (drv_data->tx) | ||
740 | drv_data->state = ERROR_STATE; | ||
741 | } | ||
742 | bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); | ||
743 | return IRQ_HANDLED; | ||
744 | } | ||
745 | |||
746 | static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) | ||
747 | { | ||
748 | struct bfin_spi_master *drv_data = dev_id; | ||
749 | struct spi_message *msg = drv_data->cur_msg; | ||
750 | u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); | ||
751 | |||
752 | clear_dma_irqstat(drv_data->rx_dma); | ||
753 | if (dma_stat & DMA_DONE) { | ||
754 | drv_data->rx_num++; | ||
755 | /* we may fail on tx dma */ | ||
756 | if (drv_data->state != ERROR_STATE) | ||
757 | msg->actual_length += drv_data->transfer_len; | ||
758 | } else { | ||
759 | drv_data->state = ERROR_STATE; | ||
760 | dev_err(&drv_data->master->dev, | ||
761 | "spi rx dma error: %d\n", dma_stat); | ||
762 | } | ||
763 | bfin_write(&drv_data->regs->tx_control, 0); | ||
764 | bfin_write(&drv_data->regs->rx_control, 0); | ||
765 | if (drv_data->rx_num != drv_data->tx_num) | ||
766 | dev_dbg(&drv_data->master->dev, | ||
767 | "dma interrupt missing: tx=%d,rx=%d\n", | ||
768 | drv_data->tx_num, drv_data->rx_num); | ||
769 | tasklet_schedule(&drv_data->pump_transfers); | ||
770 | return IRQ_HANDLED; | ||
771 | } | ||
772 | |||
773 | static int bfin_spi_probe(struct platform_device *pdev) | ||
774 | { | ||
775 | struct device *dev = &pdev->dev; | ||
776 | struct bfin_spi3_master *info = dev->platform_data; | ||
777 | struct spi_master *master; | ||
778 | struct bfin_spi_master *drv_data; | ||
779 | struct resource *mem, *res; | ||
780 | unsigned int tx_dma, rx_dma; | ||
781 | unsigned long sclk; | ||
782 | int ret; | ||
783 | |||
784 | if (!info) { | ||
785 | dev_err(dev, "platform data missing!\n"); | ||
786 | return -ENODEV; | ||
787 | } | ||
788 | |||
789 | sclk = get_sclk1(); | ||
790 | if (!sclk) { | ||
791 | dev_err(dev, "can not get sclk1\n"); | ||
792 | return -ENXIO; | ||
793 | } | ||
794 | |||
795 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
796 | if (!res) { | ||
797 | dev_err(dev, "can not get tx dma resource\n"); | ||
798 | return -ENXIO; | ||
799 | } | ||
800 | tx_dma = res->start; | ||
801 | |||
802 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
803 | if (!res) { | ||
804 | dev_err(dev, "can not get rx dma resource\n"); | ||
805 | return -ENXIO; | ||
806 | } | ||
807 | rx_dma = res->start; | ||
808 | |||
809 | /* allocate master with space for drv_data */ | ||
810 | master = spi_alloc_master(dev, sizeof(*drv_data)); | ||
811 | if (!master) { | ||
812 | dev_err(dev, "can not alloc spi_master\n"); | ||
813 | return -ENOMEM; | ||
814 | } | ||
815 | platform_set_drvdata(pdev, master); | ||
816 | |||
817 | /* the mode bits supported by this driver */ | ||
818 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; | ||
819 | |||
820 | master->bus_num = pdev->id; | ||
821 | master->num_chipselect = info->num_chipselect; | ||
822 | master->cleanup = bfin_spi_cleanup; | ||
823 | master->setup = bfin_spi_setup; | ||
824 | master->transfer_one_message = bfin_spi_transfer_one_message; | ||
825 | master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1); | ||
826 | |||
827 | drv_data = spi_master_get_devdata(master); | ||
828 | drv_data->master = master; | ||
829 | drv_data->tx_dma = tx_dma; | ||
830 | drv_data->rx_dma = rx_dma; | ||
831 | drv_data->pin_req = info->pin_req; | ||
832 | drv_data->sclk = sclk; | ||
833 | |||
834 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
835 | drv_data->regs = devm_ioremap_resource(dev, mem); | ||
836 | if (IS_ERR(drv_data->regs)) { | ||
837 | ret = PTR_ERR(drv_data->regs); | ||
838 | goto err_put_master; | ||
839 | } | ||
840 | |||
841 | /* request tx and rx dma */ | ||
842 | ret = request_dma(tx_dma, "SPI_TX_DMA"); | ||
843 | if (ret) { | ||
844 | dev_err(dev, "can not request SPI TX DMA channel\n"); | ||
845 | goto err_put_master; | ||
846 | } | ||
847 | set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data); | ||
848 | |||
849 | ret = request_dma(rx_dma, "SPI_RX_DMA"); | ||
850 | if (ret) { | ||
851 | dev_err(dev, "can not request SPI RX DMA channel\n"); | ||
852 | goto err_free_tx_dma; | ||
853 | } | ||
854 | set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); | ||
855 | |||
856 | /* request CLK, MOSI and MISO */ | ||
857 | ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3"); | ||
858 | if (ret < 0) { | ||
859 | dev_err(dev, "can not request spi pins\n"); | ||
860 | goto err_free_rx_dma; | ||
861 | } | ||
862 | |||
863 | bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); | ||
864 | bfin_write(&drv_data->regs->ssel, 0x0000FE00); | ||
865 | bfin_write(&drv_data->regs->delay, 0x0); | ||
866 | |||
867 | tasklet_init(&drv_data->pump_transfers, | ||
868 | bfin_spi_pump_transfers, (unsigned long)drv_data); | ||
869 | /* register with the SPI framework */ | ||
870 | ret = spi_register_master(master); | ||
871 | if (ret) { | ||
872 | dev_err(dev, "can not register spi master\n"); | ||
873 | goto err_free_peripheral; | ||
874 | } | ||
875 | |||
876 | return ret; | ||
877 | |||
878 | err_free_peripheral: | ||
879 | peripheral_free_list(drv_data->pin_req); | ||
880 | err_free_rx_dma: | ||
881 | free_dma(rx_dma); | ||
882 | err_free_tx_dma: | ||
883 | free_dma(tx_dma); | ||
884 | err_put_master: | ||
885 | spi_master_put(master); | ||
886 | |||
887 | return ret; | ||
888 | } | ||
889 | |||
890 | static int bfin_spi_remove(struct platform_device *pdev) | ||
891 | { | ||
892 | struct spi_master *master = platform_get_drvdata(pdev); | ||
893 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | ||
894 | |||
895 | bfin_spi_disable(drv_data); | ||
896 | |||
897 | peripheral_free_list(drv_data->pin_req); | ||
898 | free_dma(drv_data->rx_dma); | ||
899 | free_dma(drv_data->tx_dma); | ||
900 | |||
901 | spi_unregister_master(drv_data->master); | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | #ifdef CONFIG_PM | ||
906 | static int bfin_spi_suspend(struct device *dev) | ||
907 | { | ||
908 | struct spi_master *master = dev_get_drvdata(dev); | ||
909 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | ||
910 | |||
911 | spi_master_suspend(master); | ||
912 | |||
913 | drv_data->control = bfin_read(&drv_data->regs->control); | ||
914 | drv_data->ssel = bfin_read(&drv_data->regs->ssel); | ||
915 | |||
916 | bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); | ||
917 | bfin_write(&drv_data->regs->ssel, 0x0000FE00); | ||
918 | dma_disable_irq(drv_data->rx_dma); | ||
919 | dma_disable_irq(drv_data->tx_dma); | ||
920 | |||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | static int bfin_spi_resume(struct device *dev) | ||
925 | { | ||
926 | struct spi_master *master = dev_get_drvdata(dev); | ||
927 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | ||
928 | int ret = 0; | ||
929 | |||
930 | /* bootrom may modify spi and dma status when resume in spi boot mode */ | ||
931 | disable_dma(drv_data->rx_dma); | ||
932 | |||
933 | dma_enable_irq(drv_data->rx_dma); | ||
934 | dma_enable_irq(drv_data->tx_dma); | ||
935 | bfin_write(&drv_data->regs->control, drv_data->control); | ||
936 | bfin_write(&drv_data->regs->ssel, drv_data->ssel); | ||
937 | |||
938 | ret = spi_master_resume(master); | ||
939 | if (ret) { | ||
940 | free_dma(drv_data->rx_dma); | ||
941 | free_dma(drv_data->tx_dma); | ||
942 | } | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | #endif | ||
947 | static const struct dev_pm_ops bfin_spi_pm_ops = { | ||
948 | SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume) | ||
949 | }; | ||
950 | |||
951 | MODULE_ALIAS("platform:bfin-spi3"); | ||
952 | static struct platform_driver bfin_spi_driver = { | ||
953 | .driver = { | ||
954 | .name = "bfin-spi3", | ||
955 | .owner = THIS_MODULE, | ||
956 | .pm = &bfin_spi_pm_ops, | ||
957 | }, | ||
958 | .remove = bfin_spi_remove, | ||
959 | }; | ||
960 | |||
961 | module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe); | ||
962 | |||
963 | MODULE_DESCRIPTION("Analog Devices SPI3 controller driver"); | ||
964 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
965 | MODULE_LICENSE("GPL v2"); | ||