diff options
Diffstat (limited to 'drivers/spi/dw_spi.c')
-rw-r--r-- | drivers/spi/dw_spi.c | 244 |
1 files changed, 96 insertions, 148 deletions
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 56247853c298..919fa9d9e16b 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
@@ -22,10 +22,10 @@ | |||
22 | #include <linux/highmem.h> | 22 | #include <linux/highmem.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | |||
26 | #include <linux/spi/dw_spi.h> | ||
27 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
28 | 26 | ||
27 | #include "dw_spi.h" | ||
28 | |||
29 | #ifdef CONFIG_DEBUG_FS | 29 | #ifdef CONFIG_DEBUG_FS |
30 | #include <linux/debugfs.h> | 30 | #include <linux/debugfs.h> |
31 | #endif | 31 | #endif |
@@ -58,8 +58,6 @@ struct chip_data { | |||
58 | u8 bits_per_word; | 58 | u8 bits_per_word; |
59 | u16 clk_div; /* baud rate divider */ | 59 | u16 clk_div; /* baud rate divider */ |
60 | u32 speed_hz; /* baud rate */ | 60 | u32 speed_hz; /* baud rate */ |
61 | int (*write)(struct dw_spi *dws); | ||
62 | int (*read)(struct dw_spi *dws); | ||
63 | void (*cs_control)(u32 command); | 61 | void (*cs_control)(u32 command); |
64 | }; | 62 | }; |
65 | 63 | ||
@@ -131,6 +129,7 @@ static const struct file_operations mrst_spi_regs_ops = { | |||
131 | .owner = THIS_MODULE, | 129 | .owner = THIS_MODULE, |
132 | .open = spi_show_regs_open, | 130 | .open = spi_show_regs_open, |
133 | .read = spi_show_regs, | 131 | .read = spi_show_regs, |
132 | .llseek = default_llseek, | ||
134 | }; | 133 | }; |
135 | 134 | ||
136 | static int mrst_spi_debugfs_init(struct dw_spi *dws) | 135 | static int mrst_spi_debugfs_init(struct dw_spi *dws) |
@@ -161,104 +160,70 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) | |||
161 | } | 160 | } |
162 | #endif /* CONFIG_DEBUG_FS */ | 161 | #endif /* CONFIG_DEBUG_FS */ |
163 | 162 | ||
164 | static void wait_till_not_busy(struct dw_spi *dws) | 163 | /* Return the max entries we can fill into tx fifo */ |
165 | { | 164 | static inline u32 tx_max(struct dw_spi *dws) |
166 | unsigned long end = jiffies + 1 + usecs_to_jiffies(1000); | ||
167 | |||
168 | while (time_before(jiffies, end)) { | ||
169 | if (!(dw_readw(dws, sr) & SR_BUSY)) | ||
170 | return; | ||
171 | } | ||
172 | dev_err(&dws->master->dev, | ||
173 | "DW SPI: Status keeps busy for 1000us after a read/write!\n"); | ||
174 | } | ||
175 | |||
176 | static void flush(struct dw_spi *dws) | ||
177 | { | 165 | { |
178 | while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 166 | u32 tx_left, tx_room, rxtx_gap; |
179 | dw_readw(dws, dr); | ||
180 | |||
181 | wait_till_not_busy(dws); | ||
182 | } | ||
183 | 167 | ||
184 | static int null_writer(struct dw_spi *dws) | 168 | tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; |
185 | { | 169 | tx_room = dws->fifo_len - dw_readw(dws, txflr); |
186 | u8 n_bytes = dws->n_bytes; | ||
187 | 170 | ||
188 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 171 | /* |
189 | || (dws->tx == dws->tx_end)) | 172 | * Another concern is about the tx/rx mismatch, we |
190 | return 0; | 173 | * though to use (dws->fifo_len - rxflr - txflr) as |
191 | dw_writew(dws, dr, 0); | 174 | * one maximum value for tx, but it doesn't cover the |
192 | dws->tx += n_bytes; | 175 | * data which is out of tx/rx fifo and inside the |
176 | * shift registers. So a control from sw point of | ||
177 | * view is taken. | ||
178 | */ | ||
179 | rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx)) | ||
180 | / dws->n_bytes; | ||
193 | 181 | ||
194 | wait_till_not_busy(dws); | 182 | return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap)); |
195 | return 1; | ||
196 | } | 183 | } |
197 | 184 | ||
198 | static int null_reader(struct dw_spi *dws) | 185 | /* Return the max entries we should read out of rx fifo */ |
186 | static inline u32 rx_max(struct dw_spi *dws) | ||
199 | { | 187 | { |
200 | u8 n_bytes = dws->n_bytes; | 188 | u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; |
201 | 189 | ||
202 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 190 | return min(rx_left, (u32)dw_readw(dws, rxflr)); |
203 | && (dws->rx < dws->rx_end)) { | ||
204 | dw_readw(dws, dr); | ||
205 | dws->rx += n_bytes; | ||
206 | } | ||
207 | wait_till_not_busy(dws); | ||
208 | return dws->rx == dws->rx_end; | ||
209 | } | 191 | } |
210 | 192 | ||
211 | static int u8_writer(struct dw_spi *dws) | 193 | static void dw_writer(struct dw_spi *dws) |
212 | { | 194 | { |
213 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 195 | u32 max = tx_max(dws); |
214 | || (dws->tx == dws->tx_end)) | 196 | u16 txw = 0; |
215 | return 0; | ||
216 | |||
217 | dw_writew(dws, dr, *(u8 *)(dws->tx)); | ||
218 | ++dws->tx; | ||
219 | |||
220 | wait_till_not_busy(dws); | ||
221 | return 1; | ||
222 | } | ||
223 | 197 | ||
224 | static int u8_reader(struct dw_spi *dws) | 198 | while (max--) { |
225 | { | 199 | /* Set the tx word if the transfer's original "tx" is not null */ |
226 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 200 | if (dws->tx_end - dws->len) { |
227 | && (dws->rx < dws->rx_end)) { | 201 | if (dws->n_bytes == 1) |
228 | *(u8 *)(dws->rx) = dw_readw(dws, dr); | 202 | txw = *(u8 *)(dws->tx); |
229 | ++dws->rx; | 203 | else |
204 | txw = *(u16 *)(dws->tx); | ||
205 | } | ||
206 | dw_writew(dws, dr, txw); | ||
207 | dws->tx += dws->n_bytes; | ||
230 | } | 208 | } |
231 | |||
232 | wait_till_not_busy(dws); | ||
233 | return dws->rx == dws->rx_end; | ||
234 | } | ||
235 | |||
236 | static int u16_writer(struct dw_spi *dws) | ||
237 | { | ||
238 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | ||
239 | || (dws->tx == dws->tx_end)) | ||
240 | return 0; | ||
241 | |||
242 | dw_writew(dws, dr, *(u16 *)(dws->tx)); | ||
243 | dws->tx += 2; | ||
244 | |||
245 | wait_till_not_busy(dws); | ||
246 | return 1; | ||
247 | } | 209 | } |
248 | 210 | ||
249 | static int u16_reader(struct dw_spi *dws) | 211 | static void dw_reader(struct dw_spi *dws) |
250 | { | 212 | { |
251 | u16 temp; | 213 | u32 max = rx_max(dws); |
214 | u16 rxw; | ||
252 | 215 | ||
253 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 216 | while (max--) { |
254 | && (dws->rx < dws->rx_end)) { | 217 | rxw = dw_readw(dws, dr); |
255 | temp = dw_readw(dws, dr); | 218 | /* Care rx only if the transfer's original "rx" is not null */ |
256 | *(u16 *)(dws->rx) = temp; | 219 | if (dws->rx_end - dws->len) { |
257 | dws->rx += 2; | 220 | if (dws->n_bytes == 1) |
221 | *(u8 *)(dws->rx) = rxw; | ||
222 | else | ||
223 | *(u16 *)(dws->rx) = rxw; | ||
224 | } | ||
225 | dws->rx += dws->n_bytes; | ||
258 | } | 226 | } |
259 | |||
260 | wait_till_not_busy(dws); | ||
261 | return dws->rx == dws->rx_end; | ||
262 | } | 227 | } |
263 | 228 | ||
264 | static void *next_transfer(struct dw_spi *dws) | 229 | static void *next_transfer(struct dw_spi *dws) |
@@ -284,8 +249,10 @@ static void *next_transfer(struct dw_spi *dws) | |||
284 | */ | 249 | */ |
285 | static int map_dma_buffers(struct dw_spi *dws) | 250 | static int map_dma_buffers(struct dw_spi *dws) |
286 | { | 251 | { |
287 | if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited | 252 | if (!dws->cur_msg->is_dma_mapped |
288 | || !dws->cur_chip->enable_dma) | 253 | || !dws->dma_inited |
254 | || !dws->cur_chip->enable_dma | ||
255 | || !dws->dma_ops) | ||
289 | return 0; | 256 | return 0; |
290 | 257 | ||
291 | if (dws->cur_transfer->tx_dma) | 258 | if (dws->cur_transfer->tx_dma) |
@@ -328,8 +295,7 @@ static void giveback(struct dw_spi *dws) | |||
328 | 295 | ||
329 | static void int_error_stop(struct dw_spi *dws, const char *msg) | 296 | static void int_error_stop(struct dw_spi *dws, const char *msg) |
330 | { | 297 | { |
331 | /* Stop and reset hw */ | 298 | /* Stop the hw */ |
332 | flush(dws); | ||
333 | spi_enable_chip(dws, 0); | 299 | spi_enable_chip(dws, 0); |
334 | 300 | ||
335 | dev_err(&dws->master->dev, "%s\n", msg); | 301 | dev_err(&dws->master->dev, "%s\n", msg); |
@@ -337,9 +303,9 @@ static void int_error_stop(struct dw_spi *dws, const char *msg) | |||
337 | tasklet_schedule(&dws->pump_transfers); | 303 | tasklet_schedule(&dws->pump_transfers); |
338 | } | 304 | } |
339 | 305 | ||
340 | static void transfer_complete(struct dw_spi *dws) | 306 | void dw_spi_xfer_done(struct dw_spi *dws) |
341 | { | 307 | { |
342 | /* Update total byte transfered return count actual bytes read */ | 308 | /* Update total byte transferred return count actual bytes read */ |
343 | dws->cur_msg->actual_length += dws->len; | 309 | dws->cur_msg->actual_length += dws->len; |
344 | 310 | ||
345 | /* Move to next transfer */ | 311 | /* Move to next transfer */ |
@@ -352,38 +318,32 @@ static void transfer_complete(struct dw_spi *dws) | |||
352 | } else | 318 | } else |
353 | tasklet_schedule(&dws->pump_transfers); | 319 | tasklet_schedule(&dws->pump_transfers); |
354 | } | 320 | } |
321 | EXPORT_SYMBOL_GPL(dw_spi_xfer_done); | ||
355 | 322 | ||
356 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) | 323 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) |
357 | { | 324 | { |
358 | u16 irq_status, irq_mask = 0x3f; | 325 | u16 irq_status = dw_readw(dws, isr); |
359 | u32 int_level = dws->fifo_len / 2; | ||
360 | u32 left; | ||
361 | 326 | ||
362 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
363 | /* Error handling */ | 327 | /* Error handling */ |
364 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { | 328 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { |
365 | dw_readw(dws, txoicr); | 329 | dw_readw(dws, txoicr); |
366 | dw_readw(dws, rxoicr); | 330 | dw_readw(dws, rxoicr); |
367 | dw_readw(dws, rxuicr); | 331 | dw_readw(dws, rxuicr); |
368 | int_error_stop(dws, "interrupt_transfer: fifo overrun"); | 332 | int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); |
369 | return IRQ_HANDLED; | 333 | return IRQ_HANDLED; |
370 | } | 334 | } |
371 | 335 | ||
336 | dw_reader(dws); | ||
337 | if (dws->rx_end == dws->rx) { | ||
338 | spi_mask_intr(dws, SPI_INT_TXEI); | ||
339 | dw_spi_xfer_done(dws); | ||
340 | return IRQ_HANDLED; | ||
341 | } | ||
372 | if (irq_status & SPI_INT_TXEI) { | 342 | if (irq_status & SPI_INT_TXEI) { |
373 | spi_mask_intr(dws, SPI_INT_TXEI); | 343 | spi_mask_intr(dws, SPI_INT_TXEI); |
374 | 344 | dw_writer(dws); | |
375 | left = (dws->tx_end - dws->tx) / dws->n_bytes; | 345 | /* Enable TX irq always, it will be disabled when RX finished */ |
376 | left = (left > int_level) ? int_level : left; | 346 | spi_umask_intr(dws, SPI_INT_TXEI); |
377 | |||
378 | while (left--) | ||
379 | dws->write(dws); | ||
380 | dws->read(dws); | ||
381 | |||
382 | /* Re-enable the IRQ if there is still data left to tx */ | ||
383 | if (dws->tx_end > dws->tx) | ||
384 | spi_umask_intr(dws, SPI_INT_TXEI); | ||
385 | else | ||
386 | transfer_complete(dws); | ||
387 | } | 347 | } |
388 | 348 | ||
389 | return IRQ_HANDLED; | 349 | return IRQ_HANDLED; |
@@ -392,15 +352,13 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
392 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) | 352 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) |
393 | { | 353 | { |
394 | struct dw_spi *dws = dev_id; | 354 | struct dw_spi *dws = dev_id; |
395 | u16 irq_status, irq_mask = 0x3f; | 355 | u16 irq_status = dw_readw(dws, isr) & 0x3f; |
396 | 356 | ||
397 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
398 | if (!irq_status) | 357 | if (!irq_status) |
399 | return IRQ_NONE; | 358 | return IRQ_NONE; |
400 | 359 | ||
401 | if (!dws->cur_msg) { | 360 | if (!dws->cur_msg) { |
402 | spi_mask_intr(dws, SPI_INT_TXEI); | 361 | spi_mask_intr(dws, SPI_INT_TXEI); |
403 | /* Never fail */ | ||
404 | return IRQ_HANDLED; | 362 | return IRQ_HANDLED; |
405 | } | 363 | } |
406 | 364 | ||
@@ -410,14 +368,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) | |||
410 | /* Must be called inside pump_transfers() */ | 368 | /* Must be called inside pump_transfers() */ |
411 | static void poll_transfer(struct dw_spi *dws) | 369 | static void poll_transfer(struct dw_spi *dws) |
412 | { | 370 | { |
413 | while (dws->write(dws)) | 371 | do { |
414 | dws->read(dws); | 372 | dw_writer(dws); |
373 | dw_reader(dws); | ||
374 | cpu_relax(); | ||
375 | } while (dws->rx_end > dws->rx); | ||
415 | 376 | ||
416 | transfer_complete(dws); | 377 | dw_spi_xfer_done(dws); |
417 | } | ||
418 | |||
419 | static void dma_transfer(struct dw_spi *dws, int cs_change) | ||
420 | { | ||
421 | } | 378 | } |
422 | 379 | ||
423 | static void pump_transfers(unsigned long data) | 380 | static void pump_transfers(unsigned long data) |
@@ -475,8 +432,6 @@ static void pump_transfers(unsigned long data) | |||
475 | dws->tx_end = dws->tx + transfer->len; | 432 | dws->tx_end = dws->tx + transfer->len; |
476 | dws->rx = transfer->rx_buf; | 433 | dws->rx = transfer->rx_buf; |
477 | dws->rx_end = dws->rx + transfer->len; | 434 | dws->rx_end = dws->rx + transfer->len; |
478 | dws->write = dws->tx ? chip->write : null_writer; | ||
479 | dws->read = dws->rx ? chip->read : null_reader; | ||
480 | dws->cs_change = transfer->cs_change; | 435 | dws->cs_change = transfer->cs_change; |
481 | dws->len = dws->cur_transfer->len; | 436 | dws->len = dws->cur_transfer->len; |
482 | if (chip != dws->prev_chip) | 437 | if (chip != dws->prev_chip) |
@@ -510,20 +465,8 @@ static void pump_transfers(unsigned long data) | |||
510 | 465 | ||
511 | switch (bits) { | 466 | switch (bits) { |
512 | case 8: | 467 | case 8: |
513 | dws->n_bytes = 1; | ||
514 | dws->dma_width = 1; | ||
515 | dws->read = (dws->read != null_reader) ? | ||
516 | u8_reader : null_reader; | ||
517 | dws->write = (dws->write != null_writer) ? | ||
518 | u8_writer : null_writer; | ||
519 | break; | ||
520 | case 16: | 468 | case 16: |
521 | dws->n_bytes = 2; | 469 | dws->n_bytes = dws->dma_width = bits >> 3; |
522 | dws->dma_width = 2; | ||
523 | dws->read = (dws->read != null_reader) ? | ||
524 | u16_reader : null_reader; | ||
525 | dws->write = (dws->write != null_writer) ? | ||
526 | u16_writer : null_writer; | ||
527 | break; | 470 | break; |
528 | default: | 471 | default: |
529 | printk(KERN_ERR "MRST SPI0: unsupported bits:" | 472 | printk(KERN_ERR "MRST SPI0: unsupported bits:" |
@@ -567,7 +510,7 @@ static void pump_transfers(unsigned long data) | |||
567 | txint_level = dws->fifo_len / 2; | 510 | txint_level = dws->fifo_len / 2; |
568 | txint_level = (templen > txint_level) ? txint_level : templen; | 511 | txint_level = (templen > txint_level) ? txint_level : templen; |
569 | 512 | ||
570 | imask |= SPI_INT_TXEI; | 513 | imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI; |
571 | dws->transfer_handler = interrupt_transfer; | 514 | dws->transfer_handler = interrupt_transfer; |
572 | } | 515 | } |
573 | 516 | ||
@@ -586,7 +529,7 @@ static void pump_transfers(unsigned long data) | |||
586 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); | 529 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); |
587 | spi_chip_sel(dws, spi->chip_select); | 530 | spi_chip_sel(dws, spi->chip_select); |
588 | 531 | ||
589 | /* Set the interrupt mask, for poll mode just diable all int */ | 532 | /* Set the interrupt mask, for poll mode just disable all int */ |
590 | spi_mask_intr(dws, 0xff); | 533 | spi_mask_intr(dws, 0xff); |
591 | if (imask) | 534 | if (imask) |
592 | spi_umask_intr(dws, imask); | 535 | spi_umask_intr(dws, imask); |
@@ -599,7 +542,7 @@ static void pump_transfers(unsigned long data) | |||
599 | } | 542 | } |
600 | 543 | ||
601 | if (dws->dma_mapped) | 544 | if (dws->dma_mapped) |
602 | dma_transfer(dws, cs_change); | 545 | dws->dma_ops->dma_transfer(dws, cs_change); |
603 | 546 | ||
604 | if (chip->poll_mode) | 547 | if (chip->poll_mode) |
605 | poll_transfer(dws); | 548 | poll_transfer(dws); |
@@ -725,13 +668,9 @@ static int dw_spi_setup(struct spi_device *spi) | |||
725 | if (spi->bits_per_word <= 8) { | 668 | if (spi->bits_per_word <= 8) { |
726 | chip->n_bytes = 1; | 669 | chip->n_bytes = 1; |
727 | chip->dma_width = 1; | 670 | chip->dma_width = 1; |
728 | chip->read = u8_reader; | ||
729 | chip->write = u8_writer; | ||
730 | } else if (spi->bits_per_word <= 16) { | 671 | } else if (spi->bits_per_word <= 16) { |
731 | chip->n_bytes = 2; | 672 | chip->n_bytes = 2; |
732 | chip->dma_width = 2; | 673 | chip->dma_width = 2; |
733 | chip->read = u16_reader; | ||
734 | chip->write = u16_writer; | ||
735 | } else { | 674 | } else { |
736 | /* Never take >16b case for MRST SPIC */ | 675 | /* Never take >16b case for MRST SPIC */ |
737 | dev_err(&spi->dev, "invalid wordsize\n"); | 676 | dev_err(&spi->dev, "invalid wordsize\n"); |
@@ -813,7 +752,7 @@ static int stop_queue(struct dw_spi *dws) | |||
813 | 752 | ||
814 | spin_lock_irqsave(&dws->lock, flags); | 753 | spin_lock_irqsave(&dws->lock, flags); |
815 | dws->run = QUEUE_STOPPED; | 754 | dws->run = QUEUE_STOPPED; |
816 | while (!list_empty(&dws->queue) && dws->busy && limit--) { | 755 | while ((!list_empty(&dws->queue) || dws->busy) && limit--) { |
817 | spin_unlock_irqrestore(&dws->lock, flags); | 756 | spin_unlock_irqrestore(&dws->lock, flags); |
818 | msleep(10); | 757 | msleep(10); |
819 | spin_lock_irqsave(&dws->lock, flags); | 758 | spin_lock_irqsave(&dws->lock, flags); |
@@ -843,7 +782,6 @@ static void spi_hw_init(struct dw_spi *dws) | |||
843 | spi_enable_chip(dws, 0); | 782 | spi_enable_chip(dws, 0); |
844 | spi_mask_intr(dws, 0xff); | 783 | spi_mask_intr(dws, 0xff); |
845 | spi_enable_chip(dws, 1); | 784 | spi_enable_chip(dws, 1); |
846 | flush(dws); | ||
847 | 785 | ||
848 | /* | 786 | /* |
849 | * Try to detect the FIFO depth if not set by interface driver, | 787 | * Try to detect the FIFO depth if not set by interface driver, |
@@ -895,11 +833,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
895 | master->setup = dw_spi_setup; | 833 | master->setup = dw_spi_setup; |
896 | master->transfer = dw_spi_transfer; | 834 | master->transfer = dw_spi_transfer; |
897 | 835 | ||
898 | dws->dma_inited = 0; | ||
899 | |||
900 | /* Basic HW init */ | 836 | /* Basic HW init */ |
901 | spi_hw_init(dws); | 837 | spi_hw_init(dws); |
902 | 838 | ||
839 | if (dws->dma_ops && dws->dma_ops->dma_init) { | ||
840 | ret = dws->dma_ops->dma_init(dws); | ||
841 | if (ret) { | ||
842 | dev_warn(&master->dev, "DMA init failed\n"); | ||
843 | dws->dma_inited = 0; | ||
844 | } | ||
845 | } | ||
846 | |||
903 | /* Initial and start queue */ | 847 | /* Initial and start queue */ |
904 | ret = init_queue(dws); | 848 | ret = init_queue(dws); |
905 | if (ret) { | 849 | if (ret) { |
@@ -924,6 +868,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
924 | 868 | ||
925 | err_queue_alloc: | 869 | err_queue_alloc: |
926 | destroy_queue(dws); | 870 | destroy_queue(dws); |
871 | if (dws->dma_ops && dws->dma_ops->dma_exit) | ||
872 | dws->dma_ops->dma_exit(dws); | ||
927 | err_diable_hw: | 873 | err_diable_hw: |
928 | spi_enable_chip(dws, 0); | 874 | spi_enable_chip(dws, 0); |
929 | free_irq(dws->irq, dws); | 875 | free_irq(dws->irq, dws); |
@@ -932,7 +878,7 @@ err_free_master: | |||
932 | exit: | 878 | exit: |
933 | return ret; | 879 | return ret; |
934 | } | 880 | } |
935 | EXPORT_SYMBOL(dw_spi_add_host); | 881 | EXPORT_SYMBOL_GPL(dw_spi_add_host); |
936 | 882 | ||
937 | void __devexit dw_spi_remove_host(struct dw_spi *dws) | 883 | void __devexit dw_spi_remove_host(struct dw_spi *dws) |
938 | { | 884 | { |
@@ -948,6 +894,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) | |||
948 | dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " | 894 | dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " |
949 | "complete, message memory not freed\n"); | 895 | "complete, message memory not freed\n"); |
950 | 896 | ||
897 | if (dws->dma_ops && dws->dma_ops->dma_exit) | ||
898 | dws->dma_ops->dma_exit(dws); | ||
951 | spi_enable_chip(dws, 0); | 899 | spi_enable_chip(dws, 0); |
952 | /* Disable clk */ | 900 | /* Disable clk */ |
953 | spi_set_clk(dws, 0); | 901 | spi_set_clk(dws, 0); |
@@ -956,7 +904,7 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) | |||
956 | /* Disconnect from the SPI framework */ | 904 | /* Disconnect from the SPI framework */ |
957 | spi_unregister_master(dws->master); | 905 | spi_unregister_master(dws->master); |
958 | } | 906 | } |
959 | EXPORT_SYMBOL(dw_spi_remove_host); | 907 | EXPORT_SYMBOL_GPL(dw_spi_remove_host); |
960 | 908 | ||
961 | int dw_spi_suspend_host(struct dw_spi *dws) | 909 | int dw_spi_suspend_host(struct dw_spi *dws) |
962 | { | 910 | { |
@@ -969,7 +917,7 @@ int dw_spi_suspend_host(struct dw_spi *dws) | |||
969 | spi_set_clk(dws, 0); | 917 | spi_set_clk(dws, 0); |
970 | return ret; | 918 | return ret; |
971 | } | 919 | } |
972 | EXPORT_SYMBOL(dw_spi_suspend_host); | 920 | EXPORT_SYMBOL_GPL(dw_spi_suspend_host); |
973 | 921 | ||
974 | int dw_spi_resume_host(struct dw_spi *dws) | 922 | int dw_spi_resume_host(struct dw_spi *dws) |
975 | { | 923 | { |
@@ -981,7 +929,7 @@ int dw_spi_resume_host(struct dw_spi *dws) | |||
981 | dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); | 929 | dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); |
982 | return ret; | 930 | return ret; |
983 | } | 931 | } |
984 | EXPORT_SYMBOL(dw_spi_resume_host); | 932 | EXPORT_SYMBOL_GPL(dw_spi_resume_host); |
985 | 933 | ||
986 | MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); | 934 | MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); |
987 | MODULE_DESCRIPTION("Driver for DesignWare SPI controller core"); | 935 | MODULE_DESCRIPTION("Driver for DesignWare SPI controller core"); |