From 0521050215d0daae5d84b212fbe9fc16462f58f6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2019 14:42:30 +0300 Subject: [PATCH 001/102] spi: dw-mmio: Use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190710114230.30047-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 18c06568805e..1c1cac92a9de 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -138,7 +138,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio); struct dw_spi_mmio *dwsmmio; struct dw_spi *dws; - struct resource *mem; int ret; int num_cs; @@ -150,8 +149,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dws = &dwsmmio->dws; /* Get basic io resource and map it */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dws->regs = devm_ioremap_resource(&pdev->dev, mem); + dws->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dws->regs)) { dev_err(&pdev->dev, "SPI region map failed\n"); return PTR_ERR(dws->regs); From 3da9834d9381dd99273f2ad4e6d096c9187dc4f2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2019 14:42:43 +0300 Subject: [PATCH 002/102] spi: dw-mmio: Clock should be shut when error occurs When optional clock requesting fails, the main clock is still up and running, we should shut it down in such caee. Fixes: 560ee7e91009 ("spi: dw: Add support for an optional interface clock") Cc: Phil Edworthy Cc: Gareth Williams Signed-off-by: Andy Shevchenko Reviewed-by: Gareth Williams Link: https://lore.kernel.org/r/20190710114243.30101-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 1c1cac92a9de..4fa7e7a52ebd 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -170,8 +170,10 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) /* Optional clock needed to access the registers */ dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); - if (IS_ERR(dwsmmio->pclk)) - return PTR_ERR(dwsmmio->pclk); + if (IS_ERR(dwsmmio->pclk)) { + ret = PTR_ERR(dwsmmio->pclk); + goto out_clk; + } ret = clk_prepare_enable(dwsmmio->pclk); if (ret) goto out_clk; From 2a3b6f7b02cd141c990c6f5aed41070b5b7f4a7d Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 20:23:31 +0800 Subject: [PATCH 003/102] spi: dw-pci: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190724122331.21856-1-hslester96@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 9651679ee7f7..c1e2401cace0 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -98,16 +98,14 @@ static void spi_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int spi_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_suspend_host(dws); } static int spi_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_resume_host(dws); } From c627c58acdc48055a9e4d40d6f9f1b434222a68d Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:48 +0800 Subject: [PATCH 004/102] spi: sprd: adi: Remove redundant address bits setting The ADI default transfer address bits is 12bit on Spreadtrum SC9860 platform, thus there is no need to set again, remove it. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/3cb57b8aadb7747a9f833e9b4fe8596ba738d9f6.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index df5960bddfe6..11880db08ce9 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -380,9 +380,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi) const __be32 *list; u32 tmp; - /* Address bits select default 12 bits */ - writel_relaxed(0, sadi->base + REG_ADI_CTRL0); - /* Set all channels as default priority */ writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL); writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH); From cc6b3431b36a1109d44cb8e4015cc68dddc75208 Mon Sep 17 00:00:00 2001 From: Chenxu Wei Date: Fri, 26 Jul 2019 15:20:49 +0800 Subject: [PATCH 005/102] spi: sprd: adi: Add a reset reason for TOS panic Add a new reset flag to indicate the reset reason is caused by TOS. Signed-off-by: Chenxu Wei Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/97583aad1f2b849d69b4e76e8d29113da72a9fff.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 11880db08ce9..0b3f23ad6479 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -86,6 +86,7 @@ #define BIT_WDG_EN BIT(2) /* Definition of PMIC reset status register */ +#define HWRST_STATUS_SECURITY 0x02 #define HWRST_STATUS_RECOVERY 0x20 #define HWRST_STATUS_NORMAL 0x40 #define HWRST_STATUS_ALARM 0x50 @@ -336,6 +337,8 @@ static int sprd_adi_restart_handler(struct notifier_block *this, reboot_mode = HWRST_STATUS_IQMODE; else if (!strncmp(cmd, "sprdisk", 7)) reboot_mode = HWRST_STATUS_SPRDISK; + else if (!strncmp(cmd, "tospanic", 8)) + reboot_mode = HWRST_STATUS_SECURITY; else reboot_mode = HWRST_STATUS_NORMAL; From 9d9aa1cc91d68e2140e5948c15947b8254e008e2 Mon Sep 17 00:00:00 2001 From: Sherry Zong Date: Fri, 26 Jul 2019 15:20:50 +0800 Subject: [PATCH 006/102] spi: sprd: adi: Add a reset reason for factory test mode Add a new reset flag to indicate that the system need enter factory test mode after restarting system. Signed-off-by: Sherry Zong Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/8ae5651e876b527920ff878721a8a8ef47b099ac.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 0b3f23ad6479..509ce6943adc 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -98,6 +98,7 @@ #define HWRST_STATUS_AUTODLOADER 0xa0 #define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_SPRDISK 0xc0 +#define HWRST_STATUS_FACTORYTEST 0xe0 /* Use default timeout 50 ms that converts to watchdog values */ #define WDG_LOAD_VAL ((50 * 1000) / 32768) @@ -339,6 +340,8 @@ static int sprd_adi_restart_handler(struct notifier_block *this, reboot_mode = HWRST_STATUS_SPRDISK; else if (!strncmp(cmd, "tospanic", 8)) reboot_mode = HWRST_STATUS_SECURITY; + else if (!strncmp(cmd, "factorytest", 11)) + reboot_mode = HWRST_STATUS_FACTORYTEST; else reboot_mode = HWRST_STATUS_NORMAL; From e6d722ca09c1eebba5660e58b6bcac30c1ccc7ca Mon Sep 17 00:00:00 2001 From: Sherry Zong Date: Fri, 26 Jul 2019 15:20:51 +0800 Subject: [PATCH 007/102] spi: sprd: adi: Add a reset reason for watchdog mode When the system was rebooted by watchdog, now we did not save the watchdog reset mode which will make system enter a incorrect mode after rebooting. Thus we should set the watchdog reset mode as default when opening the watchdog configuration, that means if the system was rebooted by other reason through the restart_handler(), then we will clear the default watchdog reset mode to save the correct reset mode. Signed-off-by: Sherry Zong Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/1563f3de43c6c2262d597a25d6138b5de61ea23d.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 509ce6943adc..0d767eb67fcf 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -99,6 +99,7 @@ #define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_SPRDISK 0xc0 #define HWRST_STATUS_FACTORYTEST 0xe0 +#define HWRST_STATUS_WATCHDOG 0xf0 /* Use default timeout 50 ms that converts to watchdog values */ #define WDG_LOAD_VAL ((50 * 1000) / 32768) @@ -309,6 +310,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, return 0; } +static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi) +{ +#ifdef CONFIG_SPRD_WATCHDOG + u32 val; + + /* Set default watchdog reboot mode */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val |= HWRST_STATUS_WATCHDOG; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); +#endif +} + static int sprd_adi_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd) { @@ -347,6 +360,7 @@ static int sprd_adi_restart_handler(struct notifier_block *this, /* Record the reboot mode */ sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val &= ~HWRST_STATUS_WATCHDOG; val |= reboot_mode; sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); @@ -475,6 +489,7 @@ static int sprd_adi_probe(struct platform_device *pdev) } sprd_adi_hw_init(sadi); + sprd_adi_set_wdt_rst_mode(sadi); ctlr->dev.of_node = pdev->dev.of_node; ctlr->bus_num = pdev->id; From f9adf61e983f5d03334d841bc30f0e967a340b37 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:52 +0800 Subject: [PATCH 008/102] spi: sprd: adi: Change hwlock to be optional Now Spreadtrum ADI controller supplies multiple master accessing channel to support multiple subsystems accessing, instead of using a hardware spinlock to synchronize between the multiple subsystems. To keep backward compatibility, we should change the hardware spinlock to be optional. Moreover change to use of_hwspin_lock_get_id() function which return -ENOENT error number to indicate no hwlock support. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/2abe7dcf210e4197f8c5ece7fc6d6cc1eda8c655.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 66 +++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 0d767eb67fcf..9a051286f120 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -165,14 +165,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) int read_timeout = ADI_READ_TIMEOUT; unsigned long flags; u32 val, rd_addr; - int ret; + int ret = 0; - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } /* @@ -219,7 +221,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) *read_val = val & RD_VALUE_MASK; out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -230,12 +233,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) unsigned long flags; int ret; - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } ret = sprd_adi_drain_fifo(sadi); @@ -261,7 +266,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) } out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -476,16 +482,26 @@ static int sprd_adi_probe(struct platform_device *pdev) sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET; sadi->ctlr = ctlr; sadi->dev = &pdev->dev; - ret = of_hwspin_lock_get_id_byname(np, "adi"); - if (ret < 0) { - dev_err(&pdev->dev, "can not get the hardware spinlock\n"); - goto put_ctlr; - } - - sadi->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret); - if (!sadi->hwlock) { - ret = -ENXIO; - goto put_ctlr; + ret = of_hwspin_lock_get_id(np, 0); + if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) { + sadi->hwlock = + devm_hwspin_lock_request_specific(&pdev->dev, ret); + if (!sadi->hwlock) { + ret = -ENXIO; + goto put_ctlr; + } + } else { + switch (ret) { + case -ENOENT: + dev_info(&pdev->dev, "no hardware spinlock supplied\n"); + break; + default: + dev_err(&pdev->dev, + "failed to find hwlock id, %d\n", ret); + /* fall-through */ + case -EPROBE_DEFER: + goto put_ctlr; + } } sprd_adi_hw_init(sadi); From 70f69f481b87da0614360e57e05a3ba962d60439 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:53 +0800 Subject: [PATCH 009/102] spi: sprd: Change the hwlock support to be optional No need to add hardware spinlock proctection due to add multiple msater channel, so change it to be optional in documentation. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/23d51f5d9c9cc647ad0c5a1fb950d3d9fb9c1303.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-sprd-adi.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt index 8de589b376ce..2567c829e2dc 100644 --- a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt +++ b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt @@ -25,18 +25,23 @@ data by ADI software channels at the same time, or two parallel routine of setti ADI registers will make ADI controller registers chaos to lead incorrect results. Then we need one hardware spinlock to synchronize between the multiple subsystems. +The new version ADI controller supplies multiple master channels for different +subsystem accessing, that means no need to add hardware spinlock to synchronize, +thus change the hardware spinlock support to be optional to keep backward +compatibility. + Required properties: - compatible: Should be "sprd,sc9860-adi". - reg: Offset and length of ADI-SPI controller register space. -- hwlocks: Reference to a phandle of a hwlock provider node. -- hwlock-names: Reference to hwlock name strings defined in the same order - as the hwlocks, should be "adi". - #address-cells: Number of cells required to define a chip select address on the ADI-SPI bus. Should be set to 1. - #size-cells: Size of cells required to define a chip select address size on the ADI-SPI bus. Should be set to 0. Optional properties: +- hwlocks: Reference to a phandle of a hwlock provider node. +- hwlock-names: Reference to hwlock name strings defined in the same order + as the hwlocks, should be "adi". - sprd,hw-channels: This is an array of channel values up to 49 channels. The first value specifies the hardware channel id which is used to transfer data triggered by hardware automatically, and the second From cc8b4659491d23577eb8992449d82c7f4f4fc170 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 14:47:38 +0200 Subject: [PATCH 010/102] spi: core: Use DEVICE_ATTR_RW() for SPI slave control sysfs attribute Convert the SPI slave control sysfs attribute from DEVICE_ATTR() to DEVICE_ATTR_RW(), to reduce boilerplate. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190731124738.14519-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/spi/spi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 75ac046cae52..9fd7926e80c0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2105,8 +2105,8 @@ static int match_true(struct device *dev, void *data) return 1; } -static ssize_t spi_slave_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t slave_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2117,9 +2117,8 @@ static ssize_t spi_slave_show(struct device *dev, child ? to_spi_device(child)->modalias : NULL); } -static ssize_t spi_slave_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t slave_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2157,7 +2156,7 @@ static ssize_t spi_slave_store(struct device *dev, return count; } -static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store); +static DEVICE_ATTR_RW(slave); static struct attribute *spi_slave_attrs[] = { &dev_attr_slave.attr, From 4ff13d00ebd5533947b083c66d44da3243a2d559 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Aug 2019 13:13:53 +0200 Subject: [PATCH 011/102] spi: Reduce kthread priority The SPI thingies request FIFO-99 by default, reduce this to FIFO-50. FIFO-99 is the very highest priority available to SCHED_FIFO and it not a suitable default; it would indicate the SPI work is the most important work on the machine. Cc: Benson Leung Cc: Enric Balletbo i Serra Cc: Guenter Roeck Cc: Mark Brown Cc: linux-spi@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20190801111541.917256884@infradead.org Signed-off-by: Mark Brown --- drivers/platform/chrome/cros_ec_spi.c | 2 +- drivers/spi/spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 006a8ff64057..714306bc3f79 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -706,7 +706,7 @@ static int cros_ec_spi_devm_high_pri_alloc(struct device *dev, struct cros_ec_spi *ec_spi) { struct sched_param sched_priority = { - .sched_priority = MAX_RT_PRIO - 1, + .sched_priority = MAX_RT_PRIO / 2, }; int err; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9fd7926e80c0..8e83c9567353 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1434,7 +1434,7 @@ static void spi_pump_messages(struct kthread_work *work) */ static void spi_set_thread_rt(struct spi_controller *ctlr) { - struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 }; dev_info(&ctlr->dev, "will run message pump with realtime priority\n"); From 6b8ac10e0dd4b49eda513c1aa5045b3b1660d350 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:41 -0700 Subject: [PATCH 012/102] spi: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Mark Brown Cc: linux-spi@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-42-swboyd@chromium.org Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 1 - drivers/spi/spi-armada-3700.c | 1 - drivers/spi/spi-bcm2835.c | 1 - drivers/spi/spi-bcm2835aux.c | 1 - drivers/spi/spi-bcm63xx-hsspi.c | 4 +--- drivers/spi/spi-bcm63xx.c | 4 +--- drivers/spi/spi-cadence.c | 1 - drivers/spi/spi-dw-mmio.c | 4 +--- drivers/spi/spi-efm32.c | 4 +--- drivers/spi/spi-ep93xx.c | 4 +--- drivers/spi/spi-fsl-dspi.c | 1 - drivers/spi/spi-fsl-qspi.c | 4 +--- drivers/spi/spi-geni-qcom.c | 4 +--- drivers/spi/spi-lantiq-ssc.c | 12 +++--------- drivers/spi/spi-mt65xx.c | 1 - drivers/spi/spi-npcm-pspi.c | 1 - drivers/spi/spi-nuc900.c | 1 - drivers/spi/spi-nxp-fspi.c | 4 +--- drivers/spi/spi-pic32-sqi.c | 1 - drivers/spi/spi-pic32.c | 12 +++--------- drivers/spi/spi-qcom-qspi.c | 4 +--- drivers/spi/spi-s3c24xx.c | 1 - drivers/spi/spi-sh-msiof.c | 1 - drivers/spi/spi-sh.c | 4 +--- drivers/spi/spi-sifive.c | 1 - drivers/spi/spi-slave-mt27xx.c | 1 - drivers/spi/spi-sprd.c | 4 +--- drivers/spi/spi-stm32-qspi.c | 5 +---- drivers/spi/spi-sun4i.c | 1 - drivers/spi/spi-sun6i.c | 1 - drivers/spi/spi-synquacer.c | 2 -- drivers/spi/spi-ti-qspi.c | 1 - drivers/spi/spi-uniphier.c | 1 - drivers/spi/spi-xlp.c | 4 +--- drivers/spi/spi-zynq-qspi.c | 1 - drivers/spi/spi-zynqmp-gqspi.c | 1 - 36 files changed, 19 insertions(+), 80 deletions(-) diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 6a7d7b553d95..fd8007ebb145 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -526,7 +526,6 @@ static int atmel_qspi_probe(struct platform_device *pdev) /* Request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "missing IRQ\n"); err = irq; goto disable_qspick; } diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 032888344822..119ae87cc26e 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -864,7 +864,6 @@ static int a3700_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "could not get irq: %d\n", irq); ret = -ENXIO; goto error; } diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 6f243a90c844..c96797844688 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1015,7 +1015,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_controller_put; } diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index bb57035c5770..b18ce69c0375 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -540,7 +540,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_master_put; } diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 9a06ffdb73b8..373cb53579e0 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -338,10 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res_mem); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index df1c94a131e6..fdd7eaa0b8ed 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -520,10 +520,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } clk = devm_clk_get(dev, "spi"); if (IS_ERR(clk)) { diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 7c41e4e82849..1c35eaaac838 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -540,7 +540,6 @@ static int cdns_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq number is invalid\n"); goto clk_dis_all; } diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4fa7e7a52ebd..edb3cf6be201 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -156,10 +156,8 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) } dws->irq = platform_get_irq(pdev, 0); - if (dws->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (dws->irq < 0) return dws->irq; /* -ENXIO */ - } dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index eb1f2142a335..64d4c441b641 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -400,10 +400,8 @@ static int efm32_spi_probe(struct platform_device *pdev) } ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret); + if (ret <= 0) goto err; - } ddata->rxirq = ret; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4034e3ec0ba2..4e1ccd4e52b6 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -656,10 +656,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resources\n"); + if (irq < 0) return -EBUSY; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 53335ccc98f6..96eacbe6ae27 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1105,7 +1105,6 @@ static int dspi_probe(struct platform_device *pdev) dspi_init(dspi); dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { - dev_err(&pdev->dev, "can't get platform irq\n"); ret = dspi->irq; goto out_clk_put; } diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 41a49b93ca60..443d4c1196c2 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -860,10 +860,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 5f0b0d5bfef4..242b6c86cf12 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -539,10 +539,8 @@ static int spi_geni_probe(struct platform_device *pdev) struct clk *clk; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Err getting IRQ %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 8f01858c0ae6..9dfe8b04e688 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -819,22 +819,16 @@ static int lantiq_ssc_probe(struct platform_device *pdev) } rx_irq = platform_get_irq_byname(pdev, LTQ_SPI_RX_IRQ_NAME); - if (rx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_RX_IRQ_NAME); + if (rx_irq < 0) return -ENXIO; - } tx_irq = platform_get_irq_byname(pdev, LTQ_SPI_TX_IRQ_NAME); - if (tx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_TX_IRQ_NAME); + if (tx_irq < 0) return -ENXIO; - } err_irq = platform_get_irq_byname(pdev, LTQ_SPI_ERR_IRQ_NAME); - if (err_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_ERR_IRQ_NAME); + if (err_irq < 0) return -ENXIO; - } master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi)); if (!master) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 45d8a7048b6c..1f5f716016a2 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -664,7 +664,6 @@ static int mtk_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_master; } diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 734a2b956959..5c56caea04f0 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -388,7 +388,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 37e2034ad4d5..f65a029e3fe9 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -367,7 +367,6 @@ static int nuc900_spi_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); err = -ENOENT; goto err_pdata; } diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 8894f98cc99c..501b923f2c27 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -1007,10 +1007,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, nxp_fspi_irq_handler, 0, pdev->name, f); diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index b635526ad414..11b692923fd7 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -590,7 +590,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) /* irq */ sqi->irq = platform_get_irq(pdev, 0); if (sqi->irq < 0) { - dev_err(&pdev->dev, "no irq found\n"); ret = sqi->irq; goto err_free_master; } diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 10cebeaa1e6b..69f517ec59c6 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -711,22 +711,16 @@ static int pic32_spi_hw_probe(struct platform_device *pdev, /* get irq resources: err-irq, rx-irq, tx-irq */ pic32s->fault_irq = platform_get_irq_byname(pdev, "fault"); - if (pic32s->fault_irq < 0) { - dev_err(&pdev->dev, "fault-irq not found\n"); + if (pic32s->fault_irq < 0) return pic32s->fault_irq; - } pic32s->rx_irq = platform_get_irq_byname(pdev, "rx"); - if (pic32s->rx_irq < 0) { - dev_err(&pdev->dev, "rx-irq not found\n"); + if (pic32s->rx_irq < 0) return pic32s->rx_irq; - } pic32s->tx_irq = platform_get_irq_byname(pdev, "tx"); - if (pic32s->tx_irq < 0) { - dev_err(&pdev->dev, "tx-irq not found\n"); + if (pic32s->tx_irq < 0) return pic32s->tx_irq; - } /* get clock */ pic32s->clk = devm_clk_get(&pdev->dev, "mck0"); diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index e0f061139c8f..a0ad73f1cc01 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -454,10 +454,8 @@ static int qcom_qspi_probe(struct platform_device *pdev) goto exit_probe_master_put; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Failed to get irq %d\n", ret); + if (ret < 0) goto exit_probe_master_put; - } ret = devm_request_irq(dev, ret, qcom_qspi_irq, IRQF_TRIGGER_HIGH, dev_name(dev), ctrl); if (ret) { diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 48d8dff05a3a..aea8fd98a31f 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -545,7 +545,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); err = -ENOENT; goto err_no_pdata; } diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index b50bdbc27e58..f73f811c9ba7 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1346,7 +1346,6 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) i = platform_get_irq(pdev, 0); if (i < 0) { - dev_err(&pdev->dev, "cannot get IRQ\n"); ret = i; goto err1; } diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index f1ee58208216..20bdae5fdf3b 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -437,10 +437,8 @@ static int spi_sh_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq error: %d\n", irq); + if (irq < 0) return irq; - } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); if (master == NULL) { diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 93ec2c6cdbfd..5bf2b57e6929 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -323,7 +323,6 @@ static int sifive_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "Unable to find interrupt\n"); ret = irq; goto put_master; } diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index d1075433f6a6..61bc43b0fe57 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -410,7 +410,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_ctlr; } diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 1b7eebb72c07..8c9021b7f7a9 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -843,10 +843,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss) int ret; ss->irq = platform_get_irq(pdev, 0); - if (ss->irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (ss->irq < 0) return ss->irq; - } ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq, 0, pdev->name, ss); diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 655e4afbfb2a..9ac6f9fe13cf 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -570,11 +570,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "IRQ error missing or invalid\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, dev_name(dev), qspi); diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 5194bc07fd60..92e5c667b6a1 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -449,7 +449,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index ee2bdaf5b856..1cf3051bba5e 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -456,7 +456,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index f99abd85c50a..ae17c99cce03 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) rx_irq = platform_get_irq(pdev, 0); if (rx_irq <= 0) { - dev_err(&pdev->dev, "get rx_irq failed (%d)\n", rx_irq); ret = rx_irq; goto put_spi; } @@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) tx_irq = platform_get_irq(pdev, 1); if (tx_irq <= 0) { - dev_err(&pdev->dev, "get tx_irq failed (%d)\n", tx_irq); ret = tx_irq; goto put_spi; } diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 6ca600702470..3cb65371ae3b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -717,7 +717,6 @@ static int ti_qspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); ret = irq; goto free_master; } diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index b32c77df5d49..c1e6f3245557 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -454,7 +454,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c index 1dc479fab98c..4eb5bc9250fc 100644 --- a/drivers/spi/spi-xlp.c +++ b/drivers/spi/spi-xlp.c @@ -384,10 +384,8 @@ static int xlp_spi_probe(struct platform_device *pdev) return PTR_ERR(xspi->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq); + if (irq < 0) return irq; - } err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0, pdev->name, xspi); if (err) { diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index c6bee67decb5..3155e2cabb1e 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -671,7 +671,6 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq resource not found\n"); goto remove_master; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 07a83ca164c2..5e9ea8a38163 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1077,7 +1077,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(dev, "irq resource not found\n"); goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq, From 3c0448d507d42605ab6811bcd61c1cd94390d2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 1 Aug 2019 22:47:10 +0200 Subject: [PATCH 013/102] spi: atmel: add tracing to custom .transfer_one_message callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver specific implementations for .transfer_one_message need to call the tracing stuff themself. This is necessary to make spi tracing actually useful. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190801204710.27309-1-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index f00b367523cd..acf318e7330c 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -23,6 +23,7 @@ #include #include #include +#include /* SPI register offsets */ #define SPI_CR 0x0000 @@ -1409,9 +1410,13 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, msg->actual_length = 0; list_for_each_entry(xfer, &msg->transfers, transfer_list) { + trace_spi_transfer_start(msg, xfer); + ret = atmel_spi_one_transfer(master, msg, xfer); if (ret) goto msg_done; + + trace_spi_transfer_stop(msg, xfer); } if (as->use_pdc) From 79629d0f7ce5b38515c1716911a0181f01b91102 Mon Sep 17 00:00:00 2001 From: Rayagonda Kokatanur Date: Tue, 6 Aug 2019 15:37:50 +0530 Subject: [PATCH 014/102] spi: bcm-qspi: Fix BSPI QUAD and DUAL mode support when using flex mode Fix data transfer width settings based on DT field 'spi-rx-bus-width' to configure BSPI in single, dual or quad mode by using data width and not the command width. Fixes: 5f195ee7d830c ("spi: bcm-qspi: Implement the spi_mem interface") Signed-off-by: Rayagonda Kokatanur Link: https://lore.kernel.org/r/1565086070-28451-1-git-send-email-rayagonda.kokatanur@broadcom.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 584bcb018a62..285a6f463013 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -354,7 +354,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, { int bpc = 0, bpp = 0; u8 command = op->cmd.opcode; - int width = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE; + int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE; int addrlen = op->addr.nbytes; int flex_mode = 1; @@ -992,7 +992,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem, if (mspi_read) return bcm_qspi_mspi_exec_mem_op(spi, op); - ret = bcm_qspi_bspi_set_mode(qspi, op, -1); + ret = bcm_qspi_bspi_set_mode(qspi, op, 0); if (!ret) ret = bcm_qspi_bspi_exec_mem_op(spi, op); From 920d947af9cd528338bbfe989449489a9962142f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 7 Aug 2019 10:52:13 +0200 Subject: [PATCH 015/102] spi: sh-msiof: Use devm_platform_ioremap_resource() helper Use the devm_platform_ioremap_resource() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190807085213.24666-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index f73f811c9ba7..8f134735291f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1297,7 +1297,6 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p) static int sh_msiof_spi_probe(struct platform_device *pdev) { - struct resource *r; struct spi_controller *ctlr; const struct sh_msiof_chipdata *chipdata; struct sh_msiof_spi_info *info; @@ -1350,8 +1349,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) goto err1; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - p->mapbase = devm_ioremap_resource(&pdev->dev, r); + p->mapbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->mapbase)) { ret = PTR_ERR(p->mapbase); goto err1; From 43004f31ebf2705905460a6d9a77da4182170c38 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 17:03:21 +0200 Subject: [PATCH 016/102] spi: Rename of_spi_register_master() function Rename this function to of_spi_get_gpio_numbers() as this is what the function does, it does not register a master, it is called in the path of registering a master so the name is logical in a convoluted way, but it is better to follow Rusty Russell's ABI level no 7: "The obvious use is (probably) the correct one" Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808150321.23319-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8e83c9567353..aef55acb5ccd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2235,7 +2235,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, EXPORT_SYMBOL_GPL(__spi_alloc_controller); #ifdef CONFIG_OF -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { int nb, i, *cs; struct device_node *np = ctlr->dev.of_node; @@ -2268,7 +2268,7 @@ static int of_spi_register_master(struct spi_controller *ctlr) return 0; } #else -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { return 0; } @@ -2455,7 +2455,7 @@ int spi_register_controller(struct spi_controller *ctlr) ctlr->mode_bits |= SPI_CS_HIGH; } else { /* Legacy code path for GPIOs from DT */ - status = of_spi_register_master(ctlr); + status = of_spi_get_gpio_numbers(ctlr); if (status) return status; } From 52718908c3f44b939a9934ef624e68457b21704f Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 12 Aug 2019 13:13:44 +0300 Subject: [PATCH 017/102] spi: dw-pci: Add support for Intel Elkhart Lake PSE SPI Add support for Intel(R) Programmable Services Engine (Intel(R) PSE) SPI controller in Intel Elkhart Lake when interface is assigned to the host processor. Signed-off-by: Jarkko Nikula Link: https://lore.kernel.org/r/20190812101344.3975-1-jarkko.nikula@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 9651679ee7f7..e9ba63814548 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -19,6 +19,7 @@ struct spi_pci_desc { int (*setup)(struct dw_spi *); u16 num_cs; u16 bus_num; + u32 max_freq; }; static struct spi_pci_desc spi_pci_mid_desc_1 = { @@ -33,6 +34,12 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = { .bus_num = 1, }; +static struct spi_pci_desc spi_pci_ehl_desc = { + .num_cs = 1, + .bus_num = -1, + .max_freq = 100000000, +}; + static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dw_spi *dws; @@ -65,6 +72,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (desc) { dws->num_cs = desc->num_cs; dws->bus_num = desc->bus_num; + dws->max_freq = desc->max_freq; if (desc->setup) { ret = desc->setup(dws); @@ -125,6 +133,11 @@ static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc_1}, /* Intel MID platform SPI controller 2 */ { PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&spi_pci_mid_desc_2}, + /* Intel Elkhart Lake PSE SPI controllers */ + { PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc}, {}, }; From 8eb2fd00f65a96143ed1535bdbf4ca4e129d30d1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 18 Aug 2019 17:51:13 +0800 Subject: [PATCH 018/102] spi: zynq-qspi: Fix missing spi_unregister_controller when unload module Use devm_spi_register_controller to fix missing spi_unregister_controller when unload module. Signed-off-by: Axel Lin Acked-by: Michal Simek Link: https://lore.kernel.org/r/20190818095113.2397-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynq-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index c6bee67decb5..d812a215ae5c 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -695,7 +695,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) ctlr->setup = zynq_qspi_setup_op; ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2; ctlr->dev.of_node = np; - ret = spi_register_controller(ctlr); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_master failed\n"); goto clk_dis_all; From 7f01494fd85f3ac40635bc2a7bf005b607084c96 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 20 Aug 2019 17:20:00 +0530 Subject: [PATCH 019/102] spi: Fix the number of CS lines documented as an example The number of CS lines is mentioned as 2 in the spi-controller binding but however in the example, 4 cs-gpios are used. Hence fix that to mention 4. Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20190820115000.32041-1-manivannan.sadhasivam@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-controller.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index a02e2fe2bfb2..732339275848 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -31,7 +31,7 @@ properties: If that property is used, the number of chip selects will be increased automatically with max(cs-gpios, hardware chip selects). - So if, for example, the controller has 2 CS lines, and the + So if, for example, the controller has 4 CS lines, and the cs-gpios looks like this cs-gpios = <&gpio1 0 0>, <0>, <&gpio1 1 0>, <&gpio1 2 0>; From 50fcd84764fcbf40b64a8798f12a3d4be5dc8777 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:02 +0300 Subject: [PATCH 020/102] spi: spi-fsl-dspi: Fix code alignment This is a cosmetic patch that changes nothing except makes sure the code is aligned to the same column, which makes it easier to the eye. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-2-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 330 ++++++++++++++++++------------------- 1 file changed, 165 insertions(+), 165 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 96eacbe6ae27..0adfff9cedd1 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -28,7 +28,7 @@ #include #include -#define DRIVER_NAME "fsl-dspi" +#define DRIVER_NAME "fsl-dspi" #ifdef CONFIG_M5441x #define DSPI_FIFO_SIZE 16 @@ -37,101 +37,101 @@ #endif #define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) -#define SPI_MCR 0x00 -#define SPI_MCR_MASTER (1 << 31) -#define SPI_MCR_PCSIS (0x3F << 16) -#define SPI_MCR_CLR_TXF (1 << 11) -#define SPI_MCR_CLR_RXF (1 << 10) -#define SPI_MCR_XSPI (1 << 3) +#define SPI_MCR 0x00 +#define SPI_MCR_MASTER (1 << 31) +#define SPI_MCR_PCSIS (0x3F << 16) +#define SPI_MCR_CLR_TXF (1 << 11) +#define SPI_MCR_CLR_RXF (1 << 10) +#define SPI_MCR_XSPI (1 << 3) -#define SPI_TCR 0x08 -#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) +#define SPI_TCR 0x08 +#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) -#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) -#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) -#define SPI_CTAR_CPOL(x) ((x) << 26) -#define SPI_CTAR_CPHA(x) ((x) << 25) -#define SPI_CTAR_LSBFE(x) ((x) << 24) -#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22) -#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20) -#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18) -#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16) -#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12) -#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8) -#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4) -#define SPI_CTAR_BR(x) ((x) & 0x0000000f) -#define SPI_CTAR_SCALE_BITS 0xf +#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) +#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) +#define SPI_CTAR_CPOL(x) ((x) << 26) +#define SPI_CTAR_CPHA(x) ((x) << 25) +#define SPI_CTAR_LSBFE(x) ((x) << 24) +#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22) +#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20) +#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18) +#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16) +#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12) +#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8) +#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4) +#define SPI_CTAR_BR(x) ((x) & 0x0000000f) +#define SPI_CTAR_SCALE_BITS 0xf -#define SPI_CTAR0_SLAVE 0x0c +#define SPI_CTAR0_SLAVE 0x0c -#define SPI_SR 0x2c -#define SPI_SR_EOQF 0x10000000 -#define SPI_SR_TCFQF 0x80000000 -#define SPI_SR_CLEAR 0x9aaf0000 +#define SPI_SR 0x2c +#define SPI_SR_EOQF 0x10000000 +#define SPI_SR_TCFQF 0x80000000 +#define SPI_SR_CLEAR 0x9aaf0000 -#define SPI_RSER_TFFFE BIT(25) -#define SPI_RSER_TFFFD BIT(24) -#define SPI_RSER_RFDFE BIT(17) -#define SPI_RSER_RFDFD BIT(16) +#define SPI_RSER_TFFFE BIT(25) +#define SPI_RSER_TFFFD BIT(24) +#define SPI_RSER_RFDFE BIT(17) +#define SPI_RSER_RFDFD BIT(16) -#define SPI_RSER 0x30 -#define SPI_RSER_EOQFE 0x10000000 -#define SPI_RSER_TCFQE 0x80000000 +#define SPI_RSER 0x30 +#define SPI_RSER_EOQFE 0x10000000 +#define SPI_RSER_TCFQE 0x80000000 -#define SPI_PUSHR 0x34 -#define SPI_PUSHR_CMD_CONT (1 << 15) -#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16) -#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) -#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16) -#define SPI_PUSHR_CMD_EOQ (1 << 11) -#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16) -#define SPI_PUSHR_CMD_CTCNT (1 << 10) -#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16) -#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) -#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16) -#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff) +#define SPI_PUSHR 0x34 +#define SPI_PUSHR_CMD_CONT (1 << 15) +#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16) +#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) +#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16) +#define SPI_PUSHR_CMD_EOQ (1 << 11) +#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16) +#define SPI_PUSHR_CMD_CTCNT (1 << 10) +#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16) +#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) +#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16) +#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff) -#define SPI_PUSHR_SLAVE 0x34 +#define SPI_PUSHR_SLAVE 0x34 -#define SPI_POPR 0x38 -#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff) +#define SPI_POPR 0x38 +#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff) -#define SPI_TXFR0 0x3c -#define SPI_TXFR1 0x40 -#define SPI_TXFR2 0x44 -#define SPI_TXFR3 0x48 -#define SPI_RXFR0 0x7c -#define SPI_RXFR1 0x80 -#define SPI_RXFR2 0x84 -#define SPI_RXFR3 0x88 +#define SPI_TXFR0 0x3c +#define SPI_TXFR1 0x40 +#define SPI_TXFR2 0x44 +#define SPI_TXFR3 0x48 +#define SPI_RXFR0 0x7c +#define SPI_RXFR1 0x80 +#define SPI_RXFR2 0x84 +#define SPI_RXFR3 0x88 -#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4)) -#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) -#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) +#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4)) +#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) +#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) -#define SPI_SREX 0x13c +#define SPI_SREX 0x13c -#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) -#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7) +#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) +#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf) +#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf) +#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7) -#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) -#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1) +#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) +#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1) /* Register offsets for regmap_pushr */ -#define PUSHR_CMD 0x0 -#define PUSHR_TX 0x2 +#define PUSHR_CMD 0x0 +#define PUSHR_TX 0x2 -#define SPI_CS_INIT 0x01 -#define SPI_CS_ASSERT 0x02 -#define SPI_CS_DROP 0x04 +#define SPI_CS_INIT 0x01 +#define SPI_CS_ASSERT 0x02 +#define SPI_CS_DROP 0x04 -#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) +#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { - u32 ctar_val; - u16 void_write_data; + u32 ctar_val; + u16 void_write_data; }; enum dspi_trans_mode { @@ -141,75 +141,75 @@ enum dspi_trans_mode { }; struct fsl_dspi_devtype_data { - enum dspi_trans_mode trans_mode; - u8 max_clock_factor; - bool xspi_mode; + enum dspi_trans_mode trans_mode; + u8 max_clock_factor; + bool xspi_mode; }; static const struct fsl_dspi_devtype_data vf610_data = { - .trans_mode = DSPI_DMA_MODE, - .max_clock_factor = 2, + .trans_mode = DSPI_DMA_MODE, + .max_clock_factor = 2, }; static const struct fsl_dspi_devtype_data ls1021a_v1_data = { - .trans_mode = DSPI_TCFQ_MODE, - .max_clock_factor = 8, - .xspi_mode = true, + .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, + .xspi_mode = true, }; static const struct fsl_dspi_devtype_data ls2085a_data = { - .trans_mode = DSPI_TCFQ_MODE, - .max_clock_factor = 8, + .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, }; static const struct fsl_dspi_devtype_data coldfire_data = { - .trans_mode = DSPI_EOQ_MODE, - .max_clock_factor = 8, + .trans_mode = DSPI_EOQ_MODE, + .max_clock_factor = 8, }; struct fsl_dspi_dma { /* Length of transfer in words of DSPI_FIFO_SIZE */ - u32 curr_xfer_len; + u32 curr_xfer_len; - u32 *tx_dma_buf; - struct dma_chan *chan_tx; - dma_addr_t tx_dma_phys; - struct completion cmd_tx_complete; - struct dma_async_tx_descriptor *tx_desc; + u32 *tx_dma_buf; + struct dma_chan *chan_tx; + dma_addr_t tx_dma_phys; + struct completion cmd_tx_complete; + struct dma_async_tx_descriptor *tx_desc; - u32 *rx_dma_buf; - struct dma_chan *chan_rx; - dma_addr_t rx_dma_phys; - struct completion cmd_rx_complete; - struct dma_async_tx_descriptor *rx_desc; + u32 *rx_dma_buf; + struct dma_chan *chan_rx; + dma_addr_t rx_dma_phys; + struct completion cmd_rx_complete; + struct dma_async_tx_descriptor *rx_desc; }; struct fsl_dspi { - struct spi_master *master; - struct platform_device *pdev; + struct spi_master *master; + struct platform_device *pdev; - struct regmap *regmap; - struct regmap *regmap_pushr; - int irq; - struct clk *clk; + struct regmap *regmap; + struct regmap *regmap_pushr; + int irq; + struct clk *clk; - struct spi_transfer *cur_transfer; - struct spi_message *cur_msg; - struct chip_data *cur_chip; - size_t len; - const void *tx; - void *rx; - void *rx_end; - u16 void_write_data; - u16 tx_cmd; - u8 bits_per_word; - u8 bytes_per_word; - const struct fsl_dspi_devtype_data *devtype_data; + struct spi_transfer *cur_transfer; + struct spi_message *cur_msg; + struct chip_data *cur_chip; + size_t len; + const void *tx; + void *rx; + void *rx_end; + u16 void_write_data; + u16 tx_cmd; + u8 bits_per_word; + u8 bytes_per_word; + const struct fsl_dspi_devtype_data *devtype_data; - wait_queue_head_t waitq; - u32 waitflags; + wait_queue_head_t waitq; + u32 waitflags; - struct fsl_dspi_dma *dma; + struct fsl_dspi_dma *dma; }; static u32 dspi_pop_tx(struct fsl_dspi *dspi) @@ -338,7 +338,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) } time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete, - DMA_COMPLETION_TIMEOUT); + DMA_COMPLETION_TIMEOUT); if (time_left == 0) { dev_err(dev, "DMA tx timeout\n"); dmaengine_terminate_all(dma->chan_tx); @@ -347,7 +347,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) } time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete, - DMA_COMPLETION_TIMEOUT); + DMA_COMPLETION_TIMEOUT); if (time_left == 0) { dev_err(dev, "DMA rx timeout\n"); dmaengine_terminate_all(dma->chan_tx); @@ -421,14 +421,14 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) } dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE, - &dma->tx_dma_phys, GFP_KERNEL); + &dma->tx_dma_phys, GFP_KERNEL); if (!dma->tx_dma_buf) { ret = -ENOMEM; goto err_tx_dma_buf; } dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE, - &dma->rx_dma_phys, GFP_KERNEL); + &dma->rx_dma_phys, GFP_KERNEL); if (!dma->rx_dma_buf) { ret = -ENOMEM; goto err_rx_dma_buf; @@ -501,14 +501,14 @@ static void dspi_release_dma(struct fsl_dspi *dspi) } static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, - unsigned long clkrate) + unsigned long clkrate) { /* Valid baud rate pre-scaler values */ int pbr_tbl[4] = {2, 3, 5, 7}; int brs[16] = { 2, 4, 6, 8, - 16, 32, 64, 128, - 256, 512, 1024, 2048, - 4096, 8192, 16384, 32768 }; + 16, 32, 64, 128, + 256, 512, 1024, 2048, + 4096, 8192, 16384, 32768 }; int scale_needed, scale, minscale = INT_MAX; int i, j; @@ -538,7 +538,7 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, } static void ns_delay_scale(char *psc, char *sc, int delay_ns, - unsigned long clkrate) + unsigned long clkrate) { int pscale_tbl[4] = {1, 3, 5, 7}; int scale_needed, scale, minscale = INT_MAX; @@ -546,7 +546,7 @@ static void ns_delay_scale(char *psc, char *sc, int delay_ns, u32 remainder; scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, - &remainder); + &remainder); if (remainder) scale_needed++; @@ -661,7 +661,7 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) } static int dspi_transfer_one_message(struct spi_master *master, - struct spi_message *message) + struct spi_message *message) { struct fsl_dspi *dspi = spi_master_get_devdata(master); struct spi_device *spi = message->spi; @@ -677,7 +677,7 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->cur_chip = spi_get_ctldata(spi); /* Prepare command word for CMD FIFO */ dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) | - SPI_PUSHR_CMD_PCS(spi->chip_select); + SPI_PUSHR_CMD_PCS(spi->chip_select); if (list_is_last(&dspi->cur_transfer->transfer_list, &dspi->cur_msg->transfers)) { /* Leave PCS activated after last transfer when @@ -718,8 +718,8 @@ static int dspi_transfer_one_message(struct spi_master *master, SPI_FRAME_BITS(transfer->bits_per_word)); if (dspi->devtype_data->xspi_mode) regmap_write(dspi->regmap, SPI_CTARE(0), - SPI_FRAME_EBITS(transfer->bits_per_word) - | SPI_CTARE_DTCP(1)); + SPI_FRAME_EBITS(transfer->bits_per_word) | + SPI_CTARE_DTCP(1)); trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { @@ -733,8 +733,8 @@ static int dspi_transfer_one_message(struct spi_master *master, break; case DSPI_DMA_MODE: regmap_write(dspi->regmap, SPI_RSER, - SPI_RSER_TFFFE | SPI_RSER_TFFFD | - SPI_RSER_RFDFE | SPI_RSER_RFDFD); + SPI_RSER_TFFFE | SPI_RSER_TFFFD | + SPI_RSER_RFDFE | SPI_RSER_RFDFD); status = dspi_dma_xfer(dspi); break; default: @@ -746,7 +746,7 @@ static int dspi_transfer_one_message(struct spi_master *master, if (trans_mode != DSPI_DMA_MODE) { if (wait_event_interruptible(dspi->waitq, - dspi->waitflags)) + dspi->waitflags)) dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); dspi->waitflags = 0; @@ -785,10 +785,10 @@ static int dspi_setup(struct spi_device *spi) if (!pdata) { of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay", - &cs_sck_delay); + &cs_sck_delay); of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay", - &sck_cs_delay); + &sck_cs_delay); } else { cs_sck_delay = pdata->cs_sck_delay; sck_cs_delay = pdata->sck_cs_delay; @@ -829,7 +829,7 @@ static void dspi_cleanup(struct spi_device *spi) struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", - spi->master->bus_num, spi->chip_select); + spi->master->bus_num, spi->chip_select); kfree(chip); } @@ -939,16 +939,16 @@ static const struct regmap_range dspi_volatile_ranges[] = { }; static const struct regmap_access_table dspi_volatile_table = { - .yes_ranges = dspi_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges), + .yes_ranges = dspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges), }; static const struct regmap_config dspi_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x88, - .volatile_table = &dspi_volatile_table, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x88, + .volatile_table = &dspi_volatile_table, }; static const struct regmap_range dspi_xspi_volatile_ranges[] = { @@ -959,24 +959,24 @@ static const struct regmap_range dspi_xspi_volatile_ranges[] = { }; static const struct regmap_access_table dspi_xspi_volatile_table = { - .yes_ranges = dspi_xspi_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges), + .yes_ranges = dspi_xspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges), }; static const struct regmap_config dspi_xspi_regmap_config[] = { { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x13c, - .volatile_table = &dspi_xspi_volatile_table, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x13c, + .volatile_table = &dspi_xspi_volatile_table, }, { - .name = "pushr", - .reg_bits = 16, - .val_bits = 16, - .reg_stride = 2, - .max_register = 0x2, + .name = "pushr", + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, + .max_register = 0x2, }, }; @@ -1160,12 +1160,12 @@ static int dspi_remove(struct platform_device *pdev) } static struct platform_driver fsl_dspi_driver = { - .driver.name = DRIVER_NAME, - .driver.of_match_table = fsl_dspi_dt_ids, - .driver.owner = THIS_MODULE, - .driver.pm = &dspi_pm, - .probe = dspi_probe, - .remove = dspi_remove, + .driver.name = DRIVER_NAME, + .driver.of_match_table = fsl_dspi_dt_ids, + .driver.owner = THIS_MODULE, + .driver.pm = &dspi_pm, + .probe = dspi_probe, + .remove = dspi_remove, }; module_platform_driver(fsl_dspi_driver); From 5782a17fe528ce596eb5de66777a73b16f4f1549 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:03 +0300 Subject: [PATCH 021/102] spi: spi-fsl-dspi: Remove unused defines and includes This is a cosmetic patch. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-3-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 0adfff9cedd1..358b381839fb 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -9,24 +9,14 @@ #include #include #include -#include -#include #include -#include #include -#include #include -#include #include #include -#include -#include #include -#include #include #include -#include -#include #define DRIVER_NAME "fsl-dspi" @@ -80,21 +70,14 @@ #define SPI_PUSHR 0x34 #define SPI_PUSHR_CMD_CONT (1 << 15) -#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16) #define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) -#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16) #define SPI_PUSHR_CMD_EOQ (1 << 11) -#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16) #define SPI_PUSHR_CMD_CTCNT (1 << 10) -#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16) #define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) -#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16) -#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff) #define SPI_PUSHR_SLAVE 0x34 #define SPI_POPR 0x38 -#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff) #define SPI_TXFR0 0x3c #define SPI_TXFR1 0x40 @@ -112,21 +95,12 @@ #define SPI_SREX 0x13c #define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) -#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7) - #define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) -#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1) /* Register offsets for regmap_pushr */ #define PUSHR_CMD 0x0 #define PUSHR_TX 0x2 -#define SPI_CS_INIT 0x01 -#define SPI_CS_ASSERT 0x02 -#define SPI_CS_DROP 0x04 - #define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { From b2655196cf9ce783d0b6cfec1f47ac4ecf3dcf95 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:04 +0300 Subject: [PATCH 022/102] spi: spi-fsl-dspi: Use BIT() and GENMASK() macros Switch to using more idiomatic register field definitions, which makes it easier to look them up in the datasheet. Cosmetic patch. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-4-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 358b381839fb..179a9818619f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -28,35 +28,35 @@ #define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) #define SPI_MCR 0x00 -#define SPI_MCR_MASTER (1 << 31) +#define SPI_MCR_MASTER BIT(31) #define SPI_MCR_PCSIS (0x3F << 16) -#define SPI_MCR_CLR_TXF (1 << 11) -#define SPI_MCR_CLR_RXF (1 << 10) -#define SPI_MCR_XSPI (1 << 3) +#define SPI_MCR_CLR_TXF BIT(11) +#define SPI_MCR_CLR_RXF BIT(10) +#define SPI_MCR_XSPI BIT(3) #define SPI_TCR 0x08 -#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) +#define SPI_TCR_GET_TCNT(x) (((x) & GENMASK(31, 16)) >> 16) -#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) -#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) -#define SPI_CTAR_CPOL(x) ((x) << 26) -#define SPI_CTAR_CPHA(x) ((x) << 25) -#define SPI_CTAR_LSBFE(x) ((x) << 24) -#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22) -#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20) -#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18) -#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16) -#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12) -#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8) -#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4) -#define SPI_CTAR_BR(x) ((x) & 0x0000000f) +#define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4)) +#define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27)) +#define SPI_CTAR_CPOL(x) (((x) << 26) & GENMASK(26, 26)) +#define SPI_CTAR_CPHA(x) (((x) << 25) & GENMASK(25, 25)) +#define SPI_CTAR_LSBFE(x) (((x) << 24) & GENMASK(24, 24)) +#define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22)) +#define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20)) +#define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18)) +#define SPI_CTAR_PBR(x) (((x) << 16) & GENMASK(17, 16)) +#define SPI_CTAR_CSSCK(x) (((x) << 12) & GENMASK(15, 12)) +#define SPI_CTAR_ASC(x) (((x) << 8) & GENMASK(11, 8)) +#define SPI_CTAR_DT(x) (((x) << 4) & GENMASK(7, 4)) +#define SPI_CTAR_BR(x) ((x) & GENMASK(3, 0)) #define SPI_CTAR_SCALE_BITS 0xf #define SPI_CTAR0_SLAVE 0x0c #define SPI_SR 0x2c -#define SPI_SR_EOQF 0x10000000 -#define SPI_SR_TCFQF 0x80000000 +#define SPI_SR_TCFQF BIT(31) +#define SPI_SR_EOQF BIT(28) #define SPI_SR_CLEAR 0x9aaf0000 #define SPI_RSER_TFFFE BIT(25) @@ -65,15 +65,15 @@ #define SPI_RSER_RFDFD BIT(16) #define SPI_RSER 0x30 -#define SPI_RSER_EOQFE 0x10000000 -#define SPI_RSER_TCFQE 0x80000000 +#define SPI_RSER_TCFQE BIT(31) +#define SPI_RSER_EOQFE BIT(28) #define SPI_PUSHR 0x34 -#define SPI_PUSHR_CMD_CONT (1 << 15) -#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) -#define SPI_PUSHR_CMD_EOQ (1 << 11) -#define SPI_PUSHR_CMD_CTCNT (1 << 10) -#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) +#define SPI_PUSHR_CMD_CONT BIT(15) +#define SPI_PUSHR_CMD_CTAS(x) (((x) << 12 & GENMASK(14, 12))) +#define SPI_PUSHR_CMD_EOQ BIT(11) +#define SPI_PUSHR_CMD_CTCNT BIT(10) +#define SPI_PUSHR_CMD_PCS(x) (BIT(x) & GENMASK(5, 0)) #define SPI_PUSHR_SLAVE 0x34 @@ -88,7 +88,7 @@ #define SPI_RXFR2 0x84 #define SPI_RXFR3 0x88 -#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4)) +#define SPI_CTARE(x) (0x11c + (((x) & GENMASK(1, 0)) * 4)) #define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) #define SPI_CTARE_DTCP(x) ((x) & 0x7ff) From 9e6f784e66cb865de25a1f5fd1706a45d9e298a7 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:05 +0300 Subject: [PATCH 023/102] spi: spi-fsl-dspi: Demistify magic value in SPI_SR_CLEAR This patch adds the field definitions for the SPI_SR register. The SPI status register is write-1-to-clear and this value is written at init time. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-5-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 179a9818619f..923ee414d1ae 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -57,7 +57,19 @@ #define SPI_SR 0x2c #define SPI_SR_TCFQF BIT(31) #define SPI_SR_EOQF BIT(28) -#define SPI_SR_CLEAR 0x9aaf0000 +#define SPI_SR_TFUF BIT(27) +#define SPI_SR_TFFF BIT(25) +#define SPI_SR_CMDTCF BIT(23) +#define SPI_SR_SPEF BIT(21) +#define SPI_SR_RFOF BIT(19) +#define SPI_SR_TFIWF BIT(18) +#define SPI_SR_RFDF BIT(17) +#define SPI_SR_CMDFFF BIT(16) +#define SPI_SR_CLEAR (SPI_SR_TCFQF | SPI_SR_EOQF | \ + SPI_SR_TFUF | SPI_SR_TFFF | \ + SPI_SR_CMDTCF | SPI_SR_SPEF | \ + SPI_SR_RFOF | SPI_SR_TFIWF | \ + SPI_SR_RFDF | SPI_SR_CMDFFF) #define SPI_RSER_TFFFE BIT(25) #define SPI_RSER_TFFFD BIT(24) From 06d5dd29976fb49f3236b1e66142680619ea259d Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:06 +0300 Subject: [PATCH 024/102] spi: spi-fsl-dspi: Change usage pattern of SPI_MCR_* and SPI_CTAR_* macros These are macros that accept 0 or 1 as argument (a boolean value). Their use encourages the abuse of complex ternary operations inside their argument list, which detracts from the code readability. Replace these with simple if-else statements. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-6-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 923ee414d1ae..b0c546841260 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -39,9 +39,9 @@ #define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4)) #define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27)) -#define SPI_CTAR_CPOL(x) (((x) << 26) & GENMASK(26, 26)) -#define SPI_CTAR_CPHA(x) (((x) << 25) & GENMASK(25, 25)) -#define SPI_CTAR_LSBFE(x) (((x) << 24) & GENMASK(24, 24)) +#define SPI_CTAR_CPOL BIT(26) +#define SPI_CTAR_CPHA BIT(25) +#define SPI_CTAR_LSBFE BIT(24) #define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22)) #define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20)) #define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18)) @@ -587,7 +587,7 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi) */ u32 data = dspi_pop_tx(dspi); - if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE(1)) { + if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE) { /* LSB */ tx_fifo_write(dspi, data & 0xFFFF); tx_fifo_write(dspi, data >> 16); @@ -791,18 +791,22 @@ static int dspi_setup(struct spi_device *spi) /* Set After SCK delay scale values */ ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); - chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) - | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0); + chip->ctar_val = 0; + if (spi->mode & SPI_CPOL) + chip->ctar_val |= SPI_CTAR_CPOL; + if (spi->mode & SPI_CPHA) + chip->ctar_val |= SPI_CTAR_CPHA; if (!spi_controller_is_slave(dspi->master)) { - chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode & - SPI_LSB_FIRST ? 1 : 0) - | SPI_CTAR_PCSSCK(pcssck) - | SPI_CTAR_CSSCK(cssck) - | SPI_CTAR_PASC(pasc) - | SPI_CTAR_ASC(asc) - | SPI_CTAR_PBR(pbr) - | SPI_CTAR_BR(br); + chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | + SPI_CTAR_CSSCK(cssck) | + SPI_CTAR_PASC(pasc) | + SPI_CTAR_ASC(asc) | + SPI_CTAR_PBR(pbr) | + SPI_CTAR_BR(br); + + if (spi->mode & SPI_LSB_FIRST) + chip->ctar_val |= SPI_CTAR_LSBFE; } spi_set_ctldata(spi, chip); @@ -968,9 +972,10 @@ static const struct regmap_config dspi_xspi_regmap_config[] = { static void dspi_init(struct fsl_dspi *dspi) { - unsigned int mcr = SPI_MCR_PCSIS | - (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0); + unsigned int mcr = SPI_MCR_PCSIS; + if (dspi->devtype_data->xspi_mode) + mcr |= SPI_MCR_XSPI; if (!spi_controller_is_slave(dspi->master)) mcr |= SPI_MCR_MASTER; From abbd0ef1f2542621e0f94a7273b7f7e458a38497 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:07 +0300 Subject: [PATCH 025/102] spi: spi-fsl-dspi: Reduce indentation in dspi_release_dma() There is no point in surrounding an entire function block in an if condition. Rather, exit early if the condition is false. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-7-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index b0c546841260..c07525a9fd34 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -471,18 +471,19 @@ static void dspi_release_dma(struct fsl_dspi *dspi) struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; - if (dma) { - if (dma->chan_tx) { - dma_unmap_single(dev, dma->tx_dma_phys, - DSPI_DMA_BUFSIZE, DMA_TO_DEVICE); - dma_release_channel(dma->chan_tx); - } + if (!dma) + return; - if (dma->chan_rx) { - dma_unmap_single(dev, dma->rx_dma_phys, - DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE); - dma_release_channel(dma->chan_rx); - } + if (dma->chan_tx) { + dma_unmap_single(dev, dma->tx_dma_phys, + DSPI_DMA_BUFSIZE, DMA_TO_DEVICE); + dma_release_channel(dma->chan_tx); + } + + if (dma->chan_rx) { + dma_unmap_single(dev, dma->rx_dma_phys, + DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE); + dma_release_channel(dma->chan_rx); } } From 9b536d3647ee1348860657c239d247364e4374ec Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:08 +0300 Subject: [PATCH 026/102] spi: spi-fsl-dspi: Remove unused initialization of 'ret' in dspi_probe There is no code path for reaching 'return ret;' without it first being assigned to an error code. Therefore the initialization with 0 is pointless. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-8-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c07525a9fd34..c5d99f4d5e3d 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -996,7 +996,7 @@ static int dspi_probe(struct platform_device *pdev) const struct regmap_config *regmap_config; void __iomem *base; struct fsl_dspi_platform_data *pdata; - int ret = 0, cs_num, bus_num; + int ret, cs_num, bus_num; master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); if (!master) From bee44359169ecf293a0bd2351ada186a0864a94a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:09 +0300 Subject: [PATCH 027/102] spi: spi-fsl-dspi: Remove pointless assignment of master->transfer to NULL Introduced in commit 9298bc727385 ("spi: spi-fsl-dspi: Remove spi-bitbang") for less than obvious reasons, this assignment is confusing and serves no purpose. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-9-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c5d99f4d5e3d..753584c4065c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1006,7 +1006,6 @@ static int dspi_probe(struct platform_device *pdev) dspi->pdev = pdev; dspi->master = master; - master->transfer = NULL; master->setup = dspi_setup; master->transfer_one_message = dspi_transfer_one_message; master->dev.of_node = pdev->dev.of_node; From 3a11ea664be6ff16387759d57aed3a015f6339a1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:10 +0300 Subject: [PATCH 028/102] spi: spi-fsl-dspi: Replace legacy spi_master names with spi_controller This adapts the spi-fsl-dspi driver to the API changes introduced in commit 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller""). Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-10-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 100 ++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 753584c4065c..a9bcbc458172 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -171,7 +171,7 @@ struct fsl_dspi_dma { }; struct fsl_dspi { - struct spi_master *master; + struct spi_controller *ctlr; struct platform_device *pdev; struct regmap *regmap; @@ -219,7 +219,7 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) { u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); - if (spi_controller_is_slave(dspi->master)) + if (spi_controller_is_slave(dspi->ctlr)) return data; if (dspi->len > 0) @@ -318,7 +318,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_tx); - if (spi_controller_is_slave(dspi->master)) { + if (spi_controller_is_slave(dspi->ctlr)) { wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete); return 0; } @@ -647,10 +647,10 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) dspi_push_rx(dspi, fifo_read(dspi)); } -static int dspi_transfer_one_message(struct spi_master *master, +static int dspi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *message) { - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); struct spi_device *spi = message->spi; struct spi_transfer *transfer; int status = 0; @@ -745,7 +745,7 @@ static int dspi_transfer_one_message(struct spi_master *master, out: message->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return status; } @@ -753,7 +753,7 @@ out: static int dspi_setup(struct spi_device *spi) { struct chip_data *chip; - struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); + struct fsl_dspi *dspi = spi_controller_get_devdata(spi->controller); struct fsl_dspi_platform_data *pdata; u32 cs_sck_delay = 0, sck_cs_delay = 0; unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; @@ -798,7 +798,7 @@ static int dspi_setup(struct spi_device *spi) if (spi->mode & SPI_CPHA) chip->ctar_val |= SPI_CTAR_CPHA; - if (!spi_controller_is_slave(dspi->master)) { + if (!spi_controller_is_slave(dspi->ctlr)) { chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | SPI_CTAR_CSSCK(cssck) | SPI_CTAR_PASC(pasc) | @@ -820,7 +820,7 @@ static void dspi_cleanup(struct spi_device *spi) struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", - spi->master->bus_num, spi->chip_select); + spi->controller->bus_num, spi->chip_select); kfree(chip); } @@ -893,10 +893,10 @@ MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids); #ifdef CONFIG_PM_SLEEP static int dspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); - spi_master_suspend(master); + spi_controller_suspend(ctlr); clk_disable_unprepare(dspi->clk); pinctrl_pm_select_sleep_state(dev); @@ -906,8 +906,8 @@ static int dspi_suspend(struct device *dev) static int dspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); int ret; pinctrl_pm_select_default_state(dev); @@ -915,7 +915,7 @@ static int dspi_resume(struct device *dev) ret = clk_prepare_enable(dspi->clk); if (ret) return ret; - spi_master_resume(master); + spi_controller_resume(ctlr); return 0; } @@ -977,7 +977,7 @@ static void dspi_init(struct fsl_dspi *dspi) if (dspi->devtype_data->xspi_mode) mcr |= SPI_MCR_XSPI; - if (!spi_controller_is_slave(dspi->master)) + if (!spi_controller_is_slave(dspi->ctlr)) mcr |= SPI_MCR_MASTER; regmap_write(dspi->regmap, SPI_MCR, mcr); @@ -990,7 +990,7 @@ static void dspi_init(struct fsl_dspi *dspi) static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct spi_master *master; + struct spi_controller *ctlr; struct fsl_dspi *dspi; struct resource *res; const struct regmap_config *regmap_config; @@ -998,25 +998,25 @@ static int dspi_probe(struct platform_device *pdev) struct fsl_dspi_platform_data *pdata; int ret, cs_num, bus_num; - master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); - if (!master) + ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); + if (!ctlr) return -ENOMEM; - dspi = spi_master_get_devdata(master); + dspi = spi_controller_get_devdata(ctlr); dspi->pdev = pdev; - dspi->master = master; + dspi->ctlr = ctlr; - master->setup = dspi_setup; - master->transfer_one_message = dspi_transfer_one_message; - master->dev.of_node = pdev->dev.of_node; + ctlr->setup = dspi_setup; + ctlr->transfer_one_message = dspi_transfer_one_message; + ctlr->dev.of_node = pdev->dev.of_node; - master->cleanup = dspi_cleanup; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + ctlr->cleanup = dspi_cleanup; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; pdata = dev_get_platdata(&pdev->dev); if (pdata) { - master->num_chipselect = pdata->cs_num; - master->bus_num = pdata->bus_num; + ctlr->num_chipselect = pdata->cs_num; + ctlr->bus_num = pdata->bus_num; dspi->devtype_data = &coldfire_data; } else { @@ -1024,38 +1024,38 @@ static int dspi_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); if (ret < 0) { dev_err(&pdev->dev, "can't get spi-num-chipselects\n"); - goto out_master_put; + goto out_ctlr_put; } - master->num_chipselect = cs_num; + ctlr->num_chipselect = cs_num; ret = of_property_read_u32(np, "bus-num", &bus_num); if (ret < 0) { dev_err(&pdev->dev, "can't get bus-num\n"); - goto out_master_put; + goto out_ctlr_put; } - master->bus_num = bus_num; + ctlr->bus_num = bus_num; if (of_property_read_bool(np, "spi-slave")) - master->slave = true; + ctlr->slave = true; dspi->devtype_data = of_device_get_match_data(&pdev->dev); if (!dspi->devtype_data) { dev_err(&pdev->dev, "can't get devtype_data\n"); ret = -EFAULT; - goto out_master_put; + goto out_ctlr_put; } } if (dspi->devtype_data->xspi_mode) - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); else - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); - goto out_master_put; + goto out_ctlr_put; } if (dspi->devtype_data->xspi_mode) @@ -1067,7 +1067,7 @@ static int dspi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(dspi->regmap)); ret = PTR_ERR(dspi->regmap); - goto out_master_put; + goto out_ctlr_put; } if (dspi->devtype_data->xspi_mode) { @@ -1079,7 +1079,7 @@ static int dspi_probe(struct platform_device *pdev) "failed to init pushr regmap: %ld\n", PTR_ERR(dspi->regmap_pushr)); ret = PTR_ERR(dspi->regmap_pushr); - goto out_master_put; + goto out_ctlr_put; } } @@ -1087,11 +1087,11 @@ static int dspi_probe(struct platform_device *pdev) if (IS_ERR(dspi->clk)) { ret = PTR_ERR(dspi->clk); dev_err(&pdev->dev, "unable to get clock\n"); - goto out_master_put; + goto out_ctlr_put; } ret = clk_prepare_enable(dspi->clk); if (ret) - goto out_master_put; + goto out_ctlr_put; dspi_init(dspi); dspi->irq = platform_get_irq(pdev, 0); @@ -1115,15 +1115,15 @@ static int dspi_probe(struct platform_device *pdev) } } - master->max_speed_hz = + ctlr->max_speed_hz = clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; init_waitqueue_head(&dspi->waitq); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, ctlr); - ret = spi_register_master(master); + ret = spi_register_controller(ctlr); if (ret != 0) { - dev_err(&pdev->dev, "Problem registering DSPI master\n"); + dev_err(&pdev->dev, "Problem registering DSPI ctlr\n"); goto out_clk_put; } @@ -1131,21 +1131,21 @@ static int dspi_probe(struct platform_device *pdev) out_clk_put: clk_disable_unprepare(dspi->clk); -out_master_put: - spi_master_put(master); +out_ctlr_put: + spi_controller_put(ctlr); return ret; } static int dspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); /* Disconnect from the SPI framework */ dspi_release_dma(dspi); clk_disable_unprepare(dspi->clk); - spi_unregister_master(dspi->master); + spi_unregister_controller(dspi->ctlr); return 0; } From d6bdfa6c203d16e7f290ecc34137c396b1602782 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:11 +0300 Subject: [PATCH 029/102] spi: spi-fsl-dspi: Use reverse Christmas tree declaration order This patch puts variable declaration in the reverse order of their length for cosmetic purposes. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-11-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index a9bcbc458172..e2e71bd73b5c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -268,8 +268,8 @@ static void dspi_rx_dma_callback(void *arg) static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) { - struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; + struct fsl_dspi_dma *dma = dspi->dma; int time_left; int i; @@ -346,9 +346,9 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) static int dspi_dma_xfer(struct fsl_dspi *dspi) { - struct fsl_dspi_dma *dma = dspi->dma; - struct device *dev = &dspi->pdev->dev; struct spi_message *message = dspi->cur_msg; + struct device *dev = &dspi->pdev->dev; + struct fsl_dspi_dma *dma = dspi->dma; int curr_remaining_bytes; int bytes_per_buffer; int ret = 0; @@ -383,9 +383,9 @@ exit: static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) { - struct fsl_dspi_dma *dma; - struct dma_slave_config cfg; struct device *dev = &dspi->pdev->dev; + struct dma_slave_config cfg; + struct fsl_dspi_dma *dma; int ret; dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); @@ -527,10 +527,10 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, static void ns_delay_scale(char *psc, char *sc, int delay_ns, unsigned long clkrate) { - int pscale_tbl[4] = {1, 3, 5, 7}; int scale_needed, scale, minscale = INT_MAX; - int i, j; + int pscale_tbl[4] = {1, 3, 5, 7}; u32 remainder; + int i, j; scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, &remainder); @@ -652,9 +652,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, { struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); struct spi_device *spi = message->spi; + enum dspi_trans_mode trans_mode; struct spi_transfer *transfer; int status = 0; - enum dspi_trans_mode trans_mode; message->actual_length = 0; @@ -752,12 +752,12 @@ out: static int dspi_setup(struct spi_device *spi) { - struct chip_data *chip; struct fsl_dspi *dspi = spi_controller_get_devdata(spi->controller); - struct fsl_dspi_platform_data *pdata; - u32 cs_sck_delay = 0, sck_cs_delay = 0; unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; + u32 cs_sck_delay = 0, sck_cs_delay = 0; + struct fsl_dspi_platform_data *pdata; unsigned char pasc = 0, asc = 0; + struct chip_data *chip; unsigned long clkrate; /* Only alloc on first setup */ @@ -990,13 +990,13 @@ static void dspi_init(struct fsl_dspi *dspi) static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + const struct regmap_config *regmap_config; + struct fsl_dspi_platform_data *pdata; struct spi_controller *ctlr; + int ret, cs_num, bus_num; struct fsl_dspi *dspi; struct resource *res; - const struct regmap_config *regmap_config; void __iomem *base; - struct fsl_dspi_platform_data *pdata; - int ret, cs_num, bus_num; ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); if (!ctlr) From 206175306da1de0c116e8bc12db3230edb230d5a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:12 +0300 Subject: [PATCH 030/102] spi: spi-fsl-dspi: Fix typos mask of -> mask off at and -> and Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-12-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index e2e71bd73b5c..6128c695d06f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -232,7 +232,7 @@ static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata) if (!dspi->rx) return; - /* Mask of undefined bits */ + /* Mask off undefined bits */ rxdata &= (1 << dspi->bits_per_word) - 1; if (dspi->bytes_per_word == 1) @@ -642,7 +642,7 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) { int fifo_size = DSPI_FIFO_SIZE; - /* Read one FIFO entry at and push to rx buffer */ + /* Read one FIFO entry and push to rx buffer */ while ((dspi->rx < dspi->rx_end) && fifo_size--) dspi_push_rx(dspi, fifo_read(dspi)); } From a63af99f0d0d1c0992736f1aaf9e3b42bee0e2b8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 18 Aug 2019 21:01:13 +0300 Subject: [PATCH 031/102] spi: spi-fsl-dspi: Move dspi_interrupt above dspi_transfer_one_message The two functions are loosely coupled through dspi->waitq, but logically, dspi_transfer_one_message depends on dspi_interrupt in order to complete. Move its definition above it so the I/O functions are grouped closer together. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190818180115.31114-13-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 114 ++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6128c695d06f..790cb02fc181 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -647,6 +647,63 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) dspi_push_rx(dspi, fifo_read(dspi)); } +static irqreturn_t dspi_interrupt(int irq, void *dev_id) +{ + struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; + struct spi_message *msg = dspi->cur_msg; + enum dspi_trans_mode trans_mode; + u32 spi_sr, spi_tcr; + u16 spi_tcnt; + + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; + + trans_mode = dspi->devtype_data->trans_mode; + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_read(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_read(dspi); + break; + default: + dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", + trans_mode); + return IRQ_HANDLED; + } + + if (!dspi->len) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + } else { + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_write(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_write(dspi); + break; + default: + dev_err(&dspi->pdev->dev, + "unsupported trans_mode %u\n", + trans_mode); + } + } + } + + return IRQ_HANDLED; +} + static int dspi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *message) { @@ -825,63 +882,6 @@ static void dspi_cleanup(struct spi_device *spi) kfree(chip); } -static irqreturn_t dspi_interrupt(int irq, void *dev_id) -{ - struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; - struct spi_message *msg = dspi->cur_msg; - enum dspi_trans_mode trans_mode; - u32 spi_sr, spi_tcr; - u16 spi_tcnt; - - regmap_read(dspi->regmap, SPI_SR, &spi_sr); - regmap_write(dspi->regmap, SPI_SR, spi_sr); - - - if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { - /* Get transfer counter (in number of SPI transfers). It was - * reset to 0 when transfer(s) were started. - */ - regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); - spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); - /* Update total number of bytes that were transferred */ - msg->actual_length += spi_tcnt * dspi->bytes_per_word; - - trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } - - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - } else { - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } - } - } - - return IRQ_HANDLED; -} - static const struct of_device_id fsl_dspi_dt_ids[] = { { .compatible = "fsl,vf610-dspi", .data = &vf610_data, }, { .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, }, From 303290e130bfd504a8230f49e545f6b91e120553 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 13 Aug 2019 15:53:11 +0530 Subject: [PATCH 032/102] spi: fsl-qspi: Enhance binding to extend example for flash entry Add example for adding flash entry on various boards' dts using flash manufacture spansion/cypress. Signed-off-by: Ashish Kumar Link: https://lore.kernel.org/r/1565691791-26167-3-git-send-email-Ashish.Kumar@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt index e8f1d627d288..1b23cfd7b39b 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt @@ -34,7 +34,11 @@ qspi0: quadspi@40044000 { clock-names = "qspi_en", "qspi"; flash0: s25fl128s@0 { - .... + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s", "jedec,spi-nor"; + spi-max-frequency = <50000000>; + reg = <0>; }; }; From be28f76b7e8ffaf04690e30fd17683d8afea1fd9 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 13 Aug 2019 15:53:09 +0530 Subject: [PATCH 033/102] spi: spi-fsl-qspi: Add ls2080a compatibility string to bindings There are 2 version of QSPI-IP, according to which controller registers sets can be big endian or little endian.There are some other minor changes like RX fifo depth etc. The big endian version uses driver compatible "fsl,ls1021a-qspi" and little endian version uses driver compatible "fsl,ls2080a-qspi" Signed-off-by: Kuldeep Singh Signed-off-by: Ashish Kumar Reviewed-by: Rob Herring Acked-by: Han Xu Link: https://lore.kernel.org/r/1565691791-26167-1-git-send-email-Ashish.Kumar@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt index 1b23cfd7b39b..69dc5d57b1ef 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt @@ -3,9 +3,8 @@ Required properties: - compatible : Should be "fsl,vf610-qspi", "fsl,imx6sx-qspi", "fsl,imx7d-qspi", "fsl,imx6ul-qspi", - "fsl,ls1021a-qspi" + "fsl,ls1021a-qspi", "fsl,ls2080a-qspi" or - "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi", "fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi" - reg : the first contains the register location and length, the second contains the memory mapping address and length From d41f36a6464a85c06ad920703d878e4491d2c023 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:24:50 +0300 Subject: [PATCH 034/102] spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours The DSPI interrupt can be shared between two controllers at least on the LX2160A. In that case, the driver for one controller might misbehave and consume the other's interrupt. Fix this by actually checking if any of the bits in the status register have been asserted. Fixes: 13aed2392741 ("spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822212450.21420-2-olteanv@gmail.com Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-fsl-dspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 53335ccc98f6..545fc8189fb0 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -886,9 +886,11 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) trans_mode); } } + + return IRQ_HANDLED; } - return IRQ_HANDLED; + return IRQ_NONE; } static const struct of_device_id fsl_dspi_dt_ids[] = { From 12fb61a973935c63f2580b3b053017cc14b51f42 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:10 +0300 Subject: [PATCH 035/102] spi: spi-fsl-dspi: Reduce indentation level in dspi_interrupt If the entire function depends on the SPI status register having the interrupt bits asserted, then just check it and exit early if those bits aren't set (such as in the case of the shared IRQ being triggered for the other peripheral). Cosmetic patch. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-2-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 77 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 790cb02fc181..c90db7db4121 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -658,47 +658,48 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); + if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) + return IRQ_HANDLED; - if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { - /* Get transfer counter (in number of SPI transfers). It was - * reset to 0 when transfer(s) were started. - */ - regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); - spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); - /* Update total number of bytes that were transferred */ - msg->actual_length += spi_tcnt * dspi->bytes_per_word; + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; - trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } + trans_mode = dspi->devtype_data->trans_mode; + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_read(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_read(dspi); + break; + default: + dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", + trans_mode); + return IRQ_HANDLED; + } - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - } else { - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } - } + if (!dspi->len) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + return IRQ_HANDLED; + } + + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_write(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_write(dspi); + break; + default: + dev_err(&dspi->pdev->dev, + "unsupported trans_mode %u\n", + trans_mode); } return IRQ_HANDLED; From 37b4100180641968056cb4e034cebc38338e8652 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:11 +0300 Subject: [PATCH 036/102] spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours The DSPI interrupt can be shared between two controllers at least on the LX2160A. In that case, the driver for one controller might misbehave and consume the other's interrupt. Fix this by actually checking if any of the bits in the status register have been asserted. Fixes: 13aed2392741 ("spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-3-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c90db7db4121..6ef2279a3699 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -659,7 +659,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) regmap_write(dspi->regmap, SPI_SR, spi_sr); if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) - return IRQ_HANDLED; + return IRQ_NONE; /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. From 1eaeba70738e723be1e5787bdfd9a30f7471d730 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:12 +0300 Subject: [PATCH 037/102] spi: spi-fsl-dspi: Remove impossible to reach error check dspi->devtype_data is under the total control of the driver. Therefore, a bad value is a driver bug and checking it at runtime (and during an ISR, at that!) is pointless. The second "else if" check is only for clarity (instead of a broader "else") in case other transfer modes are added in the future. But the printing is dead code and can be removed. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-4-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6ef2279a3699..6d2c7984ab0e 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -670,18 +670,10 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) msg->actual_length += spi_tcnt * dspi->bytes_per_word; trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: + if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: + else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } if (!dspi->len) { dspi->waitflags = 1; @@ -689,18 +681,10 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - switch (trans_mode) { - case DSPI_EOQ_MODE: + if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: + else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } return IRQ_HANDLED; } From c55be305915974db160ce6472722ff74f45b8d4e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:13 +0300 Subject: [PATCH 038/102] spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing On platforms like LS1021A which use TCFQ mode, an interrupt needs to be processed after each byte is TXed/RXed. I tried to make the DSPI implementation on this SoC operate in other, more efficient modes (EOQ, DMA) but it looks like it simply isn't possible. Therefore allow the driver to operate in poll mode, to ease a bit of this absurd amount of IRQ load generated in TCFQ mode. Doing so reduces both the net time it takes to transmit a SPI message, as well as the inter-frame jitter that occurs while doing so. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-5-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 87 ++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6d2c7984ab0e..77db43f1290f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -647,19 +647,12 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) dspi_push_rx(dspi, fifo_read(dspi)); } -static irqreturn_t dspi_interrupt(int irq, void *dev_id) +static int dspi_rxtx(struct fsl_dspi *dspi) { - struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; struct spi_message *msg = dspi->cur_msg; enum dspi_trans_mode trans_mode; - u32 spi_sr, spi_tcr; u16 spi_tcnt; - - regmap_read(dspi->regmap, SPI_SR, &spi_sr); - regmap_write(dspi->regmap, SPI_SR, spi_sr); - - if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) - return IRQ_NONE; + u32 spi_tcr; /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. @@ -675,17 +668,55 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_read(dspi); - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - return IRQ_HANDLED; - } + if (!dspi->len) + /* Success! */ + return 0; if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_write(dspi); + return -EINPROGRESS; +} + +static int dspi_poll(struct fsl_dspi *dspi) +{ + int tries = 1000; + u32 spi_sr; + + do { + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) + break; + } while (--tries); + + if (!tries) + return -ETIMEDOUT; + + return dspi_rxtx(dspi); +} + +static irqreturn_t dspi_interrupt(int irq, void *dev_id) +{ + struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; + u32 spi_sr; + + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) + return IRQ_NONE; + + dspi_rxtx(dspi); + + if (!dspi->len) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + } + return IRQ_HANDLED; } @@ -773,13 +804,18 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, goto out; } - if (trans_mode != DSPI_DMA_MODE) { - if (wait_event_interruptible(dspi->waitq, - dspi->waitflags)) - dev_err(&dspi->pdev->dev, - "wait transfer complete fail!\n"); + if (!dspi->irq) { + do { + status = dspi_poll(dspi); + } while (status == -EINPROGRESS); + } else if (trans_mode != DSPI_DMA_MODE) { + status = wait_event_interruptible(dspi->waitq, + dspi->waitflags); dspi->waitflags = 0; } + if (status) + dev_err(&dspi->pdev->dev, + "Waiting for transfer to complete failed!\n"); if (transfer->delay_usecs) udelay(transfer->delay_usecs); @@ -1079,10 +1115,13 @@ static int dspi_probe(struct platform_device *pdev) goto out_ctlr_put; dspi_init(dspi); + dspi->irq = platform_get_irq(pdev, 0); - if (dspi->irq < 0) { - ret = dspi->irq; - goto out_clk_put; + if (dspi->irq <= 0) { + dev_info(&pdev->dev, + "can't get platform irq, using poll mode\n"); + dspi->irq = 0; + goto poll_mode; } ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, @@ -1092,6 +1131,9 @@ static int dspi_probe(struct platform_device *pdev) goto out_clk_put; } + init_waitqueue_head(&dspi->waitq); + +poll_mode: if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); if (ret < 0) { @@ -1103,7 +1145,6 @@ static int dspi_probe(struct platform_device *pdev) ctlr->max_speed_hz = clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; - init_waitqueue_head(&dspi->waitq); platform_set_drvdata(pdev, ctlr); ret = spi_register_controller(ctlr); From 0f0581b24bd019dfe32878e4c1bde266c7364e02 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 4 Aug 2019 02:35:39 +0200 Subject: [PATCH 039/102] spi: fsl: Convert to use CS GPIO descriptors This converts the Freescale SPI master driver to use GPIO descriptors for chip select handling. The Freescale (fsl) driver has a lot of quirks to look up "gpios" rather than "cs-gpios" from the device tree. After the prior patch that will make gpiolib return the GPIO descriptor for "gpios" in response to a request for "cs-gpios", this code can be cut down quite a bit. The driver has custom handling of chip select rather than using the core (which may be possible but not done in this patch) so it still needs to refer directly to spi->cs_gpiod to set the chip select. Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190804003539.985-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lib.h | 3 - drivers/spi/spi-fsl-spi.c | 193 +++++--------------------------------- 2 files changed, 25 insertions(+), 171 deletions(-) diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 3576167283dc..015a1abb6a84 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -91,9 +91,6 @@ static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) struct mpc8xxx_spi_probe_info { struct fsl_spi_platform_data pdata; - int ngpios; - int *gpios; - bool *alow_flags; __be32 __iomem *immr_spi_cs; }; diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 1d9b33aa1a3b..4b80ace1d137 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -481,32 +480,6 @@ static int fsl_spi_setup(struct spi_device *spi) return retval; } - if (mpc8xxx_spi->type == TYPE_GRLIB) { - if (gpio_is_valid(spi->cs_gpio)) { - int desel; - - retval = gpio_request(spi->cs_gpio, - dev_name(&spi->dev)); - if (retval) - return retval; - - desel = !(spi->mode & SPI_CS_HIGH); - retval = gpio_direction_output(spi->cs_gpio, desel); - if (retval) { - gpio_free(spi->cs_gpio); - return retval; - } - } else if (spi->cs_gpio != -ENOENT) { - if (spi->cs_gpio < 0) - return spi->cs_gpio; - return -EINVAL; - } - /* When spi->cs_gpio == -ENOENT, a hole in the phandle list - * indicates to use native chipselect if present, or allow for - * an always selected chip - */ - } - /* Initialize chipselect - might be active for SPI_CS_HIGH mode */ fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); @@ -515,12 +488,8 @@ static int fsl_spi_setup(struct spi_device *spi) static void fsl_spi_cleanup(struct spi_device *spi) { - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); - if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); - kfree(cs); spi_set_ctldata(spi, NULL); } @@ -586,8 +555,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) u32 slvsel; u16 cs = spi->chip_select; - if (gpio_is_valid(spi->cs_gpio)) { - gpio_set_value(spi->cs_gpio, on); + if (spi->cs_gpiod) { + gpiod_set_value(spi->cs_gpiod, on); } else if (cs < mpc8xxx_spi->native_chipselects) { slvsel = mpc8xxx_spi_read_reg(®_base->slvsel); slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); @@ -718,139 +687,19 @@ err: static void fsl_spi_cs_control(struct spi_device *spi, bool on) { - struct device *dev = spi->dev.parent->parent; - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - u16 cs = spi->chip_select; - - if (cs < pinfo->ngpios) { - int gpio = pinfo->gpios[cs]; - bool alow = pinfo->alow_flags[cs]; - - gpio_set_value(gpio, on ^ alow); + if (spi->cs_gpiod) { + gpiod_set_value(spi->cs_gpiod, on); } else { - if (WARN_ON_ONCE(cs > pinfo->ngpios || !pinfo->immr_spi_cs)) + struct device *dev = spi->dev.parent->parent; + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); + struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); + + if (WARN_ON_ONCE(!pinfo->immr_spi_cs)) return; iowrite32be(on ? SPI_BOOT_SEL_BIT : 0, pinfo->immr_spi_cs); } } -static int of_fsl_spi_get_chipselects(struct device *dev) -{ - struct device_node *np = dev->of_node; - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - bool spisel_boot = IS_ENABLED(CONFIG_FSL_SOC) && - of_property_read_bool(np, "fsl,spisel_boot"); - int ngpios; - int i = 0; - int ret; - - ngpios = of_gpio_count(np); - ngpios = max(ngpios, 0); - if (ngpios == 0 && !spisel_boot) { - /* - * SPI w/o chip-select line. One SPI device is still permitted - * though. - */ - pdata->max_chipselect = 1; - return 0; - } - - pinfo->ngpios = ngpios; - pinfo->gpios = kmalloc_array(ngpios, sizeof(*pinfo->gpios), - GFP_KERNEL); - if (!pinfo->gpios) - return -ENOMEM; - memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios)); - - pinfo->alow_flags = kcalloc(ngpios, sizeof(*pinfo->alow_flags), - GFP_KERNEL); - if (!pinfo->alow_flags) { - ret = -ENOMEM; - goto err_alloc_flags; - } - - for (; i < ngpios; i++) { - int gpio; - enum of_gpio_flags flags; - - gpio = of_get_gpio_flags(np, i, &flags); - if (!gpio_is_valid(gpio)) { - dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); - ret = gpio; - goto err_loop; - } - - ret = gpio_request(gpio, dev_name(dev)); - if (ret) { - dev_err(dev, "can't request gpio #%d: %d\n", i, ret); - goto err_loop; - } - - pinfo->gpios[i] = gpio; - pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW; - - ret = gpio_direction_output(pinfo->gpios[i], - pinfo->alow_flags[i]); - if (ret) { - dev_err(dev, - "can't set output direction for gpio #%d: %d\n", - i, ret); - goto err_loop; - } - } - -#if IS_ENABLED(CONFIG_FSL_SOC) - if (spisel_boot) { - pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); - if (!pinfo->immr_spi_cs) { - ret = -ENOMEM; - i = ngpios - 1; - goto err_loop; - } - } -#endif - - pdata->max_chipselect = ngpios + spisel_boot; - pdata->cs_control = fsl_spi_cs_control; - - return 0; - -err_loop: - while (i >= 0) { - if (gpio_is_valid(pinfo->gpios[i])) - gpio_free(pinfo->gpios[i]); - i--; - } - - kfree(pinfo->alow_flags); - pinfo->alow_flags = NULL; -err_alloc_flags: - kfree(pinfo->gpios); - pinfo->gpios = NULL; - return ret; -} - -static int of_fsl_spi_free_chipselects(struct device *dev) -{ - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - int i; - - if (!pinfo->gpios) - return 0; - - for (i = 0; i < pdata->max_chipselect; i++) { - if (gpio_is_valid(pinfo->gpios[i])) - gpio_free(pinfo->gpios[i]); - } - - kfree(pinfo->gpios); - kfree(pinfo->alow_flags); - return 0; -} - static int of_fsl_spi_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; @@ -866,9 +715,21 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) type = fsl_spi_get_type(&ofdev->dev); if (type == TYPE_FSL) { - ret = of_fsl_spi_get_chipselects(dev); - if (ret) - goto err; + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); +#if IS_ENABLED(CONFIG_FSL_SOC) + struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); + bool spisel_boot = of_property_read_bool(np, "fsl,spisel_boot"); + + if (spisel_boot) { + pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); + if (!pinfo->immr_spi_cs) { + ret = -ENOMEM; + goto err; + } + } +#endif + + pdata->cs_control = fsl_spi_cs_control; } ret = of_address_to_resource(np, 0, &mem); @@ -891,8 +752,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) err: irq_dispose_mapping(irq); - if (type == TYPE_FSL) - of_fsl_spi_free_chipselects(dev); return ret; } @@ -902,8 +761,6 @@ static int of_fsl_spi_remove(struct platform_device *ofdev) struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); fsl_spi_cpm_free(mpc8xxx_spi); - if (mpc8xxx_spi->type == TYPE_FSL) - of_fsl_spi_free_chipselects(&ofdev->dev); return 0; } From 3bd158c56a56e8767e569d7fbc66efbedc478077 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 4 Aug 2019 02:38:52 +0200 Subject: [PATCH 040/102] spi: bcm2835: Convert to use CS GPIO descriptors This converts the BCM2835 SPI master driver to use GPIO descriptors for chip select handling. The BCM2835 driver was relying on the core to drive the CS high/low so very small changes were needed for this part. If it managed to request the CS from the device tree node, all is pretty straight forward. However for native GPIOs this driver has a quite unorthodox loopback to request some GPIOs from the SoC GPIO chip by looking it up from the device tree using gpiochip_find() and then offseting hard into its numberspace. This has been augmented a bit by using gpiochip_request_own_desc() but this code really needs to be verified. If "native CS" is actually an SoC GPIO, why is it even done this way? Should this GPIO not just be defined in the device tree like any other CS GPIO? I'm confused. Cc: Lukas Wunner Cc: Stefan Wahren Cc: Martin Sperl Cc: Chris Boot Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190804003852.1312-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 58 +++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 4b89e0a04ffd..fd2bfb4aa8c3 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -25,7 +25,9 @@ #include #include #include -#include +#include +#include /* FIXME: using chip internals */ +#include /* FIXME: using chip internals */ #include #include @@ -931,14 +933,19 @@ static int chip_match_name(struct gpio_chip *chip, void *data) static int bcm2835_spi_setup(struct spi_device *spi) { - int err; struct gpio_chip *chip; + enum gpio_lookup_flags lflags; + /* * sanity checking the native-chipselects */ if (spi->mode & SPI_NO_CS) return 0; - if (gpio_is_valid(spi->cs_gpio)) + /* + * The SPI core has successfully requested the CS GPIO line from the + * device tree, so we are done. + */ + if (spi->cs_gpiod) return 0; if (spi->chip_select > 1) { /* error in the case of native CS requested with CS > 1 @@ -949,29 +956,43 @@ static int bcm2835_spi_setup(struct spi_device *spi) "setup: only two native chip-selects are supported\n"); return -EINVAL; } - /* now translate native cs to GPIO */ + + /* + * Translate native CS to GPIO + * + * FIXME: poking around in the gpiolib internals like this is + * not very good practice. Find a way to locate the real problem + * and fix it. Why is the GPIO descriptor in spi->cs_gpiod + * sometimes not assigned correctly? Erroneous device trees? + */ /* get the gpio chip for the base */ chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); if (!chip) return 0; - /* and calculate the real CS */ - spi->cs_gpio = chip->base + 8 - spi->chip_select; + /* + * Retrieve the corresponding GPIO line used for CS. + * The inversion semantics will be handled by the GPIO core + * code, so we pass GPIOS_OUT_LOW for "unasserted" and + * the correct flag for inversion semantics. The SPI_CS_HIGH + * on spi->mode cannot be checked for polarity in this case + * as the flag use_gpio_descriptors enforces SPI_CS_HIGH. + */ + if (of_property_read_bool(spi->dev.of_node, "spi-cs-high")) + lflags = GPIO_ACTIVE_HIGH; + else + lflags = GPIO_ACTIVE_LOW; + spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select, + DRV_NAME, + lflags, + GPIOD_OUT_LOW); + if (IS_ERR(spi->cs_gpiod)) + return PTR_ERR(spi->cs_gpiod); /* and set up the "mode" and level */ - dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", - spi->chip_select, spi->cs_gpio); - - /* set up GPIO as output and pull to the correct level */ - err = gpio_direction_output(spi->cs_gpio, - (spi->mode & SPI_CS_HIGH) ? 0 : 1); - if (err) { - dev_err(&spi->dev, - "could not set CS%i gpio %i as output: %i", - spi->chip_select, spi->cs_gpio, err); - return err; - } + dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n", + spi->chip_select); return 0; } @@ -989,6 +1010,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctlr); + ctlr->use_gpio_descriptors = true; ctlr->mode_bits = BCM2835_SPI_MODE_BITS; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); ctlr->num_chipselect = 3; From 94e9c0f522142e47348486f98916cb0b16e72571 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 29 Aug 2019 15:50:00 +0300 Subject: [PATCH 041/102] spi: dw-pci: Add MODULE_DEVICE_TABLE MODULE_DEVICE_TABLE is missing from the PCI part of the driver. Add it so userspace can autoload the the driver when it is built as module. Signed-off-by: Jarkko Nikula Link: https://lore.kernel.org/r/20190829125000.26303-1-jarkko.nikula@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index e9ba63814548..90e7b789da3b 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -140,6 +140,7 @@ static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc}, {}, }; +MODULE_DEVICE_TABLE(pci, pci_ids); static struct pci_driver dw_spi_driver = { .name = DRIVER_NAME, From 91d0c59f460fd61db977d35b0d7c057128e7f7b7 Mon Sep 17 00:00:00 2001 From: Tomer Maimon Date: Wed, 28 Aug 2019 17:25:12 +0300 Subject: [PATCH 042/102] dt-binding: spi: add NPCM FIU controller Added device tree binding documentation for Nuvoton BMC NPCM Flash Interface Unit(FIU) SPI master controller using SPI-MEM interface. Signed-off-by: Tomer Maimon Link: https://lore.kernel.org/r/20190828142513.228556-2-tmaimon77@gmail.com Signed-off-by: Mark Brown --- .../bindings/spi/nuvoton,npcm-fiu.txt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt diff --git a/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt new file mode 100644 index 000000000000..a388005842ad --- /dev/null +++ b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt @@ -0,0 +1,47 @@ +* Nuvoton FLASH Interface Unit (FIU) SPI Controller + +NPCM FIU supports single, dual and quad communication interface. + +The NPCM7XX supports three FIU modules, +FIU0 and FIUx supports two chip selects, +FIU3 support four chip select. + +Required properties: + - compatible : "nuvoton,npcm750-fiu" for the NPCM7XX BMC + - #address-cells : should be 1. + - #size-cells : should be 0. + - reg : the first contains the register location and length, + the second contains the memory mapping address and length + - reg-names: Should contain the reg names "control" and "memory" + - clocks : phandle of FIU reference clock. + +Required properties in case the pins can be muxed: + - pinctrl-names : a pinctrl state named "default" must be defined. + - pinctrl-0 : phandle referencing pin configuration of the device. + +Optional property: + - nuvoton,spix-mode: enable spix-mode for an expansion bus to an ASIC or CPLD. + +Aliases: +- All the FIU controller nodes should be represented in the aliases node using + the following format 'fiu{n}' where n is a unique number for the alias. + In the NPCM7XX BMC: + fiu0 represent fiu 0 controller + fiu1 represent fiu 3 controller + fiu2 represent fiu x controller + +Example: +fiu3: spi@c00000000 { + compatible = "nuvoton,npcm750-fiu"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xfb000000 0x1000>, <0x80000000 0x10000000>; + reg-names = "control", "memory"; + clocks = <&clk NPCM7XX_CLK_AHB>; + pinctrl-names = "default"; + pinctrl-0 = <&spi3_pins>; + spi-nor@0 { + ... + }; +}; + From ace55c411b11d9b12f500c7433bf469c26130182 Mon Sep 17 00:00:00 2001 From: Tomer Maimon Date: Wed, 28 Aug 2019 17:25:13 +0300 Subject: [PATCH 043/102] spi: npcm-fiu: add NPCM FIU controller driver Add Nuvoton NPCM BMC Flash Interface Unit(FIU) SPI master controller driver using SPI-MEM interface. The FIU supports single, dual or quad communication interface. the FIU controller can operate in following modes: - User Mode Access(UMA): provides flash access by using an indirect address/data mechanism. - direct rd/wr mode: maps the flash memory into the core address space. - SPI-X mode: used for an expansion bus to an ASIC or CPLD. Signed-off-by: Tomer Maimon Link: https://lore.kernel.org/r/20190828142513.228556-3-tmaimon77@gmail.com Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 10 + drivers/spi/Makefile | 1 + drivers/spi/spi-npcm-fiu.c | 771 +++++++++++++++++++++++++++++++++++++ 3 files changed, 782 insertions(+) create mode 100644 drivers/spi/spi-npcm-fiu.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3a1d8f1170de..6ee514fd0920 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -433,6 +433,16 @@ config SPI_MT7621 help This selects a driver for the MediaTek MT7621 SPI Controller. +config SPI_NPCM_FIU + tristate "Nuvoton NPCM FLASH Interface Unit" + depends on ARCH_NPCM || COMPILE_TEST + depends on OF && HAS_IOMEM + help + This enables support for the Flash Interface Unit SPI controller + in master mode. + This driver does not support generic SPI. The implementation only + supports spi-mem interface. + config SPI_NPCM_PSPI tristate "Nuvoton NPCM PSPI Controller" depends on ARCH_NPCM || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 63dcab552bcb..adbebee93a75 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o +obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c new file mode 100644 index 000000000000..3ea1ec68147e --- /dev/null +++ b/drivers/spi/spi-npcm-fiu.c @@ -0,0 +1,771 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* NPCM7xx GCR module */ +#define NPCM7XX_INTCR3_OFFSET 0x9C +#define NPCM7XX_INTCR3_FIU_FIX BIT(6) + +/* Flash Interface Unit (FIU) Registers */ +#define NPCM_FIU_DRD_CFG 0x00 +#define NPCM_FIU_DWR_CFG 0x04 +#define NPCM_FIU_UMA_CFG 0x08 +#define NPCM_FIU_UMA_CTS 0x0C +#define NPCM_FIU_UMA_CMD 0x10 +#define NPCM_FIU_UMA_ADDR 0x14 +#define NPCM_FIU_PRT_CFG 0x18 +#define NPCM_FIU_UMA_DW0 0x20 +#define NPCM_FIU_UMA_DW1 0x24 +#define NPCM_FIU_UMA_DW2 0x28 +#define NPCM_FIU_UMA_DW3 0x2C +#define NPCM_FIU_UMA_DR0 0x30 +#define NPCM_FIU_UMA_DR1 0x34 +#define NPCM_FIU_UMA_DR2 0x38 +#define NPCM_FIU_UMA_DR3 0x3C +#define NPCM_FIU_MAX_REG_LIMIT 0x80 + +/* FIU Direct Read Configuration Register */ +#define NPCM_FIU_DRD_CFG_LCK BIT(31) +#define NPCM_FIU_DRD_CFG_R_BURST GENMASK(25, 24) +#define NPCM_FIU_DRD_CFG_ADDSIZ GENMASK(17, 16) +#define NPCM_FIU_DRD_CFG_DBW GENMASK(13, 12) +#define NPCM_FIU_DRD_CFG_ACCTYPE GENMASK(9, 8) +#define NPCM_FIU_DRD_CFG_RDCMD GENMASK(7, 0) +#define NPCM_FIU_DRD_ADDSIZ_SHIFT 16 +#define NPCM_FIU_DRD_DBW_SHIFT 12 +#define NPCM_FIU_DRD_ACCTYPE_SHIFT 8 + +/* FIU Direct Write Configuration Register */ +#define NPCM_FIU_DWR_CFG_LCK BIT(31) +#define NPCM_FIU_DWR_CFG_W_BURST GENMASK(25, 24) +#define NPCM_FIU_DWR_CFG_ADDSIZ GENMASK(17, 16) +#define NPCM_FIU_DWR_CFG_ABPCK GENMASK(11, 10) +#define NPCM_FIU_DWR_CFG_DBPCK GENMASK(9, 8) +#define NPCM_FIU_DWR_CFG_WRCMD GENMASK(7, 0) +#define NPCM_FIU_DWR_ADDSIZ_SHIFT 16 +#define NPCM_FIU_DWR_ABPCK_SHIFT 10 +#define NPCM_FIU_DWR_DBPCK_SHIFT 8 + +/* FIU UMA Configuration Register */ +#define NPCM_FIU_UMA_CFG_LCK BIT(31) +#define NPCM_FIU_UMA_CFG_CMMLCK BIT(30) +#define NPCM_FIU_UMA_CFG_RDATSIZ GENMASK(28, 24) +#define NPCM_FIU_UMA_CFG_DBSIZ GENMASK(23, 21) +#define NPCM_FIU_UMA_CFG_WDATSIZ GENMASK(20, 16) +#define NPCM_FIU_UMA_CFG_ADDSIZ GENMASK(13, 11) +#define NPCM_FIU_UMA_CFG_CMDSIZ BIT(10) +#define NPCM_FIU_UMA_CFG_RDBPCK GENMASK(9, 8) +#define NPCM_FIU_UMA_CFG_DBPCK GENMASK(7, 6) +#define NPCM_FIU_UMA_CFG_WDBPCK GENMASK(5, 4) +#define NPCM_FIU_UMA_CFG_ADBPCK GENMASK(3, 2) +#define NPCM_FIU_UMA_CFG_CMBPCK GENMASK(1, 0) +#define NPCM_FIU_UMA_CFG_ADBPCK_SHIFT 2 +#define NPCM_FIU_UMA_CFG_WDBPCK_SHIFT 4 +#define NPCM_FIU_UMA_CFG_DBPCK_SHIFT 6 +#define NPCM_FIU_UMA_CFG_RDBPCK_SHIFT 8 +#define NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT 11 +#define NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT 16 +#define NPCM_FIU_UMA_CFG_DBSIZ_SHIFT 21 +#define NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT 24 + +/* FIU UMA Control and Status Register */ +#define NPCM_FIU_UMA_CTS_RDYIE BIT(25) +#define NPCM_FIU_UMA_CTS_RDYST BIT(24) +#define NPCM_FIU_UMA_CTS_SW_CS BIT(16) +#define NPCM_FIU_UMA_CTS_DEV_NUM GENMASK(9, 8) +#define NPCM_FIU_UMA_CTS_EXEC_DONE BIT(0) +#define NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT 8 + +/* FIU UMA Command Register */ +#define NPCM_FIU_UMA_CMD_DUM3 GENMASK(31, 24) +#define NPCM_FIU_UMA_CMD_DUM2 GENMASK(23, 16) +#define NPCM_FIU_UMA_CMD_DUM1 GENMASK(15, 8) +#define NPCM_FIU_UMA_CMD_CMD GENMASK(7, 0) + +/* FIU UMA Address Register */ +#define NPCM_FIU_UMA_ADDR_UMA_ADDR GENMASK(31, 0) +#define NPCM_FIU_UMA_ADDR_AB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_ADDR_AB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_ADDR_AB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_ADDR_AB0 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 0-3 Register */ +#define NPCM_FIU_UMA_DW0_WB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW0_WB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW0_WB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW0_WB0 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 4-7 Register */ +#define NPCM_FIU_UMA_DW1_WB7 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW1_WB6 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW1_WB5 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW1_WB4 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 8-11 Register */ +#define NPCM_FIU_UMA_DW2_WB11 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW2_WB10 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW2_WB9 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW2_WB8 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 12-15 Register */ +#define NPCM_FIU_UMA_DW3_WB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW3_WB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW3_WB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW3_WB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 0-3 Register */ +#define NPCM_FIU_UMA_DR0_RB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR0_RB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR0_RB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR0_RB0 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 4-7 Register */ +#define NPCM_FIU_UMA_DR1_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR1_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR1_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR1_RB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 8-11 Register */ +#define NPCM_FIU_UMA_DR2_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR2_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR2_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR2_RB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 12-15 Register */ +#define NPCM_FIU_UMA_DR3_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR3_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR3_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR3_RB12 GENMASK(7, 0) + +/* FIU Read Mode */ +enum { + DRD_SINGLE_WIRE_MODE = 0, + DRD_DUAL_IO_MODE = 1, + DRD_QUAD_IO_MODE = 2, + DRD_SPI_X_MODE = 3, +}; + +enum { + DWR_ABPCK_BIT_PER_CLK = 0, + DWR_ABPCK_2_BIT_PER_CLK = 1, + DWR_ABPCK_4_BIT_PER_CLK = 2, +}; + +enum { + DWR_DBPCK_BIT_PER_CLK = 0, + DWR_DBPCK_2_BIT_PER_CLK = 1, + DWR_DBPCK_4_BIT_PER_CLK = 2, +}; + +#define NPCM_FIU_DRD_16_BYTE_BURST 0x3000000 +#define NPCM_FIU_DWR_16_BYTE_BURST 0x3000000 + +#define MAP_SIZE_128MB 0x8000000 +#define MAP_SIZE_16MB 0x1000000 +#define MAP_SIZE_8MB 0x800000 + +#define NUM_BITS_IN_BYTE 8 +#define FIU_DRD_MAX_DUMMY_NUMBER 3 +#define NPCM_MAX_CHIP_NUM 4 +#define CHUNK_SIZE 16 +#define UMA_MICRO_SEC_TIMEOUT 150 + +enum { + FIU0 = 0, + FIU3, + FIUX, +}; + +struct npcm_fiu_info { + char *name; + u32 fiu_id; + u32 max_map_size; + u32 max_cs; +}; + +struct fiu_data { + const struct npcm_fiu_info *npcm_fiu_data_info; + int fiu_max; +}; + +static const struct npcm_fiu_info npxm7xx_fiu_info[] = { + {.name = "FIU0", .fiu_id = FIU0, + .max_map_size = MAP_SIZE_128MB, .max_cs = 2}, + {.name = "FIU3", .fiu_id = FIU3, + .max_map_size = MAP_SIZE_128MB, .max_cs = 4}, + {.name = "FIUX", .fiu_id = FIUX, + .max_map_size = MAP_SIZE_16MB, .max_cs = 2} }; + +static const struct fiu_data npxm7xx_fiu_data = { + .npcm_fiu_data_info = npxm7xx_fiu_info, + .fiu_max = 3, +}; + +struct npcm_fiu_spi; + +struct npcm_fiu_chip { + void __iomem *flash_region_mapped_ptr; + struct npcm_fiu_spi *fiu; + unsigned long clkrate; + u32 chipselect; +}; + +struct npcm_fiu_spi { + struct npcm_fiu_chip chip[NPCM_MAX_CHIP_NUM]; + const struct npcm_fiu_info *info; + struct spi_mem_op drd_op; + struct resource *res_mem; + struct regmap *regmap; + unsigned long clkrate; + struct device *dev; + struct clk *clk; + bool spix_mode; +}; + +static const struct regmap_config npcm_mtd_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = NPCM_FIU_MAX_REG_LIMIT, +}; + +static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu, + const struct spi_mem_op *op) +{ + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ACCTYPE, + ilog2(op->addr.buswidth) << + NPCM_FIU_DRD_ACCTYPE_SHIFT); + fiu->drd_op.addr.buswidth = op->addr.buswidth; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_DBW, + ((op->dummy.nbytes * ilog2(op->addr.buswidth)) + / NUM_BITS_IN_BYTE) << NPCM_FIU_DRD_DBW_SHIFT); + fiu->drd_op.dummy.nbytes = op->dummy.nbytes; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode); + fiu->drd_op.cmd.opcode = op->cmd.opcode; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ADDSIZ, + (op->addr.nbytes - 3) << NPCM_FIU_DRD_ADDSIZ_SHIFT); + fiu->drd_op.addr.nbytes = op->addr.nbytes; +} + +static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + void __iomem *src = (void __iomem *)(chip->flash_region_mapped_ptr + + offs); + u8 *buf_rx = buf; + u32 i; + + if (fiu->spix_mode) { + for (i = 0 ; i < len ; i++) + *(buf_rx + i) = ioread8(src + i); + } else { + if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth || + desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes || + desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode || + desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes) + npcm_fiu_set_drd(fiu, &desc->info.op_tmpl); + + memcpy_fromio(buf_rx, src, len); + } + + return len; +} + +static ssize_t npcm_fiu_direct_write(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, const void *buf) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + void __iomem *dst = (void __iomem *)(chip->flash_region_mapped_ptr + + offs); + const u8 *buf_tx = buf; + u32 i; + + if (fiu->spix_mode) + for (i = 0 ; i < len ; i++) + iowrite8(*(buf_tx + i), dst + i); + else + memcpy_toio(dst, buf_tx, len); + + return len; +} + +static int npcm_fiu_uma_read(struct spi_mem *mem, + const struct spi_mem_op *op, u32 addr, + bool is_address_size, u8 *data, u32 data_size) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u32 uma_cfg = BIT(10); + u32 data_reg[4]; + int ret; + u32 val; + u32 i; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD, + NPCM_FIU_UMA_CMD_CMD, op->cmd.opcode); + + if (is_address_size) { + uma_cfg |= ilog2(op->cmd.buswidth); + uma_cfg |= ilog2(op->addr.buswidth) + << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; + uma_cfg |= ilog2(op->dummy.buswidth) + << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; + uma_cfg |= ilog2(op->data.buswidth) + << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT; + uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; + uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr); + } else { + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0); + } + + uma_cfg |= data_size << NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg); + regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_EXEC_DONE, + NPCM_FIU_UMA_CTS_EXEC_DONE); + ret = regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val, + (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0, + UMA_MICRO_SEC_TIMEOUT); + if (ret) + return ret; + + if (data_size) { + for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++) + regmap_read(fiu->regmap, NPCM_FIU_UMA_DR0 + (i * 4), + &data_reg[i]); + memcpy(data, data_reg, data_size); + } + + return 0; +} + +static int npcm_fiu_uma_write(struct spi_mem *mem, + const struct spi_mem_op *op, u8 cmd, + bool is_address_size, u8 *data, u32 data_size) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u32 uma_cfg = BIT(10); + u32 data_reg[4] = {0}; + u32 val; + u32 i; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD, + NPCM_FIU_UMA_CMD_CMD, cmd); + + if (data_size) { + memcpy(data_reg, data, data_size); + for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++) + regmap_write(fiu->regmap, NPCM_FIU_UMA_DW0 + (i * 4), + data_reg[i]); + } + + if (is_address_size) { + uma_cfg |= ilog2(op->cmd.buswidth); + uma_cfg |= ilog2(op->addr.buswidth) << + NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; + uma_cfg |= ilog2(op->data.buswidth) << + NPCM_FIU_UMA_CFG_WDBPCK_SHIFT; + uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, op->addr.val); + } else { + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0); + } + + uma_cfg |= (data_size << NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT); + regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg); + + regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_EXEC_DONE, + NPCM_FIU_UMA_CTS_EXEC_DONE); + + return regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val, + (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0, + UMA_MICRO_SEC_TIMEOUT); +} + +static int npcm_fiu_manualwrite(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u8 *data = (u8 *)op->data.buf.out; + u32 num_data_chunks; + u32 remain_data; + u32 idx = 0; + int ret; + + num_data_chunks = op->data.nbytes / CHUNK_SIZE; + remain_data = op->data.nbytes % CHUNK_SIZE; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_SW_CS, 0); + + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, true, NULL, 0); + if (ret) + return ret; + + /* Starting the data writing loop in multiples of 8 */ + for (idx = 0; idx < num_data_chunks; ++idx) { + ret = npcm_fiu_uma_write(mem, op, data[0], false, + &data[1], CHUNK_SIZE - 1); + if (ret) + return ret; + + data += CHUNK_SIZE; + } + + /* Handling chunk remains */ + if (remain_data > 0) { + ret = npcm_fiu_uma_write(mem, op, data[0], false, + &data[1], remain_data - 1); + if (ret) + return ret; + } + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_SW_CS, NPCM_FIU_UMA_CTS_SW_CS); + + return 0; +} + +static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op) +{ + u8 *data = op->data.buf.in; + int i, readlen, currlen; + size_t retlen = 0; + u8 *buf_ptr; + u32 addr; + int ret; + + i = 0; + currlen = op->data.nbytes; + + do { + addr = ((u32)op->addr.val + i); + if (currlen < 16) + readlen = currlen; + else + readlen = 16; + + buf_ptr = data + i; + ret = npcm_fiu_uma_read(mem, op, addr, true, buf_ptr, + readlen); + if (ret) + return ret; + + i += readlen; + currlen -= 16; + } while (currlen > 0); + + retlen = i; + + return 0; +} + +static void npcm_fiux_set_direct_wr(struct npcm_fiu_spi *fiu) +{ + regmap_write(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_16_BYTE_BURST); + regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_CFG_ABPCK, + DWR_ABPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_ABPCK_SHIFT); + regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_CFG_DBPCK, + DWR_DBPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_DBPCK_SHIFT); +} + +static void npcm_fiux_set_direct_rd(struct npcm_fiu_spi *fiu) +{ + u32 rx_dummy = 0; + + regmap_write(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_16_BYTE_BURST); + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ACCTYPE, + DRD_SPI_X_MODE << NPCM_FIU_DRD_ACCTYPE_SHIFT); + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_DBW, + rx_dummy << NPCM_FIU_DRD_DBW_SHIFT); +} + +static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[mem->spi->chip_select]; + int ret = 0; + u8 *buf; + + dev_dbg(fiu->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", + op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, op->addr.val, + op->data.nbytes); + + if (fiu->spix_mode || op->addr.nbytes > 4) + return -ENOTSUPP; + + if (fiu->clkrate != chip->clkrate) { + ret = clk_set_rate(fiu->clk, chip->clkrate); + if (ret < 0) + dev_warn(fiu->dev, "Failed setting %lu frequancy, stay at %lu frequancy\n", chip->clkrate, fiu->clkrate); + else + fiu->clkrate = chip->clkrate; + } + + if (op->data.dir == SPI_MEM_DATA_IN) { + if (!op->addr.nbytes) { + buf = op->data.buf.in; + ret = npcm_fiu_uma_read(mem, op, op->addr.val, false, + buf, op->data.nbytes); + } else { + ret = npcm_fiu_read(mem, op); + } + } else { + if (!op->addr.nbytes && !op->data.nbytes) + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + NULL, 0); + if (op->addr.nbytes && !op->data.nbytes) { + int i; + u8 buf_addr[4]; + u32 addr = op->addr.val; + + for (i = op->addr.nbytes - 1; i >= 0; i--) { + buf_addr[i] = addr & 0xff; + addr >>= 8; + } + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + buf_addr, op->addr.nbytes); + } + if (!op->addr.nbytes && op->data.nbytes) + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + (u8 *)op->data.buf.out, + op->data.nbytes); + if (op->addr.nbytes && op->data.nbytes) + ret = npcm_fiu_manualwrite(mem, op); + } + + return ret; +} + +static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + struct regmap *gcr_regmap; + + if (!fiu->res_mem) { + dev_warn(fiu->dev, "Reserved memory not defined, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + + if (!fiu->spix_mode && + desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) { + desc->nodirmap = true; + return 0; + } + + if (!chip->flash_region_mapped_ptr) { + chip->flash_region_mapped_ptr = + devm_ioremap_nocache(fiu->dev, (fiu->res_mem->start + + (fiu->info->max_map_size * + desc->mem->spi->chip_select)), + (u32)desc->info.length); + if (!chip->flash_region_mapped_ptr) { + dev_warn(fiu->dev, "Error mapping memory region, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + } + + if (of_device_is_compatible(fiu->dev->of_node, "nuvoton,npcm750-fiu")) { + gcr_regmap = + syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); + if (IS_ERR(gcr_regmap)) { + dev_warn(fiu->dev, "Didn't find nuvoton,npcm750-gcr, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + regmap_update_bits(gcr_regmap, NPCM7XX_INTCR3_OFFSET, + NPCM7XX_INTCR3_FIU_FIX, + NPCM7XX_INTCR3_FIU_FIX); + } + + if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) { + if (!fiu->spix_mode) + npcm_fiu_set_drd(fiu, &desc->info.op_tmpl); + else + npcm_fiux_set_direct_rd(fiu); + + } else { + npcm_fiux_set_direct_wr(fiu); + } + + return 0; +} + +static int npcm_fiu_setup(struct spi_device *spi) +{ + struct spi_controller *ctrl = spi->master; + struct npcm_fiu_spi *fiu = spi_controller_get_devdata(ctrl); + struct npcm_fiu_chip *chip; + + chip = &fiu->chip[spi->chip_select]; + chip->fiu = fiu; + chip->chipselect = spi->chip_select; + chip->clkrate = spi->max_speed_hz; + + fiu->clkrate = clk_get_rate(fiu->clk); + + return 0; +} + +static const struct spi_controller_mem_ops npcm_fiu_mem_ops = { + .exec_op = npcm_fiu_exec_op, + .dirmap_create = npcm_fiu_dirmap_create, + .dirmap_read = npcm_fiu_direct_read, + .dirmap_write = npcm_fiu_direct_write, +}; + +static const struct of_device_id npcm_fiu_dt_ids[] = { + { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data }, + { /* sentinel */ } +}; + +static int npcm_fiu_probe(struct platform_device *pdev) +{ + const struct fiu_data *fiu_data_match; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct spi_controller *ctrl; + struct npcm_fiu_spi *fiu; + void __iomem *regbase; + struct resource *res; + int ret; + int id; + + ctrl = spi_alloc_master(dev, sizeof(*fiu)); + if (!ctrl) + return -ENOMEM; + + fiu = spi_controller_get_devdata(ctrl); + + match = of_match_device(npcm_fiu_dt_ids, dev); + if (!match || !match->data) { + dev_err(dev, "No compatible OF match\n"); + return -ENODEV; + } + + fiu_data_match = match->data; + id = of_alias_get_id(dev->of_node, "fiu"); + if (id < 0 || id >= fiu_data_match->fiu_max) { + dev_err(dev, "Invalid platform device id: %d\n", id); + return -EINVAL; + } + + fiu->info = &fiu_data_match->npcm_fiu_data_info[id]; + + platform_set_drvdata(pdev, fiu); + fiu->dev = dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); + regbase = devm_ioremap_resource(dev, res); + if (IS_ERR(regbase)) + return PTR_ERR(regbase); + + fiu->regmap = devm_regmap_init_mmio(dev, regbase, + &npcm_mtd_regmap_config); + if (IS_ERR(fiu->regmap)) { + dev_err(dev, "Failed to create regmap\n"); + return PTR_ERR(fiu->regmap); + } + + fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "memory"); + fiu->clk = devm_clk_get(dev, NULL); + if (IS_ERR(fiu->clk)) + return PTR_ERR(fiu->clk); + + fiu->spix_mode = of_property_read_bool(dev->of_node, + "nuvoton,spix-mode"); + + platform_set_drvdata(pdev, fiu); + clk_prepare_enable(fiu->clk); + + ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD + | SPI_TX_DUAL | SPI_TX_QUAD; + ctrl->setup = npcm_fiu_setup; + ctrl->bus_num = -1; + ctrl->mem_ops = &npcm_fiu_mem_ops; + ctrl->num_chipselect = fiu->info->max_cs; + ctrl->dev.of_node = dev->of_node; + + ret = devm_spi_register_master(dev, ctrl); + if (ret) + return ret; + + return 0; +} + +static int npcm_fiu_remove(struct platform_device *pdev) +{ + struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev); + + clk_disable_unprepare(fiu->clk); + return 0; +} + +MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids); + +static struct platform_driver npcm_fiu_driver = { + .driver = { + .name = "NPCM-FIU", + .bus = &platform_bus_type, + .of_match_table = npcm_fiu_dt_ids, + }, + .probe = npcm_fiu_probe, + .remove = npcm_fiu_remove, +}; +module_platform_driver(npcm_fiu_driver); + +MODULE_DESCRIPTION("Nuvoton FLASH Interface Unit SPI Controller Driver"); +MODULE_AUTHOR("Tomer Maimon "); +MODULE_LICENSE("GPL v2"); From ca105398430de8c11e5e56a7bbfb00746ac5a268 Mon Sep 17 00:00:00 2001 From: Rayagonda Kokatanur Date: Fri, 30 Aug 2019 09:58:45 +0530 Subject: [PATCH 044/102] spi: bcm-qspi: Make BSPI default mode The spi-nor controller defaults to BSPI mode, hence switch back to its default mode after MSPI operations (write or erase) are completed. Signed-off-by: Rayagonda Kokatanur Reviewed-by: Mark Brown Reviewed-by: Kamal Dasu Link: https://lore.kernel.org/r/1567139325-7912-1-git-send-email-rayagonda.kokatanur@broadcom.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 0dbfd2496ab8..7a3531856491 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -897,6 +897,7 @@ static int bcm_qspi_transfer_one(struct spi_master *master, read_from_hw(qspi, slots); } + bcm_qspi_enable_bspi(qspi); return 0; } From 4fbc485324d2975c54201091dfad0a7dd4902324 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Sat, 31 Aug 2019 20:04:02 +0200 Subject: [PATCH 045/102] spi: ep93xx: Repair SPI CS lookup tables The actual device name of the SPI controller being registered on EP93xx is "spi0" (as seen by gpiod_find_lookup_table()). This patch fixes all relevant lookup tables and the following failure (seen on EDB9302): ep93xx-spi ep93xx-spi.0: failed to register SPI master ep93xx-spi: probe of ep93xx-spi.0 failed with error -22 Fixes: 1dfbf334f1236 ("spi: ep93xx: Convert to use CS GPIO descriptors") Cc: stable@vger.kernel.org Signed-off-by: Alexander Sverdlin Reviewed-by: Linus Walleij Reviewed-by: Lukasz Majewski Link: https://lore.kernel.org/r/20190831180402.10008-1-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- arch/arm/mach-ep93xx/edb93xx.c | 2 +- arch/arm/mach-ep93xx/simone.c | 2 +- arch/arm/mach-ep93xx/ts72xx.c | 4 ++-- arch/arm/mach-ep93xx/vision_ep9307.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 1f0da76a39de..7b7280c21ee0 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -103,7 +103,7 @@ static struct spi_board_info edb93xx_spi_board_info[] __initdata = { }; static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = { - .dev_id = "ep93xx-spi.0", + .dev_id = "spi0", .table = { GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW), { }, diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index e2658e22bba1..8a53b74dc4b2 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -73,7 +73,7 @@ static struct spi_board_info simone_spi_devices[] __initdata = { * v1.3 parts will still work, since the signal on SFRMOUT is automatic. */ static struct gpiod_lookup_table simone_spi_cs_gpio_table = { - .dev_id = "ep93xx-spi.0", + .dev_id = "spi0", .table = { GPIO_LOOKUP("A", 1, "cs", GPIO_ACTIVE_LOW), { }, diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 582e06e104fd..e0e1b11032f1 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -267,7 +267,7 @@ static struct spi_board_info bk3_spi_board_info[] __initdata = { * goes through CPLD */ static struct gpiod_lookup_table bk3_spi_cs_gpio_table = { - .dev_id = "ep93xx-spi.0", + .dev_id = "spi0", .table = { GPIO_LOOKUP("F", 3, "cs", GPIO_ACTIVE_LOW), { }, @@ -316,7 +316,7 @@ static struct spi_board_info ts72xx_spi_devices[] __initdata = { }; static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = { - .dev_id = "ep93xx-spi.0", + .dev_id = "spi0", .table = { /* DIO_17 */ GPIO_LOOKUP("F", 2, "cs", GPIO_ACTIVE_LOW), diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c index a88a1d807b32..cbcba3136d74 100644 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ b/arch/arm/mach-ep93xx/vision_ep9307.c @@ -242,7 +242,7 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { }; static struct gpiod_lookup_table vision_spi_cs_gpio_table = { - .dev_id = "ep93xx-spi.0", + .dev_id = "spi0", .table = { GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW), From 3c633f9dbd824b2f8e5e1a3c1fd533c1b2801be5 Mon Sep 17 00:00:00 2001 From: Keiji Hayashibara Date: Tue, 3 Sep 2019 14:30:59 +0900 Subject: [PATCH 046/102] spi: uniphier: fix wrong register overwrite When it changes the spi mode, the register is overwritten incorrectly. This commit fixes this register overwrite. Signed-off-by: Keiji Hayashibara Link: https://lore.kernel.org/r/1567488661-11428-2-git-send-email-hayashibara.keiji@socionext.com Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 5a6137fe172d..50f12fb20403 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -214,6 +214,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, if (!priv->is_save_param || priv->mode != spi->mode) { uniphier_spi_set_mode(spi); priv->mode = spi->mode; + priv->is_save_param = false; } if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) { From 151d0eafa4f59bbc7f8edfbefd5de2c97370d9b9 Mon Sep 17 00:00:00 2001 From: Keiji Hayashibara Date: Tue, 3 Sep 2019 14:31:00 +0900 Subject: [PATCH 047/102] spi: uniphier: remove unnecessary code This commit removed if() because priv->is_save_param is always true. Signed-off-by: Keiji Hayashibara Link: https://lore.kernel.org/r/1567488661-11428-3-git-send-email-hayashibara.keiji@socionext.com Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index c1e6f3245557..226f8508bff2 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -226,8 +226,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, priv->speed_hz = t->speed_hz; } - if (!priv->is_save_param) - priv->is_save_param = true; + priv->is_save_param = true; /* reset FIFOs */ val = SSI_FC_TXFFL | SSI_FC_RXFFL; From 37ffab81709805c674f164948e03ba0d3fe371b6 Mon Sep 17 00:00:00 2001 From: Keiji Hayashibara Date: Tue, 3 Sep 2019 14:31:01 +0900 Subject: [PATCH 048/102] spi: uniphier: introduce polling mode Introduce new polling mode for short size transfer. Either the estimated transfer time is estimated to exceed 200us, or polling loop actually exceeds 200us, it switches to irq mode. Signed-off-by: Keiji Hayashibara Link: https://lore.kernel.org/r/1567488661-11428-4-git-send-email-hayashibara.keiji@socionext.com Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 81 +++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 226f8508bff2..938f8873e63f 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #define SSI_TIMEOUT_MS 2000 +#define SSI_POLL_TIMEOUT_US 200 #define SSI_MAX_CLK_DIVIDER 254 #define SSI_MIN_CLK_DIVIDER 4 @@ -289,21 +291,23 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv) static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv) { - unsigned int tx_count; + unsigned int fifo_threshold, fill_bytes; u32 val; - tx_count = DIV_ROUND_UP(priv->tx_bytes, + fifo_threshold = DIV_ROUND_UP(priv->rx_bytes, bytes_per_word(priv->bits_per_word)); - tx_count = min(tx_count, SSI_FIFO_DEPTH); + fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH); + + fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes); /* set fifo threshold */ val = readl(priv->base + SSI_FC); val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK); - val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count); - val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count); + val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold); + val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold); writel(val, priv->base + SSI_FC); - while (tx_count--) + while (fill_bytes--) uniphier_spi_send(priv); } @@ -322,20 +326,14 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable) writel(val, priv->base + SSI_FPS); } -static int uniphier_spi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *t) +static int uniphier_spi_transfer_one_irq(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) { struct uniphier_spi_priv *priv = spi_master_get_devdata(master); struct device *dev = master->dev.parent; unsigned long time_left; - /* Terminate and return success for 0 byte length transfer */ - if (!t->len) - return 0; - - uniphier_spi_setup_transfer(spi, t); - reinit_completion(&priv->xfer_done); uniphier_spi_fill_tx_fifo(priv); @@ -355,6 +353,59 @@ static int uniphier_spi_transfer_one(struct spi_master *master, return priv->error; } +static int uniphier_spi_transfer_one_poll(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + int loop = SSI_POLL_TIMEOUT_US * 10; + + while (priv->tx_bytes) { + uniphier_spi_fill_tx_fifo(priv); + + while ((priv->rx_bytes - priv->tx_bytes) > 0) { + while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE) + && loop--) + ndelay(100); + + if (loop == -1) + goto irq_transfer; + + uniphier_spi_recv(priv); + } + } + + return 0; + +irq_transfer: + return uniphier_spi_transfer_one_irq(master, spi, t); +} + +static int uniphier_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + unsigned long threshold; + + /* Terminate and return success for 0 byte length transfer */ + if (!t->len) + return 0; + + uniphier_spi_setup_transfer(spi, t); + + /* + * If the transfer operation will take longer than + * SSI_POLL_TIMEOUT_US, it should use irq. + */ + threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz, + USEC_PER_SEC * BITS_PER_BYTE); + if (t->len > threshold) + return uniphier_spi_transfer_one_irq(master, spi, t); + else + return uniphier_spi_transfer_one_poll(master, spi, t); +} + static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master) { struct uniphier_spi_priv *priv = spi_master_get_devdata(master); From e327364948492f6a4e866417d3d4d17d95fed285 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 3 Sep 2019 13:57:08 +0300 Subject: [PATCH 049/102] spi: spi-fsl-dspi: Fix race condition in TCFQ/EOQ interrupt When the driver is working in TCFQ/EOQ mode (i.e. interacts with the SPI controller's FIFOs directly) the following sequence of operations happens: - The first byte of the tx buffer gets pushed to the TX FIFO (dspi->len gets decremented). This triggers the train of interrupts that handle the rest of the bytes. - The dspi_interrupt handles a TX confirmation event. It reads the newly available byte from the RX FIFO, checks the dspi->len exit condition, and if there's more to be done, it kicks off the next interrupt in the train by writing the next byte to the TX FIFO. Now the problem is that the wait queue is woken up one byte too early, because dspi->len becomes 0 as soon as the byte has been pushed into the TX FIFO. Its interrupt has not yet been processed and the RX byte has not been put from the FIFO into the buffer. Depending on the timing of the wait queue wakeup vs the handling of the last dspi_interrupt, it can happen that the main SPI message pump thread has already returned back into the spi_device driver. When the rx buffer is on stack (which it can be, because in this mode, the DSPI doesn't do DMA), the last interrupt will perform a memory write into an rx buffer that has been freed. This manifests as stack corruption. The solution is to only wake up the wait queue when dspi_rxtx says so, i.e. after it has processed the last TX confirmation interrupt and collected the last RX byte. Fixes: c55be3059159 ("spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190903105708.32273-1-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 77db43f1290f..bec758e978fb 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -710,9 +710,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) return IRQ_NONE; - dspi_rxtx(dspi); - - if (!dspi->len) { + if (dspi_rxtx(dspi) == 0) { dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); } From 0d6fccc1b6fbaf9c24e71efbbe9c3826a7b6a03d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 3 Sep 2019 13:28:12 +0100 Subject: [PATCH 050/102] spi: npcm-fiu: fix spelling mistake "frequancy" -> "frequency" There is a spelling mistake in a dev_warning message. Fix it. Also break line to clear up checkpatch warning. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190903122812.3986-1-colin.king@canonical.com Signed-off-by: Mark Brown --- drivers/spi/spi-npcm-fiu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index 3ea1ec68147e..d9e2f58b104b 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -544,7 +544,8 @@ static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (fiu->clkrate != chip->clkrate) { ret = clk_set_rate(fiu->clk, chip->clkrate); if (ret < 0) - dev_warn(fiu->dev, "Failed setting %lu frequancy, stay at %lu frequancy\n", chip->clkrate, fiu->clkrate); + dev_warn(fiu->dev, "Failed setting %lu frequency, stay at %lu frequency\n", + chip->clkrate, fiu->clkrate); else fiu->clkrate = chip->clkrate; } From 5277ab6c83832082e01249976fa7d93b9e5b9da0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:43 +0800 Subject: [PATCH 051/102] spi: altera: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-2-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index ea160f117f88..41d71ba7fd32 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -170,7 +170,6 @@ static int altera_spi_probe(struct platform_device *pdev) { struct altera_spi *hw; struct spi_master *master; - struct resource *res; int err = -ENODEV; master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); @@ -189,8 +188,7 @@ static int altera_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->base = devm_ioremap_resource(&pdev->dev, res); + hw->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->base)) { err = PTR_ERR(hw->base); goto exit; From 084fae2fd7d3d668e47748be674b698b6ab9e1aa Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:44 +0800 Subject: [PATCH 052/102] spi: a3700: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-3-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 119ae87cc26e..e450ee17787f 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -817,7 +817,6 @@ static int a3700_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *of_node = dev->of_node; - struct resource *res; struct spi_master *master; struct a3700_spi *spi; u32 num_cs = 0; @@ -855,8 +854,7 @@ static int a3700_spi_probe(struct platform_device *pdev) spi->master = master; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi->base = devm_ioremap_resource(dev, res); + spi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->base)) { ret = PTR_ERR(spi->base); goto error; From bf3484190fd45e2d7c5c52306a4973ce55f7e694 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:45 +0800 Subject: [PATCH 053/102] spi: ath79: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-4-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 032a615e4ccd..eb9a243e9526 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -139,7 +139,6 @@ static int ath79_spi_probe(struct platform_device *pdev) struct spi_master *master; struct ath79_spi *sp; struct ath79_spi_platform_data *pdata; - struct resource *r; unsigned long rate; int ret; @@ -169,8 +168,7 @@ static int ath79_spi_probe(struct platform_device *pdev) sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.flags = SPI_CS_HIGH; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sp->base = devm_ioremap_resource(&pdev->dev, r); + sp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sp->base)) { ret = PTR_ERR(sp->base); goto err_put_master; From 7d6a5e2b17d46e8c48a6c7e326acb0aa4e8f9b2d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:46 +0800 Subject: [PATCH 054/102] spi: spi-axi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-5-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 3b1833e6c7ad..74842f6019ed 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -460,7 +460,6 @@ static int spi_engine_probe(struct platform_device *pdev) struct spi_engine *spi_engine; struct spi_master *master; unsigned int version; - struct resource *res; int irq; int ret; @@ -480,8 +479,7 @@ static int spi_engine_probe(struct platform_device *pdev) spin_lock_init(&spi_engine->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_engine->base = devm_ioremap_resource(&pdev->dev, res); + spi_engine->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_engine->base)) { ret = PTR_ERR(spi_engine->base); goto err_put_master; From d1975d0596ce6d25aff9aeea14ec3806548604d0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:47 +0800 Subject: [PATCH 055/102] spi: bcm2835aux: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-6-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835aux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index b18ce69c0375..a2162ff56a12 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -491,7 +491,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct bcm2835aux_spi *bs; - struct resource *res; unsigned long clk_hz; int err; @@ -524,8 +523,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) bs = spi_master_get_devdata(master); /* the main area */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); + bs->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bs->regs)) { err = PTR_ERR(bs->regs); goto out_master_put; From 6ba794dfbb537719f96b8ba96c8bf73930969759 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:48 +0800 Subject: [PATCH 056/102] spi: bcm2835: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-7-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index fd2bfb4aa8c3..fbd6d1ae4c5e 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1001,7 +1001,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) { struct spi_controller *ctlr; struct bcm2835_spi *bs; - struct resource *res; int err; ctlr = spi_alloc_master(&pdev->dev, sizeof(*bs)); @@ -1022,8 +1021,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bs = spi_controller_get_devdata(ctlr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); + bs->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bs->regs)) { err = PTR_ERR(bs->regs); goto out_controller_put; From e364c8c204db786b15978aabd2459bba3f4f09a6 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:49 +0800 Subject: [PATCH 057/102] spi: bcm63xx-hsspi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-8-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 373cb53579e0..c6836a931dbf 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -330,7 +330,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) { struct spi_master *master; struct bcm63xx_hsspi *bs; - struct resource *res_mem; void __iomem *regs; struct device *dev = &pdev->dev; struct clk *clk, *pll_clk = NULL; @@ -341,8 +340,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (irq < 0) return irq; - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res_mem); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); From 4585bb92a57605984faa49c8f9f36b8a9b14bb12 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:50 +0800 Subject: [PATCH 058/102] spi: cadence: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-9-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 1c35eaaac838..c36587b42e95 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -474,7 +474,6 @@ static int cdns_spi_probe(struct platform_device *pdev) int ret = 0, irq; struct spi_master *master; struct cdns_spi *xspi; - struct resource *res; u32 num_cs; master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); @@ -485,8 +484,7 @@ static int cdns_spi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xspi->regs = devm_ioremap_resource(&pdev->dev, res); + xspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto remove_master; From 050688dc72d0d60fb6648895a33483d9cbf6fc63 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:51 +0800 Subject: [PATCH 059/102] spi: octeon: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-10-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-cavium-octeon.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c index ee4703e84622..1a2de6ce9064 100644 --- a/drivers/spi/spi-cavium-octeon.c +++ b/drivers/spi/spi-cavium-octeon.c @@ -18,7 +18,6 @@ static int octeon_spi_probe(struct platform_device *pdev) { - struct resource *res_mem; void __iomem *reg_base; struct spi_master *master; struct octeon_spi *p; @@ -30,8 +29,7 @@ static int octeon_spi_probe(struct platform_device *pdev) p = spi_master_get_devdata(master); platform_set_drvdata(pdev, master); - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) { err = PTR_ERR(reg_base); goto fail; From ae43724d6439f1d5682d07af76dfe316b11bf041 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:52 +0800 Subject: [PATCH 060/102] spi: clps711x: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-11-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-clps711x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 4daba12ec843..5e900f228919 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -91,7 +91,6 @@ static int spi_clps711x_probe(struct platform_device *pdev) { struct spi_clps711x_data *hw; struct spi_master *master; - struct resource *res; int irq, ret; irq = platform_get_irq(pdev, 0); @@ -125,8 +124,7 @@ static int spi_clps711x_probe(struct platform_device *pdev) goto err_out; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->syncio = devm_ioremap_resource(&pdev->dev, res); + hw->syncio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->syncio)) { ret = PTR_ERR(hw->syncio); goto err_out; From 1e2d65d06d4160d9b0db317302d7020449440da5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:53 +0800 Subject: [PATCH 061/102] spi: coldfire-qspi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-12-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 5ff48ab2f534..f80e06c87fbe 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -339,7 +339,6 @@ static int mcfqspi_probe(struct platform_device *pdev) { struct spi_master *master; struct mcfqspi *mcfqspi; - struct resource *res; struct mcfqspi_platform_data *pdata; int status; @@ -362,8 +361,7 @@ static int mcfqspi_probe(struct platform_device *pdev) mcfqspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); + mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mcfqspi->iobase)) { status = PTR_ERR(mcfqspi->iobase); goto fail0; From 5cc6fdccbb4a9357ec8b6ef52c44bdffd83c7c6f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:54 +0800 Subject: [PATCH 062/102] spi: dw-mmio: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-13-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index edb3cf6be201..bd46fca3f094 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -79,14 +79,12 @@ static int dw_spi_mscc_init(struct platform_device *pdev, const char *cpu_syscon, u32 if_si_owner_offset) { struct dw_spi_mscc *dwsmscc; - struct resource *res; dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL); if (!dwsmscc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dwsmscc->spi_mst = devm_ioremap_resource(&pdev->dev, res); + dwsmscc->spi_mst = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dwsmscc->spi_mst)) { dev_err(&pdev->dev, "SPI_MST region map failed\n"); return PTR_ERR(dwsmscc->spi_mst); From d8e477abec244c0ff9b4c4979253f8c349bf1fdd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:55 +0800 Subject: [PATCH 063/102] spi: spi-geni-qcom: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-14-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-geni-qcom.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 242b6c86cf12..6f3d64a1a2b3 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -534,7 +534,6 @@ static int spi_geni_probe(struct platform_device *pdev) int ret, irq; struct spi_master *spi; struct spi_geni_master *mas; - struct resource *res; void __iomem *base; struct clk *clk; @@ -542,8 +541,7 @@ static int spi_geni_probe(struct platform_device *pdev) if (irq < 0) return irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From 7d2600b9cc1346978f81756078e3c815775be22e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:56 +0800 Subject: [PATCH 064/102] spi: lp-8841: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-15-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-lp8841-rtc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c index f50779fd329c..2d436541d6c2 100644 --- a/drivers/spi/spi-lp8841-rtc.c +++ b/drivers/spi/spi-lp8841-rtc.c @@ -185,7 +185,6 @@ spi_lp8841_rtc_probe(struct platform_device *pdev) int ret; struct spi_master *master; struct spi_lp8841_rtc *data; - void *iomem; master = spi_alloc_master(&pdev->dev, sizeof(*data)); if (!master) @@ -207,8 +206,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev) data = spi_master_get_devdata(master); - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->iomem = devm_ioremap_resource(&pdev->dev, iomem); + data->iomem = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(data->iomem); if (ret) { dev_err(&pdev->dev, "failed to get IO address\n"); From 362385c045f580c88d2882858ea77f965d25d46b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:57 +0800 Subject: [PATCH 065/102] spi: meson-spicc: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Neil Armstrong Link: https://lore.kernel.org/r/20190904135918.25352-16-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 7fe4488ace57..f3f10443f9e2 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -503,7 +503,6 @@ static int meson_spicc_probe(struct platform_device *pdev) { struct spi_master *master; struct meson_spicc_device *spicc; - struct resource *res; int ret, irq, rate; master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); @@ -517,8 +516,7 @@ static int meson_spicc_probe(struct platform_device *pdev) spicc->pdev = pdev; platform_set_drvdata(pdev, spicc); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spicc->base = devm_ioremap_resource(&pdev->dev, res); + spicc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spicc->base)) { dev_err(&pdev->dev, "io resource mapping failed\n"); ret = PTR_ERR(spicc->base); From 425aa308a23cf321a7421bdada2f980ed87ae909 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:58 +0800 Subject: [PATCH 066/102] spi: spi-meson-spifc: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20190904135918.25352-17-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spifc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c index f7fe9b13d122..c7b039980291 100644 --- a/drivers/spi/spi-meson-spifc.c +++ b/drivers/spi/spi-meson-spifc.c @@ -286,7 +286,6 @@ static int meson_spifc_probe(struct platform_device *pdev) { struct spi_master *master; struct meson_spifc *spifc; - struct resource *res; void __iomem *base; unsigned int rate; int ret = 0; @@ -300,8 +299,7 @@ static int meson_spifc_probe(struct platform_device *pdev) spifc = spi_master_get_devdata(master); spifc->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(spifc->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { ret = PTR_ERR(base); goto out_err; From f88771ca7104e47d3c62ec9872104d8252f844a0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:58:59 +0800 Subject: [PATCH 067/102] spi: mt7621: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-18-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt7621.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c index ff85982464d2..2c3b7a2a1ec7 100644 --- a/drivers/spi/spi-mt7621.c +++ b/drivers/spi/spi-mt7621.c @@ -327,7 +327,6 @@ static int mt7621_spi_probe(struct platform_device *pdev) struct spi_controller *master; struct mt7621_spi *rs; void __iomem *base; - struct resource *r; int status = 0; struct clk *clk; int ret; @@ -336,8 +335,7 @@ static int mt7621_spi_probe(struct platform_device *pdev) if (!match) return -EINVAL; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, r); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From d4225b3665e37167c9661c1c67cb2787134ce53a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:00 +0800 Subject: [PATCH 068/102] spi: mxs: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-19-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 7bf53cfc25d6..996c1c8a9c71 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -532,7 +532,6 @@ static int mxs_spi_probe(struct platform_device *pdev) struct spi_master *master; struct mxs_spi *spi; struct mxs_ssp *ssp; - struct resource *iores; struct clk *clk; void __iomem *base; int devid, clk_freq; @@ -545,12 +544,11 @@ static int mxs_spi_probe(struct platform_device *pdev) */ const int clk_freq_default = 160000000; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq_err = platform_get_irq(pdev, 0); if (irq_err < 0) return irq_err; - base = devm_ioremap_resource(&pdev->dev, iores); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From dcbceb6de0db24d383797d574e4a800fbef3580b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:01 +0800 Subject: [PATCH 069/102] spi: npcm: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-20-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-npcm-pspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 5c56caea04f0..b191d57d1dc0 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -341,7 +341,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) { struct npcm_pspi *priv; struct spi_master *master; - struct resource *res; unsigned long clk_hz; struct device_node *np = pdev->dev.of_node; int num_cs, i; @@ -368,8 +367,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) priv->is_save_param = false; priv->id = pdev->id; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto out_master_put; From 4c6f537a0397d24cd74eefd473a74488801be673 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:02 +0800 Subject: [PATCH 070/102] spi: nuc900: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-21-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-nuc900.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index f65a029e3fe9..61400358f4be 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -327,7 +327,6 @@ static int nuc900_spi_probe(struct platform_device *pdev) { struct nuc900_spi *hw; struct spi_master *master; - struct resource *res; int err = 0; master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi)); @@ -358,8 +357,7 @@ static int nuc900_spi_probe(struct platform_device *pdev) hw->bitbang.chipselect = nuc900_spi_chipsel; hw->bitbang.txrx_bufs = nuc900_spi_txrx; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->regs = devm_ioremap_resource(&pdev->dev, res); + hw->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->regs)) { err = PTR_ERR(hw->regs); goto err_pdata; From f601a654bb47b89a469446ecca6c0183a5c75b96 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:03 +0800 Subject: [PATCH 071/102] spi: oc-tiny: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-22-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-oc-tiny.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index bbc4ba66571f..e2331eb7b47a 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -240,7 +240,6 @@ static int tiny_spi_probe(struct platform_device *pdev) struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); struct tiny_spi *hw; struct spi_master *master; - struct resource *res; unsigned int i; int err = -ENODEV; @@ -264,8 +263,7 @@ static int tiny_spi_probe(struct platform_device *pdev) hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->base = devm_ioremap_resource(&pdev->dev, res); + hw->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->base)) { err = PTR_ERR(hw->base); goto exit; From e751032bcbd73667dde1a640109653a64f45a7d1 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:04 +0800 Subject: [PATCH 072/102] spi: pic32-sqi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-23-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-pic32-sqi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index 11b692923fd7..86ad17597f5f 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -570,7 +570,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) { struct spi_master *master; struct pic32_sqi *sqi; - struct resource *reg; int ret; master = spi_alloc_master(&pdev->dev, sizeof(*sqi)); @@ -580,8 +579,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) sqi = spi_master_get_devdata(master); sqi->master = master; - reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sqi->regs = devm_ioremap_resource(&pdev->dev, reg); + sqi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sqi->regs)) { ret = PTR_ERR(sqi->regs); goto err_free_master; From e0ea3cc2baf600d71fddf692e27da2e580233140 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:05 +0800 Subject: [PATCH 073/102] spi: spi-qcom-qspi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-24-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-qcom-qspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index a0ad73f1cc01..250fd60e1678 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -424,7 +424,6 @@ static int qcom_qspi_probe(struct platform_device *pdev) { int ret; struct device *dev; - struct resource *res; struct spi_master *master; struct qcom_qspi *ctrl; @@ -440,8 +439,7 @@ static int qcom_qspi_probe(struct platform_device *pdev) spin_lock_init(&ctrl->lock); ctrl->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ctrl->base = devm_ioremap_resource(dev, res); + ctrl->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ctrl->base)) { ret = PTR_ERR(ctrl->base); goto exit_probe_master_put; From 7d4c208326a0eae8eb296d2c35e1eed59accd9e5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:06 +0800 Subject: [PATCH 074/102] spi: rb4xx: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-25-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-rb4xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c index 51f03d977ad6..4c9620e0d18c 100644 --- a/drivers/spi/spi-rb4xx.c +++ b/drivers/spi/spi-rb4xx.c @@ -135,12 +135,10 @@ static int rb4xx_spi_probe(struct platform_device *pdev) struct spi_master *master; struct clk *ahb_clk; struct rb4xx_spi *rbspi; - struct resource *r; int err; void __iomem *spi_base; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_base = devm_ioremap_resource(&pdev->dev, r); + spi_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_base)) return PTR_ERR(spi_base); From b38f1f9b6e108a4d73107c93e470f5a20b1ca982 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:07 +0800 Subject: [PATCH 075/102] spi: s3c24xx: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-26-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-s3c24xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index aea8fd98a31f..2d6e37f25e2d 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -487,7 +487,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) struct s3c2410_spi_info *pdata; struct s3c24xx_spi *hw; struct spi_master *master; - struct resource *res; int err = 0; master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); @@ -536,8 +535,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->regs = devm_ioremap_resource(&pdev->dev, res); + hw->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->regs)) { err = PTR_ERR(hw->regs); goto err_no_pdata; From fa79f20047115678abca3c5c20247192128facb6 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:08 +0800 Subject: [PATCH 076/102] spi: sifive: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-27-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-sifive.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 5bf2b57e6929..35254bdc42c4 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -292,7 +292,6 @@ sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, static int sifive_spi_probe(struct platform_device *pdev) { struct sifive_spi *spi; - struct resource *res; int ret, irq, num_cs; u32 cs_bits, max_bits_per_word; struct spi_master *master; @@ -307,8 +306,7 @@ static int sifive_spi_probe(struct platform_device *pdev) init_completion(&spi->done); platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi->regs = devm_ioremap_resource(&pdev->dev, res); + spi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regs)) { ret = PTR_ERR(spi->regs); goto put_master; From a755008377df0a2053663177f2bc5d2cef1b0f97 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:09 +0800 Subject: [PATCH 077/102] spi: sirf: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-28-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-sirf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 71b882ab31b9..e1e639191557 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -1070,7 +1070,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) { struct sirfsoc_spi *sspi; struct spi_master *master; - struct resource *mem_res; const struct sirf_spi_comp_data *spi_comp_data; int irq; int ret; @@ -1097,8 +1096,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1; sspi->dat_max_frm_len = spi_comp_data->dat_max_frm_len; sspi->fifo_size = spi_comp_data->fifo_size; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); + sspi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base)) { ret = PTR_ERR(sspi->base); goto free_master; From 338dd352acf007b886ff52bc68a2a0af3980f52d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:10 +0800 Subject: [PATCH 078/102] spi: st-ssc4: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-29-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-st-ssc4.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 840a6bf81336..0c24c494f386 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -298,7 +298,6 @@ static int spi_st_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spi_master *master; - struct resource *res; struct spi_st *spi_st; int irq, ret = 0; u32 var; @@ -331,8 +330,7 @@ static int spi_st_probe(struct platform_device *pdev) init_completion(&spi_st->done); /* Get resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_st->base = devm_ioremap_resource(&pdev->dev, res); + spi_st->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_st->base)) { ret = PTR_ERR(spi_st->base); goto clk_disable; From 8c649f4d4e92b7c8dd355279a584e4bca3302a6c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:11 +0800 Subject: [PATCH 079/102] spi: sun4i: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-30-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-sun4i.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 92e5c667b6a1..cbfac6596fad 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -428,7 +428,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct sun4i_spi *sspi; - struct resource *res; int ret = 0, irq; master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi)); @@ -440,8 +439,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); + sspi->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base_addr)) { ret = PTR_ERR(sspi->base_addr); goto err_free_master; From 7c7c31f7f934a79c99ab72c30517950b5c090c48 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:12 +0800 Subject: [PATCH 080/102] spi: sun6i: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-31-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-sun6i.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 1cf3051bba5e..ec7967be9e2f 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -435,7 +435,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct sun6i_spi *sspi; - struct resource *res; int ret = 0, irq; master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi)); @@ -447,8 +446,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); + sspi->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base_addr)) { ret = PTR_ERR(sspi->base_addr); goto err_free_master; From e8d63b38b1d6895e7e36abfe2b15eac47d66aeee Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:13 +0800 Subject: [PATCH 081/102] spi: tegra: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-32-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-sflash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index cd714a4f52c6..a841a7250d14 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -419,7 +419,6 @@ static int tegra_sflash_probe(struct platform_device *pdev) { struct spi_master *master; struct tegra_sflash_data *tsd; - struct resource *r; int ret; const struct of_device_id *match; @@ -451,8 +450,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) &master->max_speed_hz)) master->max_speed_hz = 25000000; /* 25MHz */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tsd->base = devm_ioremap_resource(&pdev->dev, r); + tsd->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tsd->base)) { ret = PTR_ERR(tsd->base); goto exit_free_master; From 755f1a25004c36ddaace893f906a30d32e483e09 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:14 +0800 Subject: [PATCH 082/102] spi: uniphier: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-33-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 938f8873e63f..d4453177ad4a 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -469,7 +469,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) { struct uniphier_spi_priv *priv; struct spi_master *master; - struct resource *res; unsigned long clk_rate; int irq; int ret; @@ -484,8 +483,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) priv->master = master; priv->is_save_param = false; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto out_master_put; From 77348293078b6047947bf38a1fc2ec6e142ba4ee Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:15 +0800 Subject: [PATCH 083/102] spi: xlp: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-34-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-xlp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c index 4eb5bc9250fc..797ac0ea8fa3 100644 --- a/drivers/spi/spi-xlp.c +++ b/drivers/spi/spi-xlp.c @@ -370,7 +370,6 @@ static int xlp_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct xlp_spi_priv *xspi; - struct resource *res; struct clk *clk; int irq, err; @@ -378,8 +377,7 @@ static int xlp_spi_probe(struct platform_device *pdev) if (!xspi) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xspi->base = devm_ioremap_resource(&pdev->dev, res); + xspi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->base)) return PTR_ERR(xspi->base); From 214d1edb60432ac9d024966e6f672e8cb024e672 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:16 +0800 Subject: [PATCH 084/102] spi: zynqmp: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-35-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 5e9ea8a38163..60c4de4e4485 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1016,7 +1016,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) int ret = 0; struct spi_master *master; struct zynqmp_qspi *xqspi; - struct resource *res; struct device *dev = &pdev->dev; eemi_ops = zynqmp_pm_get_eemi_ops(); @@ -1031,8 +1030,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xqspi->regs = devm_ioremap_resource(&pdev->dev, res); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); goto remove_master; From ae91a439ac7ec8e1e925621293f45794de6366f2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:17 +0800 Subject: [PATCH 085/102] spi: zynq-qspi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-36-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynq-qspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index 4a5326ccf65a..5cf6993ddce5 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -620,7 +620,6 @@ static int zynq_qspi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct zynq_qspi *xqspi; - struct resource *res; u32 num_cs; ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi)); @@ -630,8 +629,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; platform_set_drvdata(pdev, xqspi); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xqspi->regs = devm_ioremap_resource(&pdev->dev, res); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); goto remove_master; From 43a5baa6d8b8c6d93458ab0c6a8a7700e94b9708 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Sep 2019 21:59:18 +0800 Subject: [PATCH 086/102] spi: fsl-spi: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190904135918.25352-37-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-cpm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index e967ac564761..858f0544289e 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -305,12 +305,10 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) } if (mspi->flags & SPI_CPM1) { - struct resource *res; void *pram; - res = platform_get_resource(to_platform_device(dev), - IORESOURCE_MEM, 1); - pram = devm_ioremap_resource(dev, res); + pram = devm_platform_ioremap_resource(to_platform_device(dev), + 1); if (IS_ERR(pram)) mspi->pram = NULL; else From a0ce1fd11e587be803eb2f299d478c962df3706f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 5 Sep 2019 15:24:36 +0800 Subject: [PATCH 087/102] spi: npcm-fiu: remove set but not used variable 'retlen' drivers/spi/spi-npcm-fiu.c: In function npcm_fiu_read: drivers/spi/spi-npcm-fiu.c:472:9: warning: variable retlen set but not used [-Wunused-but-set-variable] It is never used, so remove it. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190905072436.23932-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-npcm-fiu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index d9e2f58b104b..cb52fd8008d0 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -469,7 +469,6 @@ static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op) { u8 *data = op->data.buf.in; int i, readlen, currlen; - size_t retlen = 0; u8 *buf_ptr; u32 addr; int ret; @@ -494,8 +493,6 @@ static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op) currlen -= 16; } while (currlen > 0); - retlen = i; - return 0; } From d1c44c9342c17e3314371325d9272684a075b65c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 5 Sep 2019 04:01:11 +0300 Subject: [PATCH 088/102] spi: Use an abbreviated pointer to ctlr->cur_msg in __spi_pump_messages This helps a bit with line fitting now (the list_first_entry call) as well as during the next patch which needs to iterate through all transfers of ctlr->cur_msg so it timestamps them. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190905010114.26718-2-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index aef55acb5ccd..b2890923d256 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1265,8 +1265,9 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); */ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) { - unsigned long flags; + struct spi_message *msg; bool was_busy = false; + unsigned long flags; int ret; /* Lock queue */ @@ -1325,10 +1326,10 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) } /* Extract head of queue */ - ctlr->cur_msg = - list_first_entry(&ctlr->queue, struct spi_message, queue); + msg = list_first_entry(&ctlr->queue, struct spi_message, queue); + ctlr->cur_msg = msg; - list_del_init(&ctlr->cur_msg->queue); + list_del_init(&msg->queue); if (ctlr->busy) was_busy = true; else @@ -1361,7 +1362,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) if (ctlr->auto_runtime_pm) pm_runtime_put(ctlr->dev.parent); - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); mutex_unlock(&ctlr->io_mutex); @@ -1369,28 +1370,28 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) } } - trace_spi_message_start(ctlr->cur_msg); + trace_spi_message_start(msg); if (ctlr->prepare_message) { - ret = ctlr->prepare_message(ctlr, ctlr->cur_msg); + ret = ctlr->prepare_message(ctlr, msg); if (ret) { dev_err(&ctlr->dev, "failed to prepare message: %d\n", ret); - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); goto out; } ctlr->cur_msg_prepared = true; } - ret = spi_map_msg(ctlr, ctlr->cur_msg); + ret = spi_map_msg(ctlr, msg); if (ret) { - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); goto out; } - ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg); + ret = ctlr->transfer_one_message(ctlr, msg); if (ret) { dev_err(&ctlr->dev, "failed to transfer one message from queue\n"); From 8995673e6f584c2140b565d9ef20e4e4599aad7e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 7 Sep 2019 13:51:16 +0200 Subject: [PATCH 089/102] spi-gpio: Use PTR_ERR_OR_ZERO() in spi_gpio_request() Simplify this function implementation by using a known function. Generated by: scripts/coccinelle/api/ptr_ret.cocci Signed-off-by: Markus Elfring Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/b2dd074a-1693-3aea-42b4-da1f5ec155c4@web.de Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 9eb82150666e..1d3e23ec20a6 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -290,10 +290,7 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio) return PTR_ERR(spi_gpio->miso); spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); - if (IS_ERR(spi_gpio->sck)) - return PTR_ERR(spi_gpio->sck); - - return 0; + return PTR_ERR_OR_ZERO(spi_gpio->sck); } #ifdef CONFIG_OF From 4c524191c0a21d758b519087c64f84348095e940 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 3 Aug 2019 12:10:00 +0200 Subject: [PATCH 090/102] spi: bcm2835: Work around DONE bit erratum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 3bd7f6589f67 ("spi: bcm2835: Overcome sglist entry length limitation") amended the BCM2835 SPI driver with support for DMA transfers whose buffers are not aligned to 4 bytes and require more than one sglist entry. When testing this feature with upcoming commits to speed up TX-only and RX-only transfers, I noticed that SPI transmission sometimes breaks. A function introduced by the commit, bcm2835_spi_transfer_prologue(), performs one or two PIO transmissions as a prologue to the actual DMA transmission. It turns out that the breakage goes away if the DONE bit in the CS register is set when ending such a PIO transmission. The DONE bit signifies emptiness of the TX FIFO. According to the spec, the bit is of type RO, so writing it should never have any effect. Perhaps the spec is wrong and the bit is actually of type RW1C. E.g. the I2C controller on the BCM2835 does have an RW1C DONE bit which needs to be cleared by the driver. Another, possibly more likely explanation is that it's a hardware erratum since the issue does not occur consistently. Either way, amend bcm2835_spi_transfer_prologue() to always write the DONE bit. Usually a transmission is ended by bcm2835_spi_reset_hw(). If the transmission was successful, the TX FIFO is empty and thus the DONE bit is set when bcm2835_spi_reset_hw() reads the CS register. The bit is then written back to the register, so we happen to do the right thing. However if DONE is not set, e.g. because transmission is aborted with a non-empty TX FIFO, the bit won't be written by bcm2835_spi_reset_hw() and it seems possible that transmission might subsequently break. To be on the safe side, likewise amend bcm2835_spi_reset_hw() to always write the bit. Tested-by: Nuno Sá Signed-off-by: Lukas Wunner Acked-by: Stefan Wahren Acked-by: Martin Sperl Link: https://lore.kernel.org/r/edb004dff4af6106f6bfcb89e1a96391e96eb857.1564825752.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 840b1b8ff3dc..dfdcebb38830 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -319,6 +319,13 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr) BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_DMAEN | BCM2835_SPI_CS_TA); + /* + * Transmission sometimes breaks unless the DONE bit is written at the + * end of every transfer. The spec says it's a RO bit. Either the + * spec is wrong and the bit is actually of type RW1C, or it's a + * hardware erratum. + */ + cs |= BCM2835_SPI_CS_DONE; /* and reset RX/TX FIFOS */ cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; @@ -477,7 +484,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, bcm2835_wr_fifo_count(bs, bs->rx_prologue); bcm2835_wait_tx_fifo_empty(bs); bcm2835_rd_fifo_count(bs, bs->rx_prologue); - bcm2835_spi_reset_hw(ctlr); + bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX + | BCM2835_SPI_CS_CLEAR_TX + | BCM2835_SPI_CS_DONE); dma_sync_single_for_device(ctlr->dma_rx->device->dev, sg_dma_address(&tfr->rx_sg.sgl[0]), @@ -498,7 +507,8 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, | BCM2835_SPI_CS_DMAEN); bcm2835_wr_fifo_count(bs, tx_remaining); bcm2835_wait_tx_fifo_empty(bs); - bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX); + bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX + | BCM2835_SPI_CS_DONE); } if (likely(!bs->tx_spillover)) { From 1513ceee70f2bd523e025efe0c715328e1a43ffd Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 091/102] spi: bcm2835: Drop dma_pending flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 SPI driver uses a flag to keep track of whether a DMA transfer is in progress. The flag is used to avoid terminating DMA channels multiple times if a transfer finishes orderly while simultaneously the SPI core invokes the ->handle_err() callback because the transfer took too long. However terminating DMA channels multiple times is perfectly fine, so the flag is unnecessary for this particular purpose. The flag is also used to avoid invoking bcm2835_spi_undo_prologue() multiple times under this race condition. However multiple *concurrent* invocations can no longer happen since commit 2527704d8411 ("spi: bcm2835: Synchronize with callback on DMA termination") because the ->handle_err() callback now uses the _sync() variant when terminating DMA channels. The only raison d'être of the flag is therefore that bcm2835_spi_undo_prologue() cannot cope with multiple *sequential* invocations. Achieve that by setting tx_prologue to 0 at the end of the function. Subsequent invocations thus become no-ops. With that, the dma_pending flag becomes unnecessary, so drop it. Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Stefan Wahren Acked-by: Martin Sperl Link: https://lore.kernel.org/r/062b03b7f86af77a13ce0ec3b22e0bdbfcfba10d.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index fbd6d1ae4c5e..60255ac837f5 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -94,7 +94,6 @@ MODULE_PARM_DESC(polling_limit_us, * @rx_prologue: bytes received without DMA if first RX sglist entry's * length is not a multiple of 4 (to overcome hardware limitation) * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry - * @dma_pending: whether a DMA transfer is in progress * @debugfs_dir: the debugfs directory - neede to remove debugfs when * unloading the module * @count_transfer_polling: count of how often polling mode is used @@ -117,7 +116,6 @@ struct bcm2835_spi { int tx_prologue; int rx_prologue; unsigned int tx_spillover; - unsigned int dma_pending; struct dentry *debugfs_dir; u64 count_transfer_polling; @@ -541,6 +539,8 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; } + + bs->tx_prologue = 0; } static void bcm2835_spi_dma_done(void *data) @@ -556,10 +556,8 @@ static void bcm2835_spi_dma_done(void *data) * is called the tx-dma must have finished - can't get to this * situation otherwise... */ - if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_async(ctlr->dma_tx); - bcm2835_spi_undo_prologue(bs); - } + dmaengine_terminate_async(ctlr->dma_tx); + bcm2835_spi_undo_prologue(bs); /* and mark as completed */; complete(&ctlr->xfer_completion); @@ -634,9 +632,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, /* start TX early */ dma_async_issue_pending(ctlr->dma_tx); - /* mark as dma pending */ - bs->dma_pending = 1; - /* set the DMA length */ bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); @@ -652,7 +647,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, if (ret) { /* need to reset on errors */ dmaengine_terminate_sync(ctlr->dma_tx); - bs->dma_pending = false; goto err_reset_hw; } @@ -917,11 +911,10 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); /* if an error occurred and we have an active dma, then terminate */ - if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_sync(ctlr->dma_tx); - dmaengine_terminate_sync(ctlr->dma_rx); - bcm2835_spi_undo_prologue(bs); - } + dmaengine_terminate_sync(ctlr->dma_tx); + dmaengine_terminate_sync(ctlr->dma_rx); + bcm2835_spi_undo_prologue(bs); + /* and reset */ bcm2835_spi_reset_hw(ctlr); } From 4f2228cce2816e46dcac0be50a259a0311a90252 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 092/102] dmaengine: bcm2835: Allow cyclic transactions without interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 DMA driver currently requests an interrupt from the controller regardless whether or not the client has passed in the DMA_PREP_INTERRUPT flag. This causes unnecessary overhead for cyclic transactions which do not need an interrupt after each period. We're about to add such a use case, namely cyclic clearing of the SPI controller's RX FIFO, so amend the DMA driver to request an interrupt only if DMA_PREP_INTERRUPT was passed in. Ignore the period_len for such transactions and set it to the buffer length to make the driver's calculations work. Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Vinod Koul Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Florian Kauer Link: https://lore.kernel.org/r/73cf37be56eb4cbe6f696057c719f3a38cbaf26e.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/dma/bcm2835-dma.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 8101ff2f05c1..b40fb555b98b 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -691,7 +691,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( struct bcm2835_desc *d; dma_addr_t src, dst; u32 info = BCM2835_DMA_WAIT_RESP; - u32 extra = BCM2835_DMA_INT_EN; + u32 extra = 0; size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -707,6 +707,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( return NULL; } + if (flags & DMA_PREP_INTERRUPT) + extra |= BCM2835_DMA_INT_EN; + else + period_len = buf_len; + /* * warn if buf_len is not a multiple of period_len - this may leed * to unexpected latencies for interrupts and thus audiable clicks @@ -778,7 +783,10 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) /* stop DMA activity */ if (c->desc) { - vchan_terminate_vdesc(&c->desc->vd); + if (c->desc->vd.tx.flags & DMA_PREP_INTERRUPT) + vchan_terminate_vdesc(&c->desc->vd); + else + vchan_vdesc_fini(&c->desc->vd); c->desc = NULL; bcm2835_dma_abort(c); } From 6f6869dc97e8657e15d728c9a1ee3af2b9343990 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 093/102] dmaengine: bcm2835: Allow reusable descriptors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DMA engine API requires DMA drivers to explicitly allow that descriptors are prepared once and reused multiple times. Only a single driver makes use of this functionality so far (pxa_dma.c, to speed up pxa_camera.c). We're about to add another use case for reusable descriptors in the BCM2835 SPI driver, so allow that in the BCM2835 DMA driver. Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Vinod Koul Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Florian Kauer Cc: Robert Jarzmik Link: https://lore.kernel.org/r/bfc98a38225bbec4158440ad06cb9eee675e3e6f.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/dma/bcm2835-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index b40fb555b98b..a65514fcb7f2 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -915,6 +915,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | BIT(DMA_MEM_TO_MEM); od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.descriptor_reuse = true; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); From 229e6af102e407feada76d3c270395d7cda2cdfe Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 094/102] spi: Guarantee cacheline alignment of driver-private data __spi_alloc_controller() uses a single allocation to accommodate struct spi_controller and the driver-private data, but places the latter behind the former. This order does not guarantee cacheline alignment of the driver-private data. (It does guarantee cacheline alignment of struct spi_controller but the structure doesn't make any use of that property.) Round up struct spi_controller to cacheline size. A forthcoming commit leverages this to grant DMA access to driver-private data of the BCM2835 SPI master. An alternative, less economical approach would be to use two allocations. A third approach consists of reversing the order to conserve memory. But Mark Brown is concerned that it may result in a performance penalty on architectures that don't like unaligned accesses. Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/01625b9b26b93417fb09d2c15ad02dfe9cdbbbe5.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b2890923d256..f8b4654a57d3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2188,8 +2188,10 @@ extern struct class spi_slave_class; /* dummy */ * __spi_alloc_controller - allocate an SPI master or slave controller * @dev: the controller, possibly using the platform_bus * @size: how much zeroed driver-private data to allocate; the pointer to this - * memory is in the driver_data field of the returned device, - * accessible with spi_controller_get_devdata(). + * memory is in the driver_data field of the returned device, accessible + * with spi_controller_get_devdata(); the memory is cacheline aligned; + * drivers granting DMA access to portions of their private data need to + * round up @size using ALIGN(size, dma_get_cache_alignment()). * @slave: flag indicating whether to allocate an SPI master (false) or SPI * slave (true) controller * Context: can sleep @@ -2211,11 +2213,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, unsigned int size, bool slave) { struct spi_controller *ctlr; + size_t ctlr_size = ALIGN(sizeof(*ctlr), dma_get_cache_alignment()); if (!dev) return NULL; - ctlr = kzalloc(size + sizeof(*ctlr), GFP_KERNEL); + ctlr = kzalloc(size + ctlr_size, GFP_KERNEL); if (!ctlr) return NULL; @@ -2229,7 +2232,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, ctlr->dev.class = &spi_master_class; ctlr->dev.parent = dev; pm_suspend_ignore_children(&ctlr->dev, true); - spi_controller_set_devdata(ctlr, &ctlr[1]); + spi_controller_set_devdata(ctlr, (void *)ctlr + ctlr_size); return ctlr; } From c3ef8207833206f53b1ea433dc25c0c9b30d4424 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 095/102] dmaengine: bcm2835: Document struct bcm2835_dmadev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the BCM2835 DMA driver's device data structure so that upcoming commits may add further members with proper kerneldoc. Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Vinod Koul Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Florian Kauer Link: https://lore.kernel.org/r/78648f80f67d97bb7beecc1b9be6b6e4a45bc1d8.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/dma/bcm2835-dma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index a65514fcb7f2..14358faf3bff 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -37,6 +37,12 @@ #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 #define BCM2835_DMA_CHAN_NAME_SIZE 8 +/** + * struct bcm2835_dmadev - BCM2835 DMA controller + * @ddev: DMA device + * @base: base address of register map + * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients) + */ struct bcm2835_dmadev { struct dma_device ddev; void __iomem *base; From 571e31fa60b3697d5db26140e16d5c45c51c9815 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 096/102] spi: bcm2835: Cache CS register value for ->prepare_message() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 SPI driver needs to set up the clock polarity in its ->prepare_message() hook before spi_transfer_one_message() asserts chip select to avoid a gratuitous clock signal edge (cf. commit acace73df2c1 ("spi: bcm2835: set up spi-mode before asserting cs-gpio")). Precalculate the CS register value (which selects the clock polarity) once in ->setup() and use that cached value in ->prepare_message() and ->transfer_one(). This avoids one MMIO read per message and one per transfer, yielding a small latency improvement. Additionally, a forthcoming commit will use the precalculated value to derive the register value for clearing the RX FIFO, which will eliminate the need for an RX dummy buffer when performing TX-only DMA transfers. Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Stefan Wahren Acked-by: Martin Sperl Link: https://lore.kernel.org/r/d17c1d7fcdc97fffa961b8737cfd80eeb14f9416.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 46 ++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 60255ac837f5..f01d18d521f2 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -68,6 +68,7 @@ #define BCM2835_SPI_FIFO_SIZE 64 #define BCM2835_SPI_FIFO_SIZE_3_4 48 #define BCM2835_SPI_DMA_MIN_LENGTH 96 +#define BCM2835_SPI_NUM_CS 3 /* raise as necessary */ #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | SPI_NO_CS | SPI_3WIRE) @@ -94,6 +95,8 @@ MODULE_PARM_DESC(polling_limit_us, * @rx_prologue: bytes received without DMA if first RX sglist entry's * length is not a multiple of 4 (to overcome hardware limitation) * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry + * @prepare_cs: precalculated CS register value for ->prepare_message() + * (uses slave-specific clock polarity and phase settings) * @debugfs_dir: the debugfs directory - neede to remove debugfs when * unloading the module * @count_transfer_polling: count of how often polling mode is used @@ -116,6 +119,7 @@ struct bcm2835_spi { int tx_prologue; int rx_prologue; unsigned int tx_spillover; + u32 prepare_cs[BCM2835_SPI_NUM_CS]; struct dentry *debugfs_dir; u64 count_transfer_polling; @@ -808,7 +812,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); unsigned long spi_hz, clk_hz, cdiv, spi_used_hz; unsigned long hz_per_byte, byte_limit; - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + u32 cs = bs->prepare_cs[spi->chip_select]; /* set clock */ spi_hz = tfr->speed_hz; @@ -833,15 +837,6 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, if (spi->mode & SPI_3WIRE && tfr->rx_buf && tfr->rx_buf != ctlr->dummy_rx) cs |= BCM2835_SPI_CS_REN; - else - cs &= ~BCM2835_SPI_CS_REN; - - /* - * The driver always uses software-controlled GPIO Chip Select. - * Set the hardware-controlled native Chip Select to an invalid - * value to prevent it from interfering. - */ - cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; /* set transmit buffers and length */ bs->tx_buf = tfr->tx_buf; @@ -878,7 +873,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); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); int ret; if (ctlr->can_dma) { @@ -893,14 +887,11 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, return ret; } - cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); - - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; - - bcm2835_wr(bs, BCM2835_SPI_CS, cs); + /* + * Set up clock polarity before spi_transfer_one_message() asserts + * chip select to avoid a gratuitous clock signal edge. + */ + bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]); return 0; } @@ -926,8 +917,23 @@ static int chip_match_name(struct gpio_chip *chip, void *data) static int bcm2835_spi_setup(struct spi_device *spi) { + struct bcm2835_spi *bs = spi_controller_get_devdata(spi->controller); struct gpio_chip *chip; enum gpio_lookup_flags lflags; + u32 cs; + + /* + * Precalculate SPI slave's CS register value for ->prepare_message(): + * The driver always uses software-controlled GPIO chip select, hence + * set the hardware-controlled native chip select to an invalid value + * to prevent it from interfering. + */ + cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; + if (spi->mode & SPI_CPOL) + cs |= BCM2835_SPI_CS_CPOL; + if (spi->mode & SPI_CPHA) + cs |= BCM2835_SPI_CS_CPHA; + bs->prepare_cs[spi->chip_select] = cs; /* * sanity checking the native-chipselects @@ -1005,7 +1011,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ctlr->use_gpio_descriptors = true; ctlr->mode_bits = BCM2835_SPI_MODE_BITS; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ctlr->num_chipselect = 3; + ctlr->num_chipselect = BCM2835_SPI_NUM_CS; ctlr->setup = bcm2835_spi_setup; ctlr->transfer_one = bcm2835_spi_transfer_one; ctlr->handle_err = bcm2835_spi_handle_err; From bf75703d0912da7b1af72f14392c805b758c3fbc Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 097/102] dmaengine: bcm2835: Avoid accessing memory when copying zeroes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 DMA controller is capable of synthesizing zeroes instead of copying them from a source address. The feature is enabled by setting the SRC_IGNORE bit in the Transfer Information field of a Control Block: "Do not perform source reads. In addition, destination writes will zero all the write strobes. This is used for fast cache fill operations." https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf The feature is only available on 8 of the 16 channels. The others are so-called "lite" channels with a limited feature set and performance. Enable the feature if a cyclic transaction copies from the zero page. This reduces traffic on the memory bus. A forthcoming use case is the BCM2835 SPI driver, which will cyclically copy from the zero page to the TX FIFO. The idea to use SRC_IGNORE was taken from an ancient GitHub conversation between Martin and Noralf: https://github.com/msperl/spi-bcm2835/issues/13#issuecomment-98180451 Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Lukas Wunner Acked-by: Vinod Koul Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Florian Kauer Link: https://lore.kernel.org/r/b2286c904408745192e4beb3de3c88f73e4a7210.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/dma/bcm2835-dma.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 14358faf3bff..67100e4e1083 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -42,11 +42,14 @@ * @ddev: DMA device * @base: base address of register map * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients) + * @zero_page: bus address of zero page (to detect transactions copying from + * zero page and avoid accessing memory if so) */ struct bcm2835_dmadev { struct dma_device ddev; void __iomem *base; struct device_dma_parameters dma_parms; + dma_addr_t zero_page; }; struct bcm2835_dma_cb { @@ -693,6 +696,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction direction, unsigned long flags) { + struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src, dst; @@ -743,6 +747,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( dst = c->cfg.dst_addr; src = buf_addr; info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; + + /* non-lite channels can write zeroes w/o accessing memory */ + if (buf_addr == od->zero_page && !c->is_lite_channel) + info |= BCM2835_DMA_S_IGNORE; } /* calculate number of frames */ @@ -845,6 +853,9 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od) list_del(&c->vc.chan.device_node); tasklet_kill(&c->vc.task); } + + dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE, + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); } static const struct of_device_id bcm2835_dma_of_match[] = { @@ -927,6 +938,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, od); + od->zero_page = dma_map_page_attrs(od->ddev.dev, ZERO_PAGE(0), 0, + PAGE_SIZE, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(od->ddev.dev, od->zero_page)) { + dev_err(&pdev->dev, "Failed to map zero page\n"); + return -ENOMEM; + } + /* Request DMA channel mask from device tree */ if (of_property_read_u32(pdev->dev.of_node, "brcm,dma-channel-mask", From 8259bf667a0f9ea1a37bb71c7af9ebd550e9251d Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 098/102] spi: bcm2835: Speed up TX-only DMA transfers by clearing RX FIFO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 SPI driver currently sets the SPI_CONTROLLER_MUST_RX flag. When performing a TX-only transfer, this flag causes the SPI core to allocate and DMA-map a dummy buffer into which the RX FIFO contents are copied. The dummy buffer is necessary because the chip is not capable of disabling the receiver or automatically throwing away received data. Not reading the RX FIFO isn't an option either since transmission is halted once it's full. Avoid the overhead induced by the dummy buffer by preallocating a reusable DMA transaction which cyclically clears the RX FIFO. The transaction requires very little CPU time to submit and generates no interrupts while running. Specifics are provided in kerneldoc comments. With a ks8851 Ethernet chip attached to the SPI controller, I am seeing a 30 us reduction in ping time with this commit (1.819 ms vs. 1.849 ms, average of 100,000 packets) as well as a 2% reduction in CPU time (75:08 vs. 76:39 for transmission of 5 GByte over the SPI bus). The commit uses the TX DMA interrupt to signal completion of a transfer. This interrupt is raised once all bytes have been written to the TX FIFO and it is then necessary to busy-wait for the TX FIFO to become empty before the transfer can be finalized. As an alternative approach, I have explored using the SPI controller's DONE interrupt to detect completion. This interrupt is signaled when the TX FIFO becomes empty, avoiding the need to busy-wait. However latency deteriorates compared to the present commit and surprisingly, CPU time is slightly higher as well: It turns out that in 45% of the cases, no busy-waiting is needed at all and in 76% of the cases, less than 10 busy-wait iterations are sufficient for the TX FIFO to drain. This was measured on an RT kernel. On a vanilla kernel, wakeup latency is worse and thus fewer iterations are needed. The measurements were made with an SPI clock of 20 MHz, they may differ slightly for slower or faster clock speeds. Previously we always used the RX DMA interrupt to signal completion of a transfer. Using the TX DMA interrupt now introduces a race condition: TX DMA is always started before RX DMA so that bytes are already clocked out while RX DMA is still being set up. But if a TX-only transfer is very short, then the TX DMA interrupt may occur before RX DMA is set up. If the interrupt happens to occur on the same CPU, setup of RX DMA may even be delayed until after the interrupt was handled. I've solved this by having the TX DMA callback clear the RX FIFO while busy-waiting for the TX FIFO to drain, thus avoiding a dependency on setup of RX DMA. Additionally, I am using a lock-free mechanism with two flags, tx_dma_active and rx_dma_active plus memory barriers to terminate RX DMA either by the TX DMA callback or immediately after setting it up, whichever wins the race. I've explored an alternative approach which temporarily disables the TX DMA callback until RX DMA has been set up (using tasklet_disable(), local_bh_disable() or local_irq_save()), but the performance was minimally worse. [Nathan Chancellor contributed a DMA mapping fixup for an early version of this commit, hence his Signed-off-by.] Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Nathan Chancellor Signed-off-by: Lukas Wunner Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Robert Jarzmik Link: https://lore.kernel.org/r/874949385f28251e2dcaa9494e39a27b50e9f9e4.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 241 ++++++++++++++++++++++++++++++++++---- 1 file changed, 218 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index f01d18d521f2..3fe823891861 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -106,6 +106,16 @@ MODULE_PARM_DESC(polling_limit_us, * These are counted as well in @count_transfer_polling and * @count_transfer_irq * @count_transfer_dma: count how often dma mode is used + * @chip_select: SPI slave currently selected + * (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs) + * @tx_dma_active: whether a TX DMA descriptor is in progress + * @rx_dma_active: whether a RX DMA descriptor is in progress + * (used by bcm2835_spi_dma_tx_done() to handle a race) + * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers + * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register) + * @clear_rx_addr: bus address of @clear_rx_cs + * @clear_rx_cs: precalculated CS register value to clear RX FIFO + * (uses slave-specific clock polarity and phase settings) */ struct bcm2835_spi { void __iomem *regs; @@ -126,6 +136,13 @@ struct bcm2835_spi { u64 count_transfer_irq; u64 count_transfer_irq_after_polling; u64 count_transfer_dma; + + u8 chip_select; + unsigned int tx_dma_active; + unsigned int rx_dma_active; + struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS]; + dma_addr_t clear_rx_addr; + u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned; }; #if defined(CONFIG_DEBUG_FS) @@ -455,7 +472,7 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, if (!sg_is_last(&tfr->tx_sg.sgl[0])) bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3; - if (!sg_is_last(&tfr->rx_sg.sgl[0])) { + if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) { bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3; if (bs->rx_prologue > bs->tx_prologue) { @@ -547,7 +564,13 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) bs->tx_prologue = 0; } -static void bcm2835_spi_dma_done(void *data) +/** + * bcm2835_spi_dma_rx_done() - callback for DMA RX channel + * @data: SPI master controller + * + * Used for bidirectional and RX-only transfers. + */ +static void bcm2835_spi_dma_rx_done(void *data) { struct spi_controller *ctlr = data; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); @@ -561,14 +584,61 @@ static void bcm2835_spi_dma_done(void *data) * situation otherwise... */ dmaengine_terminate_async(ctlr->dma_tx); + bs->tx_dma_active = false; + bs->rx_dma_active = false; bcm2835_spi_undo_prologue(bs); /* and mark as completed */; complete(&ctlr->xfer_completion); } +/** + * bcm2835_spi_dma_tx_done() - callback for DMA TX channel + * @data: SPI master controller + * + * Used for TX-only transfers. + */ +static void bcm2835_spi_dma_tx_done(void *data) +{ + struct spi_controller *ctlr = data; + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + + /* busy-wait for TX FIFO to empty */ + while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) + bcm2835_wr(bs, BCM2835_SPI_CS, + bs->clear_rx_cs[bs->chip_select]); + + bs->tx_dma_active = false; + smp_wmb(); + + /* + * In case of a very short transfer, RX DMA may not have been + * issued yet. The onus is then on bcm2835_spi_transfer_one_dma() + * to terminate it immediately after issuing. + */ + if (cmpxchg(&bs->rx_dma_active, true, false)) + dmaengine_terminate_async(ctlr->dma_rx); + + bcm2835_spi_undo_prologue(bs); + bcm2835_spi_reset_hw(ctlr); + complete(&ctlr->xfer_completion); +} + +/** + * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist + * @ctlr: SPI master controller + * @spi: SPI slave + * @tfr: SPI transfer + * @bs: BCM2835 SPI controller + * @is_tx: whether to submit DMA descriptor for TX or RX sglist + * + * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr. + * Return 0 on success or a negative error number. + */ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, + struct spi_device *spi, struct spi_transfer *tfr, + struct bcm2835_spi *bs, bool is_tx) { struct dma_chan *chan; @@ -585,8 +655,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, chan = ctlr->dma_tx; nents = tfr->tx_sg.nents; sgl = tfr->tx_sg.sgl; - flags = 0 /* no tx interrupt */; - + flags = tfr->rx_buf ? 0 : DMA_PREP_INTERRUPT; } else { dir = DMA_DEV_TO_MEM; chan = ctlr->dma_rx; @@ -599,10 +668,17 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, if (!desc) return -EINVAL; - /* set callback for rx */ + /* + * Completion is signaled by the RX channel for bidirectional and + * RX-only transfers; else by the TX channel for TX-only transfers. + */ if (!is_tx) { - desc->callback = bcm2835_spi_dma_done; + desc->callback = bcm2835_spi_dma_rx_done; desc->callback_param = ctlr; + } else if (!tfr->rx_buf) { + desc->callback = bcm2835_spi_dma_tx_done; + desc->callback_param = ctlr; + bs->chip_select = spi->chip_select; } /* submit it to DMA-engine */ @@ -611,12 +687,42 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, return dma_submit_error(cookie); } +/** + * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine + * @ctlr: SPI master controller + * @spi: SPI slave + * @tfr: SPI transfer + * @cs: CS register + * + * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up + * the TX and RX DMA channel to copy between memory and FIFO register. + * + * For *TX-only* transfers (rx_buf is %NULL), copying the RX FIFO's contents to + * memory is pointless. However not reading the RX FIFO isn't an option either + * because transmission is halted once it's full. As a workaround, cyclically + * clear the RX FIFO by setting the CLEAR_RX bit in the CS register. + * + * The CS register value is precalculated in bcm2835_spi_setup(). Normally + * this is called only once, on slave registration. A DMA descriptor to write + * this value is preallocated in bcm2835_dma_init(). All that's left to do + * when performing a TX-only transfer is to submit this descriptor to the RX + * DMA channel. Latency is thereby minimized. The descriptor does not + * generate any interrupts while running. It must be terminated once the + * TX DMA channel is done. + * + * Clearing the RX FIFO is paced by the DREQ signal. The signal is asserted + * when the RX FIFO becomes half full, i.e. 32 bytes. (Tuneable with the DC + * register.) Reading 32 bytes from the RX FIFO would normally require 8 bus + * accesses, whereas clearing it requires only 1 bus access. So an 8-fold + * reduction in bus traffic and thus energy consumption is achieved. + */ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *tfr, u32 cs) { struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + dma_cookie_t cookie; int ret; /* update usage statistics */ @@ -629,13 +735,10 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs); /* setup tx-DMA */ - ret = bcm2835_spi_prepare_sg(ctlr, tfr, true); + ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true); if (ret) goto err_reset_hw; - /* start TX early */ - dma_async_issue_pending(ctlr->dma_tx); - /* set the DMA length */ bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); @@ -643,19 +746,43 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN); + bs->tx_dma_active = true; + smp_wmb(); + + /* start TX early */ + dma_async_issue_pending(ctlr->dma_tx); + /* setup rx-DMA late - to run transfers while * mapping of the rx buffers still takes place * this saves 10us or more. */ - ret = bcm2835_spi_prepare_sg(ctlr, tfr, false); + if (bs->rx_buf) { + ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, false); + } else { + cookie = dmaengine_submit(bs->clear_rx_desc[spi->chip_select]); + ret = dma_submit_error(cookie); + } if (ret) { /* need to reset on errors */ dmaengine_terminate_sync(ctlr->dma_tx); + bs->tx_dma_active = false; goto err_reset_hw; } /* start rx dma late */ dma_async_issue_pending(ctlr->dma_rx); + bs->rx_dma_active = true; + smp_mb(); + + /* + * In case of a very short TX-only transfer, bcm2835_spi_dma_tx_done() + * may run before RX DMA is issued. Terminate RX DMA if so. + */ + if (!bs->rx_buf && !bs->tx_dma_active && + cmpxchg(&bs->rx_dma_active, true, false)) { + dmaengine_terminate_async(ctlr->dma_rx); + bcm2835_spi_reset_hw(ctlr); + } /* wait for wakeup in framework */ return 1; @@ -678,26 +805,42 @@ static bool bcm2835_spi_can_dma(struct spi_controller *ctlr, return true; } -static void bcm2835_dma_release(struct spi_controller *ctlr) +static void bcm2835_dma_release(struct spi_controller *ctlr, + struct bcm2835_spi *bs) { + int i; + if (ctlr->dma_tx) { dmaengine_terminate_sync(ctlr->dma_tx); dma_release_channel(ctlr->dma_tx); ctlr->dma_tx = NULL; } + if (ctlr->dma_rx) { dmaengine_terminate_sync(ctlr->dma_rx); + + for (i = 0; i < BCM2835_SPI_NUM_CS; i++) + if (bs->clear_rx_desc[i]) + dmaengine_desc_free(bs->clear_rx_desc[i]); + + if (bs->clear_rx_addr) + dma_unmap_single(ctlr->dma_rx->device->dev, + bs->clear_rx_addr, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + dma_release_channel(ctlr->dma_rx); ctlr->dma_rx = NULL; } } -static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev) +static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, + struct bcm2835_spi *bs) { struct dma_slave_config slave_config; const __be32 *addr; dma_addr_t dma_reg_base; - int ret; + int ret, i; /* base address in dma-space */ addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL); @@ -727,17 +870,51 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev) if (ret) goto err_config; + /* + * The RX DMA channel is used bidirectionally: It either reads the + * RX FIFO or, in case of a TX-only transfer, cyclically writes a + * precalculated value to the CS register to clear the RX FIFO. + */ slave_config.src_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_CS); + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ret = dmaengine_slave_config(ctlr->dma_rx, &slave_config); if (ret) goto err_config; + bs->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev, + bs->clear_rx_cs, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + if (dma_mapping_error(ctlr->dma_rx->device->dev, bs->clear_rx_addr)) { + dev_err(dev, "cannot map clear_rx_cs - not using DMA mode\n"); + bs->clear_rx_addr = 0; + goto err_release; + } + + for (i = 0; i < BCM2835_SPI_NUM_CS; i++) { + bs->clear_rx_desc[i] = dmaengine_prep_dma_cyclic(ctlr->dma_rx, + bs->clear_rx_addr + i * sizeof(u32), + sizeof(u32), 0, + DMA_MEM_TO_DEV, 0); + if (!bs->clear_rx_desc[i]) { + dev_err(dev, "cannot prepare clear_rx_desc - not using DMA mode\n"); + goto err_release; + } + + ret = dmaengine_desc_set_reuse(bs->clear_rx_desc[i]); + if (ret) { + dev_err(dev, "cannot reuse clear_rx_desc - not using DMA mode\n"); + goto err_release; + } + } + /* all went well, so set can_dma */ ctlr->can_dma = bcm2835_spi_can_dma; - /* need to do TX AND RX DMA, so we need dummy buffers */ - ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; + /* need to do TX DMA, so we need a dummy buffer */ + ctlr->flags = SPI_CONTROLLER_MUST_TX; return; @@ -745,7 +922,7 @@ err_config: dev_err(dev, "issue configuring dma: %d - not using DMA mode\n", ret); err_release: - bcm2835_dma_release(ctlr); + bcm2835_dma_release(ctlr, bs); err: return; } @@ -834,8 +1011,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); /* handle all the 3-wire mode */ - if (spi->mode & SPI_3WIRE && tfr->rx_buf && - tfr->rx_buf != ctlr->dummy_rx) + if (spi->mode & SPI_3WIRE && tfr->rx_buf) cs |= BCM2835_SPI_CS_REN; /* set transmit buffers and length */ @@ -903,7 +1079,9 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, /* if an error occurred and we have an active dma, then terminate */ dmaengine_terminate_sync(ctlr->dma_tx); + bs->tx_dma_active = false; dmaengine_terminate_sync(ctlr->dma_rx); + bs->rx_dma_active = false; bcm2835_spi_undo_prologue(bs); /* and reset */ @@ -917,7 +1095,8 @@ static int chip_match_name(struct gpio_chip *chip, void *data) static int bcm2835_spi_setup(struct spi_device *spi) { - struct bcm2835_spi *bs = spi_controller_get_devdata(spi->controller); + struct spi_controller *ctlr = spi->controller; + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct gpio_chip *chip; enum gpio_lookup_flags lflags; u32 cs; @@ -935,6 +1114,21 @@ static int bcm2835_spi_setup(struct spi_device *spi) cs |= BCM2835_SPI_CS_CPHA; bs->prepare_cs[spi->chip_select] = cs; + /* + * Precalculate SPI slave's CS register value to clear RX FIFO + * in case of a TX-only DMA transfer. + */ + if (ctlr->dma_rx) { + bs->clear_rx_cs[spi->chip_select] = cs | + BCM2835_SPI_CS_TA | + BCM2835_SPI_CS_DMAEN | + BCM2835_SPI_CS_CLEAR_RX; + dma_sync_single_for_device(ctlr->dma_rx->device->dev, + bs->clear_rx_addr, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + } + /* * sanity checking the native-chipselects */ @@ -1002,7 +1196,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev) struct bcm2835_spi *bs; int err; - ctlr = spi_alloc_master(&pdev->dev, sizeof(*bs)); + ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), + dma_get_cache_alignment())); if (!ctlr) return -ENOMEM; @@ -1041,7 +1236,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) clk_prepare_enable(bs->clk); - bcm2835_dma_init(ctlr, &pdev->dev); + bcm2835_dma_init(ctlr, &pdev->dev, bs); /* initialise the hardware with the default polarities */ bcm2835_wr(bs, BCM2835_SPI_CS, @@ -1085,7 +1280,7 @@ static int bcm2835_spi_remove(struct platform_device *pdev) clk_disable_unprepare(bs->clk); - bcm2835_dma_release(ctlr); + bcm2835_dma_release(ctlr, bs); return 0; } From 2b8279aec1829da4dc645e8731c28d2f5458d652 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 11 Sep 2019 12:15:30 +0200 Subject: [PATCH 099/102] spi: bcm2835: Speed up RX-only DMA transfers by zero-filling TX FIFO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BCM2835 SPI driver currently sets the SPI_CONTROLLER_MUST_TX flag. When performing an RX-only transfer, this flag causes the SPI core to allocate and DMA-map a dummy buffer which is copied to the TX FIFO. The dummy buffer is necessary because the chip is not capable of automatically clocking out null bytes. Avoid the overhead induced by the dummy buffer by preallocating a reusable DMA transaction which fills the TX FIFO by cyclically copying from the zero page. The transaction requires very little CPU time to submit and generates no interrupts while running. Specifics are provided in kerneldoc comments. [Nathan Chancellor contributed a DMA mapping fixup for an early version of this commit, hence his Signed-off-by.] Tested-by: Nuno Sá Tested-by: Noralf Trønnes Signed-off-by: Nathan Chancellor Signed-off-by: Lukas Wunner Acked-by: Stefan Wahren Acked-by: Martin Sperl Cc: Robert Jarzmik Link: https://lore.kernel.org/r/f45920af18dbf06e34129bbc406f53dc9c5d1075.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 93 ++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 3fe823891861..8a0ea465cbe0 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -111,6 +111,9 @@ MODULE_PARM_DESC(polling_limit_us, * @tx_dma_active: whether a TX DMA descriptor is in progress * @rx_dma_active: whether a RX DMA descriptor is in progress * (used by bcm2835_spi_dma_tx_done() to handle a race) + * @fill_tx_desc: preallocated TX DMA descriptor used for RX-only transfers + * (cyclically copies from zero page to TX FIFO) + * @fill_tx_addr: bus address of zero page * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register) * @clear_rx_addr: bus address of @clear_rx_cs @@ -140,6 +143,8 @@ struct bcm2835_spi { u8 chip_select; unsigned int tx_dma_active; unsigned int rx_dma_active; + struct dma_async_tx_descriptor *fill_tx_desc; + dma_addr_t fill_tx_addr; struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS]; dma_addr_t clear_rx_addr; u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned; @@ -469,14 +474,14 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, bs->rx_prologue = 0; bs->tx_spillover = false; - if (!sg_is_last(&tfr->tx_sg.sgl[0])) + if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0])) bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3; if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) { bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3; if (bs->rx_prologue > bs->tx_prologue) { - if (sg_is_last(&tfr->tx_sg.sgl[0])) { + if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) { bs->tx_prologue = bs->rx_prologue; } else { bs->tx_prologue += 4; @@ -508,6 +513,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; } + if (!bs->tx_buf) + return; + /* * Write remaining TX prologue. Adjust first entry in TX sglist. * Also adjust second entry if prologue spills over to it. @@ -552,6 +560,9 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; } + if (!bs->tx_buf) + goto out; + if (likely(!bs->tx_spillover)) { sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; @@ -560,7 +571,7 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; } - +out: bs->tx_prologue = 0; } @@ -575,10 +586,7 @@ static void bcm2835_spi_dma_rx_done(void *data) struct spi_controller *ctlr = data; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - /* reset fifo and HW */ - bcm2835_spi_reset_hw(ctlr); - - /* and terminate tx-dma as we do not have an irq for it + /* terminate tx-dma as we do not have an irq for it * because when the rx dma will terminate and this callback * is called the tx-dma must have finished - can't get to this * situation otherwise... @@ -588,6 +596,9 @@ static void bcm2835_spi_dma_rx_done(void *data) bs->rx_dma_active = false; bcm2835_spi_undo_prologue(bs); + /* reset fifo and HW */ + bcm2835_spi_reset_hw(ctlr); + /* and mark as completed */; complete(&ctlr->xfer_completion); } @@ -715,6 +726,24 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, * register.) Reading 32 bytes from the RX FIFO would normally require 8 bus * accesses, whereas clearing it requires only 1 bus access. So an 8-fold * reduction in bus traffic and thus energy consumption is achieved. + * + * For *RX-only* transfers (tx_buf is %NULL), fill the TX FIFO by cyclically + * copying from the zero page. The DMA descriptor to do this is preallocated + * in bcm2835_dma_init(). It must be terminated once the RX DMA channel is + * done and can then be reused. + * + * The BCM2835 DMA driver autodetects when a transaction copies from the zero + * page and utilizes the DMA controller's ability to synthesize zeroes instead + * of copying them from memory. This reduces traffic on the memory bus. The + * feature is not available on so-called "lite" channels, but normally TX DMA + * is backed by a full-featured channel. + * + * Zero-filling the TX FIFO is paced by the DREQ signal. Unfortunately the + * BCM2835 SPI controller continues to assert DREQ even after the DLEN register + * has been counted down to zero (hardware erratum). Thus, when the transfer + * has finished, the DMA engine zero-fills the TX FIFO until it is half full. + * (Tuneable with the DC register.) So up to 9 gratuitous bus accesses are + * performed at the end of an RX-only transfer. */ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, struct spi_device *spi, @@ -735,7 +764,12 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs); /* setup tx-DMA */ - ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true); + if (bs->tx_buf) { + ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true); + } else { + cookie = dmaengine_submit(bs->fill_tx_desc); + ret = dma_submit_error(cookie); + } if (ret) goto err_reset_hw; @@ -812,6 +846,16 @@ static void bcm2835_dma_release(struct spi_controller *ctlr, if (ctlr->dma_tx) { dmaengine_terminate_sync(ctlr->dma_tx); + + if (bs->fill_tx_desc) + dmaengine_desc_free(bs->fill_tx_desc); + + if (bs->fill_tx_addr) + dma_unmap_page_attrs(ctlr->dma_tx->device->dev, + bs->fill_tx_addr, sizeof(u32), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + dma_release_channel(ctlr->dma_tx); ctlr->dma_tx = NULL; } @@ -862,7 +906,11 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, goto err_release; } - /* configure DMAs */ + /* + * The TX DMA channel either copies a transfer's TX buffer to the FIFO + * or, in case of an RX-only transfer, cyclically copies from the zero + * page to the FIFO using a preallocated, reusable descriptor. + */ slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -870,6 +918,31 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, if (ret) goto err_config; + bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev, + ZERO_PAGE(0), 0, sizeof(u32), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) { + dev_err(dev, "cannot map zero page - not using DMA mode\n"); + bs->fill_tx_addr = 0; + goto err_release; + } + + bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx, + bs->fill_tx_addr, + sizeof(u32), 0, + DMA_MEM_TO_DEV, 0); + if (!bs->fill_tx_desc) { + dev_err(dev, "cannot prepare fill_tx_desc - not using DMA mode\n"); + goto err_release; + } + + ret = dmaengine_desc_set_reuse(bs->fill_tx_desc); + if (ret) { + dev_err(dev, "cannot reuse fill_tx_desc - not using DMA mode\n"); + goto err_release; + } + /* * The RX DMA channel is used bidirectionally: It either reads the * RX FIFO or, in case of a TX-only transfer, cyclically writes a @@ -913,8 +986,6 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, /* all went well, so set can_dma */ ctlr->can_dma = bcm2835_spi_can_dma; - /* need to do TX DMA, so we need a dummy buffer */ - ctlr->flags = SPI_CONTROLLER_MUST_TX; return; From 7359d108d44b823d5da049ee12302125a08f2216 Mon Sep 17 00:00:00 2001 From: "luhua.xu" Date: Wed, 11 Sep 2019 05:55:29 -0400 Subject: [PATCH 100/102] dt-bindings: spi: update bindings for MT6765 SoC Add a DT binding documentation for the MT6765 soc. Signed-off-by: luhua.xu Link: https://lore.kernel.org/r/1568195731-3239-2-git-send-email-luhua.xu@mediatek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-mt65xx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt index c0f6c8ecfa2e..3a8079eb18c8 100644 --- a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt +++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt @@ -5,6 +5,7 @@ Required properties: - mediatek,mt2701-spi: for mt2701 platforms - mediatek,mt2712-spi: for mt2712 platforms - mediatek,mt6589-spi: for mt6589 platforms + - mediatek,mt6765-spi: for mt6765 platforms - mediatek,mt7622-spi: for mt7622 platforms - "mediatek,mt7629-spi", "mediatek,mt7622-spi": for mt7629 platforms - mediatek,mt8135-spi: for mt8135 platforms From 2c231e0ab638519759c9a7203ecced0aa457c6c3 Mon Sep 17 00:00:00 2001 From: "luhua.xu" Date: Wed, 11 Sep 2019 05:55:30 -0400 Subject: [PATCH 101/102] spi: mediatek: add spi support for mt6765 IC This patch add spi support for mt6765 IC. Signed-off-by: luhua.xu Link: https://lore.kernel.org/r/1568195731-3239-3-git-send-email-luhua.xu@mediatek.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 1f5f716016a2..c70911e2a6e1 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -102,6 +102,12 @@ static const struct mtk_spi_compatible mt2712_compat = { .must_tx = true, }; +static const struct mtk_spi_compatible mt6765_compat = { + .need_pad_sel = true, + .must_tx = true, + .enhance_timing = true, +}; + static const struct mtk_spi_compatible mt7622_compat = { .must_tx = true, .enhance_timing = true, @@ -137,6 +143,9 @@ static const struct of_device_id mtk_spi_of_match[] = { { .compatible = "mediatek,mt6589-spi", .data = (void *)&mtk_common_compat, }, + { .compatible = "mediatek,mt6765-spi", + .data = (void *)&mt6765_compat, + }, { .compatible = "mediatek,mt7622-spi", .data = (void *)&mt7622_compat, }, From fdeae8f5a2e5eb3fcc9c295bfb28503c3abd4d6e Mon Sep 17 00:00:00 2001 From: "luhua.xu" Date: Wed, 11 Sep 2019 05:55:31 -0400 Subject: [PATCH 102/102] spi: mediatek: support large PA Add spi large PA(max=64G) support for DMA transfer. Signed-off-by: luhua.xu Link: https://lore.kernel.org/r/1568195731-3239-4-git-send-email-luhua.xu@mediatek.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 44 +++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index c70911e2a6e1..6888a4dcff6d 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -17,6 +17,7 @@ #include #include #include +#include #define SPI_CFG0_REG 0x0000 #define SPI_CFG1_REG 0x0004 @@ -28,6 +29,8 @@ #define SPI_STATUS0_REG 0x001c #define SPI_PAD_SEL_REG 0x0024 #define SPI_CFG2_REG 0x0028 +#define SPI_TX_SRC_REG_64 0x002c +#define SPI_RX_DST_REG_64 0x0030 #define SPI_CFG0_SCK_HIGH_OFFSET 0 #define SPI_CFG0_SCK_LOW_OFFSET 8 @@ -73,6 +76,10 @@ #define MTK_SPI_MAX_FIFO_SIZE 32U #define MTK_SPI_PACKET_SIZE 1024 +#define MTK_SPI_32BITS_MASK (0xffffffff) + +#define DMA_ADDR_EXT_BITS (36) +#define DMA_ADDR_DEF_BITS (32) struct mtk_spi_compatible { bool need_pad_sel; @@ -80,6 +87,8 @@ struct mtk_spi_compatible { bool must_tx; /* some IC design adjust cfg register to enhance time accuracy */ bool enhance_timing; + /* some IC support DMA addr extension */ + bool dma_ext; }; struct mtk_spi { @@ -106,6 +115,7 @@ static const struct mtk_spi_compatible mt6765_compat = { .need_pad_sel = true, .must_tx = true, .enhance_timing = true, + .dma_ext = true, }; static const struct mtk_spi_compatible mt7622_compat = { @@ -380,10 +390,25 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master, { struct mtk_spi *mdata = spi_master_get_devdata(master); - if (mdata->tx_sgl) - writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG); - if (mdata->rx_sgl) - writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG); + if (mdata->tx_sgl) { + writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK), + mdata->base + SPI_TX_SRC_REG); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (mdata->dev_comp->dma_ext) + writel((u32)(xfer->tx_dma >> 32), + mdata->base + SPI_TX_SRC_REG_64); +#endif + } + + if (mdata->rx_sgl) { + writel((u32)(xfer->rx_dma & MTK_SPI_32BITS_MASK), + mdata->base + SPI_RX_DST_REG); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (mdata->dev_comp->dma_ext) + writel((u32)(xfer->rx_dma >> 32), + mdata->base + SPI_RX_DST_REG_64); +#endif + } } static int mtk_spi_fifo_transfer(struct spi_master *master, @@ -595,7 +620,7 @@ static int mtk_spi_probe(struct platform_device *pdev) struct mtk_spi *mdata; const struct of_device_id *of_id; struct resource *res; - int i, irq, ret; + int i, irq, ret, addr_bits; master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); if (!master) { @@ -761,6 +786,15 @@ static int mtk_spi_probe(struct platform_device *pdev) } } + if (mdata->dev_comp->dma_ext) + addr_bits = DMA_ADDR_EXT_BITS; + else + addr_bits = DMA_ADDR_DEF_BITS; + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(addr_bits)); + if (ret) + dev_notice(&pdev->dev, "SPI dma_set_mask(%d) failed, ret:%d\n", + addr_bits, ret); + return 0; err_disable_runtime_pm: