]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
spi/s3c64xx: Convert to using core message queue
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 15 Feb 2012 22:48:32 +0000 (14:48 -0800)
committerGrant Likely <grant.likely@secretlab.ca>
Fri, 9 Mar 2012 21:40:13 +0000 (14:40 -0700)
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>
drivers/spi/spi-s3c64xx.c

index b899af6640a21fecfe070494e25c515b3bfdbb73..1174d802ff4572d1c8434c94c6d12c340793d536 100644 (file)
 
 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
 
-#define SUSPND    (1<<0)
-#define SPIBUSY   (1<<1)
 #define RXBUSY    (1<<2)
 #define TXBUSY    (1<<3)
 
@@ -144,10 +142,8 @@ struct s3c64xx_spi_dma_data {
  * @clk: Pointer to the spi clock.
  * @src_clk: Pointer to the clock used to generate SPI signals.
  * @master: Pointer to the SPI Protocol master.
- * @workqueue: Work queue for the SPI xfer requests.
  * @cntrlr_info: Platform specific data for the controller this driver manages.
  * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
- * @work: Work
  * @queue: To log SPI xfer requests.
  * @lock: Controller specific lock.
  * @state: Set of FLAGS to indicate status.
@@ -167,10 +163,8 @@ struct s3c64xx_spi_driver_data {
        struct clk                      *src_clk;
        struct platform_device          *pdev;
        struct spi_master               *master;
-       struct workqueue_struct         *workqueue;
        struct s3c64xx_spi_info  *cntrlr_info;
        struct spi_device               *tgl_spi;
-       struct work_struct              work;
        struct list_head                queue;
        spinlock_t                      lock;
        unsigned long                   sfr_start;
@@ -637,9 +631,10 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
        }
 }
 
-static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
-                                       struct spi_message *msg)
+static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
+                                           struct spi_message *msg)
 {
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct spi_device *spi = msg->spi;
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
@@ -771,13 +766,15 @@ out:
 
        if (msg->complete)
                msg->complete(msg->context);
+
+       spi_finalize_current_message(master);
+
+       return 0;
 }
 
-static void s3c64xx_spi_work(struct work_struct *work)
+static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 {
-       struct s3c64xx_spi_driver_data *sdd = container_of(work,
-                                       struct s3c64xx_spi_driver_data, work);
-       unsigned long flags;
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
 
        /* Acquire DMA channels */
        while (!acquire_dma(sdd))
@@ -785,61 +782,18 @@ static void s3c64xx_spi_work(struct work_struct *work)
 
        pm_runtime_get_sync(&sdd->pdev->dev);
 
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       while (!list_empty(&sdd->queue)
-                               && !(sdd->state & SUSPND)) {
-
-               struct spi_message *msg;
-
-               msg = container_of(sdd->queue.next, struct spi_message, queue);
-
-               list_del_init(&msg->queue);
-
-               /* Set Xfer busy flag */
-               sdd->state |= SPIBUSY;
-
-               spin_unlock_irqrestore(&sdd->lock, flags);
-
-               handle_msg(sdd, msg);
-
-               spin_lock_irqsave(&sdd->lock, flags);
-
-               sdd->state &= ~SPIBUSY;
-       }
+       return 0;
+}
 
-       spin_unlock_irqrestore(&sdd->lock, flags);
+static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
+{
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
 
        /* Free DMA channels */
        sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
        sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
 
        pm_runtime_put(&sdd->pdev->dev);
-}
-
-static int s3c64xx_spi_transfer(struct spi_device *spi,
-                                               struct spi_message *msg)
-{
-       struct s3c64xx_spi_driver_data *sdd;
-       unsigned long flags;
-
-       sdd = spi_master_get_devdata(spi->master);
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       if (sdd->state & SUSPND) {
-               spin_unlock_irqrestore(&sdd->lock, flags);
-               return -ESHUTDOWN;
-       }
-
-       msg->status = -EINPROGRESS;
-       msg->actual_length = 0;
-
-       list_add_tail(&msg->queue, &sdd->queue);
-
-       queue_work(sdd->workqueue, &sdd->work);
-
-       spin_unlock_irqrestore(&sdd->lock, flags);
 
        return 0;
 }
