summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-atmel.c1
-rw-r--r--drivers/spi/spi-bcm2835.c38
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c13
-rw-r--r--drivers/spi/spi-bitbang-txrx.h4
-rw-r--r--drivers/spi/spi-davinci.c50
-rw-r--r--drivers/spi/spi-dw-mmio.c3
-rw-r--r--drivers/spi/spi-dw.c4
-rw-r--r--drivers/spi/spi-dw.h35
-rw-r--r--drivers/spi/spi-fsl-espi.c89
-rw-r--r--drivers/spi/spi-fsl-lib.c19
-rw-r--r--drivers/spi/spi-fsl-lib.h3
-rw-r--r--drivers/spi/spi-fsl-spi.c43
-rw-r--r--drivers/spi/spi-img-spfi.c61
-rw-r--r--drivers/spi/spi-imx.c5
-rw-r--r--drivers/spi/spi-mpc512x-psc.c70
-rw-r--r--drivers/spi/spi-omap2-mcspi.c10
-rw-r--r--drivers/spi/spi-orion.c54
-rw-r--r--drivers/spi/spi-xilinx.c20
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c1
-rw-r--r--drivers/spi/spi.c51
-rw-r--r--drivers/spi/spidev.c1
22 files changed, 408 insertions, 169 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 0cae1694014d..b0f30fb68914 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -612,7 +612,7 @@ config SPI_XTENSA_XTFPGA
config SPI_ZYNQMP_GQSPI
tristate "Xilinx ZynqMP GQSPI controller"
- depends on SPI_MASTER
+ depends on SPI_MASTER && HAS_DMA
help
Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index c9eca347787d..bf9ed380bb1c 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -19,7 +19,6 @@
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include <linux/platform_data/atmel.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/of.h>
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 59705ab23577..e7874a6171ec 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *tfr,
u32 cs,
- unsigned long xfer_time_us)
+ unsigned long long xfer_time_us)
{
struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long timeout;
@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
{
struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long spi_hz, clk_hz, cdiv;
- unsigned long spi_used_hz, xfer_time_us;
+ unsigned long spi_used_hz;
+ unsigned long long xfer_time_us;
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
/* set clock */
@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
- /* handle all the modes */
+ /* handle all the 3-wire mode */
if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
cs |= BCM2835_SPI_CS_REN;
- if (spi->mode & SPI_CPOL)
- cs |= BCM2835_SPI_CS_CPOL;
- if (spi->mode & SPI_CPHA)
- cs |= BCM2835_SPI_CS_CPHA;
+ else
+ cs &= ~BCM2835_SPI_CS_REN;
/* for gpio_cs set dummy CS so that no HW-CS get changed
* we can not run this in bcm2835_spi_set_cs, as it does
@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
bs->rx_len = tfr->len;
/* calculate the estimated time in us the transfer runs */
- xfer_time_us = tfr->len
+ xfer_time_us = (unsigned long long)tfr->len
* 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
- * 1000000 / spi_used_hz;
+ * 1000000;
+ do_div(xfer_time_us, spi_used_hz);
/* for short requests run polling*/
if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
}
+static int bcm2835_spi_prepare_message(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct spi_device *spi = msg->spi;
+ struct bcm2835_spi *bs = spi_master_get_devdata(master);
+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+ cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
+
+ if (spi->mode & SPI_CPOL)
+ cs |= BCM2835_SPI_CS_CPOL;
+ if (spi->mode & SPI_CPHA)
+ cs |= BCM2835_SPI_CS_CPHA;
+
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+
+ return 0;
+}
+
static void bcm2835_spi_handle_err(struct spi_master *master,
struct spi_message *msg)
{
@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
master->set_cs = bcm2835_spi_set_cs;
master->transfer_one = bcm2835_spi_transfer_one;
master->handle_err = bcm2835_spi_handle_err;
+ master->prepare_message = bcm2835_spi_prepare_message;
master->dev.of_node = pdev->dev.of_node;
bs = spi_master_get_devdata(master);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index f5ca6dc3a157..55789f7cda92 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -76,6 +76,7 @@
#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
+#define HSSPI_OP_MULTIBIT BIT(11)
#define HSSPI_OP_CODE_SHIFT 13
#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
@@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
if (opcode != HSSPI_OP_READ)
step_size -= HSSPI_OPCODE_LEN;
- __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
- 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
- 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+ if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) ||
+ (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL))
+ opcode |= HSSPI_OP_MULTIBIT;
+
+ __raw_writel(1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT |
+ 1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT | 0xff,
bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
while (pending > 0) {
@@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
master->num_chipselect = 8;
master->setup = bcm63xx_hsspi_setup;
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
+ SPI_RX_DUAL | SPI_TX_DUAL;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true;
diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h
index 06b34e5bcfa3..47bb9b898dfd 100644
--- a/drivers/spi/spi-bitbang-txrx.h
+++ b/drivers/spi/spi-bitbang-txrx.h
@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
{
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
- bool oldbit = !(word & 1);
+ u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) {
@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
{
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
- bool oldbit = !(word & (1 << 31));
+ u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) {
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 987afebea093..3cf9faa6cc3f 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -139,6 +139,8 @@ struct davinci_spi {
u32 (*get_tx)(struct davinci_spi *);
u8 *bytes_per_word;
+
+ u8 prescaler_limit;
};
static struct davinci_spi_config davinci_spi_default_cfg;
@@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
* This function calculates the prescale value that generates a clock rate
* less than or equal to the specified maximum.
*
- * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * Returns: calculated prescale value for easy programming into SPI registers
* or negative error number if valid prescalar cannot be updated.
*/
static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
@@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
{
int ret;
- ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
+ /* Subtract 1 to match what will be programmed into SPI register. */
+ ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1;
- if (ret < 1 || ret > 256)
+ if (ret < dspi->prescaler_limit || ret > 255)
return -EINVAL;
- return ret - 1;
+ return ret;
}
/**
@@ -832,13 +835,40 @@ rx_dma_failed:
}
#if defined(CONFIG_OF)
+
+/* OF SPI data structure */
+struct davinci_spi_of_data {
+ u8 version;
+ u8 prescaler_limit;
+};
+
+static const struct davinci_spi_of_data dm6441_spi_data = {
+ .version = SPI_VERSION_1,
+ .prescaler_limit = 2,
+};
+
+static const struct davinci_spi_of_data da830_spi_data = {
+ .version = SPI_VERSION_2,
+ .prescaler_limit = 2,
+};
+
+static const struct davinci_spi_of_data keystone_spi_data = {
+ .version = SPI_VERSION_1,
+ .prescaler_limit = 0,
+};
+
static const struct of_device_id davinci_spi_of_match[] = {
{
.compatible = "ti,dm6441-spi",
+ .data = &dm6441_spi_data,
},
{
.compatible = "ti,da830-spi",
- .data = (void *)SPI_VERSION_2,
+ .data = &da830_spi_data,
+ },
+ {
+ .compatible = "ti,keystone-spi",
+ .data = &keystone_spi_data,
},
{ },
};
@@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
struct davinci_spi *dspi)
{
struct device_node *node = pdev->dev.of_node;
+ struct davinci_spi_of_data *spi_data;
struct davinci_spi_platform_data *pdata;
unsigned int num_cs, intr_line = 0;
const struct of_device_id *match;
pdata = &dspi->pdata;
- pdata->version = SPI_VERSION_1;
match = of_match_device(davinci_spi_of_match, &pdev->dev);
if (!match)
return -ENODEV;
- /* match data has the SPI version number for SPI_VERSION_2 */
- if (match->data == (void *)SPI_VERSION_2)
- pdata->version = SPI_VERSION_2;
+ spi_data = (struct davinci_spi_of_data *)match->data;
+ pdata->version = spi_data->version;
+ pdata->prescaler_limit = spi_data->prescaler_limit;
/*
* default num_cs is 1 and all chipsel are internal to the chip
* indicated by chip_sel being NULL or cs_gpios being NULL or
@@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
dspi->bitbang.chipselect = davinci_spi_chipselect;
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
-
+ dspi->prescaler_limit = pdata->prescaler_limit;
dspi->version = pdata->version;
dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index eb03e1215195..7edede6e024b 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->max_freq = clk_get_rate(dwsmmio->clk);
+ of_property_read_u32(pdev->dev.of_node, "reg-io-width",
+ &dws->reg_io_width);
+
num_cs = 4;
if (pdev->dev.of_node)
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 8d67d03c71eb..4fbfcdc5cb24 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
else
txw = *(u16 *)(dws->tx);
}
- dw_writel(dws, DW_SPI_DR, txw);
+ dw_write_io_reg(dws, DW_SPI_DR, txw);
dws->tx += dws->n_bytes;
}
}
@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
u16 rxw;
while (max--) {
- rxw = dw_readl(dws, DW_SPI_DR);
+ rxw = dw_read_io_reg(dws, DW_SPI_DR);
/* Care rx only if the transfer's original "rx" is not null */
if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1)
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 6c91391c1a4f..b75ed327d5a2 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -109,6 +109,7 @@ struct dw_spi {
u32 fifo_len; /* depth of the FIFO buffer */
u32 max_freq; /* max bus freq supported */
+ u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num;
u16 num_cs; /* supported slave numbers */
@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
return __raw_readl(dws->regs + offset);
}
+static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
+{
+ return __raw_readw(dws->regs + offset);
+}
+
static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
{
__raw_writel(val, dws->regs + offset);
}
+static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
+{
+ __raw_writew(val, dws->regs + offset);
+}
+
+static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset)
+{
+ switch (dws->reg_io_width) {
+ case 2:
+ return dw_readw(dws, offset);
+ case 4:
+ default:
+ return dw_readl(dws, offset);
+ }
+}
+
+static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
+{
+ switch (dws->reg_io_width) {
+ case 2:
+ dw_writew(dws, offset, val);
+ break;
+ case 4:
+ default:
+ dw_writel(dws, offset, val);
+ break;
+ }
+}
+
static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index d3f05a0525a4..c27124a5ec8e 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h"
@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
#define SPCOM_TRANLEN(x) ((x) << 0)
#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
+#define AUTOSUSPEND_TIMEOUT 2000
+
static void fsl_espi_change_mode(struct spi_device *spi)
{
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi = spi_master_get_devdata(spi->master);
reg_base = mpc8xxx_spi->reg_base;
+ pm_runtime_get_sync(mpc8xxx_spi->dev);
+
hw_mode = cs->hw_mode; /* Save original settings */
cs->hw_mode = mpc8xxx_spi_read_reg(
&reg_base->csmode[spi->chip_select]);
@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
retval = fsl_espi_setup_transfer(spi, NULL);
+
+ pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
+ pm_runtime_put_autosuspend(mpc8xxx_spi->dev);
+
if (retval < 0) {
cs->hw_mode = hw_mode; /* Restore settings */
return retval;
@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
return ret;
}
-static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+#ifdef CONFIG_PM
+static int fsl_espi_runtime_suspend(struct device *dev)
{
- iounmap(mspi->reg_base);
-}
-
-static int fsl_espi_suspend(struct spi_master *master)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+ struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;
- mpc8xxx_spi = spi_master_get_devdata(master);
- reg_base = mpc8xxx_spi->reg_base;
-
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
return 0;
}
-static int fsl_espi_resume(struct spi_master *master)
+static int fsl_espi_runtime_resume(struct device *dev)
{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+ struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;
- mpc8xxx_spi = spi_master_get_devdata(master);
- reg_base = mpc8xxx_spi->reg_base;
-
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
}
+#endif
static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq)
@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg;
- master->prepare_transfer_hardware = fsl_espi_resume;
- master->unprepare_transfer_hardware = fsl_espi_suspend;
+ master->auto_runtime_pm = true;
mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->spi_remove = fsl_espi_remove;
- mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
- if (!mpc8xxx_spi->reg_base) {
- ret = -ENOMEM;
+ mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(mpc8xxx_spi->reg_base)) {
+ ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_probe;
}
reg_base = mpc8xxx_spi->reg_base;
/* Register for SPI Interrupt */
- ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+ ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq,
0, "fsl_espi", mpc8xxx_spi);
if (ret)
- goto free_irq;
+ goto err_probe;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16;
@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
- ret = spi_register_master(master);
+ pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+ ret = devm_spi_register_master(dev, master);
if (ret < 0)
- goto unreg_master;
+ goto err_pm;
dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
return master;
-unreg_master:
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
- iounmap(mpc8xxx_spi->reg_base);
+err_pm:
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
err_probe:
spi_master_put(master);
err:
@@ -809,7 +818,9 @@ err:
static int of_fsl_espi_remove(struct platform_device *dev)
{
- return mpc8xxx_spi_remove(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret;
}
- return fsl_espi_suspend(master);
+ ret = pm_runtime_force_suspend(dev);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int of_fsl_espi_resume(struct device *dev)
@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
- int i;
+ int i, ret;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+ ret = pm_runtime_force_resume(dev);
+ if (ret < 0)
+ return ret;
+
return spi_master_resume(master);
}
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops espi_pm = {
+ SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
+ fsl_espi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
};
diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
index cb35d2f0d0e6..1e43412cd9f8 100644
--- a/drivers/spi/spi-fsl-lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
}
EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe);
-int mpc8xxx_spi_remove(struct device *dev)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct spi_master *master;
-
- master = dev_get_drvdata(dev);
- mpc8xxx_spi = spi_master_get_devdata(master);
-
- spi_unregister_master(master);
-
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-
- if (mpc8xxx_spi->spi_remove)
- mpc8xxx_spi->spi_remove(mpc8xxx_spi);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mpc8xxx_spi_remove);
-
int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
index 1326a392adca..84f5dcb7a897 100644
--- a/drivers/spi/spi-fsl-lib.h
+++ b/drivers/spi/spi-fsl-lib.h
@@ -54,9 +54,6 @@ struct mpc8xxx_spi {
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
u32(*get_tx) (struct mpc8xxx_spi *);
- /* hooks for different controller driver */
- void (*spi_remove) (struct mpc8xxx_spi *mspi);
-
unsigned int count;
unsigned int irq;
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 60c590790854..8b290d9d7935 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
return ret;
}
-static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
-{
- iounmap(mspi->reg_base);
- fsl_spi_cpm_free(mspi);
-}
-
static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
master->transfer_one_message = fsl_spi_do_one_msg;
mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->spi_remove = fsl_spi_remove;
mpc8xxx_spi->max_bits_per_word = 32;
mpc8xxx_spi->type = fsl_spi_get_type(dev);
@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
if (ret)
goto err_cpm_init;
- mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
- if (mpc8xxx_spi->reg_base == NULL) {
- ret = -ENOMEM;
- goto err_ioremap;
+ mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(mpc8xxx_spi->reg_base)) {
+ ret = PTR_ERR(mpc8xxx_spi->reg_base);
+ goto err_probe;
}
if (mpc8xxx_spi->type == TYPE_GRLIB)
@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
&mpc8xxx_spi->tx_shift, 8, 1);
/* Register for SPI Interrupt */
- ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
- 0, "fsl_spi", mpc8xxx_spi);
+ ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq,
+ 0, "fsl_spi", mpc8xxx_spi);
if (ret != 0)
- goto free_irq;
+ goto err_probe;
reg_base = mpc8xxx_spi->reg_base;
@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
- ret = spi_register_master(master);
+ ret = devm_spi_register_master(dev, master);
if (ret < 0)
- goto unreg_master;
+ goto err_probe;
dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
return master;
-unreg_master:
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
- iounmap(mpc8xxx_spi->reg_base);
-err_ioremap:
+err_probe:
fsl_spi_cpm_free(mpc8xxx_spi);
err_cpm_init:
spi_master_put(master);
@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)
{
struct spi_master *master = platform_get_drvdata(ofdev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
- int ret;
- ret = mpc8xxx_spi_remove(&ofdev->dev);
- if (ret)
- return ret;
+ fsl_spi_cpm_free(mpc8xxx_spi);
if (mpc8xxx_spi->type == TYPE_FSL)
of_fsl_spi_free_chipselects(&ofdev->dev);
return 0;
@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
{
- return mpc8xxx_spi_remove(&pdev->dev);
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+
+ fsl_spi_cpm_free(mpc8xxx_spi);
+
+ return 0;
}
MODULE_ALIAS("platform:mpc8xxx_spi");
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c
index f31d792a4662..823cbc92d1e7 100644
--- a/drivers/spi/spi-img-spfi.c
+++ b/drivers/spi/spi-img-spfi.c
@@ -40,6 +40,7 @@
#define SPFI_CONTROL_SOFT_RESET BIT(11)
#define SPFI_CONTROL_SEND_DMA BIT(10)
#define SPFI_CONTROL_GET_DMA BIT(9)
+#define SPFI_CONTROL_SE BIT(8)
#define SPFI_CONTROL_TMODE_SHIFT 5
#define SPFI_CONTROL_TMODE_MASK 0x7
#define SPFI_CONTROL_TMODE_SINGLE 0
@@ -104,6 +105,10 @@ struct img_spfi {
bool rx_dma_busy;
};
+struct img_spfi_device_data {
+ bool gpio_requested;
+};
+
static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
{
return readl(spfi->regs + reg);
@@ -266,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master,
cpu_relax();
}
- ret = spfi_wait_all_done(spfi);
- if (ret < 0)
- return ret;
-
if (rx_bytes > 0 || tx_bytes > 0) {
dev_err(spfi->dev, "PIO transfer timed out\n");
return -ETIMEDOUT;
}
+ ret = spfi_wait_all_done(spfi);
+ if (ret < 0)
+ return ret;
+
return 0;
}
@@ -439,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master,
static int img_spfi_setup(struct spi_device *spi)
{
- int ret;
-
- ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ?
- GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
- dev_name(&spi->dev));
- if (ret)
- dev_err(&spi->dev, "can't request chipselect gpio %d\n",
+ int ret = -EINVAL;
+ struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
+
+ if (!spfi_data) {
+ spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
+ if (!spfi_data)
+ return -ENOMEM;
+ spfi_data->gpio_requested = false;
+ spi_set_ctldata(spi, spfi_data);
+ }
+ if (!spfi_data->gpio_requested) {
+ ret = gpio_request_one(spi->cs_gpio,
+ (spi->mode & SPI_CS_HIGH) ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+ dev_name(&spi->dev));
+ if (ret)
+ dev_err(&spi->dev, "can't request chipselect gpio %d\n",
spi->cs_gpio);
-
+ else
+ spfi_data->gpio_requested = true;
+ } else {
+ if (gpio_is_valid(spi->cs_gpio)) {
+ int mode = ((spi->mode & SPI_CS_HIGH) ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
+
+ ret = gpio_direction_output(spi->cs_gpio, mode);
+ if (ret)
+ dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
+ spi->cs_gpio, ret);
+ }
+ }
return ret;
}
static void img_spfi_cleanup(struct spi_device *spi)
{
- gpio_free(spi->cs_gpio);
+ struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
+
+ if (spfi_data) {
+ if (spfi_data->gpio_requested)
+ gpio_free(spi->cs_gpio);
+ kfree(spfi_data);
+ spi_set_ctldata(spi, NULL);
+ }
}
static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
@@ -491,6 +525,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
xfer->rx_nbits == SPI_NBITS_QUAD)
val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
+ val |= SPFI_CONTROL_SE;
spfi_writel(spfi, val, SPFI_CONTROL);
}
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index eb7d3a6fb14c..f9deb84e4e55 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -201,8 +201,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
- if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml)
- && (transfer->len > spi_imx->tx_wml))
+ if (spi_imx->dma_is_inited
+ && transfer->len > spi_imx->rx_wml * sizeof(u32)
+ && transfer->len > spi_imx->tx_wml * sizeof(u32))
return true;
return false;
}
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 965d2bdcfdcc..1e75341689a6 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -30,11 +30,37 @@
#include <linux/gpio.h>
#include <asm/mpc52xx_psc.h>
+enum {
+ TYPE_MPC5121,
+ TYPE_MPC5125,
+};
+
+/*
+ * This macro abstracts the differences in the PSC register layout between
+ * MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
+ */
+#define psc_addr(mps, regname) ({ \
+ void *__ret = NULL; \
+ switch (mps->type) { \
+ case TYPE_MPC5121: { \
+ struct mpc52xx_psc __iomem *psc = mps->psc; \
+ __ret = &psc->regname; \
+ }; \
+ break; \
+ case TYPE_MPC5125: { \
+ struct mpc5125_psc __iomem *psc = mps->psc; \
+ __ret = &psc->regname; \
+ }; \
+ break; \
+ } \
+ __ret; })
+
struct mpc512x_psc_spi {
void (*cs_control)(struct spi_device *spi, bool on);
/* driver internal data */
- struct mpc52xx_psc __iomem *psc;
+ int type;
+ void __iomem *psc;
struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq;
u8 bits_per_word;
@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
{
struct mpc512x_psc_spi_cs *cs = spi->controller_state;
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
u32 sicr;
u32 ccr;
int speed;
u16 bclkdiv;
- sicr = in_be32(&psc->sicr);
+ sicr = in_be32(psc_addr(mps, sicr));
/* Set clock phase and polarity */
if (spi->mode & SPI_CPHA)
@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
sicr |= 0x10000000;
else
sicr &= ~0x10000000;
- out_be32(&psc->sicr, sicr);
+ out_be32(psc_addr(mps, sicr), sicr);
- ccr = in_be32(&psc->ccr);
+ ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000;
speed = cs->speed_hz;
if (!speed)
@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
+ out_be32(psc_addr(mps, ccr), ccr);
mps->bits_per_word = cs->bits_per_word;
if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
{
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
dev_dbg(&master->dev, "%s()\n", __func__);
/* Zero MR2 */
- in_8(&psc->mode);
- out_8(&psc->mode, 0x0);
+ in_8(psc_addr(mps, mr2));
+ out_8(psc_addr(mps, mr2), 0x0);
/* enable transmitter/receiver */
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
return 0;
}
@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
{
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
dev_dbg(&master->dev, "%s()\n", __func__);
/* disable transmitter/receiver and fifo interrupt */
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
out_be32(&fifo->tximr, 0);
return 0;
@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
static int mpc512x_psc_spi_port_config(struct spi_master *master,
struct mpc512x_psc_spi *mps)
{
- struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
u32 sicr;
u32 ccr;
@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
u16 bclkdiv;
/* Reset the PSC into a known state */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
/* Disable psc interrupts all useful interrupts are in fifo */
- out_be16(&psc->isr_imr.imr, 0);
+ out_be16(psc_addr(mps, isr_imr.imr), 0);
/* Disable fifo interrupts, will be enabled later */
out_be32(&fifo->tximr, 0);
@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
0x00004000 | /* MSTR = 1 -- SPI master */
0x00000800; /* UseEOF = 1 -- SS low until EOF */
- out_be32(&psc->sicr, sicr);
+ out_be32(psc_addr(mps, sicr), sicr);
- ccr = in_be32(&psc->ccr);
+ ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000;
speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
+ out_be32(psc_addr(mps, ccr), ccr);
/* Set 2ms DTL delay */
- out_8(&psc->ctur, 0x00);
- out_8(&psc->ctlr, 0x82);
+ out_8(psc_addr(mps, ctur), 0x00);
+ out_8(psc_addr(mps, ctlr), 0x82);
/* we don't use the alarms */
out_be32(&fifo->rxalarm, 0xfff);
@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
dev_set_drvdata(dev, master);
mps = spi_master_get_devdata(master);
+ mps->type = (int)of_device_get_match_data(dev);
mps->irq = irq;
if (pdata == NULL) {
@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
}
static const struct of_device_id mpc512x_psc_spi_of_match[] = {
- { .compatible = "fsl,mpc5121-psc-spi", },
+ { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
+ { .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
{},
};
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 58673841286c..3d09e0b69b73 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
{
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
u32 l;
/* The controller handles the inverted chip selects
@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
enable = !enable;
if (spi->controller_state) {
+ int err = pm_runtime_get_sync(mcspi->dev);
+ if (err < 0) {
+ dev_err(mcspi->dev, "failed to get sync: %d\n", err);
+ return;
+ }
+
l = mcspi_cached_chconf0(spi);
if (enable)
@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
l |= OMAP2_MCSPI_CHCONF_FORCE;
mcspi_write_chconf0(spi, l);
+
+ pm_runtime_mark_last_busy(mcspi->dev);
+ pm_runtime_put_autosuspend(mcspi->dev);
}
}
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 8cad107a5b3f..a87cfd4ba17b 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -41,6 +41,11 @@
#define ORION_SPI_DATA_OUT_REG 0x08
#define ORION_SPI_DATA_IN_REG 0x0c
#define ORION_SPI_INT_CAUSE_REG 0x10
+#define ORION_SPI_TIMING_PARAMS_REG 0x18
+
+#define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6)
+#define ORION_SPI_TMISO_SAMPLE_1 (1 << 6)
+#define ORION_SPI_TMISO_SAMPLE_2 (2 << 6)
#define ORION_SPI_MODE_CPOL (1 << 11)
#define ORION_SPI_MODE_CPHA (1 << 12)
@@ -70,6 +75,7 @@ struct orion_spi_dev {
unsigned int min_divisor;
unsigned int max_divisor;
u32 prescale_mask;
+ bool is_errata_50mhz_ac;
};
struct orion_spi {
@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi)
writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
}
+static void
+orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed)
+{
+ u32 reg;
+ struct orion_spi *orion_spi;
+
+ orion_spi = spi_master_get_devdata(spi->master);
+
+ /*
+ * Erratum description: (Erratum NO. FE-9144572) The device
+ * SPI interface supports frequencies of up to 50 MHz.
+ * However, due to this erratum, when the device core clock is
+ * 250 MHz and the SPI interfaces is configured for 50MHz SPI
+ * clock and CPOL=CPHA=1 there might occur data corruption on
+ * reads from the SPI device.
+ * Erratum Workaround:
+ * Work in one of the following configurations:
+ * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
+ * Register".
+ * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
+ * Register" before setting the interface.
+ */
+ reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
+ reg &= ~ORION_SPI_TMISO_SAMPLE_MASK;
+
+ if (clk_get_rate(orion_spi->clk) == 250000000 &&
+ speed == 50000000 && spi->mode & SPI_CPOL &&
+ spi->mode & SPI_CPHA)
+ reg |= ORION_SPI_TMISO_SAMPLE_2;
+ else
+ reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */
+
+ writel(reg, spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
+}
+
/*
* called only when no transfer is active on the bus
*/
@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
orion_spi_mode_set(spi);
+ if (orion_spi->devdata->is_errata_50mhz_ac)
+ orion_spi_50mhz_ac_timing_erratum(spi, speed);
+
rc = orion_spi_baudrate_set(spi, speed);
if (rc)
return rc;
@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = {
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
};
+static const struct orion_spi_dev armada_380_spi_dev_data = {
+ .typ = ARMADA_SPI,
+ .max_hz = 50000000,
+ .max_divisor = 1920,
+ .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
+ .is_errata_50mhz_ac = true,
+};
+
static const struct of_device_id orion_spi_of_match_table[] = {
{
.compatible = "marvell,orion-spi",
@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = {
},
{
.compatible = "marvell,armada-380-spi",
- .data = &armada_xp_spi_dev_data,
+ .data = &armada_380_spi_dev_data,
},
{
.compatible = "marvell,armada-390-spi",
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 133f53a9c1d4..a339c1e9997a 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf;
remaining_words = t->len / xspi->bytes_per_word;
- reinit_completion(&xspi->done);
if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
+ u32 isr;
use_irq = true;
- xspi->write_fn(XSPI_INTR_TX_EMPTY,
- xspi->regs + XIPIF_V123B_IISR_OFFSET);
- /* Enable the global IPIF interrupt */
- xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
- xspi->regs + XIPIF_V123B_DGIER_OFFSET);
/* Inhibit irq to avoid spurious irqs on tx_empty*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);
+ /* ACK old irqs (if any) */
+ isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+ if (isr)
+ xspi->write_fn(isr,
+ xspi->regs + XIPIF_V123B_IISR_OFFSET);
+ /* Enable the global IPIF interrupt */
+ xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+ xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+ reinit_completion(&xspi->done);
}
while (remaining_words) {
@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
remaining_words -= n_words;
}
- if (use_irq)
+ if (use_irq) {
xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+ }
return t->len;
}
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 87b20a511a6b..f23f36ebaf3d 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -214,6 +214,7 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
case GQSPI_SELECT_FLASH_CS_BOTH:
instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER |
GQSPI_GENFIFO_CS_UPPER;
+ break;
case GQSPI_SELECT_FLASH_CS_UPPER:
instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER;
break;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index cf8b91b23a76..24678ea45c57 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -539,8 +539,15 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
if (!master->can_dma)
return 0;
- tx_dev = master->dma_tx->device->dev;
- rx_dev = master->dma_rx->device->dev;
+ if (master->dma_tx)
+ tx_dev = master->dma_tx->device->dev;
+ else
+ tx_dev = &master->dev;
+
+ if (master->dma_rx)
+ rx_dev = master->dma_rx->device->dev;
+ else
+ rx_dev = &master->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
@@ -579,8 +586,15 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
if (!master->cur_msg_mapped || !master->can_dma)
return 0;
- tx_dev = master->dma_tx->device->dev;
- rx_dev = master->dma_rx->device->dev;
+ if (master->dma_tx)
+ tx_dev = master->dma_tx->device->dev;
+ else
+ tx_dev = &master->dev;
+
+ if (master->dma_rx)
+ rx_dev = master->dma_rx->device->dev;
+ else
+ rx_dev = &master->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
@@ -1740,6 +1754,20 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
* other core methods are currently defined as inline functions.
*/
+static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word)
+{
+ if (master->bits_per_word_mask) {
+ /* Only 32 bits fit in the mask */
+ if (bits_per_word > 32)
+ return -EINVAL;
+ if (!(master->bits_per_word_mask &
+ SPI_BPW_MASK(bits_per_word)))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* spi_setup - setup SPI mode and clock rate
* @spi: the device whose settings are being modified
@@ -1798,6 +1826,9 @@ int spi_setup(struct spi_device *spi)
if (!spi->bits_per_word)
spi->bits_per_word = 8;
+ if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
+ return -EINVAL;
+
if (!spi->max_speed_hz)
spi->max_speed_hz = spi->master->max_speed_hz;
@@ -1860,19 +1891,15 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
if (!xfer->speed_hz)
xfer->speed_hz = spi->max_speed_hz;
+ if (!xfer->speed_hz)
+ xfer->speed_hz = master->max_speed_hz;
if (master->max_speed_hz &&
xfer->speed_hz > master->max_speed_hz)
xfer->speed_hz = master->max_speed_hz;
- if (master->bits_per_word_mask) {
- /* Only 32 bits fit in the mask */
- if (xfer->bits_per_word > 32)
- return -EINVAL;
- if (!(master->bits_per_word_mask &
- BIT(xfer->bits_per_word - 1)))
- return -EINVAL;
- }
+ if (__spi_validate_bits_per_word(master, xfer->bits_per_word))
+ return -EINVAL;
/*
* SPI transfer length should be multiple of SPI word size
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index dd616ff0ffc5..c7de64171c45 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -693,6 +693,7 @@ static struct class *spidev_class;
#ifdef CONFIG_OF
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
+ { .compatible = "lineartechnology,ltc2488" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);