diff options
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-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; |