summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-01-11 12:19:47 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-01-11 12:19:47 -0800
commit282aa44c21708835517ffaa31c63ab651248cf5e (patch)
tree43b9b3a257da33031144d1481afdedf1ba00d20a /drivers/spi
parentfef8dfaea9d6c444b6c2174b3a2b0fca4d226c5e (diff)
parent19629ae482f1800b50a5bdf2504ac57171d2bb82 (diff)
downloadlinux-282aa44c21708835517ffaa31c63ab651248cf5e.tar.gz
linux-282aa44c21708835517ffaa31c63ab651248cf5e.tar.bz2
linux-282aa44c21708835517ffaa31c63ab651248cf5e.zip
Merge tag 'spi-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown: "This has mostly been a quiet release for the SPI subsystem, almost all cleanups and fixes to existing drivers. A couple of changes that stand out: - Cleanups and support for version specific features in the DesignWare controller. - Removal of support for Netlogic devices from the XLP driver, the platform had previously been removed by MIPS so the support couldn't be used. - Conversion of several DT bindings to YAML format" * tag 'spi-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (53 commits) spi: don't include ptp_clock_kernel.h in spi.h spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe spi: atmel: Fix typo spi: dt-bindings: mediatek,spi-mtk-nor: Fix example 'interrupts' property spi: qcom: geni: handle timeout for gpi mode spi: qcom: geni: set the error code for gpi transfer spi: spi-mux: Add reference to spi-peripheral-props.yaml schema spi: ar934x: fix transfer size spi: pxa2xx: Propagate firmware node spi: dw: Propagate firmware node spi: dln2: Propagate firmware node spi: ar934x: fix transfer and word delays spi: uniphier: Fix a bug that doesn't point to private data correctly spi: spi-mtk-nor: add new clock name 'axi' for spi nor spi: atmel,quadspi: Define sama7g5 QSPI spi: atmel,quadspi: Convert to json-schema spi: Fix incorrect cs_setup delay handling dt-bindings: mtd: spi-nor: Add a reference to spi-peripheral-props.yaml spi: dt-bindings: cdns,qspi-nor: Move peripheral-specific properties out spi: dt-bindings: add schema listing peripheral-specific properties ...
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig11
-rw-r--r--drivers/spi/spi-ar934x.c18
-rw-r--r--drivers/spi/spi-atmel.c38
-rw-r--r--drivers/spi/spi-bcm-qspi.c44
-rw-r--r--drivers/spi/spi-dln2.c4
-rw-r--r--drivers/spi/spi-dw-bt1.c9
-rw-r--r--drivers/spi/spi-dw-core.c179
-rw-r--r--drivers/spi/spi-dw-dma.c55
-rw-r--r--drivers/spi/spi-dw-mmio.c22
-rw-r--r--drivers/spi/spi-dw-pci.c60
-rw-r--r--drivers/spi/spi-dw.h182
-rw-r--r--drivers/spi/spi-fsl-lpspi.c6
-rw-r--r--drivers/spi/spi-geni-qcom.c36
-rw-r--r--drivers/spi/spi-hisi-kunpeng.c15
-rw-r--r--drivers/spi/spi-meson-spifc.c1
-rw-r--r--drivers/spi/spi-pxa2xx.c61
-rw-r--r--drivers/spi/spi-pxa2xx.h7
-rw-r--r--drivers/spi/spi-rspi.c27
-rw-r--r--drivers/spi/spi-tegra210-quad.c11
-rw-r--r--drivers/spi/spi-uniphier.c11
-rw-r--r--drivers/spi/spi-xlp.c8
-rw-r--r--drivers/spi/spi.c194
-rw-r--r--drivers/spi/spidev.c9
23 files changed, 542 insertions, 466 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 596705d24400..b2a8821971e1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -974,14 +974,13 @@ config SPI_XILINX
Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
config SPI_XLP
- tristate "Netlogic XLP SPI controller driver"
- depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
+ tristate "Cavium ThunderX2 SPI controller driver"
+ depends on ARCH_THUNDER2 || COMPILE_TEST
help
- Enable support for the SPI controller on the Netlogic XLP SoCs.
- Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX
- and XLP5XX.
+ Enable support for the SPI controller on the Cavium ThunderX2.
+ (Originally on Netlogic XLP SoCs.)
- If you have a Netlogic XLP platform say Y here.
+ If you have a Cavium ThunderX2 platform say Y here.
If unsure, say N.
config SPI_XTENSA_XTFPGA
diff --git a/drivers/spi/spi-ar934x.c b/drivers/spi/spi-ar934x.c
index def32e0aaefe..ec7250c4c810 100644
--- a/drivers/spi/spi-ar934x.c
+++ b/drivers/spi/spi-ar934x.c
@@ -82,7 +82,7 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
struct spi_device *spi = m->spi;
unsigned long trx_done, trx_cur;
int stat = 0;
- u8 term = 0;
+ u8 bpw, term = 0;
int div, i;
u32 reg;
const u8 *tx_buf;
@@ -90,6 +90,11 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
m->actual_length = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
+ if (t->bits_per_word >= 8 && t->bits_per_word < 32)
+ bpw = t->bits_per_word >> 3;
+ else
+ bpw = 4;
+
if (t->speed_hz)
div = ar934x_spi_clk_div(sp, t->speed_hz);
else
@@ -105,10 +110,10 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL);
iowrite32(0, sp->base + AR934X_SPI_DATAOUT);
- for (trx_done = 0; trx_done < t->len; trx_done += 4) {
+ for (trx_done = 0; trx_done < t->len; trx_done += bpw) {
trx_cur = t->len - trx_done;
- if (trx_cur > 4)
- trx_cur = 4;
+ if (trx_cur > bpw)
+ trx_cur = bpw;
else if (list_is_last(&t->transfer_list, &m->transfers))
term = 1;
@@ -137,8 +142,10 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
reg >>= 8;
}
}
+ spi_delay_exec(&t->word_delay, t);
}
m->actual_length += t->len;
+ spi_transfer_delay_exec(t);
}
msg_done:
@@ -191,7 +198,8 @@ static int ar934x_spi_probe(struct platform_device *pdev)
ctlr->mode_bits = SPI_LSB_FIRST;
ctlr->setup = ar934x_spi_setup;
ctlr->transfer_one_message = ar934x_spi_transfer_one_message;
- ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+ ctlr->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
+ SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
ctlr->dev.of_node = pdev->dev.of_node;
ctlr->num_chipselect = 3;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index f872cf196c2f..9e300a932699 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -433,26 +433,25 @@ static bool atmel_spi_can_dma(struct spi_master *master,
}
-static int atmel_spi_dma_slave_config(struct atmel_spi *as,
- struct dma_slave_config *slave_config,
- u8 bits_per_word)
+static int atmel_spi_dma_slave_config(struct atmel_spi *as, u8 bits_per_word)
{
struct spi_master *master = platform_get_drvdata(as->pdev);
+ struct dma_slave_config slave_config;
int err = 0;
if (bits_per_word > 8) {
- slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
} else {
- slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
}
- slave_config->dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
- slave_config->src_addr = (dma_addr_t)as->phybase + SPI_RDR;
- slave_config->src_maxburst = 1;
- slave_config->dst_maxburst = 1;
- slave_config->device_fc = false;
+ slave_config.dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
+ slave_config.src_addr = (dma_addr_t)as->phybase + SPI_RDR;
+ slave_config.src_maxburst = 1;
+ slave_config.dst_maxburst = 1;
+ slave_config.device_fc = false;
/*
* This driver uses fixed peripheral select mode (PS bit set to '0' in
@@ -464,12 +463,11 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
* However, the first data has to be written into the lowest 16 bits and
* the second data into the highest 16 bits of the Transmit
* Data Register. For 8bit data (the most frequent case), it would
- * require to rework tx_buf so each data would actualy fit 16 bits.
+ * require to rework tx_buf so each data would actually fit 16 bits.
* So we'd rather write only one data at the time. Hence the transmit
* path works the same whether FIFOs are available (and enabled) or not.
*/
- slave_config->direction = DMA_MEM_TO_DEV;
- if (dmaengine_slave_config(master->dma_tx, slave_config)) {
+ if (dmaengine_slave_config(master->dma_tx, &slave_config)) {
dev_err(&as->pdev->dev,
"failed to configure tx dma channel\n");
err = -EINVAL;
@@ -483,8 +481,7 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
* So the receive path works the same whether FIFOs are available (and
* enabled) or not.
*/
- slave_config->direction = DMA_DEV_TO_MEM;
- if (dmaengine_slave_config(master->dma_rx, slave_config)) {
+ if (dmaengine_slave_config(master->dma_rx, &slave_config)) {
dev_err(&as->pdev->dev,
"failed to configure rx dma channel\n");
err = -EINVAL;
@@ -496,7 +493,6 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
static int atmel_spi_configure_dma(struct spi_master *master,
struct atmel_spi *as)
{
- struct dma_slave_config slave_config;
struct device *dev = &as->pdev->dev;
int err;
@@ -518,7 +514,7 @@ static int atmel_spi_configure_dma(struct spi_master *master,
goto error;
}
- err = atmel_spi_dma_slave_config(as, &slave_config, 8);
+ err = atmel_spi_dma_slave_config(as, 8);
if (err)
goto error;
@@ -700,7 +696,6 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
struct dma_chan *txchan = master->dma_tx;
struct dma_async_tx_descriptor *rxdesc;
struct dma_async_tx_descriptor *txdesc;
- struct dma_slave_config slave_config;
dma_cookie_t cookie;
dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_dma_submit\n");
@@ -712,8 +707,7 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
*plen = xfer->len;
- if (atmel_spi_dma_slave_config(as, &slave_config,
- xfer->bits_per_word))
+ if (atmel_spi_dma_slave_config(as, xfer->bits_per_word))
goto err_exit;
/* Send both scatterlists */
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index f3de3305d0f5..c9a769b8594b 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -287,6 +287,18 @@ static inline int bcm_qspi_spbr_min(struct bcm_qspi *qspi)
return 8;
}
+static u32 bcm_qspi_calc_spbr(u32 clk_speed_hz,
+ const struct bcm_qspi_parms *xp)
+{
+ u32 spbr = 0;
+
+ /* SPBR = System Clock/(2 * SCK Baud Rate) */
+ if (xp->speed_hz)
+ spbr = clk_speed_hz / (xp->speed_hz * 2);
+
+ return spbr;
+}
+
/* Read qspi controller register*/
static inline u32 bcm_qspi_read(struct bcm_qspi *qspi, enum base_type type,
unsigned int offset)
@@ -586,12 +598,24 @@ static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs)
qspi->curr_cs = cs;
}
+static bool bcmspi_parms_did_change(const struct bcm_qspi_parms * const cur,
+ const struct bcm_qspi_parms * const prev)
+{
+ return (cur->speed_hz != prev->speed_hz) ||
+ (cur->mode != prev->mode) ||
+ (cur->bits_per_word != prev->bits_per_word);
+}
+
+
/* MSPI helpers */
static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
const struct bcm_qspi_parms *xp)
{
u32 spcr, spbr = 0;
+ if (!bcmspi_parms_did_change(xp, &qspi->last_parms))
+ return;
+
if (!qspi->mspi_maj_rev)
/* legacy controller */
spcr = MSPI_MASTER_BIT;
@@ -621,9 +645,17 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
spcr |= MSPI_SPCR3_HALFDUPLEX | MSPI_SPCR3_HDOUTTYPE;
if (bcm_qspi_has_sysclk_108(qspi)) {
- /* SYSCLK_108 */
- spcr |= MSPI_SPCR3_SYSCLKSEL_108;
- qspi->base_clk = MSPI_BASE_FREQ * 4;
+ /* check requested baud rate before moving to 108Mhz */
+ spbr = bcm_qspi_calc_spbr(MSPI_BASE_FREQ * 4, xp);
+ if (spbr > QSPI_SPBR_MAX) {
+ /* use SYSCLK_27Mhz for slower baud rates */
+ spcr &= ~MSPI_SPCR3_SYSCLKSEL_MASK;
+ qspi->base_clk = MSPI_BASE_FREQ;
+ } else {
+ /* SYSCLK_108Mhz */
+ spcr |= MSPI_SPCR3_SYSCLKSEL_108;
+ qspi->base_clk = MSPI_BASE_FREQ * 4;
+ }
}
if (xp->bits_per_word > 16) {
@@ -649,9 +681,9 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
bcm_qspi_write(qspi, MSPI, MSPI_SPCR3, spcr);
}
- if (xp->speed_hz)
- spbr = qspi->base_clk / (2 * xp->speed_hz);
-
+ /* SCK Baud Rate = System Clock/(2 * SPBR) */
+ qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
+ spbr = bcm_qspi_calc_spbr(qspi->base_clk, xp);
spbr = clamp_val(spbr, bcm_qspi_spbr_min(qspi), QSPI_SPBR_MAX);
bcm_qspi_write(qspi, MSPI, MSPI_SPCR0_LSB, spbr);
diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c
index 3ff63ab82f4f..0a1fb2bc9e54 100644
--- a/drivers/spi/spi-dln2.c
+++ b/drivers/spi/spi-dln2.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/mfd/dln2.h>
#include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
@@ -688,6 +689,8 @@ static int dln2_spi_probe(struct platform_device *pdev)
if (!master)
return -ENOMEM;
+ device_set_node(&master->dev, dev_fwnode(dev));
+
platform_set_drvdata(pdev, master);
dln2 = spi_master_get_devdata(master);
@@ -699,7 +702,6 @@ static int dln2_spi_probe(struct platform_device *pdev)
}
dln2->master = master;
- dln2->master->dev.of_node = dev->of_node;
dln2->pdev = pdev;
dln2->port = pdata->port;
/* cs/mode can never be 0xff, so the first transfer will set them */
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c
index 5be6b7b80c21..c06553416123 100644
--- a/drivers/spi/spi-dw-bt1.c
+++ b/drivers/spi/spi-dw-bt1.c
@@ -123,7 +123,7 @@ static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,
len = min_t(size_t, len, dwsbt1->map_len - offs);
/* Collect the controller configuration required by the operation */
- cfg.tmode = SPI_TMOD_EPROMREAD;
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;
cfg.dfs = 8;
cfg.ndf = 4;
cfg.freq = mem->spi->max_speed_hz;
@@ -131,13 +131,13 @@ static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,
/* Make sure the corresponding CS is de-asserted on transmission */
dw_spi_set_cs(mem->spi, false);
- spi_enable_chip(dws, 0);
+ dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, mem->spi, &cfg);
- spi_umask_intr(dws, SPI_INT_RXFI);
+ dw_spi_umask_intr(dws, DW_SPI_INT_RXFI);
- spi_enable_chip(dws, 1);
+ dw_spi_enable_chip(dws, 1);
/*
* Enable the transparent mode of the System Boot Controller.
@@ -339,3 +339,4 @@ module_platform_driver(dw_spi_bt1_driver);
MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
MODULE_DESCRIPTION("Baikal-T1 System Boot SPI Controller driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(SPI_DW_CORE);
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index a305074c482e..ecea471ff42c 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -5,6 +5,7 @@
* Copyright (c) 2009, Intel Corporation.
*/
+#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -24,7 +25,7 @@
#endif
/* Slave spi_device related */
-struct chip_data {
+struct dw_spi_chip_data {
u32 cr0;
u32 rx_sample_dly; /* RX sample delay */
};
@@ -106,10 +107,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
else
dw_writel(dws, DW_SPI_SER, 0);
}
-EXPORT_SYMBOL_GPL(dw_spi_set_cs);
+EXPORT_SYMBOL_NS_GPL(dw_spi_set_cs, SPI_DW_CORE);
/* Return the max entries we can fill into tx fifo */
-static inline u32 tx_max(struct dw_spi *dws)
+static inline u32 dw_spi_tx_max(struct dw_spi *dws)
{
u32 tx_room, rxtx_gap;
@@ -129,14 +130,14 @@ static inline u32 tx_max(struct dw_spi *dws)
}
/* Return the max entries we should read out of rx fifo */
-static inline u32 rx_max(struct dw_spi *dws)
+static inline u32 dw_spi_rx_max(struct dw_spi *dws)
{
return min_t(u32, dws->rx_len, dw_readl(dws, DW_SPI_RXFLR));
}
static void dw_writer(struct dw_spi *dws)
{
- u32 max = tx_max(dws);
+ u32 max = dw_spi_tx_max(dws);
u32 txw = 0;
while (max--) {
@@ -157,7 +158,7 @@ static void dw_writer(struct dw_spi *dws)
static void dw_reader(struct dw_spi *dws)
{
- u32 max = rx_max(dws);
+ u32 max = dw_spi_rx_max(dws);
u32 rxw;
while (max--) {
@@ -186,31 +187,31 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw)
else
irq_status = dw_readl(dws, DW_SPI_ISR);
- if (irq_status & SPI_INT_RXOI) {
+ if (irq_status & DW_SPI_INT_RXOI) {
dev_err(&dws->master->dev, "RX FIFO overflow detected\n");
ret = -EIO;
}
- if (irq_status & SPI_INT_RXUI) {
+ if (irq_status & DW_SPI_INT_RXUI) {
dev_err(&dws->master->dev, "RX FIFO underflow detected\n");
ret = -EIO;
}
- if (irq_status & SPI_INT_TXOI) {
+ if (irq_status & DW_SPI_INT_TXOI) {
dev_err(&dws->master->dev, "TX FIFO overflow detected\n");
ret = -EIO;
}
/* Generically handle the erroneous situation */
if (ret) {
- spi_reset_chip(dws);
+ dw_spi_reset_chip(dws);
if (dws->master->cur_msg)
dws->master->cur_msg->status = ret;
}
return ret;
}
-EXPORT_SYMBOL_GPL(dw_spi_check_status);
+EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, SPI_DW_CORE);
static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
{
@@ -230,7 +231,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
*/
dw_reader(dws);
if (!dws->rx_len) {
- spi_mask_intr(dws, 0xff);
+ dw_spi_mask_intr(dws, 0xff);
spi_finalize_current_transfer(dws->master);
} else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
@@ -241,10 +242,10 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
* disabled after the data transmission is finished so not to
* have the TXE IRQ flood at the final stage of the transfer.
*/
- if (irq_status & SPI_INT_TXEI) {
+ if (irq_status & DW_SPI_INT_TXEI) {
dw_writer(dws);
if (!dws->tx_len)
- spi_mask_intr(dws, SPI_INT_TXEI);
+ dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
}
return IRQ_HANDLED;
@@ -254,13 +255,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
{
struct spi_controller *master = dev_id;
struct dw_spi *dws = spi_controller_get_devdata(master);
- u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f;
+ u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK;
if (!irq_status)
return IRQ_NONE;
if (!master->cur_msg) {
- spi_mask_intr(dws, 0xff);
+ dw_spi_mask_intr(dws, 0xff);
return IRQ_HANDLED;
}
@@ -271,37 +272,43 @@ static u32 dw_spi_prepare_cr0(struct dw_spi *dws, struct spi_device *spi)
{
u32 cr0 = 0;
- if (!(dws->caps & DW_SPI_CAP_DWC_SSI)) {
+ if (dw_spi_ip_is(dws, PSSI)) {
/* CTRLR0[ 5: 4] Frame Format */
- cr0 |= SSI_MOTO_SPI << SPI_FRF_OFFSET;
+ cr0 |= FIELD_PREP(DW_PSSI_CTRLR0_FRF_MASK, DW_SPI_CTRLR0_FRF_MOTO_SPI);
/*
* SPI mode (SCPOL|SCPH)
* CTRLR0[ 6] Serial Clock Phase
* CTRLR0[ 7] Serial Clock Polarity
*/
- cr0 |= ((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET;
- cr0 |= ((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET;
+ if (spi->mode & SPI_CPOL)
+ cr0 |= DW_PSSI_CTRLR0_SCPOL;
+ if (spi->mode & SPI_CPHA)
+ cr0 |= DW_PSSI_CTRLR0_SCPHA;
/* CTRLR0[11] Shift Register Loop */
- cr0 |= ((spi->mode & SPI_LOOP) ? 1 : 0) << SPI_SRL_OFFSET;
+ if (spi->mode & SPI_LOOP)
+ cr0 |= DW_PSSI_CTRLR0_SRL;
} else {
/* CTRLR0[ 7: 6] Frame Format */
- cr0 |= SSI_MOTO_SPI << DWC_SSI_CTRLR0_FRF_OFFSET;
+ cr0 |= FIELD_PREP(DW_HSSI_CTRLR0_FRF_MASK, DW_SPI_CTRLR0_FRF_MOTO_SPI);
/*
* SPI mode (SCPOL|SCPH)
* CTRLR0[ 8] Serial Clock Phase
* CTRLR0[ 9] Serial Clock Polarity
*/
- cr0 |= ((spi->mode & SPI_CPOL) ? 1 : 0) << DWC_SSI_CTRLR0_SCPOL_OFFSET;
- cr0 |= ((spi->mode & SPI_CPHA) ? 1 : 0) << DWC_SSI_CTRLR0_SCPH_OFFSET;
+ if (spi->mode & SPI_CPOL)
+ cr0 |= DW_HSSI_CTRLR0_SCPOL;
+ if (spi->mode & SPI_CPHA)
+ cr0 |= DW_HSSI_CTRLR0_SCPHA;
/* CTRLR0[13] Shift Register Loop */
- cr0 |= ((spi->mode & SPI_LOOP) ? 1 : 0) << DWC_SSI_CTRLR0_SRL_OFFSET;
+ if (spi->mode & SPI_LOOP)
+ cr0 |= DW_HSSI_CTRLR0_SRL;
if (dws->caps & DW_SPI_CAP_KEEMBAY_MST)
- cr0 |= DWC_SSI_CTRLR0_KEEMBAY_MST;
+ cr0 |= DW_HSSI_CTRLR0_KEEMBAY_MST;
}
return cr0;
@@ -310,7 +317,7 @@ static u32 dw_spi_prepare_cr0(struct dw_spi *dws, struct spi_device *spi)
void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
struct dw_spi_cfg *cfg)
{
- struct chip_data *chip = spi_get_ctldata(spi);
+ struct dw_spi_chip_data *chip = spi_get_ctldata(spi);
u32 cr0 = chip->cr0;
u32 speed_hz;
u16 clk_div;
@@ -318,16 +325,17 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
/* CTRLR0[ 4/3: 0] or CTRLR0[ 20: 16] Data Frame Size */
cr0 |= (cfg->dfs - 1) << dws->dfs_offset;
- if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
+ if (dw_spi_ip_is(dws, PSSI))
/* CTRLR0[ 9:8] Transfer Mode */
- cr0 |= cfg->tmode << SPI_TMOD_OFFSET;
+ cr0 |= FIELD_PREP(DW_PSSI_CTRLR0_TMOD_MASK, cfg->tmode);
else
/* CTRLR0[11:10] Transfer Mode */
- cr0 |= cfg->tmode << DWC_SSI_CTRLR0_TMOD_OFFSET;
+ cr0 |= FIELD_PREP(DW_HSSI_CTRLR0_TMOD_MASK, cfg->tmode);
dw_writel(dws, DW_SPI_CTRLR0, cr0);
- if (cfg->tmode == SPI_TMOD_EPROMREAD || cfg->tmode == SPI_TMOD_RO)
+ if (cfg->tmode == DW_SPI_CTRLR0_TMOD_EPROMREAD ||
+ cfg->tmode == DW_SPI_CTRLR0_TMOD_RO)
dw_writel(dws, DW_SPI_CTRLR1, cfg->ndf ? cfg->ndf - 1 : 0);
/* Note DW APB SSI clock divider doesn't support odd numbers */
@@ -335,7 +343,7 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
speed_hz = dws->max_freq / clk_div;
if (dws->current_freq != speed_hz) {
- spi_set_clk(dws, clk_div);
+ dw_spi_set_clk(dws, clk_div);
dws->current_freq = speed_hz;
}
@@ -345,7 +353,7 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
dws->cur_rx_sample_dly = chip->rx_sample_dly;
}
}
-EXPORT_SYMBOL_GPL(dw_spi_update_config);
+EXPORT_SYMBOL_NS_GPL(dw_spi_update_config, SPI_DW_CORE);
static void dw_spi_irq_setup(struct dw_spi *dws)
{
@@ -363,9 +371,9 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
dws->transfer_handler = dw_spi_transfer_handler;
- imask = SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI |
- SPI_INT_RXFI;
- spi_umask_intr(dws, imask);
+ imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI |
+ DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
+ dw_spi_umask_intr(dws, imask);
}
/*
@@ -405,11 +413,12 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
}
static int dw_spi_transfer_one(struct spi_controller *master,
- struct spi_device *spi, struct spi_transfer *transfer)
+ struct spi_device *spi,
+ struct spi_transfer *transfer)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
struct dw_spi_cfg cfg = {
- .tmode = SPI_TMOD_TR,
+ .tmode = DW_SPI_CTRLR0_TMOD_TR,
.dfs = transfer->bits_per_word,
.freq = transfer->speed_hz,
};
@@ -425,7 +434,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
/* Ensure the data above is visible for all CPUs */
smp_mb();
- spi_enable_chip(dws, 0);
+ dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, spi, &cfg);
@@ -436,7 +445,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
dws->dma_mapped = master->cur_msg_mapped;
/* For poll mode just disable all interrupts */
- spi_mask_intr(dws, 0xff);
+ dw_spi_mask_intr(dws, 0xff);
if (dws->dma_mapped) {
ret = dws->dma_ops->dma_setup(dws, transfer);
@@ -444,7 +453,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
return ret;
}
- spi_enable_chip(dws, 1);
+ dw_spi_enable_chip(dws, 1);
if (dws->dma_mapped)
return dws->dma_ops->dma_transfer(dws, transfer);
@@ -457,20 +466,20 @@ static int dw_spi_transfer_one(struct spi_controller *master,
}
static void dw_spi_handle_err(struct spi_controller *master,
- struct spi_message *msg)
+ struct spi_message *msg)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
if (dws->dma_mapped)
dws->dma_ops->dma_stop(dws);
- spi_reset_chip(dws);
+ dw_spi_reset_chip(dws);
}
static int dw_spi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
if (op->data.dir == SPI_MEM_DATA_IN)
- op->data.nbytes = clamp_val(op->data.nbytes, 0, SPI_NDF_MASK + 1);
+ op->data.nbytes = clamp_val(op->data.nbytes, 0, DW_SPI_NDF_MASK + 1);
return 0;
}
@@ -498,7 +507,7 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
if (op->data.dir == SPI_MEM_DATA_OUT)
len += op->data.nbytes;
- if (len <= SPI_BUF_SIZE) {
+ if (len <= DW_SPI_BUF_SIZE) {
out = dws->buf;
} else {
out = kzalloc(len, GFP_KERNEL);
@@ -512,9 +521,9 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
* single buffer in order to speed the data transmission up.
*/
for (i = 0; i < op->cmd.nbytes; ++i)
- out[i] = SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1);
+ out[i] = DW_SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1);
for (j = 0; j < op->addr.nbytes; ++i, ++j)
- out[i] = SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
+ out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
for (j = 0; j < op->dummy.nbytes; ++i, ++j)
out[i] = 0x0;
@@ -587,7 +596,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
entries = readl_relaxed(dws->regs + DW_SPI_RXFLR);
if (!entries) {
sts = readl_relaxed(dws->regs + DW_SPI_RISR);
- if (sts & SPI_INT_RXOI) {
+ if (sts & DW_SPI_INT_RXOI) {
dev_err(&dws->master->dev, "FIFO overflow on Rx\n");
return -EIO;
}
@@ -603,12 +612,12 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
static inline bool dw_spi_ctlr_busy(struct dw_spi *dws)
{
- return dw_readl(dws, DW_SPI_SR) & SR_BUSY;
+ return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY;
}
static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
{
- int retry = SPI_WAIT_RETRIES;
+ int retry = DW_SPI_WAIT_RETRIES;
struct spi_delay delay;
unsigned long ns, us;
u32 nents;
@@ -638,9 +647,9 @@ static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
static void dw_spi_stop_mem_op(struct dw_spi *dws, struct spi_device *spi)
{
- spi_enable_chip(dws, 0);
+ dw_spi_enable_chip(dws, 0);
dw_spi_set_cs(spi, true);
- spi_enable_chip(dws, 1);
+ dw_spi_enable_chip(dws, 1);
}
/*
@@ -673,19 +682,19 @@ static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
cfg.dfs = 8;
cfg.freq = clamp(mem->spi->max_speed_hz, 0U, dws->max_mem_freq);
if (op->data.dir == SPI_MEM_DATA_IN) {
- cfg.tmode = SPI_TMOD_EPROMREAD;
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;
cfg.ndf = op->data.nbytes;
} else {
- cfg.tmode = SPI_TMOD_TO;
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
}
- spi_enable_chip(dws, 0);
+ dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, mem->spi, &cfg);
- spi_mask_intr(dws, 0xff);
+ dw_spi_mask_intr(dws, 0xff);
- spi_enable_chip(dws, 1);
+ dw_spi_enable_chip(dws, 1);
/*
* DW APB SSI controller has very nasty peculiarities. First originally
@@ -768,7 +777,7 @@ static void dw_spi_init_mem_ops(struct dw_spi *dws)
static int dw_spi_setup(struct spi_device *spi)
{
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
- struct chip_data *chip;
+ struct dw_spi_chip_data *chip;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
@@ -776,7 +785,7 @@ static int dw_spi_setup(struct spi_device *spi)
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
u32 rx_sample_dly_ns;
- chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
spi_set_ctldata(spi, chip);
@@ -803,16 +812,30 @@ static int dw_spi_setup(struct spi_device *spi)
static void dw_spi_cleanup(struct spi_device *spi)
{
- struct chip_data *chip = spi_get_ctldata(spi);
+ struct dw_spi_chip_data *chip = spi_get_ctldata(spi);
kfree(chip);
spi_set_ctldata(spi, NULL);
}
/* Restart the controller, disable all interrupts, clean rx fifo */
-static void spi_hw_init(struct device *dev, struct dw_spi *dws)
+static void dw_spi_hw_init(struct device *dev, struct dw_spi *dws)
{
- spi_reset_chip(dws);
+ dw_spi_reset_chip(dws);
+
+ /*
+ * Retrieve the Synopsys component version if it hasn't been specified
+ * by the platform. CoreKit version ID is encoded as a 3-chars ASCII
+ * code enclosed with '*' (typical for the most of Synopsys IP-cores).
+ */
+ if (!dws->ver) {
+ dws->ver = dw_readl(dws, DW_SPI_VERSION);
+
+ dev_dbg(dev, "Synopsys DWC%sSSI v%c.%c%c\n",
+ dw_spi_ip_is(dws, PSSI) ? " APB " : " ",
+ DW_SPI_GET_BYTE(dws->ver, 3), DW_SPI_GET_BYTE(dws->ver, 2),
+ DW_SPI_GET_BYTE(dws->ver, 1));
+ }
/*
* Try to detect the FIFO depth if not set by interface driver,
@@ -837,18 +860,18 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
* writability. Note DWC SSI controller also has the extended DFS, but
* with zero offset.
*/
- if (!(dws->caps & DW_SPI_CAP_DWC_SSI)) {
+ if (dw_spi_ip_is(dws, PSSI)) {
u32 cr0, tmp = dw_readl(dws, DW_SPI_CTRLR0);
- spi_enable_chip(dws, 0);
+ dw_spi_enable_chip(dws, 0);
dw_writel(dws, DW_SPI_CTRLR0, 0xffffffff);
cr0 = dw_readl(dws, DW_SPI_CTRLR0);
dw_writel(dws, DW_SPI_CTRLR0, tmp);