Skip to content

Commit

Permalink
spi/s3c64xx: Convert to using core message queue
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Brown authored and Grant Likely committed Mar 9, 2012
1 parent 5e8afa3 commit ad2a99a
Showing 1 changed file with 22 additions and 103 deletions.
125 changes: 22 additions & 103 deletions drivers/spi/spi-s3c64xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@

#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)

Expand All @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -771,75 +766,34 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,

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))
msleep(10);

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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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: */
Expand Down Expand Up @@ -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 |
Expand All @@ -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 "
Expand All @@ -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:
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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;
}
Expand Down

0 comments on commit ad2a99a

Please sign in to comment.