diff options
Diffstat (limited to 'drivers/spi/omap2_mcspi.c')
-rw-r--r-- | drivers/spi/omap2_mcspi.c | 385 |
1 files changed, 172 insertions, 213 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index b3a94ca0a75a..969cdd2fe124 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2005, 2006 Nokia Corporation | 4 | * Copyright (C) 2005, 2006 Nokia Corporation |
5 | * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and | 5 | * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and |
6 | * Juha Yrjölä <juha.yrjola@nokia.com> | 6 | * Juha Yrj�l� <juha.yrjola@nokia.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/clk.h> | 33 | #include <linux/clk.h> |
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/pm_runtime.h> | ||
36 | 37 | ||
37 | #include <linux/spi/spi.h> | 38 | #include <linux/spi/spi.h> |
38 | 39 | ||
@@ -46,7 +47,6 @@ | |||
46 | #define OMAP2_MCSPI_MAX_CTRL 4 | 47 | #define OMAP2_MCSPI_MAX_CTRL 4 |
47 | 48 | ||
48 | #define OMAP2_MCSPI_REVISION 0x00 | 49 | #define OMAP2_MCSPI_REVISION 0x00 |
49 | #define OMAP2_MCSPI_SYSCONFIG 0x10 | ||
50 | #define OMAP2_MCSPI_SYSSTATUS 0x14 | 50 | #define OMAP2_MCSPI_SYSSTATUS 0x14 |
51 | #define OMAP2_MCSPI_IRQSTATUS 0x18 | 51 | #define OMAP2_MCSPI_IRQSTATUS 0x18 |
52 | #define OMAP2_MCSPI_IRQENABLE 0x1c | 52 | #define OMAP2_MCSPI_IRQENABLE 0x1c |
@@ -63,13 +63,6 @@ | |||
63 | 63 | ||
64 | /* per-register bitmasks: */ | 64 | /* per-register bitmasks: */ |
65 | 65 | ||
66 | #define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE BIT(4) | ||
67 | #define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2) | ||
68 | #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE BIT(0) | ||
69 | #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET BIT(1) | ||
70 | |||
71 | #define OMAP2_MCSPI_SYSSTATUS_RESETDONE BIT(0) | ||
72 | |||
73 | #define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) | 66 | #define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) |
74 | #define OMAP2_MCSPI_MODULCTRL_MS BIT(2) | 67 | #define OMAP2_MCSPI_MODULCTRL_MS BIT(2) |
75 | #define OMAP2_MCSPI_MODULCTRL_STEST BIT(3) | 68 | #define OMAP2_MCSPI_MODULCTRL_STEST BIT(3) |
@@ -122,13 +115,12 @@ struct omap2_mcspi { | |||
122 | spinlock_t lock; | 115 | spinlock_t lock; |
123 | struct list_head msg_queue; | 116 | struct list_head msg_queue; |
124 | struct spi_master *master; | 117 | struct spi_master *master; |
125 | struct clk *ick; | ||
126 | struct clk *fck; | ||
127 | /* Virtual base address of the controller */ | 118 | /* Virtual base address of the controller */ |
128 | void __iomem *base; | 119 | void __iomem *base; |
129 | unsigned long phys; | 120 | unsigned long phys; |
130 | /* SPI1 has 4 channels, while SPI2 has 2 */ | 121 | /* SPI1 has 4 channels, while SPI2 has 2 */ |
131 | struct omap2_mcspi_dma *dma_channels; | 122 | struct omap2_mcspi_dma *dma_channels; |
123 | struct device *dev; | ||
132 | }; | 124 | }; |
133 | 125 | ||
134 | struct omap2_mcspi_cs { | 126 | struct omap2_mcspi_cs { |
@@ -144,7 +136,6 @@ struct omap2_mcspi_cs { | |||
144 | * corresponding registers are modified. | 136 | * corresponding registers are modified. |
145 | */ | 137 | */ |
146 | struct omap2_mcspi_regs { | 138 | struct omap2_mcspi_regs { |
147 | u32 sysconfig; | ||
148 | u32 modulctrl; | 139 | u32 modulctrl; |
149 | u32 wakeupenable; | 140 | u32 wakeupenable; |
150 | struct list_head cs; | 141 | struct list_head cs; |
@@ -268,9 +259,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) | |||
268 | mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, | 259 | mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, |
269 | omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl); | 260 | omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl); |
270 | 261 | ||
271 | mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG, | ||
272 | omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig); | ||
273 | |||
274 | mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, | 262 | mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, |
275 | omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable); | 263 | omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable); |
276 | 264 | ||
@@ -280,19 +268,24 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) | |||
280 | } | 268 | } |
281 | static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) | 269 | static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) |
282 | { | 270 | { |
283 | clk_disable(mcspi->ick); | 271 | pm_runtime_put_sync(mcspi->dev); |
284 | clk_disable(mcspi->fck); | ||
285 | } | 272 | } |
286 | 273 | ||
287 | static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) | 274 | static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) |
288 | { | 275 | { |
289 | if (clk_enable(mcspi->ick)) | 276 | return pm_runtime_get_sync(mcspi->dev); |
290 | return -ENODEV; | 277 | } |
291 | if (clk_enable(mcspi->fck)) | ||
292 | return -ENODEV; | ||
293 | 278 | ||
294 | omap2_mcspi_restore_ctx(mcspi); | 279 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) |
280 | { | ||
281 | unsigned long timeout; | ||
295 | 282 | ||
283 | timeout = jiffies + msecs_to_jiffies(1000); | ||
284 | while (!(__raw_readl(reg) & bit)) { | ||
285 | if (time_after(jiffies, timeout)) | ||
286 | return -1; | ||
287 | cpu_relax(); | ||
288 | } | ||
296 | return 0; | 289 | return 0; |
297 | } | 290 | } |
298 | 291 | ||
@@ -305,15 +298,18 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
305 | unsigned int count, c; | 298 | unsigned int count, c; |
306 | unsigned long base, tx_reg, rx_reg; | 299 | unsigned long base, tx_reg, rx_reg; |
307 | int word_len, data_type, element_count; | 300 | int word_len, data_type, element_count; |
308 | int elements; | 301 | int elements = 0; |
309 | u32 l; | 302 | u32 l; |
310 | u8 * rx; | 303 | u8 * rx; |
311 | const u8 * tx; | 304 | const u8 * tx; |
305 | void __iomem *chstat_reg; | ||
312 | 306 | ||
313 | mcspi = spi_master_get_devdata(spi->master); | 307 | mcspi = spi_master_get_devdata(spi->master); |
314 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; | 308 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; |
315 | l = mcspi_cached_chconf0(spi); | 309 | l = mcspi_cached_chconf0(spi); |
316 | 310 | ||
311 | chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; | ||
312 | |||
317 | count = xfer->len; | 313 | count = xfer->len; |
318 | c = count; | 314 | c = count; |
319 | word_len = cs->word_len; | 315 | word_len = cs->word_len; |
@@ -381,12 +377,22 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
381 | 377 | ||
382 | if (tx != NULL) { | 378 | if (tx != NULL) { |
383 | wait_for_completion(&mcspi_dma->dma_tx_completion); | 379 | wait_for_completion(&mcspi_dma->dma_tx_completion); |
384 | dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE); | 380 | dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE); |
381 | |||
382 | /* for TX_ONLY mode, be sure all words have shifted out */ | ||
383 | if (rx == NULL) { | ||
384 | if (mcspi_wait_for_reg_bit(chstat_reg, | ||
385 | OMAP2_MCSPI_CHSTAT_TXS) < 0) | ||
386 | dev_err(&spi->dev, "TXS timed out\n"); | ||
387 | else if (mcspi_wait_for_reg_bit(chstat_reg, | ||
388 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | ||
389 | dev_err(&spi->dev, "EOT timed out\n"); | ||
390 | } | ||
385 | } | 391 | } |
386 | 392 | ||
387 | if (rx != NULL) { | 393 | if (rx != NULL) { |
388 | wait_for_completion(&mcspi_dma->dma_rx_completion); | 394 | wait_for_completion(&mcspi_dma->dma_rx_completion); |
389 | dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE); | 395 | dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); |
390 | omap2_mcspi_set_enable(spi, 0); | 396 | omap2_mcspi_set_enable(spi, 0); |
391 | 397 | ||
392 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { | 398 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { |
@@ -435,19 +441,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
435 | return count; | 441 | return count; |
436 | } | 442 | } |
437 | 443 | ||
438 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) | ||
439 | { | ||
440 | unsigned long timeout; | ||
441 | |||
442 | timeout = jiffies + msecs_to_jiffies(1000); | ||
443 | while (!(__raw_readl(reg) & bit)) { | ||
444 | if (time_after(jiffies, timeout)) | ||
445 | return -1; | ||
446 | cpu_relax(); | ||
447 | } | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static unsigned | 444 | static unsigned |
452 | omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | 445 | omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) |
453 | { | 446 | { |
@@ -474,6 +467,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
474 | rx_reg = base + OMAP2_MCSPI_RX0; | 467 | rx_reg = base + OMAP2_MCSPI_RX0; |
475 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; | 468 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; |
476 | 469 | ||
470 | if (c < (word_len>>3)) | ||
471 | return 0; | ||
472 | |||
477 | if (word_len <= 8) { | 473 | if (word_len <= 8) { |
478 | u8 *rx; | 474 | u8 *rx; |
479 | const u8 *tx; | 475 | const u8 *tx; |
@@ -489,10 +485,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
489 | dev_err(&spi->dev, "TXS timed out\n"); | 485 | dev_err(&spi->dev, "TXS timed out\n"); |
490 | goto out; | 486 | goto out; |
491 | } | 487 | } |
492 | #ifdef VERBOSE | 488 | dev_vdbg(&spi->dev, "write-%d %02x\n", |
493 | dev_dbg(&spi->dev, "write-%d %02x\n", | ||
494 | word_len, *tx); | 489 | word_len, *tx); |
495 | #endif | ||
496 | __raw_writel(*tx++, tx_reg); | 490 | __raw_writel(*tx++, tx_reg); |
497 | } | 491 | } |
498 | if (rx != NULL) { | 492 | if (rx != NULL) { |
@@ -506,10 +500,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
506 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 500 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
507 | omap2_mcspi_set_enable(spi, 0); | 501 | omap2_mcspi_set_enable(spi, 0); |
508 | *rx++ = __raw_readl(rx_reg); | 502 | *rx++ = __raw_readl(rx_reg); |
509 | #ifdef VERBOSE | 503 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
510 | dev_dbg(&spi->dev, "read-%d %02x\n", | ||
511 | word_len, *(rx - 1)); | 504 | word_len, *(rx - 1)); |
512 | #endif | ||
513 | if (mcspi_wait_for_reg_bit(chstat_reg, | 505 | if (mcspi_wait_for_reg_bit(chstat_reg, |
514 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 506 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
515 | dev_err(&spi->dev, | 507 | dev_err(&spi->dev, |
@@ -522,10 +514,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
522 | } | 514 | } |
523 | 515 | ||
524 | *rx++ = __raw_readl(rx_reg); | 516 | *rx++ = __raw_readl(rx_reg); |
525 | #ifdef VERBOSE | 517 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
526 | dev_dbg(&spi->dev, "read-%d %02x\n", | ||
527 | word_len, *(rx - 1)); | 518 | word_len, *(rx - 1)); |
528 | #endif | ||
529 | } | 519 | } |
530 | } while (c); | 520 | } while (c); |
531 | } else if (word_len <= 16) { | 521 | } else if (word_len <= 16) { |
@@ -542,10 +532,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
542 | dev_err(&spi->dev, "TXS timed out\n"); | 532 | dev_err(&spi->dev, "TXS timed out\n"); |
543 | goto out; | 533 | goto out; |
544 | } | 534 | } |
545 | #ifdef VERBOSE | 535 | dev_vdbg(&spi->dev, "write-%d %04x\n", |
546 | dev_dbg(&spi->dev, "write-%d %04x\n", | ||
547 | word_len, *tx); | 536 | word_len, *tx); |
548 | #endif | ||
549 | __raw_writel(*tx++, tx_reg); | 537 | __raw_writel(*tx++, tx_reg); |
550 | } | 538 | } |
551 | if (rx != NULL) { | 539 | if (rx != NULL) { |
@@ -559,10 +547,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
559 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 547 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
560 | omap2_mcspi_set_enable(spi, 0); | 548 | omap2_mcspi_set_enable(spi, 0); |
561 | *rx++ = __raw_readl(rx_reg); | 549 | *rx++ = __raw_readl(rx_reg); |
562 | #ifdef VERBOSE | 550 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
563 | dev_dbg(&spi->dev, "read-%d %04x\n", | ||
564 | word_len, *(rx - 1)); | 551 | word_len, *(rx - 1)); |
565 | #endif | ||
566 | if (mcspi_wait_for_reg_bit(chstat_reg, | 552 | if (mcspi_wait_for_reg_bit(chstat_reg, |
567 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 553 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
568 | dev_err(&spi->dev, | 554 | dev_err(&spi->dev, |
@@ -575,12 +561,10 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
575 | } | 561 | } |
576 | 562 | ||
577 | *rx++ = __raw_readl(rx_reg); | 563 | *rx++ = __raw_readl(rx_reg); |
578 | #ifdef VERBOSE | 564 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
579 | dev_dbg(&spi->dev, "read-%d %04x\n", | ||
580 | word_len, *(rx - 1)); | 565 | word_len, *(rx - 1)); |
581 | #endif | ||
582 | } | 566 | } |
583 | } while (c); | 567 | } while (c >= 2); |
584 | } else if (word_len <= 32) { | 568 | } else if (word_len <= 32) { |
585 | u32 *rx; | 569 | u32 *rx; |
586 | const u32 *tx; | 570 | const u32 *tx; |
@@ -595,10 +579,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
595 | dev_err(&spi->dev, "TXS timed out\n"); | 579 | dev_err(&spi->dev, "TXS timed out\n"); |
596 | goto out; | 580 | goto out; |
597 | } | 581 | } |
598 | #ifdef VERBOSE | 582 | dev_vdbg(&spi->dev, "write-%d %08x\n", |
599 | dev_dbg(&spi->dev, "write-%d %08x\n", | ||
600 | word_len, *tx); | 583 | word_len, *tx); |
601 | #endif | ||
602 | __raw_writel(*tx++, tx_reg); | 584 | __raw_writel(*tx++, tx_reg); |
603 | } | 585 | } |
604 | if (rx != NULL) { | 586 | if (rx != NULL) { |
@@ -612,10 +594,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
612 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 594 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
613 | omap2_mcspi_set_enable(spi, 0); | 595 | omap2_mcspi_set_enable(spi, 0); |
614 | *rx++ = __raw_readl(rx_reg); | 596 | *rx++ = __raw_readl(rx_reg); |
615 | #ifdef VERBOSE | 597 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
616 | dev_dbg(&spi->dev, "read-%d %08x\n", | ||
617 | word_len, *(rx - 1)); | 598 | word_len, *(rx - 1)); |
618 | #endif | ||
619 | if (mcspi_wait_for_reg_bit(chstat_reg, | 599 | if (mcspi_wait_for_reg_bit(chstat_reg, |
620 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 600 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
621 | dev_err(&spi->dev, | 601 | dev_err(&spi->dev, |
@@ -628,12 +608,10 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
628 | } | 608 | } |
629 | 609 | ||
630 | *rx++ = __raw_readl(rx_reg); | 610 | *rx++ = __raw_readl(rx_reg); |
631 | #ifdef VERBOSE | 611 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
632 | dev_dbg(&spi->dev, "read-%d %08x\n", | ||
633 | word_len, *(rx - 1)); | 612 | word_len, *(rx - 1)); |
634 | #endif | ||
635 | } | 613 | } |
636 | } while (c); | 614 | } while (c >= 4); |
637 | } | 615 | } |
638 | 616 | ||
639 | /* for TX_ONLY mode, be sure all words have shifted out */ | 617 | /* for TX_ONLY mode, be sure all words have shifted out */ |
@@ -644,12 +622,29 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
644 | } else if (mcspi_wait_for_reg_bit(chstat_reg, | 622 | } else if (mcspi_wait_for_reg_bit(chstat_reg, |
645 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | 623 | OMAP2_MCSPI_CHSTAT_EOT) < 0) |
646 | dev_err(&spi->dev, "EOT timed out\n"); | 624 | dev_err(&spi->dev, "EOT timed out\n"); |
625 | |||
626 | /* disable chan to purge rx datas received in TX_ONLY transfer, | ||
627 | * otherwise these rx datas will affect the direct following | ||
628 | * RX_ONLY transfer. | ||
629 | */ | ||
630 | omap2_mcspi_set_enable(spi, 0); | ||
647 | } | 631 | } |
648 | out: | 632 | out: |
649 | omap2_mcspi_set_enable(spi, 1); | 633 | omap2_mcspi_set_enable(spi, 1); |
650 | return count - c; | 634 | return count - c; |
651 | } | 635 | } |
652 | 636 | ||
637 | static u32 omap2_mcspi_calc_divisor(u32 speed_hz) | ||
638 | { | ||
639 | u32 div; | ||
640 | |||
641 | for (div = 0; div < 15; div++) | ||
642 | if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) | ||
643 | return div; | ||
644 | |||
645 | return 15; | ||
646 | } | ||
647 | |||
653 | /* called only when no transfer is active to this device */ | 648 | /* called only when no transfer is active to this device */ |
654 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, | 649 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, |
655 | struct spi_transfer *t) | 650 | struct spi_transfer *t) |
@@ -672,12 +667,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
672 | if (t && t->speed_hz) | 667 | if (t && t->speed_hz) |
673 | speed_hz = t->speed_hz; | 668 | speed_hz = t->speed_hz; |
674 | 669 | ||
675 | if (speed_hz) { | 670 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); |
676 | while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div)) | 671 | div = omap2_mcspi_calc_divisor(speed_hz); |
677 | > speed_hz) | ||
678 | div++; | ||
679 | } else | ||
680 | div = 15; | ||
681 | 672 | ||
682 | l = mcspi_cached_chconf0(spi); | 673 | l = mcspi_cached_chconf0(spi); |
683 | 674 | ||
@@ -714,7 +705,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
714 | mcspi_write_chconf0(spi, l); | 705 | mcspi_write_chconf0(spi, l); |
715 | 706 | ||
716 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", | 707 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", |
717 | OMAP2_MCSPI_MAX_FREQ / (1 << div), | 708 | OMAP2_MCSPI_MAX_FREQ >> div, |
718 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", | 709 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", |
719 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); | 710 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); |
720 | 711 | ||
@@ -818,8 +809,9 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
818 | return ret; | 809 | return ret; |
819 | } | 810 | } |
820 | 811 | ||
821 | if (omap2_mcspi_enable_clocks(mcspi)) | 812 | ret = omap2_mcspi_enable_clocks(mcspi); |
822 | return -ENODEV; | 813 | if (ret < 0) |
814 | return ret; | ||
823 | 815 | ||
824 | ret = omap2_mcspi_setup_transfer(spi, NULL); | 816 | ret = omap2_mcspi_setup_transfer(spi, NULL); |
825 | omap2_mcspi_disable_clocks(mcspi); | 817 | omap2_mcspi_disable_clocks(mcspi); |
@@ -862,10 +854,11 @@ static void omap2_mcspi_work(struct work_struct *work) | |||
862 | struct omap2_mcspi *mcspi; | 854 | struct omap2_mcspi *mcspi; |
863 | 855 | ||
864 | mcspi = container_of(work, struct omap2_mcspi, work); | 856 | mcspi = container_of(work, struct omap2_mcspi, work); |
865 | spin_lock_irq(&mcspi->lock); | ||
866 | 857 | ||
867 | if (omap2_mcspi_enable_clocks(mcspi)) | 858 | if (omap2_mcspi_enable_clocks(mcspi) < 0) |
868 | goto out; | 859 | return; |
860 | |||
861 | spin_lock_irq(&mcspi->lock); | ||
869 | 862 | ||
870 | /* We only enable one channel at a time -- the one whose message is | 863 | /* We only enable one channel at a time -- the one whose message is |
871 | * at the head of the queue -- although this controller would gladly | 864 | * at the head of the queue -- although this controller would gladly |
@@ -978,10 +971,9 @@ static void omap2_mcspi_work(struct work_struct *work) | |||
978 | spin_lock_irq(&mcspi->lock); | 971 | spin_lock_irq(&mcspi->lock); |
979 | } | 972 | } |
980 | 973 | ||
981 | omap2_mcspi_disable_clocks(mcspi); | ||
982 | |||
983 | out: | ||
984 | spin_unlock_irq(&mcspi->lock); | 974 | spin_unlock_irq(&mcspi->lock); |
975 | |||
976 | omap2_mcspi_disable_clocks(mcspi); | ||
985 | } | 977 | } |
986 | 978 | ||
987 | static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | 979 | static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) |
@@ -1014,21 +1006,16 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
1014 | t->bits_per_word); | 1006 | t->bits_per_word); |
1015 | return -EINVAL; | 1007 | return -EINVAL; |
1016 | } | 1008 | } |
1017 | if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) { | 1009 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { |
1018 | dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", | 1010 | dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n", |
1019 | t->speed_hz, | 1011 | t->speed_hz, |
1020 | OMAP2_MCSPI_MAX_FREQ/(1<<16)); | 1012 | OMAP2_MCSPI_MAX_FREQ >> 15); |
1021 | return -EINVAL; | 1013 | return -EINVAL; |
1022 | } | 1014 | } |
1023 | 1015 | ||
1024 | if (m->is_dma_mapped || len < DMA_MIN_BYTES) | 1016 | if (m->is_dma_mapped || len < DMA_MIN_BYTES) |
1025 | continue; | 1017 | continue; |
1026 | 1018 | ||
1027 | /* Do DMA mapping "early" for better error reporting and | ||
1028 | * dcache use. Note that if dma_unmap_single() ever starts | ||
1029 | * to do real work on ARM, we'd need to clean up mappings | ||
1030 | * for previous transfers on *ALL* exits of this loop... | ||
1031 | */ | ||
1032 | if (tx_buf != NULL) { | 1019 | if (tx_buf != NULL) { |
1033 | t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf, | 1020 | t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf, |
1034 | len, DMA_TO_DEVICE); | 1021 | len, DMA_TO_DEVICE); |
@@ -1045,7 +1032,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
1045 | dev_dbg(&spi->dev, "dma %cX %d bytes error\n", | 1032 | dev_dbg(&spi->dev, "dma %cX %d bytes error\n", |
1046 | 'R', len); | 1033 | 'R', len); |
1047 | if (tx_buf != NULL) | 1034 | if (tx_buf != NULL) |
1048 | dma_unmap_single(NULL, t->tx_dma, | 1035 | dma_unmap_single(&spi->dev, t->tx_dma, |
1049 | len, DMA_TO_DEVICE); | 1036 | len, DMA_TO_DEVICE); |
1050 | return -EINVAL; | 1037 | return -EINVAL; |
1051 | } | 1038 | } |
@@ -1062,25 +1049,15 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
1062 | return 0; | 1049 | return 0; |
1063 | } | 1050 | } |
1064 | 1051 | ||
1065 | static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) | 1052 | static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) |
1066 | { | 1053 | { |
1067 | struct spi_master *master = mcspi->master; | 1054 | struct spi_master *master = mcspi->master; |
1068 | u32 tmp; | 1055 | u32 tmp; |
1056 | int ret = 0; | ||
1069 | 1057 | ||
1070 | if (omap2_mcspi_enable_clocks(mcspi)) | 1058 | ret = omap2_mcspi_enable_clocks(mcspi); |
1071 | return -1; | 1059 | if (ret < 0) |
1072 | 1060 | return ret; | |
1073 | mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, | ||
1074 | OMAP2_MCSPI_SYSCONFIG_SOFTRESET); | ||
1075 | do { | ||
1076 | tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS); | ||
1077 | } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE)); | ||
1078 | |||
1079 | tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | | ||
1080 | OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | | ||
1081 | OMAP2_MCSPI_SYSCONFIG_SMARTIDLE; | ||
1082 | mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp); | ||
1083 | omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp; | ||
1084 | 1061 | ||
1085 | tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN; | 1062 | tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN; |
1086 | mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp); | 1063 | mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp); |
@@ -1091,91 +1068,26 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) | |||
1091 | return 0; | 1068 | return 0; |
1092 | } | 1069 | } |
1093 | 1070 | ||
1094 | static u8 __initdata spi1_rxdma_id [] = { | 1071 | static int omap_mcspi_runtime_resume(struct device *dev) |
1095 | OMAP24XX_DMA_SPI1_RX0, | 1072 | { |
1096 | OMAP24XX_DMA_SPI1_RX1, | 1073 | struct omap2_mcspi *mcspi; |
1097 | OMAP24XX_DMA_SPI1_RX2, | 1074 | struct spi_master *master; |
1098 | OMAP24XX_DMA_SPI1_RX3, | ||
1099 | }; | ||
1100 | |||
1101 | static u8 __initdata spi1_txdma_id [] = { | ||
1102 | OMAP24XX_DMA_SPI1_TX0, | ||
1103 | OMAP24XX_DMA_SPI1_TX1, | ||
1104 | OMAP24XX_DMA_SPI1_TX2, | ||
1105 | OMAP24XX_DMA_SPI1_TX3, | ||
1106 | }; | ||
1107 | |||
1108 | static u8 __initdata spi2_rxdma_id[] = { | ||
1109 | OMAP24XX_DMA_SPI2_RX0, | ||
1110 | OMAP24XX_DMA_SPI2_RX1, | ||
1111 | }; | ||
1112 | |||
1113 | static u8 __initdata spi2_txdma_id[] = { | ||
1114 | OMAP24XX_DMA_SPI2_TX0, | ||
1115 | OMAP24XX_DMA_SPI2_TX1, | ||
1116 | }; | ||
1117 | |||
1118 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \ | ||
1119 | || defined(CONFIG_ARCH_OMAP4) | ||
1120 | static u8 __initdata spi3_rxdma_id[] = { | ||
1121 | OMAP24XX_DMA_SPI3_RX0, | ||
1122 | OMAP24XX_DMA_SPI3_RX1, | ||
1123 | }; | ||
1124 | 1075 | ||
1125 | static u8 __initdata spi3_txdma_id[] = { | 1076 | master = dev_get_drvdata(dev); |
1126 | OMAP24XX_DMA_SPI3_TX0, | 1077 | mcspi = spi_master_get_devdata(master); |
1127 | OMAP24XX_DMA_SPI3_TX1, | 1078 | omap2_mcspi_restore_ctx(mcspi); |
1128 | }; | ||
1129 | #endif | ||
1130 | 1079 | ||
1131 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) | 1080 | return 0; |
1132 | static u8 __initdata spi4_rxdma_id[] = { | 1081 | } |
1133 | OMAP34XX_DMA_SPI4_RX0, | ||
1134 | }; | ||
1135 | 1082 | ||
1136 | static u8 __initdata spi4_txdma_id[] = { | ||
1137 | OMAP34XX_DMA_SPI4_TX0, | ||
1138 | }; | ||
1139 | #endif | ||
1140 | 1083 | ||
1141 | static int __init omap2_mcspi_probe(struct platform_device *pdev) | 1084 | static int __init omap2_mcspi_probe(struct platform_device *pdev) |
1142 | { | 1085 | { |
1143 | struct spi_master *master; | 1086 | struct spi_master *master; |
1087 | struct omap2_mcspi_platform_config *pdata = pdev->dev.platform_data; | ||
1144 | struct omap2_mcspi *mcspi; | 1088 | struct omap2_mcspi *mcspi; |
1145 | struct resource *r; | 1089 | struct resource *r; |
1146 | int status = 0, i; | 1090 | int status = 0, i; |
1147 | const u8 *rxdma_id, *txdma_id; | ||
1148 | unsigned num_chipselect; | ||
1149 | |||
1150 | switch (pdev->id) { | ||
1151 | case 1: | ||
1152 | rxdma_id = spi1_rxdma_id; | ||
1153 | txdma_id = spi1_txdma_id; | ||
1154 | num_chipselect = 4; | ||
1155 | break; | ||
1156 | case 2: | ||
1157 | rxdma_id = spi2_rxdma_id; | ||
1158 | txdma_id = spi2_txdma_id; | ||
1159 | num_chipselect = 2; | ||
1160 | break; | ||
1161 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \ | ||
1162 | || defined(CONFIG_ARCH_OMAP4) | ||
1163 | case 3: | ||
1164 | rxdma_id = spi3_rxdma_id; | ||
1165 | txdma_id = spi3_txdma_id; | ||
1166 | num_chipselect = 2; | ||
1167 | break; | ||
1168 | #endif | ||
1169 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) | ||
1170 | case 4: | ||
1171 | rxdma_id = spi4_rxdma_id; | ||
1172 | txdma_id = spi4_txdma_id; | ||
1173 | num_chipselect = 1; | ||
1174 | break; | ||
1175 | #endif | ||
1176 | default: | ||
1177 | return -EINVAL; | ||
1178 | } | ||
1179 | 1091 | ||
1180 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); | 1092 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); |
1181 | if (master == NULL) { | 1093 | if (master == NULL) { |
@@ -1192,7 +1104,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1192 | master->setup = omap2_mcspi_setup; | 1104 | master->setup = omap2_mcspi_setup; |
1193 | master->transfer = omap2_mcspi_transfer; | 1105 | master->transfer = omap2_mcspi_transfer; |
1194 | master->cleanup = omap2_mcspi_cleanup; | 1106 | master->cleanup = omap2_mcspi_cleanup; |
1195 | master->num_chipselect = num_chipselect; | 1107 | master->num_chipselect = pdata->num_cs; |
1196 | 1108 | ||
1197 | dev_set_drvdata(&pdev->dev, master); | 1109 | dev_set_drvdata(&pdev->dev, master); |
1198 | 1110 | ||
@@ -1210,49 +1122,62 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1210 | goto err1; | 1122 | goto err1; |
1211 | } | 1123 | } |
1212 | 1124 | ||
1125 | r->start += pdata->regs_offset; | ||
1126 | r->end += pdata->regs_offset; | ||
1213 | mcspi->phys = r->start; | 1127 | mcspi->phys = r->start; |
1214 | mcspi->base = ioremap(r->start, r->end - r->start + 1); | 1128 | mcspi->base = ioremap(r->start, r->end - r->start + 1); |
1215 | if (!mcspi->base) { | 1129 | if (!mcspi->base) { |
1216 | dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); | 1130 | dev_dbg(&pdev->dev, "can't ioremap MCSPI\n"); |
1217 | status = -ENOMEM; | 1131 | status = -ENOMEM; |
1218 | goto err1aa; | 1132 | goto err2; |
1219 | } | 1133 | } |
1220 | 1134 | ||
1135 | mcspi->dev = &pdev->dev; | ||
1221 | INIT_WORK(&mcspi->work, omap2_mcspi_work); | 1136 | INIT_WORK(&mcspi->work, omap2_mcspi_work); |
1222 | 1137 | ||
1223 | spin_lock_init(&mcspi->lock); | 1138 | spin_lock_init(&mcspi->lock); |
1224 | INIT_LIST_HEAD(&mcspi->msg_queue); | 1139 | INIT_LIST_HEAD(&mcspi->msg_queue); |
1225 | INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs); | 1140 | INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs); |
1226 | 1141 | ||
1227 | mcspi->ick = clk_get(&pdev->dev, "ick"); | ||
1228 | if (IS_ERR(mcspi->ick)) { | ||
1229 | dev_dbg(&pdev->dev, "can't get mcspi_ick\n"); | ||
1230 | status = PTR_ERR(mcspi->ick); | ||
1231 | goto err1a; | ||
1232 | } | ||
1233 | mcspi->fck = clk_get(&pdev->dev, "fck"); | ||
1234 | if (IS_ERR(mcspi->fck)) { | ||
1235 | dev_dbg(&pdev->dev, "can't get mcspi_fck\n"); | ||
1236 | status = PTR_ERR(mcspi->fck); | ||
1237 | goto err2; | ||
1238 | } | ||
1239 | |||
1240 | mcspi->dma_channels = kcalloc(master->num_chipselect, | 1142 | mcspi->dma_channels = kcalloc(master->num_chipselect, |
1241 | sizeof(struct omap2_mcspi_dma), | 1143 | sizeof(struct omap2_mcspi_dma), |
1242 | GFP_KERNEL); | 1144 | GFP_KERNEL); |
1243 | 1145 | ||
1244 | if (mcspi->dma_channels == NULL) | 1146 | if (mcspi->dma_channels == NULL) |
1245 | goto err3; | 1147 | goto err2; |
1148 | |||
1149 | for (i = 0; i < master->num_chipselect; i++) { | ||
1150 | char dma_ch_name[14]; | ||
1151 | struct resource *dma_res; | ||
1152 | |||
1153 | sprintf(dma_ch_name, "rx%d", i); | ||
1154 | dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, | ||
1155 | dma_ch_name); | ||
1156 | if (!dma_res) { | ||
1157 | dev_dbg(&pdev->dev, "cannot get DMA RX channel\n"); | ||
1158 | status = -ENODEV; | ||
1159 | break; | ||
1160 | } | ||
1246 | 1161 | ||
1247 | for (i = 0; i < num_chipselect; i++) { | ||
1248 | mcspi->dma_channels[i].dma_rx_channel = -1; | 1162 | mcspi->dma_channels[i].dma_rx_channel = -1; |
1249 | mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i]; | 1163 | mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; |
1164 | sprintf(dma_ch_name, "tx%d", i); | ||
1165 | dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, | ||
1166 | dma_ch_name); | ||
1167 | if (!dma_res) { | ||
1168 | dev_dbg(&pdev->dev, "cannot get DMA TX channel\n"); | ||
1169 | status = -ENODEV; | ||
1170 | break; | ||
1171 | } | ||
1172 | |||
1250 | mcspi->dma_channels[i].dma_tx_channel = -1; | 1173 | mcspi->dma_channels[i].dma_tx_channel = -1; |
1251 | mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i]; | 1174 | mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; |
1252 | } | 1175 | } |
1253 | 1176 | ||
1254 | if (omap2_mcspi_reset(mcspi) < 0) | 1177 | pm_runtime_enable(&pdev->dev); |
1255 | goto err4; | 1178 | |
1179 | if (status || omap2_mcspi_master_setup(mcspi) < 0) | ||
1180 | goto err3; | ||
1256 | 1181 | ||
1257 | status = spi_register_master(master); | 1182 | status = spi_register_master(master); |
1258 | if (status < 0) | 1183 | if (status < 0) |
@@ -1261,17 +1186,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
1261 | return status; | 1186 | return status; |
1262 | 1187 | ||
1263 | err4: | 1188 | err4: |
1264 | kfree(mcspi->dma_channels); | 1189 | spi_master_put(master); |
1265 | err3: | 1190 | err3: |
1266 | clk_put(mcspi->fck); | 1191 | kfree(mcspi->dma_channels); |
1267 | err2: | 1192 | err2: |
1268 | clk_put(mcspi->ick); | ||
1269 | err1a: | ||
1270 | iounmap(mcspi->base); | ||
1271 | err1aa: | ||
1272 | release_mem_region(r->start, (r->end - r->start) + 1); | 1193 | release_mem_region(r->start, (r->end - r->start) + 1); |
1194 | iounmap(mcspi->base); | ||
1273 | err1: | 1195 | err1: |
1274 | spi_master_put(master); | ||
1275 | return status; | 1196 | return status; |
1276 | } | 1197 | } |
1277 | 1198 | ||
@@ -1287,9 +1208,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1287 | mcspi = spi_master_get_devdata(master); | 1208 | mcspi = spi_master_get_devdata(master); |
1288 | dma_channels = mcspi->dma_channels; | 1209 | dma_channels = mcspi->dma_channels; |
1289 | 1210 | ||
1290 | clk_put(mcspi->fck); | 1211 | omap2_mcspi_disable_clocks(mcspi); |
1291 | clk_put(mcspi->ick); | ||
1292 | |||
1293 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1212 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1294 | release_mem_region(r->start, (r->end - r->start) + 1); | 1213 | release_mem_region(r->start, (r->end - r->start) + 1); |
1295 | 1214 | ||
@@ -1304,10 +1223,50 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) | |||
1304 | /* work with hotplug and coldplug */ | 1223 | /* work with hotplug and coldplug */ |
1305 | MODULE_ALIAS("platform:omap2_mcspi"); | 1224 | MODULE_ALIAS("platform:omap2_mcspi"); |
1306 | 1225 | ||
1226 | #ifdef CONFIG_SUSPEND | ||
1227 | /* | ||
1228 | * When SPI wake up from off-mode, CS is in activate state. If it was in | ||
1229 | * unactive state when driver was suspend, then force it to unactive state at | ||
1230 | * wake up. | ||
1231 | */ | ||
1232 | static int omap2_mcspi_resume(struct device *dev) | ||
1233 | { | ||
1234 | struct spi_master *master = dev_get_drvdata(dev); | ||
1235 | struct omap2_mcspi *mcspi = spi_master_get_devdata(master); | ||
1236 | struct omap2_mcspi_cs *cs; | ||
1237 | |||
1238 | omap2_mcspi_enable_clocks(mcspi); | ||
1239 | list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs, | ||
1240 | node) { | ||
1241 | if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { | ||
1242 | |||
1243 | /* | ||
1244 | * We need to toggle CS state for OMAP take this | ||
1245 | * change in account. | ||
1246 | */ | ||
1247 | MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1); | ||
1248 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); | ||
1249 | MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0); | ||
1250 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); | ||
1251 | } | ||
1252 | } | ||
1253 | omap2_mcspi_disable_clocks(mcspi); | ||
1254 | return 0; | ||
1255 | } | ||
1256 | #else | ||
1257 | #define omap2_mcspi_resume NULL | ||
1258 | #endif | ||
1259 | |||
1260 | static const struct dev_pm_ops omap2_mcspi_pm_ops = { | ||
1261 | .resume = omap2_mcspi_resume, | ||
1262 | .runtime_resume = omap_mcspi_runtime_resume, | ||
1263 | }; | ||
1264 | |||
1307 | static struct platform_driver omap2_mcspi_driver = { | 1265 | static struct platform_driver omap2_mcspi_driver = { |
1308 | .driver = { | 1266 | .driver = { |
1309 | .name = "omap2_mcspi", | 1267 | .name = "omap2_mcspi", |
1310 | .owner = THIS_MODULE, | 1268 | .owner = THIS_MODULE, |
1269 | .pm = &omap2_mcspi_pm_ops | ||
1311 | }, | 1270 | }, |
1312 | .remove = __exit_p(omap2_mcspi_remove), | 1271 | .remove = __exit_p(omap2_mcspi_remove), |
1313 | }; | 1272 | }; |