diff options
-rw-r--r-- | drivers/spi/spi-atmel.c | 255 |
1 files changed, 245 insertions, 10 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index aa7d202d6905..c9eca347787d 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #define SPI_CSR1 0x0034 | 41 | #define SPI_CSR1 0x0034 |
42 | #define SPI_CSR2 0x0038 | 42 | #define SPI_CSR2 0x0038 |
43 | #define SPI_CSR3 0x003c | 43 | #define SPI_CSR3 0x003c |
44 | #define SPI_FMR 0x0040 | ||
45 | #define SPI_FLR 0x0044 | ||
44 | #define SPI_VERSION 0x00fc | 46 | #define SPI_VERSION 0x00fc |
45 | #define SPI_RPR 0x0100 | 47 | #define SPI_RPR 0x0100 |
46 | #define SPI_RCR 0x0104 | 48 | #define SPI_RCR 0x0104 |
@@ -62,6 +64,14 @@ | |||
62 | #define SPI_SWRST_SIZE 1 | 64 | #define SPI_SWRST_SIZE 1 |
63 | #define SPI_LASTXFER_OFFSET 24 | 65 | #define SPI_LASTXFER_OFFSET 24 |
64 | #define SPI_LASTXFER_SIZE 1 | 66 | #define SPI_LASTXFER_SIZE 1 |
67 | #define SPI_TXFCLR_OFFSET 16 | ||
68 | #define SPI_TXFCLR_SIZE 1 | ||
69 | #define SPI_RXFCLR_OFFSET 17 | ||
70 | #define SPI_RXFCLR_SIZE 1 | ||
71 | #define SPI_FIFOEN_OFFSET 30 | ||
72 | #define SPI_FIFOEN_SIZE 1 | ||
73 | #define SPI_FIFODIS_OFFSET 31 | ||
74 | #define SPI_FIFODIS_SIZE 1 | ||
65 | 75 | ||
66 | /* Bitfields in MR */ | 76 | /* Bitfields in MR */ |
67 | #define SPI_MSTR_OFFSET 0 | 77 | #define SPI_MSTR_OFFSET 0 |
@@ -114,6 +124,22 @@ | |||
114 | #define SPI_TXEMPTY_SIZE 1 | 124 | #define SPI_TXEMPTY_SIZE 1 |
115 | #define SPI_SPIENS_OFFSET 16 | 125 | #define SPI_SPIENS_OFFSET 16 |
116 | #define SPI_SPIENS_SIZE 1 | 126 | #define SPI_SPIENS_SIZE 1 |
127 | #define SPI_TXFEF_OFFSET 24 | ||
128 | #define SPI_TXFEF_SIZE 1 | ||
129 | #define SPI_TXFFF_OFFSET 25 | ||
130 | #define SPI_TXFFF_SIZE 1 | ||
131 | #define SPI_TXFTHF_OFFSET 26 | ||
132 | #define SPI_TXFTHF_SIZE 1 | ||
133 | #define SPI_RXFEF_OFFSET 27 | ||
134 | #define SPI_RXFEF_SIZE 1 | ||
135 | #define SPI_RXFFF_OFFSET 28 | ||
136 | #define SPI_RXFFF_SIZE 1 | ||
137 | #define SPI_RXFTHF_OFFSET 29 | ||
138 | #define SPI_RXFTHF_SIZE 1 | ||
139 | #define SPI_TXFPTEF_OFFSET 30 | ||
140 | #define SPI_TXFPTEF_SIZE 1 | ||
141 | #define SPI_RXFPTEF_OFFSET 31 | ||
142 | #define SPI_RXFPTEF_SIZE 1 | ||
117 | 143 | ||
118 | /* Bitfields in CSR0 */ | 144 | /* Bitfields in CSR0 */ |
119 | #define SPI_CPOL_OFFSET 0 | 145 | #define SPI_CPOL_OFFSET 0 |
@@ -157,6 +183,22 @@ | |||
157 | #define SPI_TXTDIS_OFFSET 9 | 183 | #define SPI_TXTDIS_OFFSET 9 |
158 | #define SPI_TXTDIS_SIZE 1 | 184 | #define SPI_TXTDIS_SIZE 1 |
159 | 185 | ||
186 | /* Bitfields in FMR */ | ||
187 | #define SPI_TXRDYM_OFFSET 0 | ||
188 | #define SPI_TXRDYM_SIZE 2 | ||
189 | #define SPI_RXRDYM_OFFSET 4 | ||
190 | #define SPI_RXRDYM_SIZE 2 | ||
191 | #define SPI_TXFTHRES_OFFSET 16 | ||
192 | #define SPI_TXFTHRES_SIZE 6 | ||
193 | #define SPI_RXFTHRES_OFFSET 24 | ||
194 | #define SPI_RXFTHRES_SIZE 6 | ||
195 | |||
196 | /* Bitfields in FLR */ | ||
197 | #define SPI_TXFL_OFFSET 0 | ||
198 | #define SPI_TXFL_SIZE 6 | ||
199 | #define SPI_RXFL_OFFSET 16 | ||
200 | #define SPI_RXFL_SIZE 6 | ||
201 | |||
160 | /* Constants for BITS */ | 202 | /* Constants for BITS */ |
161 | #define SPI_BITS_8_BPT 0 | 203 | #define SPI_BITS_8_BPT 0 |
162 | #define SPI_BITS_9_BPT 1 | 204 | #define SPI_BITS_9_BPT 1 |
@@ -167,6 +209,9 @@ | |||
167 | #define SPI_BITS_14_BPT 6 | 209 | #define SPI_BITS_14_BPT 6 |
168 | #define SPI_BITS_15_BPT 7 | 210 | #define SPI_BITS_15_BPT 7 |
169 | #define SPI_BITS_16_BPT 8 | 211 | #define SPI_BITS_16_BPT 8 |
212 | #define SPI_ONE_DATA 0 | ||
213 | #define SPI_TWO_DATA 1 | ||
214 | #define SPI_FOUR_DATA 2 | ||
170 | 215 | ||
171 | /* Bit manipulation macros */ | 216 | /* Bit manipulation macros */ |
172 | #define SPI_BIT(name) \ | 217 | #define SPI_BIT(name) \ |
@@ -185,11 +230,31 @@ | |||
185 | __raw_readl((port)->regs + SPI_##reg) | 230 | __raw_readl((port)->regs + SPI_##reg) |
186 | #define spi_writel(port, reg, value) \ | 231 | #define spi_writel(port, reg, value) \ |
187 | __raw_writel((value), (port)->regs + SPI_##reg) | 232 | __raw_writel((value), (port)->regs + SPI_##reg) |
233 | |||
234 | #define spi_readw(port, reg) \ | ||
235 | __raw_readw((port)->regs + SPI_##reg) | ||
236 | #define spi_writew(port, reg, value) \ | ||
237 | __raw_writew((value), (port)->regs + SPI_##reg) | ||
238 | |||
239 | #define spi_readb(port, reg) \ | ||
240 | __raw_readb((port)->regs + SPI_##reg) | ||
241 | #define spi_writeb(port, reg, value) \ | ||
242 | __raw_writeb((value), (port)->regs + SPI_##reg) | ||
188 | #else | 243 | #else |
189 | #define spi_readl(port, reg) \ | 244 | #define spi_readl(port, reg) \ |
190 | readl_relaxed((port)->regs + SPI_##reg) | 245 | readl_relaxed((port)->regs + SPI_##reg) |
191 | #define spi_writel(port, reg, value) \ | 246 | #define spi_writel(port, reg, value) \ |
192 | writel_relaxed((value), (port)->regs + SPI_##reg) | 247 | writel_relaxed((value), (port)->regs + SPI_##reg) |
248 | |||
249 | #define spi_readw(port, reg) \ | ||
250 | readw_relaxed((port)->regs + SPI_##reg) | ||
251 | #define spi_writew(port, reg, value) \ | ||
252 | writew_relaxed((value), (port)->regs + SPI_##reg) | ||
253 | |||
254 | #define spi_readb(port, reg) \ | ||
255 | readb_relaxed((port)->regs + SPI_##reg) | ||
256 | #define spi_writeb(port, reg, value) \ | ||
257 | writeb_relaxed((value), (port)->regs + SPI_##reg) | ||
193 | #endif | 258 | #endif |
194 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and | 259 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and |
195 | * cache operations; better heuristics consider wordsize and bitrate. | 260 | * cache operations; better heuristics consider wordsize and bitrate. |
@@ -252,6 +317,8 @@ struct atmel_spi { | |||
252 | 317 | ||
253 | bool keep_cs; | 318 | bool keep_cs; |
254 | bool cs_active; | 319 | bool cs_active; |
320 | |||
321 | u32 fifo_size; | ||
255 | }; | 322 | }; |
256 | 323 | ||
257 | /* Controller-specific per-slave state */ | 324 | /* Controller-specific per-slave state */ |
@@ -410,6 +477,20 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, | |||
410 | slave_config->dst_maxburst = 1; | 477 | slave_config->dst_maxburst = 1; |
411 | slave_config->device_fc = false; | 478 | slave_config->device_fc = false; |
412 | 479 | ||
480 | /* | ||
481 | * This driver uses fixed peripheral select mode (PS bit set to '0' in | ||
482 | * the Mode Register). | ||
483 | * So according to the datasheet, when FIFOs are available (and | ||
484 | * enabled), the Transmit FIFO operates in Multiple Data Mode. | ||
485 | * In this mode, up to 2 data, not 4, can be written into the Transmit | ||
486 | * Data Register in a single access. | ||
487 | * However, the first data has to be written into the lowest 16 bits and | ||
488 | * the second data into the highest 16 bits of the Transmit | ||
489 | * Data Register. For 8bit data (the most frequent case), it would | ||
490 | * require to rework tx_buf so each data would actualy fit 16 bits. | ||
491 | * So we'd rather write only one data at the time. Hence the transmit | ||
492 | * path works the same whether FIFOs are available (and enabled) or not. | ||
493 | */ | ||
413 | slave_config->direction = DMA_MEM_TO_DEV; | 494 | slave_config->direction = DMA_MEM_TO_DEV; |
414 | if (dmaengine_slave_config(as->dma.chan_tx, slave_config)) { | 495 | if (dmaengine_slave_config(as->dma.chan_tx, slave_config)) { |
415 | dev_err(&as->pdev->dev, | 496 | dev_err(&as->pdev->dev, |
@@ -417,6 +498,14 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, | |||
417 | err = -EINVAL; | 498 | err = -EINVAL; |
418 | } | 499 | } |
419 | 500 | ||
501 | /* | ||
502 | * This driver configures the spi controller for master mode (MSTR bit | ||
503 | * set to '1' in the Mode Register). | ||
504 | * So according to the datasheet, when FIFOs are available (and | ||
505 | * enabled), the Receive FIFO operates in Single Data Mode. | ||
506 | * So the receive path works the same whether FIFOs are available (and | ||
507 | * enabled) or not. | ||
508 | */ | ||
420 | slave_config->direction = DMA_DEV_TO_MEM; | 509 | slave_config->direction = DMA_DEV_TO_MEM; |
421 | if (dmaengine_slave_config(as->dma.chan_rx, slave_config)) { | 510 | if (dmaengine_slave_config(as->dma.chan_rx, slave_config)) { |
422 | dev_err(&as->pdev->dev, | 511 | dev_err(&as->pdev->dev, |
@@ -506,10 +595,10 @@ static void dma_callback(void *data) | |||
506 | } | 595 | } |
507 | 596 | ||
508 | /* | 597 | /* |
509 | * Next transfer using PIO. | 598 | * Next transfer using PIO without FIFO. |
510 | */ | 599 | */ |
511 | static void atmel_spi_next_xfer_pio(struct spi_master *master, | 600 | static void atmel_spi_next_xfer_single(struct spi_master *master, |
512 | struct spi_transfer *xfer) | 601 | struct spi_transfer *xfer) |
513 | { | 602 | { |
514 | struct atmel_spi *as = spi_master_get_devdata(master); | 603 | struct atmel_spi *as = spi_master_get_devdata(master); |
515 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; | 604 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; |
@@ -542,6 +631,99 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master, | |||
542 | } | 631 | } |
543 | 632 | ||
544 | /* | 633 | /* |
634 | * Next transfer using PIO with FIFO. | ||
635 | */ | ||
636 | static void atmel_spi_next_xfer_fifo(struct spi_master *master, | ||
637 | struct spi_transfer *xfer) | ||
638 | { | ||
639 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
640 | u32 current_remaining_data, num_data; | ||
641 | u32 offset = xfer->len - as->current_remaining_bytes; | ||
642 | const u16 *words = (const u16 *)((u8 *)xfer->tx_buf + offset); | ||
643 | const u8 *bytes = (const u8 *)((u8 *)xfer->tx_buf + offset); | ||
644 | u16 td0, td1; | ||
645 | u32 fifomr; | ||
646 | |||
647 | dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_fifo\n"); | ||
648 | |||
649 | /* Compute the number of data to transfer in the current iteration */ | ||
650 | current_remaining_data = ((xfer->bits_per_word > 8) ? | ||
651 | ((u32)as->current_remaining_bytes >> 1) : | ||
652 | (u32)as->current_remaining_bytes); | ||
653 | num_data = min(current_remaining_data, as->fifo_size); | ||
654 | |||
655 | /* Flush RX and TX FIFOs */ | ||
656 | spi_writel(as, CR, SPI_BIT(RXFCLR) | SPI_BIT(TXFCLR)); | ||
657 | while (spi_readl(as, FLR)) | ||
658 | cpu_relax(); | ||
659 | |||
660 | /* Set RX FIFO Threshold to the number of data to transfer */ | ||
661 | fifomr = spi_readl(as, FMR); | ||
662 | spi_writel(as, FMR, SPI_BFINS(RXFTHRES, num_data, fifomr)); | ||
663 | |||
664 | /* Clear FIFO flags in the Status Register, especially RXFTHF */ | ||
665 | (void)spi_readl(as, SR); | ||
666 | |||
667 | /* Fill TX FIFO */ | ||
668 | while (num_data >= 2) { | ||
669 | if (xfer->tx_buf) { | ||
670 | if (xfer->bits_per_word > 8) { | ||
671 | td0 = *words++; | ||
672 | td1 = *words++; | ||
673 | } else { | ||
674 | td0 = *bytes++; | ||
675 | td1 = *bytes++; | ||
676 | } | ||
677 | } else { | ||
678 | td0 = 0; | ||
679 | td1 = 0; | ||
680 | } | ||
681 | |||
682 | spi_writel(as, TDR, (td1 << 16) | td0); | ||
683 | num_data -= 2; | ||
684 | } | ||
685 | |||
686 | if (num_data) { | ||
687 | if (xfer->tx_buf) { | ||
688 | if (xfer->bits_per_word > 8) | ||
689 | td0 = *words++; | ||
690 | else | ||
691 | td0 = *bytes++; | ||
692 | } else { | ||
693 | td0 = 0; | ||
694 | } | ||
695 | |||
696 | spi_writew(as, TDR, td0); | ||
697 | num_data--; | ||
698 | } | ||
699 | |||
700 | dev_dbg(master->dev.parent, | ||
701 | " start fifo xfer %p: len %u tx %p rx %p bitpw %d\n", | ||
702 | xfer, xfer->len, xfer->tx_buf, xfer->rx_buf, | ||
703 | xfer->bits_per_word); | ||
704 | |||
705 | /* | ||
706 | * Enable RX FIFO Threshold Flag interrupt to be notified about | ||
707 | * transfer completion. | ||
708 | */ | ||
709 | spi_writel(as, IER, SPI_BIT(RXFTHF) | SPI_BIT(OVRES)); | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * Next transfer using PIO. | ||
714 | */ | ||
715 | static void atmel_spi_next_xfer_pio(struct spi_master *master, | ||
716 | struct spi_transfer *xfer) | ||
717 | { | ||
718 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
719 | |||
720 | if (as->fifo_size) | ||
721 | atmel_spi_next_xfer_fifo(master, xfer); | ||
722 | else | ||
723 | atmel_spi_next_xfer_single(master, xfer); | ||
724 | } | ||
725 | |||
726 | /* | ||
545 | * Submit next transfer for DMA. | 727 | * Submit next transfer for DMA. |
546 | */ | 728 | */ |
547 | static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, | 729 | static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, |
@@ -843,13 +1025,8 @@ static void atmel_spi_disable_pdc_transfer(struct atmel_spi *as) | |||
843 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); | 1025 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); |
844 | } | 1026 | } |
845 | 1027 | ||
846 | /* Called from IRQ | ||
847 | * | ||
848 | * Must update "current_remaining_bytes" to keep track of data | ||
849 | * to transfer. | ||
850 | */ | ||
851 | static void | 1028 | static void |
852 | atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer) | 1029 | atmel_spi_pump_single_data(struct atmel_spi *as, struct spi_transfer *xfer) |
853 | { | 1030 | { |
854 | u8 *rxp; | 1031 | u8 *rxp; |
855 | u16 *rxp16; | 1032 | u16 *rxp16; |
@@ -876,6 +1053,57 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer) | |||
876 | } | 1053 | } |
877 | } | 1054 | } |
878 | 1055 | ||
1056 | static void | ||
1057 | atmel_spi_pump_fifo_data(struct atmel_spi *as, struct spi_transfer *xfer) | ||
1058 | { | ||
1059 | u32 fifolr = spi_readl(as, FLR); | ||
1060 | u32 num_bytes, num_data = SPI_BFEXT(RXFL, fifolr); | ||
1061 | u32 offset = xfer->len - as->current_remaining_bytes; | ||
1062 | u16 *words = (u16 *)((u8 *)xfer->rx_buf + offset); | ||
1063 | u8 *bytes = (u8 *)((u8 *)xfer->rx_buf + offset); | ||
1064 | u16 rd; /* RD field is the lowest 16 bits of RDR */ | ||
1065 | |||
1066 | /* Update the number of remaining bytes to transfer */ | ||
1067 | num_bytes = ((xfer->bits_per_word > 8) ? | ||
1068 | (num_data << 1) : | ||
1069 | num_data); | ||
1070 | |||
1071 | if (as->current_remaining_bytes > num_bytes) | ||
1072 | as->current_remaining_bytes -= num_bytes; | ||
1073 | else | ||
1074 | as->current_remaining_bytes = 0; | ||
1075 | |||
1076 | /* Handle odd number of bytes when data are more than 8bit width */ | ||
1077 | if (xfer->bits_per_word > 8) | ||
1078 | as->current_remaining_bytes &= ~0x1; | ||
1079 | |||
1080 | /* Read data */ | ||
1081 | while (num_data) { | ||
1082 | rd = spi_readl(as, RDR); | ||
1083 | if (xfer->rx_buf) { | ||
1084 | if (xfer->bits_per_word > 8) | ||
1085 | *words++ = rd; | ||
1086 | else | ||
1087 | *bytes++ = rd; | ||
1088 | } | ||
1089 | num_data--; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | /* Called from IRQ | ||
1094 | * | ||
1095 | * Must update "current_remaining_bytes" to keep track of data | ||
1096 | * to transfer. | ||
1097 | */ | ||
1098 | static void | ||
1099 | atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer) | ||
1100 | { | ||
1101 | if (as->fifo_size) | ||
1102 | atmel_spi_pump_fifo_data(as, xfer); | ||
1103 | else | ||
1104 | atmel_spi_pump_single_data(as, xfer); | ||
1105 | } | ||
1106 | |||
879 | /* Interrupt | 1107 | /* Interrupt |
880 | * | 1108 | * |
881 | * No need for locking in this Interrupt handler: done_status is the | 1109 | * No need for locking in this Interrupt handler: done_status is the |
@@ -916,7 +1144,7 @@ atmel_spi_pio_interrupt(int irq, void *dev_id) | |||
916 | 1144 | ||
917 | complete(&as->xfer_completion); | 1145 | complete(&as->xfer_completion); |
918 | 1146 | ||
919 | } else if (pending & SPI_BIT(RDRF)) { | 1147 | } else if (pending & (SPI_BIT(RDRF) | SPI_BIT(RXFTHF))) { |
920 | atmel_spi_lock(as); | 1148 | atmel_spi_lock(as); |
921 | 1149 | ||
922 | if (as->current_remaining_bytes) { | 1150 | if (as->current_remaining_bytes) { |
@@ -1399,6 +1627,13 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
1399 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); | 1627 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); |
1400 | spi_writel(as, CR, SPI_BIT(SPIEN)); | 1628 | spi_writel(as, CR, SPI_BIT(SPIEN)); |
1401 | 1629 | ||
1630 | as->fifo_size = 0; | ||
1631 | if (!of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size", | ||
1632 | &as->fifo_size)) { | ||
1633 | dev_info(&pdev->dev, "Using FIFO (%u data)\n", as->fifo_size); | ||
1634 | spi_writel(as, CR, SPI_BIT(FIFOEN)); | ||
1635 | } | ||
1636 | |||
1402 | /* go! */ | 1637 | /* go! */ |
1403 | dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", | 1638 | dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", |
1404 | (unsigned long)regs->start, irq); | 1639 | (unsigned long)regs->start, irq); |