summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/Kconfig9
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-amd.c183
-rw-r--r--drivers/spi/spi-aspeed-smc.c4
-rw-r--r--drivers/spi/spi-cadence-quadspi.c3
-rw-r--r--drivers/spi/spi-cadence-xspi.c4
-rw-r--r--drivers/spi/spi-dw-bt1.c4
-rw-r--r--drivers/spi/spi-dw-core.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c3
-rw-r--r--drivers/spi/spi-fsl-lpspi.c10
-rw-r--r--drivers/spi/spi-fsl-qspi.c3
-rw-r--r--drivers/spi/spi-fsl-spi.c157
-rw-r--r--drivers/spi/spi-gxp.c10
-rw-r--r--drivers/spi/spi-img-spfi.c6
-rw-r--r--drivers/spi/spi-intel.c164
-rw-r--r--drivers/spi/spi-loopback-test.c27
-rw-r--r--drivers/spi/spi-meson-spicc.c8
-rw-r--r--drivers/spi/spi-microchip-core-qspi.c600
-rw-r--r--drivers/spi/spi-microchip-core.c4
-rw-r--r--drivers/spi/spi-mpc52xx.c35
-rw-r--r--drivers/spi/spi-mt65xx.c5
-rw-r--r--drivers/spi/spi-mt7621.c42
-rw-r--r--drivers/spi/spi-npcm-pspi.c1
-rw-r--r--drivers/spi/spi-nxp-fspi.c8
-rw-r--r--drivers/spi/spi-omap-100k.c1
-rw-r--r--drivers/spi/spi-omap2-mcspi.c4
-rw-r--r--drivers/spi/spi-pxa2xx.c4
-rw-r--r--drivers/spi/spi-qup.c21
-rw-r--r--drivers/spi/spi-s3c24xx.c24
-rw-r--r--drivers/spi/spi-s3c64xx.c13
-rw-r--r--drivers/spi/spi-sh-msiof.c1
-rw-r--r--drivers/spi/spi-stm32-qspi.c125
-rw-r--r--drivers/spi/spi-xilinx.c20
-rw-r--r--drivers/spi/spi-xtensa-xtfpga.c16
-rw-r--r--drivers/spi/spi.c157
35 files changed, 1304 insertions, 375 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index e32f6a2058ae..d1bb62f7368b 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -591,6 +591,15 @@ config SPI_MICROCHIP_CORE
PolarFire SoC.
If built as a module, it will be called spi-microchip-core.
+config SPI_MICROCHIP_CORE_QSPI
+ tristate "Microchip FPGA QSPI controllers"
+ depends on SPI_MASTER
+ help
+ This enables the QSPI driver for Microchip FPGA QSPI controllers.
+ Say Y or M here if you want to use the QSPI controllers on
+ PolarFire SoC.
+ If built as a module, it will be called spi-microchip-core-qspi.
+
config SPI_MT65XX
tristate "MediaTek SPI controller"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 15d2f3835e45..4b34e855c841 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MICROCHIP_CORE) += spi-microchip-core.o
+obj-$(CONFIG_SPI_MICROCHIP_CORE_QSPI) += spi-microchip-core-qspi.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 08df4f8d0531..e23121456c70 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -36,9 +36,17 @@
#define AMD_SPI_FIFO_SIZE 70
#define AMD_SPI_MEM_SIZE 200
-/* M_CMD OP codes for SPI */
-#define AMD_SPI_XFER_TX 1
-#define AMD_SPI_XFER_RX 2
+#define AMD_SPI_ENA_REG 0x20
+#define AMD_SPI_ALT_SPD_SHIFT 20
+#define AMD_SPI_ALT_SPD_MASK GENMASK(23, AMD_SPI_ALT_SPD_SHIFT)
+#define AMD_SPI_SPI100_SHIFT 0
+#define AMD_SPI_SPI100_MASK GENMASK(AMD_SPI_SPI100_SHIFT, AMD_SPI_SPI100_SHIFT)
+#define AMD_SPI_SPEED_REG 0x6C
+#define AMD_SPI_SPD7_SHIFT 8
+#define AMD_SPI_SPD7_MASK GENMASK(13, AMD_SPI_SPD7_SHIFT)
+
+#define AMD_SPI_MAX_HZ 100000000
+#define AMD_SPI_MIN_HZ 800000
/**
* enum amd_spi_versions - SPI controller versions
@@ -50,14 +58,41 @@ enum amd_spi_versions {
AMD_SPI_V2,
};
+enum amd_spi_speed {
+ F_66_66MHz,
+ F_33_33MHz,
+ F_22_22MHz,
+ F_16_66MHz,
+ F_100MHz,
+ F_800KHz,
+ SPI_SPD7,
+ F_50MHz = 0x4,
+ F_4MHz = 0x32,
+ F_3_17MHz = 0x3F
+};
+
+/**
+ * struct amd_spi_freq - Matches device speed with values to write in regs
+ * @speed_hz: Device frequency
+ * @enable_val: Value to be written to "enable register"
+ * @spd7_val: Some frequencies requires to have a value written at SPISPEED register
+ */
+struct amd_spi_freq {
+ u32 speed_hz;
+ u32 enable_val;
+ u32 spd7_val;
+};
+
/**
* struct amd_spi - SPI driver instance
* @io_remap_addr: Start address of the SPI controller registers
* @version: SPI controller hardware version
+ * @speed_hz: Device frequency
*/
struct amd_spi {
void __iomem *io_remap_addr;
enum amd_spi_versions version;
+ unsigned int speed_hz;
};
static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
@@ -189,65 +224,125 @@ static int amd_spi_master_setup(struct spi_device *spi)
return 0;
}
+static const struct amd_spi_freq amd_spi_freq[] = {
+ { AMD_SPI_MAX_HZ, F_100MHz, 0},
+ { 66660000, F_66_66MHz, 0},
+ { 50000000, SPI_SPD7, F_50MHz},
+ { 33330000, F_33_33MHz, 0},
+ { 22220000, F_22_22MHz, 0},
+ { 16660000, F_16_66MHz, 0},
+ { 4000000, SPI_SPD7, F_4MHz},
+ { 3170000, SPI_SPD7, F_3_17MHz},
+ { AMD_SPI_MIN_HZ, F_800KHz, 0},
+};
+
+static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz)
+{
+ unsigned int i, spd7_val, alt_spd;
+
+ if (speed_hz < AMD_SPI_MIN_HZ)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(amd_spi_freq); i++)
+ if (speed_hz >= amd_spi_freq[i].speed_hz)
+ break;
+
+ if (amd_spi->speed_hz == amd_spi_freq[i].speed_hz)
+ return 0;
+
+ amd_spi->speed_hz = amd_spi_freq[i].speed_hz;
+
+ alt_spd = (amd_spi_freq[i].enable_val << AMD_SPI_ALT_SPD_SHIFT)
+ & AMD_SPI_ALT_SPD_MASK;
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, alt_spd,
+ AMD_SPI_ALT_SPD_MASK);
+
+ if (amd_spi->speed_hz == AMD_SPI_MAX_HZ)
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, 1,
+ AMD_SPI_SPI100_MASK);
+
+ if (amd_spi_freq[i].spd7_val) {
+ spd7_val = (amd_spi_freq[i].spd7_val << AMD_SPI_SPD7_SHIFT)
+ & AMD_SPI_SPD7_MASK;
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_SPEED_REG, spd7_val,
+ AMD_SPI_SPD7_MASK);
+ }
+
+ return 0;
+}
+
static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
struct spi_master *master,
struct spi_message *message)
{
struct spi_transfer *xfer = NULL;
- u8 cmd_opcode;
+ struct spi_device *spi = message->spi;
+ u8 cmd_opcode = 0, fifo_pos = AMD_SPI_FIFO_BASE;
u8 *buf = NULL;
- u32 m_cmd = 0;
u32 i = 0;
u32 tx_len = 0, rx_len = 0;
list_for_each_entry(xfer, &message->transfers,
transfer_list) {
- if (xfer->rx_buf)
- m_cmd = AMD_SPI_XFER_RX;
- if (xfer->tx_buf)
- m_cmd = AMD_SPI_XFER_TX;
+ if (xfer->speed_hz)
+ amd_set_spi_freq(amd_spi, xfer->speed_hz);
+ else
+ amd_set_spi_freq(amd_spi, spi->max_speed_hz);
- if (m_cmd & AMD_SPI_XFER_TX) {
+ if (xfer->tx_buf) {
buf = (u8 *)xfer->tx_buf;
- tx_len = xfer->len - 1;
- cmd_opcode = *(u8 *)xfer->tx_buf;
- buf++;
- amd_spi_set_opcode(amd_spi, cmd_opcode);
+ if (!tx_len) {
+ cmd_opcode = *(u8 *)xfer->tx_buf;
+ buf++;
+ xfer->len--;
+ }
+ tx_len += xfer->len;
/* Write data into the FIFO. */
- for (i = 0; i < tx_len; i++) {
- iowrite8(buf[i], ((u8 __iomem *)amd_spi->io_remap_addr +
- AMD_SPI_FIFO_BASE + i));
- }
+ for (i = 0; i < xfer->len; i++)
+ amd_spi_writereg8(amd_spi, fifo_pos + i, buf[i]);
- amd_spi_set_tx_count(amd_spi, tx_len);
- amd_spi_clear_fifo_ptr(amd_spi);
- /* Execute command */
- amd_spi_execute_opcode(amd_spi);
- }
- if (m_cmd & AMD_SPI_XFER_RX) {
- /*
- * Store no. of bytes to be received from
- * FIFO
- */
- rx_len = xfer->len;
- buf = (u8 *)xfer->rx_buf;
- amd_spi_set_rx_count(amd_spi, rx_len);
- amd_spi_clear_fifo_ptr(amd_spi);
- /* Execute command */
- amd_spi_execute_opcode(amd_spi);
- amd_spi_busy_wait(amd_spi);
- /* Read data from FIFO to receive buffer */
- for (i = 0; i < rx_len; i++)
- buf[i] = amd_spi_readreg8(amd_spi, AMD_SPI_FIFO_BASE + tx_len + i);
+ fifo_pos += xfer->len;
}
+
+ /* Store no. of bytes to be received from FIFO */
+ if (xfer->rx_buf)
+ rx_len += xfer->len;
+ }
+
+ if (!buf) {
+ message->status = -EINVAL;
+ goto fin_msg;
+ }
+
+ amd_spi_set_opcode(amd_spi, cmd_opcode);
+ amd_spi_set_tx_count(amd_spi, tx_len);
+ amd_spi_set_rx_count(amd_spi, rx_len);
+
+ /* Execute command */
+ message->status = amd_spi_execute_opcode(amd_spi);
+ if (message->status)
+ goto fin_msg;
+
+ if (rx_len) {
+ message->status = amd_spi_busy_wait(amd_spi);
+ if (message->status)
+ goto fin_msg;
+
+ list_for_each_entry(xfer, &message->transfers, transfer_list)
+ if (xfer->rx_buf) {
+ buf = (u8 *)xfer->rx_buf;
+ /* Read data from FIFO to receive buffer */
+ for (i = 0; i < xfer->len; i++)
+ buf[i] = amd_spi_readreg8(amd_spi, fifo_pos + i);
+ fifo_pos += xfer->len;
+ }
}
/* Update statistics */
message->actual_length = tx_len + rx_len + 1;
- /* complete the transaction */
- message->status = 0;
+fin_msg:
switch (amd_spi->version) {
case AMD_SPI_V1:
break;
@@ -260,7 +355,7 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
spi_finalize_current_message(master);
- return 0;
+ return message->status;
}
static int amd_spi_master_transfer(struct spi_master *master,
@@ -275,9 +370,7 @@ static int amd_spi_master_transfer(struct spi_master *master,
* Extract spi_transfers from the spi message and
* program the controller.
*/
- amd_spi_fifo_xfer(amd_spi, master, msg);
-
- return 0;
+ return amd_spi_fifo_xfer(amd_spi, master, msg);
}
static size_t amd_spi_max_transfer_size(struct spi_device *spi)
@@ -312,6 +405,8 @@ static int amd_spi_probe(struct platform_device *pdev)
master->num_chipselect = 4;
master->mode_bits = 0;
master->flags = SPI_MASTER_HALF_DUPLEX;
+ master->max_speed_hz = AMD_SPI_MAX_HZ;
+ master->min_speed_hz = AMD_SPI_MIN_HZ;
master->setup = amd_spi_master_setup;
master->transfer_one_message = amd_spi_master_transfer;
master->max_transfer_size = amd_spi_max_transfer_size;
diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index 3e891bf22470..a334e89add86 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -736,10 +736,8 @@ static int aspeed_spi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aspi->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(aspi->regs)) {
- dev_err(dev, "missing AHB register window\n");
+ if (IS_ERR(aspi->regs))
return PTR_ERR(aspi->regs);
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
aspi->ahb_base = devm_ioremap_resource(dev, res);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index e12ab5b43f34..447230547945 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -1645,7 +1645,7 @@ static int cqspi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ goto probe_pm_failed;
ret = clk_prepare_enable(cqspi->clk);
if (ret) {
@@ -1740,6 +1740,7 @@ probe_reset_failed:
clk_disable_unprepare(cqspi->clk);
probe_clk_failed:
pm_runtime_put_sync(dev);
+probe_pm_failed:
pm_runtime_disable(dev);
return ret;
}
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index 3ab19be83095..9e187f9c6c95 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -565,10 +565,8 @@ static int cdns_xspi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma");
cdns_xspi->sdmabase = devm_ioremap_resource(dev, res);
- if (IS_ERR(cdns_xspi->sdmabase)) {
- dev_err(dev, "Failed to remap SDMA address\n");
+ if (IS_ERR(cdns_xspi->sdmabase))
return PTR_ERR(cdns_xspi->sdmabase);
- }
cdns_xspi->sdmasize = resource_size(res);
cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux");
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c
index c06553416123..3fb89dee595e 100644
--- a/drivers/spi/spi-dw-bt1.c
+++ b/drivers/spi/spi-dw-bt1.c
@@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = dw_spi_add_host(&pdev->dev, dws);
- if (ret)
+ if (ret) {
+ pm_runtime_disable(&pdev->dev);
goto err_disable_clk;
+ }
platform_set_drvdata(pdev, dwsbt1);
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index f87d97ccd2d6..99edddf9958b 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -955,7 +955,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
ret = spi_register_controller(master);
if (ret) {
- dev_err(&master->dev, "problem registering spi master\n");
+ dev_err_probe(dev, ret, "problem registering spi master\n");
goto err_dma_exit;
}
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index fd004c9db9dc..a33e547b7d39 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1294,8 +1294,7 @@ static int dspi_probe(struct platform_device *pdev)
else
ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
goto out_ctlr_put;
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 19b1f3d881b0..e8c1c8a4c6c8 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -855,8 +855,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
init_completion(&fsl_lpspi->xfer_done);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res);
+ fsl_lpspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(fsl_lpspi->base)) {
ret = PTR_ERR(fsl_lpspi->base);
goto out_controller_put;
@@ -912,7 +911,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
- dev_err_probe(&pdev->dev, ret, "spi_register_controller error: %i\n", ret);
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
goto free_dma;
}
@@ -947,11 +946,8 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
static int __maybe_unused fsl_lpspi_suspend(struct device *dev)
{
- int ret;
-
pinctrl_pm_select_sleep_state(dev);
- ret = pm_runtime_force_suspend(dev);
- return ret;
+ return pm_runtime_force_suspend(dev);
}
static int __maybe_unused fsl_lpspi_resume(struct device *dev)
diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
index 46ae46a944c5..85cc71ba624a 100644
--- a/drivers/spi/spi-fsl-qspi.c
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -867,8 +867,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, q);
/* find the resources */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
- q->iobase = devm_ioremap_resource(dev, res);
+ q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI");
if (IS_ERR(q->iobase)) {
ret = PTR_ERR(q->iobase);
goto err_put_ctrl;
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index bdf94cc7be1a..731624f157fc 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi)
local_irq_restore(flags);
}
-static void fsl_spi_chipselect(struct spi_device *spi, int value)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_spi_platform_data *pdata;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- pdata = spi->dev.parent->parent->platform_data;
-
- if (value == BITBANG_CS_INACTIVE) {
- if (pdata->cs_control)
- pdata->cs_control(spi, false);
- }
-
- if (value == BITBANG_CS_ACTIVE) {
- mpc8xxx_spi->rx_shift = cs->rx_shift;
- mpc8xxx_spi->tx_shift = cs->tx_shift;
- mpc8xxx_spi->get_rx = cs->get_rx;
- mpc8xxx_spi->get_tx = cs->get_tx;
-
- fsl_spi_change_mode(spi);
-
- if (pdata->cs_control)
- pdata->cs_control(spi, true);
- }
-}
-
static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
int bits_per_word, int msb_first)
{
@@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
return mpc8xxx_spi->count;
}
-static int fsl_spi_do_one_msg(struct spi_master *master,
- struct spi_message *m)
+static int fsl_spi_prepare_message(struct spi_controller *ctlr,
+ struct spi_message *m)
{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
- struct spi_device *spi = m->spi;
- struct spi_transfer *t, *first;
- unsigned int cs_change;
- const int nsecs = 50;
- int status, last_bpw;
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
+ struct spi_transfer *t;
/*
* In CPU mode, optimize large byte transfers to use larger
@@ -378,62 +348,30 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
t->bits_per_word = 16;
}
}
+ return 0;
+}
- /* Don't allow changes if CS is active */
- cs_change = 1;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (cs_change)
- first = t;
- cs_change = t->cs_change;
- if (first->speed_hz != t->speed_hz) {
- dev_err(&spi->dev,
- "speed_hz cannot change while CS is active\n");
- return -EINVAL;
- }
- }
-
- last_bpw = -1;
- cs_change = 1;
- status = -EINVAL;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (cs_change || last_bpw != t->bits_per_word)
- status = fsl_spi_setup_transfer(spi, t);
- if (status < 0)
- break;
- last_bpw = t->bits_per_word;
-
- if (cs_change) {
- fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
- ndelay(nsecs);
- }
- cs_change = t->cs_change;
- if (t->len)
- status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
- if (status) {
- status = -EMSGSIZE;
- break;
- }
- m->actual_length += t->len;
-
- spi_transfer_delay_exec(t);
-
- if (cs_change) {
- ndelay(nsecs);
- fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
- }
+static int fsl_spi_transfer_one(struct spi_controller *controller,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ int status;
- m->status = status;
+ status = fsl_spi_setup_transfer(spi, t);
+ if (status < 0)
+ return status;
+ if (t->len)
+ status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
+ if (status > 0)
+ return -EMSGSIZE;
- if (status || !cs_change) {
- ndelay(nsecs);
- fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
- }
+ return status;
+}
- fsl_spi_setup_transfer(spi, NULL);
- spi_finalize_current_message(master);
- return 0;
+static int fsl_spi_unprepare_message(struct spi_controller *controller,
+ struct spi_message *msg)
+{
+ return fsl_spi_setup_transfer(msg->spi, NULL);
}
static int fsl_spi_setup(struct spi_device *spi)
@@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi)
return retval;
}
- /* Initialize chipselect - might be active for SPI_CS_HIGH mode */
- fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-
return 0;
}
@@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
u32 slvsel;
u16 cs = spi->chip_select;
- if (spi->cs_gpiod) {
- gpiod_set_value(spi->cs_gpiod, on);
- } else if (cs < mpc8xxx_spi->native_chipselects) {
+ if (cs < mpc8xxx_spi->native_chipselects) {
slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
@@ -568,7 +501,6 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
static void fsl_spi_grlib_probe(struct device *dev)
{
- struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
@@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
}
master->num_chipselect = mpc8xxx_spi->native_chipselects;
- pdata->cs_control = fsl_spi_grlib_cs_control;
+ master->set_cs = fsl_spi_grlib_cs_control;
+}
+
+static void fsl_spi_cs_control(struct spi_device *spi, bool on)
+{
+ struct device *dev = spi->dev.parent->parent;
+ struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+ struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+
+ if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
+ return;
+ iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
}
static struct spi_master *fsl_spi_probe(struct device *dev,
@@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
master->setup = fsl_spi_setup;
master->cleanup = fsl_spi_cleanup;
- master->transfer_one_message = fsl_spi_do_one_msg;
+ master->prepare_message = fsl_spi_prepare_message;
+ master->transfer_one = fsl_spi_transfer_one;
+ master->unprepare_message = fsl_spi_unprepare_message;
master->use_gpio_descriptors = true;
+ master->set_cs = fsl_spi_cs_control;
mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->max_bits_per_word = 32;
@@ -688,21 +634,6 @@ err:
return ERR_PTR(ret);
}
-static void fsl_spi_cs_control(struct spi_device *spi, bool on)
-{
- if (spi->cs_gpiod) {
- gpiod_set_value(spi->cs_gpiod, on);
- } else {
- struct device *dev = spi->dev.parent->parent;
- struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-
- if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
- return;
- iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
- }
-}
-
static int of_fsl_spi_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
@@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
ret = gpiod_count(dev, "cs");
if (ret < 0)
ret = 0;
- if (ret == 0 && !spisel_boot) {
+ if (ret == 0 && !spisel_boot)
pdata->max_chipselect = 1;
- } else {
+ else
pdata->max_chipselect = ret + spisel_boot;
- pdata->cs_control = fsl_spi_cs_control;
- }
}
ret = of_address_to_resource(np, 0, &mem);
diff --git a/drivers/spi/spi-gxp.c b/drivers/spi/spi-gxp.c
index 9ea355f7d64f..15b110183839 100644
--- a/drivers/spi/spi-gxp.c
+++ b/drivers/spi/spi-gxp.c
@@ -254,7 +254,6 @@ static int gxp_spifi_probe(struct platform_device *pdev)
const struct gxp_spi_data *data;
struct spi_controller *ctlr;
struct gxp_spi *spifi;
- struct resource *res;
int ret;
data = of_device_get_match_data(&pdev->dev);
@@ -269,18 +268,15 @@ static int gxp_spifi_probe(struct platform_device *pdev)
spifi->data = data;
spifi->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- spifi->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ spifi->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spifi->reg_base))
return PTR_ERR(spifi->reg_base);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- spifi->dat_base = devm_ioremap_resource(&pdev->dev, res);
+ spifi->dat_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(spifi->dat_base))
return PTR_ERR(spifi->dat_base);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- spifi->dir_base = devm_ioremap_resource(&pdev->dev, res);
+ spifi->dir_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(spifi->dir_base))
return PTR_ERR(spifi->dir_base);
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c
index 71376b6df89d..bfd12247f173 100644
--- a/drivers/spi/spi-img-spfi.c
+++ b/drivers/spi/spi-img-spfi.c
@@ -730,11 +730,9 @@ static int img_spfi_resume(struct device *dev)
struct img_spfi *spfi = spi_master_get_devdata(master);
int ret;
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pm_runtime_put_noidle(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
return ret;
- }
spfi_reset(spfi);
pm_runtime_put(dev);
diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c
index 66063687ae27..55f4ee2db002 100644
--- a/drivers/spi/spi-intel.c
+++ b/drivers/spi/spi-intel.c
@@ -116,6 +116,22 @@
#define ERASE_64K_OPCODE_SHIFT 16
#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
+/* Flash descriptor fields */
+#define FLVALSIG_MAGIC 0x0ff0a55a
+#define FLMAP0_NC_MASK GENMASK(9, 8)
+#define FLMAP0_NC_SHIFT 8
+#define FLMAP0_FCBA_MASK GENMASK(7, 0)
+
+#define FLCOMP_C0DEN_MASK GENMASK(3, 0)
+#define FLCOMP_C0DEN_512K 0x00
+#define FLCOMP_C0DEN_1M 0x01
+#define FLCOMP_C0DEN_2M 0x02
+#define FLCOMP_C0DEN_4M 0x03
+#define FLCOMP_C0DEN_8M 0x04
+#define FLCOMP_C0DEN_16M 0x05
+#define FLCOMP_C0DEN_32M 0x06
+#define FLCOMP_C0DEN_64M 0x07
+
#define INTEL_SPI_TIMEOUT 5000 /* ms */
#define INTEL_SPI_FIFO_SZ 64
@@ -129,6 +145,7 @@
* @master: Pointer to the SPI controller structure
* @nregions: Maximum number of regions
* @pr_num: Maximum number of protected range registers
+ * @chip0_size: Size of the first flash chip in bytes
* @locked: Is SPI setting locked
* @swseq_reg: Use SW sequencer in register reads/writes
* @swseq_erase: Use SW sequencer in erase operation
@@ -146,6 +163,7 @@ struct intel_spi {
struct spi_controller *master;
size_t nregions;
size_t pr_num;
+ size_t chip0_size;
bool locked;
bool swseq_reg;
bool swseq_erase;
@@ -158,6 +176,7 @@ struct intel_spi_mem_op {
struct spi_mem_op mem_op;
u32 replacement_op;
int (*exec_op)(struct intel_spi *ispi,
+ const struct spi_mem *mem,
const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op);
};
@@ -441,7 +460,16 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
return 0;
}
-static int intel_spi_read_reg(struct intel_spi *ispi,
+static u32 intel_spi_chip_addr(const struct intel_spi *ispi,
+ const struct spi_mem *mem)
+{