spi: rspi: Use core message handling

Let the generic SPI core handle SPI messages, calling into our
rspi_transfer_one() method.

rspi_assert_ssl() and rspi_negate_ssl() are absorbed into
rspi_prepare_message() and rspi_unprepare_message(), as they actually
enable/disable the whole SPI function, instead of just (de)asserting the
chip select line.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Geert Uytterhoeven 2014-01-24 09:43:52 +01:00 committed by Mark Brown
parent 91949a2d4a
commit 79d2349542
1 changed files with 34 additions and 77 deletions

View File

@ -25,8 +25,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
@ -181,10 +179,7 @@ struct rspi_data {
void __iomem *addr; void __iomem *addr;
u32 max_speed_hz; u32 max_speed_hz;
struct spi_master *master; struct spi_master *master;
struct list_head queue;
struct work_struct ws;
wait_queue_head_t wait; wait_queue_head_t wait;
spinlock_t lock;
struct clk *clk; struct clk *clk;
u8 spsr; u8 spsr;
u16 spcmd; u16 spcmd;
@ -345,16 +340,6 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
return 0; return 0;
} }
static void rspi_assert_ssl(const struct rspi_data *rspi)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
}
static void rspi_negate_ssl(const struct rspi_data *rspi)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
}
static int rspi_send_pio(struct rspi_data *rspi, struct spi_transfer *t) static int rspi_send_pio(struct rspi_data *rspi, struct spi_transfer *t)
{ {
int remain = t->len; int remain = t->len;
@ -739,56 +724,27 @@ static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
return 0; return 0;
} }
static void rspi_work(struct work_struct *work) static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = container_of(work, struct rspi_data, ws); struct rspi_data *rspi = spi_master_get_devdata(master);
struct spi_message *mesg; int ret = 0;
struct spi_transfer *t;
unsigned long flags;
int ret;
while (1) { if (xfer->tx_buf) {
spin_lock_irqsave(&rspi->lock, flags); if (rspi_is_dma(rspi, xfer))
if (list_empty(&rspi->queue)) { ret = rspi_send_dma(rspi, xfer);
spin_unlock_irqrestore(&rspi->lock, flags); else
break; ret = send_pio(rspi, xfer);
} if (ret < 0)
mesg = list_entry(rspi->queue.next, struct spi_message, queue); return ret;
list_del_init(&mesg->queue);
spin_unlock_irqrestore(&rspi->lock, flags);
rspi_assert_ssl(rspi);
list_for_each_entry(t, &mesg->transfers, transfer_list) {
if (t->tx_buf) {
if (rspi_is_dma(rspi, t))
ret = rspi_send_dma(rspi, t);
else
ret = send_pio(rspi, t);
if (ret < 0)
goto error;
}
if (t->rx_buf) {
if (rspi_is_dma(rspi, t))
ret = rspi_receive_dma(rspi, t);
else
ret = receive_pio(rspi, t);
if (ret < 0)
goto error;
}
mesg->actual_length += t->len;
}
rspi_negate_ssl(rspi);
mesg->status = 0;
mesg->complete(mesg->context);
} }
if (xfer->rx_buf) {
return; if (rspi_is_dma(rspi, xfer))
ret = rspi_receive_dma(rspi, xfer);
error: else
mesg->status = ret; ret = receive_pio(rspi, xfer);
mesg->complete(mesg->context); }
return ret;
} }
static int rspi_setup(struct spi_device *spi) static int rspi_setup(struct spi_device *spi)
@ -808,24 +764,26 @@ static int rspi_setup(struct spi_device *spi)
return 0; return 0;
} }
static int rspi_transfer(struct spi_device *spi, struct spi_message *mesg) static void rspi_cleanup(struct spi_device *spi)
{ {
struct rspi_data *rspi = spi_master_get_devdata(spi->master); }
unsigned long flags;
mesg->actual_length = 0; static int rspi_prepare_message(struct spi_master *master,
mesg->status = -EINPROGRESS; struct spi_message *message)
{
spin_lock_irqsave(&rspi->lock, flags); struct rspi_data *rspi = spi_master_get_devdata(master);
list_add_tail(&mesg->queue, &rspi->queue);
schedule_work(&rspi->ws);
spin_unlock_irqrestore(&rspi->lock, flags);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
return 0; return 0;
} }
static void rspi_cleanup(struct spi_device *spi) static int rspi_unprepare_message(struct spi_master *master,
struct spi_message *message)
{ {
struct rspi_data *rspi = spi_master_get_devdata(master);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
return 0;
} }
static irqreturn_t rspi_irq(int irq, void *_sr) static irqreturn_t rspi_irq(int irq, void *_sr)
@ -972,9 +930,6 @@ static int rspi_probe(struct platform_device *pdev)
} }
clk_enable(rspi->clk); clk_enable(rspi->clk);
INIT_LIST_HEAD(&rspi->queue);
spin_lock_init(&rspi->lock);
INIT_WORK(&rspi->ws, rspi_work);
init_waitqueue_head(&rspi->wait); init_waitqueue_head(&rspi->wait);
if (rspi_pd && rspi_pd->num_chipselect) if (rspi_pd && rspi_pd->num_chipselect)
@ -984,8 +939,10 @@ static int rspi_probe(struct platform_device *pdev)
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->setup = rspi_setup; master->setup = rspi_setup;
master->transfer = rspi_transfer; master->transfer_one = rspi_transfer_one;
master->cleanup = rspi_cleanup; master->cleanup = rspi_cleanup;
master->prepare_message = rspi_prepare_message;
master->unprepare_message = rspi_unprepare_message;
master->mode_bits = SPI_CPHA | SPI_CPOL; master->mode_bits = SPI_CPHA | SPI_CPOL;
ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0, ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,