aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/pxa2xx_spi.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 913e1aff0235..596bf820b70c 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -120,6 +120,8 @@ struct driver_data {
120 dma_addr_t tx_dma; 120 dma_addr_t tx_dma;
121 size_t rx_map_len; 121 size_t rx_map_len;
122 size_t tx_map_len; 122 size_t tx_map_len;
123 u8 n_bytes;
124 u32 dma_width;
123 int cs_change; 125 int cs_change;
124 void (*write)(struct driver_data *drv_data); 126 void (*write)(struct driver_data *drv_data);
125 void (*read)(struct driver_data *drv_data); 127 void (*read)(struct driver_data *drv_data);
@@ -139,6 +141,8 @@ struct chip_data {
139 u32 threshold; 141 u32 threshold;
140 u32 dma_threshold; 142 u32 dma_threshold;
141 u8 enable_dma; 143 u8 enable_dma;
144 u8 bits_per_word;
145 u32 speed_hz;
142 void (*write)(struct driver_data *drv_data); 146 void (*write)(struct driver_data *drv_data);
143 void (*read)(struct driver_data *drv_data); 147 void (*read)(struct driver_data *drv_data);
144 void (*cs_control)(u32 command); 148 void (*cs_control)(u32 command);
@@ -186,7 +190,7 @@ static void null_cs_control(u32 command)
186static void null_writer(struct driver_data *drv_data) 190static void null_writer(struct driver_data *drv_data)
187{ 191{
188 void *reg = drv_data->ioaddr; 192 void *reg = drv_data->ioaddr;
189 u8 n_bytes = drv_data->cur_chip->n_bytes; 193 u8 n_bytes = drv_data->n_bytes;
190 194
191 while ((read_SSSR(reg) & SSSR_TNF) 195 while ((read_SSSR(reg) & SSSR_TNF)
192 && (drv_data->tx < drv_data->tx_end)) { 196 && (drv_data->tx < drv_data->tx_end)) {
@@ -198,7 +202,7 @@ static void null_writer(struct driver_data *drv_data)
198static void null_reader(struct driver_data *drv_data) 202static void null_reader(struct driver_data *drv_data)
199{ 203{
200 void *reg = drv_data->ioaddr; 204 void *reg = drv_data->ioaddr;
201 u8 n_bytes = drv_data->cur_chip->n_bytes; 205 u8 n_bytes = drv_data->n_bytes;
202 206
203 while ((read_SSSR(reg) & SSSR_RNE) 207 while ((read_SSSR(reg) & SSSR_RNE)
204 && (drv_data->rx < drv_data->rx_end)) { 208 && (drv_data->rx < drv_data->rx_end)) {
@@ -256,7 +260,7 @@ static void u32_writer(struct driver_data *drv_data)
256 260
257 while ((read_SSSR(reg) & SSSR_TNF) 261 while ((read_SSSR(reg) & SSSR_TNF)
258 && (drv_data->tx < drv_data->tx_end)) { 262 && (drv_data->tx < drv_data->tx_end)) {
259 write_SSDR(*(u16 *)(drv_data->tx), reg); 263 write_SSDR(*(u32 *)(drv_data->tx), reg);
260 drv_data->tx += 4; 264 drv_data->tx += 4;
261 } 265 }
262} 266}
@@ -677,6 +681,10 @@ static void pump_transfers(unsigned long data)
677 struct spi_transfer *previous = NULL; 681 struct spi_transfer *previous = NULL;
678 struct chip_data *chip = NULL; 682 struct chip_data *chip = NULL;
679 void *reg = drv_data->ioaddr; 683 void *reg = drv_data->ioaddr;
684 u32 clk_div = 0;
685 u8 bits = 0;
686 u32 speed = 0;
687 u32 cr0;
680 688
681 /* Get current state information */ 689 /* Get current state information */
682 message = drv_data->cur_msg; 690 message = drv_data->cur_msg;
@@ -713,6 +721,8 @@ static void pump_transfers(unsigned long data)
713 giveback(message, drv_data); 721 giveback(message, drv_data);
714 return; 722 return;
715 } 723 }
724 drv_data->n_bytes = chip->n_bytes;
725 drv_data->dma_width = chip->dma_width;
716 drv_data->cs_control = chip->cs_control; 726 drv_data->cs_control = chip->cs_control;
717 drv_data->tx = (void *)transfer->tx_buf; 727 drv_data->tx = (void *)transfer->tx_buf;
718 drv_data->tx_end = drv_data->tx + transfer->len; 728 drv_data->tx_end = drv_data->tx + transfer->len;
@@ -724,6 +734,62 @@ static void pump_transfers(unsigned long data)
724 drv_data->write = drv_data->tx ? chip->write : null_writer; 734 drv_data->write = drv_data->tx ? chip->write : null_writer;
725 drv_data->read = drv_data->rx ? chip->read : null_reader; 735 drv_data->read = drv_data->rx ? chip->read : null_reader;
726 drv_data->cs_change = transfer->cs_change; 736 drv_data->cs_change = transfer->cs_change;
737
738 /* Change speed and bit per word on a per transfer */
739 if (transfer->speed_hz || transfer->bits_per_word) {
740
741 /* Disable clock */
742 write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg);
743 cr0 = chip->cr0;
744 bits = chip->bits_per_word;
745 speed = chip->speed_hz;
746
747 if (transfer->speed_hz)
748 speed = transfer->speed_hz;
749
750 if (transfer->bits_per_word)
751 bits = transfer->bits_per_word;
752
753 if (reg == SSP1_VIRT)
754 clk_div = SSP1_SerClkDiv(speed);
755 else if (reg == SSP2_VIRT)
756 clk_div = SSP2_SerClkDiv(speed);
757 else if (reg == SSP3_VIRT)
758 clk_div = SSP3_SerClkDiv(speed);
759
760 if (bits <= 8) {
761 drv_data->n_bytes = 1;
762 drv_data->dma_width = DCMD_WIDTH1;
763 drv_data->read = drv_data->read != null_reader ?
764 u8_reader : null_reader;
765 drv_data->write = drv_data->write != null_writer ?
766 u8_writer : null_writer;
767 } else if (bits <= 16) {
768 drv_data->n_bytes = 2;
769 drv_data->dma_width = DCMD_WIDTH2;
770 drv_data->read = drv_data->read != null_reader ?
771 u16_reader : null_reader;
772 drv_data->write = drv_data->write != null_writer ?
773 u16_writer : null_writer;
774 } else if (bits <= 32) {
775 drv_data->n_bytes = 4;
776 drv_data->dma_width = DCMD_WIDTH4;
777 drv_data->read = drv_data->read != null_reader ?
778 u32_reader : null_reader;
779 drv_data->write = drv_data->write != null_writer ?
780 u32_writer : null_writer;
781 }
782
783 cr0 = clk_div
784 | SSCR0_Motorola
785 | SSCR0_DataSize(bits & 0x0f)
786 | SSCR0_SSE
787 | (bits > 16 ? SSCR0_EDSS : 0);
788
789 /* Start it back up */
790 write_SSCR0(cr0, reg);
791 }
792
727 message->state = RUNNING_STATE; 793 message->state = RUNNING_STATE;
728 794
729 /* Try to map dma buffer and do a dma transfer if successful */ 795 /* Try to map dma buffer and do a dma transfer if successful */
@@ -739,13 +805,13 @@ static void pump_transfers(unsigned long data)
739 if (drv_data->rx == drv_data->null_dma_buf) 805 if (drv_data->rx == drv_data->null_dma_buf)
740 /* No target address increment */ 806 /* No target address increment */
741 DCMD(drv_data->rx_channel) = DCMD_FLOWSRC 807 DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
742 | chip->dma_width 808 | drv_data->dma_width
743 | chip->dma_burst_size 809 | chip->dma_burst_size
744 | drv_data->len; 810 | drv_data->len;
745 else 811 else
746 DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR 812 DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
747 | DCMD_FLOWSRC 813 | DCMD_FLOWSRC
748 | chip->dma_width 814 | drv_data->dma_width
749 | chip->dma_burst_size 815 | chip->dma_burst_size
750 | drv_data->len; 816 | drv_data->len;
751 817
@@ -756,13 +822,13 @@ static void pump_transfers(unsigned long data)
756 if (drv_data->tx == drv_data->null_dma_buf) 822 if (drv_data->tx == drv_data->null_dma_buf)
757 /* No source address increment */ 823 /* No source address increment */
758 DCMD(drv_data->tx_channel) = DCMD_FLOWTRG 824 DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
759 | chip->dma_width 825 | drv_data->dma_width
760 | chip->dma_burst_size 826 | chip->dma_burst_size
761 | drv_data->len; 827 | drv_data->len;
762 else 828 else
763 DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR 829 DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
764 | DCMD_FLOWTRG 830 | DCMD_FLOWTRG
765 | chip->dma_width 831 | drv_data->dma_width
766 | chip->dma_burst_size 832 | chip->dma_burst_size
767 | drv_data->len; 833 | drv_data->len;
768 834
@@ -943,6 +1009,7 @@ static int setup(struct spi_device *spi)
943 clk_div = SSP3_SerClkDiv(spi->max_speed_hz); 1009 clk_div = SSP3_SerClkDiv(spi->max_speed_hz);
944 else 1010 else
945 return -ENODEV; 1011 return -ENODEV;
1012 chip->speed_hz = spi->max_speed_hz;
946 1013
947 chip->cr0 = clk_div 1014 chip->cr0 = clk_div
948 | SSCR0_Motorola 1015 | SSCR0_Motorola
@@ -987,6 +1054,7 @@ static int setup(struct spi_device *spi)
987 kfree(chip); 1054 kfree(chip);
988 return -ENODEV; 1055 return -ENODEV;
989 } 1056 }
1057 chip->bits_per_word = spi->bits_per_word;
990 1058
991 spi_set_ctldata(spi, chip); 1059 spi_set_ctldata(spi, chip);
992 1060