@@ -879,13 +833,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                }
        }
 
-       if (sdd->state & SUSPND) {
-               spin_unlock_irqrestore(&sdd->lock, flags);
-               dev_err(&spi->dev,
-                       "setup: SPI-%d not active!\n", spi->master->bus_num);
-               return -ESHUTDOWN;
-       }
-
        spin_unlock_irqrestore(&sdd->lock, flags);
 
        if (spi->bits_per_word != 8
@@ -1073,7 +1020,9 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 
        master->bus_num = pdev->id;
        master->setup = s3c64xx_spi_setup;
-       master->transfer = s3c64xx_spi_transfer;
+       master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
+       master->transfer_one_message = s3c64xx_spi_transfer_one_message;
+       master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
        master->num_chipselect = sci->num_cs;
        master->dma_alignment = 8;
        /* the spi->mode bits understood by this driver: */
@@ -1128,27 +1077,18 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                goto err6;
        }
 
-       sdd->workqueue = create_singlethread_workqueue(
-                                               dev_name(master->dev.parent));
-       if (sdd->workqueue == NULL) {
-               dev_err(&pdev->dev, "Unable to create workqueue\n");
-               ret = -ENOMEM;
-               goto err7;
-       }
-
        /* Setup Deufult Mode */
        s3c64xx_spi_hwinit(sdd, pdev->id);
 
        spin_lock_init(&sdd->lock);
        init_completion(&sdd->xfer_completion);
-       INIT_WORK(&sdd->work, s3c64xx_spi_work);
        INIT_LIST_HEAD(&sdd->queue);
 
        ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
                        irq, ret);
-               goto err8;
+               goto err7;
        }
 
        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)
        if (spi_register_master(master)) {
                dev_err(&pdev->dev, "cannot register SPI master\n");
                ret = -EBUSY;
-               goto err9;
+               goto err8;
        }
 
        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)
 
        return 0;
 
-err9:
-       free_irq(irq, sdd);
 err8:
-       destroy_workqueue(sdd->workqueue);
+       free_irq(irq, sdd);
 err7:
        clk_disable(sdd->src_clk);
 err6:
@@ -1201,25 +1139,15 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
        struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        struct resource *mem_res;
-       unsigned long flags;
 
        pm_runtime_disable(&pdev->dev);
 
-       spin_lock_irqsave(&sdd->lock, flags);
-       sdd->state |= SUSPND;
-       spin_unlock_irqrestore(&sdd->lock, flags);
-
-       while (sdd->state & SPIBUSY)
-               msleep(10);
-
        spi_unregister_master(master);
 
        writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
 
        free_irq(platform_get_irq(pdev, 0), sdd);
 
-       destroy_workqueue(sdd->workqueue);
-
        clk_disable(sdd->src_clk);
        clk_put(sdd->src_clk);
 
@@ -1243,14 +1171,8 @@ static int s3c64xx_spi_suspend(struct device *dev)
 {
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-       sdd->state |= SUSPND;
-       spin_unlock_irqrestore(&sdd->lock, flags);
 
-       while (sdd->state & SPIBUSY)
-               msleep(10);
+       spi_master_suspend(master);
 
        /* Disable the clock */
        clk_disable(sdd->src_clk);
@@ -1267,7 +1189,6 @@ static int s3c64xx_spi_resume(struct device *dev)
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-       unsigned long flags;
 
        sci->cfg_gpio(pdev);
 
@@ -1277,9 +1198,7 @@ static int s3c64xx_spi_resume(struct device *dev)
 
        s3c64xx_spi_hwinit(sdd, pdev->id);
 
-       spin_lock_irqsave(&sdd->lock, flags);
-       sdd->state &= ~SUSPND;
-       spin_unlock_irqrestore(&sdd->lock, flags);
+       spi_master_resume(master);
 
        return 0;
 }