aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-15 17:48:32 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-03-09 16:40:13 -0500
commitad2a99af0d7242726723575efaffa1625664b384 (patch)
treea9114736ed9b0d81540e5bad4d6122ca5a84374c /drivers/spi
parent5e8afa34cc4ab2cea3472b80317a929b83b3c65b (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.c125
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
640static void handle_msg(struct s3c64xx_spi_driver_data *sdd, 634static 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
776static void s3c64xx_spi_work(struct work_struct *work) 775static 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); 788static 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
820static 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
1175err9:
1176 free_irq(irq, sdd);
1177err8: 1115err8:
1178 destroy_workqueue(sdd->workqueue); 1116 free_irq(irq, sdd);
1179err7: 1117err7:
1180 clk_disable(sdd->src_clk); 1118 clk_disable(sdd->src_clk);
1181err6: 1119err6:
@@ -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}