diff options
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 82 |
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) | |||
186 | static void null_writer(struct driver_data *drv_data) | 190 | static 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) | |||
198 | static void null_reader(struct driver_data *drv_data) | 202 | static 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 | ||