From 4247d7f2ca564bbede54054da1f35a359bb061bd Mon Sep 17 00:00:00 2001 From: Ruihai Zhou Date: Mon, 8 Jan 2024 20:08:02 +0800 Subject: [PATCH 001/122] spi: spi-mt65xx: Support sleep pin control Supports configuring sleep pin control during system suspend to prevent potential power leakage and additional power consumption. Signed-off-by: Ruihai Zhou Link: https://msgid.link/r/20240108120802.7601-1-zhouruihai@huaqin.corp-partner.google.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 8d5d170d49cc..8d4633b353ee 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1316,6 +1317,8 @@ static int mtk_spi_suspend(struct device *dev) clk_disable_unprepare(mdata->spi_hclk); } + pinctrl_pm_select_sleep_state(dev); + return 0; } @@ -1325,6 +1328,8 @@ static int mtk_spi_resume(struct device *dev) struct spi_controller *host = dev_get_drvdata(dev); struct mtk_spi *mdata = spi_controller_get_devdata(host); + pinctrl_pm_select_default_state(dev); + if (!pm_runtime_suspended(dev)) { ret = clk_prepare_enable(mdata->spi_clk); if (ret < 0) { From 6df534cc7136fc9e023cbd4e0011a04e3659e74d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 5 Jan 2024 11:32:50 +0100 Subject: [PATCH 002/122] spi: make spi_bus_type const Now that the driver core can properly handle constant struct bus_type, move the spi_bus_type variable to be a constant structure as well, placing it into read-only memory which can not be modified at runtime. Cc: Mark Brown Cc: Signed-off-by: Greg Kroah-Hartman Link: https://msgid.link/r/2024010549-erasure-swoop-1cc6@gregkh Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- include/linux/spi/spi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7477a11e12be..bc3d7c0ce6b4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -459,7 +459,7 @@ static void spi_shutdown(struct device *dev) } } -struct bus_type spi_bus_type = { +const struct bus_type spi_bus_type = { .name = "spi", .dev_groups = spi_dev_groups, .match = spi_match_device, diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 471fe2ff9066..f306aececeaf 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -36,7 +36,7 @@ struct spi_message; * INTERFACES between SPI master-side drivers and SPI slave protocol handlers, * and SPI infrastructure. */ -extern struct bus_type spi_bus_type; +extern const struct bus_type spi_bus_type; /** * struct spi_statistics - statistics for spi transfers From 50c4f8172dbf9fdf152eae5179e233879a72dd47 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 18 Jan 2024 13:10:16 +0100 Subject: [PATCH 003/122] spi: nxp-fspi: Adjust LUT debug output alignment Ensure the command value and LUT entry values have a fixed width. This way consecutive output lines can be read much easier. Signed-off-by: Alexander Stein Link: https://msgid.link/r/20240118121016.3734770-1-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index e13f678f2395..88397f712a3b 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -591,7 +591,7 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, for (i = 0; i < ARRAY_SIZE(lutval); i++) fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); - dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n", + dev_dbg(f->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x], size: 0x%08x\n", op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); /* lock LUT */ From 460efee706c2b6a4daba62ec143fea29c2e7b358 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Sat, 20 Jan 2024 11:00:01 -0600 Subject: [PATCH 004/122] spi: s3c64xx: Extract FIFO depth calculation to a dedicated macro Simplify the code by extracting all cases of FIFO depth calculation into a dedicated macro. No functional change. Signed-off-by: Sam Protsenko Reviewed-by: Andi Shyti Link: https://msgid.link/r/20240120170001.3356-1-semen.protsenko@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 0e48ffd499b9..432ec60d3568 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -109,6 +109,7 @@ #define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i)) #define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \ FIFO_LVL_MASK(i)) +#define FIFO_DEPTH(i) ((FIFO_LVL_MASK(i) >> 1) + 1) #define S3C64XX_SPI_MAX_TRAILCNT 0x3ff #define S3C64XX_SPI_TRAILCNT_OFF 19 @@ -406,7 +407,7 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); if (sdd->rx_dma.ch && sdd->tx_dma.ch) { - return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1; + return xfer->len > FIFO_DEPTH(sdd); } else { return false; } @@ -495,9 +496,7 @@ static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, void __iomem *regs = sdd->regs; unsigned long val = 1; u32 status; - - /* max fifo depth available */ - u32 max_fifo = (FIFO_LVL_MASK(sdd) >> 1) + 1; + u32 max_fifo = FIFO_DEPTH(sdd); if (timeout_ms) val = msecs_to_loops(timeout_ms); @@ -604,7 +603,7 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, * For any size less than the fifo size the below code is * executed atleast once. */ - loops = xfer->len / ((FIFO_LVL_MASK(sdd) >> 1) + 1); + loops = xfer->len / FIFO_DEPTH(sdd); buf = xfer->rx_buf; do { /* wait for data to be received in the fifo */ @@ -741,7 +740,7 @@ static int s3c64xx_spi_transfer_one(struct spi_controller *host, struct spi_transfer *xfer) { struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); - const unsigned int fifo_len = (FIFO_LVL_MASK(sdd) >> 1) + 1; + const unsigned int fifo_len = FIFO_DEPTH(sdd); const void *tx_buf = NULL; void *rx_buf = NULL; int target_len = 0, origin_len = 0; @@ -1280,7 +1279,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Targets attached\n", sdd->port_id, host->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\n", - mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1); + mem_res, FIFO_DEPTH(sdd)); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); From 6685d552a0cc3a86e10dbe6d98e1b51717a27a63 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 22 Jan 2024 17:15:09 +0800 Subject: [PATCH 005/122] dt-bindings: spi: fsl-lpspi: support i.MX95 LPSPI Add i.MX95 LPSPI compatible string, same as i.MX93 compatible with i.MX7ULP Signed-off-by: Peng Fan Acked-by: Conor Dooley Link: https://msgid.link/r/20240122091510.2077498-1-peng.fan@oss.nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml b/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml index 727c5346b8ce..2ff174244795 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml +++ b/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml @@ -22,6 +22,7 @@ properties: - enum: - fsl,imx8ulp-spi - fsl,imx93-spi + - fsl,imx95-spi - const: fsl,imx7ulp-spi reg: maxItems: 1 From 18ab9e9e8889ecba23a5e8b7f8924f09284e33d8 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 22 Jan 2024 17:15:10 +0800 Subject: [PATCH 006/122] dt-bindings: spi: nxp-fspi: support i.MX93 and i.MX95 Add i.MX93/95 flexspi compatible strings, which are compatible with i.MX8MM Signed-off-by: Peng Fan Acked-by: Han Xu Acked-by: Conor Dooley Link: https://msgid.link/r/20240122091510.2077498-2-peng.fan@oss.nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-nxp-fspi.yaml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml index 7fd591145480..4a5f41bde00f 100644 --- a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml +++ b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml @@ -15,12 +15,18 @@ allOf: properties: compatible: - enum: - - nxp,imx8dxl-fspi - - nxp,imx8mm-fspi - - nxp,imx8mp-fspi - - nxp,imx8qxp-fspi - - nxp,lx2160a-fspi + oneOf: + - enum: + - nxp,imx8dxl-fspi + - nxp,imx8mm-fspi + - nxp,imx8mp-fspi + - nxp,imx8qxp-fspi + - nxp,lx2160a-fspi + - items: + - enum: + - nxp,imx93-fspi + - nxp,imx95-fspi + - const: nxp,imx8mm-fspi reg: items: From 0229278bf33ea69cc1bba12c287f173e9b18c1f8 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Fri, 19 Jan 2024 19:29:46 -0600 Subject: [PATCH 007/122] spi: s3c64xx: Add Exynos850 support Add SPI port configuration for Exynos850 SoC. It has 3 USI blocks which can be configured in SPI mode: * spi_0: BLK_PERI_SPI_0 (0x13940000) * spi_1: BLK_ALIVE_USI_CMGP00 (0x11d00000) * spi_2: BLK_ALIVE_USI_CMGP01 (0x11d20000) SPI FIFO depth is 64 bytes for all those SPI blocks, so the .fifo_lvl_mask value is set to 0x7f. All blocks have DIV_4 as the default internal clock divider, and an internal loopback mode to run a loopback test. Signed-off-by: Sam Protsenko Reviewed-by: Tudor Ambarus Link: https://msgid.link/r/20240120012948.8836-6-semen.protsenko@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 432ec60d3568..7f7eb8f742e4 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1460,6 +1460,17 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; +static const struct s3c64xx_spi_port_config exynos850_spi_port_config = { + .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f }, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .clk_div = 4, + .high_speed = true, + .clk_from_cmu = true, + .has_loopback = true, + .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, +}; + static const struct s3c64xx_spi_port_config exynosautov9_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, @@ -1514,6 +1525,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,exynos5433-spi", .data = (void *)&exynos5433_spi_port_config, }, + { .compatible = "samsung,exynos850-spi", + .data = (void *)&exynos850_spi_port_config, + }, { .compatible = "samsung,exynosautov9-spi", .data = (void *)&exynosautov9_spi_port_config, }, From 737cf74b38007fd5d5d2f15d4d4bc16e5f1cbfed Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Fri, 19 Jan 2024 19:29:43 -0600 Subject: [PATCH 008/122] spi: dt-bindings: samsung: Add Exynos850 SPI Document samsung,exynos850-spi compatible which will be used on Exynos850 SoC. Exynos850 doesn't have ioclk, so only two clocks are needed (bus clock and functional SPI clock). Signed-off-by: Sam Protsenko Reviewed-by: Tudor Ambarus Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240120012948.8836-3-semen.protsenko@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/samsung,spi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml index 79da99ca0e53..f71099852653 100644 --- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -22,6 +22,7 @@ properties: - samsung,s5pv210-spi # for S5PV210 and S5PC110 - samsung,exynos4210-spi - samsung,exynos5433-spi + - samsung,exynos850-spi - samsung,exynosautov9-spi - tesla,fsd-spi - const: samsung,exynos7-spi From b204aa0f99cfe3c9d796ecfc0bc6f3f89585789e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 23 Jan 2024 15:49:46 -0600 Subject: [PATCH 009/122] spi: consolidate setting message->spi Previously, __spi_sync() and __spi_async() set message->spi to the spi device independently after calling __spi_validate(). __spi_validate() also would conditionally set this if it needed to split the message since it wasn't set yet. Since both __spi_sync() and __spi_async() call __spi_validate(), we can consolidate this into only setting message->spi once (unconditionally) in __spi_validate(). This will also save any future callers of __spi_validate() from also needing to set message->spi. Signed-off-by: David Lechner Link: https://msgid.link/r/20240123214946.2616786-1-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bc3d7c0ce6b4..7a70ef47cdf6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4059,6 +4059,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) if (list_empty(&message->transfers)) return -EINVAL; + message->spi = spi; + /* * If an SPI controller does not support toggling the CS line on each * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO @@ -4071,9 +4073,6 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) size_t maxsize = BITS_TO_BYTES(spi->bits_per_word); int ret; - /* spi_split_transfers_maxsize() requires message->spi */ - message->spi = spi; - ret = spi_split_transfers_maxsize(ctlr, message, maxsize, GFP_KERNEL); if (ret) @@ -4210,8 +4209,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if (!ctlr->transfer) return -ENOTSUPP; - message->spi = spi; - SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_async); SPI_STATISTICS_INCREMENT_FIELD(spi->pcpu_statistics, spi_async); @@ -4391,8 +4388,6 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) if (status != 0) return status; - message->spi = spi; - SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_sync); SPI_STATISTICS_INCREMENT_FIELD(spi->pcpu_statistics, spi_sync); From a6fc5c5b35f688480167a7a7947ddd91c07e72c8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 25 Jan 2024 10:34:26 +0000 Subject: [PATCH 010/122] spi: cs42l43: Handle error from devm_pm_runtime_enable() As it devm_pm_runtime_enable() can fail due to memory allocations, it is best to handle the error. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Charles Keepax Link: https://msgid.link/r/20240125103426.2622549-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/spi/spi-cs42l43.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c index f13073e12593..b24190526ce9 100644 --- a/drivers/spi/spi-cs42l43.c +++ b/drivers/spi/spi-cs42l43.c @@ -244,7 +244,10 @@ static int cs42l43_spi_probe(struct platform_device *pdev) priv->ctlr->use_gpio_descriptors = true; priv->ctlr->auto_runtime_pm = true; - devm_pm_runtime_enable(priv->dev); + ret = devm_pm_runtime_enable(priv->dev); + if (ret) + return ret; + pm_runtime_idle(priv->dev); regmap_write(priv->regmap, CS42L43_TRAN_CONFIG6, CS42L43_FIFO_SIZE - 1); From 0da9a5794cfda615668eaefde811e8ef378134fe Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 25 Jan 2024 17:47:31 -0600 Subject: [PATCH 011/122] spi: avoid double validation in __spi_sync() The __spi_sync() function calls __spi_validate() early in the function. Later, it can call spi_async_locked() which calls __spi_validate() again. __spi_validate() is an expensive function, so we can improve performance measurably by avoiding calling it twice. Instead of calling spi_async_locked(), we can call __spi_async() with the spin lock held. spi_async_locked() is removed since there are no more callers. Signed-off-by: David Lechner Link: https://msgid.link/r/20240125234732.3530278-2-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 58 +++++------------------------------------------ 1 file changed, 6 insertions(+), 52 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7a70ef47cdf6..6610aeced765 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4278,57 +4278,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message) } EXPORT_SYMBOL_GPL(spi_async); -/** - * spi_async_locked - version of spi_async with exclusive bus usage - * @spi: device with which data will be exchanged - * @message: describes the data transfers, including completion callback - * Context: any (IRQs may be blocked, etc) - * - * This call may be used in_irq and other contexts which can't sleep, - * as well as from task contexts which can sleep. - * - * The completion callback is invoked in a context which can't sleep. - * Before that invocation, the value of message->status is undefined. - * When the callback is issued, message->status holds either zero (to - * indicate complete success) or a negative error code. After that - * callback returns, the driver which issued the transfer request may - * deallocate the associated memory; it's no longer in use by any SPI - * core or controller driver code. - * - * Note that although all messages to a spi_device are handled in - * FIFO order, messages may go to different devices in other orders. - * Some device might be higher priority, or have various "hard" access - * time requirements, for example. - * - * On detection of any fault during the transfer, processing of - * the entire message is aborted, and the device is deselected. - * Until returning from the associated message completion callback, - * no other spi_message queued to that device will be processed. - * (This rule applies equally to all the synchronous transfer calls, - * which are wrappers around this core asynchronous primitive.) - * - * Return: zero on success, else a negative error code. - */ -static int spi_async_locked(struct spi_device *spi, struct spi_message *message) -{ - struct spi_controller *ctlr = spi->controller; - int ret; - unsigned long flags; - - ret = __spi_validate(spi, message); - if (ret != 0) - return ret; - - spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); - - ret = __spi_async(spi, message); - - spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); - - return ret; - -} - static void __spi_transfer_message_noqueue(struct spi_controller *ctlr, struct spi_message *msg) { bool was_busy; @@ -4376,6 +4325,7 @@ static void spi_complete(void *arg) static int __spi_sync(struct spi_device *spi, struct spi_message *message) { DECLARE_COMPLETION_ONSTACK(done); + unsigned long flags; int status; struct spi_controller *ctlr = spi->controller; @@ -4419,7 +4369,11 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) */ message->complete = spi_complete; message->context = &done; - status = spi_async_locked(spi, message); + + spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); + status = __spi_async(spi, message); + spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + if (status == 0) { wait_for_completion(&done); status = message->status; From 8613dda6af8ee1e8675a37c86bf8d4661d24bf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahelenia=20Ziemia=C5=84ska?= Date: Sun, 28 Jan 2024 06:53:19 +0100 Subject: [PATCH 012/122] spi: Kconfig: cap[c]ability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ahelenia Ziemiańska Link: https://msgid.link/r/lq6gstev3sd7i4iw2btiq3gg7lhsraj5w74fkbp6lpbl6nkyff@tarta.nabijaczleweli.xyz Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ddae0fde798e..bc7021da2fe9 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -694,7 +694,7 @@ config SPI_MTK_SNFI This enables support for SPI-NAND mode on the MediaTek NAND Flash Interface found on MediaTek ARM SoCs. This controller is implemented as a SPI-MEM controller with pipelined ECC - capcability. + capability. config SPI_WPCM_FIU tristate "Nuvoton WPCM450 Flash Interface Unit" From e6c5812dc4d0b3e890608cb9c98597d1bed7e937 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 31 Jan 2024 11:07:27 -0600 Subject: [PATCH 013/122] spi: reorder spi_message struct member doc comments The members of `struct spi_message` were reordered in commit ae2ade4ba581 ("spi: Reorder fields in 'struct spi_message'") but the documentation comments were not updated to match. This commit updates the comments to match the new order. Signed-off-by: David Lechner Link: https://msgid.link/r/20240131170732.1665105-1-dlechner@baylibre.com Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index f306aececeaf..29c3e4dd5d93 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1113,16 +1113,16 @@ struct spi_transfer { * @spi: SPI device to which the transaction is queued * @is_dma_mapped: if true, the caller provided both DMA and CPU virtual * addresses for each transfer buffer + * @prepared: spi_prepare_message was called for the this message + * @status: zero for success, else negative errno * @complete: called to report transaction completions * @context: the argument to complete() when it's called * @frame_length: the total number of bytes in the message * @actual_length: the total number of bytes that were transferred in all * successful segments - * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message * @resources: for resource management when the SPI message is processed - * @prepared: spi_prepare_message was called for the this message * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" From 1e942b5bb18e8a9709a5cb5293b15dd54ed79f98 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 2 Feb 2024 10:34:30 +0000 Subject: [PATCH 014/122] spi: cs42l43: Clean up of firmware node As we get a child node in the OF case, we should also clean up the reference, add code to do so. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Charles Keepax Link: https://msgid.link/r/20240202103430.951598-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/spi/spi-cs42l43.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c index b24190526ce9..d45d9e2e1611 100644 --- a/drivers/spi/spi-cs42l43.c +++ b/drivers/spi/spi-cs42l43.c @@ -202,6 +202,11 @@ static size_t cs42l43_spi_max_length(struct spi_device *spi) return CS42L43_SPI_MAX_LENGTH; } +static void cs42l43_release_of_node(void *data) +{ + fwnode_handle_put(data); +} + static int cs42l43_spi_probe(struct platform_device *pdev) { struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); @@ -228,12 +233,6 @@ static int cs42l43_spi_probe(struct platform_device *pdev) priv->ctlr->transfer_one = cs42l43_transfer_one; priv->ctlr->set_cs = cs42l43_set_cs; priv->ctlr->max_transfer_size = cs42l43_spi_max_length; - - if (is_of_node(fwnode)) - fwnode = fwnode_get_named_child_node(fwnode, "spi"); - - device_set_node(&priv->ctlr->dev, fwnode); - priv->ctlr->mode_bits = SPI_3WIRE | SPI_MODE_X_MASK; priv->ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; priv->ctlr->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | @@ -257,6 +256,17 @@ static int cs42l43_spi_probe(struct platform_device *pdev) regmap_write(priv->regmap, CS42L43_SPI_CONFIG3, 0); regmap_write(priv->regmap, CS42L43_SPI_CONFIG4, CS42L43_SPI_STALL_ENA_MASK); + if (is_of_node(fwnode)) { + fwnode = fwnode_get_named_child_node(fwnode, "spi"); + ret = devm_add_action(priv->dev, cs42l43_release_of_node, fwnode); + if (ret) { + fwnode_handle_put(fwnode); + return ret; + } + } + + device_set_node(&priv->ctlr->dev, fwnode); + ret = devm_spi_register_controller(priv->dev, priv->ctlr); if (ret) { dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret); From f156743c526281ddcc19511e9073f8c987506913 Mon Sep 17 00:00:00 2001 From: "andy.shevchenko@gmail.com" Date: Sun, 4 Feb 2024 22:29:18 +0200 Subject: [PATCH 015/122] spi: fsl-dspi: Preserve error code returned by dmaengine_slave_config() dmaengine_slave_config() may return different error codes based on the circumstances. Preserve it instead of shadowing to -EINVAL. Suggested-by: Vladimir Oltean Signed-off-by: Andy Shevchenko Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20240204203127.1186621-2-andy.shevchenko@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c9eae046f66c..0b5ea7a7da71 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -542,7 +542,6 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) ret = dmaengine_slave_config(dma->chan_rx, &cfg); if (ret) { dev_err(dev, "can't configure rx dma channel\n"); - ret = -EINVAL; goto err_slave_config; } @@ -550,7 +549,6 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) ret = dmaengine_slave_config(dma->chan_tx, &cfg); if (ret) { dev_err(dev, "can't configure tx dma channel\n"); - ret = -EINVAL; goto err_slave_config; } From 51b8e79c45d5a42891c6196dcd3f73cbb599940a Mon Sep 17 00:00:00 2001 From: "andy.shevchenko@gmail.com" Date: Sun, 4 Feb 2024 22:29:19 +0200 Subject: [PATCH 016/122] spi: fsl-dspi: Unify error messaging in dspi_request_dma() Use dev_err_probe() for all messages in dspi_request_dma() for the sake of making them uniform. While at it, fix indentation issue reported by Vladimir Oltean. Signed-off-by: Andy Shevchenko Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20240204203127.1186621-3-andy.shevchenko@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 0b5ea7a7da71..38defdcf9370 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -502,15 +502,12 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) return -ENOMEM; dma->chan_rx = dma_request_chan(dev, "rx"); - if (IS_ERR(dma->chan_rx)) { - return dev_err_probe(dev, PTR_ERR(dma->chan_rx), - "rx dma channel not available\n"); - } + if (IS_ERR(dma->chan_rx)) + return dev_err_probe(dev, PTR_ERR(dma->chan_rx), "rx dma channel not available\n"); dma->chan_tx = dma_request_chan(dev, "tx"); if (IS_ERR(dma->chan_tx)) { - ret = PTR_ERR(dma->chan_tx); - dev_err_probe(dev, ret, "tx dma channel not available\n"); + ret = dev_err_probe(dev, PTR_ERR(dma->chan_tx), "tx dma channel not available\n"); goto err_tx_channel; } @@ -541,14 +538,14 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) cfg.direction = DMA_DEV_TO_MEM; ret = dmaengine_slave_config(dma->chan_rx, &cfg); if (ret) { - dev_err(dev, "can't configure rx dma channel\n"); + dev_err_probe(dev, ret, "can't configure rx dma channel\n"); goto err_slave_config; } cfg.direction = DMA_MEM_TO_DEV; ret = dmaengine_slave_config(dma->chan_tx, &cfg); if (ret) { - dev_err(dev, "can't configure tx dma channel\n"); + dev_err_probe(dev, ret, "can't configure tx dma channel\n"); goto err_slave_config; } From c8bec3355f08ddb887d5c13b7095dfa79e6db108 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 26 Jan 2024 15:23:57 -0600 Subject: [PATCH 017/122] spi: move split xfers for CS_WORD emulation This moves splitting transfers for CS_WORD software emulation to the same place where we split transfers for controller-specific reasons. This fixes a few subtle bugs. The calculation for maxsize was wrong for bit sizes between 17 and 24. This is fixed by making use of spi_split_transfers_maxwords() which already has the correct calculation. Also, since this indirectly calls spi_res_alloc(), to avoid leaking resources, spi_finalize_current_message() would need to be called on all error paths in __spi_validate() and callers of __spi_validate() would need to do the same. This is fixed by moving the call to __spi_pump_transfer_message() where it is already splitting transfers for other reasons and correctly releases resources in the subsequent error paths. Fixes: cbaa62e0094a ("spi: add software implementation for SPI_CS_WORD") Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240126212358.3916280-2-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 63 +++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6610aeced765..517558e01559 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1743,13 +1743,37 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, trace_spi_message_start(msg); - ret = spi_split_transfers_maxsize(ctlr, msg, - spi_max_transfer_size(msg->spi), - GFP_KERNEL | GFP_DMA); - if (ret) { - msg->status = ret; - spi_finalize_current_message(ctlr); - return ret; + /* + * If an SPI controller does not support toggling the CS line on each + * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO + * for the CS line, we can emulate the CS-per-word hardware function by + * splitting transfers into one-word transfers and ensuring that + * cs_change is set for each transfer. + */ + if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || + spi_is_csgpiod(msg->spi))) { + ret = spi_split_transfers_maxwords(ctlr, msg, 1, GFP_KERNEL); + if (ret) { + msg->status = ret; + spi_finalize_current_message(ctlr); + return ret; + } + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* Don't change cs_change on the last entry in the list */ + if (list_is_last(&xfer->transfer_list, &msg->transfers)) + break; + xfer->cs_change = 1; + } + } else { + ret = spi_split_transfers_maxsize(ctlr, msg, + spi_max_transfer_size(msg->spi), + GFP_KERNEL | GFP_DMA); + if (ret) { + msg->status = ret; + spi_finalize_current_message(ctlr); + return ret; + } } if (ctlr->prepare_message) { @@ -4061,31 +4085,6 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) message->spi = spi; - /* - * If an SPI controller does not support toggling the CS line on each - * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO - * for the CS line, we can emulate the CS-per-word hardware function by - * splitting transfers into one-word transfers and ensuring that - * cs_change is set for each transfer. - */ - if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || - spi_is_csgpiod(spi))) { - size_t maxsize = BITS_TO_BYTES(spi->bits_per_word); - int ret; - - ret = spi_split_transfers_maxsize(ctlr, message, maxsize, - GFP_KERNEL); - if (ret) - return ret; - - list_for_each_entry(xfer, &message->transfers, transfer_list) { - /* Don't change cs_change on the last entry in the list */ - if (list_is_last(&xfer->transfer_list, &message->transfers)) - break; - xfer->cs_change = 1; - } - } - /* * Half-duplex links include original MicroWire, and ones with * only one data pin like SPI_3WIRE (switches direction) or where From 2733092baa3e8a1f05fd16088808be17c98990b4 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 26 Jan 2024 16:00:23 -0600 Subject: [PATCH 018/122] spi: bcm2835: implement ctlr->max_transfer_size The core SPI code will handle splitting transfers if needed as long as ctlr->max_transfer_size is implemented. It does this in __spi_pump_transfer_message() immediately before calling ctlr->prepare_message. So effectively, this change does not alter the behavior of the driver. Also, several peripheral drivers make use of spi_max_transfer_size(), so this should improve compatibility with those drivers. Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240126220024.3926403-2-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index e709887eb2a9..e1b9b1235787 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1117,19 +1117,6 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, struct spi_device *spi = msg->spi; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct bcm2835_spidev *target = spi_get_ctldata(spi); - int ret; - - if (ctlr->can_dma) { - /* - * DMA transfers are limited to 16 bit (0 to 65535 bytes) by - * the SPI HW due to DLEN. Split up transfers (32-bit FIFO - * aligned) if the limit is exceeded. - */ - ret = spi_split_transfers_maxsize(ctlr, msg, 65532, - GFP_KERNEL | GFP_DMA); - if (ret) - return ret; - } /* * Set up clock polarity before spi_transfer_one_message() asserts @@ -1219,6 +1206,19 @@ static int bcm2835_spi_setup_dma(struct spi_controller *ctlr, return 0; } +static size_t bcm2835_spi_max_transfer_size(struct spi_device *spi) +{ + /* + * DMA transfers are limited to 16 bit (0 to 65535 bytes) by + * the SPI HW due to DLEN. Split up transfers (32-bit FIFO + * aligned) if the limit is exceeded. + */ + if (spi->controller->can_dma) + return 65532; + + return SIZE_MAX; +} + static int bcm2835_spi_setup(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; @@ -1348,6 +1348,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ctlr->mode_bits = BCM2835_SPI_MODE_BITS; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); ctlr->num_chipselect = 3; + ctlr->max_transfer_size = bcm2835_spi_max_transfer_size; ctlr->setup = bcm2835_spi_setup; ctlr->cleanup = bcm2835_spi_cleanup; ctlr->transfer_one = bcm2835_spi_transfer_one; From 88c2b56c2690061121cad03f0f551db465287575 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 2 Feb 2024 15:31:32 -0600 Subject: [PATCH 019/122] spi: axi-spi-engine: use common AXI macros This avoid duplicating the same macros in multiple drivers by reusing the common AXI macros for the version register. Signed-off-by: David Lechner Reviewed-by: Nuno Sa Link: https://lore.kernel.org/r/20240202213132.3863124-2-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 9ace259d2d29..6b0c72bf3395 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -15,12 +16,6 @@ #include #include -#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) -#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) -#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) - -#define SPI_ENGINE_REG_VERSION 0x00 - #define SPI_ENGINE_REG_RESET 0x40 #define SPI_ENGINE_REG_INT_ENABLE 0x80 @@ -661,12 +656,12 @@ static int spi_engine_probe(struct platform_device *pdev) if (IS_ERR(spi_engine->base)) return PTR_ERR(spi_engine->base); - version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION); - if (SPI_ENGINE_VERSION_MAJOR(version) != 1) { + version = readl(spi_engine->base + ADI_AXI_REG_VERSION); + if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) { dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n", - SPI_ENGINE_VERSION_MAJOR(version), - SPI_ENGINE_VERSION_MINOR(version), - SPI_ENGINE_VERSION_PATCH(version)); + ADI_AXI_PCORE_VER_MAJOR(version), + ADI_AXI_PCORE_VER_MINOR(version), + ADI_AXI_PCORE_VER_PATCH(version)); return -ENODEV; } From e58db3bcd93b9e0bf5068a29f7e1a97c29926830 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 1 Feb 2024 14:16:37 +0200 Subject: [PATCH 020/122] spi: intel: Add default partition and name to the second chip This should make it easier to identify the second chip and also allows using "mtdparts=" and the like with this chip too. Signed-off-by: Mika Westerberg Link: https://lore.kernel.org/r/20240201121638.207632-1-mika.westerberg@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-intel.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 3654ae35d2db..467d39bf00b4 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -1346,6 +1346,7 @@ static int intel_spi_read_desc(struct intel_spi *ispi) static int intel_spi_populate_chip(struct intel_spi *ispi) { struct flash_platform_data *pdata; + struct mtd_partition *parts; struct spi_board_info chip; int ret; @@ -1376,7 +1377,23 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) if (ispi->host->num_chipselect < 2) return 0; - chip.platform_data = NULL; + pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->name = devm_kasprintf(ispi->dev, GFP_KERNEL, "%s-chip1", + dev_name(ispi->dev)); + pdata->nr_parts = 1; + parts = devm_kcalloc(ispi->dev, pdata->nr_parts, sizeof(*parts), + GFP_KERNEL); + if (!parts) + return -ENOMEM; + + parts[0].size = MTDPART_SIZ_FULL; + parts[0].name = "BIOS1"; + pdata->parts = parts; + + chip.platform_data = pdata; chip.chip_select = 1; if (!spi_new_device(ispi->host, &chip)) From 83c9c7ec8b914faf91567132ab197c54253c277f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 1 Feb 2024 14:16:38 +0200 Subject: [PATCH 021/122] spi: intel: Keep the BIOS partition inside the first chip If there are two flash chips connected flash regions can refer to the second chip too. In this case we may see the following warning: mtd: partition "BIOS" extends beyond the end of device "0000:00:1f.5" -- size truncated to 0x400000 For this reason, check the BIOS partition size against the chip size and make sure it stays within the that. Signed-off-by: Mika Westerberg Link: https://lore.kernel.org/r/20240201121638.207632-2-mika.westerberg@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-intel.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 467d39bf00b4..3e5dcf2b3c8a 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -1254,6 +1254,13 @@ static void intel_spi_fill_partition(struct intel_spi *ispi, if (end > part->size) part->size = end; } + + /* + * Regions can refer to the second chip too so in this case we + * just make the BIOS partition to occupy the whole chip. + */ + if (ispi->chip0_size && part->size > ispi->chip0_size) + part->size = MTDPART_SIZ_FULL; } static int intel_spi_read_desc(struct intel_spi *ispi) @@ -1350,6 +1357,10 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) struct spi_board_info chip; int ret; + ret = intel_spi_read_desc(ispi); + if (ret) + return ret; + pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; @@ -1369,10 +1380,6 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) if (!spi_new_device(ispi->host, &chip)) return -ENODEV; - ret = intel_spi_read_desc(ispi); - if (ret) - return ret; - /* Add the second chip if present */ if (ispi->host->num_chipselect < 2) return 0; From 5c018e378f916b56503bba65cbdec66ad16f20b7 Mon Sep 17 00:00:00 2001 From: Luis de Arquer Date: Fri, 26 Jan 2024 20:46:22 +0100 Subject: [PATCH 022/122] spi: spi-rockchip: Fix out of bounds array access Since spi-rockchip enables use_gpio_descriptors and the SPI_CONTROLLER_GPIO_SS flag, the spi subsytem may call set_cs() for spi devices with indexes above ROCKCHIP_SPI_MAX_CS_NUM Remove array cs_asserted[] which held a shadow copy of the state of the chip select lines with the only purpose of optimizing out rewriting a chip select line to the current state (no-op) This case is already handled by spi.c Signed-off-by: Luis de Arquer Link: https://lore.kernel.org/r/d0a0c4b94f933f7f43973c34765214303ee82b77.camel@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 4b9669da2cf3..2fb2d65bd5f4 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -192,8 +192,6 @@ struct rockchip_spi { u8 n_bytes; u8 rsd; - bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; - bool target_abort; bool cs_inactive; /* spi target tansmition stop when cs inactive */ bool cs_high_supported; /* native CS supports active-high polarity */ @@ -245,10 +243,6 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable; - /* Return immediately for no-op */ - if (cs_asserted == rs->cs_asserted[spi_get_chipselect(spi, 0)]) - return; - if (cs_asserted) { /* Keep things powered as long as CS is asserted */ pm_runtime_get_sync(rs->dev); @@ -268,8 +262,6 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) /* Drop reference from when we first asserted CS */ pm_runtime_put(rs->dev); } - - rs->cs_asserted[spi_get_chipselect(spi, 0)] = cs_asserted; } static void rockchip_spi_handle_err(struct spi_controller *ctlr, From 07d6749317bf8cc416fb7eb8f997a884bd610f8d Mon Sep 17 00:00:00 2001 From: Luis de Arquer Date: Fri, 26 Jan 2024 20:46:44 +0100 Subject: [PATCH 023/122] spi: spi-rockchip: Fix max_native_cs Signed-off-by: Luis de Arquer Link: https://lore.kernel.org/r/4d18808e85b85077761c5655083f20ebfd7d3770.camel@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 2fb2d65bd5f4..e1ecd96c7858 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -160,8 +160,7 @@ */ #define ROCKCHIP_SPI_MAX_TRANLEN 0xffff -/* 2 for native cs, 2 for cs-gpio */ -#define ROCKCHIP_SPI_MAX_CS_NUM 4 +#define ROCKCHIP_SPI_MAX_NATIVE_CS_NUM 2 #define ROCKCHIP_SPI_VER2_TYPE1 0x05EC0002 #define ROCKCHIP_SPI_VER2_TYPE2 0x00110002 @@ -839,7 +838,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) ctlr->target_abort = rockchip_spi_target_abort; } else { ctlr->flags = SPI_CONTROLLER_GPIO_SS; - ctlr->max_native_cs = ROCKCHIP_SPI_MAX_CS_NUM; + ctlr->max_native_cs = ROCKCHIP_SPI_MAX_NATIVE_CS_NUM; /* * rk spi0 has two native cs, spi1..5 one cs only * if num-cs is missing in the dts, default to 1 From c0c0293cf7a0f21ef461956d44e4add718574f3f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 6 Feb 2024 14:06:46 -0600 Subject: [PATCH 024/122] spi: drop gpf arg from __spi_split_transfer_maxsize() The __spi_split_transfer_maxsize() function has a gpf argument to allow callers to specify the type of memory allocation that needs to be used. However, this function only allocates struct spi_transfer and is not intended to be used from atomic contexts so this type should always be GFP_KERNEL, so we can just drop the argument. Some callers of these functions also passed GFP_DMA, but since only struct spi_transfer is allocated and not any tx/rx buffers, this is not actually necessary and is removed in this commit. Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240206200648.1782234-1-dlechner@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 4 +--- drivers/spi/spi.c | 22 ++++++++-------------- include/linux/spi/spi.h | 6 ++---- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index e61302ef3c21..c32e57bb38bd 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1170,9 +1170,7 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl, if (spi->cfg->set_number_of_data) { int ret; - ret = spi_split_transfers_maxwords(ctrl, msg, - spi->t_size_max, - GFP_KERNEL | GFP_DMA); + ret = spi_split_transfers_maxwords(ctrl, msg, spi->t_size_max); if (ret) return ret; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 517558e01559..3270a1337a5b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1752,7 +1752,7 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, */ if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || spi_is_csgpiod(msg->spi))) { - ret = spi_split_transfers_maxwords(ctlr, msg, 1, GFP_KERNEL); + ret = spi_split_transfers_maxwords(ctlr, msg, 1); if (ret) { msg->status = ret; spi_finalize_current_message(ctlr); @@ -1767,8 +1767,7 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, } } else { ret = spi_split_transfers_maxsize(ctlr, msg, - spi_max_transfer_size(msg->spi), - GFP_KERNEL | GFP_DMA); + spi_max_transfer_size(msg->spi)); if (ret) { msg->status = ret; spi_finalize_current_message(ctlr); @@ -3707,8 +3706,7 @@ static struct spi_replaced_transfers *spi_replace_transfers( static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, struct spi_message *msg, struct spi_transfer **xferp, - size_t maxsize, - gfp_t gfp) + size_t maxsize) { struct spi_transfer *xfer = *xferp, *xfers; struct spi_replaced_transfers *srt; @@ -3719,7 +3717,7 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, count = DIV_ROUND_UP(xfer->len, maxsize); /* Create replacement */ - srt = spi_replace_transfers(msg, xfer, 1, count, NULL, 0, gfp); + srt = spi_replace_transfers(msg, xfer, 1, count, NULL, 0, GFP_KERNEL); if (IS_ERR(srt)) return PTR_ERR(srt); xfers = srt->inserted_transfers; @@ -3779,14 +3777,12 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, * @ctlr: the @spi_controller for this transfer * @msg: the @spi_message to transform * @maxsize: the maximum when to apply this - * @gfp: GFP allocation flags * * Return: status of transformation */ int spi_split_transfers_maxsize(struct spi_controller *ctlr, struct spi_message *msg, - size_t maxsize, - gfp_t gfp) + size_t maxsize) { struct spi_transfer *xfer; int ret; @@ -3801,7 +3797,7 @@ int spi_split_transfers_maxsize(struct spi_controller *ctlr, list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (xfer->len > maxsize) { ret = __spi_split_transfer_maxsize(ctlr, msg, &xfer, - maxsize, gfp); + maxsize); if (ret) return ret; } @@ -3819,14 +3815,12 @@ EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize); * @ctlr: the @spi_controller for this transfer * @msg: the @spi_message to transform * @maxwords: the number of words to limit each transfer to - * @gfp: GFP allocation flags * * Return: status of transformation */ int spi_split_transfers_maxwords(struct spi_controller *ctlr, struct spi_message *msg, - size_t maxwords, - gfp_t gfp) + size_t maxwords) { struct spi_transfer *xfer; @@ -3844,7 +3838,7 @@ int spi_split_transfers_maxwords(struct spi_controller *ctlr, maxsize = maxwords * roundup_pow_of_two(BITS_TO_BYTES(xfer->bits_per_word)); if (xfer->len > maxsize) { ret = __spi_split_transfer_maxsize(ctlr, msg, &xfer, - maxsize, gfp); + maxsize); if (ret) return ret; } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 29c3e4dd5d93..9339c8ed1f8f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1365,12 +1365,10 @@ struct spi_replaced_transfers { extern int spi_split_transfers_maxsize(struct spi_controller *ctlr, struct spi_message *msg, - size_t maxsize, - gfp_t gfp); + size_t maxsize); extern int spi_split_transfers_maxwords(struct spi_controller *ctlr, struct spi_message *msg, - size_t maxwords, - gfp_t gfp); + size_t maxwords); /*---------------------------------------------------------------------------*/ From 531860e12da76a444e0ecfd37a9d786e7986957a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Feb 2024 08:51:24 -0600 Subject: [PATCH 025/122] spi: axi-spi-engine: remove use of ida for sync id Profiling has shown that ida_alloc_range() accounts for about 10% of the time spent in spi_sync() when using the AXI SPI Engine controller. This call is used to create a unique id for each SPI message to match to an IRQ when the message is complete. Since the core SPI code serializes messages in a message queue, we can only have one message in flight at a time, namely host->cur_msg. This means that we can use a fixed value instead of a unique id for each message since there can never be more than one message pending at a time. This patch removes the use of ida for the sync id and replaces it with a constant value. This simplifies the driver and improves performance. Reviewed-by: Nuno Sa Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240207-axi-spi-engine-round-2-1-v2-1-40c0b4e85352@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 6b0c72bf3395..606389566129 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -57,6 +56,9 @@ #define SPI_ENGINE_TRANSFER_WRITE 0x1 #define SPI_ENGINE_TRANSFER_READ 0x2 +/* Arbitrary sync ID for use by host->cur_msg */ +#define AXI_SPI_ENGINE_CUR_MSG_SYNC_ID 0x1 + #define SPI_ENGINE_CMD(inst, arg1, arg2) \ (((inst) << 12) | ((arg1) << 8) | (arg2)) @@ -98,8 +100,6 @@ struct spi_engine_message_state { unsigned int rx_length; /** @rx_buf: Bytes not yet written to the RX FIFO. */ uint8_t *rx_buf; - /** @sync_id: ID to correlate SYNC interrupts with this message. */ - u8 sync_id; }; struct spi_engine { @@ -109,7 +109,6 @@ struct spi_engine { spinlock_t lock; void __iomem *base; - struct ida sync_ida; struct timer_list watchdog_timer; struct spi_controller *controller; @@ -483,9 +482,7 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) } if (pending & SPI_ENGINE_INT_SYNC && msg) { - struct spi_engine_message_state *st = msg->state; - - if (completed_id == st->sync_id) { + if (completed_id == AXI_SPI_ENGINE_CUR_MSG_SYNC_ID) { if (timer_delete_sync(&spi_engine->watchdog_timer)) { msg->status = 0; msg->actual_length = msg->frame_length; @@ -510,10 +507,8 @@ static int spi_engine_prepare_message(struct spi_controller *host, struct spi_message *msg) { struct spi_engine_program p_dry, *p; - struct spi_engine *spi_engine = spi_controller_get_devdata(host); struct spi_engine_message_state *st; size_t size; - int ret; st = kzalloc(sizeof(*st), GFP_KERNEL); if (!st) @@ -531,18 +526,10 @@ static int spi_engine_prepare_message(struct spi_controller *host, return -ENOMEM; } - ret = ida_alloc_range(&spi_engine->sync_ida, 0, U8_MAX, GFP_KERNEL); - if (ret < 0) { - kfree(p); - kfree(st); - return ret; - } - - st->sync_id = ret; - spi_engine_compile_message(msg, false, p); - spi_engine_program_add_cmd(p, false, SPI_ENGINE_CMD_SYNC(st->sync_id)); + spi_engine_program_add_cmd(p, false, SPI_ENGINE_CMD_SYNC( + AXI_SPI_ENGINE_CUR_MSG_SYNC_ID)); st->p = p; st->cmd_buf = p->instructions; @@ -555,10 +542,8 @@ static int spi_engine_prepare_message(struct spi_controller *host, static int spi_engine_unprepare_message(struct spi_controller *host, struct spi_message *msg) { - struct spi_engine *spi_engine = spi_controller_get_devdata(host); struct spi_engine_message_state *st = msg->state; - ida_free(&spi_engine->sync_ida, st->sync_id); kfree(st->p); kfree(st); @@ -640,7 +625,6 @@ static int spi_engine_probe(struct platform_device *pdev) spi_engine = spi_controller_get_devdata(host); spin_lock_init(&spi_engine->lock); - ida_init(&spi_engine->sync_ida); timer_setup(&spi_engine->watchdog_timer, spi_engine_timeout, TIMER_IRQSAFE); spi_engine->controller = host; From abb4b46c43689dd1f4d80c41e49127ca0ede75b3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Feb 2024 08:51:25 -0600 Subject: [PATCH 026/122] spi: axi-spi-engine: move msg finalization out of irq handler As a general principal, it is best to do as little as possible in an interrupt handler. This patch reworks the AXI SPI Engine driver to move timer_delete_sync() and spi_finalize_current_message() out of the interrupt handler. Instead, spi_finalize_current_message() is moved to the transfer_one_message function (similar to nearly all other SPI controllers). A completion is now used to wait for the sync interrupt that indicates that the message is complete. The watchdog timer is no longer needed since we can use the wait_for_completion_timeout() function to wait for the message to complete with the same effect. As a bonus, these changes also improve throughput of the SPI controller. For example, this was tested on a ZynqMP with a 80MHz SCLK reading 4 byte samples from an ADC. The max measured throughput increased from 26k to 28k samples per second. Reviewed-by: Nuno Sa Signed-off-by: David Lechner Link: https://lore.kernel.org/r/20240207-axi-spi-engine-round-2-1-v2-2-40c0b4e85352@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 606389566129..ca66d202f0e2 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #define SPI_ENGINE_REG_RESET 0x40 @@ -109,9 +109,7 @@ struct spi_engine { spinlock_t lock; void __iomem *base; - struct timer_list watchdog_timer; - struct spi_controller *controller; - + struct completion msg_complete; unsigned int int_enable; }; @@ -483,11 +481,9 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) if (pending & SPI_ENGINE_INT_SYNC && msg) { if (completed_id == AXI_SPI_ENGINE_CUR_MSG_SYNC_ID) { - if (timer_delete_sync(&spi_engine->watchdog_timer)) { - msg->status = 0; - msg->actual_length = msg->frame_length; - spi_finalize_current_message(host); - } + msg->status = 0; + msg->actual_length = msg->frame_length; + complete(&spi_engine->msg_complete); disable_int |= SPI_ENGINE_INT_SYNC; } } @@ -558,7 +554,7 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, unsigned int int_enable = 0; unsigned long flags; - mod_timer(&spi_engine->watchdog_timer, jiffies + msecs_to_jiffies(5000)); + reinit_completion(&spi_engine->msg_complete); spin_lock_irqsave(&spi_engine->lock, flags); @@ -580,21 +576,16 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, spi_engine->int_enable = int_enable; spin_unlock_irqrestore(&spi_engine->lock, flags); - return 0; -} + if (!wait_for_completion_timeout(&spi_engine->msg_complete, + msecs_to_jiffies(5000))) { + dev_err(&host->dev, + "Timeout occurred while waiting for transfer to complete. Hardware is probably broken.\n"); + msg->status = -ETIMEDOUT; + } -static void spi_engine_timeout(struct timer_list *timer) -{ - struct spi_engine *spi_engine = from_timer(spi_engine, timer, watchdog_timer); - struct spi_controller *host = spi_engine->controller; - - if (WARN_ON(!host->cur_msg)) - return; - - dev_err(&host->dev, - "Timeout occurred while waiting for transfer to complete. Hardware is probably broken.\n"); - host->cur_msg->status = -ETIMEDOUT; spi_finalize_current_message(host); + + return msg->status; } static void spi_engine_release_hw(void *p) @@ -625,8 +616,7 @@ static int spi_engine_probe(struct platform_device *pdev) spi_engine = spi_controller_get_devdata(host); spin_lock_init(&spi_engine->lock); - timer_setup(&spi_engine->watchdog_timer, spi_engine_timeout, TIMER_IRQSAFE); - spi_engine->controller = host; + init_completion(&spi_engine->msg_complete); spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); if (IS_ERR(spi_engine->clk)) From 227ab73b89d66e3064b3c2bcb5fe382b1815763d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:15 +0100 Subject: [PATCH 027/122] fpga: ice40-spi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Xu Yilun Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/6a3ddedc955cf55dddbc68ccf5ff5e46af5e8b6f.1707324793.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/fpga/ice40-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 7cbb3558b844..c0028ae4c5b7 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c @@ -66,7 +66,7 @@ static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, } /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ - spi_bus_lock(dev->master); + spi_bus_lock(dev->controller); gpiod_set_value(priv->reset, 1); @@ -94,7 +94,7 @@ static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, ret = spi_sync_locked(dev, &message); fail: - spi_bus_unlock(dev->master); + spi_bus_unlock(dev->controller); return ret; } From 167b78446706bb4d19f7dd93ca320aed25ae1bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:16 +0100 Subject: [PATCH 028/122] ieee802154: ca8210: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Simon Horman Acked-by: Stefan Schmidt Acked-by: Miquel Raynal Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/dec96b1d3cf43bb442128957b27d02007ffeb68d.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/net/ieee802154/ca8210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 4ec0dab38872..f732c150462b 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2956,7 +2956,7 @@ static int ca8210_test_interface_init(struct ca8210_priv *priv) node_name, sizeof(node_name), "ca8210@%d_%d", - priv->spi->master->bus_num, + priv->spi->controller->bus_num, spi_get_chipselect(priv->spi, 0) ); From 2780e7b716a605781dbee753ef4983d775a65427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:17 +0100 Subject: [PATCH 029/122] iio: adc: ad_sigma_delta: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Acked-by: Nuno Sa Link: https://lore.kernel.org/r/de866d09c80c89816df62602ba4ba8ba30e9971f.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/iio/adc/ad_sigma_delta.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 7e2192870743..55442eddf57c 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -212,7 +212,7 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, if (ret) return ret; - spi_bus_lock(sigma_delta->spi->master); + spi_bus_lock(sigma_delta->spi->controller); sigma_delta->bus_locked = true; sigma_delta->keep_cs_asserted = true; reinit_completion(&sigma_delta->completion); @@ -235,7 +235,7 @@ out: sigma_delta->keep_cs_asserted = false; ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); sigma_delta->bus_locked = false; - spi_bus_unlock(sigma_delta->spi->master); + spi_bus_unlock(sigma_delta->spi->controller); return ret; } @@ -287,7 +287,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, ad_sigma_delta_set_channel(sigma_delta, chan->address); - spi_bus_lock(sigma_delta->spi->master); + spi_bus_lock(sigma_delta->spi->controller); sigma_delta->bus_locked = true; sigma_delta->keep_cs_asserted = true; reinit_completion(&sigma_delta->completion); @@ -322,7 +322,7 @@ out: sigma_delta->keep_cs_asserted = false; ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); sigma_delta->bus_locked = false; - spi_bus_unlock(sigma_delta->spi->master); + spi_bus_unlock(sigma_delta->spi->controller); iio_device_release_direct_mode(indio_dev); if (ret) @@ -387,7 +387,7 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) sigma_delta->samples_buf = samples_buf; - spi_bus_lock(sigma_delta->spi->master); + spi_bus_lock(sigma_delta->spi->controller); sigma_delta->bus_locked = true; sigma_delta->keep_cs_asserted = true; @@ -401,7 +401,7 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) return 0; err_unlock: - spi_bus_unlock(sigma_delta->spi->master); + spi_bus_unlock(sigma_delta->spi->controller); return ret; } @@ -426,7 +426,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev) ad_sigma_delta_disable_all(sigma_delta); sigma_delta->bus_locked = false; - return spi_bus_unlock(sigma_delta->spi->master); + return spi_bus_unlock(sigma_delta->spi->controller); } static irqreturn_t ad_sd_trigger_handler(int irq, void *p) From a78acec53b8524593afeed7258a442adc3450818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:18 +0100 Subject: [PATCH 030/122] Input: pxspad - follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Dmitry Torokhov Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/820fa151077dc192391d546aec35328680803f9f.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/input/joystick/psxpad-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/joystick/psxpad-spi.c b/drivers/input/joystick/psxpad-spi.c index de734a927b4d..c47fc5f34bd0 100644 --- a/drivers/input/joystick/psxpad-spi.c +++ b/drivers/input/joystick/psxpad-spi.c @@ -342,8 +342,8 @@ static int psxpad_spi_probe(struct spi_device *spi) spi->mode = SPI_MODE_3; spi->bits_per_word = 8; /* (PlayStation 1/2 joypad might be possible works 250kHz/500kHz) */ - spi->master->min_speed_hz = 125000; - spi->master->max_speed_hz = 125000; + spi->controller->min_speed_hz = 125000; + spi->controller->max_speed_hz = 125000; spi_setup(spi); /* pad settings */ From 1245633c61baf159fcc1303d7f0855f49831b9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:19 +0100 Subject: [PATCH 031/122] Input: synaptics-rmi4 - follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Dmitry Torokhov Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/b88413456c970a97319fa7e505768bf82966541b.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/input/rmi4/rmi_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c index 07c866f42296..9d92129aa432 100644 --- a/drivers/input/rmi4/rmi_spi.c +++ b/drivers/input/rmi4/rmi_spi.c @@ -375,7 +375,7 @@ static int rmi_spi_probe(struct spi_device *spi) struct rmi_device_platform_data *spi_pdata = spi->dev.platform_data; int error; - if (spi->master->flags & SPI_CONTROLLER_HALF_DUPLEX) + if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) return -EINVAL; rmi_spi = devm_kzalloc(&spi->dev, sizeof(struct rmi_spi_xport), From 2c2f93fbfba7186cc081e23120f169eac3b5b62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:20 +0100 Subject: [PATCH 032/122] media: mgb4: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Martin Tůma Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/ccad7ad4176265bf90af92add18a0242652f5a84.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/media/pci/mgb4/mgb4_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/pci/mgb4/mgb4_core.c b/drivers/media/pci/mgb4/mgb4_core.c index 5bfb8a06202e..9bcf10a77fd3 100644 --- a/drivers/media/pci/mgb4/mgb4_core.c +++ b/drivers/media/pci/mgb4/mgb4_core.c @@ -144,7 +144,7 @@ static int match_spi_adap(struct device *dev, void *data) return to_spi_device(dev) ? 1 : 0; } -static struct spi_master *get_spi_adap(struct platform_device *pdev) +static struct spi_controller *get_spi_adap(struct platform_device *pdev) { struct device *dev; @@ -152,7 +152,7 @@ static struct spi_master *get_spi_adap(struct platform_device *pdev) dev = device_find_child(&pdev->dev, NULL, match_spi_adap); mutex_unlock(&pdev->dev.mutex); - return dev ? container_of(dev, struct spi_master, dev) : NULL; + return dev ? container_of(dev, struct spi_controller, dev) : NULL; } static int init_spi(struct mgb4_dev *mgbdev, u32 devid) @@ -179,7 +179,7 @@ static int init_spi(struct mgb4_dev *mgbdev, u32 devid) }; struct pci_dev *pdev = mgbdev->pdev; struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *ctlr; struct spi_device *spi_dev; u32 irq; int rv, id; @@ -207,8 +207,8 @@ static int init_spi(struct mgb4_dev *mgbdev, u32 devid) return PTR_ERR(mgbdev->spi_pdev); } - master = get_spi_adap(mgbdev->spi_pdev); - if (!master) { + ctlr = get_spi_adap(mgbdev->spi_pdev); + if (!ctlr) { dev_err(dev, "failed to get SPI adapter\n"); rv = -EINVAL; goto err_pdev; @@ -242,8 +242,8 @@ static int init_spi(struct mgb4_dev *mgbdev, u32 devid) spi_info.platform_data = &mgbdev->flash_data; - spi_dev = spi_new_device(master, &spi_info); - put_device(&master->dev); + spi_dev = spi_new_device(ctlr, &spi_info); + put_device(&ctlr->dev); if (!spi_dev) { dev_err(dev, "failed to create MTD device\n"); rv = -EINVAL; From cfa13a64bd631d8f04a1c385923706fcef9a63ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:21 +0100 Subject: [PATCH 033/122] media: netup_unidvb: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Mauro Carvalho Chehab Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/c37fceef8c631c5b49538f3f143573b605fc2c24.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- .../media/pci/netup_unidvb/netup_unidvb_spi.c | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c index 526042d8afae..e90aa1c1584c 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c @@ -35,7 +35,7 @@ struct netup_spi_regs { struct netup_spi { struct device *dev; - struct spi_master *master; + struct spi_controller *ctlr; struct netup_spi_regs __iomem *regs; u8 __iomem *mmio; spinlock_t lock; @@ -78,7 +78,7 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi) reg = readw(&spi->regs->control_stat); if (!(reg & NETUP_SPI_CTRL_IRQ)) { spin_unlock_irqrestore(&spi->lock, flags); - dev_dbg(&spi->master->dev, + dev_dbg(&spi->ctlr->dev, "%s(): not mine interrupt\n", __func__); return IRQ_NONE; } @@ -88,15 +88,15 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi) spi->state = SPI_STATE_DONE; wake_up(&spi->waitq); spin_unlock_irqrestore(&spi->lock, flags); - dev_dbg(&spi->master->dev, + dev_dbg(&spi->ctlr->dev, "%s(): SPI interrupt handled\n", __func__); return IRQ_HANDLED; } -static int netup_spi_transfer(struct spi_master *master, +static int netup_spi_transfer(struct spi_controller *ctlr, struct spi_message *msg) { - struct netup_spi *spi = spi_master_get_devdata(master); + struct netup_spi *spi = spi_controller_get_devdata(ctlr); struct spi_transfer *t; int result = 0; u32 tr_size; @@ -131,7 +131,7 @@ static int netup_spi_transfer(struct spi_master *master, NETUP_SPI_CTRL_START | (frag_last ? NETUP_SPI_CTRL_LAST_CS : 0), &spi->regs->control_stat); - dev_dbg(&spi->master->dev, + dev_dbg(&spi->ctlr->dev, "%s(): control_stat 0x%04x\n", __func__, readw(&spi->regs->control_stat)); wait_event_timeout(spi->waitq, @@ -144,11 +144,11 @@ static int netup_spi_transfer(struct spi_master *master, } } else { if (spi->state == SPI_STATE_START) { - dev_dbg(&spi->master->dev, + dev_dbg(&spi->ctlr->dev, "%s(): transfer timeout\n", __func__); } else { - dev_dbg(&spi->master->dev, + dev_dbg(&spi->ctlr->dev, "%s(): invalid state %d\n", __func__, spi->state); } @@ -161,7 +161,7 @@ static int netup_spi_transfer(struct spi_master *master, } done: msg->status = result; - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return result; } @@ -172,30 +172,30 @@ static int netup_spi_setup(struct spi_device *spi) int netup_spi_init(struct netup_unidvb_dev *ndev) { - struct spi_master *master; + struct spi_controller *ctlr; struct netup_spi *nspi; - master = devm_spi_alloc_master(&ndev->pci_dev->dev, - sizeof(struct netup_spi)); - if (!master) { + ctlr = devm_spi_alloc_master(&ndev->pci_dev->dev, + sizeof(struct netup_spi)); + if (!ctlr) { dev_err(&ndev->pci_dev->dev, "%s(): unable to alloc SPI master\n", __func__); return -EINVAL; } - nspi = spi_master_get_devdata(master); - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->bus_num = -1; - master->num_chipselect = 1; - master->transfer_one_message = netup_spi_transfer; - master->setup = netup_spi_setup; + nspi = spi_controller_get_devdata(ctlr); + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + ctlr->bus_num = -1; + ctlr->num_chipselect = 1; + ctlr->transfer_one_message = netup_spi_transfer; + ctlr->setup = netup_spi_setup; spin_lock_init(&nspi->lock); init_waitqueue_head(&nspi->waitq); - nspi->master = master; + nspi->ctlr = ctlr; nspi->regs = (struct netup_spi_regs __iomem *)(ndev->bmmio0 + 0x4000); writew(2, &nspi->regs->clock_divider); writew(NETUP_UNIDVB_IRQ_SPI, ndev->bmmio0 + REG_IMASK_SET); ndev->spi = nspi; - if (spi_register_master(master)) { + if (spi_register_controller(ctlr)) { ndev->spi = NULL; dev_err(&ndev->pci_dev->dev, "%s(): unable to register SPI bus\n", __func__); @@ -207,8 +207,8 @@ int netup_spi_init(struct netup_unidvb_dev *ndev) ndev->pci_bus, ndev->pci_slot, ndev->pci_func); - if (!spi_new_device(master, &netup_spi_board)) { - spi_unregister_master(master); + if (!spi_new_device(ctlr, &netup_spi_board)) { + spi_unregister_controller(ctlr); ndev->spi = NULL; dev_err(&ndev->pci_dev->dev, "%s(): unable to create SPI device\n", __func__); @@ -227,7 +227,7 @@ void netup_spi_release(struct netup_unidvb_dev *ndev) if (!spi) return; - spi_unregister_master(spi->master); + spi_unregister_controller(spi->ctlr); spin_lock_irqsave(&spi->lock, flags); reg = readw(&spi->regs->control_stat); writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat); From dd868ae646d5770f80f90dc056d06eb2e6d39c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:22 +0100 Subject: [PATCH 034/122] media: usb/msi2500: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/d4dc8acc3c4105b9093e97f6337a81d11e6d30ae.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/media/usb/msi2500/msi2500.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 9759996ee6a4..5138486abfa0 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -107,7 +107,7 @@ struct msi2500_dev { struct video_device vdev; struct v4l2_device v4l2_dev; struct v4l2_subdev *v4l2_subdev; - struct spi_master *master; + struct spi_controller *ctlr; /* videobuf2 queue and queued buffers list */ struct vb2_queue vb_queue; @@ -574,7 +574,7 @@ static void msi2500_disconnect(struct usb_interface *intf) dev->udev = NULL; v4l2_device_disconnect(&dev->v4l2_dev); video_unregister_device(&dev->vdev); - spi_unregister_master(dev->master); + spi_unregister_controller(dev->ctlr); mutex_unlock(&dev->v4l2_lock); mutex_unlock(&dev->vb_queue_lock); @@ -1136,10 +1136,10 @@ static void msi2500_video_release(struct v4l2_device *v) kfree(dev); } -static int msi2500_transfer_one_message(struct spi_master *master, +static int msi2500_transfer_one_message(struct spi_controller *ctlr, struct spi_message *m) { - struct msi2500_dev *dev = spi_master_get_devdata(master); + struct msi2500_dev *dev = spi_controller_get_devdata(ctlr); struct spi_transfer *t; int ret = 0; u32 data; @@ -1154,7 +1154,7 @@ static int msi2500_transfer_one_message(struct spi_master *master, } m->status = ret; - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return ret; } @@ -1163,7 +1163,7 @@ static int msi2500_probe(struct usb_interface *intf, { struct msi2500_dev *dev; struct v4l2_subdev *sd; - struct spi_master *master; + struct spi_controller *ctlr; int ret; static struct spi_board_info board_info = { .modalias = "msi001", @@ -1220,30 +1220,30 @@ static int msi2500_probe(struct usb_interface *intf, } /* SPI master adapter */ - master = spi_alloc_master(dev->dev, 0); - if (master == NULL) { + ctlr = spi_alloc_master(dev->dev, 0); + if (ctlr == NULL) { ret = -ENOMEM; goto err_unregister_v4l2_dev; } - dev->master = master; - master->bus_num = -1; - master->num_chipselect = 1; - master->transfer_one_message = msi2500_transfer_one_message; - spi_master_set_devdata(master, dev); - ret = spi_register_master(master); + dev->ctlr = ctlr; + ctlr->bus_num = -1; + ctlr->num_chipselect = 1; + ctlr->transfer_one_message = msi2500_transfer_one_message; + spi_controller_set_devdata(ctlr, dev); + ret = spi_register_controller(ctlr); if (ret) { - spi_master_put(master); + spi_controller_put(ctlr); goto err_unregister_v4l2_dev; } /* load v4l2 subdevice */ - sd = v4l2_spi_new_subdev(&dev->v4l2_dev, master, &board_info); + sd = v4l2_spi_new_subdev(&dev->v4l2_dev, ctlr, &board_info); dev->v4l2_subdev = sd; if (sd == NULL) { dev_err(dev->dev, "cannot get v4l2 subdevice\n"); ret = -ENODEV; - goto err_unregister_master; + goto err_unregister_controller; } /* Register controls */ @@ -1276,8 +1276,8 @@ static int msi2500_probe(struct usb_interface *intf, return 0; err_free_controls: v4l2_ctrl_handler_free(&dev->hdl); -err_unregister_master: - spi_unregister_master(dev->master); +err_unregister_controller: + spi_unregister_controller(dev->ctlr); err_unregister_v4l2_dev: v4l2_device_unregister(&dev->v4l2_dev); err_free_mem: From d920b3a672b7f79cd13b341234aebd49233f836c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:23 +0100 Subject: [PATCH 035/122] media: v4l2-subdev: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into v4l2_spi_new_subdev(). Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/b6e3a53ce75dfb8a21a5958a381070944dfa0875.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/media/v4l2-core/v4l2-spi.c | 4 ++-- include/media/v4l2-common.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-spi.c b/drivers/media/v4l2-core/v4l2-spi.c index eadecdff7349..a7092c3930d6 100644 --- a/drivers/media/v4l2-core/v4l2-spi.c +++ b/drivers/media/v4l2-core/v4l2-spi.c @@ -34,7 +34,7 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, - struct spi_master *master, + struct spi_controller *ctlr, struct spi_board_info *info) { struct v4l2_subdev *sd = NULL; @@ -45,7 +45,7 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, if (info->modalias[0]) request_module(info->modalias); - spi = spi_new_device(master, info); + spi = spi_new_device(ctlr, info); if (!spi || !spi->dev.driver) goto error; diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index acf5be24a5ca..739b0f0fc1a0 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -278,13 +278,13 @@ static inline void v4l2_i2c_subdev_unregister(struct v4l2_subdev *sd) * * * @v4l2_dev: pointer to &struct v4l2_device. - * @master: pointer to struct spi_master. + * @ctlr: pointer to struct spi_controller. * @info: pointer to struct spi_board_info. * * returns a &struct v4l2_subdev pointer. */ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, - struct spi_master *master, struct spi_board_info *info); + struct spi_controller *ctlr, struct spi_board_info *info); /** * v4l2_spi_subdev_init - Initialize a v4l2_subdev with data from an @@ -308,7 +308,7 @@ void v4l2_spi_subdev_unregister(struct v4l2_subdev *sd); static inline struct v4l2_subdev * v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, - struct spi_master *master, struct spi_board_info *info) + struct spi_controller *ctlr, struct spi_board_info *info) { return NULL; } From 26dcf09ee5d9ceba2c627ae3ba174a229f25638f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:24 +0100 Subject: [PATCH 036/122] misc: gehc-achc: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Greg Kroah-Hartman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/3c93bf41d2399d06b5a379a76c8f6e877f3560b7.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/misc/gehc-achc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/misc/gehc-achc.c b/drivers/misc/gehc-achc.c index 4c9c5394da6f..b8fca4d393c6 100644 --- a/drivers/misc/gehc-achc.c +++ b/drivers/misc/gehc-achc.c @@ -65,7 +65,7 @@ static int ezport_start_programming(struct spi_device *spi, struct gpio_desc *re struct spi_transfer release_cs = { }; int ret; - spi_bus_lock(spi->master); + spi_bus_lock(spi->controller); /* assert chip select */ spi_message_init(&msg); @@ -85,16 +85,16 @@ static int ezport_start_programming(struct spi_device *spi, struct gpio_desc *re ret = spi_sync_locked(spi, &msg); fail: - spi_bus_unlock(spi->master); + spi_bus_unlock(spi->controller); return ret; } static void ezport_stop_programming(struct spi_device *spi, struct gpio_desc *reset) { /* reset without asserted chip select to return into normal mode */ - spi_bus_lock(spi->master); + spi_bus_lock(spi->controller); ezport_reset(reset); - spi_bus_unlock(spi->master); + spi_bus_unlock(spi->controller); } static int ezport_get_status_register(struct spi_device *spi) From b0a6776e53403aa380411f2a43cdefb9f00ff50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:25 +0100 Subject: [PATCH 037/122] mmc: mmc_spi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Ulf Hansson Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/a9c95759cf77a19c160d1d497c76ac5770c67684.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/mmc/host/mmc_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index b8dda8160c4e..bf35761f783a 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -935,7 +935,7 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) #endif /* request exclusive bus access */ - spi_bus_lock(host->spi->master); + spi_bus_lock(host->spi->controller); crc_recover: /* issue command; then optionally data and stop */ @@ -967,7 +967,7 @@ crc_recover: } /* release the bus */ - spi_bus_unlock(host->spi->master); + spi_bus_unlock(host->spi->controller); mmc_request_done(host->mmc, mrq); } @@ -1157,7 +1157,7 @@ static int mmc_spi_probe(struct spi_device *spi) /* We rely on full duplex transfers, mostly to reduce * per-transfer overheads (by making fewer transfers). */ - if (spi->master->flags & SPI_CONTROLLER_HALF_DUPLEX) + if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) return -EINVAL; /* MMC and SD specs only seem to care that sampling is on the From 44ee998db9eef84bf005c39486566a67cb018354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:26 +0100 Subject: [PATCH 038/122] mtd: dataflash: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Miquel Raynal Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/38bf50b391c117621e406fa8cd00c4daef78615c.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/mtd/devices/mtd_dataflash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 0c1b93303618..ec52277e3dd5 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -638,7 +638,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, /* name must be usable with cmdlinepart */ sprintf(priv->name, "spi%d.%d-%s", - spi->master->bus_num, spi_get_chipselect(spi, 0), + spi->controller->bus_num, spi_get_chipselect(spi, 0), name); device = &priv->mtd; From 1cc711a72ae7fd44e90839f0c8d3226664de55a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:27 +0100 Subject: [PATCH 039/122] net: ks8851: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Simon Horman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/4f26761c0c86072a084b2a20439da1d0a681b07b.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/net/ethernet/micrel/ks8851_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c index 54f2eac11a63..2f803377c9f9 100644 --- a/drivers/net/ethernet/micrel/ks8851_spi.c +++ b/drivers/net/ethernet/micrel/ks8851_spi.c @@ -156,7 +156,7 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned int op, txb[0] = cpu_to_le16(op | KS_SPIOP_RD); - if (kss->spidev->master->flags & SPI_CONTROLLER_HALF_DUPLEX) { + if (kss->spidev->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) { msg = &kss->spi_msg2; xfer = kss->spi_xfer2; @@ -180,7 +180,7 @@ static void ks8851_rdreg(struct ks8851_net *ks, unsigned int op, ret = spi_sync(kss->spidev, msg); if (ret < 0) netdev_err(ks->netdev, "read: spi_sync() failed\n"); - else if (kss->spidev->master->flags & SPI_CONTROLLER_HALF_DUPLEX) + else if (kss->spidev->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) memcpy(rxb, trx, rxl); else memcpy(rxb, trx + 2, rxl); From 7969b98b80c0332f940c547f84650a20aab33841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:28 +0100 Subject: [PATCH 040/122] net: vertexcom: mse102x: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Simon Horman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/feacee68c00f6f976c82864ba2f10a3f0c1b99f2.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/net/ethernet/vertexcom/mse102x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c index aeed2a093e34..edd8b59680e5 100644 --- a/drivers/net/ethernet/vertexcom/mse102x.c +++ b/drivers/net/ethernet/vertexcom/mse102x.c @@ -664,7 +664,7 @@ static int mse102x_probe_spi(struct spi_device *spi) spi->bits_per_word = 8; spi->mode |= SPI_MODE_3; /* enforce minimum speed to ensure device functionality */ - spi->master->min_speed_hz = MIN_FREQ_HZ; + spi->controller->min_speed_hz = MIN_FREQ_HZ; if (!spi->max_speed_hz) spi->max_speed_hz = MAX_FREQ_HZ; From 85ad0ec049a771c4910c8aebb2d0bd9ce9311fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:29 +0100 Subject: [PATCH 041/122] platform/chrome: cros_ec_spi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Tzung-Bi Shih Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/cfbafd8a581a3ca37134cb84cef4370959012d9d.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/platform/chrome/cros_ec_spi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 3e88cc92e819..86a3d32a7763 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -409,7 +409,7 @@ static int do_cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, if (!rx_buf) return -ENOMEM; - spi_bus_lock(ec_spi->spi->master); + spi_bus_lock(ec_spi->spi->controller); /* * Leave a gap between CS assertion and clocking of data to allow the @@ -469,7 +469,7 @@ static int do_cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, final_ret = terminate_request(ec_dev); - spi_bus_unlock(ec_spi->spi->master); + spi_bus_unlock(ec_spi->spi->controller); if (!ret) ret = final_ret; @@ -554,7 +554,7 @@ static int do_cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, if (!rx_buf) return -ENOMEM; - spi_bus_lock(ec_spi->spi->master); + spi_bus_lock(ec_spi->spi->controller); /* Transmit phase - send our message */ debug_packet(ec_dev->dev, "out", ec_dev->dout, len); @@ -590,7 +590,7 @@ static int do_cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, final_ret = terminate_request(ec_dev); - spi_bus_unlock(ec_spi->spi->master); + spi_bus_unlock(ec_spi->spi->controller); if (!ret) ret = final_ret; From 2259233110d90059187c5ba75537eb93eba8417b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:30 +0100 Subject: [PATCH 042/122] spi: bitbang: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into the SPI bitbang controller drivers. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/f7f949feb803acb8bea75798f41371a13287f4e8.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 4 +-- drivers/spi/spi-au1550.c | 2 +- drivers/spi/spi-bitbang.c | 64 ++++++++++++++++----------------- drivers/spi/spi-butterfly.c | 6 ++-- drivers/spi/spi-davinci.c | 6 ++-- drivers/spi/spi-gpio.c | 2 +- drivers/spi/spi-lm70llp.c | 6 ++-- drivers/spi/spi-oc-tiny.c | 6 ++-- drivers/spi/spi-omap-uwire.c | 4 +-- drivers/spi/spi-sh-sci.c | 10 +++--- drivers/spi/spi-xilinx.c | 4 +-- drivers/spi/spi-xtensa-xtfpga.c | 2 +- include/linux/spi/spi_bitbang.h | 2 +- 13 files changed, 59 insertions(+), 59 deletions(-) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index b7ada981464a..d78762d4db98 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -189,7 +189,7 @@ static int ath79_spi_probe(struct platform_device *pdev) host->num_chipselect = 3; host->mem_ops = &ath79_mem_ops; - sp->bitbang.master = host; + sp->bitbang.ctlr = host; sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.flags = SPI_CS_HIGH; @@ -237,7 +237,7 @@ static void ath79_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&sp->bitbang); ath79_spi_disable(sp); - spi_controller_put(sp->bitbang.master); + spi_controller_put(sp->bitbang.ctlr); } static void ath79_spi_shutdown(struct platform_device *pdev) diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 1011b1a8f241..825d2f1cdff8 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -800,7 +800,7 @@ static int au1550_spi_probe(struct platform_device *pdev) init_completion(&hw->host_done); - hw->bitbang.master = hw->host; + hw->bitbang.ctlr = hw->host; hw->bitbang.setup_transfer = au1550_spi_setupxfer; hw->bitbang.chipselect = au1550_spi_chipsel; hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index ecd44016c197..a0e2204fc039 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -187,7 +187,7 @@ int spi_bitbang_setup(struct spi_device *spi) bool initial_setup = false; int retval; - bitbang = spi_master_get_devdata(spi->master); + bitbang = spi_controller_get_devdata(spi->controller); if (!cs) { cs = kzalloc(sizeof(*cs), GFP_KERNEL); @@ -236,7 +236,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) unsigned nsecs = cs->nsecs; struct spi_bitbang *bitbang; - bitbang = spi_master_get_devdata(spi->master); + bitbang = spi_controller_get_devdata(spi->controller); if (bitbang->set_line_direction) { int err; @@ -268,11 +268,11 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * transfer-at-a-time ones to leverage dma or fifo hardware. */ -static int spi_bitbang_prepare_hardware(struct spi_master *spi) +static int spi_bitbang_prepare_hardware(struct spi_controller *spi) { struct spi_bitbang *bitbang; - bitbang = spi_master_get_devdata(spi); + bitbang = spi_controller_get_devdata(spi); mutex_lock(&bitbang->lock); bitbang->busy = 1; @@ -281,11 +281,11 @@ static int spi_bitbang_prepare_hardware(struct spi_master *spi) return 0; } -static int spi_bitbang_transfer_one(struct spi_master *master, +static int spi_bitbang_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *transfer) { - struct spi_bitbang *bitbang = spi_master_get_devdata(master); + struct spi_bitbang *bitbang = spi_controller_get_devdata(ctlr); int status = 0; if (bitbang->setup_transfer) { @@ -303,16 +303,16 @@ static int spi_bitbang_transfer_one(struct spi_master *master, status = -EREMOTEIO; out: - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(ctlr); return status; } -static int spi_bitbang_unprepare_hardware(struct spi_master *spi) +static int spi_bitbang_unprepare_hardware(struct spi_controller *spi) { struct spi_bitbang *bitbang; - bitbang = spi_master_get_devdata(spi); + bitbang = spi_controller_get_devdata(spi); mutex_lock(&bitbang->lock); bitbang->busy = 0; @@ -323,7 +323,7 @@ static int spi_bitbang_unprepare_hardware(struct spi_master *spi) static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) { - struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master); + struct spi_bitbang *bitbang = spi_controller_get_devdata(spi->controller); /* SPI core provides CS high / low, but bitbang driver * expects CS active @@ -341,10 +341,10 @@ static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) int spi_bitbang_init(struct spi_bitbang *bitbang) { - struct spi_master *master = bitbang->master; + struct spi_controller *ctlr = bitbang->ctlr; bool custom_cs; - if (!master) + if (!ctlr) return -EINVAL; /* * We only need the chipselect callback if we are actually using it. @@ -352,39 +352,39 @@ int spi_bitbang_init(struct spi_bitbang *bitbang) * SPI_CONTROLLER_GPIO_SS flag is set, we always need to call the * driver-specific chipselect routine. */ - custom_cs = (!master->use_gpio_descriptors || - (master->flags & SPI_CONTROLLER_GPIO_SS)); + custom_cs = (!ctlr->use_gpio_descriptors || + (ctlr->flags & SPI_CONTROLLER_GPIO_SS)); if (custom_cs && !bitbang->chipselect) return -EINVAL; mutex_init(&bitbang->lock); - if (!master->mode_bits) - master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; + if (!ctlr->mode_bits) + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; - if (master->transfer || master->transfer_one_message) + if (ctlr->transfer || ctlr->transfer_one_message) return -EINVAL; - master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; - master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; - master->transfer_one = spi_bitbang_transfer_one; + ctlr->prepare_transfer_hardware = spi_bitbang_prepare_hardware; + ctlr->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; + ctlr->transfer_one = spi_bitbang_transfer_one; /* * When using GPIO descriptors, the ->set_cs() callback doesn't even * get called unless SPI_CONTROLLER_GPIO_SS is set. */ if (custom_cs) - master->set_cs = spi_bitbang_set_cs; + ctlr->set_cs = spi_bitbang_set_cs; if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; bitbang->txrx_bufs = spi_bitbang_bufs; - if (!master->setup) { + if (!ctlr->setup) { if (!bitbang->setup_transfer) bitbang->setup_transfer = spi_bitbang_setup_transfer; - master->setup = spi_bitbang_setup; - master->cleanup = spi_bitbang_cleanup; + ctlr->setup = spi_bitbang_setup; + ctlr->cleanup = spi_bitbang_cleanup; } } @@ -411,18 +411,18 @@ EXPORT_SYMBOL_GPL(spi_bitbang_init); * master methods. Those methods are the defaults if the bitbang->txrx_bufs * routine isn't initialized. * - * This routine registers the spi_master, which will process requests in a + * This routine registers the spi_controller, which will process requests in a * dedicated task, keeping IRQs unblocked most of the time. To stop * processing those requests, call spi_bitbang_stop(). * - * On success, this routine will take a reference to master. The caller is - * responsible for calling spi_bitbang_stop() to decrement the reference and - * spi_master_put() as counterpart of spi_alloc_master() to prevent a memory + * On success, this routine will take a reference to the controller. The caller + * is responsible for calling spi_bitbang_stop() to decrement the reference and + * spi_controller_put() as counterpart of spi_alloc_master() to prevent a memory * leak. */ int spi_bitbang_start(struct spi_bitbang *bitbang) { - struct spi_master *master = bitbang->master; + struct spi_controller *ctlr = bitbang->ctlr; int ret; ret = spi_bitbang_init(bitbang); @@ -432,9 +432,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices */ - ret = spi_register_master(spi_master_get(master)); + ret = spi_register_controller(spi_controller_get(ctlr)); if (ret) - spi_master_put(master); + spi_controller_put(ctlr); return ret; } @@ -445,7 +445,7 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start); */ void spi_bitbang_stop(struct spi_bitbang *bitbang) { - spi_unregister_master(bitbang->master); + spi_unregister_controller(bitbang->ctlr); } EXPORT_SYMBOL_GPL(spi_bitbang_stop); diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 289b4454242a..1d267e6c22a4 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -205,7 +205,7 @@ static void butterfly_attach(struct parport *p) host->bus_num = 42; host->num_chipselect = 2; - pp->bitbang.master = host; + pp->bitbang.ctlr = host; pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; @@ -263,7 +263,7 @@ static void butterfly_attach(struct parport *p) pp->info[0].platform_data = &flash; pp->info[0].chip_select = 1; pp->info[0].controller_data = pp; - pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); + pp->dataflash = spi_new_device(pp->bitbang.ctlr, &pp->info[0]); if (pp->dataflash) pr_debug("%s: dataflash at %s\n", p->name, dev_name(&pp->dataflash->dev)); @@ -308,7 +308,7 @@ static void butterfly_detach(struct parport *p) parport_release(pp->pd); parport_unregister_device(pp->pd); - spi_controller_put(pp->bitbang.master); + spi_controller_put(pp->bitbang.ctlr); } static struct parport_driver butterfly_driver = { diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 5688be245c68..be3998104bfb 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -459,7 +459,7 @@ static bool davinci_spi_can_dma(struct spi_controller *host, static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) { - struct device *sdev = dspi->bitbang.master->dev.parent; + struct device *sdev = dspi->bitbang.ctlr->dev.parent; if (int_status & SPIFLG_TIMEOUT_MASK) { dev_err(sdev, "SPI Time-out Error\n"); @@ -742,7 +742,7 @@ static irqreturn_t davinci_spi_irq(s32 irq, void *data) static int davinci_spi_request_dma(struct davinci_spi *dspi) { - struct device *sdev = dspi->bitbang.master->dev.parent; + struct device *sdev = dspi->bitbang.ctlr->dev.parent; dspi->dma_rx = dma_request_chan(sdev, "rx"); if (IS_ERR(dspi->dma_rx)) @@ -913,7 +913,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto free_host; - dspi->bitbang.master = host; + dspi->bitbang.ctlr = host; dspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index d8db4564b406..909cce109bba 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -427,7 +427,7 @@ static int spi_gpio_probe(struct platform_device *pdev) host->cleanup = spi_gpio_cleanup; bb = &spi_gpio->bitbang; - bb->master = host; + bb->ctlr = host; /* * There is some additional business, apart from driving the CS GPIO * line, that we need to do on selection. This makes the local diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index e6a65b5c8c31..f982bdebd028 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -212,7 +212,7 @@ static void spi_lm70llp_attach(struct parport *p) /* * SPI and bitbang hookup. */ - pp->bitbang.master = host; + pp->bitbang.ctlr = host; pp->bitbang.chipselect = lm70_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx; pp->bitbang.flags = SPI_3WIRE; @@ -264,7 +264,7 @@ static void spi_lm70llp_attach(struct parport *p) * the board info's (void *)controller_data. */ pp->info.controller_data = pp; - pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info); + pp->spidev_lm70 = spi_new_device(pp->bitbang.ctlr, &pp->info); if (pp->spidev_lm70) dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n", dev_name(&pp->spidev_lm70->dev)); @@ -309,7 +309,7 @@ static void spi_lm70llp_detach(struct parport *p) parport_release(pp->pd); parport_unregister_device(pp->pd); - spi_controller_put(pp->bitbang.master); + spi_controller_put(pp->bitbang.ctlr); lm70llp = NULL; } diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index cf7c111088a6..6ea38f5e7d64 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -194,7 +194,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev) if (!np) return 0; - hw->bitbang.master->dev.of_node = pdev->dev.of_node; + hw->bitbang.ctlr->dev.of_node = pdev->dev.of_node; if (!of_property_read_u32(np, "clock-frequency", &val)) hw->freq = val; if (!of_property_read_u32(np, "baud-width", &val)) @@ -229,7 +229,7 @@ static int tiny_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = host; + hw->bitbang.ctlr = host; hw->bitbang.setup_transfer = tiny_spi_setup_transfer; hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; @@ -274,7 +274,7 @@ exit: static void tiny_spi_remove(struct platform_device *pdev) { struct tiny_spi *hw = platform_get_drvdata(pdev); - struct spi_controller *host = hw->bitbang.master; + struct spi_controller *host = hw->bitbang.ctlr; spi_bitbang_stop(&hw->bitbang); spi_controller_put(host); diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index 2dd1c1bcf4bf..210a98d903fa 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -448,7 +448,7 @@ static void uwire_off(struct uwire_spi *uwire) { uwire_write_reg(UWIRE_SR3, 0); clk_disable_unprepare(uwire->ck); - spi_controller_put(uwire->bitbang.master); + spi_controller_put(uwire->bitbang.ctlr); } static int uwire_probe(struct platform_device *pdev) @@ -493,7 +493,7 @@ static int uwire_probe(struct platform_device *pdev) host->setup = uwire_setup; host->cleanup = uwire_cleanup; - uwire->bitbang.master = host; + uwire->bitbang.ctlr = host; uwire->bitbang.chipselect = uwire_chipselect; uwire->bitbang.setup_transfer = uwire_setup_transfer; uwire->bitbang.txrx_bufs = uwire_txrx; diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 148d615d2f38..3d560b154ad3 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -136,9 +136,9 @@ static int sh_sci_spi_probe(struct platform_device *dev) } /* setup spi bitbang adaptor */ - sp->bitbang.master = host; - sp->bitbang.master->bus_num = sp->info->bus_num; - sp->bitbang.master->num_chipselect = sp->info->num_chipselect; + sp->bitbang.ctlr = host; + sp->bitbang.ctlr->bus_num = sp->info->bus_num; + sp->bitbang.ctlr->num_chipselect = sp->info->num_chipselect; sp->bitbang.chipselect = sh_sci_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0; @@ -166,7 +166,7 @@ static int sh_sci_spi_probe(struct platform_device *dev) setbits(sp, PIN_INIT, 0); iounmap(sp->membase); err1: - spi_controller_put(sp->bitbang.master); + spi_controller_put(sp->bitbang.ctlr); err0: return ret; } @@ -178,7 +178,7 @@ static void sh_sci_spi_remove(struct platform_device *dev) spi_bitbang_stop(&sp->bitbang); setbits(sp, PIN_INIT, 0); iounmap(sp->membase); - spi_controller_put(sp->bitbang.master); + spi_controller_put(sp->bitbang.ctlr); } static struct platform_driver sh_sci_spi_drv = { diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 12355957be97..7795328427a6 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -434,7 +434,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) xspi = spi_controller_get_devdata(host); xspi->cs_inactive = 0xffffffff; - xspi->bitbang.master = host; + xspi->bitbang.ctlr = host; xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; @@ -516,7 +516,7 @@ static void xilinx_spi_remove(struct platform_device *pdev) /* Disable the global IPIF interrupt */ xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); - spi_controller_put(xspi->bitbang.master); + spi_controller_put(xspi->bitbang.ctlr); } /* work with hotplug and coldplug */ diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c index 3c7721894376..3c2cda315397 100644 --- a/drivers/spi/spi-xtensa-xtfpga.c +++ b/drivers/spi/spi-xtensa-xtfpga.c @@ -93,7 +93,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev) host->dev.of_node = pdev->dev.of_node; xspi = spi_controller_get_devdata(host); - xspi->bitbang.master = host; + xspi->bitbang.ctlr = host; xspi->bitbang.chipselect = xtfpga_spi_chipselect; xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word; xspi->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 4444c2a992cb..b930eca2ef7b 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -10,7 +10,7 @@ struct spi_bitbang { u8 use_dma; u16 flags; /* extra spi->mode support */ - struct spi_master *master; + struct spi_controller *ctlr; /* setup_transfer() changes clock and/or wordsize to match settings * for this transfer; zeroes restore defaults from spi_device. From e71011dacc3413bed4118d2c42f10736ffcd762c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:31 +0100 Subject: [PATCH 043/122] spi: cadence-quadspi: Don't emit error message on allocation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers are not supposed to emit an error message when a memory allocation fails, as the kernel is very loud in this case already anyhow. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/8da90785395664bf17d16428f46e84b95ef5cc3b.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index f94e0d370d46..eb6cc861b00b 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1712,10 +1712,9 @@ static int cqspi_probe(struct platform_device *pdev) int irq; host = devm_spi_alloc_host(&pdev->dev, sizeof(*cqspi)); - if (!host) { - dev_err(&pdev->dev, "devm_spi_alloc_host failed\n"); + if (!host) return -ENOMEM; - } + host->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL; host->mem_ops = &cqspi_mem_ops; host->mem_caps = &cqspi_mem_caps; From 28e59d8bf1ace0ddf05f989a48d6824d75731267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:32 +0100 Subject: [PATCH 044/122] spi: cadence-quadspi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/d741960846b7f4896eeff91a4c8c7dfa8a6f8b7b.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index eb6cc861b00b..a5e2f7786b76 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1410,7 +1410,7 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { int ret; - struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master); + struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); struct device *dev = &cqspi->pdev->dev; ret = pm_runtime_resume_and_get(dev); From 1747fbdedba8b6b3fd459895ed5d57e534549884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:33 +0100 Subject: [PATCH 045/122] spi: cavium: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/8aa122cffa6c8c18cc3367def872f81cd9471f2a.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-cavium.c | 6 +++--- drivers/spi/spi-cavium.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-cavium.c b/drivers/spi/spi-cavium.c index dfe224defd6e..26b8cd1c76e1 100644 --- a/drivers/spi/spi-cavium.c +++ b/drivers/spi/spi-cavium.c @@ -124,10 +124,10 @@ static int octeon_spi_do_transfer(struct octeon_spi *p, return xfer->len; } -int octeon_spi_transfer_one_message(struct spi_master *master, +int octeon_spi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct octeon_spi *p = spi_master_get_devdata(master); + struct octeon_spi *p = spi_controller_get_devdata(ctlr); unsigned int total_len = 0; int status = 0; struct spi_transfer *xfer; @@ -145,6 +145,6 @@ int octeon_spi_transfer_one_message(struct spi_master *master, err: msg->status = status; msg->actual_length = total_len; - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return status; } diff --git a/drivers/spi/spi-cavium.h b/drivers/spi/spi-cavium.h index 1f3ac463a20b..af53a0c31476 100644 --- a/drivers/spi/spi-cavium.h +++ b/drivers/spi/spi-cavium.h @@ -28,7 +28,7 @@ struct octeon_spi { #define OCTEON_SPI_TX(x) (x->regs.tx) #define OCTEON_SPI_DAT0(x) (x->regs.data) -int octeon_spi_transfer_one_message(struct spi_master *master, +int octeon_spi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *msg); /* MPI register descriptions */ From 14cea92338a0776c1615994150e738ac0f5fbb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:34 +0100 Subject: [PATCH 046/122] spi: geni-qcom: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. This was already tried before in commit 8726bdcef62e ("spi: geni-qcom: switch to use modern name"), that's why this change is so small. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/895f9a42691dcea037b30dcce5e61be0b44e3a25.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-geni-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 15f84e68d4d2..37ef8c40b276 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -647,7 +647,7 @@ static void spi_geni_release_dma_chan(struct spi_geni_master *mas) static int spi_geni_init(struct spi_geni_master *mas) { - struct spi_master *spi = dev_get_drvdata(mas->dev); + struct spi_controller *spi = dev_get_drvdata(mas->dev); struct geni_se *se = &mas->se; unsigned int proto, major, minor, ver; u32 spi_tx_cfg, fifo_disable; From 2c2310c17fac13aa7e78756d7f3780c7891f9397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:35 +0100 Subject: [PATCH 047/122] spi: loopback-test: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/2f57c89d601d0875cd245a2e95c915b9bfcfc47d.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-loopback-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index bbf2015d8e5c..fee8893d2751 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -1031,8 +1031,8 @@ int spi_test_run_test(struct spi_device *spi, const struct spi_test *test, #define FOR_EACH_ALIGNMENT(var) \ for (var = 0; \ var < (test->iterate_##var ? \ - (spi->master->dma_alignment ? \ - spi->master->dma_alignment : \ + (spi->controller->dma_alignment ? \ + spi->controller->dma_alignment : \ test->iterate_##var) : \ 1); \ var++) From 8197b136bbbe64a7cab1020a4b067020e5977d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:36 +0100 Subject: [PATCH 048/122] spi: slave-mt27xx: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/184a5263af2ec01fd5ad9b8db667ae4d6cbec948.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-slave-mt27xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index 6d6772974783..f1ddf4c099a3 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -297,7 +297,7 @@ static int mtk_spi_slave_transfer_one(struct spi_controller *ctlr, static int mtk_spi_slave_setup(struct spi_device *spi) { - struct mtk_spi_slave *mdata = spi_controller_get_devdata(spi->master); + struct mtk_spi_slave *mdata = spi_controller_get_devdata(spi->controller); u32 reg_val; reg_val = DMA_DONE_EN | DATA_DONE_EN | From d934cd6f0e5d0052772612db4b07df60cb9da387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:37 +0100 Subject: [PATCH 049/122] spi: spidev: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/15ebfdf58a6590962bdd51b49b2e85a69b3bf443.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 655f2c959cd4..95fb5f1c91c1 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -802,7 +802,7 @@ static int spidev_probe(struct spi_device *spi) spidev->devt = MKDEV(SPIDEV_MAJOR, minor); dev = device_create(&spidev_class, &spi->dev, spidev->devt, spidev, "spidev%d.%d", - spi->master->bus_num, spi_get_chipselect(spi, 0)); + spi->controller->bus_num, spi_get_chipselect(spi, 0)); status = PTR_ERR_OR_ZERO(dev); } else { dev_dbg(&spi->dev, "no minor number available!\n"); From bbd25d7260eeeaef89f7371cbadcd33dd7f7bff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:38 +0100 Subject: [PATCH 050/122] staging: fbtft: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Greg Kroah-Hartman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/df79f22caf31d2c5ca2b15b33670323d1e1120c7.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/staging/fbtft/fbtft-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 3626f429b002..68add4d598ae 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -794,7 +794,7 @@ int fbtft_register_framebuffer(struct fb_info *fb_info) if (par->txbuf.buf && par->txbuf.len >= 1024) sprintf(text1, ", %zu KiB buffer memory", par->txbuf.len >> 10); if (spi) - sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num, + sprintf(text2, ", spi%d.%d at %d MHz", spi->controller->bus_num, spi_get_chipselect(spi, 0), spi->max_speed_hz / 1000000); dev_info(fb_info->dev, "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n", @@ -1215,7 +1215,7 @@ int fbtft_probe_common(struct fbtft_display *display, /* 9-bit SPI setup */ if (par->spi && display->buswidth == 9) { - if (par->spi->master->bits_per_word_mask & SPI_BPW_MASK(9)) { + if (par->spi->controller->bits_per_word_mask & SPI_BPW_MASK(9)) { par->spi->bits_per_word = 9; } else { dev_warn(&par->spi->dev, From ee3c668dda3d2783b0fff4091461356fe000e4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:39 +0100 Subject: [PATCH 051/122] staging: greybus: spi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Viresh Kumar Acked-by: Greg Kroah-Hartman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/f6f0568df29f9a51358e86326b917d81af8aba74.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/staging/greybus/spilib.c | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index efb3bec58e15..34f10685139f 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -42,7 +42,7 @@ struct gb_spilib { #define XFER_TIMEOUT_TOLERANCE 200 -static struct spi_master *get_master_from_spi(struct gb_spilib *spi) +static struct spi_controller *get_controller_from_spi(struct gb_spilib *spi) { return gb_connection_get_data(spi->connection); } @@ -324,10 +324,10 @@ static void gb_spi_decode_response(struct gb_spilib *spi, } } -static int gb_spi_transfer_one_message(struct spi_master *master, +static int gb_spi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct gb_spilib *spi = spi_master_get_devdata(master); + struct gb_spilib *spi = spi_controller_get_devdata(ctlr); struct gb_connection *connection = spi->connection; struct gb_spi_transfer_response *response; struct gb_operation *operation; @@ -371,21 +371,21 @@ static int gb_spi_transfer_one_message(struct spi_master *master, out: msg->status = ret; clean_xfer_state(spi); - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return ret; } -static int gb_spi_prepare_transfer_hardware(struct spi_master *master) +static int gb_spi_prepare_transfer_hardware(struct spi_controller *ctlr) { - struct gb_spilib *spi = spi_master_get_devdata(master); + struct gb_spilib *spi = spi_controller_get_devdata(ctlr); return spi->ops->prepare_transfer_hardware(spi->parent); } -static int gb_spi_unprepare_transfer_hardware(struct spi_master *master) +static int gb_spi_unprepare_transfer_hardware(struct spi_controller *ctlr) { - struct gb_spilib *spi = spi_master_get_devdata(master); + struct gb_spilib *spi = spi_controller_get_devdata(ctlr); spi->ops->unprepare_transfer_hardware(spi->parent); @@ -440,7 +440,7 @@ static int gb_spi_get_master_config(struct gb_spilib *spi) static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) { - struct spi_master *master = get_master_from_spi(spi); + struct spi_controller *ctlr = get_controller_from_spi(spi); struct gb_spi_device_config_request request; struct gb_spi_device_config_response response; struct spi_board_info spi_board = { {0} }; @@ -471,11 +471,11 @@ static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) return -EINVAL; spi_board.mode = le16_to_cpu(response.mode); - spi_board.bus_num = master->bus_num; + spi_board.bus_num = ctlr->bus_num; spi_board.chip_select = cs; spi_board.max_speed_hz = le32_to_cpu(response.max_speed_hz); - spidev = spi_new_device(master, &spi_board); + spidev = spi_new_device(ctlr, &spi_board); if (!spidev) return -EINVAL; @@ -486,52 +486,52 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops) { struct gb_spilib *spi; - struct spi_master *master; + struct spi_controller *ctlr; int ret; u8 i; /* Allocate master with space for data */ - master = spi_alloc_master(dev, sizeof(*spi)); - if (!master) { + ctlr = spi_alloc_master(dev, sizeof(*spi)); + if (!ctlr) { dev_err(dev, "cannot alloc SPI master\n"); return -ENOMEM; } - spi = spi_master_get_devdata(master); + spi = spi_controller_get_devdata(ctlr); spi->connection = connection; - gb_connection_set_data(connection, master); + gb_connection_set_data(connection, ctlr); spi->parent = dev; spi->ops = ops; - /* get master configuration */ + /* get controller configuration */ ret = gb_spi_get_master_config(spi); if (ret) goto exit_spi_put; - master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ - master->num_chipselect = spi->num_chipselect; - master->mode_bits = spi->mode; - master->flags = spi->flags; - master->bits_per_word_mask = spi->bits_per_word_mask; + ctlr->bus_num = -1; /* Allow spi-core to allocate it dynamically */ + ctlr->num_chipselect = spi->num_chipselect; + ctlr->mode_bits = spi->mode; + ctlr->flags = spi->flags; + ctlr->bits_per_word_mask = spi->bits_per_word_mask; /* Attach methods */ - master->cleanup = gb_spi_cleanup; - master->setup = gb_spi_setup; - master->transfer_one_message = gb_spi_transfer_one_message; + ctlr->cleanup = gb_spi_cleanup; + ctlr->setup = gb_spi_setup; + ctlr->transfer_one_message = gb_spi_transfer_one_message; if (ops && ops->prepare_transfer_hardware) { - master->prepare_transfer_hardware = + ctlr->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware; } if (ops && ops->unprepare_transfer_hardware) { - master->unprepare_transfer_hardware = + ctlr->unprepare_transfer_hardware = gb_spi_unprepare_transfer_hardware; } - master->auto_runtime_pm = true; + ctlr->auto_runtime_pm = true; - ret = spi_register_master(master); + ret = spi_register_controller(ctlr); if (ret < 0) goto exit_spi_put; @@ -548,12 +548,12 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, return 0; exit_spi_put: - spi_master_put(master); + spi_controller_put(ctlr); return ret; exit_spi_unregister: - spi_unregister_master(master); + spi_unregister_controller(ctlr); return ret; } @@ -561,9 +561,9 @@ EXPORT_SYMBOL_GPL(gb_spilib_master_init); void gb_spilib_master_exit(struct gb_connection *connection) { - struct spi_master *master = gb_connection_get_data(connection); + struct spi_controller *ctlr = gb_connection_get_data(connection); - spi_unregister_master(master); + spi_unregister_controller(ctlr); } EXPORT_SYMBOL_GPL(gb_spilib_master_exit); From b6af14eacc8814b0986e20507df423cebe9fd859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:40 +0100 Subject: [PATCH 052/122] tpm_tis_spi: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Jarkko Sakkinen Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/29000c8fc0612974242e3c23d14dd4771b92c71e.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/char/tpm/tpm_tis_spi_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index c5c3197ee29f..c647de7b3709 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -146,7 +146,7 @@ static int tpm_tis_spi_transfer_full(struct tpm_tis_data *data, u32 addr, struct spi_transfer spi_xfer; u8 transfer_len; - spi_bus_lock(phy->spi_device->master); + spi_bus_lock(phy->spi_device->controller); while (len) { transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); @@ -210,7 +210,7 @@ exit: spi_sync_locked(phy->spi_device, &m); } - spi_bus_unlock(phy->spi_device->master); + spi_bus_unlock(phy->spi_device->controller); return ret; } From 8c716f4a3d4fcbec976247e3443d36cbc24c0512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:41 +0100 Subject: [PATCH 053/122] usb: gadget: max3420_udc: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Reviewed-by: Herve Codina Acked-by: Greg Kroah-Hartman Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/5caf03b6f321a9870aabb9282f1f22211d052740.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/usb/gadget/udc/max3420_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/max3420_udc.c b/drivers/usb/gadget/udc/max3420_udc.c index 89e8cf2a2a7d..7349ea774adf 100644 --- a/drivers/usb/gadget/udc/max3420_udc.c +++ b/drivers/usb/gadget/udc/max3420_udc.c @@ -1201,7 +1201,7 @@ static int max3420_probe(struct spi_device *spi) int err, irq; u8 reg[8]; - if (spi->master->flags & SPI_CONTROLLER_HALF_DUPLEX) { + if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) { dev_err(&spi->dev, "UDC needs full duplex to work\n"); return -EINVAL; } From b23031e730e72ec9067b7c38c25e776c5e27e116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:42 +0100 Subject: [PATCH 054/122] video: fbdev: mmp: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/136f59b6e272e5ff7ec210627c9c3ea27d066d51.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/video/fbdev/mmp/hw/mmp_spi.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/video/fbdev/mmp/hw/mmp_spi.c b/drivers/video/fbdev/mmp/hw/mmp_spi.c index 0f8f0312a7c4..cf23650d7f0b 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_spi.c +++ b/drivers/video/fbdev/mmp/hw/mmp_spi.c @@ -32,7 +32,7 @@ static inline int lcd_spi_write(struct spi_device *spi, u32 data) int timeout = 100000, isr, ret = 0; u32 tmp; void __iomem *reg_base = (void __iomem *) - *(void **)spi_master_get_devdata(spi->master); + *(void **) spi_controller_get_devdata(spi->controller); /* clear ISR */ writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR); @@ -81,7 +81,7 @@ static inline int lcd_spi_write(struct spi_device *spi, u32 data) static int lcd_spi_setup(struct spi_device *spi) { void __iomem *reg_base = (void __iomem *) - *(void **)spi_master_get_devdata(spi->master); + *(void **) spi_controller_get_devdata(spi->controller); u32 tmp; tmp = CFG_SCLKCNT(16) | @@ -136,32 +136,32 @@ static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m) int lcd_spi_register(struct mmphw_ctrl *ctrl) { - struct spi_master *master; + struct spi_controller *ctlr; void **p_regbase; int err; - master = spi_alloc_master(ctrl->dev, sizeof(void *)); - if (!master) { + ctlr = spi_alloc_master(ctrl->dev, sizeof(void *)); + if (!ctlr) { dev_err(ctrl->dev, "unable to allocate SPI master\n"); return -ENOMEM; } - p_regbase = spi_master_get_devdata(master); + p_regbase = spi_controller_get_devdata(ctlr); *p_regbase = (void __force *)ctrl->reg_base; /* set bus num to 5 to avoid conflict with other spi hosts */ - master->bus_num = 5; - master->num_chipselect = 1; - master->setup = lcd_spi_setup; - master->transfer = lcd_spi_one_transfer; + ctlr->bus_num = 5; + ctlr->num_chipselect = 1; + ctlr->setup = lcd_spi_setup; + ctlr->transfer = lcd_spi_one_transfer; - err = spi_register_master(master); + err = spi_register_controller(ctlr); if (err < 0) { dev_err(ctrl->dev, "unable to register SPI master\n"); - spi_master_put(master); + spi_controller_put(ctlr); return err; } - dev_info(&master->dev, "registered\n"); + dev_info(&ctlr->dev, "registered\n"); return 0; } From 30060d57cee194d6b70283f2faf787e2fdc61b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:43 +0100 Subject: [PATCH 055/122] wifi: libertas: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Kalle Valo Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/971429eacddbad4c2f49b783ddd68746c1929ab3.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/net/wireless/marvell/libertas/if_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 8690b0114e23..b722a6587fd3 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -1052,7 +1052,7 @@ static int if_spi_init_card(struct if_spi_card *card) "attached to SPI bus_num %d, chip_select %d. " "spi->max_speed_hz=%d\n", card->card_id, card->card_rev, - card->spi->master->bus_num, + card->spi->controller->bus_num, spi_get_chipselect(card->spi, 0), card->spi->max_speed_hz); err = if_spi_prog_helper_firmware(card, helper); From 801185efa2402dce57828930e9684884fc8d62da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:44 +0100 Subject: [PATCH 056/122] spi: fsl-lib: Follow renaming of SPI "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. To not break all drivers compatibility macros were provided. To be able to remove these compatibility macros push the renaming into this driver. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/b3d724ca2b641f1d717a7ddb9810bdf27168dc35.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lib.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c index 885757c29fbb..4fc2c56555b5 100644 --- a/drivers/spi/spi-fsl-lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -82,18 +82,18 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) { struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct spi_master *master; + struct spi_controller *ctlr; struct mpc8xxx_spi *mpc8xxx_spi; - master = dev_get_drvdata(dev); + ctlr = dev_get_drvdata(dev); /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_LOOP; - master->dev.of_node = dev->of_node; + ctlr->dev.of_node = dev->of_node; - mpc8xxx_spi = spi_master_get_devdata(master); + mpc8xxx_spi = spi_controller_get_devdata(ctlr); mpc8xxx_spi->dev = dev; mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8; @@ -104,8 +104,8 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, mpc8xxx_spi->rx_shift = 0; mpc8xxx_spi->tx_shift = 0; - master->bus_num = pdata->bus_num; - master->num_chipselect = pdata->max_chipselect; + ctlr->bus_num = pdata->bus_num; + ctlr->num_chipselect = pdata->max_chipselect; init_completion(&mpc8xxx_spi->done); } From 620d269f29a569ba37419cc03cf1da2d55f6252a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:45 +0100 Subject: [PATCH 057/122] spi: Drop compat layer from renaming "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all in-tree users followed the rename, the compat stuff can go away. This completes the renaming started with commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/ad1d949325b61a4682e8d6ecf9d05da751e6a99f.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- .../driver-api/driver-model/devres.rst | 2 +- drivers/spi/spi.c | 2 +- include/linux/spi/spi.h | 20 +------------------ 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index c5f99d834ec5..49c6fd82cd5d 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -462,7 +462,7 @@ SLAVE DMA ENGINE SPI devm_spi_alloc_master() devm_spi_alloc_slave() - devm_spi_register_master() + devm_spi_register_controller() WATCHDOG devm_watchdog_register_device() diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f2170f4b5077..4b3e7a624de2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -584,7 +584,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) return NULL; } - spi->master = spi->controller = ctlr; + spi->controller = ctlr; spi->dev.parent = &ctlr->dev; spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 600fbd5daf68..30ada46b51cd 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -131,7 +131,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg, * struct spi_device - Controller side proxy for an SPI slave device * @dev: Driver model representation of the device. * @controller: SPI controller used with the device. - * @master: Copy of controller, for backwards compatibility. * @max_speed_hz: Maximum clock rate to be used with this chip * (on this board); may be changed by the device's driver. * The spi_transfer.speed_hz can override this for each transfer. @@ -185,7 +184,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg, struct spi_device { struct device dev; struct spi_controller *controller; - struct spi_controller *master; /* Compatibility layer */ u32 max_speed_hz; u8 chip_select[SPI_CS_CNT_MAX]; u8 bits_per_word; @@ -1298,7 +1296,7 @@ spi_max_transfer_size(struct spi_device *spi) */ static inline bool spi_is_bpw_supported(struct spi_device *spi, u32 bpw) { - u32 bpw_mask = spi->master->bits_per_word_mask; + u32 bpw_mask = spi->controller->bits_per_word_mask; if (bpw == 8 || (bpw <= 32 && bpw_mask & SPI_BPW_MASK(bpw))) return true; @@ -1670,20 +1668,4 @@ spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer) return list_is_last(&xfer->transfer_list, &ctlr->cur_msg->transfers); } -/* Compatibility layer */ -#define spi_master spi_controller - -#define spi_master_get_devdata(_ctlr) spi_controller_get_devdata(_ctlr) -#define spi_master_set_devdata(_ctlr, _data) \ - spi_controller_set_devdata(_ctlr, _data) -#define spi_master_get(_ctlr) spi_controller_get(_ctlr) -#define spi_master_put(_ctlr) spi_controller_put(_ctlr) -#define spi_master_suspend(_ctlr) spi_controller_suspend(_ctlr) -#define spi_master_resume(_ctlr) spi_controller_resume(_ctlr) - -#define spi_register_master(_ctlr) spi_register_controller(_ctlr) -#define devm_spi_register_master(_dev, _ctlr) \ - devm_spi_register_controller(_dev, _ctlr) -#define spi_unregister_master(_ctlr) spi_unregister_controller(_ctlr) - #endif /* __LINUX_SPI_H */ From 76b31eb4c2da3ddb3195cc14f6aad24908adf524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Feb 2024 19:40:46 +0100 Subject: [PATCH 058/122] Documentation: spi: Update documentation for renaming "master" to "controller" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. Adapt the documentation accordingly. Acked-by: Jonathan Cameron Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/3d643e22cacff12d3918ad5224baa1d01813d03b.1707324794.git.u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- Documentation/spi/spi-summary.rst | 74 +++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/Documentation/spi/spi-summary.rst b/Documentation/spi/spi-summary.rst index 33f05901ccf3..e714472007f1 100644 --- a/Documentation/spi/spi-summary.rst +++ b/Documentation/spi/spi-summary.rst @@ -9,7 +9,7 @@ What is SPI? The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial link used to connect microcontrollers to sensors, memory, and peripherals. It's a simple "de facto" standard, not complicated enough to acquire a -standardization body. SPI uses a master/slave configuration. +standardization body. SPI uses a host/target configuration. The three signal wires hold a clock (SCK, often on the order of 10 MHz), and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, @@ -19,11 +19,11 @@ commonly used. Each clock cycle shifts data out and data in; the clock doesn't cycle except when there is a data bit to shift. Not all data bits are used though; not every protocol uses those full duplex capabilities. -SPI masters use a fourth "chip select" line to activate a given SPI slave +SPI hosts use a fourth "chip select" line to activate a given SPI slave device, so those three signal wires may be connected to several chips in parallel. All SPI slaves support chipselects; they are usually active low signals, labeled nCSx for slave 'x' (e.g. nCS0). Some devices have -other signals, often including an interrupt to the master. +other signals, often including an interrupt to the host. Unlike serial busses like USB or SMBus, even low level protocols for SPI slave functions are usually not interoperable between vendors @@ -45,8 +45,8 @@ SPI slave functions are usually not interoperable between vendors In the same way, SPI slaves will only rarely support any kind of automatic discovery/enumeration protocol. The tree of slave devices accessible from -a given SPI master will normally be set up manually, with configuration -tables. +a given SPI host controller will normally be set up manually, with +configuration tables. SPI is only one of the names used by such four-wire protocols, and most controllers have no problem handling "MicroWire" (think of it as @@ -62,8 +62,8 @@ course they won't handle full duplex transfers. You may find such chips described as using "three wire" signaling: SCK, data, nCSx. (That data line is sometimes called MOMI or SISO.) -Microcontrollers often support both master and slave sides of the SPI -protocol. This document (and Linux) supports both the master and slave +Microcontrollers often support both host and target sides of the SPI +protocol. This document (and Linux) supports both the host and target sides of SPI interactions. @@ -118,7 +118,7 @@ starting low (CPOL=0) and data stabilized for sampling during the trailing clock edge (CPHA=1), that's SPI mode 1. Note that the clock mode is relevant as soon as the chipselect goes -active. So the master must set the clock to inactive before selecting +active. So the host must set the clock to inactive before selecting a slave, and the slave can tell the chosen polarity by sampling the clock level when its select line goes active. That's why many devices support for example both modes 0 and 3: they don't care about polarity, @@ -179,7 +179,7 @@ shows up in sysfs in several locations:: /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices /sys/class/spi_master/spiB ... symlink to a logical node which could hold - class related state for the SPI master controller managing bus "B". + class related state for the SPI host controller managing bus "B". All spiB.* devices share one physical SPI bus segment, with SCLK, MOSI, and MISO. @@ -316,7 +316,7 @@ sharing a bus with a device that interprets chipselect "backwards" is not possible until the infrastructure knows how to deselect it. Then your board initialization code would register that table with the SPI -infrastructure, so that it's available later when the SPI master controller +infrastructure, so that it's available later when the SPI host controller driver is registered:: spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); @@ -474,34 +474,34 @@ How do I write an "SPI Master Controller Driver"? An SPI controller will probably be registered on the platform_bus; write a driver to bind to the device, whichever bus is involved. -The main task of this type of driver is to provide an "spi_master". -Use spi_alloc_master() to allocate the master, and spi_master_get_devdata() -to get the driver-private data allocated for that device. +The main task of this type of driver is to provide an "spi_controller". +Use spi_alloc_host() to allocate the host controller, and +spi_controller_get_devdata() to get the driver-private data allocated for that +device. :: - struct spi_master *master; + struct spi_controller *ctlr; struct CONTROLLER *c; - master = spi_alloc_master(dev, sizeof *c); - if (!master) + ctlr = spi_alloc_host(dev, sizeof *c); + if (!ctlr) return -ENODEV; - c = spi_master_get_devdata(master); + c = spi_controller_get_devdata(ctlr); -The driver will initialize the fields of that spi_master, including the -bus number (maybe the same as the platform device ID) and three methods -used to interact with the SPI core and SPI protocol drivers. It will -also initialize its own internal state. (See below about bus numbering -and those methods.) +The driver will initialize the fields of that spi_controller, including the bus +number (maybe the same as the platform device ID) and three methods used to +interact with the SPI core and SPI protocol drivers. It will also initialize +its own internal state. (See below about bus numbering and those methods.) -After you initialize the spi_master, then use spi_register_master() to +After you initialize the spi_controller, then use spi_register_controller() to publish it to the rest of the system. At that time, device nodes for the controller and any predeclared spi devices will be made available, and the driver model core will take care of binding them to drivers. -If you need to remove your SPI controller driver, spi_unregister_master() -will reverse the effect of spi_register_master(). +If you need to remove your SPI controller driver, spi_unregister_controller() +will reverse the effect of spi_register_controller(). Bus Numbering @@ -519,10 +519,10 @@ then be replaced by a dynamically assigned number. You'd then need to treat this as a non-static configuration (see above). -SPI Master Methods -^^^^^^^^^^^^^^^^^^ +SPI Host Controller Methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``master->setup(struct spi_device *spi)`` +``ctlr->setup(struct spi_device *spi)`` This sets up the device clock rate, SPI mode, and word sizes. Drivers may change the defaults provided by board_info, and then call spi_setup(spi) to invoke this routine. It may sleep. @@ -534,34 +534,34 @@ SPI Master Methods .. note:: BUG ALERT: for some reason the first version of - many spi_master drivers seems to get this wrong. + many spi_controller drivers seems to get this wrong. When you code setup(), ASSUME that the controller is actively processing transfers for another device. -``master->cleanup(struct spi_device *spi)`` +``ctlr->cleanup(struct spi_device *spi)`` Your controller driver may use spi_device.controller_state to hold state it dynamically associates with that device. If you do that, be sure to provide the cleanup() method to free that state. -``master->prepare_transfer_hardware(struct spi_master *master)`` +``ctlr->prepare_transfer_hardware(struct spi_controller *ctlr)`` This will be called by the queue mechanism to signal to the driver that a message is coming in soon, so the subsystem requests the driver to prepare the transfer hardware by issuing this call. This may sleep. -``master->unprepare_transfer_hardware(struct spi_master *master)`` +``ctlr->unprepare_transfer_hardware(struct spi_controller *ctlr)`` This will be called by the queue mechanism to signal to the driver that there are no more messages pending in the queue and it may relax the hardware (e.g. by power management calls). This may sleep. -``master->transfer_one_message(struct spi_master *master, struct spi_message *mesg)`` +``ctlr->transfer_one_message(struct spi_controller *ctlr, struct spi_message *mesg)`` The subsystem calls the driver to transfer a single message while queuing transfers that arrive in the meantime. When the driver is finished with this message, it must call spi_finalize_current_message() so the subsystem can issue the next message. This may sleep. -``master->transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer)`` +``ctrl->transfer_one(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *transfer)`` The subsystem calls the driver to transfer a single transfer while queuing transfers that arrive in the meantime. When the driver is finished with this transfer, it must call @@ -576,15 +576,15 @@ SPI Master Methods * 0: transfer is finished * 1: transfer is still in progress -``master->set_cs_timing(struct spi_device *spi, u8 setup_clk_cycles, u8 hold_clk_cycles, u8 inactive_clk_cycles)`` - This method allows SPI client drivers to request SPI master controller +``ctrl->set_cs_timing(struct spi_device *spi, u8 setup_clk_cycles, u8 hold_clk_cycles, u8 inactive_clk_cycles)`` + This method allows SPI client drivers to request SPI host controller for configuring device specific CS setup, hold and inactive timing requirements. Deprecated Methods ^^^^^^^^^^^^^^^^^^ -``master->transfer(struct spi_device *spi, struct spi_message *message)`` +``ctrl->transfer(struct spi_device *spi, struct spi_message *message)`` This must not sleep. Its responsibility is to arrange that the transfer happens and its complete() callback is issued. The two will normally happen later, after other transfers complete, and From a77ce80f63f06d7ae933c332ed77c79136fa69b0 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:15 +0000 Subject: [PATCH 059/122] spi: s3c64xx: sort headers alphabetically Sorting headers alphabetically helps locating duplicates, and makes it easier to figure out where to insert new headers. Reviewed-by: Andi Shyti Reviewed-by: Peter Griffin Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-2-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7f7eb8f742e4..8faa66bfa84e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -3,19 +3,18 @@ // Copyright (c) 2009 Samsung Electronics Co., Ltd. // Jaswinder Singh -#include -#include -#include -#include #include +#include #include #include +#include +#include +#include +#include +#include #include #include #include -#include - -#include #define MAX_SPI_PORTS 12 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) From 42a9ac378d918176e17592cbe79d8b0606f951e4 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:16 +0000 Subject: [PATCH 060/122] spi: s3c64xx: explicitly include The driver uses readl() but does not include . It is good practice to directly include all headers used, it avoids implicit dependencies and spurious breakage if someone rearranges headers and causes the implicit include to vanish. Include the missing header. Reviewed-by: Peter Griffin Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-3-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8faa66bfa84e..9b8dd05360fa 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include From 4568fa574fcef3811a8140702979f076ef0f5bc0 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:17 +0000 Subject: [PATCH 061/122] spi: s3c64xx: explicitly include The driver uses GENMASK() but does not include . It is good practice to directly include all headers used, it avoids implicit dependencies and spurious breakage if someone rearranges headers and causes the implicit include to vanish. Include the missing header. Reviewed-by: Peter Griffin Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-4-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 9b8dd05360fa..5c9ac9d8dbd6 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -3,6 +3,7 @@ // Copyright (c) 2009 Samsung Electronics Co., Ltd. // Jaswinder Singh +#include #include #include #include From 7256d6bdd4fe0eac6d4bcd138c3d87f95f79c750 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:18 +0000 Subject: [PATCH 062/122] spi: s3c64xx: explicitly include The driver uses u32 and relies on an implicit inclusion of . It is good practice to directly include all headers used, it avoids implicit dependencies and spurious breakage if someone rearranges headers and causes the implicit include to vanish. Include the missing header. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-5-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 5c9ac9d8dbd6..f6048345022d 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -17,6 +17,7 @@ #include #include #include +#include #define MAX_SPI_PORTS 12 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) From a336d41bbea51e11e3e4f56bd3877a535c077129 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:19 +0000 Subject: [PATCH 063/122] spi: s3c64xx: avoid possible negative array index The platform id is used as an index into the fifo_lvl_mask array. Platforms can come with a negative device ID, PLATFORM_DEVID_NONE (-1), thus we risked a negative array index. Catch such cases and fail to probe. Reviewed-by: Sam Protsenko Reviewed-by: Peter Griffin Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-6-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index f6048345022d..87b7203f9b1f 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1189,6 +1189,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) "Failed to get alias id\n"); sdd->port_id = ret; } else { + if (pdev->id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Negative platform ID is not allowed\n"); sdd->port_id = pdev->id; } From 97b63f4707046b2ef99d077dd4d333c3acca06ae Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:20 +0000 Subject: [PATCH 064/122] spi: s3c64xx: fix typo, s/configuartion/configuration Fix typo, s/configuartion/configuration. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-7-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 87b7203f9b1f..6b93e8a0c637 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -180,7 +180,7 @@ struct s3c64xx_spi_port_config { * @cur_speed: Current clock speed * @rx_dma: Local receive DMA data (e.g. chan and direction) * @tx_dma: Local transmit DMA data (e.g. chan and direction) - * @port_conf: Local SPI port configuartion data + * @port_conf: Local SPI port configuration data * @port_id: Port identification number */ struct s3c64xx_spi_driver_data { From 271f18816b3ba2f75785660e427c16585b7302f2 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:21 +0000 Subject: [PATCH 065/122] spi: s3c64xx: remove unneeded (void *) casts in of_match_table of_device_id::data is an opaque pointer. No explicit cast is needed. Remove unneeded (void *) casts in of_match_table. Reviewed-by: Andi Shyti Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-8-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6b93e8a0c637..3f8fc9d5a508 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1513,31 +1513,31 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = { static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,s3c2443-spi", - .data = (void *)&s3c2443_spi_port_config, + .data = &s3c2443_spi_port_config, }, { .compatible = "samsung,s3c6410-spi", - .data = (void *)&s3c6410_spi_port_config, + .data = &s3c6410_spi_port_config, }, { .compatible = "samsung,s5pv210-spi", - .data = (void *)&s5pv210_spi_port_config, + .data = &s5pv210_spi_port_config, }, { .compatible = "samsung,exynos4210-spi", - .data = (void *)&exynos4_spi_port_config, + .data = &exynos4_spi_port_config, }, { .compatible = "samsung,exynos7-spi", - .data = (void *)&exynos7_spi_port_config, + .data = &exynos7_spi_port_config, }, { .compatible = "samsung,exynos5433-spi", - .data = (void *)&exynos5433_spi_port_config, + .data = &exynos5433_spi_port_config, }, { .compatible = "samsung,exynos850-spi", - .data = (void *)&exynos850_spi_port_config, + .data = &exynos850_spi_port_config, }, { .compatible = "samsung,exynosautov9-spi", - .data = (void *)&exynosautov9_spi_port_config, + .data = &exynosautov9_spi_port_config, }, { .compatible = "tesla,fsd-spi", - .data = (void *)&fsd_spi_port_config, + .data = &fsd_spi_port_config, }, { }, }; From 9d47e411f4d636519a8d26587928d34cf52c0c1f Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:22 +0000 Subject: [PATCH 066/122] spi: s3c64xx: remove else after return Else case is not needed after a return, remove it. Reviewed-by: Andi Shyti Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-9-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 3f8fc9d5a508..fc0fe81ac95f 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -408,12 +408,10 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, { struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); - if (sdd->rx_dma.ch && sdd->tx_dma.ch) { + if (sdd->rx_dma.ch && sdd->tx_dma.ch) return xfer->len > FIFO_DEPTH(sdd); - } else { - return false; - } + return false; } static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, From 5d7f4f4367079992c7a1bb1654ffea87ddc82be8 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:23 +0000 Subject: [PATCH 067/122] spi: s3c64xx: move common code outside if else Move common code outside if else to avoid code duplication. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-10-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index fc0fe81ac95f..8c76894d0eb1 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -292,20 +292,18 @@ static int prepare_dma(struct s3c64xx_spi_dma_data *dma, if (dma->direction == DMA_DEV_TO_MEM) { sdd = container_of((void *)dma, struct s3c64xx_spi_driver_data, rx_dma); - config.direction = dma->direction; config.src_addr = sdd->sfr_start + S3C64XX_SPI_RX_DATA; config.src_addr_width = sdd->cur_bpw / 8; config.src_maxburst = 1; - dmaengine_slave_config(dma->ch, &config); } else { sdd = container_of((void *)dma, struct s3c64xx_spi_driver_data, tx_dma); - config.direction = dma->direction; config.dst_addr = sdd->sfr_start + S3C64XX_SPI_TX_DATA; config.dst_addr_width = sdd->cur_bpw / 8; config.dst_maxburst = 1; - dmaengine_slave_config(dma->ch, &config); } + config.direction = dma->direction; + dmaengine_slave_config(dma->ch, &config); desc = dmaengine_prep_slave_sg(dma->ch, sgt->sgl, sgt->nents, dma->direction, DMA_PREP_INTERRUPT); From e9c49effde70fb4b10d0ad9c94b69fe6314fc608 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:24 +0000 Subject: [PATCH 068/122] spi: s3c64xx: check return code of dmaengine_slave_config() Check the return code of dmaengine_slave_config(). Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-11-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8c76894d0eb1..5da82013e17b 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -303,7 +303,9 @@ static int prepare_dma(struct s3c64xx_spi_dma_data *dma, config.dst_maxburst = 1; } config.direction = dma->direction; - dmaengine_slave_config(dma->ch, &config); + ret = dmaengine_slave_config(dma->ch, &config); + if (ret) + return ret; desc = dmaengine_prep_slave_sg(dma->ch, sgt->sgl, sgt->nents, dma->direction, DMA_PREP_INTERRUPT); From 60dc8d342e933097eb82db5859edcac9077a6db5 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:25 +0000 Subject: [PATCH 069/122] spi: s3c64xx: propagate the dma_submit_error() error code DMA submit should just add the dma descriptor to a queue, without firing it. EIO is misleading and hides what happens in DMA. Propagate the dma_submit_error() error code, don't overwrite it. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-12-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 5da82013e17b..6012c88cb2ec 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -322,7 +322,7 @@ static int prepare_dma(struct s3c64xx_spi_dma_data *dma, ret = dma_submit_error(dma->cookie); if (ret) { dev_err(&sdd->pdev->dev, "DMA submission failed"); - return -EIO; + return ret; } dma_async_issue_pending(dma->ch); From 4c6452050530b741daf108de0c02cd2299f8f5d1 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:26 +0000 Subject: [PATCH 070/122] spi: s3c64xx: rename prepare_dma() to s3c64xx_prepare_dma() Don't monopolize the name. Prepend the driver prefix to the function name. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-13-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6012c88cb2ec..fbd500f26765 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -279,8 +279,8 @@ static void s3c64xx_spi_dmacb(void *data) spin_unlock_irqrestore(&sdd->lock, flags); } -static int prepare_dma(struct s3c64xx_spi_dma_data *dma, - struct sg_table *sgt) +static int s3c64xx_prepare_dma(struct s3c64xx_spi_dma_data *dma, + struct sg_table *sgt) { struct s3c64xx_spi_driver_data *sdd; struct dma_slave_config config; @@ -445,7 +445,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, chcfg |= S3C64XX_SPI_CH_TXCH_ON; if (dma_mode) { modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; - ret = prepare_dma(&sdd->tx_dma, &xfer->tx_sg); + ret = s3c64xx_prepare_dma(&sdd->tx_dma, &xfer->tx_sg); } else { switch (sdd->cur_bpw) { case 32: @@ -477,7 +477,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) | S3C64XX_SPI_PACKET_CNT_EN, regs + S3C64XX_SPI_PACKET_CNT); - ret = prepare_dma(&sdd->rx_dma, &xfer->rx_sg); + ret = s3c64xx_prepare_dma(&sdd->rx_dma, &xfer->rx_sg); } } From 1a234accc93191a3a73eb4cc264abb6d79d63430 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:27 +0000 Subject: [PATCH 071/122] spi: s3c64xx: return ETIMEDOUT for wait_for_completion_timeout() ETIMEDOUT is more specific than EIO, use it for wait_for_completion_timeout(). Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-14-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index fbd500f26765..470610431ef8 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -527,7 +527,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd, /* * If the previous xfer was completed within timeout, then - * proceed further else return -EIO. + * proceed further else return -ETIMEDOUT. * DmaTx returns after simply writing data in the FIFO, * w/o waiting for real transmission on the bus to finish. * DmaRx returns only after Dma read data from FIFO which @@ -548,7 +548,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd, /* If timed out while checking rx/tx status return error */ if (!val) - return -EIO; + return -ETIMEDOUT; return 0; } @@ -578,7 +578,7 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, if (use_irq) { val = msecs_to_jiffies(ms); if (!wait_for_completion_timeout(&sdd->xfer_completion, val)) - return -EIO; + return -ETIMEDOUT; } val = msecs_to_loops(ms); From 91a9b8e6b63eeb3634e736a4b65ae536c08155b2 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:28 +0000 Subject: [PATCH 072/122] spi: s3c64xx: drop blank line between declarations Drop the blank line and move the logical operation in the body of the function rather than in initialization list. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-15-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 470610431ef8..458ed0cc48e6 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1321,8 +1321,9 @@ static int s3c64xx_spi_suspend(struct device *dev) { struct spi_controller *host = dev_get_drvdata(dev); struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); + int ret; - int ret = spi_controller_suspend(host); + ret = spi_controller_suspend(host); if (ret) return ret; From f186d34071fb2a7db7249b09d5e1796b18b37d7d Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:29 +0000 Subject: [PATCH 073/122] spi: s3c64xx: downgrade dev_warn to dev_dbg for optional dt props "samsung,spi-src-clk" and "num-cs" are optional dt properties. Downgrade the message from warning to debug message. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-16-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 458ed0cc48e6..66260f7cd7ad 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1110,14 +1110,14 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) return ERR_PTR(-ENOMEM); if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) { - dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n"); + dev_dbg(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n"); sci->src_clk_nr = 0; } else { sci->src_clk_nr = temp; } if (of_property_read_u32(dev->of_node, "num-cs", &temp)) { - dev_warn(dev, "number of chip select lines not specified, assuming 1 chip select line\n"); + dev_dbg(dev, "number of chip select lines not specified, assuming 1 chip select line\n"); sci->num_cs = 1; } else { sci->num_cs = temp; From eb8096c30ad07e6201830816e398b3ad603cc096 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:30 +0000 Subject: [PATCH 074/122] spi: s3c64xx: remove duplicated definition S3C64XX_SPI_TRAILCNT brings no benefit in terms of name over S3C64XX_SPI_MAX_TRAILCNT. Remove the duplicated definition. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-17-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 66260f7cd7ad..c1d028d1530e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -116,8 +116,6 @@ #define S3C64XX_SPI_MAX_TRAILCNT 0x3ff #define S3C64XX_SPI_TRAILCNT_OFF 19 -#define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT - #define S3C64XX_SPI_POLLING_SIZE 32 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) @@ -1093,7 +1091,7 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd) val = readl(regs + S3C64XX_SPI_MODE_CFG); val &= ~S3C64XX_SPI_MODE_4BURST; val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF); - val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF); + val |= (S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF); writel(val, regs + S3C64XX_SPI_MODE_CFG); s3c64xx_flush_fifo(sdd); From acd6c7b1d2765fd30b7d7487aff50dc824db314e Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 12:04:31 +0000 Subject: [PATCH 075/122] spi: s3c64xx: drop a superfluous bitwise NOT operation val &= ~mask; val |= mask; is equivalent to: val |= mask; Drop the superfluous bitwise NOT operation. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207120431.2766269-18-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index c1d028d1530e..c15ca6a910dc 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1090,7 +1090,6 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd) val = readl(regs + S3C64XX_SPI_MODE_CFG); val &= ~S3C64XX_SPI_MODE_4BURST; - val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF); val |= (S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF); writel(val, regs + S3C64XX_SPI_MODE_CFG); From ff690e75d64b0ca119adbfc3bd0b444bc1d0a1c5 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 11:15:13 +0000 Subject: [PATCH 076/122] spi: dt-bindings: samsung: add google,gs101-spi compatible Add "google,gs101-spi" dedicated compatible for representing SPI of Google GS101 SoC. Reviewed-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski Reviewed-by: Peter Griffin Acked-by: Andi Shyti Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207111516.2563218-2-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/samsung,spi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml index f71099852653..2f0a0835ecfb 100644 --- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -17,6 +17,7 @@ properties: compatible: oneOf: - enum: + - google,gs101-spi - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450 - samsung,s3c6410-spi - samsung,s5pv210-spi # for S5PV210 and S5PC110 From 80d3204a3b1dbef570ed29d4d375e4d6922da82d Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 11:15:14 +0000 Subject: [PATCH 077/122] spi: s3c64xx: prepare for a different flavor of iowrite rep There are SoCs (gs101) that allow only 32 bit register accesses. As the requirement is rare enough, for those SoCs we'll open code in the driver some s3c64xx_iowrite{8,16}_32_rep() accessors. Prepare for such addition. Suggested-by: Sam Protsenko Signed-off-by: Tudor Ambarus Reviewed-by: Sam Protsenko Link: https://lore.kernel.org/r/20240207111516.2563218-3-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7f7eb8f742e4..eb79c6e4f509 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -414,6 +414,26 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, } +static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd, + struct spi_transfer *xfer) +{ + void __iomem *addr = sdd->regs + S3C64XX_SPI_TX_DATA; + const void *buf = xfer->tx_buf; + unsigned int len = xfer->len; + + switch (sdd->cur_bpw) { + case 32: + iowrite32_rep(addr, buf, len / 4); + break; + case 16: + iowrite16_rep(addr, buf, len / 2); + break; + default: + iowrite8_rep(addr, buf, len); + break; + } +} + static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer, int dma_mode) { @@ -447,20 +467,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; ret = prepare_dma(&sdd->tx_dma, &xfer->tx_sg); } else { - switch (sdd->cur_bpw) { - case 32: - iowrite32_rep(regs + S3C64XX_SPI_TX_DATA, - xfer->tx_buf, xfer->len / 4); - break; - case 16: - iowrite16_rep(regs + S3C64XX_SPI_TX_DATA, - xfer->tx_buf, xfer->len / 2); - break; - default: - iowrite8_rep(regs + S3C64XX_SPI_TX_DATA, - xfer->tx_buf, xfer->len); - break; - } + s3c64xx_iowrite_rep(sdd, xfer); } } From b7bafb9f54fc4609ff84ecd633f918f6f973f471 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 11:15:15 +0000 Subject: [PATCH 078/122] spi: s3c64xx: add s3c64xx_iowrite{8,16}_32_rep accessors Allow SoCs that require 32 bits register accesses to write data in chunks of 8 or 16 bits. One SoC that requires 32 bit register accesses is the google gs101. The operation is rare, thus open code it in the driver rather than making it generic (through asm-generic/io.h). Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207111516.2563218-4-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index eb79c6e4f509..014fcc933c90 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -142,6 +142,7 @@ struct s3c64xx_spi_dma_data { * prescaler unit. * @clk_ioclk: True if clock is present on this device * @has_loopback: True if loopback mode can be supported + * @use_32bit_io: True if the SoC allows only 32-bit register accesses. * * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but * differ in some aspects such as the size of the fifo and spi bus clock @@ -158,6 +159,7 @@ struct s3c64xx_spi_port_config { bool clk_from_cmu; bool clk_ioclk; bool has_loopback; + bool use_32bit_io; }; /** @@ -414,6 +416,30 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, } +static void s3c64xx_iowrite8_32_rep(volatile void __iomem *addr, + const void *buffer, unsigned int count) +{ + if (count) { + const u8 *buf = buffer; + + do { + __raw_writel(*buf++, addr); + } while (--count); + } +} + +static void s3c64xx_iowrite16_32_rep(volatile void __iomem *addr, + const void *buffer, unsigned int count) +{ + if (count) { + const u16 *buf = buffer; + + do { + __raw_writel(*buf++, addr); + } while (--count); + } +} + static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer) { @@ -426,10 +452,16 @@ static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd, iowrite32_rep(addr, buf, len / 4); break; case 16: - iowrite16_rep(addr, buf, len / 2); + if (sdd->port_conf->use_32bit_io) + s3c64xx_iowrite16_32_rep(addr, buf, len / 2); + else + iowrite16_rep(addr, buf, len / 2); break; default: - iowrite8_rep(addr, buf, len); + if (sdd->port_conf->use_32bit_io) + s3c64xx_iowrite8_32_rep(addr, buf, len); + else + iowrite8_rep(addr, buf, len); break; } } From e010c04958604edd7034913c5348f537852449bc Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 7 Feb 2024 11:15:16 +0000 Subject: [PATCH 079/122] spi: s3c64xx: add support for google,gs101-spi Add support for GS101 SPI. GS101 integrates 16 SPI nodes, all with 64 bytes FIFOs. GS101 allows just 32 bit register accesses, otherwise a Serror Interrupt is raised. Do the write reg accesses in 32 bits. Reviewed-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240207111516.2563218-5-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 014fcc933c90..7ab3f3c2e9aa 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -17,7 +17,7 @@ #include -#define MAX_SPI_PORTS 12 +#define MAX_SPI_PORTS 16 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) #define AUTOSUSPEND_TIMEOUT 2000 @@ -1534,6 +1534,19 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; +static const struct s3c64xx_spi_port_config gs101_spi_port_config = { + .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .clk_div = 4, + .high_speed = true, + .clk_from_cmu = true, + .has_loopback = true, + .use_32bit_io = true, + .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, +}; + static const struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", @@ -1546,6 +1559,9 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = { }; static const struct of_device_id s3c64xx_spi_dt_match[] = { + { .compatible = "google,gs101-spi", + .data = &gs101_spi_port_config, + }, { .compatible = "samsung,s3c2443-spi", .data = (void *)&s3c2443_spi_port_config, }, From 3e7cfd6ad29a7483ce3addebb4fba87d6409c71c Mon Sep 17 00:00:00 2001 From: Thangaraj Samynathan Date: Wed, 7 Feb 2024 13:36:20 +0530 Subject: [PATCH 080/122] spi: mchp-pci1xxxx: Add support for DMA in SPI In PCI1xxxx C0, support for DMA in PCIe endpoint is added to enhance the SPI performance. With this support, the performance is improved from 6Mbps to 17Mbps with 20Mhz clock. - DMA Supports two Channels, 0 and 1 - SPI Instance 0 uses chan 0 and SPI Instance 1 uses chan 1 - DMA can be used only if SPI is mapped to PF0 in the multi function endpoint and the MSI interrupt is supported - MSI interrupt of one of the SPI instance is assigned to the DMA and both channels 0 and 1 share the same irq, the MSI address and MSI Data of the irq is obtained and stored in DMA registers to generate interrupt Signed-off-by: Thangaraj Samynathan Link: https://lore.kernel.org/r/20240207080621.30742-2-thangaraj.s@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-pci1xxxx.c | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index 5b2d3e4e21b7..85a6068b244d 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -5,7 +5,12 @@ // Kumaravel Thiagarajan +#include +#include +#include #include +#include +#include #include #include #include @@ -32,8 +37,33 @@ #define SPI_MST_CTL_MODE_SEL (BIT(2)) #define SPI_MST_CTL_GO (BIT(0)) +#define SPI_SYSTEM_ADDR_BASE (0x2000) #define SPI_MST1_ADDR_BASE (0x800) +#define DEV_REV_REG (SPI_SYSTEM_ADDR_BASE + 0x00) +#define SPI_SYSLOCK_REG (SPI_SYSTEM_ADDR_BASE + 0xA0) +#define SPI_CONFIG_PERI_ENABLE_REG (SPI_SYSTEM_ADDR_BASE + 0x108) + +#define SPI_PERI_ENBLE_PF_MASK (GENMASK(17, 16)) +#define DEV_REV_MASK (GENMASK(7, 0)) + +#define SPI_SYSLOCK BIT(4) + +/* DMA Related Registers */ +#define SPI_DMA_ADDR_BASE (0x1000) +#define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C) +#define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C) +#define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60) +#define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64) +#define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68) +#define SPI_DMA_INTR_IMWR_WABORT_HIGH (SPI_DMA_ADDR_BASE + 0x6C) +#define SPI_DMA_INTR_WR_IMWR_DATA (SPI_DMA_ADDR_BASE + 0x70) +#define SPI_DMA_INTR_IMWR_RDONE_LOW (SPI_DMA_ADDR_BASE + 0xCC) +#define SPI_DMA_INTR_IMWR_RDONE_HIGH (SPI_DMA_ADDR_BASE + 0xD0) +#define SPI_DMA_INTR_IMWR_RABORT_LOW (SPI_DMA_ADDR_BASE + 0xD4) +#define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8) +#define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC) + /* x refers to SPI Host Controller HW instance id in the below macros - 0 or 1 */ #define SPI_MST_CMD_BUF_OFFSET(x) (((x) * SPI_MST1_ADDR_BASE) + 0x00) @@ -50,6 +80,8 @@ #define SPI_MAX_DATA_LEN 320 #define PCI1XXXX_SPI_TIMEOUT (msecs_to_jiffies(100)) +#define SYSLOCK_RETRY_CNT (1000) +#define SPI_DMA_ENGINE_EN (0x1) #define SPI_INTR BIT(8) #define SPI_FORCE_CE BIT(4) @@ -76,7 +108,10 @@ struct pci1xxxx_spi_internal { struct pci1xxxx_spi { struct pci_dev *dev; u8 total_hw_instances; + u8 dev_rev; void __iomem *reg_base; + void __iomem *dma_offset_bar; + bool can_dma; struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances); }; @@ -106,6 +141,112 @@ static const struct pci_device_id pci1xxxx_spi_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, pci1xxxx_spi_pci_id_table); +static int pci1xxxx_set_sys_lock(struct pci1xxxx_spi *par) +{ + writel(SPI_SYSLOCK, par->reg_base + SPI_SYSLOCK_REG); + return readl(par->reg_base + SPI_SYSLOCK_REG); +} + +static int pci1xxxx_acquire_sys_lock(struct pci1xxxx_spi *par) +{ + u32 regval; + + return readx_poll_timeout(pci1xxxx_set_sys_lock, par, regval, + (regval & SPI_SYSLOCK), 100, + SYSLOCK_RETRY_CNT * 100); +} + +static void pci1xxxx_release_sys_lock(struct pci1xxxx_spi *par) +{ + writel(0x0, par->reg_base + SPI_SYSLOCK_REG); +} + +static int pci1xxxx_check_spi_can_dma(struct pci1xxxx_spi *spi_bus, int irq) +{ + struct pci_dev *pdev = spi_bus->dev; + u32 pf_num; + u32 regval; + int ret; + + /* + * DEV REV Registers is a system register, HW Syslock bit + * should be acquired before accessing the register + */ + ret = pci1xxxx_acquire_sys_lock(spi_bus); + if (ret) { + dev_err(&pdev->dev, "Error failed to acquire syslock\n"); + return ret; + } + + regval = readl(spi_bus->reg_base + DEV_REV_REG); + spi_bus->dev_rev = regval & DEV_REV_MASK; + if (spi_bus->dev_rev >= 0xC0) { + regval = readl(spi_bus->reg_base + + SPI_CONFIG_PERI_ENABLE_REG); + pf_num = regval & SPI_PERI_ENBLE_PF_MASK; + } + + pci1xxxx_release_sys_lock(spi_bus); + + /* + * DMA is supported only from C0 and SPI can use DMA only if + * it is mapped to PF0 + */ + if (spi_bus->dev_rev < 0xC0 || pf_num) + return -EOPNOTSUPP; + + /* + * DMA Supported only with MSI Interrupts + * One of the SPI instance's MSI vector address and data + * is used for DMA Interrupt + */ + if (!irq_get_msi_desc(irq)) { + dev_warn(&pdev->dev, "Error MSI Interrupt not supported, will operate in PIO mode\n"); + return -EOPNOTSUPP; + } + + spi_bus->dma_offset_bar = pcim_iomap(pdev, 2, pci_resource_len(pdev, 2)); + if (!spi_bus->dma_offset_bar) { + dev_warn(&pdev->dev, "Error failed to map dma bar, will operate in PIO mode\n"); + return -EOPNOTSUPP; + } + + if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { + dev_warn(&pdev->dev, "Error failed to set DMA mask, will operate in PIO mode\n"); + pcim_iounmap(pdev, spi_bus->dma_offset_bar); + spi_bus->dma_offset_bar = NULL; + return -EOPNOTSUPP; + } + + return 0; +} + +static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int irq) +{ + struct msi_msg msi; + int ret; + + ret = pci1xxxx_check_spi_can_dma(spi_bus, irq); + if (ret) + return ret; + + get_cached_msi_msg(irq, &msi); + writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); + writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN); + writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WDONE_HIGH); + writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WABORT_HIGH); + writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RDONE_HIGH); + writel(msi.address_hi, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RABORT_HIGH); + writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WDONE_LOW); + writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_WABORT_LOW); + writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RDONE_LOW); + writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RABORT_LOW); + writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_WR_IMWR_DATA); + writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_RD_IMWR_DATA); + spi_bus->can_dma = true; + return 0; +} + static void pci1xxxx_spi_set_cs(struct spi_device *spi, bool enable) { struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi->controller); @@ -324,6 +465,10 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * goto error; } + ret = pci1xxxx_spi_dma_init(spi_bus, spi_sub_ptr->irq); + if (ret && ret != -EOPNOTSUPP) + return ret; + /* This register is only applicable for 1st instance */ regval = readl(spi_bus->reg_base + SPI_PCI_CTRL_REG_OFFSET(0)); if (!only_sec_inst) From 9538edeb72c989a4b90964ae4bba107eaf21a791 Mon Sep 17 00:00:00 2001 From: Thangaraj Samynathan Date: Wed, 7 Feb 2024 13:36:21 +0530 Subject: [PATCH 081/122] spi: mchp-pci1xxxx: DMA support for copying data to and from SPI Buf pci1xxxx_spi_transfer_with_dma adds DMA support to copy the data between host cpu buffer and SPI IO Buffer. On DMA Completion interrupt, the next SPI transaction is initiated in isr. Helper functions pci1xxxx_spi_setup, pci1xxxx_spi_setup_dma_from_io, pci1xxxx_spi_setup_dma_to_io and pci1xxxx_start_spi_xfer are added for setting up spi, setting up dma operations, and to start spi transfer respectively. In the existing implementation, codes are replaced with helper functions wherever applicable. Signed-off-by: Thangaraj Samynathan Link: https://lore.kernel.org/r/20240207080621.30742-3-thangaraj.s@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-pci1xxxx.c | 369 ++++++++++++++++++++++++++++++++++--- 1 file changed, 340 insertions(+), 29 deletions(-) diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index 85a6068b244d..a99db6163aec 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -5,6 +5,7 @@ // Kumaravel Thiagarajan +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,6 +39,7 @@ #define SPI_MST_CTL_MODE_SEL (BIT(2)) #define SPI_MST_CTL_GO (BIT(0)) +#define SPI_PERI_ADDR_BASE (0x160000) #define SPI_SYSTEM_ADDR_BASE (0x2000) #define SPI_MST1_ADDR_BASE (0x800) @@ -48,22 +51,56 @@ #define DEV_REV_MASK (GENMASK(7, 0)) #define SPI_SYSLOCK BIT(4) +#define SPI0 (0) +#define SPI1 (1) /* DMA Related Registers */ #define SPI_DMA_ADDR_BASE (0x1000) #define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C) +#define SPI_DMA_WR_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x10) #define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C) +#define SPI_DMA_RD_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x30) +#define SPI_DMA_INTR_WR_STS (SPI_DMA_ADDR_BASE + 0x4C) +#define SPI_DMA_WR_INT_MASK (SPI_DMA_ADDR_BASE + 0x54) +#define SPI_DMA_INTR_WR_CLR (SPI_DMA_ADDR_BASE + 0x58) +#define SPI_DMA_ERR_WR_STS (SPI_DMA_ADDR_BASE + 0x5C) #define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60) #define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64) #define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68) #define SPI_DMA_INTR_IMWR_WABORT_HIGH (SPI_DMA_ADDR_BASE + 0x6C) #define SPI_DMA_INTR_WR_IMWR_DATA (SPI_DMA_ADDR_BASE + 0x70) +#define SPI_DMA_INTR_RD_STS (SPI_DMA_ADDR_BASE + 0xA0) +#define SPI_DMA_RD_INT_MASK (SPI_DMA_ADDR_BASE + 0xA8) +#define SPI_DMA_INTR_RD_CLR (SPI_DMA_ADDR_BASE + 0xAC) +#define SPI_DMA_ERR_RD_STS (SPI_DMA_ADDR_BASE + 0xB8) #define SPI_DMA_INTR_IMWR_RDONE_LOW (SPI_DMA_ADDR_BASE + 0xCC) #define SPI_DMA_INTR_IMWR_RDONE_HIGH (SPI_DMA_ADDR_BASE + 0xD0) #define SPI_DMA_INTR_IMWR_RABORT_LOW (SPI_DMA_ADDR_BASE + 0xD4) #define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8) #define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC) +#define SPI_DMA_CH0_WR_BASE (SPI_DMA_ADDR_BASE + 0x200) +#define SPI_DMA_CH0_RD_BASE (SPI_DMA_ADDR_BASE + 0x300) +#define SPI_DMA_CH1_WR_BASE (SPI_DMA_ADDR_BASE + 0x400) +#define SPI_DMA_CH1_RD_BASE (SPI_DMA_ADDR_BASE + 0x500) + +#define SPI_DMA_CH_CTL1_OFFSET (0x00) +#define SPI_DMA_CH_XFER_LEN_OFFSET (0x08) +#define SPI_DMA_CH_SAR_LO_OFFSET (0x0C) +#define SPI_DMA_CH_SAR_HI_OFFSET (0x10) +#define SPI_DMA_CH_DAR_LO_OFFSET (0x14) +#define SPI_DMA_CH_DAR_HI_OFFSET (0x18) + +#define SPI_DMA_CH0_DONE_INT BIT(0) +#define SPI_DMA_CH1_DONE_INT BIT(1) +#define SPI_DMA_CH0_ABORT_INT BIT(16) +#define SPI_DMA_CH1_ABORT_INT BIT(17) +#define SPI_DMA_DONE_INT_MASK (SPI_DMA_CH0_DONE_INT | SPI_DMA_CH1_DONE_INT) +#define SPI_DMA_ABORT_INT_MASK (SPI_DMA_CH0_ABORT_INT | SPI_DMA_CH1_ABORT_INT) +#define DMA_CH_CONTROL_LIE BIT(3) +#define DMA_CH_CONTROL_RIE BIT(4) +#define DMA_INTR_EN (DMA_CH_CONTROL_RIE | DMA_CH_CONTROL_LIE) + /* x refers to SPI Host Controller HW instance id in the below macros - 0 or 1 */ #define SPI_MST_CMD_BUF_OFFSET(x) (((x) * SPI_MST1_ADDR_BASE) + 0x00) @@ -82,6 +119,7 @@ #define PCI1XXXX_SPI_TIMEOUT (msecs_to_jiffies(100)) #define SYSLOCK_RETRY_CNT (1000) #define SPI_DMA_ENGINE_EN (0x1) +#define SPI_DMA_ENGINE_DIS (0x0) #define SPI_INTR BIT(8) #define SPI_FORCE_CE BIT(4) @@ -94,11 +132,21 @@ struct pci1xxxx_spi_internal { u8 hw_inst; - bool spi_xfer_in_progress; + u8 clkdiv; int irq; + int mode; + bool spi_xfer_in_progress; + void *rx_buf; + bool dma_aborted_rd; + u32 bytes_recvd; + u32 tx_sgl_len; + u32 rx_sgl_len; + struct scatterlist *tx_sgl, *rx_sgl; + bool dma_aborted_wr; struct completion spi_xfer_done; struct spi_controller *spi_host; struct pci1xxxx_spi *parent; + struct spi_transfer *xfer; struct { unsigned int dev_sel : 3; unsigned int msi_vector_sel : 1; @@ -111,6 +159,8 @@ struct pci1xxxx_spi { u8 dev_rev; void __iomem *reg_base; void __iomem *dma_offset_bar; + /* lock to safely access the DMA registers in isr */ + spinlock_t dma_reg_lock; bool can_dma; struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances); }; @@ -230,6 +280,7 @@ static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int irq) if (ret) return ret; + spin_lock_init(&spi_bus->dma_reg_lock); get_cached_msi_msg(irq, &msi); writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); writel(SPI_DMA_ENGINE_EN, spi_bus->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN); @@ -243,6 +294,7 @@ static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int irq) writel(msi.address_lo, spi_bus->dma_offset_bar + SPI_DMA_INTR_IMWR_RABORT_LOW); writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_WR_IMWR_DATA); writel(msi.data, spi_bus->dma_offset_bar + SPI_DMA_INTR_RD_IMWR_DATA); + dma_set_max_seg_size(&spi_bus->dev->dev, PCI1XXXX_SPI_BUFFER_SIZE); spi_bus->can_dma = true; return 0; } @@ -287,12 +339,79 @@ static u8 pci1xxxx_get_clock_div(u32 hz) return val; } -static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr, - struct spi_device *spi, struct spi_transfer *xfer) +static void pci1xxxx_spi_setup_dma_to_io(struct pci1xxxx_spi_internal *p, + dma_addr_t dma_addr, u32 len) +{ + void __iomem *base; + + if (!p->hw_inst) + base = p->parent->dma_offset_bar + SPI_DMA_CH0_RD_BASE; + else + base = p->parent->dma_offset_bar + SPI_DMA_CH1_RD_BASE; + + writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET); + writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET); + writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_SAR_LO_OFFSET); + writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_SAR_HI_OFFSET); + /* Updated SPI Command Registers */ + writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_DAR_LO_OFFSET); + writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_CMD_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_DAR_HI_OFFSET); +} + +static void pci1xxxx_spi_setup_dma_from_io(struct pci1xxxx_spi_internal *p, + dma_addr_t dma_addr, u32 len) +{ + void *base; + + if (!p->hw_inst) + base = p->parent->dma_offset_bar + SPI_DMA_CH0_WR_BASE; + else + base = p->parent->dma_offset_bar + SPI_DMA_CH1_WR_BASE; + + writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET); + writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET); + writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_DAR_LO_OFFSET); + writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_DAR_HI_OFFSET); + writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_SAR_LO_OFFSET); + writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_SAR_HI_OFFSET); +} + +static void pci1xxxx_spi_setup(struct pci1xxxx_spi *par, u8 hw_inst, u32 mode, + u8 clkdiv, u32 len) +{ + u32 regval; + + regval = readl(par->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst)); + regval &= ~(SPI_MST_CTL_MODE_SEL | SPI_MST_CTL_CMD_LEN_MASK | + SPI_MST_CTL_SPEED_MASK); + + if (mode == SPI_MODE_3) + regval |= SPI_MST_CTL_MODE_SEL; + + regval |= FIELD_PREP(SPI_MST_CTL_CMD_LEN_MASK, len); + regval |= FIELD_PREP(SPI_MST_CTL_SPEED_MASK, clkdiv); + writel(regval, par->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst)); +} + +static void pci1xxxx_start_spi_xfer(struct pci1xxxx_spi_internal *p, u8 hw_inst) +{ + u32 regval; + + regval = readl(p->parent->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst)); + regval |= SPI_MST_CTL_GO; + writel(regval, p->parent->reg_base + SPI_MST_CTL_REG_OFFSET(hw_inst)); +} + +static int pci1xxxx_spi_transfer_with_io(struct spi_controller *spi_ctlr, + struct spi_device *spi, struct spi_transfer *xfer) { struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr); - int mode, len, loop_iter, transfer_len; struct pci1xxxx_spi *par = p->parent; + int len, loop_iter, transfer_len; unsigned long bytes_transfered; unsigned long bytes_recvd; unsigned long loop_count; @@ -302,7 +421,7 @@ static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr, u8 clkdiv; p->spi_xfer_in_progress = true; - mode = spi->mode; + p->bytes_recvd = 0; clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz); tx_buf = xfer->tx_buf; rx_buf = xfer->rx_buf; @@ -327,26 +446,8 @@ static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr, memcpy_toio(par->reg_base + SPI_MST_CMD_BUF_OFFSET(p->hw_inst), &tx_buf[bytes_transfered], len); bytes_transfered += len; - regval = readl(par->reg_base + - SPI_MST_CTL_REG_OFFSET(p->hw_inst)); - regval &= ~(SPI_MST_CTL_MODE_SEL | SPI_MST_CTL_CMD_LEN_MASK | - SPI_MST_CTL_SPEED_MASK); - - if (mode == SPI_MODE_3) - regval |= SPI_MST_CTL_MODE_SEL; - else - regval &= ~SPI_MST_CTL_MODE_SEL; - - regval |= (clkdiv << 5); - regval &= ~SPI_MST_CTL_CMD_LEN_MASK; - regval |= (len << 8); - writel(regval, par->reg_base + - SPI_MST_CTL_REG_OFFSET(p->hw_inst)); - regval = readl(par->reg_base + - SPI_MST_CTL_REG_OFFSET(p->hw_inst)); - regval |= SPI_MST_CTL_GO; - writel(regval, par->reg_base + - SPI_MST_CTL_REG_OFFSET(p->hw_inst)); + pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len); + pci1xxxx_start_spi_xfer(p, p->hw_inst); /* Wait for DMA_TERM interrupt */ result = wait_for_completion_timeout(&p->spi_xfer_done, @@ -366,7 +467,113 @@ static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr, return 0; } -static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) +static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr); + struct pci1xxxx_spi *par = p->parent; + dma_addr_t rx_dma_addr = 0; + dma_addr_t tx_dma_addr = 0; + int ret = 0; + u32 regval; + + p->spi_xfer_in_progress = true; + p->tx_sgl = xfer->tx_sg.sgl; + p->rx_sgl = xfer->rx_sg.sgl; + p->rx_buf = xfer->rx_buf; + regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + writel(regval, par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + + if (!xfer->tx_buf || !p->tx_sgl) { + ret = -EINVAL; + goto error; + } + p->xfer = xfer; + p->mode = spi->mode; + p->clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz); + p->bytes_recvd = 0; + p->rx_buf = xfer->rx_buf; + regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + writel(regval, par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + + tx_dma_addr = sg_dma_address(p->tx_sgl); + rx_dma_addr = sg_dma_address(p->rx_sgl); + p->tx_sgl_len = sg_dma_len(p->tx_sgl); + p->rx_sgl_len = sg_dma_len(p->rx_sgl); + pci1xxxx_spi_setup(par, p->hw_inst, p->mode, p->clkdiv, p->tx_sgl_len); + pci1xxxx_spi_setup_dma_to_io(p, (tx_dma_addr), p->tx_sgl_len); + if (rx_dma_addr) + pci1xxxx_spi_setup_dma_from_io(p, rx_dma_addr, p->rx_sgl_len); + writel(p->hw_inst, par->dma_offset_bar + SPI_DMA_RD_DOORBELL_REG); + + reinit_completion(&p->spi_xfer_done); + /* Wait for DMA_TERM interrupt */ + ret = wait_for_completion_timeout(&p->spi_xfer_done, PCI1XXXX_SPI_TIMEOUT); + if (!ret) { + ret = -ETIMEDOUT; + if (p->dma_aborted_rd) { + writel(SPI_DMA_ENGINE_DIS, + par->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN); + /* + * DMA ENGINE reset takes time if any TLP + * completeion in progress, should wait + * till DMA Engine reset is completed. + */ + ret = readl_poll_timeout(par->dma_offset_bar + + SPI_DMA_GLOBAL_RD_ENGINE_EN, regval, + (regval == 0x0), 0, USEC_PER_MSEC); + if (ret) { + ret = -ECANCELED; + goto error; + } + writel(SPI_DMA_ENGINE_EN, + par->dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN); + p->dma_aborted_rd = false; + ret = -ECANCELED; + } + if (p->dma_aborted_wr) { + writel(SPI_DMA_ENGINE_DIS, + par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); + + /* + * DMA ENGINE reset takes time if any TLP + * completeion in progress, should wait + * till DMA Engine reset is completed. + */ + ret = readl_poll_timeout(par->dma_offset_bar + + SPI_DMA_GLOBAL_WR_ENGINE_EN, regval, + (regval == 0x0), 0, USEC_PER_MSEC); + if (ret) { + ret = -ECANCELED; + goto error; + } + + writel(SPI_DMA_ENGINE_EN, + par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); + p->dma_aborted_wr = false; + ret = -ECANCELED; + } + goto error; + } + ret = 0; + +error: + p->spi_xfer_in_progress = false; + + return ret; +} + +static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr, + struct spi_device *spi, struct spi_transfer *xfer) +{ + if (spi_ctlr->can_dma(spi_ctlr, spi, xfer) && spi_ctlr->cur_msg_mapped) + return pci1xxxx_spi_transfer_with_dma(spi_ctlr, spi, xfer); + else + return pci1xxxx_spi_transfer_with_io(spi_ctlr, spi, xfer); +} + +static irqreturn_t pci1xxxx_spi_isr_io(int irq, void *dev) { struct pci1xxxx_spi_internal *p = dev; irqreturn_t spi_int_fired = IRQ_NONE; @@ -376,15 +583,117 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) regval = readl(p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); if (regval & SPI_INTR) { /* Clear xfer_done */ - complete(&p->spi_xfer_done); + if (p->parent->can_dma && p->rx_buf) + writel(p->hw_inst, p->parent->dma_offset_bar + + SPI_DMA_WR_DOORBELL_REG); + else + complete(&p->parent->spi_int[p->hw_inst]->spi_xfer_done); spi_int_fired = IRQ_HANDLED; } - writel(regval, p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); - return spi_int_fired; } +static void pci1xxxx_spi_setup_next_dma_transfer(struct pci1xxxx_spi_internal *p) +{ + dma_addr_t tx_dma_addr = 0; + dma_addr_t rx_dma_addr = 0; + u32 prev_len; + + p->tx_sgl = sg_next(p->tx_sgl); + if (p->rx_sgl) + p->rx_sgl = sg_next(p->rx_sgl); + if (!p->tx_sgl) { + /* Clear xfer_done */ + complete(&p->spi_xfer_done); + } else { + tx_dma_addr = sg_dma_address(p->tx_sgl); + prev_len = p->tx_sgl_len; + p->tx_sgl_len = sg_dma_len(p->tx_sgl); + if (prev_len != p->tx_sgl_len) + pci1xxxx_spi_setup(p->parent, + p->hw_inst, p->mode, p->clkdiv, p->tx_sgl_len); + pci1xxxx_spi_setup_dma_to_io(p, tx_dma_addr, p->tx_sgl_len); + if (p->rx_sgl) { + rx_dma_addr = sg_dma_address(p->rx_sgl); + p->rx_sgl_len = sg_dma_len(p->rx_sgl); + pci1xxxx_spi_setup_dma_from_io(p, rx_dma_addr, p->rx_sgl_len); + } + writel(p->hw_inst, p->parent->dma_offset_bar + SPI_DMA_RD_DOORBELL_REG); + } +} + +static irqreturn_t pci1xxxx_spi_isr_dma(int irq, void *dev) +{ + struct pci1xxxx_spi_internal *p = dev; + irqreturn_t spi_int_fired = IRQ_NONE; + unsigned long flags; + u32 regval; + + spin_lock_irqsave(&p->parent->dma_reg_lock, flags); + /* Clear the DMA RD INT and start spi xfer*/ + regval = readl(p->parent->dma_offset_bar + SPI_DMA_INTR_RD_STS); + if (regval & SPI_DMA_DONE_INT_MASK) { + if (regval & SPI_DMA_CH0_DONE_INT) + pci1xxxx_start_spi_xfer(p, SPI0); + if (regval & SPI_DMA_CH1_DONE_INT) + pci1xxxx_start_spi_xfer(p, SPI1); + spi_int_fired = IRQ_HANDLED; + } + if (regval & SPI_DMA_ABORT_INT_MASK) { + p->dma_aborted_rd = true; + spi_int_fired = IRQ_HANDLED; + } + writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_RD_CLR); + + /* Clear the DMA WR INT */ + regval = readl(p->parent->dma_offset_bar + SPI_DMA_INTR_WR_STS); + if (regval & SPI_DMA_DONE_INT_MASK) { + if (regval & SPI_DMA_CH0_DONE_INT) + pci1xxxx_spi_setup_next_dma_transfer(p->parent->spi_int[SPI0]); + + if (regval & SPI_DMA_CH1_DONE_INT) + pci1xxxx_spi_setup_next_dma_transfer(p->parent->spi_int[SPI1]); + + spi_int_fired = IRQ_HANDLED; + } + if (regval & SPI_DMA_ABORT_INT_MASK) { + p->dma_aborted_wr = true; + spi_int_fired = IRQ_HANDLED; + } + writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_WR_CLR); + spin_unlock_irqrestore(&p->parent->dma_reg_lock, flags); + + /* Clear the SPI GO_BIT Interrupt */ + regval = readl(p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + if (regval & SPI_INTR) { + writel(p->hw_inst, p->parent->dma_offset_bar + SPI_DMA_WR_DOORBELL_REG); + spi_int_fired = IRQ_HANDLED; + } + writel(regval, p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); + return spi_int_fired; +} + +static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) +{ + struct pci1xxxx_spi_internal *p = dev; + + if (p->spi_host->can_dma(p->spi_host, NULL, p->xfer)) + return pci1xxxx_spi_isr_dma(irq, dev); + else + return pci1xxxx_spi_isr_io(irq, dev); +} + +static bool pci1xxxx_spi_can_dma(struct spi_controller *host, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(host); + struct pci1xxxx_spi *par = p->parent; + + return par->can_dma; +} + static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { u8 hw_inst_cnt, iter, start, only_sec_inst; @@ -505,7 +814,9 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * spi_host->num_chipselect = SPI_CHIP_SEL_COUNT; spi_host->mode_bits = SPI_MODE_0 | SPI_MODE_3 | SPI_RX_DUAL | SPI_TX_DUAL | SPI_LOOP; + spi_host->can_dma = pci1xxxx_spi_can_dma; spi_host->transfer_one = pci1xxxx_spi_transfer_one; + spi_host->set_cs = pci1xxxx_spi_set_cs; spi_host->bits_per_word_mask = SPI_BPW_MASK(8); spi_host->max_speed_hz = PCI1XXXX_SPI_MAX_CLOCK_HZ; From d1ff85fdf0b8f63a6e042ae7559c630f9b1c50e2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 8 Feb 2024 21:21:52 +0100 Subject: [PATCH 082/122] spi: pl022: Use typedef for dma_filter_fn Use existing typedef for dma_filter_fn to avoid duplicating type definition. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240208202154.630336-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- include/linux/amba/pl022.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index 9bf58aac0df2..e08488df6d28 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h @@ -16,6 +16,7 @@ #ifndef _SSP_PL022_H #define _SSP_PL022_H +#include #include /** @@ -235,7 +236,7 @@ struct dma_chan; struct pl022_ssp_controller { u16 bus_id; u8 enable_dma:1; - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); + dma_filter_fn dma_filter; void *dma_rx_param; void *dma_tx_param; int autosuspend_delay; From c42d9bead493854507e1a180942ebe33c9180598 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 8 Feb 2024 21:21:53 +0100 Subject: [PATCH 083/122] spi: pl022: Add missing dma_filter field kerneldoc Add kerneldoc for dma_filter field in struct pl022_ssp_controller. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240208202154.630336-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- include/linux/amba/pl022.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index e08488df6d28..d7b07d0311e1 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h @@ -225,6 +225,7 @@ struct dma_chan; * struct pl022_ssp_master - device.platform_data for SPI controller devices. * @bus_id: identifier for this bus * @enable_dma: if true enables DMA driven transfers. + * @dma_filter: callback filter for dma_request_channel. * @dma_rx_param: parameter to locate an RX DMA channel. * @dma_tx_param: parameter to locate a TX DMA channel. * @autosuspend_delay: delay in ms following transfer completion before the From 3d4dd10b376e1b8b6d0409f7e7b752f9baa51c24 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 8 Feb 2024 21:21:54 +0100 Subject: [PATCH 084/122] spi: pxa2xx: Use typedef for dma_filter_fn Use existing typedef for dma_filter_fn to avoid duplicating type definition. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240208202154.630336-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- include/linux/spi/pxa2xx_spi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index 0916cb9bcb0a..ca2cd4e30ead 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -5,6 +5,7 @@ #ifndef __LINUX_SPI_PXA2XX_SPI_H #define __LINUX_SPI_PXA2XX_SPI_H +#include #include #include @@ -22,7 +23,7 @@ struct pxa2xx_spi_controller { bool is_target; /* DMA engine specific config */ - bool (*dma_filter)(struct dma_chan *chan, void *param); + dma_filter_fn dma_filter; void *tx_param; void *rx_param; From fc5b764bef24d0cf722deb5c1a44948cd17d4afe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 9 Feb 2024 18:54:23 +0200 Subject: [PATCH 085/122] spi: gpio: Follow renaming of SPI "master" to "controller" In commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") some functions and struct members were renamed. Recent work by Uwe completes this renaming. However, there are plenty of leftovers in the comments and in-code documentation. Update them as well. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240209165423.2305493-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/linux/spi/spi_gpio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/spi/spi_gpio.h b/include/linux/spi/spi_gpio.h index 9e7e83d8645b..5f0e1407917a 100644 --- a/include/linux/spi/spi_gpio.h +++ b/include/linux/spi/spi_gpio.h @@ -15,8 +15,8 @@ */ /** - * struct spi_gpio_platform_data - parameter for bitbanged SPI master - * @num_chipselect: how many slaves to allow + * struct spi_gpio_platform_data - parameter for bitbanged SPI host controller + * @num_chipselect: how many target devices to allow */ struct spi_gpio_platform_data { u16 num_chipselect; From df20385302eb01cb610b9edc71611a63d1683923 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 13 Feb 2024 21:07:45 +0300 Subject: [PATCH 086/122] spi: mchp-pci1xxxx: release resources on error in probe() Call pci_release_regions(pdev) before returning on this error path. Fixes: 3e7cfd6ad29a ("spi: mchp-pci1xxxx: Add support for DMA in SPI") Signed-off-by: Dan Carpenter Link: https://msgid.link/r/efc92197-4023-4bfe-bc63-452e7ed112e8@moroto.mountain Signed-off-by: Mark Brown --- drivers/spi/spi-pci1xxxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index a99db6163aec..969965d7bc98 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -776,7 +776,7 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * ret = pci1xxxx_spi_dma_init(spi_bus, spi_sub_ptr->irq); if (ret && ret != -EOPNOTSUPP) - return ret; + goto error; /* This register is only applicable for 1st instance */ regval = readl(spi_bus->reg_base + SPI_PCI_CTRL_REG_OFFSET(0)); From 125b28b18926e050e770160a5897b81082304f8c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Feb 2024 13:16:03 +0000 Subject: [PATCH 087/122] spi: dw: remove redundant assignment to variable len The variable id len being initialized with a value that is never read, it is being re-assigned later on in a for-loop. The initialization is redundant and can be removed. Cleans up clang scan build warning: drivers/spi/spi-dw-dma.c:580:17: warning: Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len' [deadcode.DeadStores] Signed-off-by: Colin Ian King Acked-by: Serge Semin Link: https://msgid.link/r/20240215131603.2062332-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index 0ecbb6c36e23..f4c209e5f52b 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -577,7 +577,7 @@ static int dw_spi_dma_transfer_one(struct dw_spi *dws, sg_init_table(&tx_tmp, 1); sg_init_table(&rx_tmp, 1); - for (base = 0, len = 0; base < xfer->len; base += len) { + for (base = 0; base < xfer->len; base += len) { /* Fetch next Tx DMA data chunk */ if (!tx_len) { tx_sg = !tx_sg ? &xfer->tx_sg.sgl[0] : sg_next(tx_sg); From 99769a52464d9f4c3b44bf903d08743cd53c49f6 Mon Sep 17 00:00:00 2001 From: Dhruva Gole Date: Thu, 15 Feb 2024 14:24:05 +0530 Subject: [PATCH 088/122] spi: Update the "master/slave" terminology in documentation Update the master/slave terminology wherever possible to adopt usage of the controller/host/target. Some parts have been left untouched because they were sysfs entries and will probably end up being inaccurate if simply replaced here. Signed-off-by: Dhruva Gole Link: https://msgid.link/r/20240215085404.1711976-1-d-gole@ti.com Signed-off-by: Mark Brown --- Documentation/spi/spi-summary.rst | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Documentation/spi/spi-summary.rst b/Documentation/spi/spi-summary.rst index e714472007f1..c8395cf7e4fc 100644 --- a/Documentation/spi/spi-summary.rst +++ b/Documentation/spi/spi-summary.rst @@ -19,14 +19,14 @@ commonly used. Each clock cycle shifts data out and data in; the clock doesn't cycle except when there is a data bit to shift. Not all data bits are used though; not every protocol uses those full duplex capabilities. -SPI hosts use a fourth "chip select" line to activate a given SPI slave +SPI hosts use a fourth "chip select" line to activate a given SPI target device, so those three signal wires may be connected to several chips -in parallel. All SPI slaves support chipselects; they are usually active -low signals, labeled nCSx for slave 'x' (e.g. nCS0). Some devices have +in parallel. All SPI targets support chipselects; they are usually active +low signals, labeled nCSx for target 'x' (e.g. nCS0). Some devices have other signals, often including an interrupt to the host. Unlike serial busses like USB or SMBus, even low level protocols for -SPI slave functions are usually not interoperable between vendors +SPI target functions are usually not interoperable between vendors (except for commodities like SPI memory chips). - SPI may be used for request/response style device protocols, as with @@ -43,8 +43,8 @@ SPI slave functions are usually not interoperable between vendors - Sometimes SPI is used to daisy-chain devices, like shift registers. -In the same way, SPI slaves will only rarely support any kind of automatic -discovery/enumeration protocol. The tree of slave devices accessible from +In the same way, SPI targets will only rarely support any kind of automatic +discovery/enumeration protocol. The tree of target devices accessible from a given SPI host controller will normally be set up manually, with configuration tables. @@ -75,7 +75,7 @@ protocol supported by every MMC or SD memory card. (The older "DataFlash" cards, predating MMC cards but using the same connectors and card shape, support only SPI.) Some PC hardware uses SPI flash for BIOS code. -SPI slave chips range from digital/analog converters used for analog +SPI target chips range from digital/analog converters used for analog sensors and codecs, to memory, to peripherals like USB controllers or Ethernet adapters; and more. @@ -119,7 +119,7 @@ trailing clock edge (CPHA=1), that's SPI mode 1. Note that the clock mode is relevant as soon as the chipselect goes active. So the host must set the clock to inactive before selecting -a slave, and the slave can tell the chosen polarity by sampling the +a target, and the target can tell the chosen polarity by sampling the clock level when its select line goes active. That's why many devices support for example both modes 0 and 3: they don't care about polarity, and always clock data in/out on rising clock edges. @@ -142,13 +142,13 @@ There are two types of SPI driver, here called: Controller drivers ... controllers may be built into System-On-Chip - processors, and often support both Master and Slave roles. + processors, and often support both Controller and target roles. These drivers touch hardware registers and may use DMA. Or they can be PIO bitbangers, needing just GPIO pins. Protocol drivers ... these pass messages through the controller - driver to communicate with a Slave or Master device on the + driver to communicate with a target or Controller device on the other side of an SPI link. So for example one protocol driver might talk to the MTD layer to export @@ -184,17 +184,17 @@ shows up in sysfs in several locations:: MOSI, and MISO. /sys/devices/.../CTLR/slave ... virtual file for (un)registering the - slave device for an SPI slave controller. - Writing the driver name of an SPI slave handler to this file - registers the slave device; writing "(null)" unregisters the slave + target device for an SPI target controller. + Writing the driver name of an SPI target handler to this file + registers the target device; writing "(null)" unregisters the target device. - Reading from this file shows the name of the slave device ("(null)" + Reading from this file shows the name of the target device ("(null)" if not registered). /sys/class/spi_slave/spiB ... symlink to a logical node which could hold - class related state for the SPI slave controller on bus "B". When + class related state for the SPI target controller on bus "B". When registered, a single spiB.* device is present here, possible sharing - the physical SPI bus segment with other SPI slave devices. + the physical SPI bus segment with other SPI target devices. At this time, the only class-specific state is the bus number ("B" in "spiB"), so those /sys/class entries are only useful to quickly identify busses. @@ -270,10 +270,10 @@ same SOC controller is used. For example, on one board SPI might use an external clock, where another derives the SPI clock from current settings of some master clock. -Declare Slave Devices +Declare target Devices ^^^^^^^^^^^^^^^^^^^^^ -The second kind of information is a list of what SPI slave devices exist +The second kind of information is a list of what SPI target devices exist on the target board, often with some board-specific data needed for the driver to work correctly. @@ -469,7 +469,7 @@ routines are available to allocate and zero-initialize an spi_message with several transfers. -How do I write an "SPI Master Controller Driver"? +How do I write an "SPI Controller Driver"? ------------------------------------------------- An SPI controller will probably be registered on the platform_bus; write a driver to bind to the device, whichever bus is involved. @@ -527,7 +527,7 @@ SPI Host Controller Methods Drivers may change the defaults provided by board_info, and then call spi_setup(spi) to invoke this routine. It may sleep. - Unless each SPI slave has its own configuration registers, don't + Unless each SPI target has its own configuration registers, don't change them right away ... otherwise drivers could corrupt I/O that's in progress for other SPI devices. From afd2a4ae296d5e8b13aefb056c1060ddf302a199 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 15 Feb 2024 21:16:37 -0800 Subject: [PATCH 089/122] spi: spi-summary.rst: fix underline length The change to use "target" requires an underline to be extended by one more character to fix a documentation build warning: Documentation/spi/spi-summary.rst:274: WARNING: Title underline too short. Declare target Devices ^^^^^^^^^^^^^^^^^^^^^ Fixes: hash ("spi: Update the "master/slave" terminology in documentation") Signed-off-by: Randy Dunlap Cc: Dhruva Gole Cc: Mark Brown Cc: linux-spi@vger.kernel.org Reviewed-by: Dhruva Gole Link: https://msgid.link/r/20240216051637.10920-1-rdunlap@infradead.org Signed-off-by: Mark Brown --- Documentation/spi/spi-summary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/spi/spi-summary.rst b/Documentation/spi/spi-summary.rst index c8395cf7e4fc..546de37d6caf 100644 --- a/Documentation/spi/spi-summary.rst +++ b/Documentation/spi/spi-summary.rst @@ -271,7 +271,7 @@ an external clock, where another derives the SPI clock from current settings of some master clock. Declare target Devices -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^ The second kind of information is a list of what SPI target devices exist on the target board, often with some board-specific data needed for the From 0d62c64a8e48438545dcef7e5d2f4839ff5cfe4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Fri, 9 Feb 2024 14:45:30 +0100 Subject: [PATCH 090/122] spi: cadence-qspi: assert each subnode flash CS is valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check each flash CS against the num-cs property from devicetree. Fallback to the driver max supported value (CQSPI_MAX_CHIPSELECT) if num-cs isn't present. cqspi->num_chipselect is set in cqspi_of_get_pdata() to the num-cs devicetree property, or to CQSPI_MAX_CHIPSELECT if num-cs is not set. Signed-off-by: Théo Lebrun Reviewed-by: Dhruva Gole Link: https://msgid.link/r/20240209-cdns-qspi-cs-v1-1-a4f9dfed9ab4@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index a5e2f7786b76..a397f2c2b5fc 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1635,7 +1635,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) return ret; } - if (cs >= CQSPI_MAX_CHIPSELECT) { + if (cs >= cqspi->num_chipselect) { dev_err(dev, "Chip select %d out of range.\n", cs); of_node_put(np); return -EINVAL; From 7cc3522aedb5f4360c4502b2e89b279b7aa94ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Fri, 9 Feb 2024 14:45:31 +0100 Subject: [PATCH 091/122] spi: cadence-qspi: set maximum chip-select to 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the maximum chip-select count in cadence-qspi to 4 instead of 16. The value gets used as default ->num_chipselect when the num-cs DT property isn't received from devicetree. It also determines the cqspi->f_pdata array size. Hardware only supports values up to 4; see cqspi_chipselect() that sets CS using a one-bit-per-CS 4-bit register field. Add a static_assert() call as a defensive measure to ensure we stay under the SPI subsystem limit. It got set to 4 when introduced in 4d8ff6b0991d ("spi: Add multi-cs memories support in SPI core") and later increased to 16 in 2f8c7c3715f2 ("spi: Raise limit on number of chip selects"). Signed-off-by: Théo Lebrun Link: https://msgid.link/r/20240209-cdns-qspi-cs-v1-2-a4f9dfed9ab4@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index a397f2c2b5fc..fd34b48dfb4f 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -31,7 +31,9 @@ #include #define CQSPI_NAME "cadence-qspi" -#define CQSPI_MAX_CHIPSELECT 16 +#define CQSPI_MAX_CHIPSELECT 4 + +static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX); /* Quirks */ #define CQSPI_NEEDS_WR_DELAY BIT(0) From 0f3841a5e1152eca1a58cfbd9ceb6d311aa7e647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Fri, 9 Feb 2024 14:45:32 +0100 Subject: [PATCH 092/122] spi: cadence-qspi: report correct number of chip-select MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the ->num_chipselect field in struct cqspi_st and struct spi_controller to the current number of chip-select. The value is dependent on declared flashes in devicetree. Previously, the num-cs property from devicetree or the maximum value was being reported. Signed-off-by: Théo Lebrun Link: https://msgid.link/r/20240209-cdns-qspi-cs-v1-3-a4f9dfed9ab4@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index fd34b48dfb4f..0df732b03a2d 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1621,6 +1621,7 @@ static const struct spi_controller_mem_caps cqspi_mem_caps = { static int cqspi_setup_flash(struct cqspi_st *cqspi) { + unsigned int max_cs = cqspi->num_chipselect - 1; struct platform_device *pdev = cqspi->pdev; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -1641,6 +1642,8 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) dev_err(dev, "Chip select %d out of range.\n", cs); of_node_put(np); return -EINVAL; + } else if (cs < max_cs) { + max_cs = cs; } f_pdata = &cqspi->f_pdata[cs]; @@ -1654,6 +1657,7 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) } } + cqspi->num_chipselect = max_cs + 1; return 0; } @@ -1864,14 +1868,14 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->current_cs = -1; cqspi->sclk = 0; - host->num_chipselect = cqspi->num_chipselect; - ret = cqspi_setup_flash(cqspi); if (ret) { dev_err(dev, "failed to setup flash parameters %d\n", ret); goto probe_setup_failed; } + host->num_chipselect = cqspi->num_chipselect; + if (cqspi->use_direct_mode) { ret = cqspi_request_mmap_dma(cqspi); if (ret == -EPROBE_DEFER) From 7b1d87af14d9ae902ed0c5dc5fabf4eea5abdf02 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2024 16:33:18 -0600 Subject: [PATCH 093/122] spi: add spi_optimize_message() APIs This adds a new spi_optimize_message() function that can be used to optimize SPI messages that are used more than once. Peripheral drivers that use the same message multiple times can use this API to perform SPI message validation and controller-specific optimizations once and then reuse the message while avoiding the overhead of revalidating the message on each spi_(a)sync() call. Internally, the SPI core will also call this function for each message if the peripheral driver did not explicitly call it. This is done to so that controller drivers don't have to have multiple code paths for optimized and non-optimized messages. A hook is provided for controller drivers to perform controller-specific optimizations. Suggested-by: Martin Sperl Link: https://lore.kernel.org/linux-spi/39DEC004-10A1-47EF-9D77-276188D2580C@martin.sperl.org/ Signed-off-by: David Lechner Link: https://msgid.link/r/20240219-mainline-spi-precook-message-v2-1-4a762c6701b9@baylibre.com Reviewed-by: Jonathan Cameron Signed-off-by: Mark Brown --- drivers/spi/spi.c | 151 ++++++++++++++++++++++++++++++++++++++-- include/linux/spi/spi.h | 20 ++++++ 2 files changed, 167 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c2b10e2c75f0..f68d92b57543 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2106,6 +2106,41 @@ struct spi_message *spi_get_next_queued_message(struct spi_controller *ctlr) } EXPORT_SYMBOL_GPL(spi_get_next_queued_message); +/* + * __spi_unoptimize_message - shared implementation of spi_unoptimize_message() + * and spi_maybe_unoptimize_message() + * @msg: the message to unoptimize + * + * Peripheral drivers should use spi_unoptimize_message() and callers inside + * core should use spi_maybe_unoptimize_message() rather than calling this + * function directly. + * + * It is not valid to call this on a message that is not currently optimized. + */ +static void __spi_unoptimize_message(struct spi_message *msg) +{ + struct spi_controller *ctlr = msg->spi->controller; + + if (ctlr->unoptimize_message) + ctlr->unoptimize_message(msg); + + msg->optimized = false; + msg->opt_state = NULL; +} + +/* + * spi_maybe_unoptimize_message - unoptimize msg not managed by a peripheral + * @msg: the message to unoptimize + * + * This function is used to unoptimize a message if and only if it was + * optimized by the core (via spi_maybe_optimize_message()). + */ +static void spi_maybe_unoptimize_message(struct spi_message *msg) +{ + if (!msg->pre_optimized && msg->optimized) + __spi_unoptimize_message(msg); +} + /** * spi_finalize_current_message() - the current message is complete * @ctlr: the controller to return the message to @@ -2153,6 +2188,8 @@ void spi_finalize_current_message(struct spi_controller *ctlr) mesg->prepared = false; + spi_maybe_unoptimize_message(mesg); + WRITE_ONCE(ctlr->cur_msg_incomplete, false); smp_mb(); /* See __spi_pump_transfer_message()... */ if (READ_ONCE(ctlr->cur_msg_need_completion)) @@ -4194,6 +4231,110 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) return 0; } +/* + * __spi_optimize_message - shared implementation for spi_optimize_message() + * and spi_maybe_optimize_message() + * @spi: the device that will be used for the message + * @msg: the message to optimize + * + * Peripheral drivers will call spi_optimize_message() and the spi core will + * call spi_maybe_optimize_message() instead of calling this directly. + * + * It is not valid to call this on a message that has already been optimized. + * + * Return: zero on success, else a negative error code + */ +static int __spi_optimize_message(struct spi_device *spi, + struct spi_message *msg) +{ + struct spi_controller *ctlr = spi->controller; + int ret; + + ret = __spi_validate(spi, msg); + if (ret) + return ret; + + if (ctlr->optimize_message) { + ret = ctlr->optimize_message(msg); + if (ret) + return ret; + } + + msg->optimized = true; + + return 0; +} + +/* + * spi_maybe_optimize_message - optimize message if it isn't already pre-optimized + * @spi: the device that will be used for the message + * @msg: the message to optimize + * Return: zero on success, else a negative error code + */ +static int spi_maybe_optimize_message(struct spi_device *spi, + struct spi_message *msg) +{ + if (msg->pre_optimized) + return 0; + + return __spi_optimize_message(spi, msg); +} + +/** + * spi_optimize_message - do any one-time validation and setup for a SPI message + * @spi: the device that will be used for the message + * @msg: the message to optimize + * + * Peripheral drivers that reuse the same message repeatedly may call this to + * perform as much message prep as possible once, rather than repeating it each + * time a message transfer is performed to improve throughput and reduce CPU + * usage. + * + * Once a message has been optimized, it cannot be modified with the exception + * of updating the contents of any xfer->tx_buf (the pointer can't be changed, + * only the data in the memory it points to). + * + * Calls to this function must be balanced with calls to spi_unoptimize_message() + * to avoid leaking resources. + * + * Context: can sleep + * Return: zero on success, else a negative error code + */ +int spi_optimize_message(struct spi_device *spi, struct spi_message *msg) +{ + int ret; + + ret = __spi_optimize_message(spi, msg); + if (ret) + return ret; + + /* + * This flag indicates that the peripheral driver called spi_optimize_message() + * and therefore we shouldn't unoptimize message automatically when finalizing + * the message but rather wait until spi_unoptimize_message() is called + * by the peripheral driver. + */ + msg->pre_optimized = true; + + return 0; +} +EXPORT_SYMBOL_GPL(spi_optimize_message); + +/** + * spi_unoptimize_message - releases any resources allocated by spi_optimize_message() + * @msg: the message to unoptimize + * + * Calls to this function must be balanced with calls to spi_optimize_message(). + * + * Context: can sleep + */ +void spi_unoptimize_message(struct spi_message *msg) +{ + __spi_unoptimize_message(msg); + msg->pre_optimized = false; +} +EXPORT_SYMBOL_GPL(spi_unoptimize_message); + static int __spi_async(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; @@ -4258,8 +4399,8 @@ int spi_async(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; - ret = __spi_validate(spi, message); - if (ret != 0) + ret = spi_maybe_optimize_message(spi, message); + if (ret) return ret; spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); @@ -4271,6 +4412,8 @@ int spi_async(struct spi_device *spi, struct spi_message *message) spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + spi_maybe_unoptimize_message(message); + return ret; } EXPORT_SYMBOL_GPL(spi_async); @@ -4331,8 +4474,8 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) return -ESHUTDOWN; } - status = __spi_validate(spi, message); - if (status != 0) + status = spi_maybe_optimize_message(spi, message); + if (status) return status; SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_sync); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 2b8e2746769a..ddfb66dd4caf 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -475,6 +475,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * * @set_cs: set the logic level of the chip select line. May be called * from interrupt context. + * @optimize_message: optimize the message for reuse + * @unoptimize_message: release resources allocated by optimize_message * @prepare_message: set up the controller to transfer a single message, * for example doing DMA mapping. Called from threaded * context. @@ -715,6 +717,8 @@ struct spi_controller { struct completion xfer_completion; size_t max_dma_len; + int (*optimize_message)(struct spi_message *msg); + int (*unoptimize_message)(struct spi_message *msg); int (*prepare_transfer_hardware)(struct spi_controller *ctlr); int (*transfer_one_message)(struct spi_controller *ctlr, struct spi_message *mesg); @@ -1111,6 +1115,8 @@ struct spi_transfer { * @spi: SPI device to which the transaction is queued * @is_dma_mapped: if true, the caller provided both DMA and CPU virtual * addresses for each transfer buffer + * @pre_optimized: peripheral driver pre-optimized the message + * @optimized: the message is in the optimized state * @prepared: spi_prepare_message was called for the this message * @status: zero for success, else negative errno * @complete: called to report transaction completions @@ -1120,6 +1126,7 @@ struct spi_transfer { * successful segments * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message + * @opt_state: for use by whichever driver currently owns the message * @resources: for resource management when the SPI message is processed * * A @spi_message is used to execute an atomic sequence of data transfers, @@ -1143,6 +1150,11 @@ struct spi_message { unsigned is_dma_mapped:1; + /* spi_optimize_message() was called for this message */ + bool pre_optimized; + /* __spi_optimize_message() was called for this message */ + bool optimized; + /* spi_prepare_message() was called for this message */ bool prepared; @@ -1172,6 +1184,11 @@ struct spi_message { */ struct list_head queue; void *state; + /* + * Optional state for use by controller driver between calls to + * __spi_optimize_message() and __spi_unoptimize_message(). + */ + void *opt_state; /* List of spi_res resources when the SPI message is processed */ struct list_head resources; @@ -1255,6 +1272,9 @@ static inline void spi_message_free(struct spi_message *m) kfree(m); } +extern int spi_optimize_message(struct spi_device *spi, struct spi_message *msg); +extern void spi_unoptimize_message(struct spi_message *msg); + extern int spi_setup(struct spi_device *spi); extern int spi_async(struct spi_device *spi, struct spi_message *message); extern int spi_slave_abort(struct spi_device *spi); From fab53fea21a909e4e0656764a8ee7c356fe89d6f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2024 16:33:19 -0600 Subject: [PATCH 094/122] spi: move splitting transfers to spi_optimize_message() Splitting transfers is an expensive operation so we can potentially optimize it by doing it only once per optimization of the message instead of repeating each time the message is transferred. The transfer splitting functions are currently the only user of spi_res_alloc() so spi_res_release() can be safely moved at this time from spi_finalize_current_message() to spi_unoptimize_message(). The doc comments of the public functions for splitting transfers are also updated so that callers will know when it is safe to call them to ensure proper resource management. Reviewed-by: Jonathan Cameron Signed-off-by: David Lechner Link: https://msgid.link/r/20240219-mainline-spi-precook-message-v2-2-4a762c6701b9@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 110 ++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f68d92b57543..ba4d3fde2054 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1747,38 +1747,6 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, trace_spi_message_start(msg); - /* - * If an SPI controller does not support toggling the CS line on each - * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO - * for the CS line, we can emulate the CS-per-word hardware function by - * splitting transfers into one-word transfers and ensuring that - * cs_change is set for each transfer. - */ - if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || - spi_is_csgpiod(msg->spi))) { - ret = spi_split_transfers_maxwords(ctlr, msg, 1); - if (ret) { - msg->status = ret; - spi_finalize_current_message(ctlr); - return ret; - } - - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - /* Don't change cs_change on the last entry in the list */ - if (list_is_last(&xfer->transfer_list, &msg->transfers)) - break; - xfer->cs_change = 1; - } - } else { - ret = spi_split_transfers_maxsize(ctlr, msg, - spi_max_transfer_size(msg->spi)); - if (ret) { - msg->status = ret; - spi_finalize_current_message(ctlr); - return ret; - } - } - if (ctlr->prepare_message) { ret = ctlr->prepare_message(ctlr, msg); if (ret) { @@ -2124,6 +2092,8 @@ static void __spi_unoptimize_message(struct spi_message *msg) if (ctlr->unoptimize_message) ctlr->unoptimize_message(msg); + spi_res_release(ctlr, msg); + msg->optimized = false; msg->opt_state = NULL; } @@ -2169,15 +2139,6 @@ void spi_finalize_current_message(struct spi_controller *ctlr) spi_unmap_msg(ctlr, mesg); - /* - * In the prepare_messages callback the SPI bus has the opportunity - * to split a transfer to smaller chunks. - * - * Release the split transfers here since spi_map_msg() is done on - * the split transfers. - */ - spi_res_release(ctlr, mesg); - if (mesg->prepared && ctlr->unprepare_message) { ret = ctlr->unprepare_message(ctlr, mesg); if (ret) { @@ -3819,6 +3780,10 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, * @msg: the @spi_message to transform * @maxsize: the maximum when to apply this * + * This function allocates resources that are automatically freed during the + * spi message unoptimize phase so this function should only be called from + * optimize_message callbacks. + * * Return: status of transformation */ int spi_split_transfers_maxsize(struct spi_controller *ctlr, @@ -3857,6 +3822,10 @@ EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize); * @msg: the @spi_message to transform * @maxwords: the number of words to limit each transfer to * + * This function allocates resources that are automatically freed during the + * spi message unoptimize phase so this function should only be called from + * optimize_message callbacks. + * * Return: status of transformation */ int spi_split_transfers_maxwords(struct spi_controller *ctlr, @@ -4231,6 +4200,57 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) return 0; } +/* + * spi_split_transfers - generic handling of transfer splitting + * @msg: the message to split + * + * Under certain conditions, a SPI controller may not support arbitrary + * transfer sizes or other features required by a peripheral. This function + * will split the transfers in the message into smaller transfers that are + * supported by the controller. + * + * Controllers with special requirements not covered here can also split + * transfers in the optimize_message() callback. + * + * Context: can sleep + * Return: zero on success, else a negative error code + */ +static int spi_split_transfers(struct spi_message *msg) +{ + struct spi_controller *ctlr = msg->spi->controller; + struct spi_transfer *xfer; + int ret; + + /* + * If an SPI controller does not support toggling the CS line on each + * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO + * for the CS line, we can emulate the CS-per-word hardware function by + * splitting transfers into one-word transfers and ensuring that + * cs_change is set for each transfer. + */ + if ((msg->spi->mode & SPI_CS_WORD) && + (!(ctlr->mode_bits & SPI_CS_WORD) || spi_is_csgpiod(msg->spi))) { + ret = spi_split_transfers_maxwords(ctlr, msg, 1); + if (ret) + return ret; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* Don't change cs_change on the last entry in the list */ + if (list_is_last(&xfer->transfer_list, &msg->transfers)) + break; + + xfer->cs_change = 1; + } + } else { + ret = spi_split_transfers_maxsize(ctlr, msg, + spi_max_transfer_size(msg->spi)); + if (ret) + return ret; + } + + return 0; +} + /* * __spi_optimize_message - shared implementation for spi_optimize_message() * and spi_maybe_optimize_message() @@ -4254,10 +4274,16 @@ static int __spi_optimize_message(struct spi_device *spi, if (ret) return ret; + ret = spi_split_transfers(msg); + if (ret) + return ret; + if (ctlr->optimize_message) { ret = ctlr->optimize_message(msg); - if (ret) + if (ret) { + spi_res_release(ctlr, msg); return ret; + } } msg->optimized = true; From c2bcfe7c6edf418d5adf731a7d60a8abd81e952f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2024 16:33:20 -0600 Subject: [PATCH 095/122] spi: stm32: move splitting transfers to optimize_message Since splitting transfers was moved to spi_optimize_message() in the core SPI code, we now need to use the optimize_message callback in the STM32 SPI driver to ensure that the operation is only performed once when spi_optimize_message() is used by peripheral drivers explicitly. Signed-off-by: David Lechner Link: https://msgid.link/r/20240219-mainline-spi-precook-message-v2-3-4a762c6701b9@baylibre.com Reviewed-by: Jonathan Cameron Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index c32e57bb38bd..e4e7ddb7524a 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1118,6 +1118,21 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } +static int stm32_spi_optimize_message(struct spi_message *msg) +{ + struct spi_controller *ctrl = msg->spi->controller; + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + /* On STM32H7, messages should not exceed a maximum size set + * later via the set_number_of_data function. In order to + * ensure that, split large messages into several messages + */ + if (spi->cfg->set_number_of_data) + return spi_split_transfers_maxwords(ctrl, msg, spi->t_size_max); + + return 0; +} + /** * stm32_spi_prepare_msg - set up the controller to transfer a single message * @ctrl: controller interface @@ -1163,18 +1178,6 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl, !!(spi_dev->mode & SPI_LSB_FIRST), !!(spi_dev->mode & SPI_CS_HIGH)); - /* On STM32H7, messages should not exceed a maximum size setted - * afterward via the set_number_of_data function. In order to - * ensure that, split large messages into several messages - */ - if (spi->cfg->set_number_of_data) { - int ret; - - ret = spi_split_transfers_maxwords(ctrl, msg, spi->t_size_max); - if (ret) - return ret; - } - spin_lock_irqsave(&spi->lock, flags); /* CPOL, CPHA and LSB FIRST bits have common register */ @@ -2180,6 +2183,7 @@ static int stm32_spi_probe(struct platform_device *pdev) ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; ctrl->use_gpio_descriptors = true; + ctrl->optimize_message = stm32_spi_optimize_message; ctrl->prepare_message = stm32_spi_prepare_msg; ctrl->transfer_one = stm32_spi_transfer_one; ctrl->unprepare_message = stm32_spi_unprepare_msg; From 7dba2adb063bcf7a293eacb88980e0975b1fb1fd Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2024 16:33:21 -0600 Subject: [PATCH 096/122] spi: axi-spi-engine: move message compile to optimize_message In the AXI SPI Engine driver, compiling the message is an expensive operation. Previously, it was done per message transfer in the prepare_message hook. This patch moves the message compile to the optimize_message hook so that it is only done once per message in cases where the peripheral driver calls spi_optimize_message(). This can be a significant performance improvement for some peripherals. For example, the ad7380 driver saw a 13% improvement in throughput when using the AXI SPI Engine driver with this patch. Since we now need two message states, one for the optimization stage that doesn't change for the lifetime of the message and one that is reset on each transfer for managing the current transfer state, the old msg->state is split into msg->opt_state and spi_engine->msg_state. The latter is included in the driver struct now since there is only one current message at a time that can ever use it and it is in a hot path so avoiding allocating a new one on each message transfer saves a few cpu cycles and lets us get rid of the prepare_message callback. Signed-off-by: David Lechner Link: https://msgid.link/r/20240219-mainline-spi-precook-message-v2-4-4a762c6701b9@baylibre.com Reviewed-by: Jonathan Cameron Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 40 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index ca66d202f0e2..6177c1a8d56e 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -109,6 +109,7 @@ struct spi_engine { spinlock_t lock; void __iomem *base; + struct spi_engine_message_state msg_state; struct completion msg_complete; unsigned int int_enable; }; @@ -499,17 +500,11 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) return IRQ_HANDLED; } -static int spi_engine_prepare_message(struct spi_controller *host, - struct spi_message *msg) +static int spi_engine_optimize_message(struct spi_message *msg) { struct spi_engine_program p_dry, *p; - struct spi_engine_message_state *st; size_t size; - st = kzalloc(sizeof(*st), GFP_KERNEL); - if (!st) - return -ENOMEM; - spi_engine_precompile_message(msg); p_dry.length = 0; @@ -517,31 +512,22 @@ static int spi_engine_prepare_message(struct spi_controller *host, size = sizeof(*p->instructions) * (p_dry.length + 1); p = kzalloc(sizeof(*p) + size, GFP_KERNEL); - if (!p) { - kfree(st); + if (!p) return -ENOMEM; - } spi_engine_compile_message(msg, false, p); spi_engine_program_add_cmd(p, false, SPI_ENGINE_CMD_SYNC( AXI_SPI_ENGINE_CUR_MSG_SYNC_ID)); - st->p = p; - st->cmd_buf = p->instructions; - st->cmd_length = p->length; - msg->state = st; + msg->opt_state = p; return 0; } -static int spi_engine_unprepare_message(struct spi_controller *host, - struct spi_message *msg) +static int spi_engine_unoptimize_message(struct spi_message *msg) { - struct spi_engine_message_state *st = msg->state; - - kfree(st->p); - kfree(st); + kfree(msg->opt_state); return 0; } @@ -550,10 +536,18 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, struct spi_message *msg) { struct spi_engine *spi_engine = spi_controller_get_devdata(host); - struct spi_engine_message_state *st = msg->state; + struct spi_engine_message_state *st = &spi_engine->msg_state; + struct spi_engine_program *p = msg->opt_state; unsigned int int_enable = 0; unsigned long flags; + /* reinitialize message state for this transfer */ + memset(st, 0, sizeof(*st)); + st->p = p; + st->cmd_buf = p->instructions; + st->cmd_length = p->length; + msg->state = st; + reinit_completion(&spi_engine->msg_complete); spin_lock_irqsave(&spi_engine->lock, flags); @@ -658,8 +652,8 @@ static int spi_engine_probe(struct platform_device *pdev) host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); host->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; host->transfer_one_message = spi_engine_transfer_one_message; - host->prepare_message = spi_engine_prepare_message; - host->unprepare_message = spi_engine_unprepare_message; + host->optimize_message = spi_engine_optimize_message; + host->unoptimize_message = spi_engine_unoptimize_message; host->num_chipselect = 8; if (host->max_speed_hz == 0) From e63aef9c9121e5061cbf5112d12cadc9da399692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Fri, 16 Feb 2024 17:42:19 +0100 Subject: [PATCH 097/122] spi: spi-mem: add statistics support to ->exec_op() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current behavior is that spi-mem operations do not increment statistics, neither per-controller nor per-device, if ->exec_op() is used. For operations that do NOT use ->exec_op(), stats are increased as the usual spi_sync() is called. The newly implemented spi_mem_add_op_stats() function is strongly inspired by spi_statistics_add_transfer_stats(); locking logic and l2len computation comes from there. Statistics that are being filled: bytes{,_rx,_tx}, messages, transfers, errors, timedout, transfer_bytes_histo_*. Note about messages & transfers counters: in the fallback to spi_sync() case, there are from 1 to 4 transfers per message. We only register one big transfer in the ->exec_op() case as that is closer to reality. This patch is NOT touching: - spi_async, spi_sync, spi_sync_immediate: those counters describe precise function calls, incrementing them would be lying. I believe comparing the messages counter to spi_async+spi_sync is a good way to detect ->exec_op() calls, but I might be missing edge cases knowledge. - transfers_split_maxsize: splitting cannot happen if ->exec_op() is provided. Reviewed-by: Dhruva Gole Signed-off-by: Théo Lebrun Reviewed-by: Tudor Ambarus Link: https://msgid.link/r/20240216-spi-mem-stats-v2-1-9256dfe4887d@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-mem.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 2dc8ceb85374..c9d6d42a88f5 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -297,6 +297,49 @@ static void spi_mem_access_end(struct spi_mem *mem) pm_runtime_put(ctlr->dev.parent); } +static void spi_mem_add_op_stats(struct spi_statistics __percpu *pcpu_stats, + const struct spi_mem_op *op, int exec_op_ret) +{ + struct spi_statistics *stats; + u64 len, l2len; + + get_cpu(); + stats = this_cpu_ptr(pcpu_stats); + u64_stats_update_begin(&stats->syncp); + + /* + * We do not have the concept of messages or transfers. Let's consider + * that one operation is equivalent to one message and one transfer. + */ + u64_stats_inc(&stats->messages); + u64_stats_inc(&stats->transfers); + + /* Use the sum of all lengths as bytes count and histogram value. */ + len = op->cmd.nbytes + op->addr.nbytes; + len += op->dummy.nbytes + op->data.nbytes; + u64_stats_add(&stats->bytes, len); + l2len = min(fls(len), SPI_STATISTICS_HISTO_SIZE) - 1; + u64_stats_inc(&stats->transfer_bytes_histo[l2len]); + + /* Only account for data bytes as transferred bytes. */ + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) + u64_stats_add(&stats->bytes_tx, op->data.nbytes); + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN) + u64_stats_add(&stats->bytes_rx, op->data.nbytes); + + /* + * A timeout is not an error, following the same behavior as + * spi_transfer_one_message(). + */ + if (exec_op_ret == -ETIMEDOUT) + u64_stats_inc(&stats->timedout); + else if (exec_op_ret) + u64_stats_inc(&stats->errors); + + u64_stats_update_end(&stats->syncp); + put_cpu(); +} + /** * spi_mem_exec_op() - Execute a memory operation * @mem: the SPI memory @@ -339,8 +382,12 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) * read path) and expect the core to use the regular SPI * interface in other cases. */ - if (!ret || ret != -ENOTSUPP || ret != -EOPNOTSUPP) + if (!ret || ret != -ENOTSUPP || ret != -EOPNOTSUPP) { + spi_mem_add_op_stats(ctlr->pcpu_statistics, op, ret); + spi_mem_add_op_stats(mem->spi->pcpu_statistics, op, ret); + return ret; + } } tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; From d748b48eeba8e1a10c822109252b75ca30288ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 10 Feb 2024 17:40:07 +0100 Subject: [PATCH 098/122] spi: ppc4xx: Fix fallout from rename in struct spi_bitbang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I failed to adapt this driver because it's not enabled in a powerpc allmodconfig build and also wasn't hit by my grep expertise. Fix accordingly. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202402100815.XQXw9XCF-lkp@intel.com/ Fixes: 2259233110d9 ("spi: bitbang: Follow renaming of SPI "master" to "controller"") Signed-off-by: Uwe Kleine-König Link: https://msgid.link/r/20240210164006.208149-7-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-ppc4xx.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 03aab661be9d..b07bb5e5811e 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -362,22 +362,22 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) /* Setup the state for the bitbang driver */ bbp = &hw->bitbang; - bbp->master = hw->host; + bbp->ctlr = hw->host; bbp->setup_transfer = spi_ppc4xx_setupxfer; bbp->txrx_bufs = spi_ppc4xx_txrx; bbp->use_dma = 0; - bbp->master->setup = spi_ppc4xx_setup; - bbp->master->cleanup = spi_ppc4xx_cleanup; - bbp->master->bits_per_word_mask = SPI_BPW_MASK(8); - bbp->master->use_gpio_descriptors = true; + bbp->ctlr->setup = spi_ppc4xx_setup; + bbp->ctlr->cleanup = spi_ppc4xx_cleanup; + bbp->ctlr->bits_per_word_mask = SPI_BPW_MASK(8); + bbp->ctlr->use_gpio_descriptors = true; /* * The SPI core will count the number of GPIO descriptors to figure * out the number of chip selects available on the platform. */ - bbp->master->num_chipselect = 0; + bbp->ctlr->num_chipselect = 0; /* the spi->mode bits understood by this driver: */ - bbp->master->mode_bits = + bbp->ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; /* Get the clock for the OPB */ From 666db8fd4265f938795004838d2a9335ce7b9da1 Mon Sep 17 00:00:00 2001 From: Varshini Rajendran Date: Fri, 23 Feb 2024 22:56:38 +0530 Subject: [PATCH 099/122] spi: dt-bindings: atmel,at91rm9200-spi: remove 9x60 compatible from list Remove microchip,sam9x60-spi compatible from the list as the driver used has the compatible atmel,at91rm9200-spi and sam9x60 devices also use the same compatible as fallback. So removing the microchip,sam9x60-spi compatible from the list since it is not needed. Signed-off-by: Varshini Rajendran Reviewed-by: Tudor Ambarus Link: https://msgid.link/r/20240223172638.672366-1-varshini.rajendran@microchip.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml index 58367587bfbc..32e7c14033c2 100644 --- a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml +++ b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml @@ -22,7 +22,6 @@ properties: - const: atmel,at91rm9200-spi - items: - const: microchip,sam9x7-spi - - const: microchip,sam9x60-spi - const: atmel,at91rm9200-spi reg: From 18ebe6f6fccfb093eec85bcdf3e77d48cc03a592 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Feb 2024 21:48:08 +0200 Subject: [PATCH 100/122] spi: pic32: Replace of_gpio.h by proper one of_gpio.h is deprecated and subject to remove. The driver doesn't use it directly, replace it with what is really being used. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240228194818.3606841-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pic32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index f55b38c577e4..709edb70ad7d 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -11,13 +11,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include From bc9c0a9967fea2c0333bea26ab1bbb66c2bff31a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Feb 2024 21:46:32 +0200 Subject: [PATCH 101/122] spi: stm32-qspi: Replace of_gpio.h by proper one of_gpio.h is deprecated and subject to remove. The driver doesn't use it directly, replace it with what is really being used. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240228194632.3606563-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 385832030459..f1e922fd362a 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -8,13 +8,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include From ee09bb727bff1f14f3f2d81592741b8a081af2ee Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 1 Mar 2024 11:55:46 +0000 Subject: [PATCH 102/122] spi: dt-bindings: samsung: make dma properties not required Since the addition of the driver in 2009, the driver selects between DMA and polling mode depending on the transfer length - DMA mode for transfers bigger than the FIFO depth, polling mode otherwise. All versions of the IP support polling mode, make the dma properties not required. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240301115546.2266676-1-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/samsung,spi.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml index 2f0a0835ecfb..f681372da81f 100644 --- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -76,8 +76,6 @@ required: - compatible - clocks - clock-names - - dmas - - dma-names - interrupts - reg From 69d54ee2e5b0dab9350be2a7019c472b9b8d4c14 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 4 Mar 2024 10:04:23 -0600 Subject: [PATCH 103/122] spi: axi-spi-engine: remove p from struct spi_engine_message_state The program pointer p in struct spi_engine_message_state in the AXI SPI Engine controller driver was assigned but never read so it can be removed. Reviewed-by: Kees Cook Signed-off-by: David Lechner Reviewed-by: Gustavo A. R. Silva Link: https://msgid.link/r/20240304-mainline-axi-spi-engine-small-cleanups-v2-1-5b14ed729a31@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 6177c1a8d56e..d89f75170c9e 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -82,8 +82,6 @@ struct spi_engine_program { * struct spi_engine_message_state - SPI engine per-message state */ struct spi_engine_message_state { - /** @p: Instructions for executing this message. */ - struct spi_engine_program *p; /** @cmd_length: Number of elements in cmd_buf array. */ unsigned cmd_length; /** @cmd_buf: Array of commands not yet written to CMD FIFO. */ @@ -543,7 +541,6 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, /* reinitialize message state for this transfer */ memset(st, 0, sizeof(*st)); - st->p = p; st->cmd_buf = p->instructions; st->cmd_length = p->length; msg->state = st; From c8340ac1015471ec5af234beff535efe15f382e9 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 4 Mar 2024 10:04:24 -0600 Subject: [PATCH 104/122] spi: axi-spi-engine: use __counted_by() attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the __counted_by() attribute to the flex array at the end of struct spi_engine_program in the AXI SPI Engine controller driver. The assignment of the length field has to be reordered to be before the access to the flex array in order to avoid potential compiler warnings/errors due to adding the __counted_by() attribute. Suggested-by: Nuno Sá Signed-off-by: David Lechner Reviewed-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Link: https://msgid.link/r/20240304-mainline-axi-spi-engine-small-cleanups-v2-2-5b14ed729a31@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index d89f75170c9e..a8f626165f44 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -75,7 +75,7 @@ struct spi_engine_program { unsigned int length; - uint16_t instructions[]; + uint16_t instructions[] __counted_by(length); }; /** @@ -115,9 +115,10 @@ struct spi_engine { static void spi_engine_program_add_cmd(struct spi_engine_program *p, bool dry, uint16_t cmd) { - if (!dry) - p->instructions[p->length] = cmd; p->length++; + + if (!dry) + p->instructions[p->length - 1] = cmd; } static unsigned int spi_engine_get_config(struct spi_device *spi) From 5c708541301e695b611cb0b9c6d732bed9b5d904 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 4 Mar 2024 10:04:25 -0600 Subject: [PATCH 105/122] spi: axi-spi-engine: use struct_size() macro This makes use of the struct_size() macro to calculate the size of the struct axi_spi_engine when allocating it. Suggested-by: Christophe JAILLET Reviewed-by: Kees Cook Signed-off-by: David Lechner Reviewed-by: Gustavo A. R. Silva Link: https://msgid.link/r/20240304-mainline-axi-spi-engine-small-cleanups-v2-3-5b14ed729a31@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index a8f626165f44..7cc219d78551 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -502,15 +503,13 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) static int spi_engine_optimize_message(struct spi_message *msg) { struct spi_engine_program p_dry, *p; - size_t size; spi_engine_precompile_message(msg); p_dry.length = 0; spi_engine_compile_message(msg, true, &p_dry); - size = sizeof(*p->instructions) * (p_dry.length + 1); - p = kzalloc(sizeof(*p) + size, GFP_KERNEL); + p = kzalloc(struct_size(p, instructions, p_dry.length + 1), GFP_KERNEL); if (!p) return -ENOMEM; From 80a38bfbbd5965c8bda73b20aa78d308739bbc31 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:44 +0000 Subject: [PATCH 106/122] spi: dt-bindings: introduce FIFO depth properties There are SPI IPs that can be configured by the integrator with a specific FIFO depth depending on the system's capabilities. For example, the samsung USI SPI IP can be configured by the integrator with a TX/RX FIFO from 8 byte to 256 bytes. Introduce the ``fifo-depth`` property for such instances of IPs where the same FIFO depth is used for both RX and TX. Introduce ``rx-fifo-depth`` and ``tx-fifo-depth`` properties for cases where the RX FIFO depth is different from the TX FIFO depth. Make the dedicated RX/TX properties dependent on each other and mutual exclusive with the other. Reviewed-by: Rob Herring Signed-off-by: Tudor Ambarus Reviewed-by: Conor Dooley Link: https://msgid.link/r/20240216070555.2483977-2-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- .../bindings/spi/spi-controller.yaml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index 524f6fe8c27b..093150c0cb87 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -69,6 +69,21 @@ properties: Should be generally avoided and be replaced by spi-cs-high + ACTIVE_HIGH. + fifo-depth: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Size of the RX and TX data FIFOs in bytes. + + rx-fifo-depth: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Size of the RX data FIFO in bytes. + + tx-fifo-depth: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Size of the TX data FIFO in bytes. + num-cs: $ref: /schemas/types.yaml#/definitions/uint32 description: @@ -116,6 +131,10 @@ patternProperties: - compatible - reg +dependencies: + rx-fifo-depth: [ tx-fifo-depth ] + tx-fifo-depth: [ rx-fifo-depth ] + allOf: - if: not: @@ -129,6 +148,14 @@ allOf: properties: "#address-cells": const: 0 + - not: + required: + - fifo-depth + - rx-fifo-depth + - not: + required: + - fifo-depth + - tx-fifo-depth additionalProperties: true From ff8faa8a5c0f4c2da797cd22a163ee3cc8823b13 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:45 +0000 Subject: [PATCH 107/122] spi: s3c64xx: define a magic value Define a magic value, it will be used in the next patch as well. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-3-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6f29dca68491..6ff3b25b6feb 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -78,6 +78,7 @@ #define S3C64XX_SPI_INT_RX_FIFORDY_EN (1<<1) #define S3C64XX_SPI_INT_TX_FIFORDY_EN (1<<0) +#define S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT 6 #define S3C64XX_SPI_ST_RX_OVERRUN_ERR (1<<5) #define S3C64XX_SPI_ST_RX_UNDERRUN_ERR (1<<4) #define S3C64XX_SPI_ST_TX_OVERRUN_ERR (1<<3) @@ -108,7 +109,8 @@ #define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id]) #define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \ (1 << (i)->port_conf->tx_st_done)) ? 1 : 0) -#define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i)) +#define TX_FIFO_LVL(v, i) (((v) >> S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT) & \ + FIFO_LVL_MASK(i)) #define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \ FIFO_LVL_MASK(i)) #define FIFO_DEPTH(i) ((FIFO_LVL_MASK(i) >> 1) + 1) From d6911cf27e5c8491cbfedd4ae2d1ee74a3e685b4 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:46 +0000 Subject: [PATCH 108/122] spi: s3c64xx: allow full FIFO masks The driver is wrong because is using partial register field masks for the SPI_STATUS.{RX, TX}_FIFO_LVL register fields. We see s3c64xx_spi_port_config.fifo_lvl_mask with different values for different instances of the same IP. Take s5pv210_spi_port_config for example, it defines: .fifo_lvl_mask = { 0x1ff, 0x7F }, fifo_lvl_mask is used to determine the FIFO depth of the instance of the IP. In this case, the integrator uses a 256 bytes FIFO for the first SPI instance of the IP, and a 64 bytes FIFO for the second instance. While the first mask reflects the SPI_STATUS.{RX, TX}_FIFO_LVL register fields, the second one is two bits short. Using partial field masks is misleading and can hide problems of the driver's logic. Allow platforms to specify the full FIFO mask, regardless of the FIFO depth. Introduce {rx, tx}_fifomask to represent the SPI_STATUS.{RX, TX}_FIFO_LVL register fields. It's a shifted mask defining the field's length and position. We'll be able to deprecate the use of @rx_lvl_offset, as the shift value can be determined from the mask. The existing compatibles shall start using {rx, tx}_fifomask so that they use the full field mask and to avoid shifting the mask to position, and then shifting it back to zero in the {TX, RX}_FIFO_LVL macros. @rx_lvl_offset will be deprecated in a further patch, after we have the infrastructure to deprecate @fifo_lvl_mask as well. No functional change intended. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-4-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 40 +++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6ff3b25b6feb..338ca3f03ea5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -3,6 +3,7 @@ // Copyright (c) 2009 Samsung Electronics Co., Ltd. // Jaswinder Singh +#include #include #include #include @@ -109,10 +110,10 @@ #define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id]) #define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \ (1 << (i)->port_conf->tx_st_done)) ? 1 : 0) -#define TX_FIFO_LVL(v, i) (((v) >> S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT) & \ - FIFO_LVL_MASK(i)) -#define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \ - FIFO_LVL_MASK(i)) +#define TX_FIFO_LVL(v, sdd) (((v) & (sdd)->tx_fifomask) >> \ + __ffs((sdd)->tx_fifomask)) +#define RX_FIFO_LVL(v, sdd) (((v) & (sdd)->rx_fifomask) >> \ + __ffs((sdd)->rx_fifomask)) #define FIFO_DEPTH(i) ((FIFO_LVL_MASK(i) >> 1) + 1) #define S3C64XX_SPI_MAX_TRAILCNT 0x3ff @@ -136,6 +137,10 @@ struct s3c64xx_spi_dma_data { * struct s3c64xx_spi_port_config - SPI Controller hardware info * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register. * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter. + * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's + * length and position. + * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's + * length and position. * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter. * @clk_div: Internal clock divider * @quirks: Bitmask of known quirks @@ -154,6 +159,8 @@ struct s3c64xx_spi_dma_data { struct s3c64xx_spi_port_config { int fifo_lvl_mask[MAX_SPI_PORTS]; int rx_lvl_offset; + u32 rx_fifomask; + u32 tx_fifomask; int tx_st_done; int quirks; int clk_div; @@ -184,6 +191,10 @@ struct s3c64xx_spi_port_config { * @tx_dma: Local transmit DMA data (e.g. chan and direction) * @port_conf: Local SPI port configuration data * @port_id: Port identification number + * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's + * length and position. + * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's + * length and position. */ struct s3c64xx_spi_driver_data { void __iomem *regs; @@ -203,6 +214,8 @@ struct s3c64xx_spi_driver_data { struct s3c64xx_spi_dma_data tx_dma; const struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; + u32 rx_fifomask; + u32 tx_fifomask; }; static void s3c64xx_flush_fifo(struct s3c64xx_spi_driver_data *sdd) @@ -1183,6 +1196,23 @@ static inline const struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( return (const struct s3c64xx_spi_port_config *)platform_get_device_id(pdev)->driver_data; } +static void s3c64xx_spi_set_fifomask(struct s3c64xx_spi_driver_data *sdd) +{ + const struct s3c64xx_spi_port_config *port_conf = sdd->port_conf; + + if (port_conf->rx_fifomask) + sdd->rx_fifomask = port_conf->rx_fifomask; + else + sdd->rx_fifomask = FIFO_LVL_MASK(sdd) << + port_conf->rx_lvl_offset; + + if (port_conf->tx_fifomask) + sdd->tx_fifomask = port_conf->tx_fifomask; + else + sdd->tx_fifomask = FIFO_LVL_MASK(sdd) << + S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT; +} + static int s3c64xx_spi_probe(struct platform_device *pdev) { struct resource *mem_res; @@ -1231,6 +1261,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->port_id = pdev->id; } + s3c64xx_spi_set_fifomask(sdd); + sdd->cur_bpw = 8; sdd->tx_dma.direction = DMA_MEM_TO_DEV; From c6e776ab6abdfce5a1edcde7a22c639e76499939 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:47 +0000 Subject: [PATCH 109/122] spi: s3c64xx: determine the fifo depth only once Determine the FIFO depth only once, at probe time. ``sdd->fifo_depth`` can be set later on with the FIFO depth specified in the device tree. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-5-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 338ca3f03ea5..72572e23cde5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -191,6 +191,7 @@ struct s3c64xx_spi_port_config { * @tx_dma: Local transmit DMA data (e.g. chan and direction) * @port_conf: Local SPI port configuration data * @port_id: Port identification number + * @fifo_depth: depth of the FIFO. * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's * length and position. * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's @@ -214,6 +215,7 @@ struct s3c64xx_spi_driver_data { struct s3c64xx_spi_dma_data tx_dma; const struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; + unsigned int fifo_depth; u32 rx_fifomask; u32 tx_fifomask; }; @@ -424,7 +426,7 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); if (sdd->rx_dma.ch && sdd->tx_dma.ch) - return xfer->len > FIFO_DEPTH(sdd); + return xfer->len > sdd->fifo_depth; return false; } @@ -548,7 +550,7 @@ static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, void __iomem *regs = sdd->regs; unsigned long val = 1; u32 status; - u32 max_fifo = FIFO_DEPTH(sdd); + u32 max_fifo = sdd->fifo_depth; if (timeout_ms) val = msecs_to_loops(timeout_ms); @@ -655,7 +657,7 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, * For any size less than the fifo size the below code is * executed atleast once. */ - loops = xfer->len / FIFO_DEPTH(sdd); + loops = xfer->len / sdd->fifo_depth; buf = xfer->rx_buf; do { /* wait for data to be received in the fifo */ @@ -792,7 +794,7 @@ static int s3c64xx_spi_transfer_one(struct spi_controller *host, struct spi_transfer *xfer) { struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); - const unsigned int fifo_len = FIFO_DEPTH(sdd); + const unsigned int fifo_len = sdd->fifo_depth; const void *tx_buf = NULL; void *rx_buf = NULL; int target_len = 0, origin_len = 0; @@ -1261,6 +1263,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->port_id = pdev->id; } + sdd->fifo_depth = FIFO_DEPTH(sdd); + s3c64xx_spi_set_fifomask(sdd); sdd->cur_bpw = 8; @@ -1352,7 +1356,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Targets attached\n", sdd->port_id, host->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\n", - mem_res, FIFO_DEPTH(sdd)); + mem_res, sdd->fifo_depth); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); From 414d7b8c9147db7dc34c0e2bae2e2361b922dc07 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:48 +0000 Subject: [PATCH 110/122] spi: s3c64xx: retrieve the FIFO depth from the device tree There are SoCs that configure different FIFO depths for their instances of the SPI IP. See the fifo_lvl_mask defined for exynos4_spi_port_config for example: .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, The first instance of the IP is configured with 256 bytes FIFOs, whereas the last two are configured with 64 bytes FIFOs. Instead of mangling with the .fifo_lvl_mask and its dependency of the DT alias ID, allow such SoCs to determine the FIFO depth via the ``fifo-depth`` DT property. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-6-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 72572e23cde5..b1c63f75021d 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1263,7 +1263,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->port_id = pdev->id; } - sdd->fifo_depth = FIFO_DEPTH(sdd); + if (of_property_read_u32(pdev->dev.of_node, "fifo-depth", + &sdd->fifo_depth)) + sdd->fifo_depth = FIFO_DEPTH(sdd); s3c64xx_spi_set_fifomask(sdd); From 82b98fb8cd33db7793e3e695c44e4e75bca03b3e Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:49 +0000 Subject: [PATCH 111/122] spi: s3c64xx: allow FIFO depth to be determined from the compatible There are SoCs that use the same FIFO depth for all the instances of the SPI IP. See the fifo_lvl_mask defined for gs101 for example: .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, Instead of specifying the FIFO depth with the same value for all 16 nodes in this case, allow such SoCs to infer the FIFO depth from the compatible. There are other SoCs than can benefit of this, see: {gs101, fsd, exynos850, s3c641, s3c2443}_spi_port_config. The FIFO depth inferred from the compatible has a higher precedence than the one that might be specified via device tree, the driver shall know better. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-7-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index b1c63f75021d..68f95c04d092 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -137,6 +137,7 @@ struct s3c64xx_spi_dma_data { * struct s3c64xx_spi_port_config - SPI Controller hardware info * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register. * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter. + * @fifo_depth: depth of the FIFO. * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's * length and position. * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's @@ -159,6 +160,7 @@ struct s3c64xx_spi_dma_data { struct s3c64xx_spi_port_config { int fifo_lvl_mask[MAX_SPI_PORTS]; int rx_lvl_offset; + unsigned int fifo_depth; u32 rx_fifomask; u32 tx_fifomask; int tx_st_done; @@ -1263,8 +1265,10 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->port_id = pdev->id; } - if (of_property_read_u32(pdev->dev.of_node, "fifo-depth", - &sdd->fifo_depth)) + if (sdd->port_conf->fifo_depth) + sdd->fifo_depth = sdd->port_conf->fifo_depth; + else if (of_property_read_u32(pdev->dev.of_node, "fifo-depth", + &sdd->fifo_depth)) sdd->fifo_depth = FIFO_DEPTH(sdd); s3c64xx_spi_set_fifomask(sdd); From e08433e095dda8b5e44c376648dbf65c6fb6771a Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:50 +0000 Subject: [PATCH 112/122] spi: s3c64xx: let the SPI core determine the bus number Let the core determine the bus number, either by getting the alias ID (as the driver forces now), or by allocating a dynamic bus number when the alias is absent. Prepare the driver to allow dt aliases to be absent. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-8-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 68f95c04d092..ac47755beb02 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1279,7 +1279,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->rx_dma.direction = DMA_DEV_TO_MEM; host->dev.of_node = pdev->dev.of_node; - host->bus_num = sdd->port_id; + host->bus_num = -1; host->setup = s3c64xx_spi_setup; host->cleanup = s3c64xx_spi_cleanup; host->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; @@ -1360,7 +1360,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) } dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Targets attached\n", - sdd->port_id, host->num_chipselect); + host->bus_num, host->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\n", mem_res, sdd->fifo_depth); From 2cda3623ff4f002877a81f4e7a4c3401fd98aa2d Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:51 +0000 Subject: [PATCH 113/122] spi: s3c64xx: introduce s3c64xx_spi_set_port_id() Prepare driver to get rid of the of alias ID dependency. Split the port_id logic into a dedicated method. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-9-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ac47755beb02..40de325bd094 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1200,6 +1200,27 @@ static inline const struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( return (const struct s3c64xx_spi_port_config *)platform_get_device_id(pdev)->driver_data; } +static int s3c64xx_spi_set_port_id(struct platform_device *pdev, + struct s3c64xx_spi_driver_data *sdd) +{ + int ret; + + if (pdev->dev.of_node) { + ret = of_alias_get_id(pdev->dev.of_node, "spi"); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Failed to get alias id\n"); + sdd->port_id = ret; + } else { + if (pdev->id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Negative platform ID is not allowed\n"); + sdd->port_id = pdev->id; + } + + return 0; +} + static void s3c64xx_spi_set_fifomask(struct s3c64xx_spi_driver_data *sdd) { const struct s3c64xx_spi_port_config *port_conf = sdd->port_conf; @@ -1252,18 +1273,10 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->host = host; sdd->cntrlr_info = sci; sdd->pdev = pdev; - if (pdev->dev.of_node) { - ret = of_alias_get_id(pdev->dev.of_node, "spi"); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "Failed to get alias id\n"); - sdd->port_id = ret; - } else { - if (pdev->id < 0) - return dev_err_probe(&pdev->dev, -EINVAL, - "Negative platform ID is not allowed\n"); - sdd->port_id = pdev->id; - } + + ret = s3c64xx_spi_set_port_id(pdev, sdd); + if (ret) + return ret; if (sdd->port_conf->fifo_depth) sdd->fifo_depth = sdd->port_conf->fifo_depth; From ea3fba7c41babda225fea324a72d171be9ff6de6 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:52 +0000 Subject: [PATCH 114/122] spi: s3c64xx: get rid of the OF alias ID dependency Compatibles that set ``port_conf->{rx, tx}_fifomask`` are now safe to get rid of the OF alias ID dependency. Let the driver probe even without the alias for these. With this we also protect the FIFO_LVL_MASK calls from s3c64xx_spi_set_fifomask(). Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-10-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 40de325bd094..d2d1c9767145 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1203,8 +1203,12 @@ static inline const struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( static int s3c64xx_spi_set_port_id(struct platform_device *pdev, struct s3c64xx_spi_driver_data *sdd) { + const struct s3c64xx_spi_port_config *port_conf = sdd->port_conf; int ret; + if (port_conf->rx_fifomask && port_conf->tx_fifomask) + return 0; + if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "spi"); if (ret < 0) From ad0adac84d42b693295f4bde407d9f20c9a694ab Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:53 +0000 Subject: [PATCH 115/122] spi: s3c64xx: deprecate fifo_lvl_mask, rx_lvl_offset and port_id Deprecate fifo_lvl_mask, rx_lvl_offset and port_id. One shall use {rx, tx}_fifomask instead. Add messages to each port configuration. Suggested-by: Sam Protsenko Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-11-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index d2d1c9767145..128f4a7c4bd9 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -135,8 +135,8 @@ struct s3c64xx_spi_dma_data { /** * struct s3c64xx_spi_port_config - SPI Controller hardware info - * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register. - * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter. + * @fifo_lvl_mask: [DEPRECATED] use @{rx, tx}_fifomask instead. + * @rx_lvl_offset: [DEPRECATED] use @{rx,tx}_fifomask instead. * @fifo_depth: depth of the FIFO. * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's * length and position. @@ -192,7 +192,7 @@ struct s3c64xx_spi_port_config { * @rx_dma: Local receive DMA data (e.g. chan and direction) * @tx_dma: Local transmit DMA data (e.g. chan and direction) * @port_conf: Local SPI port configuration data - * @port_id: Port identification number + * @port_id: [DEPRECATED] use @{rx,tx}_fifomask instead. * @fifo_depth: depth of the FIFO. * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's * length and position. @@ -1508,7 +1508,9 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { }; static const struct s3c64xx_spi_port_config s3c2443_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x7f }, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 13, .tx_st_done = 21, .clk_div = 2, @@ -1516,14 +1518,18 @@ static const struct s3c64xx_spi_port_config s3c2443_spi_port_config = { }; static const struct s3c64xx_spi_port_config s3c6410_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x7f, 0x7F }, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 13, .tx_st_done = 21, .clk_div = 2, }; static const struct s3c64xx_spi_port_config s5pv210_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x1ff, 0x7F }, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 2, @@ -1531,7 +1537,9 @@ static const struct s3c64xx_spi_port_config s5pv210_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynos4_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 2, @@ -1541,7 +1549,9 @@ static const struct s3c64xx_spi_port_config exynos4_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynos7_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F, 0x7F, 0x7F, 0x1ff}, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 2, @@ -1551,7 +1561,9 @@ static const struct s3c64xx_spi_port_config exynos7_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff}, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 2, @@ -1562,7 +1574,9 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynos850_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f }, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 4, @@ -1573,8 +1587,10 @@ static const struct s3c64xx_spi_port_config exynos850_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynosautov9_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x1ff, 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 4, @@ -1586,7 +1602,9 @@ static const struct s3c64xx_spi_port_config exynosautov9_spi_port_config = { }; static const struct s3c64xx_spi_port_config fsd_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 2, @@ -1597,8 +1615,10 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = { }; static const struct s3c64xx_spi_port_config gs101_spi_port_config = { + /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, + /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 4, From e8b16c7a420420a994f68c181abc4a82dcca0616 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:54 +0000 Subject: [PATCH 116/122] spi: s3c64xx: switch gs101 to new port config data Drop the fifo_lvl_mask and rx_lvl_offset and switch to the new port config data. Advantages of the change: - drop dependency on the OF alias ID. - FIFO depth is inferred from the compatible. GS101 integrates 16 SPI IPs, all with 64 bytes FIFO depths. - use full mask for SPI_STATUS.{RX, TX}_FIFO_LVL fields. Using partial masks is misleading and can hide problems of the driver logic. S3C64XX_SPI_ST_TX_FIFO_RDY_V2 was defined based on the USI's SPI_VERSION.USI_IP_VERSION register field, which has value 2 at reset. MAX_SPI_PORTS is updated to reflect the maximum number of ports for the rest of the compatibles. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-12-tudor.ambarus@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 128f4a7c4bd9..784786407d2e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -20,7 +20,7 @@ #include #include -#define MAX_SPI_PORTS 16 +#define MAX_SPI_PORTS 12 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) #define AUTOSUSPEND_TIMEOUT 2000 @@ -79,6 +79,8 @@ #define S3C64XX_SPI_INT_RX_FIFORDY_EN (1<<1) #define S3C64XX_SPI_INT_TX_FIFORDY_EN (1<<0) +#define S3C64XX_SPI_ST_RX_FIFO_RDY_V2 GENMASK(23, 15) +#define S3C64XX_SPI_ST_TX_FIFO_RDY_V2 GENMASK(14, 6) #define S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT 6 #define S3C64XX_SPI_ST_RX_OVERRUN_ERR (1<<5) #define S3C64XX_SPI_ST_RX_UNDERRUN_ERR (1<<4) @@ -1615,11 +1617,9 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = { }; static const struct s3c64xx_spi_port_config gs101_spi_port_config = { - /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ - .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, - /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ - .rx_lvl_offset = 15, + .fifo_depth = 64, + .rx_fifomask = S3C64XX_SPI_ST_RX_FIFO_RDY_V2, + .tx_fifomask = S3C64XX_SPI_ST_TX_FIFO_RDY_V2, .tx_st_done = 25, .clk_div = 4, .high_speed = true, From 7ad288208d24e42047e5bf0b88271684a32aa967 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 16 Feb 2024 07:05:55 +0000 Subject: [PATCH 117/122] spi: s3c64xx: switch exynos850 to new port config data Exynos850 has the same version of USI SPI (v2.1) as GS101. Drop the fifo_lvl_mask and rx_lvl_offset and switch to the new port config data. Backward compatibility with DT is not broken because when alises are set: - the SPI core will set the bus number according to the alias ID - the FIFO depth is always the same size for exynos850 (64 bytes) no matter the alias ID number. Advantages of the change: - drop dependency on the OF alias ID. - FIFO depth is inferred from the compatible. Exynos850 integrates 3 SPI IPs, all with 64 bytes FIFO depths. - use full mask for SPI_STATUS.{RX, TX}_FIFO_LVL fields. Using partial masks is misleading and can hide problems of the driver logic. Just compiled tested. Signed-off-by: Tudor Ambarus Link: https://msgid.link/r/20240216070555.2483977-13-tudor.ambarus@linaro.org Tested-by: Sam Protsenko Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 784786407d2e..9fcbe040cb2f 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1576,10 +1576,9 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { }; static const struct s3c64xx_spi_port_config exynos850_spi_port_config = { - /* fifo_lvl_mask is deprecated. Use {rx, tx}_fifomask instead. */ - .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f }, - /* rx_lvl_offset is deprecated. Use {rx, tx}_fifomask instead. */ - .rx_lvl_offset = 15, + .fifo_depth = 64, + .rx_fifomask = S3C64XX_SPI_ST_RX_FIFO_RDY_V2, + .tx_fifomask = S3C64XX_SPI_ST_TX_FIFO_RDY_V2, .tx_st_done = 25, .clk_div = 4, .high_speed = true, From 5ee91605ad9ad363766a7ed13dc7d47f5102982a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 6 Mar 2024 17:59:40 +0200 Subject: [PATCH 118/122] spi: Exctract spi_set_all_cs_unused() helper It seems a few functions implement the similar for-loop to mark all chip select pins unused. Let's deduplicate that code in order to have a single place of that for better maintenance. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240306160114.3471398-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 74 +++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 50 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index ba4d3fde2054..5e530fa790b0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -745,6 +745,23 @@ int spi_add_device(struct spi_device *spi) } EXPORT_SYMBOL_GPL(spi_add_device); +static void spi_set_all_cs_unused(struct spi_device *spi) +{ + u8 idx; + + /* + * Zero(0) is a valid physical CS value and can be located at any + * logical CS in the spi->chip_select[]. If all the physical CS + * are initialized to 0 then It would be difficult to differentiate + * between a valid physical CS 0 & an unused logical CS whose physical + * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. + * Now all the unused logical CS will have 0xFF physical CS value & can be + * ignore while performing physical CS validity checks. + */ + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) + spi_set_chipselect(spi, idx, 0xFF); +} + /** * spi_new_device - instantiate one new SPI device * @ctlr: Controller to which device is connected @@ -764,7 +781,6 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, { struct spi_device *proxy; int status; - u8 idx; /* * NOTE: caller did any chip->bus_num checks necessary. @@ -780,19 +796,10 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias)); - /* - * Zero(0) is a valid physical CS value and can be located at any - * logical CS in the spi->chip_select[]. If all the physical CS - * are initialized to 0 then It would be difficult to differentiate - * between a valid physical CS 0 & an unused logical CS whose physical - * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. - * Now all the unused logical CS will have 0xFF physical CS value & can be - * ignore while performing physical CS validity checks. - */ - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi_set_chipselect(proxy, idx, 0xFF); - + /* Use provided chip-select for proxy device */ + spi_set_all_cs_unused(proxy); spi_set_chipselect(proxy, 0, chip->chip_select); + proxy->max_speed_hz = chip->max_speed_hz; proxy->mode = chip->mode; proxy->irq = chip->irq; @@ -2418,17 +2425,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, return -EINVAL; } - /* - * Zero(0) is a valid physical CS value and can be located at any - * logical CS in the spi->chip_select[]. If all the physical CS - * are initialized to 0 then It would be difficult to differentiate - * between a valid physical CS 0 & an unused logical CS whose physical - * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. - * Now all the unused logical CS will have 0xFF physical CS value & can be - * ignore while performing physical CS validity checks. - */ - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi_set_chipselect(spi, idx, 0xFF); + spi_set_all_cs_unused(spi); /* Device address */ rc = of_property_read_variable_u32_array(nc, "reg", &cs[0], 1, @@ -2565,7 +2562,6 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, struct spi_controller *ctlr = spi->controller; struct spi_device *ancillary; int rc = 0; - u8 idx; /* Alloc an spi_device */ ancillary = spi_alloc_device(ctlr); @@ -2576,19 +2572,8 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, strscpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias)); - /* - * Zero(0) is a valid physical CS value and can be located at any - * logical CS in the spi->chip_select[]. If all the physical CS - * are initialized to 0 then It would be difficult to differentiate - * between a valid physical CS 0 & an unused logical CS whose physical - * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. - * Now all the unused logical CS will have 0xFF physical CS value & can be - * ignore while performing physical CS validity checks. - */ - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi_set_chipselect(ancillary, idx, 0xFF); - /* Use provided chip-select for ancillary device */ + spi_set_all_cs_unused(ancillary); spi_set_chipselect(ancillary, 0, chip_select); /* Take over SPI mode/speed from SPI main device */ @@ -2805,7 +2790,6 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, struct acpi_spi_lookup lookup = {}; struct spi_device *spi; int ret; - u8 idx; if (!ctlr && index == -1) return ERR_PTR(-EINVAL); @@ -2841,24 +2825,14 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, return ERR_PTR(-ENOMEM); } - /* - * Zero(0) is a valid physical CS value and can be located at any - * logical CS in the spi->chip_select[]. If all the physical CS - * are initialized to 0 then It would be difficult to differentiate - * between a valid physical CS 0 & an unused logical CS whose physical - * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. - * Now all the unused logical CS will have 0xFF physical CS value & can be - * ignore while performing physical CS validity checks. - */ - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi_set_chipselect(spi, idx, 0xFF); + spi_set_all_cs_unused(spi); + spi_set_chipselect(spi, 0, lookup.chip_select); ACPI_COMPANION_SET(&spi->dev, adev); spi->max_speed_hz = lookup.max_speed_hz; spi->mode |= lookup.mode; spi->irq = lookup.irq; spi->bits_per_word = lookup.bits_per_word; - spi_set_chipselect(spi, 0, lookup.chip_select); /* * spi->chip_select[i] gives the corresponding physical CS for logical CS i * logical CS number is represented by setting the ith bit in spi->cs_index_mask From 9086d0f23b7c292f162a828967975e29e97c0680 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 6 Mar 2024 17:59:41 +0200 Subject: [PATCH 119/122] spi: Exctract spi_dev_check_cs() helper It seems a few functions implement the similar for-loop to validate chip select pins for uniqueness. Let's deduplicate that code in order to have a single place of that for better maintenance. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240306160114.3471398-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5e530fa790b0..eb7e3ddf909b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -608,23 +608,35 @@ static void spi_dev_set_name(struct spi_device *spi) spi_get_chipselect(spi, 0)); } +static inline int spi_dev_check_cs(struct device *dev, + struct spi_device *spi, u8 idx, + struct spi_device *new_spi, u8 new_idx) +{ + u8 cs, cs_new; + u8 idx_new; + + cs = spi_get_chipselect(spi, idx); + for (idx_new = new_idx; idx_new < SPI_CS_CNT_MAX; idx_new++) { + cs_new = spi_get_chipselect(new_spi, idx_new); + if (cs != 0xFF && cs_new != 0xFF && cs == cs_new) { + dev_err(dev, "chipselect %u already in use\n", cs_new); + return -EBUSY; + } + } + return 0; +} + static int spi_dev_check(struct device *dev, void *data) { struct spi_device *spi = to_spi_device(dev); struct spi_device *new_spi = data; - int idx, nw_idx; - u8 cs, cs_nw; + int status, idx; if (spi->controller == new_spi->controller) { for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { - cs = spi_get_chipselect(spi, idx); - for (nw_idx = 0; nw_idx < SPI_CS_CNT_MAX; nw_idx++) { - cs_nw = spi_get_chipselect(new_spi, nw_idx); - if (cs != 0xFF && cs_nw != 0xFF && cs == cs_nw) { - dev_err(dev, "chipselect %d already in use\n", cs_nw); - return -EBUSY; - } - } + status = spi_dev_check_cs(dev, spi, idx, new_spi, 0); + if (status) + return status; } } return 0; @@ -640,8 +652,8 @@ static int __spi_add_device(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; - int status, idx, nw_idx; - u8 cs, nw_cs; + int status, idx; + u8 cs; for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { /* Chipselects are numbered 0..max; validate. */ @@ -658,14 +670,9 @@ static int __spi_add_device(struct spi_device *spi) * For example, spi->chip_select[0] != spi->chip_select[1] and so on. */ for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { - cs = spi_get_chipselect(spi, idx); - for (nw_idx = idx + 1; nw_idx < SPI_CS_CNT_MAX; nw_idx++) { - nw_cs = spi_get_chipselect(spi, nw_idx); - if (cs != 0xFF && nw_cs != 0xFF && cs == nw_cs) { - dev_err(dev, "chipselect %d already in use\n", nw_cs); - return -EBUSY; - } - } + status = spi_dev_check_cs(dev, spi, idx, spi, idx + 1); + if (status) + return status; } /* Set the bus ID string */ From 1209c5566f9b244bd047478b7fc90318c9a310f0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 7 Mar 2024 17:00:59 +0200 Subject: [PATCH 120/122] spi: Consistently use BIT for cs_index_mask Some of the parts related to the chip select are using BIT() macro the rest are using plain numbers. Unify all of them to use BIT(). While at it, make the (repetitive) comment clearer when assigning cs_index_mask during SPI target device enumeration. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240307150256.3789138-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index eb7e3ddf909b..4ab155f698c8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1021,7 +1021,7 @@ static inline bool spi_is_last_cs(struct spi_device *spi) bool last = false; for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { - if ((spi->cs_index_mask >> idx) & 0x01) { + if (spi->cs_index_mask & BIT(idx)) { if (spi->controller->last_cs[idx] == spi_get_chipselect(spi, idx)) last = true; } @@ -1072,8 +1072,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) * into account. */ for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { - if (((spi->cs_index_mask >> idx) & 0x01) && - spi_get_csgpiod(spi, idx)) { + if ((spi->cs_index_mask & BIT(idx)) && spi_get_csgpiod(spi, idx)) { if (has_acpi_companion(&spi->dev)) gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx), !enable); @@ -2456,14 +2455,10 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, spi_set_chipselect(spi, idx, cs[idx]); /* - * spi->chip_select[i] gives the corresponding physical CS for logical CS i - * logical CS number is represented by setting the ith bit in spi->cs_index_mask - * So, for example, if spi->cs_index_mask = 0x01 then logical CS number is 0 and - * spi->chip_select[0] will give the physical CS. - * By default spi->chip_select[0] will hold the physical CS number so, set - * spi->cs_index_mask as 0x01. + * By default spi->chip_select[0] will hold the physical CS number, + * so set bit 0 in spi->cs_index_mask. */ - spi->cs_index_mask = 0x01; + spi->cs_index_mask = BIT(0); /* Device speed */ if (!of_property_read_u32(nc, "spi-max-frequency", &value)) @@ -2587,14 +2582,10 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, ancillary->max_speed_hz = spi->max_speed_hz; ancillary->mode = spi->mode; /* - * spi->chip_select[i] gives the corresponding physical CS for logical CS i - * logical CS number is represented by setting the ith bit in spi->cs_index_mask - * So, for example, if spi->cs_index_mask = 0x01 then logical CS number is 0 and - * spi->chip_select[0] will give the physical CS. - * By default spi->chip_select[0] will hold the physical CS number so, set - * spi->cs_index_mask as 0x01. + * By default spi->chip_select[0] will hold the physical CS number, + * so set bit 0 in spi->cs_index_mask. */ - ancillary->cs_index_mask = 0x01; + ancillary->cs_index_mask = BIT(0); WARN_ON(!mutex_is_locked(&ctlr->add_lock)); @@ -2841,14 +2832,10 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, spi->irq = lookup.irq; spi->bits_per_word = lookup.bits_per_word; /* - * spi->chip_select[i] gives the corresponding physical CS for logical CS i - * logical CS number is represented by setting the ith bit in spi->cs_index_mask - * So, for example, if spi->cs_index_mask = 0x01 then logical CS number is 0 and - * spi->chip_select[0] will give the physical CS. - * By default spi->chip_select[0] will hold the physical CS number so, set - * spi->cs_index_mask as 0x01. + * By default spi->chip_select[0] will hold the physical CS number, + * so set bit 0 in spi->cs_index_mask. */ - spi->cs_index_mask = 0x01; + spi->cs_index_mask = BIT(0); return spi; } From 14fe5a98fb24192f73639590d9d3cdb5640d48db Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 7 Mar 2024 17:01:00 +0200 Subject: [PATCH 121/122] spi: Fix types of the last chip select storage variables First of all, last_cs_index_mask should be aligned with the original cs_index_mask, which is 16-bit (for now) wide. Use the same pattern for the last_cs_index_mask. Second, last_cs can be negative and since 'char' is equal to 'unsigned char' in the kernel, it's incorrect, strictly speaking, to assign signed number to it. Use s8 type as it's done for *_native_cs ones. With this change, regroup a bit the ordering to avoid too much memory space to be wasted due to paddings. Shuffle kernel documentation accordignly. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240307150256.3789138-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index ddfb66dd4caf..b05d5a87c313 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -450,9 +450,11 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * the @cur_msg_completion. This flag is used to signal the context that * is running spi_finalize_current_message() that it needs to complete() * @cur_msg_mapped: message has been mapped for DMA + * @fallback: fallback to PIO if DMA transfer return failure with + * SPI_TRANS_FAIL_NO_START. + * @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs. * @last_cs: the last chip_select that is recorded by set_cs, -1 on non chip * selected - * @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs. * @xfer_completion: used by core transfer_one_message() * @busy: message pump is busy * @running: message pump is running @@ -529,8 +531,6 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * If the driver does not set this, the SPI core takes the snapshot as * close to the driver hand-over as possible. * @irq_flags: Interrupt enable state during PTP system timestamping - * @fallback: fallback to PIO if DMA transfer return failure with - * SPI_TRANS_FAIL_NO_START. * @queue_empty: signal green light for opportunistically skipping the queue * for spi_sync transfers. * @must_async: disable all fast paths in the core @@ -710,10 +710,10 @@ struct spi_controller { bool rt; bool auto_runtime_pm; bool cur_msg_mapped; - char last_cs[SPI_CS_CNT_MAX]; - char last_cs_index_mask; - bool last_cs_mode_high; bool fallback; + bool last_cs_mode_high; + s8 last_cs[SPI_CS_CNT_MAX]; + u32 last_cs_index_mask : SPI_CS_CNT_MAX; struct completion xfer_completion; size_t max_dma_len; From be84be4a35fa99cca7e81e6dd21516a324cca413 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 7 Mar 2024 17:01:01 +0200 Subject: [PATCH 122/122] spi: Introduce SPI_INVALID_CS and is_valid_cs() The SPI core inconsistently uses the marker value for unused chip select pin. Define a constant (with appropriate type) and introduce is_valid_cs() helper function to avoid spreading this inconsistency in the future. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240307150256.3789138-4-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4ab155f698c8..f18738ae95f8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -608,6 +608,22 @@ static void spi_dev_set_name(struct spi_device *spi) spi_get_chipselect(spi, 0)); } +/* + * Zero(0) is a valid physical CS value and can be located at any + * logical CS in the spi->chip_select[]. If all the physical CS + * are initialized to 0 then It would be difficult to differentiate + * between a valid physical CS 0 & an unused logical CS whose physical + * CS can be 0. As a solution to this issue initialize all the CS to -1. + * Now all the unused logical CS will have -1 physical CS value & can be + * ignored while performing physical CS validity checks. + */ +#define SPI_INVALID_CS ((s8)-1) + +static inline bool is_valid_cs(s8 chip_select) +{ + return chip_select != SPI_INVALID_CS; +} + static inline int spi_dev_check_cs(struct device *dev, struct spi_device *spi, u8 idx, struct spi_device *new_spi, u8 new_idx) @@ -618,7 +634,7 @@ static inline int spi_dev_check_cs(struct device *dev, cs = spi_get_chipselect(spi, idx); for (idx_new = new_idx; idx_new < SPI_CS_CNT_MAX; idx_new++) { cs_new = spi_get_chipselect(new_spi, idx_new); - if (cs != 0xFF && cs_new != 0xFF && cs == cs_new) { + if (is_valid_cs(cs) && is_valid_cs(cs_new) && cs == cs_new) { dev_err(dev, "chipselect %u already in use\n", cs_new); return -EBUSY; } @@ -658,7 +674,7 @@ static int __spi_add_device(struct spi_device *spi) for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { /* Chipselects are numbered 0..max; validate. */ cs = spi_get_chipselect(spi, idx); - if (cs != 0xFF && cs >= ctlr->num_chipselect) { + if (is_valid_cs(cs) && cs >= ctlr->num_chipselect) { dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, idx), ctlr->num_chipselect); return -EINVAL; @@ -698,7 +714,7 @@ static int __spi_add_device(struct spi_device *spi) for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { cs = spi_get_chipselect(spi, idx); - if (cs != 0xFF) + if (is_valid_cs(cs)) spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]); } } @@ -756,17 +772,8 @@ static void spi_set_all_cs_unused(struct spi_device *spi) { u8 idx; - /* - * Zero(0) is a valid physical CS value and can be located at any - * logical CS in the spi->chip_select[]. If all the physical CS - * are initialized to 0 then It would be difficult to differentiate - * between a valid physical CS 0 & an unused logical CS whose physical - * CS can be 0. As a solution to this issue initialize all the CS to 0xFF. - * Now all the unused logical CS will have 0xFF physical CS value & can be - * ignore while performing physical CS validity checks. - */ for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi_set_chipselect(spi, idx, 0xFF); + spi_set_chipselect(spi, idx, SPI_INVALID_CS); } /** @@ -1050,7 +1057,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) spi->controller->last_cs_index_mask = spi->cs_index_mask; for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - spi->controller->last_cs[idx] = enable ? spi_get_chipselect(spi, 0) : -1; + spi->controller->last_cs[idx] = enable ? spi_get_chipselect(spi, 0) : SPI_INVALID_CS; spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; if (spi->mode & SPI_CS_HIGH) @@ -3333,9 +3340,9 @@ int spi_register_controller(struct spi_controller *ctlr) goto free_bus_id; } - /* Setting last_cs to -1 means no chip selected */ + /* Setting last_cs to SPI_INVALID_CS means no chip selected */ for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) - ctlr->last_cs[idx] = -1; + ctlr->last_cs[idx] = SPI_INVALID_CS; status = device_add(&ctlr->dev); if (status < 0)