diff options
| author | Stephen Street <stephen@streetfiresound.com> | 2006-03-28 17:05:23 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-05-16 17:33:58 -0400 |
| commit | 9708c121c38fe864eb6f5a119f7525729686e095 (patch) | |
| tree | 27d5afdcafdcf10b45f4a228c739d5819cc9240c | |
| parent | a020ed7521a9737bcf3e34eb880867c60c3c68d0 (diff) | |
[PATCH] spi: Update to PXA2xx SPI Driver
Fix two outstanding issues with the pxa2xx_spi driver:
1) Bad cast in the function u32_writer. Thanks to Henrik Bechmann
2) Adds support for per transfer changes to speed and bits per word
Signed-off-by: Stephen Street <stephen@streetfiresound.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -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 | ||
