Root/
1 | /* |
2 | * Designware SPI core controller driver (refer pxa2xx_spi.c) |
3 | * |
4 | * Copyright (c) 2009, Intel Corporation. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, |
8 | * version 2, as published by the Free Software Foundation. |
9 | * |
10 | * This program is distributed in the hope it will be useful, but WITHOUT |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
13 | * more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along with |
16 | * this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
18 | */ |
19 | |
20 | #include <linux/dma-mapping.h> |
21 | #include <linux/interrupt.h> |
22 | #include <linux/module.h> |
23 | #include <linux/highmem.h> |
24 | #include <linux/delay.h> |
25 | #include <linux/slab.h> |
26 | #include <linux/spi/spi.h> |
27 | |
28 | #include "spi-dw.h" |
29 | |
30 | #ifdef CONFIG_DEBUG_FS |
31 | #include <linux/debugfs.h> |
32 | #endif |
33 | |
34 | #define START_STATE ((void *)0) |
35 | #define RUNNING_STATE ((void *)1) |
36 | #define DONE_STATE ((void *)2) |
37 | #define ERROR_STATE ((void *)-1) |
38 | |
39 | #define QUEUE_RUNNING 0 |
40 | #define QUEUE_STOPPED 1 |
41 | |
42 | #define MRST_SPI_DEASSERT 0 |
43 | #define MRST_SPI_ASSERT 1 |
44 | |
45 | /* Slave spi_dev related */ |
46 | struct chip_data { |
47 | u16 cr0; |
48 | u8 cs; /* chip select pin */ |
49 | u8 n_bytes; /* current is a 1/2/4 byte op */ |
50 | u8 tmode; /* TR/TO/RO/EEPROM */ |
51 | u8 type; /* SPI/SSP/MicroWire */ |
52 | |
53 | u8 poll_mode; /* 1 means use poll mode */ |
54 | |
55 | u32 dma_width; |
56 | u32 rx_threshold; |
57 | u32 tx_threshold; |
58 | u8 enable_dma; |
59 | u8 bits_per_word; |
60 | u16 clk_div; /* baud rate divider */ |
61 | u32 speed_hz; /* baud rate */ |
62 | void (*cs_control)(u32 command); |
63 | }; |
64 | |
65 | #ifdef CONFIG_DEBUG_FS |
66 | #define SPI_REGS_BUFSIZE 1024 |
67 | static ssize_t spi_show_regs(struct file *file, char __user *user_buf, |
68 | size_t count, loff_t *ppos) |
69 | { |
70 | struct dw_spi *dws; |
71 | char *buf; |
72 | u32 len = 0; |
73 | ssize_t ret; |
74 | |
75 | dws = file->private_data; |
76 | |
77 | buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL); |
78 | if (!buf) |
79 | return 0; |
80 | |
81 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
82 | "MRST SPI0 registers:\n"); |
83 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
84 | "=================================\n"); |
85 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
86 | "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0)); |
87 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
88 | "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1)); |
89 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
90 | "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR)); |
91 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
92 | "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER)); |
93 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
94 | "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR)); |
95 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
96 | "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR)); |
97 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
98 | "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR)); |
99 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
100 | "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR)); |
101 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
102 | "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR)); |
103 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
104 | "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR)); |
105 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
106 | "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR)); |
107 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
108 | "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR)); |
109 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
110 | "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR)); |
111 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
112 | "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR)); |
113 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
114 | "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR)); |
115 | len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, |
116 | "=================================\n"); |
117 | |
118 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
119 | kfree(buf); |
120 | return ret; |
121 | } |
122 | |
123 | static const struct file_operations mrst_spi_regs_ops = { |
124 | .owner = THIS_MODULE, |
125 | .open = simple_open, |
126 | .read = spi_show_regs, |
127 | .llseek = default_llseek, |
128 | }; |
129 | |
130 | static int mrst_spi_debugfs_init(struct dw_spi *dws) |
131 | { |
132 | dws->debugfs = debugfs_create_dir("mrst_spi", NULL); |
133 | if (!dws->debugfs) |
134 | return -ENOMEM; |
135 | |
136 | debugfs_create_file("registers", S_IFREG | S_IRUGO, |
137 | dws->debugfs, (void *)dws, &mrst_spi_regs_ops); |
138 | return 0; |
139 | } |
140 | |
141 | static void mrst_spi_debugfs_remove(struct dw_spi *dws) |
142 | { |
143 | if (dws->debugfs) |
144 | debugfs_remove_recursive(dws->debugfs); |
145 | } |
146 | |
147 | #else |
148 | static inline int mrst_spi_debugfs_init(struct dw_spi *dws) |
149 | { |
150 | return 0; |
151 | } |
152 | |
153 | static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) |
154 | { |
155 | } |
156 | #endif /* CONFIG_DEBUG_FS */ |
157 | |
158 | /* Return the max entries we can fill into tx fifo */ |
159 | static inline u32 tx_max(struct dw_spi *dws) |
160 | { |
161 | u32 tx_left, tx_room, rxtx_gap; |
162 | |
163 | tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; |
164 | tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR); |
165 | |
166 | /* |
167 | * Another concern is about the tx/rx mismatch, we |
168 | * though to use (dws->fifo_len - rxflr - txflr) as |
169 | * one maximum value for tx, but it doesn't cover the |
170 | * data which is out of tx/rx fifo and inside the |
171 | * shift registers. So a control from sw point of |
172 | * view is taken. |
173 | */ |
174 | rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx)) |
175 | / dws->n_bytes; |
176 | |
177 | return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap)); |
178 | } |
179 | |
180 | /* Return the max entries we should read out of rx fifo */ |
181 | static inline u32 rx_max(struct dw_spi *dws) |
182 | { |
183 | u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; |
184 | |
185 | return min(rx_left, (u32)dw_readw(dws, DW_SPI_RXFLR)); |
186 | } |
187 | |
188 | static void dw_writer(struct dw_spi *dws) |
189 | { |
190 | u32 max = tx_max(dws); |
191 | u16 txw = 0; |
192 | |
193 | while (max--) { |
194 | /* Set the tx word if the transfer's original "tx" is not null */ |
195 | if (dws->tx_end - dws->len) { |
196 | if (dws->n_bytes == 1) |
197 | txw = *(u8 *)(dws->tx); |
198 | else |
199 | txw = *(u16 *)(dws->tx); |
200 | } |
201 | dw_writew(dws, DW_SPI_DR, txw); |
202 | dws->tx += dws->n_bytes; |
203 | } |
204 | } |
205 | |
206 | static void dw_reader(struct dw_spi *dws) |
207 | { |
208 | u32 max = rx_max(dws); |
209 | u16 rxw; |
210 | |
211 | while (max--) { |
212 | rxw = dw_readw(dws, DW_SPI_DR); |
213 | /* Care rx only if the transfer's original "rx" is not null */ |
214 | if (dws->rx_end - dws->len) { |
215 | if (dws->n_bytes == 1) |
216 | *(u8 *)(dws->rx) = rxw; |
217 | else |
218 | *(u16 *)(dws->rx) = rxw; |
219 | } |
220 | dws->rx += dws->n_bytes; |
221 | } |
222 | } |
223 | |
224 | static void *next_transfer(struct dw_spi *dws) |
225 | { |
226 | struct spi_message *msg = dws->cur_msg; |
227 | struct spi_transfer *trans = dws->cur_transfer; |
228 | |
229 | /* Move to next transfer */ |
230 | if (trans->transfer_list.next != &msg->transfers) { |
231 | dws->cur_transfer = |
232 | list_entry(trans->transfer_list.next, |
233 | struct spi_transfer, |
234 | transfer_list); |
235 | return RUNNING_STATE; |
236 | } else |
237 | return DONE_STATE; |
238 | } |
239 | |
240 | /* |
241 | * Note: first step is the protocol driver prepares |
242 | * a dma-capable memory, and this func just need translate |
243 | * the virt addr to physical |
244 | */ |
245 | static int map_dma_buffers(struct dw_spi *dws) |
246 | { |
247 | if (!dws->cur_msg->is_dma_mapped |
248 | || !dws->dma_inited |
249 | || !dws->cur_chip->enable_dma |
250 | || !dws->dma_ops) |
251 | return 0; |
252 | |
253 | if (dws->cur_transfer->tx_dma) |
254 | dws->tx_dma = dws->cur_transfer->tx_dma; |
255 | |
256 | if (dws->cur_transfer->rx_dma) |
257 | dws->rx_dma = dws->cur_transfer->rx_dma; |
258 | |
259 | return 1; |
260 | } |
261 | |
262 | /* Caller already set message->status; dma and pio irqs are blocked */ |
263 | static void giveback(struct dw_spi *dws) |
264 | { |
265 | struct spi_transfer *last_transfer; |
266 | unsigned long flags; |
267 | struct spi_message *msg; |
268 | |
269 | spin_lock_irqsave(&dws->lock, flags); |
270 | msg = dws->cur_msg; |
271 | dws->cur_msg = NULL; |
272 | dws->cur_transfer = NULL; |
273 | dws->prev_chip = dws->cur_chip; |
274 | dws->cur_chip = NULL; |
275 | dws->dma_mapped = 0; |
276 | queue_work(dws->workqueue, &dws->pump_messages); |
277 | spin_unlock_irqrestore(&dws->lock, flags); |
278 | |
279 | last_transfer = list_entry(msg->transfers.prev, |
280 | struct spi_transfer, |
281 | transfer_list); |
282 | |
283 | if (!last_transfer->cs_change && dws->cs_control) |
284 | dws->cs_control(MRST_SPI_DEASSERT); |
285 | |
286 | msg->state = NULL; |
287 | if (msg->complete) |
288 | msg->complete(msg->context); |
289 | } |
290 | |
291 | static void int_error_stop(struct dw_spi *dws, const char *msg) |
292 | { |
293 | /* Stop the hw */ |
294 | spi_enable_chip(dws, 0); |
295 | |
296 | dev_err(&dws->master->dev, "%s\n", msg); |
297 | dws->cur_msg->state = ERROR_STATE; |
298 | tasklet_schedule(&dws->pump_transfers); |
299 | } |
300 | |
301 | void dw_spi_xfer_done(struct dw_spi *dws) |
302 | { |
303 | /* Update total byte transferred return count actual bytes read */ |
304 | dws->cur_msg->actual_length += dws->len; |
305 | |
306 | /* Move to next transfer */ |
307 | dws->cur_msg->state = next_transfer(dws); |
308 | |
309 | /* Handle end of message */ |
310 | if (dws->cur_msg->state == DONE_STATE) { |
311 | dws->cur_msg->status = 0; |
312 | giveback(dws); |
313 | } else |
314 | tasklet_schedule(&dws->pump_transfers); |
315 | } |
316 | EXPORT_SYMBOL_GPL(dw_spi_xfer_done); |
317 | |
318 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) |
319 | { |
320 | u16 irq_status = dw_readw(dws, DW_SPI_ISR); |
321 | |
322 | /* Error handling */ |
323 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { |
324 | dw_readw(dws, DW_SPI_TXOICR); |
325 | dw_readw(dws, DW_SPI_RXOICR); |
326 | dw_readw(dws, DW_SPI_RXUICR); |
327 | int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); |
328 | return IRQ_HANDLED; |
329 | } |
330 | |
331 | dw_reader(dws); |
332 | if (dws->rx_end == dws->rx) { |
333 | spi_mask_intr(dws, SPI_INT_TXEI); |
334 | dw_spi_xfer_done(dws); |
335 | return IRQ_HANDLED; |
336 | } |
337 | if (irq_status & SPI_INT_TXEI) { |
338 | spi_mask_intr(dws, SPI_INT_TXEI); |
339 | dw_writer(dws); |
340 | /* Enable TX irq always, it will be disabled when RX finished */ |
341 | spi_umask_intr(dws, SPI_INT_TXEI); |
342 | } |
343 | |
344 | return IRQ_HANDLED; |
345 | } |
346 | |
347 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) |
348 | { |
349 | struct dw_spi *dws = dev_id; |
350 | u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f; |
351 | |
352 | if (!irq_status) |
353 | return IRQ_NONE; |
354 | |
355 | if (!dws->cur_msg) { |
356 | spi_mask_intr(dws, SPI_INT_TXEI); |
357 | return IRQ_HANDLED; |
358 | } |
359 | |
360 | return dws->transfer_handler(dws); |
361 | } |
362 | |
363 | /* Must be called inside pump_transfers() */ |
364 | static void poll_transfer(struct dw_spi *dws) |
365 | { |
366 | do { |
367 | dw_writer(dws); |
368 | dw_reader(dws); |
369 | cpu_relax(); |
370 | } while (dws->rx_end > dws->rx); |
371 | |
372 | dw_spi_xfer_done(dws); |
373 | } |
374 | |
375 | static void pump_transfers(unsigned long data) |
376 | { |
377 | struct dw_spi *dws = (struct dw_spi *)data; |
378 | struct spi_message *message = NULL; |
379 | struct spi_transfer *transfer = NULL; |
380 | struct spi_transfer *previous = NULL; |
381 | struct spi_device *spi = NULL; |
382 | struct chip_data *chip = NULL; |
383 | u8 bits = 0; |
384 | u8 imask = 0; |
385 | u8 cs_change = 0; |
386 | u16 txint_level = 0; |
387 | u16 clk_div = 0; |
388 | u32 speed = 0; |
389 | u32 cr0 = 0; |
390 | |
391 | /* Get current state information */ |
392 | message = dws->cur_msg; |
393 | transfer = dws->cur_transfer; |
394 | chip = dws->cur_chip; |
395 | spi = message->spi; |
396 | |
397 | if (unlikely(!chip->clk_div)) |
398 | chip->clk_div = dws->max_freq / chip->speed_hz; |
399 | |
400 | if (message->state == ERROR_STATE) { |
401 | message->status = -EIO; |
402 | goto early_exit; |
403 | } |
404 | |
405 | /* Handle end of message */ |
406 | if (message->state == DONE_STATE) { |
407 | message->status = 0; |
408 | goto early_exit; |
409 | } |
410 | |
411 | /* Delay if requested at end of transfer*/ |
412 | if (message->state == RUNNING_STATE) { |
413 | previous = list_entry(transfer->transfer_list.prev, |
414 | struct spi_transfer, |
415 | transfer_list); |
416 | if (previous->delay_usecs) |
417 | udelay(previous->delay_usecs); |
418 | } |
419 | |
420 | dws->n_bytes = chip->n_bytes; |
421 | dws->dma_width = chip->dma_width; |
422 | dws->cs_control = chip->cs_control; |
423 | |
424 | dws->rx_dma = transfer->rx_dma; |
425 | dws->tx_dma = transfer->tx_dma; |
426 | dws->tx = (void *)transfer->tx_buf; |
427 | dws->tx_end = dws->tx + transfer->len; |
428 | dws->rx = transfer->rx_buf; |
429 | dws->rx_end = dws->rx + transfer->len; |
430 | dws->cs_change = transfer->cs_change; |
431 | dws->len = dws->cur_transfer->len; |
432 | if (chip != dws->prev_chip) |
433 | cs_change = 1; |
434 | |
435 | cr0 = chip->cr0; |
436 | |
437 | /* Handle per transfer options for bpw and speed */ |
438 | if (transfer->speed_hz) { |
439 | speed = chip->speed_hz; |
440 | |
441 | if (transfer->speed_hz != speed) { |
442 | speed = transfer->speed_hz; |
443 | if (speed > dws->max_freq) { |
444 | printk(KERN_ERR "MRST SPI0: unsupported" |
445 | "freq: %dHz\n", speed); |
446 | message->status = -EIO; |
447 | goto early_exit; |
448 | } |
449 | |
450 | /* clk_div doesn't support odd number */ |
451 | clk_div = dws->max_freq / speed; |
452 | clk_div = (clk_div + 1) & 0xfffe; |
453 | |
454 | chip->speed_hz = speed; |
455 | chip->clk_div = clk_div; |
456 | } |
457 | } |
458 | if (transfer->bits_per_word) { |
459 | bits = transfer->bits_per_word; |
460 | |
461 | switch (bits) { |
462 | case 8: |
463 | case 16: |
464 | dws->n_bytes = dws->dma_width = bits >> 3; |
465 | break; |
466 | default: |
467 | printk(KERN_ERR "MRST SPI0: unsupported bits:" |
468 | "%db\n", bits); |
469 | message->status = -EIO; |
470 | goto early_exit; |
471 | } |
472 | |
473 | cr0 = (bits - 1) |
474 | | (chip->type << SPI_FRF_OFFSET) |
475 | | (spi->mode << SPI_MODE_OFFSET) |
476 | | (chip->tmode << SPI_TMOD_OFFSET); |
477 | } |
478 | message->state = RUNNING_STATE; |
479 | |
480 | /* |
481 | * Adjust transfer mode if necessary. Requires platform dependent |
482 | * chipselect mechanism. |
483 | */ |
484 | if (dws->cs_control) { |
485 | if (dws->rx && dws->tx) |
486 | chip->tmode = SPI_TMOD_TR; |
487 | else if (dws->rx) |
488 | chip->tmode = SPI_TMOD_RO; |
489 | else |
490 | chip->tmode = SPI_TMOD_TO; |
491 | |
492 | cr0 &= ~SPI_TMOD_MASK; |
493 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); |
494 | } |
495 | |
496 | /* Check if current transfer is a DMA transaction */ |
497 | dws->dma_mapped = map_dma_buffers(dws); |
498 | |
499 | /* |
500 | * Interrupt mode |
501 | * we only need set the TXEI IRQ, as TX/RX always happen syncronizely |
502 | */ |
503 | if (!dws->dma_mapped && !chip->poll_mode) { |
504 | int templen = dws->len / dws->n_bytes; |
505 | txint_level = dws->fifo_len / 2; |
506 | txint_level = (templen > txint_level) ? txint_level : templen; |
507 | |
508 | imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI; |
509 | dws->transfer_handler = interrupt_transfer; |
510 | } |
511 | |
512 | /* |
513 | * Reprogram registers only if |
514 | * 1. chip select changes |
515 | * 2. clk_div is changed |
516 | * 3. control value changes |
517 | */ |
518 | if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) { |
519 | spi_enable_chip(dws, 0); |
520 | |
521 | if (dw_readw(dws, DW_SPI_CTRL0) != cr0) |
522 | dw_writew(dws, DW_SPI_CTRL0, cr0); |
523 | |
524 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); |
525 | spi_chip_sel(dws, spi->chip_select); |
526 | |
527 | /* Set the interrupt mask, for poll mode just disable all int */ |
528 | spi_mask_intr(dws, 0xff); |
529 | if (imask) |
530 | spi_umask_intr(dws, imask); |
531 | if (txint_level) |
532 | dw_writew(dws, DW_SPI_TXFLTR, txint_level); |
533 | |
534 | spi_enable_chip(dws, 1); |
535 | if (cs_change) |
536 | dws->prev_chip = chip; |
537 | } |
538 | |
539 | if (dws->dma_mapped) |
540 | dws->dma_ops->dma_transfer(dws, cs_change); |
541 | |
542 | if (chip->poll_mode) |
543 | poll_transfer(dws); |
544 | |
545 | return; |
546 | |
547 | early_exit: |
548 | giveback(dws); |
549 | return; |
550 | } |
551 | |
552 | static void pump_messages(struct work_struct *work) |
553 | { |
554 | struct dw_spi *dws = |
555 | container_of(work, struct dw_spi, pump_messages); |
556 | unsigned long flags; |
557 | |
558 | /* Lock queue and check for queue work */ |
559 | spin_lock_irqsave(&dws->lock, flags); |
560 | if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) { |
561 | dws->busy = 0; |
562 | spin_unlock_irqrestore(&dws->lock, flags); |
563 | return; |
564 | } |
565 | |
566 | /* Make sure we are not already running a message */ |
567 | if (dws->cur_msg) { |
568 | spin_unlock_irqrestore(&dws->lock, flags); |
569 | return; |
570 | } |
571 | |
572 | /* Extract head of queue */ |
573 | dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue); |
574 | list_del_init(&dws->cur_msg->queue); |
575 | |
576 | /* Initial message state*/ |
577 | dws->cur_msg->state = START_STATE; |
578 | dws->cur_transfer = list_entry(dws->cur_msg->transfers.next, |
579 | struct spi_transfer, |
580 | transfer_list); |
581 | dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi); |
582 | |
583 | /* Mark as busy and launch transfers */ |
584 | tasklet_schedule(&dws->pump_transfers); |
585 | |
586 | dws->busy = 1; |
587 | spin_unlock_irqrestore(&dws->lock, flags); |
588 | } |
589 | |
590 | /* spi_device use this to queue in their spi_msg */ |
591 | static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg) |
592 | { |
593 | struct dw_spi *dws = spi_master_get_devdata(spi->master); |
594 | unsigned long flags; |
595 | |
596 | spin_lock_irqsave(&dws->lock, flags); |
597 | |
598 | if (dws->run == QUEUE_STOPPED) { |
599 | spin_unlock_irqrestore(&dws->lock, flags); |
600 | return -ESHUTDOWN; |
601 | } |
602 | |
603 | msg->actual_length = 0; |
604 | msg->status = -EINPROGRESS; |
605 | msg->state = START_STATE; |
606 | |
607 | list_add_tail(&msg->queue, &dws->queue); |
608 | |
609 | if (dws->run == QUEUE_RUNNING && !dws->busy) { |
610 | |
611 | if (dws->cur_transfer || dws->cur_msg) |
612 | queue_work(dws->workqueue, |
613 | &dws->pump_messages); |
614 | else { |
615 | /* If no other data transaction in air, just go */ |
616 | spin_unlock_irqrestore(&dws->lock, flags); |
617 | pump_messages(&dws->pump_messages); |
618 | return 0; |
619 | } |
620 | } |
621 | |
622 | spin_unlock_irqrestore(&dws->lock, flags); |
623 | return 0; |
624 | } |
625 | |
626 | /* This may be called twice for each spi dev */ |
627 | static int dw_spi_setup(struct spi_device *spi) |
628 | { |
629 | struct dw_spi_chip *chip_info = NULL; |
630 | struct chip_data *chip; |
631 | |
632 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) |
633 | return -EINVAL; |
634 | |
635 | /* Only alloc on first setup */ |
636 | chip = spi_get_ctldata(spi); |
637 | if (!chip) { |
638 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); |
639 | if (!chip) |
640 | return -ENOMEM; |
641 | } |
642 | |
643 | /* |
644 | * Protocol drivers may change the chip settings, so... |
645 | * if chip_info exists, use it |
646 | */ |
647 | chip_info = spi->controller_data; |
648 | |
649 | /* chip_info doesn't always exist */ |
650 | if (chip_info) { |
651 | if (chip_info->cs_control) |
652 | chip->cs_control = chip_info->cs_control; |
653 | |
654 | chip->poll_mode = chip_info->poll_mode; |
655 | chip->type = chip_info->type; |
656 | |
657 | chip->rx_threshold = 0; |
658 | chip->tx_threshold = 0; |
659 | |
660 | chip->enable_dma = chip_info->enable_dma; |
661 | } |
662 | |
663 | if (spi->bits_per_word <= 8) { |
664 | chip->n_bytes = 1; |
665 | chip->dma_width = 1; |
666 | } else if (spi->bits_per_word <= 16) { |
667 | chip->n_bytes = 2; |
668 | chip->dma_width = 2; |
669 | } else { |
670 | /* Never take >16b case for MRST SPIC */ |
671 | dev_err(&spi->dev, "invalid wordsize\n"); |
672 | return -EINVAL; |
673 | } |
674 | chip->bits_per_word = spi->bits_per_word; |
675 | |
676 | if (!spi->max_speed_hz) { |
677 | dev_err(&spi->dev, "No max speed HZ parameter\n"); |
678 | return -EINVAL; |
679 | } |
680 | chip->speed_hz = spi->max_speed_hz; |
681 | |
682 | chip->tmode = 0; /* Tx & Rx */ |
683 | /* Default SPI mode is SCPOL = 0, SCPH = 0 */ |
684 | chip->cr0 = (chip->bits_per_word - 1) |
685 | | (chip->type << SPI_FRF_OFFSET) |
686 | | (spi->mode << SPI_MODE_OFFSET) |
687 | | (chip->tmode << SPI_TMOD_OFFSET); |
688 | |
689 | spi_set_ctldata(spi, chip); |
690 | return 0; |
691 | } |
692 | |
693 | static void dw_spi_cleanup(struct spi_device *spi) |
694 | { |
695 | struct chip_data *chip = spi_get_ctldata(spi); |
696 | kfree(chip); |
697 | } |
698 | |
699 | static int __devinit init_queue(struct dw_spi *dws) |
700 | { |
701 | INIT_LIST_HEAD(&dws->queue); |
702 | spin_lock_init(&dws->lock); |
703 | |
704 | dws->run = QUEUE_STOPPED; |
705 | dws->busy = 0; |
706 | |
707 | tasklet_init(&dws->pump_transfers, |
708 | pump_transfers, (unsigned long)dws); |
709 | |
710 | INIT_WORK(&dws->pump_messages, pump_messages); |
711 | dws->workqueue = create_singlethread_workqueue( |
712 | dev_name(dws->master->dev.parent)); |
713 | if (dws->workqueue == NULL) |
714 | return -EBUSY; |
715 | |
716 | return 0; |
717 | } |
718 | |
719 | static int start_queue(struct dw_spi *dws) |
720 | { |
721 | unsigned long flags; |
722 | |
723 | spin_lock_irqsave(&dws->lock, flags); |
724 | |
725 | if (dws->run == QUEUE_RUNNING || dws->busy) { |
726 | spin_unlock_irqrestore(&dws->lock, flags); |
727 | return -EBUSY; |
728 | } |
729 | |
730 | dws->run = QUEUE_RUNNING; |
731 | dws->cur_msg = NULL; |
732 | dws->cur_transfer = NULL; |
733 | dws->cur_chip = NULL; |
734 | dws->prev_chip = NULL; |
735 | spin_unlock_irqrestore(&dws->lock, flags); |
736 | |
737 | queue_work(dws->workqueue, &dws->pump_messages); |
738 | |
739 | return 0; |
740 | } |
741 | |
742 | static int stop_queue(struct dw_spi *dws) |
743 | { |
744 | unsigned long flags; |
745 | unsigned limit = 50; |
746 | int status = 0; |
747 | |
748 | spin_lock_irqsave(&dws->lock, flags); |
749 | dws->run = QUEUE_STOPPED; |
750 | while ((!list_empty(&dws->queue) || dws->busy) && limit--) { |
751 | spin_unlock_irqrestore(&dws->lock, flags); |
752 | msleep(10); |
753 | spin_lock_irqsave(&dws->lock, flags); |
754 | } |
755 | |
756 | if (!list_empty(&dws->queue) || dws->busy) |
757 | status = -EBUSY; |
758 | spin_unlock_irqrestore(&dws->lock, flags); |
759 | |
760 | return status; |
761 | } |
762 | |
763 | static int destroy_queue(struct dw_spi *dws) |
764 | { |
765 | int status; |
766 | |
767 | status = stop_queue(dws); |
768 | if (status != 0) |
769 | return status; |
770 | destroy_workqueue(dws->workqueue); |
771 | return 0; |
772 | } |
773 | |
774 | /* Restart the controller, disable all interrupts, clean rx fifo */ |
775 | static void spi_hw_init(struct dw_spi *dws) |
776 | { |
777 | spi_enable_chip(dws, 0); |
778 | spi_mask_intr(dws, 0xff); |
779 | spi_enable_chip(dws, 1); |
780 | |
781 | /* |
782 | * Try to detect the FIFO depth if not set by interface driver, |
783 | * the depth could be from 2 to 256 from HW spec |
784 | */ |
785 | if (!dws->fifo_len) { |
786 | u32 fifo; |
787 | for (fifo = 2; fifo <= 257; fifo++) { |
788 | dw_writew(dws, DW_SPI_TXFLTR, fifo); |
789 | if (fifo != dw_readw(dws, DW_SPI_TXFLTR)) |
790 | break; |
791 | } |
792 | |
793 | dws->fifo_len = (fifo == 257) ? 0 : fifo; |
794 | dw_writew(dws, DW_SPI_TXFLTR, 0); |
795 | } |
796 | } |
797 | |
798 | int __devinit dw_spi_add_host(struct dw_spi *dws) |
799 | { |
800 | struct spi_master *master; |
801 | int ret; |
802 | |
803 | BUG_ON(dws == NULL); |
804 | |
805 | master = spi_alloc_master(dws->parent_dev, 0); |
806 | if (!master) { |
807 | ret = -ENOMEM; |
808 | goto exit; |
809 | } |
810 | |
811 | dws->master = master; |
812 | dws->type = SSI_MOTO_SPI; |
813 | dws->prev_chip = NULL; |
814 | dws->dma_inited = 0; |
815 | dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); |
816 | snprintf(dws->name, sizeof(dws->name), "dw_spi%d", |
817 | dws->bus_num); |
818 | |
819 | ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, |
820 | dws->name, dws); |
821 | if (ret < 0) { |
822 | dev_err(&master->dev, "can not get IRQ\n"); |
823 | goto err_free_master; |
824 | } |
825 | |
826 | master->mode_bits = SPI_CPOL | SPI_CPHA; |
827 | master->bus_num = dws->bus_num; |
828 | master->num_chipselect = dws->num_cs; |
829 | master->cleanup = dw_spi_cleanup; |
830 | master->setup = dw_spi_setup; |
831 | master->transfer = dw_spi_transfer; |
832 | |
833 | /* Basic HW init */ |
834 | spi_hw_init(dws); |
835 | |
836 | if (dws->dma_ops && dws->dma_ops->dma_init) { |
837 | ret = dws->dma_ops->dma_init(dws); |
838 | if (ret) { |
839 | dev_warn(&master->dev, "DMA init failed\n"); |
840 | dws->dma_inited = 0; |
841 | } |
842 | } |
843 | |
844 | /* Initial and start queue */ |
845 | ret = init_queue(dws); |
846 | if (ret) { |
847 | dev_err(&master->dev, "problem initializing queue\n"); |
848 | goto err_diable_hw; |
849 | } |
850 | ret = start_queue(dws); |
851 | if (ret) { |
852 | dev_err(&master->dev, "problem starting queue\n"); |
853 | goto err_diable_hw; |
854 | } |
855 | |
856 | spi_master_set_devdata(master, dws); |
857 | ret = spi_register_master(master); |
858 | if (ret) { |
859 | dev_err(&master->dev, "problem registering spi master\n"); |
860 | goto err_queue_alloc; |
861 | } |
862 | |
863 | mrst_spi_debugfs_init(dws); |
864 | return 0; |
865 | |
866 | err_queue_alloc: |
867 | destroy_queue(dws); |
868 | if (dws->dma_ops && dws->dma_ops->dma_exit) |
869 | dws->dma_ops->dma_exit(dws); |
870 | err_diable_hw: |
871 | spi_enable_chip(dws, 0); |
872 | free_irq(dws->irq, dws); |
873 | err_free_master: |
874 | spi_master_put(master); |
875 | exit: |
876 | return ret; |
877 | } |
878 | EXPORT_SYMBOL_GPL(dw_spi_add_host); |
879 | |
880 | void __devexit dw_spi_remove_host(struct dw_spi *dws) |
881 | { |
882 | int status = 0; |
883 | |
884 | if (!dws) |
885 | return; |
886 | mrst_spi_debugfs_remove(dws); |
887 | |
888 | /* Remove the queue */ |
889 | status = destroy_queue(dws); |
890 | if (status != 0) |
891 | dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " |
892 | "complete, message memory not freed\n"); |
893 | |
894 | if (dws->dma_ops && dws->dma_ops->dma_exit) |
895 | dws->dma_ops->dma_exit(dws); |
896 | spi_enable_chip(dws, 0); |
897 | /* Disable clk */ |
898 | spi_set_clk(dws, 0); |
899 | free_irq(dws->irq, dws); |
900 | |
901 | /* Disconnect from the SPI framework */ |
902 | spi_unregister_master(dws->master); |
903 | } |
904 | EXPORT_SYMBOL_GPL(dw_spi_remove_host); |
905 | |
906 | int dw_spi_suspend_host(struct dw_spi *dws) |
907 | { |
908 | int ret = 0; |
909 | |
910 | ret = stop_queue(dws); |
911 | if (ret) |
912 | return ret; |
913 | spi_enable_chip(dws, 0); |
914 | spi_set_clk(dws, 0); |
915 | return ret; |
916 | } |
917 | EXPORT_SYMBOL_GPL(dw_spi_suspend_host); |
918 | |
919 | int dw_spi_resume_host(struct dw_spi *dws) |
920 | { |
921 | int ret; |
922 | |
923 | spi_hw_init(dws); |
924 | ret = start_queue(dws); |
925 | if (ret) |
926 | dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); |
927 | return ret; |
928 | } |
929 | EXPORT_SYMBOL_GPL(dw_spi_resume_host); |
930 | |
931 | MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); |
932 | MODULE_DESCRIPTION("Driver for DesignWare SPI controller core"); |
933 | MODULE_LICENSE("GPL v2"); |
934 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9