Commit | Line | Data |
---|---|---|
fa4bd4f1 SJ |
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 | /* get register base and tx/rx dma */ | |
796 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
797 | if (!mem) { | |
798 | dev_err(dev, "can not get register base\n"); | |
799 | return -ENXIO; | |
800 | } | |
801 | ||
802 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | |
803 | if (!res) { | |
804 | dev_err(dev, "can not get tx dma resource\n"); | |
805 | return -ENXIO; | |
806 | } | |
807 | tx_dma = res->start; | |
808 | ||
809 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | |
810 | if (!res) { | |
811 | dev_err(dev, "can not get rx dma resource\n"); | |
812 | return -ENXIO; | |
813 | } | |
814 | rx_dma = res->start; | |
815 | ||
816 | /* allocate master with space for drv_data */ | |
817 | master = spi_alloc_master(dev, sizeof(*drv_data)); | |
818 | if (!master) { | |
819 | dev_err(dev, "can not alloc spi_master\n"); | |
820 | return -ENOMEM; | |
821 | } | |
822 | platform_set_drvdata(pdev, master); | |
823 | ||
824 | /* the mode bits supported by this driver */ | |
825 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; | |
826 | ||
827 | master->bus_num = pdev->id; | |
828 | master->num_chipselect = info->num_chipselect; | |
829 | master->cleanup = bfin_spi_cleanup; | |
830 | master->setup = bfin_spi_setup; | |
831 | master->transfer_one_message = bfin_spi_transfer_one_message; | |
832 | master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1); | |
833 | ||
834 | drv_data = spi_master_get_devdata(master); | |
835 | drv_data->master = master; | |
836 | drv_data->tx_dma = tx_dma; | |
837 | drv_data->rx_dma = rx_dma; | |
838 | drv_data->pin_req = info->pin_req; | |
839 | drv_data->sclk = sclk; | |
840 | ||
841 | drv_data->regs = devm_ioremap_resource(dev, mem); | |
842 | if (IS_ERR(drv_data->regs)) { | |
843 | ret = PTR_ERR(drv_data->regs); | |
844 | goto err_put_master; | |
845 | } | |
846 | ||
847 | /* request tx and rx dma */ | |
848 | ret = request_dma(tx_dma, "SPI_TX_DMA"); | |
849 | if (ret) { | |
850 | dev_err(dev, "can not request SPI TX DMA channel\n"); | |
851 | goto err_put_master; | |
852 | } | |
853 | set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data); | |
854 | ||
855 | ret = request_dma(rx_dma, "SPI_RX_DMA"); | |
856 | if (ret) { | |
857 | dev_err(dev, "can not request SPI RX DMA channel\n"); | |
858 | goto err_free_tx_dma; | |
859 | } | |
860 | set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); | |
861 | ||
862 | /* request CLK, MOSI and MISO */ | |
863 | ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3"); | |
864 | if (ret < 0) { | |
865 | dev_err(dev, "can not request spi pins\n"); | |
866 | goto err_free_rx_dma; | |
867 | } | |
868 | ||
869 | bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); | |
870 | bfin_write(&drv_data->regs->ssel, 0x0000FE00); | |
871 | bfin_write(&drv_data->regs->delay, 0x0); | |
872 | ||
873 | tasklet_init(&drv_data->pump_transfers, | |
874 | bfin_spi_pump_transfers, (unsigned long)drv_data); | |
875 | /* register with the SPI framework */ | |
876 | ret = spi_register_master(master); | |
877 | if (ret) { | |
878 | dev_err(dev, "can not register spi master\n"); | |
879 | goto err_free_peripheral; | |
880 | } | |
881 | ||
882 | return ret; | |
883 | ||
884 | err_free_peripheral: | |
885 | peripheral_free_list(drv_data->pin_req); | |
886 | err_free_rx_dma: | |
887 | free_dma(rx_dma); | |
888 | err_free_tx_dma: | |
889 | free_dma(tx_dma); | |
890 | err_put_master: | |
891 | platform_set_drvdata(pdev, NULL); | |
892 | spi_master_put(master); | |
893 | ||
894 | return ret; | |
895 | } | |
896 | ||
897 | static int bfin_spi_remove(struct platform_device *pdev) | |
898 | { | |
899 | struct spi_master *master = platform_get_drvdata(pdev); | |
900 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | |
901 | ||
902 | bfin_spi_disable(drv_data); | |
903 | ||
904 | peripheral_free_list(drv_data->pin_req); | |
905 | free_dma(drv_data->rx_dma); | |
906 | free_dma(drv_data->tx_dma); | |
907 | ||
908 | platform_set_drvdata(pdev, NULL); | |
909 | spi_unregister_master(drv_data->master); | |
910 | return 0; | |
911 | } | |
912 | ||
913 | #ifdef CONFIG_PM | |
914 | static int bfin_spi_suspend(struct device *dev) | |
915 | { | |
916 | struct spi_master *master = dev_get_drvdata(dev); | |
917 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | |
918 | ||
919 | spi_master_suspend(master); | |
920 | ||
921 | drv_data->control = bfin_read(&drv_data->regs->control); | |
922 | drv_data->ssel = bfin_read(&drv_data->regs->ssel); | |
923 | ||
924 | bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); | |
925 | bfin_write(&drv_data->regs->ssel, 0x0000FE00); | |
926 | dma_disable_irq(drv_data->rx_dma); | |
927 | dma_disable_irq(drv_data->tx_dma); | |
928 | ||
929 | return 0; | |
930 | } | |
931 | ||
932 | static int bfin_spi_resume(struct device *dev) | |
933 | { | |
934 | struct spi_master *master = dev_get_drvdata(dev); | |
935 | struct bfin_spi_master *drv_data = spi_master_get_devdata(master); | |
936 | int ret = 0; | |
937 | ||
938 | /* bootrom may modify spi and dma status when resume in spi boot mode */ | |
939 | disable_dma(drv_data->rx_dma); | |
940 | ||
941 | dma_enable_irq(drv_data->rx_dma); | |
942 | dma_enable_irq(drv_data->tx_dma); | |
943 | bfin_write(&drv_data->regs->control, drv_data->control); | |
944 | bfin_write(&drv_data->regs->ssel, drv_data->ssel); | |
945 | ||
946 | ret = spi_master_resume(master); | |
947 | if (ret) { | |
948 | free_dma(drv_data->rx_dma); | |
949 | free_dma(drv_data->tx_dma); | |
950 | } | |
951 | ||
952 | return ret; | |
953 | } | |
954 | #endif | |
955 | static const struct dev_pm_ops bfin_spi_pm_ops = { | |
956 | SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume) | |
957 | }; | |
958 | ||
959 | MODULE_ALIAS("platform:bfin-spi3"); | |
960 | static struct platform_driver bfin_spi_driver = { | |
961 | .driver = { | |
962 | .name = "bfin-spi3", | |
963 | .owner = THIS_MODULE, | |
964 | .pm = &bfin_spi_pm_ops, | |
965 | }, | |
966 | .remove = bfin_spi_remove, | |
967 | }; | |
968 | ||
969 | module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe); | |
970 | ||
971 | MODULE_DESCRIPTION("Analog Devices SPI3 controller driver"); | |
972 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | |
973 | MODULE_LICENSE("GPL v2"); |