summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig1
-rw-r--r--drivers/spi/spi-altera.c163
-rw-r--r--drivers/spi/spi-ath79.c13
-rw-r--r--drivers/spi/spi-bcm-qspi.c89
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c10
-rw-r--r--drivers/spi/spi-bcm63xx.c4
-rw-r--r--drivers/spi/spi-cadence.c4
-rw-r--r--drivers/spi/spi-ep93xx.c501
-rw-r--r--drivers/spi/spi-falcon.c5
-rw-r--r--drivers/spi/spi-imx.c218
-rw-r--r--drivers/spi/spi-loopback-test.c34
-rw-r--r--drivers/spi/spi-orion.c4
-rw-r--r--drivers/spi/spi-pic32.c4
-rw-r--r--drivers/spi/spi-pl022.c2
-rw-r--r--drivers/spi/spi.c110
15 files changed, 584 insertions, 578 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9b31351fe429..acf566f06241 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -55,7 +55,6 @@ comment "SPI Master Controller Drivers"
config SPI_ALTERA
tristate "Altera SPI Controller"
- select SPI_BITBANG
help
This is the driver for the Altera SPI Controller.
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index b95010e72452..a5adf0d868fc 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -18,7 +18,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -45,10 +44,6 @@
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
struct altera_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
-
void __iomem *base;
int irq;
int len;
@@ -66,59 +61,64 @@ static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
return spi_master_get_devdata(sdev->master);
}
-static void altera_spi_chipsel(struct spi_device *spi, int value)
+static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
{
struct altera_spi *hw = altera_spi_to_hw(spi);
- if (spi->mode & SPI_CS_HIGH) {
- switch (value) {
- case BITBANG_CS_INACTIVE:
- writel(1 << spi->chip_select,
- hw->base + ALTERA_SPI_SLAVE_SEL);
- hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- break;
-
- case BITBANG_CS_ACTIVE:
- hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
- break;
- }
+ if (is_high) {
+ hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+ writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+ writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
} else {
- switch (value) {
- case BITBANG_CS_INACTIVE:
- hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- break;
+ writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL);
+ hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+ writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+ }
+}
+
+static void altera_spi_tx_word(struct altera_spi *hw)
+{
+ unsigned int txd = 0;
- case BITBANG_CS_ACTIVE:
- writel(1 << spi->chip_select,
- hw->base + ALTERA_SPI_SLAVE_SEL);
- hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+ if (hw->tx) {
+ switch (hw->bytes_per_word) {
+ case 1:
+ txd = hw->tx[hw->count];
+ break;
+ case 2:
+ txd = (hw->tx[hw->count * 2]
+ | (hw->tx[hw->count * 2 + 1] << 8));
break;
}
}
+
+ writel(txd, hw->base + ALTERA_SPI_TXDATA);
}
-static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
+static void altera_spi_rx_word(struct altera_spi *hw)
{
- if (hw->tx) {
+ unsigned int rxd;
+
+ rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+ if (hw->rx) {
switch (hw->bytes_per_word) {
case 1:
- return hw->tx[count];
+ hw->rx[hw->count] = rxd;
+ break;
case 2:
- return (hw->tx[count * 2]
- | (hw->tx[count * 2 + 1] << 8));
+ hw->rx[hw->count * 2] = rxd;
+ hw->rx[hw->count * 2 + 1] = rxd >> 8;
+ break;
}
}
- return 0;
+
+ hw->count++;
}
-static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+static int altera_spi_txrx(struct spi_master *master,
+ struct spi_device *spi, struct spi_transfer *t)
{
- struct altera_spi *hw = altera_spi_to_hw(spi);
+ struct altera_spi *hw = spi_master_get_devdata(master);
hw->tx = t->tx_buf;
hw->rx = t->rx_buf;
@@ -132,67 +132,39 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
/* send the first byte */
- writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
- wait_for_completion(&hw->done);
- /* disable receive interrupt */
- hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+ altera_spi_tx_word(hw);
} else {
while (hw->count < hw->len) {
- unsigned int rxd;
-
- writel(hw_txbyte(hw, hw->count),
- hw->base + ALTERA_SPI_TXDATA);
+ altera_spi_tx_word(hw);
while (!(readl(hw->base + ALTERA_SPI_STATUS) &
ALTERA_SPI_STATUS_RRDY_MSK))
cpu_relax();
- rxd = readl(hw->base + ALTERA_SPI_RXDATA);
- if (hw->rx) {
- switch (hw->bytes_per_word) {
- case 1:
- hw->rx[hw->count] = rxd;
- break;
- case 2:
- hw->rx[hw->count * 2] = rxd;
- hw->rx[hw->count * 2 + 1] = rxd >> 8;
- break;
- }
- }
-
- hw->count++;
+ altera_spi_rx_word(hw);
}
+ spi_finalize_current_transfer(master);
}
- return hw->count * hw->bytes_per_word;
+ return t->len;
}
static irqreturn_t altera_spi_irq(int irq, void *dev)
{
- struct altera_spi *hw = dev;
- unsigned int rxd;
+ struct spi_master *master = dev;
+ struct altera_spi *hw = spi_master_get_devdata(master);
- rxd = readl(hw->base + ALTERA_SPI_RXDATA);
- if (hw->rx) {
- switch (hw->bytes_per_word) {
- case 1:
- hw->rx[hw->count] = rxd;
- break;
- case 2:
- hw->rx[hw->count * 2] = rxd;
- hw->rx[hw->count * 2 + 1] = rxd >> 8;
- break;
- }
- }
+ altera_spi_rx_word(hw);
- hw->count++;
+ if (hw->count < hw->len) {
+ altera_spi_tx_word(hw);
+ } else {
+ /* disable receive interrupt */
+ hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
+ writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- if (hw->count < hw->len)
- writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
- else
- complete(&hw->done);
+ spi_finalize_current_transfer(master);
+ }
return IRQ_HANDLED;
}
@@ -214,14 +186,10 @@ static int altera_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
master->dev.of_node = pdev->dev.of_node;
+ master->transfer_one = altera_spi_txrx;
+ master->set_cs = altera_spi_set_cs;
hw = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, hw);
-
- /* setup the state for the bitbang driver */
- hw->bitbang.master = master;
- hw->bitbang.chipselect = altera_spi_chipsel;
- hw->bitbang.txrx_bufs = altera_spi_txrx;
/* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -239,15 +207,13 @@ static int altera_spi_probe(struct platform_device *pdev)
/* irq is optional */
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq >= 0) {
- init_completion(&hw->done);
err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
- pdev->name, hw);
+ pdev->name, master);
if (err)
goto exit;
}
- /* register our spi controller */
- err = spi_bitbang_start(&hw->bitbang);
+ err = devm_spi_register_master(&pdev->dev, master);
if (err)
goto exit;
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
@@ -258,16 +224,6 @@ exit:
return err;
}
-static int altera_spi_remove(struct platform_device *dev)
-{
- struct altera_spi *hw = platform_get_drvdata(dev);
- struct spi_master *master = hw->bitbang.master;
-
- spi_bitbang_stop(&hw->bitbang);
- spi_master_put(master);
- return 0;
-}
-
#ifdef CONFIG_OF
static const struct of_device_id altera_spi_match[] = {
{ .compatible = "ALTR,spi-1.0", },
@@ -279,7 +235,6 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
static struct platform_driver altera_spi_driver = {
.probe = altera_spi_probe,
- .remove = altera_spi_remove,
.driver = {
.name = DRV_NAME,
.pm = NULL,
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index b89cee11f418..0719bd484891 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -39,15 +39,15 @@ struct ath79_spi {
u32 reg_ctrl;
void __iomem *base;
struct clk *clk;
- unsigned rrw_delay;
+ unsigned int rrw_delay;
};
-static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
+static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned int reg)
{
return ioread32(sp->base + reg);
}
-static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
+static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned int reg, u32 val)
{
iowrite32(val, sp->base + reg);
}
@@ -57,7 +57,7 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
return spi_master_get_devdata(spi->master);
}
-static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
+static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned int nsecs)
{
if (nsecs > sp->rrw_delay)
ndelay(nsecs - sp->rrw_delay);
@@ -148,9 +148,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
static void ath79_spi_cleanup_cs(struct spi_device *spi)
{
- if (gpio_is_valid(spi->cs_gpio)) {
+ if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio);
- }
}
static int ath79_spi_setup(struct spi_device *spi)
@@ -176,7 +175,7 @@ static void ath79_spi_cleanup(struct spi_device *spi)
spi_bitbang_cleanup(spi);
}
-static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
+static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
u32 word, u8 bits)
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index b19722ba908c..6ef6c44f39f5 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -25,7 +25,6 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/mtd/spi-nor.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
@@ -349,76 +348,60 @@ static void bcm_qspi_bspi_set_xfer_params(struct bcm_qspi *qspi, u8 cmd_byte,
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, flex_mode);
}
-static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, int width,
- int addrlen, int hp)
+static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
+ struct spi_flash_read_message *msg,
+ int hp)
{
int bpc = 0, bpp = 0;
- u8 command = SPINOR_OP_READ_FAST;
- int flex_mode = 1, rv = 0;
- bool spans_4byte = false;
+ u8 command = msg->read_opcode;
+ int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
+ int addrlen = msg->addr_width;
+ int addr_nbits = msg->addr_nbits ? msg->addr_nbits : SPI_NBITS_SINGLE;
+ int flex_mode = 1;
dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n",
width, addrlen, hp);
- if (addrlen == BSPI_ADDRLEN_4BYTES) {
+ if (addrlen == BSPI_ADDRLEN_4BYTES)
bpp = BSPI_BPP_ADDR_SELECT_MASK;
- spans_4byte = true;
- }
- bpp |= 8;
+ bpp |= msg->dummy_bytes * (8/addr_nbits);
switch (width) {
case SPI_NBITS_SINGLE:
if (addrlen == BSPI_ADDRLEN_3BYTES)
/* default mode, does not need flex_cmd */
flex_mode = 0;
- else
- command = SPINOR_OP_READ_FAST_4B;
break;
case SPI_NBITS_DUAL:
bpc = 0x00000001;
if (hp) {
bpc |= 0x00010100; /* address and mode are 2-bit */
bpp = BSPI_BPP_MODE_SELECT_MASK;
- command = OPCODE_DIOR;
- if (spans_4byte)
- command = OPCODE_DIOR_4B;
- } else {
- command = SPINOR_OP_READ_1_1_2;
- if (spans_4byte)
- command = SPINOR_OP_READ_1_1_2_4B;
}
break;
case SPI_NBITS_QUAD:
bpc = 0x00000002;
if (hp) {
bpc |= 0x00020200; /* address and mode are 4-bit */
- bpp = 4; /* dummy cycles */
- bpp |= BSPI_BPP_ADDR_SELECT_MASK;
- command = OPCODE_QIOR;
- if (spans_4byte)
- command = OPCODE_QIOR_4B;
- } else {
- command = SPINOR_OP_READ_1_1_4;
- if (spans_4byte)
- command = SPINOR_OP_READ_1_1_4_4B;
+ bpp |= BSPI_BPP_MODE_SELECT_MASK;
}
break;
default:
- rv = -EINVAL;
- break;
+ return -EINVAL;
}
- if (rv == 0)
- bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc,
- flex_mode);
+ bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc, flex_mode);
- return rv;
+ return 0;
}
-static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
- int addrlen, int hp)
+static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi,
+ struct spi_flash_read_message *msg,
+ int hp)
{
+ int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
+ int addrlen = msg->addr_width;
u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n",
@@ -430,7 +413,6 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
data &= ~(BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD |
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL);
break;
-
case SPI_NBITS_QUAD:
/* clear dual mode and set quad mode */
data &= ~BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL;
@@ -455,15 +437,17 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
/* set the override mode */
data |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data);
- bcm_qspi_bspi_set_xfer_params(qspi, SPINOR_OP_READ_FAST, 0, 0, 0);
+ bcm_qspi_bspi_set_xfer_params(qspi, msg->read_opcode, 0, 0, 0);
return 0;
}
static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
- int width, int addrlen, int hp)
+ struct spi_flash_read_message *msg, int hp)
{
int error = 0;
+ int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
+ int addrlen = msg->addr_width;
/* default mode */
qspi->xfer_mode.flex_mode = true;
@@ -475,23 +459,13 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
if (val & mask || qspi->s3_strap_override_ctrl & mask) {
qspi->xfer_mode.flex_mode = false;
- bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE,
- 0);
-
- if ((val | qspi->s3_strap_override_ctrl) &
- BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL)
- width = SPI_NBITS_DUAL;
- else if ((val | qspi->s3_strap_override_ctrl) &
- BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD)
- width = SPI_NBITS_QUAD;
-
- error = bcm_qspi_bspi_set_override(qspi, width, addrlen,
- hp);
+ bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, 0);
+ error = bcm_qspi_bspi_set_override(qspi, msg, hp);
}
}
if (qspi->xfer_mode.flex_mode)
- error = bcm_qspi_bspi_set_flex_mode(qspi, width, addrlen, hp);
+ error = bcm_qspi_bspi_set_flex_mode(qspi, msg, hp);
if (error) {
dev_warn(&qspi->pdev->dev,
@@ -981,7 +955,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
int ret = 0;
bool mspi_read = false;
- u32 io_width, addrlen, addr, len;
+ u32 addr, len;
u_char *buf;
buf = msg->buf;
@@ -1010,9 +984,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
if (mspi_read)
return bcm_qspi_mspi_flash_read(spi, msg);
- io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
- addrlen = msg->addr_width;
- ret = bcm_qspi_bspi_set_mode(qspi, io_width, addrlen, -1);
+ ret = bcm_qspi_bspi_set_mode(qspi, msg, -1);
if (!ret)
ret = bcm_qspi_bspi_flash_read(spi, msg);
@@ -1422,6 +1394,11 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev)
{
struct bcm_qspi *qspi = dev_get_drvdata(dev);
+ /* store the override strap value */
+ if (!bcm_qspi_bspi_ver_three(qspi))
+ qspi->s3_strap_override_ctrl =
+ bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
+
spi_master_suspend(qspi->master);
clk_disable(qspi->clk);
bcm_qspi_hw_uninit(qspi);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 4da2d4a524ca..cbcba614b253 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -108,7 +108,7 @@ struct bcm63xx_hsspi {
u8 cs_polarity;
};
-static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
+static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned int cs,
bool active)
{
u32 reg;
@@ -127,7 +127,7 @@ static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
struct spi_device *spi, int hz)
{
- unsigned profile = spi->chip_select;
+ unsigned int profile = spi->chip_select;
u32 reg;
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
@@ -154,7 +154,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
{
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
- unsigned chip_select = spi->chip_select;
+ unsigned int chip_select = spi->chip_select;
u16 opcode = 0;
int pending = t->len;
int step_size = HSSPI_BUFFER_LEN;
@@ -338,8 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(dev, "no irq\n");
- return -ENXIO;
+ dev_err(dev, "no irq: %d\n", irq);
+ return irq;
}
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 84c7356ce5b4..bfe5754768f9 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -530,8 +530,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(dev, "no irq\n");
- return -ENXIO;
+ dev_err(dev, "no irq: %d\n", irq);
+ return irq;
}
clk = devm_clk_get(dev, "spi");
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index f0b5c7b91f37..5c9516ae4942 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -576,10 +576,10 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb;
}
- pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
@@ -704,7 +704,9 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct spi_master *master = platform_get_drvdata(pdev);
+ struct cdns_spi *xspi = spi_master_get_devdata(master);
+ cdns_spi_init_hw(xspi);
return spi_master_resume(master);
}
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index b5d766064b7b..e5cc07357746 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -70,12 +70,9 @@
/**
* struct ep93xx_spi - EP93xx SPI controller structure
- * @pdev: pointer to platform device
* @clk: clock for the controller
- * @regs_base: pointer to ioremap()'d registers
+ * @mmio: pointer to ioremap()'d registers
* @sspdr_phys: physical address of the SSPDR register
- * @wait: wait here until given transfer is completed
- * @current_msg: message that is currently processed (or %NULL if none)
* @tx: current byte in transfer to transmit
* @rx: current byte in transfer to receive
* @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
@@ -90,12 +87,9 @@
* the client
*/
struct ep93xx_spi {
- const struct platform_device *pdev;
struct clk *clk;
- void __iomem *regs_base;
+ void __iomem *mmio;
unsigned long sspdr_phys;
- struct completion wait;
- struct spi_message *current_msg;
size_t tx;
size_t rx;
size_t fifo_level;
@@ -111,91 +105,23 @@ struct ep93xx_spi {
/* converts bits per word to CR0.DSS value */
#define bits_per_word_to_dss(bpw) ((bpw) - 1)
-static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi,
- u16 reg, u8 value)
-{
- writeb(value, espi->regs_base + reg);
-}
-
-static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
-{
- return readb(spi->regs_base + reg);
-}
-
-static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi,
- u16 reg, u16 value)
-{
- writew(value, espi->regs_base + reg);
-}
-
-static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
-{
- return readw(spi->regs_base + reg);
-}
-
-static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
-{
- u8 regval;
- int err;
-
- err = clk_enable(espi->clk);
- if (err)
- return err;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval |= SSPCR1_SSE;
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
- return 0;
-}
-
-static void ep93xx_spi_disable(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval &= ~SSPCR1_SSE;
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
- clk_disable(espi->clk);
-}
-
-static void ep93xx_spi_enable_interrupts(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
-static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
/**
* ep93xx_spi_calc_divisors() - calculates SPI clock divisors
- * @espi: ep93xx SPI controller struct
+ * @master: SPI master
* @rate: desired SPI output clock rate
* @div_cpsr: pointer to return the cpsr (pre-scaler) divider
* @div_scr: pointer to return the scr divider
*/
-static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
+static int ep93xx_spi_calc_divisors(struct spi_master *master,
u32 rate, u8 *div_cpsr, u8 *div_scr)
{
- struct spi_master *master = platform_get_drvdata(espi->pdev);
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
unsigned long spi_clk_rate = clk_get_rate(espi->clk);
int cpsr, scr;
/*
* Make sure that max value is between values supported by the
- * controller. Note that minimum value is already checked in
- * ep93xx_spi_transfer_one_message().
+ * controller.
*/
rate = clamp(rate, master->min_speed_hz, master->max_speed_hz);
@@ -220,26 +146,18 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
return -EINVAL;
}
-static void ep93xx_spi_cs_control(struct spi_device *spi, bool enable)
-{
- if (spi->mode & SPI_CS_HIGH)
- enable = !enable;
-
- if (gpio_is_valid(spi->cs_gpio))
- gpio_set_value(spi->cs_gpio, !enable);
-}
-
-static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
+static int ep93xx_spi_chip_setup(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
{
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
u8 dss = bits_per_word_to_dss(xfer->bits_per_word);
u8 div_cpsr = 0;
u8 div_scr = 0;
u16 cr0;
int err;
- err = ep93xx_spi_calc_divisors(espi, xfer->speed_hz,
+ err = ep93xx_spi_calc_divisors(master, xfer->speed_hz,
&div_cpsr, &div_scr);
if (err)
return err;
@@ -248,51 +166,49 @@ static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
cr0 |= (spi->mode & (SPI_CPHA | SPI_CPOL)) << SSPCR0_MODE_SHIFT;
cr0 |= dss;
- dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
+ dev_dbg(&master->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
spi->mode, div_cpsr, div_scr, dss);
- dev_dbg(&espi->pdev->dev, "setup: cr0 %#x\n", cr0);
+ dev_dbg(&master->dev, "setup: cr0 %#x\n", cr0);
- ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
- ep93xx_spi_write_u16(espi, SSPCR0, cr0);
+ writel(div_cpsr, espi->mmio + SSPCPSR);
+ writel(cr0, espi->mmio + SSPCR0);
return 0;
}
-static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
+static void ep93xx_do_write(struct spi_master *master)
{
- if (t->bits_per_word > 8) {
- u16 tx_val = 0;
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
+ struct spi_transfer *xfer = master->cur_msg->state;
+ u32 val = 0;
- if (t->tx_buf)
- tx_val = ((u16 *)t->tx_buf)[espi->tx];
- ep93xx_spi_write_u16(espi, SSPDR, tx_val);
- espi->tx += sizeof(tx_val);
+ if (xfer->bits_per_word > 8) {
+ if (xfer->tx_buf)
+ val = ((u16 *)xfer->tx_buf)[espi->tx];
+ espi->tx += 2;
} else {
- u8 tx_val = 0;
-
- if (t->tx_buf)
- tx_val = ((u8 *)t->tx_buf)[espi->tx];
- ep93xx_spi_write_u8(espi, SSPDR, tx_val);
- espi->tx += sizeof(tx_val);
+ if (xfer->tx_buf)
+ val = ((u8 *)xfer->tx_buf)[espi->tx];
+ espi->tx += 1;
}
+ writel(val, espi->mmio + SSPDR);
}
-static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
+static void ep93xx_do_read(struct spi_master *master)
{
- if (t->bits_per_word > 8) {
- u16 rx_val;
-
- rx_val = ep93xx_spi_read_u16(espi, SSPDR);
- if (t->rx_buf)
- ((u16 *)t->rx_buf)[espi->rx] = rx_val;
- espi->rx += sizeof(rx_val);
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
+ struct spi_transfer *xfer = master->cur_msg->state;
+ u32 val;
+
+ val = readl(espi->mmio + SSPDR);
+ if (xfer->bits_per_word > 8) {
+ if (xfer->rx_buf)
+ ((u16 *)xfer->rx_buf)[espi->rx] = val;
+ espi->rx += 2;
} else {
- u8 rx_val;
-
- rx_val = ep93xx_spi_read_u8(espi, SSPDR);
- if (t->rx_buf)
- ((u8 *)t->rx_buf)[espi->rx] = rx_val;
- espi->rx += sizeof(rx_val);
+ if (xfer->rx_buf)
+ ((u8 *)xfer->rx_buf)[espi->rx] = val;
+ espi->rx += 1;
}
}
@@ -307,44 +223,32 @@ static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
* When this function is finished, RX FIFO should be empty and TX FIFO should be
* full.
*/
-static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
+static int ep93xx_spi_read_write(struct spi_master *master)
{
- struct spi_message *msg = espi->current_msg;
- struct spi_transfer *t = msg->state;
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
+ struct spi_transfer *xfer = master->cur_msg->state;
/* read as long as RX FIFO has frames in it */
- while ((ep93xx_spi_read_u8(espi, SSPSR) & SSPSR_RNE)) {
- ep93xx_do_read(espi, t);
+ while ((readl(espi->mmio + SSPSR) & SSPSR_RNE)) {
+ ep93xx_do_read(master);
espi->fifo_level--;
}
/* write as long as TX FIFO has room */
- while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < t->len) {
- ep93xx_do_write(espi, t);
+ while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < xfer->len) {
+ ep93xx_do_write(master);
espi->fifo_level++;
}
- if (espi->rx == t->len)
+ if (espi->rx == xfer->len)
return 0;
return -EINPROGRESS;
}
-static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
-{
- /*
- * Now everything is set up for the current transfer. We prime the TX
- * FIFO, enable interrupts, and wait for the transfer to complete.
- */
- if (ep93xx_spi_read_write(espi)) {
- ep93xx_spi_enable_interrupts(espi);
- wait_for_completion(&espi->wait);
- }
-}
-
/**
* ep93xx_spi_dma_prepare() - prepares a DMA transfer
- * @espi: ep93xx SPI controller struct
+ * @master: SPI master
* @dir: DMA transfer direction
*
* Function configures the DMA, maps the buffer and prepares the DMA
@@ -352,9 +256,11 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
* in case of failure.
*/
static struct dma_async_tx_descriptor *
-ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
+ep93xx_spi_dma_prepare(struct spi_master *master,
+ enum dma_transfer_direction dir)
{
- struct spi_transfer *t = espi->current_msg->state;
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
+ struct spi_transfer *xfer = master->cur_msg->state;
struct dma_async_tx_descriptor *txd;
enum dma_slave_buswidth buswidth;
struct dma_slave_config conf;
@@ -362,10 +268,10 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
struct sg_table *sgt;
struct dma_chan *chan;
const void *buf, *pbuf;
- size_t len = t->len;
+ size_t len = xfer->len;
int i, ret, nents;
- if (t->bits_per_word > 8)
+ if (xfer->bits_per_word > 8)
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
else
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
@@ -375,14 +281,14 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
if (dir == DMA_DEV_TO_MEM) {
chan = espi->dma_rx;
- buf = t->rx_buf;
+ buf = xfer->rx_buf;
sgt = &espi->rx_sgt;
conf.src_addr = espi->sspdr_phys;
conf.src_addr_width = buswidth;
} else {
chan = espi->dma_tx;
- buf = t->tx_buf;
+ buf = xfer->tx_buf;
sgt = &espi->tx_sgt;
conf.dst_addr = espi->sspdr_phys;
@@ -429,7 +335,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
}
if (WARN_ON(len)) {
- dev_warn(&espi->pdev->dev, "len = %zu expected 0!\n", len);
+ dev_warn(&master->dev, "len = %zu expected 0!\n", len);
return ERR_PTR(-EINVAL);
}
@@ -447,15 +353,16 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
/**
* ep93xx_spi_dma_finish() - finishes with a DMA transfer
- * @espi: ep93xx SPI controller struct
+ * @master: SPI master
* @dir: DMA transfer direction
*
* Function finishes with the DMA transfer. After this, the DMA buffer is
* unmapped.
*/
-static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
+static void ep93xx_spi_dma_finish(struct spi_master *master,
enum dma_transfer_direction dir)
{
+ struct ep93xx_spi *espi = spi_master_get_devdata(master);
struct dma_chan *chan;
struct sg_table *sgt;
@@ -472,72 +379,107 @@ static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
static void ep93xx_spi_dma_callback(void *callback_param)
{
- complete(callback_param);
+ struct spi_master *master = callback_param;
+
+ ep93xx_spi_dma_finish(master, DMA_MEM_TO_DEV);
+ ep93xx_spi_dma_finish(master, DMA_DEV_TO_MEM);
+