From 6cf3c0f84d40847843f86e8ead58c92602b2d80d Mon Sep 17 00:00:00 2001 From: Ji Sheng Teoh Date: Wed, 8 May 2024 13:47:27 +0800 Subject: spi: spi-cadence: Add optional reset control support Add optional reset control support for spi-cadence to properly bring the SPI device into an operating condition. Co-developed-by: Eng Lee Teh Signed-off-by: Eng Lee Teh Co-developed-by: Ley Foon Tan Signed-off-by: Ley Foon Tan Signed-off-by: Ji Sheng Teoh Link: https://msgid.link/r/20240508054728.1751162-2-jisheng.teoh@starfivetech.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index e5140532071d..4eacf3f6e031 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* Name of this driver */ @@ -111,6 +112,7 @@ * @dev_busy: Device busy flag * @is_decoded_cs: Flag for decoder property set or not * @tx_fifo_depth: Depth of the TX FIFO + * @rstc: Optional reset control for SPI controller */ struct cdns_spi { void __iomem *regs; @@ -125,6 +127,7 @@ struct cdns_spi { u8 dev_busy; u32 is_decoded_cs; unsigned int tx_fifo_depth; + struct reset_control *rstc; }; /* Macros for the SPI controller read/write */ @@ -588,6 +591,16 @@ static int cdns_spi_probe(struct platform_device *pdev) goto remove_ctlr; } + xspi->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, "spi"); + if (IS_ERR(xspi->rstc)) { + ret = dev_err_probe(&pdev->dev, PTR_ERR(xspi->rstc), + "Cannot get SPI reset.\n"); + goto remove_ctlr; + } + + reset_control_assert(xspi->rstc); + reset_control_deassert(xspi->rstc); + if (!spi_controller_is_target(ctlr)) { xspi->ref_clk = devm_clk_get_enabled(&pdev->dev, "ref_clk"); if (IS_ERR(xspi->ref_clk)) { -- cgit v1.2.3 From 837e53f766fe9423fcb4e0eacbb3b7ff0e33103c Mon Sep 17 00:00:00 2001 From: Ji Sheng Teoh Date: Wed, 8 May 2024 13:47:28 +0800 Subject: spi: dt-bindings: spi-cadence: Add optional reset control Document the optional reset control to SPI. Co-developed-by: Eng Lee Teh Signed-off-by: Eng Lee Teh Co-developed-by: Ley Foon Tan Signed-off-by: Ley Foon Tan Signed-off-by: Ji Sheng Teoh Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240508054728.1751162-3-jisheng.teoh@starfivetech.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-cadence.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-cadence.yaml b/Documentation/devicetree/bindings/spi/spi-cadence.yaml index d4b61b0e8301..8de96abe9da1 100644 --- a/Documentation/devicetree/bindings/spi/spi-cadence.yaml +++ b/Documentation/devicetree/bindings/spi/spi-cadence.yaml @@ -55,6 +55,13 @@ properties: label: description: Descriptive name of the SPI controller. + resets: + maxItems: 1 + + reset-names: + items: + - const: spi + required: - compatible - reg -- cgit v1.2.3 From 19a9aa9302276d49a4c4890f656359808d3a0151 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 22 May 2024 16:52:52 +0200 Subject: spi: dw: differentiate between unsupported and invalid requests The driver does not support dirmap write operations, return -EOPTNOTSUPP in this case. Most controllers have a maximum linear mapping area. Requests beyond this limit can be considered invalid, rather than unsupported. >From a caller (and reviewer) point of view, distinguising between the two may be helpful because somehow one can be "fixed" while the other will always be refused no matter how hard we try. As part of a wider work to bring spi-nand continuous reads, it was useful to easily catch the upper limit direct mapping boundaries for each controller, with the idea of enlarging this area from a page to an eraseblock, without risking too many regressions. Signed-off-by: Miquel Raynal Link: https://msgid.link/r/20240522145255.995778-2-miquel.raynal@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-bt1.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c index 5391bcac305c..4577e8096cd9 100644 --- a/drivers/spi/spi-dw-bt1.c +++ b/drivers/spi/spi-dw-bt1.c @@ -55,13 +55,15 @@ static int dw_spi_bt1_dirmap_create(struct spi_mem_dirmap_desc *desc) !dwsbt1->dws.mem_ops.supports_op(desc->mem, &desc->info.op_tmpl)) return -EOPNOTSUPP; + if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN) + return -EOPNOTSUPP; + /* * Make sure the requested region doesn't go out of the physically - * mapped flash memory bounds and the operation is read-only. + * mapped flash memory bounds. */ - if (desc->info.offset + desc->info.length > dwsbt1->map_len || - desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN) - return -EOPNOTSUPP; + if (desc->info.offset + desc->info.length > dwsbt1->map_len) + return -EINVAL; return 0; } -- cgit v1.2.3 From 5e657a8e660c0fcafa83527d3a7f4f447f4a9364 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 22 May 2024 16:52:53 +0200 Subject: spi: mxic: differentiate between unsupported and invalid requests If the request is out of range, returning -EINVAL seems sensible. However if there is no direct mapping available (which is a possible case), no direct mapping will ever be allowed, hence -EOPNOTSUP is probably more relevant in this case. >From a caller (and reviewer) point of view, distinguising between the two may be helpful because somehow one can be "fixed" while the other will always be refused no matter how hard we try. As part of a wider work to bring spi-nand continuous reads, it was useful to easily catch the upper limit direct mapping boundaries for each controller, with the idea of enlarging this area from a page to an eraseblock, without risking too many regressions. Signed-off-by: Miquel Raynal Link: https://msgid.link/r/20240522145255.995778-3-miquel.raynal@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-mxic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index 60c9f3048ac9..6156d691630a 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -496,7 +496,7 @@ static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller); if (!mxic->linear.map) - return -EINVAL; + return -EOPNOTSUPP; if (desc->info.offset + desc->info.length > U32_MAX) return -EINVAL; -- cgit v1.2.3 From 615725a9a8c8aa0976a1469b88a1e5d696e25eb0 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 22 May 2024 16:52:54 +0200 Subject: spi: rpc-if: differentiate between unsupported and invalid requests If the request is out of range, returning -EINVAL seems a better pick than -ENOTSUPP. >From a caller (and reviewer) point of view, distinguising between the two may be helpful because somehow one can be "fixed" while the other will always be refused no matter how hard we try. As part of a wider work to bring spi-nand continuous reads, it was useful to easily catch the upper limit direct mapping boundaries for each controller, with the idea of enlarging this area from a page to an eraseblock, without risking too many regressions. In all other cases, as part of a wider work towards using -EOPNOTSUP rather than -ENOTSUPP (which is not a SUSV4 code), let's change the error code to be uniform across spi-mem controller drivers. Finally, reword a little bit the conditions to clarify what is intended (ie. checking for the presence of a direct mapping, and also ensuring we create a dirmap only on DATA_IN flows). Signed-off-by: Miquel Raynal Link: https://msgid.link/r/20240522145255.995778-4-miquel.raynal@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-rpc-if.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c index e11146932828..d3f07fd719bd 100644 --- a/drivers/spi/spi-rpc-if.c +++ b/drivers/spi/spi-rpc-if.c @@ -95,16 +95,16 @@ static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) spi_controller_get_devdata(desc->mem->spi->controller); if (desc->info.offset + desc->info.length > U32_MAX) - return -ENOTSUPP; + return -EINVAL; if (!rpcif_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl)) - return -ENOTSUPP; + return -EOPNOTSUPP; - if (!rpc->dirmap && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) - return -ENOTSUPP; + if (!rpc->dirmap) + return -EOPNOTSUPP; - if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) - return -ENOTSUPP; + if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN) + return -EOPNOTSUPP; return 0; } -- cgit v1.2.3 From 41b86b1455079600fa2b13e59f7c6f256d1d3131 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 22 May 2024 16:52:55 +0200 Subject: spi: wpcm-fiu: differentiate between unsupported and invalid requests When the requested dirmap accesses are outside of the window, it is probably more sensible to return -EINVAL rather than an "unsupported" error code. If however the operation in itself is not supported, then -EOPNOTSUP is likely going to be preferred as it is a standard error code. >From a caller (and reviewer) point of view, distinguising between the two may be helpful because somehow one can be "fixed" while the other will always be refused no matter how hard we try. As part of a wider work to bring spi-nand continuous reads, it was useful to easily catch the upper limit direct mapping boundaries for each controller, with the idea of enlarging this area from a page to an eraseblock, without risking too many regressions. Signed-off-by: Miquel Raynal Link: https://msgid.link/r/20240522145255.995778-5-miquel.raynal@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-wpcm-fiu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c index 6b16a22cc3a4..886d6d7771d4 100644 --- a/drivers/spi/spi-wpcm-fiu.c +++ b/drivers/spi/spi-wpcm-fiu.c @@ -378,7 +378,7 @@ static int wpcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) int cs = spi_get_chipselect(desc->mem->spi, 0); if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN) - return -ENOTSUPP; + return -EOPNOTSUPP; /* * Unfortunately, FIU only supports a 16 MiB direct mapping window (per @@ -387,11 +387,11 @@ static int wpcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) * flashes that are bigger than 16 MiB. */ if (desc->info.offset + desc->info.length > MAX_MEMORY_SIZE_PER_CS) - return -ENOTSUPP; + return -EINVAL; /* Don't read past the memory window */ if (cs * MAX_MEMORY_SIZE_PER_CS + desc->info.offset + desc->info.length > fiu->memory_size) - return -ENOTSUPP; + return -EINVAL; return 0; } -- cgit v1.2.3 From 3b4c0fbc19930af0904fb5995ed4e7b6ffe0b237 Mon Sep 17 00:00:00 2001 From: Prajna Rajendra Kumar Date: Tue, 14 May 2024 11:45:06 +0100 Subject: spi: dt-bindings: Add num-cs property for mpfs-spi The PolarFire SoC SPI "hard" controller supports eight CS lines, out of which only one CS line is physically wired. The default value of 'num-cs' was never set and it did not didn't impose a maximum value. To reflect this hardware limitation in the device tree, the binding enforces that the 'num-cs' property cannot exceed 1 unless additional CS lines are explicitly defined using GPIO descriptors. Fixes: 2da187304e55 ("spi: add bindings for microchip mpfs spi") Signed-off-by: Prajna Rajendra Kumar Link: https://msgid.link/r/20240514104508.938448-2-prajna.rajendrakumar@microchip.com Reviewed-by: Conor Dooley Signed-off-by: Mark Brown --- .../bindings/spi/microchip,mpfs-spi.yaml | 29 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml index 74a817cc7d94..ffa8d1b48f8b 100644 --- a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml +++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml @@ -13,9 +13,6 @@ description: maintainers: - Conor Dooley -allOf: - - $ref: spi-controller.yaml# - properties: compatible: oneOf: @@ -43,6 +40,32 @@ required: - interrupts - clocks +allOf: + - $ref: spi-controller.yaml# + + - if: + properties: + compatible: + contains: + const: microchip,mpfs-spi + then: + properties: + num-cs: + default: 1 + + - if: + properties: + compatible: + contains: + const: microchip,mpfs-spi + not: + required: + - cs-gpios + then: + properties: + num-cs: + maximum: 1 + unevaluatedProperties: false examples: -- cgit v1.2.3 From a7ed3a11202d90939a3d00ffcc8cf50703cb7b35 Mon Sep 17 00:00:00 2001 From: Prajna Rajendra Kumar Date: Tue, 14 May 2024 11:45:07 +0100 Subject: spi: spi-microchip-core: Fix the number of chip selects supported The SPI "hard" controller in PolarFire SoC has eight CS lines, but only one CS line is wired. When the 'num-cs' property is not specified in the device tree, the driver defaults to the MAX_CS value, which has been fixed to 1 to match the hardware configuration; however, when the 'num-cs' property is explicitly defined in the device tree, it overrides the default value. Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers") Signed-off-by: Prajna Rajendra Kumar Reviewed-by: Conor Dooley Link: https://msgid.link/r/20240514104508.938448-3-prajna.rajendrakumar@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-microchip-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c index 634364c7cfe6..c10de45aa472 100644 --- a/drivers/spi/spi-microchip-core.c +++ b/drivers/spi/spi-microchip-core.c @@ -21,7 +21,7 @@ #include #define MAX_LEN (0xffff) -#define MAX_CS (8) +#define MAX_CS (1) #define DEFAULT_FRAMESIZE (8) #define FIFO_DEPTH (32) #define CLK_GEN_MODE1_MAX (255) -- cgit v1.2.3 From 9c84429324ea2b5bc537ef8ec7d3727579d37116 Mon Sep 17 00:00:00 2001 From: Prajna Rajendra Kumar Date: Tue, 14 May 2024 11:45:08 +0100 Subject: spi: spi-microchip-core: Add support for GPIO based CS The SPI "hard" controller within the PolarFire SoC is capable of handling eight CS lines, but only one CS line is wired. Therefore, use GPIO descriptors to configure additional CS lines. Signed-off-by: Prajna Rajendra Kumar Link: https://msgid.link/r/20240514104508.938448-4-prajna.rajendrakumar@microchip.com Acked-by: Conor Dooley Signed-off-by: Mark Brown --- drivers/spi/spi-microchip-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c index c10de45aa472..6246254e1dff 100644 --- a/drivers/spi/spi-microchip-core.c +++ b/drivers/spi/spi-microchip-core.c @@ -258,6 +258,9 @@ static int mchp_corespi_setup(struct spi_device *spi) struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); u32 reg; + if (spi_is_csgpiod(spi)) + return 0; + /* * Active high targets need to be specifically set to their inactive * states during probe by adding them to the "control group" & thus @@ -516,6 +519,7 @@ static int mchp_corespi_probe(struct platform_device *pdev) host->num_chipselect = num_cs; host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->use_gpio_descriptors = true; host->setup = mchp_corespi_setup; host->bits_per_word_mask = SPI_BPW_MASK(8); host->transfer_one = mchp_corespi_transfer_one; -- cgit v1.2.3 From f261172d39f358dcecce13c310690d3937e0cca6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2024 22:40:20 +0300 Subject: spi: bitbang: Use typedef for txrx_*() callbacks With a typedef for the txrx_*() callbacks the code looks neater. Note that typedef for a function is okay to have. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240517194104.747328-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 31 +++++++++---------------------- include/linux/spi/spi_bitbang.h | 7 ++++--- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index ca5cc67555c5..d88110acdc5f 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -38,26 +38,19 @@ * working quickly, or testing for differences that aren't speed related. */ +typedef unsigned int (*spi_bb_txrx_bufs_fn)(struct spi_device *, spi_bb_txrx_word_fn, + unsigned int, struct spi_transfer *, + unsigned int); + struct spi_bitbang_cs { unsigned nsecs; /* (clock cycle time)/2 */ - u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, - u32 word, u8 bits, unsigned flags); - unsigned (*txrx_bufs)(struct spi_device *, - u32 (*txrx_word)( - struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), - unsigned, struct spi_transfer *, - unsigned); + spi_bb_txrx_word_fn txrx_word; + spi_bb_txrx_bufs_fn txrx_bufs; }; static unsigned bitbang_txrx_8( struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), + spi_bb_txrx_word_fn txrx_word, unsigned ns, struct spi_transfer *t, unsigned flags @@ -83,10 +76,7 @@ static unsigned bitbang_txrx_8( static unsigned bitbang_txrx_16( struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), + spi_bb_txrx_word_fn txrx_word, unsigned ns, struct spi_transfer *t, unsigned flags @@ -112,10 +102,7 @@ static unsigned bitbang_txrx_16( static unsigned bitbang_txrx_32( struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), + spi_bb_txrx_word_fn txrx_word, unsigned ns, struct spi_transfer *t, unsigned flags diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index b930eca2ef7b..7ca08b430ed5 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -4,6 +4,8 @@ #include +typedef u32 (*spi_bb_txrx_word_fn)(struct spi_device *, unsigned int, u32, u8, unsigned int); + struct spi_bitbang { struct mutex lock; u8 busy; @@ -28,9 +30,8 @@ struct spi_bitbang { int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); /* txrx_word[SPI_MODE_*]() just looks like a shift register */ - u32 (*txrx_word[4])(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, unsigned flags); + spi_bb_txrx_word_fn txrx_word[4]; + int (*set_line_direction)(struct spi_device *spi, bool output); }; -- cgit v1.2.3 From c3358a746e078d0f9048732c90fdab4f37c00e0d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2024 22:40:21 +0300 Subject: spi: bitbang: Convert unsigned to unsigned int Simple type conversion with no functional change implied. While at it, adjust indentation where it makes sense. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240517194104.747328-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index d88110acdc5f..afb1b1105ec2 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -43,21 +43,19 @@ typedef unsigned int (*spi_bb_txrx_bufs_fn)(struct spi_device *, spi_bb_txrx_wor unsigned int); struct spi_bitbang_cs { - unsigned nsecs; /* (clock cycle time)/2 */ + unsigned int nsecs; /* (clock cycle time) / 2 */ spi_bb_txrx_word_fn txrx_word; spi_bb_txrx_bufs_fn txrx_bufs; }; -static unsigned bitbang_txrx_8( - struct spi_device *spi, +static unsigned int bitbang_txrx_8(struct spi_device *spi, spi_bb_txrx_word_fn txrx_word, - unsigned ns, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; @@ -74,16 +72,14 @@ static unsigned bitbang_txrx_8( return t->len - count; } -static unsigned bitbang_txrx_16( - struct spi_device *spi, +static unsigned int bitbang_txrx_16(struct spi_device *spi, spi_bb_txrx_word_fn txrx_word, - unsigned ns, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u16 *tx = t->tx_buf; u16 *rx = t->rx_buf; @@ -100,16 +96,14 @@ static unsigned bitbang_txrx_16( return t->len - count; } -static unsigned bitbang_txrx_32( - struct spi_device *spi, +static unsigned int bitbang_txrx_32(struct spi_device *spi, spi_bb_txrx_word_fn txrx_word, - unsigned ns, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u32 *tx = t->tx_buf; u32 *rx = t->rx_buf; @@ -221,7 +215,7 @@ EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) { struct spi_bitbang_cs *cs = spi->controller_state; - unsigned nsecs = cs->nsecs; + unsigned int nsecs = cs->nsecs; struct spi_bitbang *bitbang; bitbang = spi_controller_get_devdata(spi->controller); @@ -234,7 +228,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) } if (spi->mode & SPI_3WIRE) { - unsigned flags; + unsigned int flags; flags = t->tx_buf ? SPI_CONTROLLER_NO_RX : SPI_CONTROLLER_NO_TX; return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags); -- cgit v1.2.3 From b90cc232e2ce8c959b19dc4b183e23e7aec137ab Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2024 22:40:22 +0300 Subject: spi: bitbang: Replace hard coded number of SPI modes Instead of using hard coded number of modes, replace it with SPI_MODE_X_MASK + 1 to show relation to the SPI modes. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240517194104.747328-4-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/linux/spi/spi_bitbang.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 7ca08b430ed5..d4cb83195f7a 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -30,7 +30,7 @@ struct spi_bitbang { int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); /* txrx_word[SPI_MODE_*]() just looks like a shift register */ - spi_bb_txrx_word_fn txrx_word[4]; + spi_bb_txrx_word_fn txrx_word[SPI_MODE_X_MASK + 1]; int (*set_line_direction)(struct spi_device *spi, bool output); }; -- cgit v1.2.3 From 04518cd88776721960aff724049138a8bd929c59 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2024 22:42:01 +0300 Subject: spi: gpio: Make use of device properties Convert the module to be property provider agnostic and allow it to be used on non-OF platforms. Include mod_devicetable.h explicitly to replace the dropped of.h which included mod_devicetable.h indirectly. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240517194246.747427-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 51 ++++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 909cce109bba..abf426711c22 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -5,17 +5,17 @@ * Copyright (C) 2006,2008 David Brownell * Copyright (C) 2017 Linus Walleij */ +#include #include +#include #include #include -#include -#include +#include #include #include #include - /* * This bitbanging SPI host driver should help make systems usable * when a native hardware SPI engine is not available, perhaps because @@ -326,29 +326,6 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio) return PTR_ERR_OR_ZERO(spi_gpio->sck); } -#ifdef CONFIG_OF -static const struct of_device_id spi_gpio_dt_ids[] = { - { .compatible = "spi-gpio" }, - {} -}; -MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); - -static int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_controller *host) -{ - host->dev.of_node = pdev->dev.of_node; - host->use_gpio_descriptors = true; - - return 0; -} -#else -static inline int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_controller *host) -{ - return 0; -} -#endif - static int spi_gpio_probe_pdata(struct platform_device *pdev, struct spi_controller *host) { @@ -389,19 +366,21 @@ static int spi_gpio_probe(struct platform_device *pdev) struct spi_controller *host; struct spi_gpio *spi_gpio; struct device *dev = &pdev->dev; + struct fwnode_handle *fwnode = dev_fwnode(dev); struct spi_bitbang *bb; host = devm_spi_alloc_host(dev, sizeof(*spi_gpio)); if (!host) return -ENOMEM; - if (pdev->dev.of_node) - status = spi_gpio_probe_dt(pdev, host); - else + if (fwnode) { + device_set_node(&host->dev, fwnode); + host->use_gpio_descriptors = true; + } else { status = spi_gpio_probe_pdata(pdev, host); - - if (status) - return status; + if (status) + return status; + } spi_gpio = spi_controller_get_devdata(host); @@ -459,10 +438,16 @@ static int spi_gpio_probe(struct platform_device *pdev) MODULE_ALIAS("platform:" DRIVER_NAME); +static const struct of_device_id spi_gpio_dt_ids[] = { + { .compatible = "spi-gpio" }, + {} +}; +MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); + static struct platform_driver spi_gpio_driver = { .driver = { .name = DRIVER_NAME, - .of_match_table = of_match_ptr(spi_gpio_dt_ids), + .of_match_table = spi_gpio_dt_ids, }, .probe = spi_gpio_probe, }; -- cgit v1.2.3 From 196bf3e7fe2267ed7c1a193338d0aacecb9f9ff8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2024 22:42:02 +0300 Subject: spi: gpio: Use traditional pattern when checking error codes Instead of 'if (!ret)' switch to "check for the error first" rule. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240517194246.747427-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index abf426711c22..36c587be9e28 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -239,8 +239,8 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) static int spi_gpio_setup(struct spi_device *spi) { struct gpio_desc *cs; - int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + int ret; /* * The CS GPIOs have already been @@ -248,15 +248,14 @@ static int spi_gpio_setup(struct spi_device *spi) */ if (spi_gpio->cs_gpios) { cs = spi_gpio->cs_gpios[spi_get_chipselect(spi, 0)]; - if (!spi->controller_state && cs) - status = gpiod_direction_output(cs, - !(spi->mode & SPI_CS_HIGH)); + if (!spi->controller_state && cs) { + ret = gpiod_direction_output(cs, !(spi->mode & SPI_CS_HIGH)); + if (ret) + return ret; + } } - if (!status) - status = spi_bitbang_setup(spi); - - return status; + return spi_bitbang_setup(spi); } static int spi_gpio_set_direction(struct spi_device *spi, bool output) -- cgit v1.2.3 From 6ecdb0aa4dca62d236a659426e11e6cf302e8f18 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 8 May 2024 11:06:53 -0500 Subject: spi: axi-spi-engine: Add SPI_CS_HIGH support The AXI SPI Engine IP core v1.2 added support for SPI_CS_HIGH. This provides the driver implementation to make use of this feature when supported hardware is detected. Signed-off-by: David Lechner Link: https://msgid.link/r/20240508-spi-axi-spi-engine-add-spi_cs_high-support-v1-1-695dd8e45f00@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index e358ac5b4509..3231f67ae265 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -46,6 +46,7 @@ #define SPI_ENGINE_INST_ASSERT 0x1 #define SPI_ENGINE_INST_WRITE 0x2 #define SPI_ENGINE_INST_MISC 0x3 +#define SPI_ENGINE_INST_CS_INV 0x4 #define SPI_ENGINE_CMD_REG_CLK_DIV 0x0 #define SPI_ENGINE_CMD_REG_CONFIG 0x1 @@ -73,6 +74,8 @@ SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay)) #define SPI_ENGINE_CMD_SYNC(id) \ SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id)) +#define SPI_ENGINE_CMD_CS_INV(flags) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_CS_INV, 0, (flags)) struct spi_engine_program { unsigned int length; @@ -111,6 +114,8 @@ struct spi_engine { struct spi_engine_message_state msg_state; struct completion msg_complete; unsigned int int_enable; + /* shadows hardware CS inversion flag state */ + u8 cs_inv; }; static void spi_engine_program_add_cmd(struct spi_engine_program *p, @@ -530,6 +535,29 @@ static int spi_engine_unoptimize_message(struct spi_message *msg) return 0; } +static int spi_engine_setup(struct spi_device *device) +{ + struct spi_controller *host = device->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + + if (device->mode & SPI_CS_HIGH) + spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0)); + else + spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0)); + + writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + + /* + * In addition to setting the flags, we have to do a CS assert command + * to make the new setting actually take effect. + */ + writel_relaxed(SPI_ENGINE_CMD_ASSERT(0, 0xff), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + + return 0; +} + static int spi_engine_transfer_one_message(struct spi_controller *host, struct spi_message *msg) { @@ -653,6 +681,12 @@ static int spi_engine_probe(struct platform_device *pdev) host->unoptimize_message = spi_engine_unoptimize_message; host->num_chipselect = 8; + /* Some features depend of the IP core version. */ + if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) { + host->mode_bits |= SPI_CS_HIGH; + host->setup = spi_engine_setup; + } + if (host->max_speed_hz == 0) return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0"); -- cgit v1.2.3 From 5bcbbaf0747cfe510814f40f36bbda49b851c956 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Wed, 22 May 2024 08:28:58 -0500 Subject: spi: dt-bindings: marvell,mmp2-ssp: Merge PXA SSP into schema The Marvell PXA SSP block is the same or similiar to the MMP2 variant. The only difference in the binding is the PXA version supports DMA (and that's probably a binding difference rather than an actual h/w difference). The old binding didn't belong under 'serial' as it is not a UART. The SSP block also supports audio devices, so 'spi' is not a perfect fit either. As the existing schema for MMP2 is there, just leave things as-is. The examples in the old text binding were pretty out of sync with reality. 'clock-names' and 'ssp-id' aren't documented nor used. Cc: Andy Shevchenko Signed-off-by: Rob Herring (Arm) Link: https://msgid.link/r/20240522132859.3146335-1-robh@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/serial/mrvl,pxa-ssp.txt | 64 ---------------------- .../devicetree/bindings/spi/marvell,mmp2-ssp.yaml | 35 ++++++++++-- 2 files changed, 31 insertions(+), 68 deletions(-) delete mode 100644 Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt deleted file mode 100644 index d10cc06c0c37..000000000000 --- a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt +++ /dev/null @@ -1,64 +0,0 @@ -Device tree bindings for Marvell PXA SSP ports - -Required properties: - - - compatible: Must be one of - mrvl,pxa25x-ssp - mvrl,pxa25x-nssp - mrvl,pxa27x-ssp - mrvl,pxa3xx-ssp - mvrl,pxa168-ssp - mrvl,pxa910-ssp - mrvl,ce4100-ssp - - - reg: The memory base - - dmas: Two dma phandles, one for rx, one for tx - - dma-names: Must be "rx", "tx" - - -Example for PXA3xx: - - ssp0: ssp@41000000 { - compatible = "mrvl,pxa3xx-ssp"; - reg = <0x41000000 0x40>; - ssp-id = <1>; - interrupts = <24>; - clock-names = "pxa27x-ssp.0"; - dmas = <&dma 13 - &dma 14>; - dma-names = "rx", "tx"; - }; - - ssp1: ssp@41700000 { - compatible = "mrvl,pxa3xx-ssp"; - reg = <0x41700000 0x40>; - ssp-id = <2>; - interrupts = <16>; - clock-names = "pxa27x-ssp.1"; - dmas = <&dma 15 - &dma 16>; - dma-names = "rx", "tx"; - }; - - ssp2: ssp@41900000 { - compatibl3 = "mrvl,pxa3xx-ssp"; - reg = <0x41900000 0x40>; - ssp-id = <3>; - interrupts = <0>; - clock-names = "pxa27x-ssp.2"; - dmas = <&dma 66 - &dma 67>; - dma-names = "rx", "tx"; - }; - - ssp3: ssp@41a00000 { - compatible = "mrvl,pxa3xx-ssp"; - reg = <0x41a00000 0x40>; - ssp-id = <4>; - interrupts = <13>; - clock-names = "pxa27x-ssp.3"; - dmas = <&dma 2 - &dma 3>; - dma-names = "rx", "tx"; - }; - diff --git a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml index 5f4f6b5615d0..0a1bada8f800 100644 --- a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml +++ b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml @@ -10,12 +10,17 @@ title: PXA2xx SSP SPI Controller maintainers: - Lubomir Rintel -allOf: - - $ref: spi-controller.yaml# - properties: compatible: - const: marvell,mmp2-ssp + enum: + - marvell,mmp2-ssp + - mrvl,ce4100-ssp + - mvrl,pxa168-ssp + - mrvl,pxa25x-ssp + - mvrl,pxa25x-nssp + - mrvl,pxa27x-ssp + - mrvl,pxa3xx-ssp + - mrvl,pxa910-ssp interrupts: maxItems: 1 @@ -26,6 +31,16 @@ properties: clocks: maxItems: 1 + dmas: + items: + - description: Receive DMA + - description: Transmit DMA + + dma-names: + items: + - const: rx + - const: tx + ready-gpios: description: | GPIO used to signal a SPI master that the FIFO is filled and we're @@ -41,6 +56,18 @@ required: dependencies: ready-gpios: [ spi-slave ] +allOf: + - $ref: spi-controller.yaml# + - if: + properties: + compatible: + contains: + const: marvell,mmp2-ssp + then: + properties: + dmas: false + dma-names: false + unevaluatedProperties: false examples: -- cgit v1.2.3 From 61cabbd5ef7625fe5ece4aa16ccc21c91bc2fc8f Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Mon, 20 May 2024 18:59:06 +0200 Subject: spi: imx: remove empty cleanup function Remove the empty spi_imx_cleanup function. It's ok if a driver does not set the controller->cleanup pointer, the caller does a NULL check. Signed-off-by: Martin Kaiser Link: https://msgid.link/r/20240520165906.164906-1-martin@kaiser.cx Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index f4006c82f867..cf0cb52946d2 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1666,10 +1666,6 @@ static int spi_imx_setup(struct spi_device *spi) return 0; } -static void spi_imx_cleanup(struct spi_device *spi) -{ -} - static int spi_imx_prepare_message(struct spi_controller *controller, struct spi_message *msg) { @@ -1766,7 +1762,6 @@ static int spi_imx_probe(struct platform_device *pdev) controller->transfer_one = spi_imx_transfer_one; controller->setup = spi_imx_setup; - controller->cleanup = spi_imx_cleanup; controller->prepare_message = spi_imx_prepare_message; controller->unprepare_message = spi_imx_unprepare_message; controller->target_abort = spi_imx_target_abort; -- cgit v1.2.3 From ef901b38d3a4610c4067cd306c1a209f32e7ca31 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Wed, 15 May 2024 16:40:28 +0800 Subject: spi: atmel-quadspi: Add missing check for clk_prepare Add check for the return value of clk_prepare() and return the error if it fails in order to catch the error. Fixes: 4a2f83b7f780 ("spi: atmel-quadspi: add runtime pm support") Signed-off-by: Chen Ni Link: https://msgid.link/r/20240515084028.3210406-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 370c4d1572ed..5aaff3bee1b7 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -756,8 +756,15 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev) struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); int ret; - clk_prepare(aq->pclk); - clk_prepare(aq->qspick); + ret = clk_prepare(aq->pclk); + if (ret) + return ret; + + ret = clk_prepare(aq->qspick); + if (ret) { + clk_unprepare(aq->pclk); + return ret; + } ret = pm_runtime_force_resume(dev); if (ret < 0) -- cgit v1.2.3 From 2d19ea9e8840a1a77b1d464b06e62dd9b0f21e0d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 10 May 2024 23:49:52 +0300 Subject: spi: Replace custom code with device_match_acpi_handle() Since driver core provides a generic device_match_acpi_handle() we may replace the custom code with it. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240510204952.2582093-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f94420858c22..26ef4e147681 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2729,7 +2729,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) return -ENODEV; if (ctlr) { - if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle) + if (!device_match_acpi_handle(ctlr->dev.parent, parent_handle)) return -ENODEV; } else { struct acpi_device *adev; @@ -2828,7 +2828,7 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, if (!lookup.max_speed_hz && ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) && - ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) { + device_match_acpi_handle(lookup.ctlr->dev.parent, parent_handle)) { /* Apple does not use _CRS but nested devices for SPI slaves */ acpi_spi_parse_apple_properties(adev, &lookup); } -- cgit v1.2.3 From 85ce0dc28ffd4861d91b96f488d31878d8901e49 Mon Sep 17 00:00:00 2001 From: Kanak Shilledar Date: Tue, 14 May 2024 12:30:47 +0530 Subject: spi: dt-bindings: brcm,bcm2835-spi: convert to dtschema Convert the Broadcom BCM2835 SPI0 controller to newer DT schema. Created DT schema based on the .txt file which had `comaptible`, `reg`, `interrupts`, `clocks` as required properties. Added GPL-2.0 OR BSD-2-Clause License Signed-off-by: Kanak Shilledar Reviewed-by: Conor Dooley Link: https://msgid.link/r/20240514070051.2959-1-kanakshilledar111@protonmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/brcm,bcm2835-spi.txt | 23 ---------- .../devicetree/bindings/spi/brcm,bcm2835-spi.yaml | 50 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 23 deletions(-) delete mode 100644 Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt create mode 100644 Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt deleted file mode 100644 index 3d55dd64b1be..000000000000 --- a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt +++ /dev/null @@ -1,23 +0,0 @@ -Broadcom BCM2835 SPI0 controller - -The BCM2835 contains two forms of SPI master controller, one known simply as -SPI0, and the other known as the "Universal SPI Master"; part of the -auxiliary block. This binding applies to the SPI0 controller. - -Required properties: -- compatible: Should be one of "brcm,bcm2835-spi" for BCM2835/2836/2837 or - "brcm,bcm2711-spi" for BCM2711 or "brcm,bcm7211-spi" for BCM7211. -- reg: Should contain register location and length. -- interrupts: Should contain interrupt. -- clocks: The clock feeding the SPI controller. - -Example: - -spi@20204000 { - compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; - interrupts = <2 22>; - clocks = <&clk_spi>; - #address-cells = <1>; - #size-cells = <0>; -}; diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml new file mode 100644 index 000000000000..94da68792194 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/brcm,bcm2835-spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2835 SPI0 controller + +maintainers: + - Florian Fainelli + - Kanak Shilledar + - Stefan Wahren + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + enum: + - brcm,bcm2835-spi + - brcm,bcm2711-spi + - brcm,bcm7211-spi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + spi@20204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; + clocks = <&clk_spi>; + #address-cells = <1>; + #size-cells = <0>; + }; -- cgit v1.2.3 From a71b7845c0e417f2787a8e2ac77e571fce7dc72c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 10 May 2024 23:49:45 +0300 Subject: spi: Refactor spi_stop_queue() The refactoring makes code less verbose and easier to read. Besides that the binary size is also reduced, which sounds like a win-win case: add/remove: 0/1 grow/shrink: 2/2 up/down: 210/-226 (-16) Function old new delta spi_destroy_queue 42 156 +114 spi_controller_suspend 101 197 +96 spi_unregister_controller 346 319 -27 spi_register_controller 1834 1794 -40 spi_stop_queue 159 - -159 Total: Before=49230, After=49214, chg -0.03% Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240510204945.2581944-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 26ef4e147681..cc8bb7d5ba1a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2219,11 +2219,8 @@ static int spi_start_queue(struct spi_controller *ctlr) static int spi_stop_queue(struct spi_controller *ctlr) { + unsigned int limit = 500; unsigned long flags; - unsigned limit = 500; - int ret = 0; - - spin_lock_irqsave(&ctlr->queue_lock, flags); /* * This is a bit lame, but is optimized for the common execution path. @@ -2231,20 +2228,18 @@ static int spi_stop_queue(struct spi_controller *ctlr) * execution path (pump_messages) would be required to call wake_up or * friends on every SPI message. Do this instead. */ - while ((!list_empty(&ctlr->queue) || ctlr->busy) && limit--) { + do { + spin_lock_irqsave(&ctlr->queue_lock, flags); + if (list_empty(&ctlr->queue) && !ctlr->busy) { + ctlr->running = false; + spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return 0; + } spin_unlock_irqrestore(&ctlr->queue_lock, flags); usleep_range(10000, 11000); - spin_lock_irqsave(&ctlr->queue_lock, flags); - } - - if (!list_empty(&ctlr->queue) || ctlr->busy) - ret = -EBUSY; - else - ctlr->running = false; + } while (--limit); - spin_unlock_irqrestore(&ctlr->queue_lock, flags); - - return ret; + return -EBUSY; } static int spi_destroy_queue(struct spi_controller *ctlr) -- cgit v1.2.3 From 060bbd65dd4b4bcd519f6c470ec71fc58f9a6190 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Tue, 14 May 2024 14:26:30 -0500 Subject: spi: dt-bindings: Document the IBM FSI-attached SPI controller IBM Power processors have a SPI controller that can be accessed over FSI from a service processor. Document it. Signed-off-by: Eddie James Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240514192630.152747-1-eajames@linux.ibm.com Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/ibm,spi-fsi.yaml | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml diff --git a/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml new file mode 100644 index 000000000000..d7fec4c3a801 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/ibm,spi-fsi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IBM FSI-attached SPI Controller + +maintainers: + - Eddie James + +description: + A SPI controller found on IBM Power processors, accessed over FSI from a + service processor. This node will always be a child node of an ibm,fsi2spi + node. + +properties: + compatible: + enum: + - ibm,spi-fsi + + reg: + maxItems: 1 + +required: + - compatible + - reg + +allOf: + - $ref: spi-controller.yaml# + +unevaluatedProperties: false + +examples: + - | + fsi { + #address-cells = <1>; + #size-cells = <0>; + + spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + size = <0x80000>; + address-width = <24>; + pagesize = <256>; + spi-max-frequency = <1000000>; + }; + }; + }; -- cgit v1.2.3 From a2fca8f2e242b3cdfed2a15084e733348ef68509 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:09:57 +0300 Subject: spi: pxa2xx: Wrap pxa_ssp_request() to be device managed resource In the error path or remove path the reference counter in PXA SSP driver may be dropped before the other resources, that were allocated after bumbing the reference counter. This breaks reversed order of freeing and might have an undesired side effects. Prevent this from happening by wrapping pxa_ssp_request() to be device managed resource. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 50 +++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index efe76d0c21bb..820a3702447a 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1304,6 +1304,27 @@ pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum p return 0; } +static void pxa2xx_spi_ssp_release(void *ssp) +{ + pxa_ssp_free(ssp); +} + +static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev) +{ + struct ssp_device *ssp; + int status; + + ssp = pxa_ssp_request(pdev->id, pdev->name); + if (!ssp) + return ssp; + + status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp); + if (status) + return ERR_PTR(status); + + return ssp; +} + static struct pxa2xx_spi_controller * pxa2xx_spi_init_pdata(struct platform_device *pdev) { @@ -1331,11 +1352,11 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) type = (enum pxa_ssp_type)value; } else { - ssp = pxa_ssp_request(pdev->id, pdev->name); - if (ssp) { + ssp = pxa2xx_spi_ssp_request(pdev); + if (IS_ERR(ssp)) + return ERR_CAST(ssp); + if (ssp) type = ssp->type; - pxa_ssp_free(ssp); - } } /* Validate the SSP type correctness */ @@ -1420,7 +1441,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size); - ssp = pxa_ssp_request(pdev->id, pdev->name); + ssp = pxa2xx_spi_ssp_request(pdev); + if (IS_ERR(ssp)) + return PTR_ERR(ssp); if (!ssp) ssp = &platform_info->ssp; @@ -1431,11 +1454,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) controller = devm_spi_alloc_target(dev, sizeof(*drv_data)); else controller = devm_spi_alloc_host(dev, sizeof(*drv_data)); + if (!controller) + return dev_err_probe(dev, -ENOMEM, "cannot alloc spi_controller\n"); - if (!controller) { - status = dev_err_probe(dev, -ENOMEM, "cannot alloc spi_controller\n"); - goto out_error_controller_alloc; - } drv_data = spi_controller_get_devdata(controller); drv_data->controller = controller; drv_data->controller_info = platform_info; @@ -1486,10 +1507,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev), drv_data); - if (status < 0) { - dev_err_probe(dev, status, "cannot get IRQ %d\n", ssp->irq); - goto out_error_controller_alloc; - } + if (status < 0) + return dev_err_probe(dev, status, "cannot get IRQ %d\n", ssp->irq); /* Setup DMA if requested */ if (platform_info->enable_dma) { @@ -1619,8 +1638,6 @@ out_error_dma_irq_alloc: pxa2xx_spi_dma_release(drv_data); free_irq(ssp->irq, drv_data); -out_error_controller_alloc: - pxa_ssp_free(ssp); return status; } @@ -1646,9 +1663,6 @@ static void pxa2xx_spi_remove(struct platform_device *pdev) /* Release IRQ */ free_irq(ssp->irq, drv_data); - - /* Release SSP */ - pxa_ssp_free(ssp); } static int pxa2xx_spi_suspend(struct device *dev) -- cgit v1.2.3 From 8aa5062e26054b8c081d5bba930baac4faadd1b0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:09:58 +0300 Subject: spi: pxa2xx: Reorganize the SSP type retrieval The old Intel platforms, such as Intel Braswell, also provide the property of SSP type. Reorganize the pxa2xx_spi_init_pdata() to take that into account. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 820a3702447a..f4dc113768cd 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1331,19 +1331,21 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) struct pxa2xx_spi_controller *pdata; struct device *dev = &pdev->dev; struct device *parent = dev->parent; + const void *match = device_get_match_data(dev); enum pxa_ssp_type type = SSP_UNDEFINED; - struct ssp_device *ssp = NULL; - const void *match; + struct ssp_device *ssp; bool is_lpss_priv; u32 num_cs = 1; int status; - is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv"); - - match = device_get_match_data(dev); - if (match) - type = (uintptr_t)match; - else if (is_lpss_priv) { + ssp = pxa2xx_spi_ssp_request(pdev); + if (IS_ERR(ssp)) + return ERR_CAST(ssp); + if (ssp) { + type = ssp->type; + } else if (match) { + type = (enum pxa_ssp_type)(uintptr_t)match; + } else { u32 value; status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value); @@ -1351,12 +1353,6 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) return ERR_PTR(status); type = (enum pxa_ssp_type)value; - } else { - ssp = pxa2xx_spi_ssp_request(pdev); - if (IS_ERR(ssp)) - return ERR_CAST(ssp); - if (ssp) - type = ssp->type; } /* Validate the SSP type correctness */ @@ -1368,6 +1364,7 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) return ERR_PTR(-ENOMEM); /* Platforms with iDMA 64-bit */ + is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv"); if (is_lpss_priv) { pdata->tx_param = parent; pdata->rx_param = parent; -- cgit v1.2.3 From 7b0f2c1050643c4793e6eae0246a8de3b22c950a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:09:59 +0300 Subject: spi: pxa2xx: Remove no more needed driver data Since the ACPI enumerated devices provide a property with SSP type, there is no more necessity to bear the copy of them in the ID table. Drop the driver data in ACPI ID table. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-4-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f4dc113768cd..b62a613378e0 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1718,12 +1718,12 @@ static const struct dev_pm_ops pxa2xx_spi_pm_ops = { }; static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { - { "80860F0E", LPSS_BYT_SSP }, - { "8086228E", LPSS_BSW_SSP }, - { "INT33C0", LPSS_LPT_SSP }, - { "INT33C1", LPSS_LPT_SSP }, - { "INT3430", LPSS_LPT_SSP }, - { "INT3431", LPSS_LPT_SSP }, + { "80860F0E" }, + { "8086228E" }, + { "INT33C0" }, + { "INT33C1" }, + { "INT3430" }, + { "INT3431" }, {} }; MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); -- cgit v1.2.3 From c1b93986dfb2a31b0528fe929d574843801089f5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:10:00 +0300 Subject: spi: pxa2xx: Remove hard coded number of chip select pins Remove hard coded number of chip select pins for Intel Braswell. This comes via property. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-5-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index b62a613378e0..53815aab41aa 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -99,7 +99,6 @@ struct lpss_config { /* Chip select control */ unsigned cs_sel_shift; unsigned cs_sel_mask; - unsigned cs_num; /* Quirks */ unsigned cs_clk_stays_gated : 1; }; @@ -137,7 +136,6 @@ static const struct lpss_config lpss_platforms[] = { .tx_threshold_hi = 224, .cs_sel_shift = 2, .cs_sel_mask = 1 << 2, - .cs_num = 2, }, { /* LPSS_SPT_SSP */ .offset = 0x200, @@ -1594,8 +1592,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) tmp &= LPSS_CAPS_CS_EN_MASK; tmp >>= LPSS_CAPS_CS_EN_SHIFT; platform_info->num_chipselect = ffz(tmp); - } else if (config->cs_num) { - platform_info->num_chipselect = config->cs_num; } } controller->num_chipselect = platform_info->num_chipselect; -- cgit v1.2.3 From c65174fdb2f7fe83ee515966c08de9a990e722f9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:10:01 +0300 Subject: spi: pxa2xx: Utilise temporary variable for struct device We have a temporary variable to keep a pointer to struct device. Utilise it where it makes sense. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-6-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 53815aab41aa..19ee7739f4bd 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1606,13 +1606,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } } - pm_runtime_set_autosuspend_delay(&pdev->dev, 50); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); + pm_runtime_set_autosuspend_delay(dev, 50); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); /* Register with the SPI framework */ - platform_set_drvdata(pdev, drv_data); + dev_set_drvdata(dev, drv_data); status = spi_register_controller(controller); if (status) { dev_err_probe(dev, status, "problem registering SPI controller\n"); @@ -1622,7 +1622,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) return status; out_error_pm_runtime_enabled: - pm_runtime_disable(&pdev->dev); + pm_runtime_disable(dev); out_error_clock_enabled: clk_disable_unprepare(ssp->clk); @@ -1636,10 +1636,11 @@ out_error_dma_irq_alloc: static void pxa2xx_spi_remove(struct platform_device *pdev) { - struct driver_data *drv_data = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + struct driver_data *drv_data = dev_get_drvdata(dev); struct ssp_device *ssp = drv_data->ssp; - pm_runtime_get_sync(&pdev->dev); + pm_runtime_get_sync(dev); spi_unregister_controller(drv_data->controller); @@ -1651,8 +1652,8 @@ static void pxa2xx_spi_remove(struct platform_device *pdev) if (drv_data->controller_info->enable_dma) pxa2xx_spi_dma_release(drv_data); - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); /* Release IRQ */ free_irq(ssp->irq, drv_data); -- cgit v1.2.3 From 9b328f5f5c921ec83e1765075b82e6cc05e576b9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:10:02 +0300 Subject: spi: pxa2xx: Print DMA burst size only when DMA is enabled Print DMA burst size only when DMA is enabled to avoid making a false impression that DMA is enabled when it may be not. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-7-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 19ee7739f4bd..30a829b74a22 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1434,7 +1434,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) if (IS_ERR(platform_info)) return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n"); } - dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size); ssp = pxa2xx_spi_ssp_request(pdev); if (IS_ERR(ssp)) @@ -1516,6 +1515,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) controller->max_dma_len = MAX_DMA_LEN; controller->max_transfer_size = pxa2xx_spi_max_dma_transfer_size; + + dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size); } } -- cgit v1.2.3 From 560fb06df2fd250004a1cac079717dbe7f863ff2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:10:03 +0300 Subject: spi: pxa2xx: Remove duplicate check The mmio_base can't be NULL at this point. It's either checked in both pxa_ssp_probe() and pxa2xx_spi_init_ssp() or correctly provided by PCI core. Hence, remove duplicate check which is a dead code. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-8-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 30a829b74a22..9724d9455837 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1441,9 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) if (!ssp) ssp = &platform_info->ssp; - if (!ssp->mmio_base) - return dev_err_probe(dev, -ENODEV, "failed to get SSP\n"); - if (platform_info->is_target) controller = devm_spi_alloc_target(dev, sizeof(*drv_data)); else -- cgit v1.2.3 From 75bfdccaecf96189318b29100b880c416d89ed46 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 May 2024 18:10:04 +0300 Subject: spi: pxa2xx: Remove superflous check for Intel Atom SoCs pxa2xx_spi_fw_translate_cs() checks for the ACPI companion device presence along with the SSP type. But the SSP type is uniquely determines the case. Hence remove the superflous check. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240530151117.1130792-9-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 9724d9455837..3c03a8cd9ee6 100644 --- a/drivers/spi/spi-pxa2xx.