diff options
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 243 |
1 files changed, 110 insertions, 133 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index f374eeebb8c2..46ef5fe51db5 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
| @@ -120,10 +120,6 @@ struct omap2_mcspi_regs { | |||
| 120 | }; | 120 | }; |
| 121 | 121 | ||
| 122 | struct omap2_mcspi { | 122 | struct omap2_mcspi { |
| 123 | struct work_struct work; | ||
| 124 | /* lock protects queue and registers */ | ||
| 125 | spinlock_t lock; | ||
| 126 | struct list_head msg_queue; | ||
| 127 | struct spi_master *master; | 123 | struct spi_master *master; |
| 128 | /* Virtual base address of the controller */ | 124 | /* Virtual base address of the controller */ |
| 129 | void __iomem *base; | 125 | void __iomem *base; |
| @@ -131,7 +127,6 @@ struct omap2_mcspi { | |||
| 131 | /* SPI1 has 4 channels, while SPI2 has 2 */ | 127 | /* SPI1 has 4 channels, while SPI2 has 2 */ |
| 132 | struct omap2_mcspi_dma *dma_channels; | 128 | struct omap2_mcspi_dma *dma_channels; |
| 133 | struct device *dev; | 129 | struct device *dev; |
| 134 | struct workqueue_struct *wq; | ||
| 135 | struct omap2_mcspi_regs ctx; | 130 | struct omap2_mcspi_regs ctx; |
| 136 | }; | 131 | }; |
| 137 | 132 | ||
| @@ -275,6 +270,23 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) | |||
| 275 | return pm_runtime_get_sync(mcspi->dev); | 270 | return pm_runtime_get_sync(mcspi->dev); |
| 276 | } | 271 | } |
| 277 | 272 | ||
| 273 | static int omap2_prepare_transfer(struct spi_master *master) | ||
| 274 | { | ||
| 275 | struct omap2_mcspi *mcspi = spi_master_get_devdata(master); | ||
| 276 | |||
| 277 | pm_runtime_get_sync(mcspi->dev); | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int omap2_unprepare_transfer(struct spi_master *master) | ||
| 282 | { | ||
| 283 | struct omap2_mcspi *mcspi = spi_master_get_devdata(master); | ||
| 284 | |||
| 285 | pm_runtime_mark_last_busy(mcspi->dev); | ||
| 286 | pm_runtime_put_autosuspend(mcspi->dev); | ||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 278 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) | 290 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) |
| 279 | { | 291 | { |
| 280 | unsigned long timeout; | 292 | unsigned long timeout; |
| @@ -846,144 +858,122 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) | |||
| 846 | } | 858 | } |
| 847 | } | 859 | } |
| 848 | 860 | ||
| 849 | static void omap2_mcspi_work(struct work_struct *work) | 861 | static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) |
| 850 | { | 862 | { |
| 851 | struct omap2_mcspi *mcspi; | ||
| 852 | |||
| 853 | mcspi = container_of(work, struct omap2_mcspi, work); | ||
| 854 | |||
| 855 | if (omap2_mcspi_enable_clocks(mcspi) < 0) | ||
| 856 | return; | ||
| 857 | |||
| 858 | spin_lock_irq(&mcspi->lock); | ||
| 859 | 863 | ||
| 860 | /* We only enable one channel at a time -- the one whose message is | 864 | /* We only enable one channel at a time -- the one whose message is |
| 861 | * at the head of the queue -- although this controller would gladly | 865 | * -- although this controller would gladly |
| 862 | * arbitrate among multiple channels. This corresponds to "single | 866 | * arbitrate among multiple channels. This corresponds to "single |
| 863 | * channel" master mode. As a side effect, we need to manage the | 867 | * channel" master mode. As a side effect, we need to manage the |
| 864 | * chipselect with the FORCE bit ... CS != channel enable. | 868 | * chipselect with the FORCE bit ... CS != channel enable. |
| 865 | */ | 869 | */ |
| 866 | while (!list_empty(&mcspi->msg_queue)) { | ||
| 867 | struct spi_message *m; | ||
| 868 | struct spi_device *spi; | ||
| 869 | struct spi_transfer *t = NULL; | ||
| 870 | int cs_active = 0; | ||
| 871 | struct omap2_mcspi_cs *cs; | ||
| 872 | struct omap2_mcspi_device_config *cd; | ||
| 873 | int par_override = 0; | ||
| 874 | int status = 0; | ||
| 875 | u32 chconf; | ||
| 876 | |||
| 877 | m = container_of(mcspi->msg_queue.next, struct spi_message, | ||
| 878 | queue); | ||
| 879 | |||
| 880 | list_del_init(&m->queue); | ||
| 881 | spin_unlock_irq(&mcspi->lock); | ||
| 882 | |||
| 883 | spi = m->spi; | ||
| 884 | cs = spi->controller_state; | ||
| 885 | cd = spi->controller_data; | ||
| 886 | 870 | ||
| 887 | omap2_mcspi_set_enable(spi, 1); | 871 | struct spi_device *spi; |
| 888 | list_for_each_entry(t, &m->transfers, transfer_list) { | 872 | struct spi_transfer *t = NULL; |
| 889 | if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { | 873 | int cs_active = 0; |
| 890 | status = -EINVAL; | 874 | struct omap2_mcspi_cs *cs; |
| 891 | break; | 875 | struct omap2_mcspi_device_config *cd; |
| 892 | } | 876 | int par_override = 0; |
| 893 | if (par_override || t->speed_hz || t->bits_per_word) { | 877 | int status = 0; |
| 894 | par_override = 1; | 878 | u32 chconf; |
| 895 | status = omap2_mcspi_setup_transfer(spi, t); | ||
| 896 | if (status < 0) | ||
| 897 | break; | ||
| 898 | if (!t->speed_hz && !t->bits_per_word) | ||
| 899 | par_override = 0; | ||
| 900 | } | ||
| 901 | 879 | ||
| 902 | if (!cs_active) { | 880 | spi = m->spi; |
| 903 | omap2_mcspi_force_cs(spi, 1); | 881 | cs = spi->controller_state; |
| 904 | cs_active = 1; | 882 | cd = spi->controller_data; |
| 905 | } | ||
| 906 | 883 | ||
| 907 | chconf = mcspi_cached_chconf0(spi); | 884 | omap2_mcspi_set_enable(spi, 1); |
| 908 | chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; | 885 | list_for_each_entry(t, &m->transfers, transfer_list) { |
| 909 | chconf &= ~OMAP2_MCSPI_CHCONF_TURBO; | 886 | if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { |
| 887 | status = -EINVAL; | ||
| 888 | break; | ||
| 889 | } | ||
| 890 | if (par_override || t->speed_hz || t->bits_per_word) { | ||
| 891 | par_override = 1; | ||
| 892 | status = omap2_mcspi_setup_transfer(spi, t); | ||
| 893 | if (status < 0) | ||
| 894 | break; | ||
| 895 | if (!t->speed_hz && !t->bits_per_word) | ||
| 896 | par_override = 0; | ||
| 897 | } | ||
| 910 | 898 | ||
| 911 | if (t->tx_buf == NULL) | 899 | if (!cs_active) { |
| 912 | chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; | 900 | omap2_mcspi_force_cs(spi, 1); |
| 913 | else if (t->rx_buf == NULL) | 901 | cs_active = 1; |
| 914 | chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; | 902 | } |
| 915 | |||
| 916 | if (cd && cd->turbo_mode && t->tx_buf == NULL) { | ||
| 917 | /* Turbo mode is for more than one word */ | ||
| 918 | if (t->len > ((cs->word_len + 7) >> 3)) | ||
| 919 | chconf |= OMAP2_MCSPI_CHCONF_TURBO; | ||
| 920 | } | ||
| 921 | 903 | ||
| 922 | mcspi_write_chconf0(spi, chconf); | 904 | chconf = mcspi_cached_chconf0(spi); |
| 905 | chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; | ||
| 906 | chconf &= ~OMAP2_MCSPI_CHCONF_TURBO; | ||
| 923 | 907 | ||
| 924 | if (t->len) { | 908 | if (t->tx_buf == NULL) |
| 925 | unsigned count; | 909 | chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; |
| 910 | else if (t->rx_buf == NULL) | ||
| 911 | chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; | ||
| 926 | 912 | ||
| 927 | /* RX_ONLY mode needs dummy data in TX reg */ | 913 | if (cd && cd->turbo_mode && t->tx_buf == NULL) { |
| 928 | if (t->tx_buf == NULL) | 914 | /* Turbo mode is for more than one word */ |
| 929 | __raw_writel(0, cs->base | 915 | if (t->len > ((cs->word_len + 7) >> 3)) |
| 930 | + OMAP2_MCSPI_TX0); | 916 | chconf |= OMAP2_MCSPI_CHCONF_TURBO; |
| 917 | } | ||
| 931 | 918 | ||
| 932 | if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES) | 919 | mcspi_write_chconf0(spi, chconf); |
| 933 | count = omap2_mcspi_txrx_dma(spi, t); | ||
| 934 | else | ||
| 935 | count = omap2_mcspi_txrx_pio(spi, t); | ||
| 936 | m->actual_length += count; | ||
| 937 | 920 | ||
| 938 | if (count != t->len) { | 921 | if (t->len) { |
| 939 | status = -EIO; | 922 | unsigned count; |
| 940 | break; | 923 | |
| 941 | } | 924 | /* RX_ONLY mode needs dummy data in TX reg */ |
| 942 | } | 925 | if (t->tx_buf == NULL) |
| 926 | __raw_writel(0, cs->base | ||
| 927 | + OMAP2_MCSPI_TX0); | ||
| 943 | 928 | ||
| 944 | if (t->delay_usecs) | 929 | if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES) |
| 945 | udelay(t->delay_usecs); | 930 | count = omap2_mcspi_txrx_dma(spi, t); |
| 931 | else | ||
| 932 | count = omap2_mcspi_txrx_pio(spi, t); | ||
| 933 | m->actual_length += count; | ||
| 946 | 934 | ||
| 947 | /* ignore the "leave it on after last xfer" hint */ | 935 | if (count != t->len) { |
| 948 | if (t->cs_change) { | 936 | status = -EIO; |
| 949 | omap2_mcspi_force_cs(spi, 0); | 937 | break; |
| 950 | cs_active = 0; | ||
| 951 | } | 938 | } |
| 952 | } | 939 | } |
| 953 | 940 | ||
| 954 | /* Restore defaults if they were overriden */ | 941 | if (t->delay_usecs) |
| 955 | if (par_override) { | 942 | udelay(t->delay_usecs); |
| 956 | par_override = 0; | ||
| 957 | status = omap2_mcspi_setup_transfer(spi, NULL); | ||
| 958 | } | ||
| 959 | 943 | ||
| 960 | if (cs_active) | 944 | /* ignore the "leave it on after last xfer" hint */ |
| 945 | if (t->cs_change) { | ||
| 961 | omap2_mcspi_force_cs(spi, 0); | 946 | omap2_mcspi_force_cs(spi, 0); |
| 947 | cs_active = 0; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | /* Restore defaults if they were overriden */ | ||
| 951 | if (par_override) { | ||
| 952 | par_override = 0; | ||
| 953 | status = omap2_mcspi_setup_transfer(spi, NULL); | ||
| 954 | } | ||
| 962 | 955 | ||
| 963 | omap2_mcspi_set_enable(spi, 0); | 956 | if (cs_active) |
| 964 | 957 | omap2_mcspi_force_cs(spi, 0); | |
| 965 | m->status = status; | ||
| 966 | m->complete(m->context); | ||
| 967 | 958 | ||
| 968 | spin_lock_irq(&mcspi->lock); | 959 | omap2_mcspi_set_enable(spi, 0); |
| 969 | } | ||
| 970 | 960 | ||
| 971 | spin_unlock_irq(&mcspi->lock); | 961 | m->status = status; |
| 972 | 962 | ||
| 973 | omap2_mcspi_disable_clocks(mcspi); | ||
| 974 | } | 963 | } |
| 975 | 964 | ||
| 976 | static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | 965 | static int omap2_mcspi_transfer_one_message(struct spi_master *master, |
| 966 | struct spi_message *m) | ||
| 977 | { | 967 | { |
| 978 | struct omap2_mcspi *mcspi; | 968 | struct omap2_mcspi *mcspi; |
| 979 | unsigned long flags; | ||
| 980 | struct spi_transfer *t; | 969 | struct spi_transfer *t; |
| 981 | 970 | ||
| 971 | mcspi = spi_master_get_devdata(master); | ||
| 982 | m->actual_length = 0; | 972 | m->actual_length = 0; |
| 983 | m->status = 0; | 973 | m->status = 0; |
| 984 | 974 | ||
| 985 | /* reject invalid messages and transfers */ | 975 | /* reject invalid messages and transfers */ |
| 986 | if (list_empty(&m->transfers) || !m->complete) | 976 | if (list_empty(&m->transfers)) |
| 987 | return -EINVAL; | 977 | return -EINVAL; |
| 988 | list_for_each_entry(t, &m->transfers, transfer_list) { | 978 | list_for_each_entry(t, &m->transfers, transfer_list) { |
| 989 | const void *tx_buf = t->tx_buf; | 979 | const void *tx_buf = t->tx_buf; |
| @@ -995,7 +985,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 995 | || (t->bits_per_word && | 985 | || (t->bits_per_word && |
| 996 | ( t->bits_per_word < 4 | 986 | ( t->bits_per_word < 4 |
| 997 | || t->bits_per_word > 32))) { | 987 | || t->bits_per_word > 32))) { |
| 998 | dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", | 988 | dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", |
| 999 | t->speed_hz, | 989 | t->speed_hz, |
| 1000 | len, | 990 | len, |
| 1001 | tx_buf ? "tx" : "", | 991 | tx_buf ? "tx" : "", |
| @@ -1004,7 +994,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 1004 | return -EINVAL; | 994 | return -EINVAL; |
| 1005 | } | 995 | } |
| 1006 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { | 996 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { |
| 1007 | dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n", | 997 | dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n", |
| 1008 | t->speed_hz, | 998 | t->speed_hz, |
| 1009 | OMAP2_MCSPI_MAX_FREQ >> 15); | 999 | OMAP2_MCSPI_MAX_FREQ >> 15); |
| 1010 | return -EINVAL; | 1000 | return -EINVAL; |
| @@ -1014,35 +1004,30 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 1014 | continue; | 1004 | continue; |
| 1015 | 1005 | ||
| 1016 | if (tx_buf != NULL) { | 1006 | if (tx_buf != NULL) { |
| 1017 | t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf, | 1007 | t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, |
| 1018 | len, DMA_TO_DEVICE); | 1008 | len, DMA_TO_DEVICE); |
| 1019 | if (dma_mapping_error(&spi->dev, t->tx_dma)) { | 1009 | if (dma_mapping_error(mcspi->dev, t->tx_dma)) { |
| 1020 | dev_dbg(&spi->dev, "dma %cX %d bytes error\n", | 1010 | dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", |
| 1021 | 'T', len); | 1011 | 'T', len); |
| 1022 | return -EINVAL; | 1012 | return -EINVAL; |
| 1023 | } | 1013 | } |
| 1024 | } | 1014 | } |
| 1025 | if (rx_buf != NULL) { | 1015 | if (rx_buf != NULL) { |
| 1026 | t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len, | 1016 | t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, |
| 1027 | DMA_FROM_DEVICE); | 1017 | DMA_FROM_DEVICE); |
| 1028 | if (dma_mapping_error(&spi->dev, t->rx_dma)) { | 1018 | if (dma_mapping_error(mcspi->dev, t->rx_dma)) { |
| 1029 | dev_dbg(&spi->dev, "dma %cX %d bytes error\n", | 1019 | dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", |
| 1030 | 'R', len); | 1020 | 'R', len); |
| 1031 | if (tx_buf != NULL) | 1021 | if (tx_buf != NULL) |
| 1032 | dma_unmap_single(&spi->dev, t->tx_dma, | 1022 | dma_unmap_single(mcspi->dev, t->tx_dma, |
| 1033 | len, DMA_TO_DEVICE); | 1023 | len, DMA_TO_DEVICE); |
| 1034 | return -EINVAL; | 1024 | return -EINVAL; |
| 1035 | } | 1025 | } |
| 1036 | } | 1026 | } |
| 1037 | } | 1027 | } |
| 1038 | 1028 | ||
| 1039 | mcspi = spi_master_get_devdata(spi->master); | 1029 | omap2_mcspi_work(mcspi, m); |
| 1040 | 1030 | spi_finalize_current_message(master); | |
| 1041 | spin_lock_irqsave(&mcspi->lock, flags); | ||
| 1042 | list_add_tail(&m->queue, &mcspi->msg_queue); | ||
| 1043 | queue_work(mcspi->wq, &mcspi->work); | ||
| 1044 | spin_unlock_irqrestore(&mcspi->lock, flags); | ||
| 1045 | |||
| 1046 | return 0; | 1031 | return 0; |
| 1047 | } | 1032 | } |
| 1048 | 1033 | ||
| @@ -1120,7 +1105,9 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) | |||
| 1120 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1105 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
| 1121 | 1106 | ||
| 1122 | master->setup = omap2_mcspi_setup; | 1107 | master->setup = omap2_mcspi_setup; |
| 1123 | master->transfer = omap2_mcspi_transfer; | 1108 | master->prepare_transfer_hardware = omap2_prepare_transfer; |
| 1109 | master->unprepare_transfer_hardware = omap2_unprepare_transfer; | ||
| 1110 | master->transfer_one_message = omap2_mcspi_transfer_one_message; | ||
| 1124 | master->cleanup = omap2_mcspi_cleanup; | 1111 | master->cleanup = omap2_mcspi_cleanup; |
| 1125 | master->dev.of_node = node; | 1112 | master->dev.of_node = node; |
| 1126 | 1113 | ||
| @@ -1145,12 +1132,6 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) | |||
| 1145 | mcspi = spi_master_get_devdata(master); | 1132 | mcspi = spi_master_get_devdata(master); |
| 1146 | mcspi->master = master; | 1133 | mcspi->master = master; |
| 1147 | 1134 | ||
| 1148 | mcspi->wq = alloc_workqueue(dev_name(&pdev->dev), WQ_MEM_RECLAIM, 1); | ||
| 1149 | if (mcspi->wq == NULL) { | ||
| 1150 | status = -ENOMEM; | ||
| 1151 | goto free_master; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1135 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1155 | if (r == NULL) { | 1136 | if (r == NULL) { |
| 1156 | status = -ENODEV; | 1137 | status = -ENODEV; |
| @@ -1169,10 +1150,7 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) | |||
| 1169 | } | 1150 | } |
| 1170 | 1151 | ||
| 1171 | mcspi->dev = &pdev->dev; | 1152 | mcspi->dev = &pdev->dev; |
| 1172 | INIT_WORK(&mcspi->work, omap2_mcspi_work); | ||
| 1173 | 1153 | ||
| 1174 | spin_lock_init(&mcspi->lock); | ||
| 1175 | INIT_LIST_HEAD(&mcspi->msg_queue); | ||
| 1176 | INIT_LIST_HEAD(&mcspi->ctx.cs); | 1154 | INIT_LIST_HEAD(&mcspi->ctx.cs); |
| 1177 | 1155 | ||
| 1178 | mcspi->dma_channels = kcalloc(master->num_chipselect, | 1156 | mcspi->dma_channels = kcalloc(master->num_chipselect, |
| @@ -1253,7 +1231,6 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) | |||
| 1253 | 1231 | ||
| 1254 | spi_unregister_master(master); | 1232 | spi_unregister_master(master); |
| 1255 | kfree(dma_channels); | 1233 | kfree(dma_channels); |
| 1256 | destroy_workqueue(mcspi->wq); | ||
| 1257 | platform_set_drvdata(pdev, NULL); | 1234 | platform_set_drvdata(pdev, NULL); |
| 1258 | 1235 | ||
| 1259 | return 0; | 1236 | return 0; |
