aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml6
-rw-r--r--drivers/spi/spi-ath79.c34
-rw-r--r--drivers/spi/spi-sunplus-sp7021.c63
-rw-r--r--drivers/spi/spi-tegra114.c4
-rw-r--r--drivers/spi/spi-tegra210-quad.c2
-rw-r--r--drivers/spi/spidev.c31
6 files changed, 92 insertions, 48 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml b/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
index 38589fdbc80d..298eac28c40f 100644
--- a/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
@@ -59,8 +59,6 @@ unevaluatedProperties: false
examples:
- |
- #include <dt-bindings/clock/sp-sp7021.h>
- #include <dt-bindings/reset/sp-sp7021.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi@9C002D80 {
compatible = "sunplus,sp7021-spi";
@@ -73,8 +71,8 @@ examples:
interrupts = <144 IRQ_TYPE_LEVEL_HIGH>,
<146 IRQ_TYPE_LEVEL_HIGH>,
<145 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clkc SPI_COMBO_0>;
- resets = <&rstc RST_SPI_COMBO_0>;
+ clocks = <&clkc 0x32>;
+ resets = <&rstc 0x22>;
pinctrl-names = "default";
pinctrl-0 = <&pins_spi0>;
};
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index d1e287d2d9cd..607e7a49fb89 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/bitops.h>
#include <linux/clk.h>
@@ -133,6 +134,38 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
}
+static int ath79_exec_mem_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi);
+
+ /* Ensures that reading is performed on device connected to hardware cs0 */
+ if (mem->spi->chip_select || mem->spi->cs_gpiod)
+ return -ENOTSUPP;
+
+ /* Only use for fast-read op. */
+ if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN ||
+ op->addr.nbytes != 3 || op->dummy.nbytes != 1)
+ return -ENOTSUPP;
+
+ /* disable GPIO mode */
+ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+
+ memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes);
+
+ /* enable GPIO mode */
+ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+ /* restore IOC register */
+ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+
+ return 0;
+}
+
+static const struct spi_controller_mem_ops ath79_mem_ops = {
+ .exec_op = ath79_exec_mem_op,
+};
+
static int ath79_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
@@ -154,6 +187,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->flags = SPI_MASTER_GPIO_SS;
master->num_chipselect = 3;
+ master->mem_ops = &ath79_mem_ops;
sp->bitbang.master = master;
sp->bitbang.chipselect = ath79_spi_chipselect;
diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c
index e5bdeb3eba45..ba5ed9f7277a 100644
--- a/drivers/spi/spi-sunplus-sp7021.c
+++ b/drivers/spi/spi-sunplus-sp7021.c
@@ -110,7 +110,8 @@ static irqreturn_t sp7021_spi_slave_irq(int irq, void *dev)
unsigned int data_status;
data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG);
- writel(data_status | SP7021_SLAVE_CLR_INT, pspim->s_base + SP7021_DATA_RDY_REG);
+ data_status |= SP7021_SLAVE_CLR_INT;
+ writel(data_status , pspim->s_base + SP7021_DATA_RDY_REG);
complete(&pspim->slave_isr);
return IRQ_HANDLED;
}
@@ -127,14 +128,16 @@ static int sp7021_spi_slave_abort(struct spi_controller *ctlr)
static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer)
{
struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
+ u32 value;
reinit_completion(&pspim->slave_isr);
- writel(SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3),
- pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
+ value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
+ writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
- writel(readl(pspim->s_base + SP7021_DATA_RDY_REG) | SP7021_SLAVE_DATA_RDY,
- pspim->s_base + SP7021_DATA_RDY_REG);
+ value = readl(pspim->s_base + SP7021_DATA_RDY_REG);
+ value |= SP7021_SLAVE_DATA_RDY;
+ writel(value, pspim->s_base + SP7021_DATA_RDY_REG);
if (wait_for_completion_interruptible(&pspim->isr_done)) {
dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__);
return -EINTR;
@@ -145,11 +148,11 @@ static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer
static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer)
{
struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
- int ret = 0;
+ u32 value;
reinit_completion(&pspim->isr_done);
- writel(SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3),
- pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
+ value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
+ writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
if (wait_for_completion_interruptible(&pspim->isr_done)) {
@@ -157,7 +160,7 @@ static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer
return -EINTR;
}
writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
- return ret;
+ return 0;
}
static void sp7021_spi_master_rb(struct sp7021_spi_ctlr *pspim, unsigned int len)
@@ -188,7 +191,6 @@ static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
unsigned int tx_cnt, total_len;
unsigned int tx_len, rx_cnt;
unsigned int fd_status;
- unsigned long flags;
bool isrdone = false;
u32 value;
@@ -203,7 +205,7 @@ static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
if (tx_len == 0 && total_len == 0)
return IRQ_NONE;
- spin_lock_irqsave(&pspim->lock, flags);
+ spin_lock_irq(&pspim->lock);
rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status);
if (fd_status & SP7021_RX_FULL_FLAG)
@@ -243,7 +245,7 @@ static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
if (isrdone)
complete(&pspim->isr_done);
- spin_unlock_irqrestore(&pspim->lock, flags);
+ spin_unlock_irq(&pspim->lock);
return IRQ_HANDLED;
}
@@ -296,11 +298,10 @@ static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfe
u32 clk_rate, clk_sel, div;
clk_rate = clk_get_rate(pspim->spi_clk);
- div = clk_rate / xfer->speed_hz;
- if (div < 2)
- div = 2;
+ div = max(2U, clk_rate / xfer->speed_hz);
+
clk_sel = (div / 2) - 1;
- pspim->xfer_conf &= SP7021_CLK_MASK;
+ pspim->xfer_conf &= ~SP7021_CLK_MASK;
pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel);
writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
}
@@ -313,7 +314,6 @@ static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct sp
unsigned int xfer_cnt, xfer_len, last_len;
unsigned int i, len_temp;
u32 reg_temp;
- int ret;
xfer_cnt = xfer->len / SP7021_SPI_DATA_SIZE;
last_len = xfer->len % SP7021_SPI_DATA_SIZE;
@@ -366,9 +366,8 @@ static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct sp
writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
mutex_unlock(&pspim->buf_lock);
- ret = 0;
}
- return ret;
+ return 0;
}
static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi_device *spi,
@@ -376,12 +375,12 @@ static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi
{
struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
struct device *dev = pspim->dev;
- int mode, ret = 0;
+ int mode, ret;
mode = SP7021_SPI_IDLE;
if (xfer->tx_buf && xfer->rx_buf) {
dev_dbg(&ctlr->dev, "%s() wrong command\n", __func__);
- ret = -EINVAL;
+ return -EINVAL;
} else if (xfer->tx_buf) {
xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf,
xfer->len, DMA_TO_DEVICE);
@@ -445,7 +444,7 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev)
ctlr = devm_spi_alloc_master(dev, sizeof(*pspim));
if (!ctlr)
return -ENOMEM;
- device_set_node(&ctlr->dev, pdev->dev.fwnode);
+ device_set_node(&ctlr->dev, dev_fwnode(dev));
ctlr->bus_num = pdev->id;
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
ctlr->auto_runtime_pm = true;
@@ -488,16 +487,6 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev)
if (pspim->s_irq < 0)
return pspim->s_irq;
- ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq,
- IRQF_TRIGGER_RISING, pdev->name, pspim);
- if (ret)
- return ret;
-
- ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq,
- IRQF_TRIGGER_RISING, pdev->name, pspim);
- if (ret)
- return ret;
-
pspim->spi_clk = devm_clk_get(dev, NULL);
if (IS_ERR(pspim->spi_clk))
return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n");
@@ -522,6 +511,16 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq,
+ IRQF_TRIGGER_RISING, pdev->name, pspim);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq,
+ IRQF_TRIGGER_RISING, pdev->name, pspim);
+ if (ret)
+ return ret;
+
pm_runtime_enable(dev);
ret = spi_register_controller(ctlr);
if (ret) {
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index e9de1d958bbd..8f345247a8c3 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1352,6 +1352,10 @@ static int tegra_spi_probe(struct platform_device *pdev)
tspi->phys = r->start;
spi_irq = platform_get_irq(pdev, 0);
+ if (spi_irq < 0) {
+ ret = spi_irq;
+ goto exit_free_master;
+ }
tspi->irq = spi_irq;
tspi->clk = devm_clk_get(&pdev->dev, "spi");
diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c
index ce1bdb4767ea..cb00ac2fc7d8 100644
--- a/drivers/spi/spi-tegra210-quad.c
+++ b/drivers/spi/spi-tegra210-quad.c
@@ -1240,6 +1240,8 @@ static int tegra_qspi_probe(struct platform_device *pdev)
tqspi->phys = r->start;
qspi_irq = platform_get_irq(pdev, 0);
+ if (qspi_irq < 0)
+ return qspi_irq;
tqspi->irq = qspi_irq;
tqspi->clk = devm_clk_get(&pdev->dev, "qspi");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index a5cceca8b82b..dd824db63fbe 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -453,22 +453,29 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
dev_dbg(&spi->dev, "%d bits per word\n", tmp);
}
break;
- case SPI_IOC_WR_MAX_SPEED_HZ:
+ case SPI_IOC_WR_MAX_SPEED_HZ: {
+ u32 save;
+
retval = get_user(tmp, (__u32 __user *)arg);
- if (retval == 0) {
- u32 save = spi->max_speed_hz;
+ if (retval)
+ break;
+ if (tmp == 0) {
+ retval = -EINVAL;
+ break;
+ }
- spi->max_speed_hz = tmp;
- retval = spi_setup(spi);
- if (retval == 0) {
- spidev->speed_hz = tmp;
- dev_dbg(&spi->dev, "%d Hz (max)\n",
- spidev->speed_hz);
- }
- spi->max_speed_hz = save;
+ save = spi->max_speed_hz;
+
+ spi->max_speed_hz = tmp;
+ retval = spi_setup(spi);
+ if (retval == 0) {
+ spidev->speed_hz = tmp;
+ dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz);
}
- break;
+ spi->max_speed_hz = save;
+ break;
+ }
default:
/* segmented and/or full-duplex I/O request */
/* Check message and copy into scratch area */