diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-15 17:48:32 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-03-09 16:40:13 -0500 |
commit | ad2a99af0d7242726723575efaffa1625664b384 (patch) | |
tree | a9114736ed9b0d81540e5bad4d6122ca5a84374c /drivers/spi | |
parent | 5e8afa34cc4ab2cea3472b80317a929b83b3c65b (diff) |
spi/s3c64xx: Convert to using core message queue
Convert the s3c64xx driver to using the new message queue factored out of
the pl022 driver by Linus Walleij, saving us a nice block of code and
getting the benefits of improvements implemented in the core.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 125 |
1 files changed, 22 insertions, 103 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index b899af6640a2..1174d802ff45 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -128,8 +128,6 @@ | |||
128 | 128 | ||
129 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) | 129 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) |
130 | 130 | ||
131 | #define SUSPND (1<<0) | ||
132 | #define SPIBUSY (1<<1) | ||
133 | #define RXBUSY (1<<2) | 131 | #define RXBUSY (1<<2) |
134 | #define TXBUSY (1<<3) | 132 | #define TXBUSY (1<<3) |
135 | 133 | ||
@@ -144,10 +142,8 @@ struct s3c64xx_spi_dma_data { | |||
144 | * @clk: Pointer to the spi clock. | 142 | * @clk: Pointer to the spi clock. |
145 | * @src_clk: Pointer to the clock used to generate SPI signals. | 143 | * @src_clk: Pointer to the clock used to generate SPI signals. |
146 | * @master: Pointer to the SPI Protocol master. | 144 | * @master: Pointer to the SPI Protocol master. |
147 | * @workqueue: Work queue for the SPI xfer requests. | ||
148 | * @cntrlr_info: Platform specific data for the controller this driver manages. | 145 | * @cntrlr_info: Platform specific data for the controller this driver manages. |
149 | * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint. | 146 | * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint. |
150 | * @work: Work | ||
151 | * @queue: To log SPI xfer requests. | 147 | * @queue: To log SPI xfer requests. |
152 | * @lock: Controller specific lock. | 148 | * @lock: Controller specific lock. |
153 | * @state: Set of FLAGS to indicate status. | 149 | * @state: Set of FLAGS to indicate status. |
@@ -167,10 +163,8 @@ struct s3c64xx_spi_driver_data { | |||
167 | struct clk *src_clk; | 163 | struct clk *src_clk; |
168 | struct platform_device *pdev; | 164 | struct platform_device *pdev; |
169 | struct spi_master *master; | 165 | struct spi_master *master; |
170 | struct workqueue_struct *workqueue; | ||
171 | struct s3c64xx_spi_info *cntrlr_info; | 166 | struct s3c64xx_spi_info *cntrlr_info; |
172 | struct spi_device *tgl_spi; | 167 | struct spi_device *tgl_spi; |
173 | struct work_struct work; | ||
174 | struct list_head queue; | 168 | struct list_head queue; |
175 | spinlock_t lock; | 169 | spinlock_t lock; |
176 | unsigned long sfr_start; | 170 | unsigned long sfr_start; |
@@ -637,9 +631,10 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
637 | } | 631 | } |
638 | } | 632 | } |
639 | 633 | ||
640 | static void handle_msg(struct s3c64xx_spi_driver_data *sdd, | 634 | static int s3c64xx_spi_transfer_one_message(struct spi_master *master, |
641 | struct spi_message *msg) | 635 | struct spi_message *msg) |
642 | { | 636 | { |
637 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | ||
643 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; | 638 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; |
644 | struct spi_device *spi = msg->spi; | 639 | struct spi_device *spi = msg->spi; |
645 | struct s3c64xx_spi_csinfo *cs = spi->controller_data; | 640 | struct s3c64xx_spi_csinfo *cs = spi->controller_data; |
@@ -771,13 +766,15 @@ out: | |||
771 | 766 | ||
772 | if (msg->complete) | 767 | if (msg->complete) |
773 | msg->complete(msg->context); | 768 | msg->complete(msg->context); |
769 | |||
770 | spi_finalize_current_message(master); | ||
771 | |||
772 | return 0; | ||
774 | } | 773 | } |
775 | 774 | ||
776 | static void s3c64xx_spi_work(struct work_struct *work) | 775 | static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) |
777 | { | 776 | { |
778 | struct s3c64xx_spi_driver_data *sdd = container_of(work, | 777 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); |
779 | struct s3c64xx_spi_driver_data, work); | ||
780 | unsigned long flags; | ||
781 | 778 | ||
782 | /* Acquire DMA channels */ | 779 | /* Acquire DMA channels */ |
783 | while (!acquire_dma(sdd)) | 780 | while (!acquire_dma(sdd)) |
@@ -785,61 +782,18 @@ static void s3c64xx_spi_work(struct work_struct *work) | |||
785 | 782 | ||
786 | pm_runtime_get_sync(&sdd->pdev->dev); | 783 | pm_runtime_get_sync(&sdd->pdev->dev); |
787 | 784 | ||
788 | spin_lock_irqsave(&sdd->lock, flags); | 785 | return 0; |
789 | 786 | } | |
790 | while (!list_empty(&sdd->queue) | ||
791 | && !(sdd->state & SUSPND)) { | ||
792 | |||
793 | struct spi_message *msg; | ||
794 | |||
795 | msg = container_of(sdd->queue.next, struct spi_message, queue); | ||
796 | |||
797 | list_del_init(&msg->queue); | ||
798 | |||
799 | /* Set Xfer busy flag */ | ||
800 | sdd->state |= SPIBUSY; | ||
801 | |||
802 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
803 | |||
804 | handle_msg(sdd, msg); | ||
805 | |||
806 | spin_lock_irqsave(&sdd->lock, flags); | ||
807 | |||
808 | sdd->state &= ~SPIBUSY; | ||
809 | } | ||
810 | 787 | ||
811 | spin_unlock_irqrestore(&sdd->lock, flags); | 788 | static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) |
789 | { | ||
790 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); | ||
812 | 791 | ||
813 | /* Free DMA channels */ | 792 | /* Free DMA channels */ |
814 | sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client); | 793 | sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client); |
815 | sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client); | 794 | sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client); |
816 | 795 | ||
817 | pm_runtime_put(&sdd->pdev->dev); | 796 | pm_runtime_put(&sdd->pdev->dev); |
818 | } | ||
819 | |||
820 | static int s3c64xx_spi_transfer(struct spi_device *spi, | ||
821 | struct spi_message *msg) | ||
822 | { | ||
823 | struct s3c64xx_spi_driver_data *sdd; | ||
824 | unsigned long flags; | ||
825 | |||
826 | sdd = spi_master_get_devdata(spi->master); | ||
827 | |||
828 | spin_lock_irqsave(&sdd->lock, flags); | ||
829 | |||
830 | if (sdd->state & SUSPND) { | ||
831 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
832 | return -ESHUTDOWN; | ||
833 | } | ||
834 | |||
835 | msg->status = -EINPROGRESS; | ||
836 | msg->actual_length = 0; | ||
837 | |||
838 | list_add_tail(&msg->queue, &sdd->queue); | ||
839 | |||
840 | queue_work(sdd->workqueue, &sdd->work); | ||
841 | |||
842 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
843 | 797 | ||
844 | return 0; | 798 | return 0; |
845 | } | 799 | } |
@@ -879,13 +833,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
879 | } | 833 | } |
880 | } | 834 | } |
881 | 835 | ||
882 | if (sdd->state & SUSPND) { | ||
883 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
884 | dev_err(&spi->dev, | ||
885 | "setup: SPI-%d not active!\n", spi->master->bus_num); | ||
886 | return -ESHUTDOWN; | ||
887 | } | ||
888 | |||
889 | spin_unlock_irqrestore(&sdd->lock, flags); | 836 | spin_unlock_irqrestore(&sdd->lock, flags); |
890 | 837 | ||
891 | if (spi->bits_per_word != 8 | 838 | if (spi->bits_per_word != 8 |
@@ -1073,7 +1020,9 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
1073 | 1020 | ||
1074 | master->bus_num = pdev->id; | 1021 | master->bus_num = pdev->id; |
1075 | master->setup = s3c64xx_spi_setup; | 1022 | master->setup = s3c64xx_spi_setup; |
1076 | master->transfer = s3c64xx_spi_transfer; | 1023 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; |
1024 | master->transfer_one_message = s3c64xx_spi_transfer_one_message; | ||
1025 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; | ||
1077 | master->num_chipselect = sci->num_cs; | 1026 | master->num_chipselect = sci->num_cs; |
1078 | master->dma_alignment = 8; | 1027 | master->dma_alignment = 8; |
1079 | /* the spi->mode bits understood by this driver: */ | 1028 | /* the spi->mode bits understood by this driver: */ |
@@ -1128,27 +1077,18 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
1128 | goto err6; | 1077 | goto err6; |
1129 | } | 1078 | } |
1130 | 1079 | ||
1131 | sdd->workqueue = create_singlethread_workqueue( | ||
1132 | dev_name(master->dev.parent)); | ||
1133 | if (sdd->workqueue == NULL) { | ||
1134 | dev_err(&pdev->dev, "Unable to create workqueue\n"); | ||
1135 | ret = -ENOMEM; | ||
1136 | goto err7; | ||
1137 | } | ||
1138 | |||
1139 | /* Setup Deufult Mode */ | 1080 | /* Setup Deufult Mode */ |
1140 | s3c64xx_spi_hwinit(sdd, pdev->id); | 1081 | s3c64xx_spi_hwinit(sdd, pdev->id); |
1141 | 1082 | ||
1142 | spin_lock_init(&sdd->lock); | 1083 | spin_lock_init(&sdd->lock); |
1143 | init_completion(&sdd->xfer_completion); | 1084 | init_completion(&sdd->xfer_completion); |
1144 | INIT_WORK(&sdd->work, s3c64xx_spi_work); | ||
1145 | INIT_LIST_HEAD(&sdd->queue); | 1085 | INIT_LIST_HEAD(&sdd->queue); |
1146 | 1086 | ||
1147 | ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd); | 1087 | ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd); |
1148 | if (ret != 0) { | 1088 | if (ret != 0) { |
1149 | dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", | 1089 | dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", |
1150 | irq, ret); | 1090 | irq, ret); |
1151 | goto err8; | 1091 | goto err7; |
1152 | } | 1092 | } |
1153 | 1093 | ||
1154 | writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN | | 1094 | writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN | |
@@ -1158,7 +1098,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
1158 | if (spi_register_master(master)) { | 1098 | if (spi_register_master(master)) { |
1159 | dev_err(&pdev->dev, "cannot register SPI master\n"); | 1099 | dev_err(&pdev->dev, "cannot register SPI master\n"); |
1160 | ret = -EBUSY; | 1100 | ret = -EBUSY; |
1161 | goto err9; | 1101 | goto err8; |
1162 | } | 1102 | } |
1163 | 1103 | ||
1164 | dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " | 1104 | dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " |
@@ -1172,10 +1112,8 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
1172 | 1112 | ||
1173 | return 0; | 1113 | return 0; |
1174 | 1114 | ||
1175 | err9: | ||
1176 | free_irq(irq, sdd); | ||
1177 | err8: | 1115 | err8: |
1178 | destroy_workqueue(sdd->workqueue); | 1116 | free_irq(irq, sdd); |
1179 | err7: | 1117 | err7: |
1180 | clk_disable(sdd->src_clk); | 1118 | clk_disable(sdd->src_clk); |
1181 | err6: | 1119 | err6: |
@@ -1201,25 +1139,15 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) | |||
1201 | struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); | 1139 | struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); |
1202 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1140 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1203 | struct resource *mem_res; | 1141 | struct resource *mem_res; |
1204 | unsigned long flags; | ||
1205 | 1142 | ||
1206 | pm_runtime_disable(&pdev->dev); | 1143 | pm_runtime_disable(&pdev->dev); |
1207 | 1144 | ||
1208 | spin_lock_irqsave(&sdd->lock, flags); | ||
1209 | sdd->state |= SUSPND; | ||
1210 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
1211 | |||
1212 | while (sdd->state & SPIBUSY) | ||
1213 | msleep(10); | ||
1214 | |||
1215 | spi_unregister_master(master); | 1145 | spi_unregister_master(master); |
1216 | 1146 | ||
1217 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); | 1147 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); |
1218 | 1148 | ||
1219 | free_irq(platform_get_irq(pdev, 0), sdd); | 1149 | free_irq(platform_get_irq(pdev, 0), sdd); |
1220 | 1150 | ||
1221 | destroy_workqueue(sdd->workqueue); | ||
1222 | |||
1223 | clk_disable(sdd->src_clk); | 1151 | clk_disable(sdd->src_clk); |
1224 | clk_put(sdd->src_clk); | 1152 | clk_put(sdd->src_clk); |
1225 | 1153 | ||
@@ -1243,14 +1171,8 @@ static int s3c64xx_spi_suspend(struct device *dev) | |||
1243 | { | 1171 | { |
1244 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); | 1172 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); |
1245 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1173 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1246 | unsigned long flags; | ||
1247 | |||
1248 | spin_lock_irqsave(&sdd->lock, flags); | ||
1249 | sdd->state |= SUSPND; | ||
1250 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
1251 | 1174 | ||
1252 | while (sdd->state & SPIBUSY) | 1175 | spi_master_suspend(master); |
1253 | msleep(10); | ||
1254 | 1176 | ||
1255 | /* Disable the clock */ | 1177 | /* Disable the clock */ |
1256 | clk_disable(sdd->src_clk); | 1178 | clk_disable(sdd->src_clk); |
@@ -1267,7 +1189,6 @@ static int s3c64xx_spi_resume(struct device *dev) | |||
1267 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); | 1189 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); |
1268 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1190 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1269 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; | 1191 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; |
1270 | unsigned long flags; | ||
1271 | 1192 | ||
1272 | sci->cfg_gpio(pdev); | 1193 | sci->cfg_gpio(pdev); |
1273 | 1194 | ||
@@ -1277,9 +1198,7 @@ static int s3c64xx_spi_resume(struct device *dev) | |||
1277 | 1198 | ||
1278 | s3c64xx_spi_hwinit(sdd, pdev->id); | 1199 | s3c64xx_spi_hwinit(sdd, pdev->id); |
1279 | 1200 | ||
1280 | spin_lock_irqsave(&sdd->lock, flags); | 1201 | spi_master_resume(master); |
1281 | sdd->state &= ~SUSPND; | ||
1282 | spin_unlock_irqrestore(&sdd->lock, flags); | ||
1283 | 1202 | ||
1284 | return 0; | 1203 | return 0; |
1285 | } | 1204 | } |