summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-rspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-rspi.c')
-rw-r--r--drivers/spi/spi-rspi.c273
1 files changed, 41 insertions, 232 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 9e829ce..8719206 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -59,14 +59,6 @@
#define RSPI_SPCMD6 0x1c
#define RSPI_SPCMD7 0x1e
-/*qspi only */
-#define QSPI_SPBFCR 0x18
-#define QSPI_SPBDCR 0x1a
-#define QSPI_SPBMUL0 0x1c
-#define QSPI_SPBMUL1 0x20
-#define QSPI_SPBMUL2 0x24
-#define QSPI_SPBMUL3 0x28
-
/* SPCR */
#define SPCR_SPRIE 0x80
#define SPCR_SPE 0x40
@@ -134,8 +126,6 @@
#define SPCMD_LSBF 0x1000
#define SPCMD_SPB_MASK 0x0f00
#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
-#define SPCMD_SPB_8BIT 0x0000 /* qspi only */
-#define SPCMD_SPB_16BIT 0x0100
#define SPCMD_SPB_20BIT 0x0000
#define SPCMD_SPB_24BIT 0x0100
#define SPCMD_SPB_32BIT 0x0200
@@ -145,10 +135,6 @@
#define SPCMD_CPOL 0x0002
#define SPCMD_CPHA 0x0001
-/* SPBFCR */
-#define SPBFCR_TXRST 0x80 /* qspi only */
-#define SPBFCR_RXRST 0x40 /* qspi only */
-
struct rspi_data {
void __iomem *addr;
u32 max_speed_hz;
@@ -159,7 +145,6 @@ struct rspi_data {
spinlock_t lock;
struct clk *clk;
unsigned char spsr;
- const struct spi_ops *ops;
/* for dmaengine */
struct dma_chan *chan_tx;
@@ -180,11 +165,6 @@ static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
iowrite16(data, rspi->addr + offset);
}
-static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
-{
- iowrite32(data, rspi->addr + offset);
-}
-
static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
{
return ioread8(rspi->addr + offset);
@@ -195,103 +175,17 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
return ioread16(rspi->addr + offset);
}
-/* optional functions */
-struct spi_ops {
- int (*set_config_register)(struct rspi_data *rspi, int access_size);
- int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
- struct spi_transfer *t);
- int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
- struct spi_transfer *t);
-
-};
-
-/*
- * functions for RSPI
- */
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
-{
- int spbr;
-
- /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
- rspi_write8(rspi, 0x00, RSPI_SPPCR);
-
- /* Sets transfer bit rate */
- spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
- rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
-
- /* Sets number of frames to be used: 1 frame */
- rspi_write8(rspi, 0x00, RSPI_SPDCR);
-
- /* Sets RSPCK, SSL, next-access delay value */
- rspi_write8(rspi, 0x00, RSPI_SPCKD);
- rspi_write8(rspi, 0x00, RSPI_SSLND);
- rspi_write8(rspi, 0x00, RSPI_SPND);
-
- /* Sets parity, interrupt mask */
- rspi_write8(rspi, 0x00, RSPI_SPCR2);
-
- /* Sets SPCMD */
- rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
- RSPI_SPCMD0);
-
- /* Sets RSPI mode */
- rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
-
- return 0;
-}
-
-/*
- * functions for QSPI
- */
-static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
+static unsigned char rspi_calc_spbr(struct rspi_data *rspi)
{
- u16 spcmd;
- int spbr;
-
- /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
- rspi_write8(rspi, 0x00, RSPI_SPPCR);
-
- /* Sets transfer bit rate */
- spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
- rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
-
- /* Sets number of frames to be used: 1 frame */
- rspi_write8(rspi, 0x00, RSPI_SPDCR);
-
- /* Sets RSPCK, SSL, next-access delay value */
- rspi_write8(rspi, 0x00, RSPI_SPCKD);
- rspi_write8(rspi, 0x00, RSPI_SSLND);
- rspi_write8(rspi, 0x00, RSPI_SPND);
-
- /* Data Length Setting */
- if (access_size == 8)
- spcmd = SPCMD_SPB_8BIT;
- else if (access_size == 16)
- spcmd = SPCMD_SPB_16BIT;
- else if (access_size == 32)
- spcmd = SPCMD_SPB_32BIT;
-
- spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
-
- /* Resets transfer data length */
- rspi_write32(rspi, 0, QSPI_SPBMUL0);
-
- /* Resets transmit and receive buffer */
- rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
- /* Sets buffer to allow normal operation */
- rspi_write8(rspi, 0x00, QSPI_SPBFCR);
-
- /* Sets SPCMD */
- rspi_write16(rspi, spcmd, RSPI_SPCMD0);
+ int tmp;
+ unsigned char spbr;
- /* Enables SPI function in a master mode */
- rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
+ tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
+ spbr = clamp(tmp, 0, 255);
- return 0;
+ return spbr;
}
-#define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
-
static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
@@ -326,60 +220,54 @@ static void rspi_negate_ssl(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_message *mesg,
- struct spi_transfer *t)
+static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
{
- int remain = t->len;
- u8 *data;
+ /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
+ rspi_write8(rspi, 0x00, RSPI_SPPCR);
- data = (u8 *)t->tx_buf;
- while (remain > 0) {
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
- RSPI_SPCR);
+ /* Sets transfer bit rate */
+ rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR);
- if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: tx empty timeout\n", __func__);
- return -ETIMEDOUT;
- }
+ /* Sets number of frames to be used: 1 frame */
+ rspi_write8(rspi, 0x00, RSPI_SPDCR);
- rspi_write16(rspi, *data, RSPI_SPDR);
- data++;
- remain--;
- }
+ /* Sets RSPCK, SSL, next-access delay value */
+ rspi_write8(rspi, 0x00, RSPI_SPCKD);
+ rspi_write8(rspi, 0x00, RSPI_SSLND);
+ rspi_write8(rspi, 0x00, RSPI_SPND);
- /* Waiting for the last transmition */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ /* Sets parity, interrupt mask */
+ rspi_write8(rspi, 0x00, RSPI_SPCR2);
+
+ /* Sets SPCMD */
+ rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
+ RSPI_SPCMD0);
+
+ /* Sets RSPI mode */
+ rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
return 0;
}
-static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
+static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
int remain = t->len;
u8 *data;
- rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
- rspi_write8(rspi, 0x00, QSPI_SPBFCR);
-
data = (u8 *)t->tx_buf;
while (remain > 0) {
+ rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
+ RSPI_SPCR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
"%s: tx empty timeout\n", __func__);
return -ETIMEDOUT;
}
- rspi_write8(rspi, *data++, RSPI_SPDR);
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: receive timeout\n", __func__);
- return -ETIMEDOUT;
- }
- rspi_read8(rspi, RSPI_SPDR);
+ rspi_write16(rspi, *data, RSPI_SPDR);
+ data++;
remain--;
}
@@ -389,8 +277,6 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
return 0;
}
-#define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t)
-
static void rspi_dma_complete(void *arg)
{
struct rspi_data *rspi = arg;
@@ -556,51 +442,6 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
return 0;
}
-static void qspi_receive_init(struct rspi_data *rspi)
-{
- unsigned char spsr;
-
- spsr = rspi_read8(rspi, RSPI_SPSR);
- if (spsr & SPSR_SPRF)
- rspi_read8(rspi, RSPI_SPDR); /* dummy read */
- rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
- rspi_write8(rspi, 0x00, QSPI_SPBFCR);
-}
-
-static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
- struct spi_transfer *t)
-{
- int remain = t->len;
- u8 *data;
-
- qspi_receive_init(rspi);
-
- data = (u8 *)t->rx_buf;
- while (remain > 0) {
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: tx empty timeout\n", __func__);
- return -ETIMEDOUT;
- }
- /* dummy write for generate clock */
- rspi_write8(rspi, 0x00, RSPI_SPDR);
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: receive timeout\n", __func__);
- return -ETIMEDOUT;
- }
- /* SPDR allows 8, 16 or 32-bit access */
- *data++ = rspi_read8(rspi, RSPI_SPDR);
- remain--;
- }
-
- return 0;
-}
-
-#define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t)
-
static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
struct scatterlist sg, sg_dummy;
@@ -740,7 +581,7 @@ static void rspi_work(struct work_struct *work)
if (rspi_is_dma(rspi, t))
ret = rspi_send_dma(rspi, t);
else
- ret = send_pio(rspi, mesg, t);
+ ret = rspi_send_pio(rspi, mesg, t);
if (ret < 0)
goto error;
}
@@ -748,7 +589,7 @@ static void rspi_work(struct work_struct *work)
if (rspi_is_dma(rspi, t))
ret = rspi_receive_dma(rspi, t);
else
- ret = receive_pio(rspi, mesg, t);
+ ret = rspi_receive_pio(rspi, mesg, t);
if (ret < 0)
goto error;
}
@@ -775,7 +616,7 @@ static int rspi_setup(struct spi_device *spi)
spi->bits_per_word = 8;
rspi->max_speed_hz = spi->max_speed_hz;
- set_config_register(rspi, 8);
+ rspi_set_config_register(rspi, 8);
return 0;
}
@@ -885,13 +726,14 @@ static void rspi_release_dma(struct rspi_data *rspi)
static int rspi_remove(struct platform_device *pdev)
{
- struct rspi_data *rspi = platform_get_drvdata(pdev);
+ struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
spi_unregister_master(rspi->master);
rspi_release_dma(rspi);
free_irq(platform_get_irq(pdev, 0), rspi);
clk_put(rspi->clk);
iounmap(rspi->addr);
+ spi_master_put(rspi->master);
return 0;
}
@@ -903,16 +745,7 @@ static int rspi_probe(struct platform_device *pdev)
struct rspi_data *rspi;
int ret, irq;
char clk_name[16];
- struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
- const struct spi_ops *ops;
- const struct platform_device_id *id_entry = pdev->id_entry;
-
- ops = (struct spi_ops *)id_entry->driver_data;
- /* ops parameter check */
- if (!ops->set_config_register) {
- dev_err(&pdev->dev, "there is no set_config_register\n");
- return -ENODEV;
- }
+
/* get base addr */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(res == NULL)) {
@@ -934,7 +767,7 @@ static int rspi_probe(struct platform_device *pdev)
rspi = spi_master_get_devdata(master);
platform_set_drvdata(pdev, rspi);
- rspi->ops = ops;
+
rspi->master = master;
rspi->addr = ioremap(res->start, resource_size(res));
if (rspi->addr == NULL) {
@@ -943,7 +776,7 @@ static int rspi_probe(struct platform_device *pdev)
goto error1;
}
- snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
+ snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id);
rspi->clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(rspi->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
@@ -957,10 +790,7 @@ static int rspi_probe(struct platform_device *pdev)
INIT_WORK(&rspi->ws, rspi_work);
init_waitqueue_head(&rspi->wait);
- master->num_chipselect = rspi_pd->num_chipselect;
- if (!master->num_chipselect)
- master->num_chipselect = 2; /* default */
-
+ master->num_chipselect = 2;
master->bus_num = pdev->id;
master->setup = rspi_setup;
master->transfer = rspi_transfer;
@@ -1002,32 +832,11 @@ error1:
return ret;
}
-static struct spi_ops rspi_ops = {
- .set_config_register = rspi_set_config_register,
- .send_pio = rspi_send_pio,
- .receive_pio = rspi_receive_pio,
-};
-
-static struct spi_ops qspi_ops = {
- .set_config_register = qspi_set_config_register,
- .send_pio = qspi_send_pio,
- .receive_pio = qspi_receive_pio,
-};
-
-static struct platform_device_id spi_driver_ids[] = {
- { "rspi", (kernel_ulong_t)&rspi_ops },
- { "qspi", (kernel_ulong_t)&qspi_ops },
- {},
-};
-
-MODULE_DEVICE_TABLE(platform, spi_driver_ids);
-
static struct platform_driver rspi_driver = {
.probe = rspi_probe,
.remove = rspi_remove,
- .id_table = spi_driver_ids,
.driver = {
- .name = "renesas_spi",
+ .name = "rspi",
.owner = THIS_MODULE,
},
};