From e0ccf861b80698a5cc6f97c89bf8d5761f465fce Mon Sep 17 00:00:00 2001 From: Zhi-Jun You Date: Sun, 7 Jan 2024 14:41:20 +0000 Subject: mtd: spinand: winbond: add support for W25N04KV Add support for W25N04KV. W25N04KV has 8-bit on-die ECC. Signed-off-by: Zhi-Jun You Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240107144120.532-1-hujy652@gmail.com --- drivers/mtd/nand/spi/winbond.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 1a473021cca5..ba7c813b9542 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -15,6 +15,8 @@ #define WINBOND_CFG_BUF_READ BIT(3) +#define W25N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) + static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), @@ -118,6 +120,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, return -EBADMSG; case STATUS_ECC_HAS_BITFLIPS: + case W25N04KV_STATUS_ECC_5_8_BITFLIPS: /* * Let's try to retrieve the real maximum number of bitflips * in order to avoid forcing the wear-leveling layer to move @@ -214,6 +217,15 @@ static const struct spinand_info winbond_spinand_table[] = { &update_cache_variants), 0, SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N04KV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), + NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), }; static int winbond_spinand_init(struct spinand_device *spinand) -- cgit v1.2.3 From c7f0f920ddfd12999335eee44f488bcf773edfb4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 15 Jan 2024 15:12:46 +0100 Subject: mtd: rawnand: fsl_elbc: Let .probe retry if local bus is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If during probe fsl_lbc_ctrl_dev is NULL that might just be because the fsl_lbc driver didn't bind yet. So return -EPROBE_DEFER in this case to make the driver core retry probing later. Signed-off-by: Uwe Kleine-König Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240115141245.3415035-2-u.kleine-koenig@pengutronix.de --- drivers/mtd/nand/raw/fsl_elbc_nand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 1e3a80f06f33..df6a0d5c86bb 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -869,7 +869,8 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) struct mtd_info *mtd; if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) - return -ENODEV; + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "lbc_ctrl_dev missing\n"); + lbc = fsl_lbc_ctrl_dev->regs; dev = fsl_lbc_ctrl_dev->dev; -- cgit v1.2.3 From 8d55a90b2b401e6b5dd289ebbc04dfd9e72ed35f Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Wed, 10 Jan 2024 19:21:45 +0800 Subject: dt-bindings: mtd: avoid automatically select from mtd.yaml The mtd binding is always $ref'ed by other bindings, default selector should be from other binding files which ref'ed it. Now, "$nodename" in mtd.yaml turns into a "select" automatically such that a few binding check issues reported because it conflicts with sram devices(eg, qcom,imem.yaml, rules in folder sram/*) To avoid the automatically created "select" in mtd.yaml, adding: select: false Suggested-by: Bjorn Andersson Fixes: 7bdc671822e9 ("dt-bindings: mtd: physmap: Reuse the generic definitions") Signed-off-by: Zhenhua Huang Reviewed-by: Bjorn Andersson Acked-by: Rob Herring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1704885705-7486-1-git-send-email-quic_zhenhuah@quicinc.com --- Documentation/devicetree/bindings/mtd/mtd.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/mtd.yaml b/Documentation/devicetree/bindings/mtd/mtd.yaml index f322290ee516..ee442ecb11cd 100644 --- a/Documentation/devicetree/bindings/mtd/mtd.yaml +++ b/Documentation/devicetree/bindings/mtd/mtd.yaml @@ -10,6 +10,8 @@ maintainers: - Miquel Raynal - Richard Weinberger +select: false + properties: $nodename: pattern: "^(flash|.*sram|nand)(@.*)?$" -- cgit v1.2.3 From e8b7d11c7e4b88c4988f2c740e9303f39a8c2ec4 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Dec 2023 13:21:52 +0100 Subject: mtd: ssfdc: One function call less in ssfdcr_add_mtd() after error detection The kfree() function was called in one case by the ssfdcr_add_mtd() function during error handling even if the passed data structure member contained a null pointer. This issue was detected by using the Coccinelle software. Thus use another label. Signed-off-by: Markus Elfring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/56d92e42-db9e-4767-bcb1-9686bdf34a03@web.de --- drivers/mtd/ssfdc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 211f279a33a9..3ee8535d4515 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c @@ -332,7 +332,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) kmalloc_array(ssfdc->map_len, sizeof(ssfdc->logic_block_map[0]), GFP_KERNEL); if (!ssfdc->logic_block_map) - goto out_err; + goto out_free_ssfdc; memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * ssfdc->map_len); @@ -350,6 +350,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) out_err: kfree(ssfdc->logic_block_map); +out_free_ssfdc: kfree(ssfdc); } -- cgit v1.2.3 From 086cd7a6c50bb3206fc08e0a850daaabef03e810 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Dec 2023 15:17:58 +0100 Subject: mtd: ssfdc: Fix indentation in ssfdcr_add_mtd() Replace eight space characters by one tab. Signed-off-by: Markus Elfring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/4045abdd-fb88-4c1f-a947-cdb3d4e59aa6@web.de --- drivers/mtd/ssfdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 3ee8535d4515..e6de25087647 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c @@ -351,7 +351,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) out_err: kfree(ssfdc->logic_block_map); out_free_ssfdc: - kfree(ssfdc); + kfree(ssfdc); } static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev) -- cgit v1.2.3 From 0d9a4164ba4929bbc231eef438d4cba1caee9d25 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Dec 2023 15:30:06 +0100 Subject: mtd: ssfdc: Improve a size determination in ssfdcr_add_mtd() Replace the specification of a data structure by a pointer dereference as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/b7ee7d1b-49a2-41d8-9c8f-3674f1aecc43@web.de --- drivers/mtd/ssfdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index e6de25087647..46c01fa2ec46 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c @@ -295,7 +295,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) if (cis_sector == -1) return; - ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL); + ssfdc = kzalloc(sizeof(*ssfdc), GFP_KERNEL); if (!ssfdc) return; -- cgit v1.2.3 From 34a956739d295de6010cdaafeed698ccbba87ea4 Mon Sep 17 00:00:00 2001 From: Ezra Buehler Date: Thu, 25 Jan 2024 22:01:07 +0200 Subject: mtd: spinand: Add support for 5-byte IDs E.g. ESMT chips will return an identification code with a length of 5 bytes. In order to prevent ambiguity, flash chips would actually need to return IDs that are up to 17 or more bytes long due to JEDEC's continuation scheme. I understand that if a manufacturer ID is located in bank N of JEDEC's database (there are currently 16 banks), N - 1 continuation codes (7Fh) need to be added to the identification code (comprising of manufacturer ID and device ID). However, most flash chip manufacturers don't seem to implement this (correctly). Signed-off-by: Ezra Buehler Reviewed-by: Martin Kurbanov Tested-by: Martin Kurbanov Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240125200108.24374-2-ezra@easyb.ch --- include/linux/mtd/spinand.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index badb4c1ac079..5c19ead60499 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -169,7 +169,7 @@ struct spinand_op; struct spinand_device; -#define SPINAND_MAX_ID_LEN 4 +#define SPINAND_MAX_ID_LEN 5 /* * For erase, write and read operation, we got the following timings : * tBERS (erase) 1ms to 4ms -- cgit v1.2.3 From 4bd14b2fd8a83a2f5220ba4ef323f741e11bfdfd Mon Sep 17 00:00:00 2001 From: Ezra Buehler Date: Thu, 25 Jan 2024 22:01:08 +0200 Subject: mtd: spinand: esmt: Extend IDs to 5 bytes According to the datasheets, the ESMT chips in question will return a 5 byte long identification code where the last 3 bytes are the JEDEC continuation codes (7Fh). Although, I would have expected 4 continuation codes as Powerchip Semiconductor (C8h, corresponding to the parameter page data) is located in bank 5 of the JEDEC database. By matching the full 5 bytes we can avoid clashes with GigaDevice NAND flashes. This fix allows the MT7688-based GARDENA smart Gateway to boot again. Fixes: aa08bf187f32 ("mtd: spinand: esmt: add support for F50D2G41KA") Signed-off-by: Ezra Buehler Reviewed-by: Martin Kurbanov Tested-by: Martin Kurbanov Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240125200108.24374-3-ezra@easyb.ch --- drivers/mtd/nand/spi/esmt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/spi/esmt.c b/drivers/mtd/nand/spi/esmt.c index 31c439a557b1..4597a82de23a 100644 --- a/drivers/mtd/nand/spi/esmt.c +++ b/drivers/mtd/nand/spi/esmt.c @@ -104,7 +104,8 @@ static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = { static const struct spinand_info esmt_c8_spinand_table[] = { SPINAND_INFO("F50L1G41LB", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01, 0x7f, + 0x7f, 0x7f), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(1, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -113,7 +114,8 @@ static const struct spinand_info esmt_c8_spinand_table[] = { 0, SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), SPINAND_INFO("F50D1G41LB", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11), + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11, 0x7f, + 0x7f, 0x7f), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(1, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -122,7 +124,8 @@ static const struct spinand_info esmt_c8_spinand_table[] = { 0, SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), SPINAND_INFO("F50D2G41KA", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51), + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51, 0x7f, + 0x7f, 0x7f), NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -- cgit v1.2.3 From 18af7e357033f1a1cee50db2663ef982b4a2226e Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 5 Feb 2024 12:09:55 +0200 Subject: mtd: flashchip: explicitly include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While reviewing the hyperbus sfdp proposal the following problem was noticed: In file included from ./include/linux/mtd/gen_probe.h:10, from drivers/mtd/hyperbus/hyperbus-sfdp.c:6: ./include/linux/mtd/flashchip.h:77:9: error: unknown type name ‘wait_queue_head_t’ 77 | wait_queue_head_t wq; /* Wait on here when we're waiting for the chip | ^~~~~~~~~~~~~~~~~ It is good practice to directly include all headers used, it avoids implicit dependencies and spurious breakage if someone rearranges headers and causes the implicit include to vanish. Explicitly include in include/linux/mtd/flashchip. Signed-off-by: Tudor Ambarus Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240205100955.149755-1-tudor.ambarus@linaro.org --- include/linux/mtd/flashchip.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index c04f690871ca..9798c1a1d3b6 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -13,6 +13,7 @@ */ #include #include +#include typedef enum { FL_READY, -- cgit v1.2.3 From a956502aa844a20a794a47f76c0f760f593fc97a Mon Sep 17 00:00:00 2001 From: Josua Mayer Date: Mon, 19 Feb 2024 15:41:19 +0100 Subject: dt-bindings: mtd: spi-nor: add optional interrupts property Some spi flash memories have an interrupt signal which can be used for signalling on-chip events such as busy status or ecc errors to the host. Add binding for "interrupts" property so that boards wiring this signal may describe the connection. Signed-off-by: Josua Mayer Acked-by: Rob Herring Acked-by: Pratyush Yadav Acked-by: Michael Walle Link: https://lore.kernel.org/r/20240219-mtd-flash-interrupt-binding-v7-1-206e30a656fa@solid-run.com Signed-off-by: Tudor Ambarus --- Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml index 58f0cea160ef..6e3afb42926e 100644 --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml @@ -52,6 +52,9 @@ properties: minItems: 1 maxItems: 2 + interrupts: + maxItems: 1 + m25p,fast-read: type: boolean description: -- cgit v1.2.3 From 3884f03edd34887514a0865a80769cd5362d5c3b Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 8 Feb 2024 12:34:18 +0200 Subject: mtd: maps: physmap-core: fix flash size larger than 32-bit mtd-ram can potentially be larger than 4GB. get_bitmask_order() uses fls() that is not guaranteed to work with values larger than 32-bit. Specifically on aarch64 fls() returns 0 when all 32 LSB bits are clear. Use fls64() instead. Fixes: ba32ce95cbd987 ("mtd: maps: Merge gpio-addr-flash.c into physmap-core.c") Signed-off-by: Baruch Siach Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/9fbf3664ce00f8b07867f1011834015f21d162a5.1707388458.git.baruch@tkos.co.il --- drivers/mtd/maps/physmap-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 746a27d15d44..96eb2e782c38 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -518,7 +518,7 @@ static int physmap_flash_probe(struct platform_device *dev) if (!info->maps[i].phys) info->maps[i].phys = res->start; - info->win_order = get_bitmask_order(resource_size(res)) - 1; + info->win_order = fls64(resource_size(res)) - 1; info->maps[i].size = BIT(info->win_order + (info->gpios ? info->gpios->ndescs : 0)); -- cgit v1.2.3 From 8709aa3e9d7ed8aadf0ba193821c8a2b692092a1 Mon Sep 17 00:00:00 2001 From: Nayab Sayed Date: Thu, 8 Feb 2024 17:12:12 +0530 Subject: dt-bindings: mtd: update references from partition.txt to mtd.yaml Commit f902baa917b6 ("dt-bindings: mtd: Remove useless file about partitions") removed the file partition.txt. Hence, in this commit, the lines mentioning this file are updated to reference mtd.yaml, which now includes partition{,s}.yaml. Signed-off-by: Nayab Sayed Acked-by: Rob Herring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240208-partition-txt-v1-1-4398af3b7bb2@microchip.com --- Documentation/devicetree/bindings/mtd/davinci-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/flctl-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/gpio-control-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/gpmi-nand.yaml | 2 +- Documentation/devicetree/bindings/mtd/hisi504-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/orion-nand.txt | 2 +- Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/davinci-nand.txt b/Documentation/devicetree/bindings/mtd/davinci-nand.txt index edebeae1f5b3..eb8e2ff4dbd2 100644 --- a/Documentation/devicetree/bindings/mtd/davinci-nand.txt +++ b/Documentation/devicetree/bindings/mtd/davinci-nand.txt @@ -68,7 +68,7 @@ Deprecated properties: false. Nand device bindings may contain additional sub-nodes describing partitions of -the address space. See partition.txt for more detail. The NAND Flash timing +the address space. See mtd.yaml for more detail. The NAND Flash timing values must be programmed in the chip select’s node of AEMIF memory-controller (see Documentation/devicetree/bindings/memory-controllers/ davinci-aemif.txt). diff --git a/Documentation/devicetree/bindings/mtd/flctl-nand.txt b/Documentation/devicetree/bindings/mtd/flctl-nand.txt index 427f46dc60ad..51518399d737 100644 --- a/Documentation/devicetree/bindings/mtd/flctl-nand.txt +++ b/Documentation/devicetree/bindings/mtd/flctl-nand.txt @@ -15,7 +15,7 @@ The DMA fields are not used yet in the driver but are listed here for completing the bindings. The device tree may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. +address space. See mtd.yaml for more detail. Example: diff --git a/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt b/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt index 25f07c1f9e44..530c017e014e 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt @@ -22,7 +22,7 @@ Deprecated properties: (R/B# pins not connected). Each flash chip described may optionally contain additional sub-nodes -describing partitions of the address space. See partition.txt for more +describing partitions of the address space. See mtd.yaml for more detail. Examples: diff --git a/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt b/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt index 486a17d533d7..0edf55d47ea8 100644 --- a/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt @@ -26,7 +26,7 @@ Optional properties: read to ensure that the GPIO accesses have completed. The device tree may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. +address space. See mtd.yaml for more detail. Examples: diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml b/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml index ba086c34626d..021c0da0b072 100644 --- a/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml @@ -12,7 +12,7 @@ maintainers: description: | The GPMI nand controller provides an interface to control the NAND flash chips. The device tree may optionally contain sub-nodes - describing partitions of the address space. See partition.txt for + describing partitions of the address space. See mtd.yaml for more detail. properties: diff --git a/Documentation/devicetree/bindings/mtd/hisi504-nand.txt b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt index 8963983ae7cb..362203e7d50e 100644 --- a/Documentation/devicetree/bindings/mtd/hisi504-nand.txt +++ b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt @@ -22,7 +22,7 @@ The following ECC strength and step size are currently supported: - nand-ecc-strength = <16>, nand-ecc-step-size = <1024> Flash chip may optionally contain additional sub-nodes describing partitions of -the address space. See partition.txt for more detail. +the address space. See mtd.yaml for more detail. Example: diff --git a/Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt b/Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt index e737e5beb7bf..4a00ec2b2540 100644 --- a/Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt +++ b/Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt @@ -39,7 +39,7 @@ Optional children node properties: - wp-gpios: GPIO specifier for the write protect pin. Optional child node of NAND chip nodes: -Partitions: see partition.txt +Partitions: see mtd.yaml Example: nand-controller@70008000 { diff --git a/Documentation/devicetree/bindings/mtd/orion-nand.txt b/Documentation/devicetree/bindings/mtd/orion-nand.txt index 2d6ab660e603..b9997b1f13ac 100644 --- a/Documentation/devicetree/bindings/mtd/orion-nand.txt +++ b/Documentation/devicetree/bindings/mtd/orion-nand.txt @@ -13,7 +13,7 @@ Optional properties: registers in usecs The device tree may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. +address space. See mtd.yaml for more detail. Example: diff --git a/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt index 09815c40fc8a..635455350660 100644 --- a/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt +++ b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt @@ -19,7 +19,7 @@ Optional child properties: Each child device node may optionally contain a 'partitions' sub-node, which further contains sub-nodes describing the flash partition mapping. -See partition.txt for more detail. +See mtd.yaml for more detail. Example: -- cgit v1.2.3 From f1d00496a15bcdfe54bdb54cf1e7f207d6ad9b79 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 8 Feb 2024 21:21:13 +0100 Subject: mtd: lpc32xx: use typedef for dma_filter_fn Use existing typedef for dma_filter_fn to avoid duplicating type definition. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240208202113.630190-1-krzysztof.kozlowski@linaro.org --- include/linux/mtd/lpc32xx_mlc.h | 2 +- include/linux/mtd/lpc32xx_slc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/mtd/lpc32xx_mlc.h b/include/linux/mtd/lpc32xx_mlc.h index d168c628c0d5..35e971be0950 100644 --- a/include/linux/mtd/lpc32xx_mlc.h +++ b/include/linux/mtd/lpc32xx_mlc.h @@ -11,7 +11,7 @@ #include struct lpc32xx_mlc_platform_data { - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); + dma_filter_fn dma_filter; }; #endif /* __LINUX_MTD_LPC32XX_MLC_H */ diff --git a/include/linux/mtd/lpc32xx_slc.h b/include/linux/mtd/lpc32xx_slc.h index cf54a9f80460..a044b806566b 100644 --- a/include/linux/mtd/lpc32xx_slc.h +++ b/include/linux/mtd/lpc32xx_slc.h @@ -11,7 +11,7 @@ #include struct lpc32xx_slc_platform_data { - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); + dma_filter_fn dma_filter; }; #endif /* __LINUX_MTD_LPC32XX_SLC_H */ -- cgit v1.2.3 From 2416a2e7be9b27157f173268f5c7f769bd72a8dc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Feb 2024 14:01:06 +0000 Subject: mtd: chips: remove redundant assignment to variable timeo In two functions the variable timeo is being initialized with a value that is never read, it is being re-assigned later on. The initializations are redundant and can be removed. Cleans up clang scan build warning: warning: Value stored to 'timeo' during its initialization is never read [deadcode.DeadStores] Signed-off-by: Colin Ian King Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240215140106.2062858-1-colin.i.king@gmail.com --- drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index df589d9b4d70..9f2223d3e8e1 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2411,7 +2411,7 @@ static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) { struct cfi_private *cfi = map->fldrv_priv; - unsigned long timeo = jiffies + HZ; + unsigned long timeo; unsigned long int adr; DECLARE_WAITQUEUE(wait, current); int ret; @@ -2512,7 +2512,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; - unsigned long timeo = jiffies + HZ; + unsigned long timeo; DECLARE_WAITQUEUE(wait, current); int ret; int retry_cnt = 0; -- cgit v1.2.3 From 081064cc103929c8a0d7d5fd057110c739c62ee1 Mon Sep 17 00:00:00 2001 From: Marcel Hamer Date: Fri, 16 Feb 2024 16:50:22 +0100 Subject: mtd: fix minor comment typo for struct mtd_master Minor typo in the suspend description. Signed-off-by: Marcel Hamer Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240216155022.79371-1-marcel.hamer@windriver.com --- include/linux/mtd/mtd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 914a9f974baa..8d10d9d2e830 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -223,7 +223,7 @@ struct mtd_part { * @partitions_lock: lock protecting accesses to the partition list. Protects * not only the master partition list, but also all * sub-partitions. - * @suspended: et to 1 when the device is suspended, 0 otherwise + * @suspended: set to 1 when the device is suspended, 0 otherwise * * This struct is embedded in mtd_info and contains master-specific * properties/fields. The master is the root MTD device from the MTD partition -- cgit v1.2.3 From 77bf032528393d2dc9430b3cea1fee8d0762a86f Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Fri, 8 Dec 2023 22:47:03 +0000 Subject: mtd: Remove support for Carillo Ranch driver As far as anybody can tell, this product never shipped. If it did, it shipped in 2007 and nobody has access to one any more. Remove the mtd NOR driver. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20231208224703.1603264-2-willy@infradead.org --- drivers/mtd/maps/Kconfig | 7 -- drivers/mtd/maps/Makefile | 1 - drivers/mtd/maps/intel_vr_nor.c | 265 ---------------------------------------- 3 files changed, 273 deletions(-) delete mode 100644 drivers/mtd/maps/intel_vr_nor.c diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index e098ae937ce8..8a8b19874e23 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -341,13 +341,6 @@ config MTD_UCLINUX help Map driver to support image based filesystems for uClinux. -config MTD_INTEL_VR_NOR - tristate "NOR flash on Intel Vermilion Range Expansion Bus CS0" - depends on PCI - help - Map driver for a NOR flash bank located on the Expansion Bus of the - Intel Vermilion Range chipset. - config MTD_PLATRAM tristate "Map driver for platform device RAM (mtd-ram)" select MTD_RAM diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 094cfb244086..a9083c888e3b 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -40,6 +40,5 @@ obj-$(CONFIG_MTD_UCLINUX) += uclinux.o obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o -obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c deleted file mode 100644 index d67b845b0e89..000000000000 --- a/drivers/mtd/maps/intel_vr_nor.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * drivers/mtd/maps/intel_vr_nor.c - * - * An MTD map driver for a NOR flash bank on the Expansion Bus of the Intel - * Vermilion Range chipset. - * - * The Vermilion Range Expansion Bus supports four chip selects, each of which - * has 64MiB of address space. The 2nd BAR of the Expansion Bus PCI Device - * is a 256MiB memory region containing the address spaces for all four of the - * chip selects, with start addresses hardcoded on 64MiB boundaries. - * - * This map driver only supports NOR flash on chip select 0. The buswidth - * (either 8 bits or 16 bits) is determined by reading the Expansion Bus Timing - * and Control Register for Chip Select 0 (EXP_TIMING_CS0). This driver does - * not modify the value in the EXP_TIMING_CS0 register except to enable writing - * and disable boot acceleration. The timing parameters in the register are - * assumed to have been properly initialized by the BIOS. The reset default - * timing parameters are maximally conservative (slow), so access to the flash - * will be slower than it should be if the BIOS has not initialized the timing - * parameters. - * - * Author: Andy Lowe - * - * 2006 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "vr_nor" - -struct vr_nor_mtd { - void __iomem *csr_base; - struct map_info map; - struct mtd_info *info; - struct pci_dev *dev; -}; - -/* Expansion Bus Configuration and Status Registers are in BAR 0 */ -#define EXP_CSR_MBAR 0 -/* Expansion Bus Memory Window is BAR 1 */ -#define EXP_WIN_MBAR 1 -/* Maximum address space for Chip Select 0 is 64MiB */ -#define CS0_SIZE 0x04000000 -/* Chip Select 0 is at offset 0 in the Memory Window */ -#define CS0_START 0x0 -/* Chip Select 0 Timing Register is at offset 0 in CSR */ -#define EXP_TIMING_CS0 0x00 -#define TIMING_CS_EN (1 << 31) /* Chip Select Enable */ -#define TIMING_BOOT_ACCEL_DIS (1 << 8) /* Boot Acceleration Disable */ -#define TIMING_WR_EN (1 << 1) /* Write Enable */ -#define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ -#define TIMING_MASK 0x3FFF0000 - -static void vr_nor_destroy_partitions(struct vr_nor_mtd *p) -{ - mtd_device_unregister(p->info); -} - -static int vr_nor_init_partitions(struct vr_nor_mtd *p) -{ - /* register the flash bank */ - /* partition the flash bank */ - return mtd_device_register(p->info, NULL, 0); -} - -static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) -{ - map_destroy(p->info); -} - -static int vr_nor_mtd_setup(struct vr_nor_mtd *p) -{ - static const char * const probe_types[] = - { "cfi_probe", "jedec_probe", NULL }; - const char * const *type; - - for (type = probe_types; !p->info && *type; type++) - p->info = do_map_probe(*type, &p->map); - if (!p->info) - return -ENODEV; - - p->info->dev.parent = &p->dev->dev; - - return 0; -} - -static void vr_nor_destroy_maps(struct vr_nor_mtd *p) -{ - unsigned int exp_timing_cs0; - - /* write-protect the flash bank */ - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); - exp_timing_cs0 &= ~TIMING_WR_EN; - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); - - /* unmap the flash window */ - iounmap(p->map.virt); - - /* unmap the csr window */ - iounmap(p->csr_base); -} - -/* - * Initialize the map_info structure and map the flash. - * Returns 0 on success, nonzero otherwise. - */ -static int vr_nor_init_maps(struct vr_nor_mtd *p) -{ - unsigned long csr_phys, csr_len; - unsigned long win_phys, win_len; - unsigned int exp_timing_cs0; - int err; - - csr_phys = pci_resource_start(p->dev, EXP_CSR_MBAR); - csr_len = pci_resource_len(p->dev, EXP_CSR_MBAR); - win_phys = pci_resource_start(p->dev, EXP_WIN_MBAR); - win_len = pci_resource_len(p->dev, EXP_WIN_MBAR); - - if (!csr_phys || !csr_len || !win_phys || !win_len) - return -ENODEV; - - if (win_len < (CS0_START + CS0_SIZE)) - return -ENXIO; - - p->csr_base = ioremap(csr_phys, csr_len); - if (!p->csr_base) - return -ENOMEM; - - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); - if (!(exp_timing_cs0 & TIMING_CS_EN)) { - dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " - "is disabled.\n"); - err = -ENODEV; - goto release; - } - if ((exp_timing_cs0 & TIMING_MASK) == TIMING_MASK) { - dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " - "is configured for maximally slow access times.\n"); - } - p->map.name = DRV_NAME; - p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2; - p->map.phys = win_phys + CS0_START; - p->map.size = CS0_SIZE; - p->map.virt = ioremap(p->map.phys, p->map.size); - if (!p->map.virt) { - err = -ENOMEM; - goto release; - } - simple_map_init(&p->map); - - /* Enable writes to flash bank */ - exp_timing_cs0 |= TIMING_BOOT_ACCEL_DIS | TIMING_WR_EN; - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); - - return 0; - - release: - iounmap(p->csr_base); - return err; -} - -static const struct pci_device_id vr_nor_pci_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)}, - {0,} -}; - -static void vr_nor_pci_remove(struct pci_dev *dev) -{ - struct vr_nor_mtd *p = pci_get_drvdata(dev); - - vr_nor_destroy_partitions(p); - vr_nor_destroy_mtd_setup(p); - vr_nor_destroy_maps(p); - kfree(p); - pci_release_regions(dev); - pci_disable_device(dev); -} - -static int vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct vr_nor_mtd *p = NULL; - unsigned int exp_timing_cs0; - int err; - - err = pci_enable_device(dev); - if (err) - goto out; - - err = pci_request_regions(dev, DRV_NAME); - if (err) - goto disable_dev; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - err = -ENOMEM; - if (!p) - goto release; - - p->dev = dev; - - err = vr_nor_init_maps(p); - if (err) - goto release; - - err = vr_nor_mtd_setup(p); - if (err) - goto destroy_maps; - - err = vr_nor_init_partitions(p); - if (err) - goto destroy_mtd_setup; - - pci_set_drvdata(dev, p); - - return 0; - - destroy_mtd_setup: - map_destroy(p->info); - - destroy_maps: - /* write-protect the flash bank */ - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); - exp_timing_cs0 &= ~TIMING_WR_EN; - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); - - /* unmap the flash window */ - iounmap(p->map.virt); - - /* unmap the csr window */ - iounmap(p->csr_base); - - release: - kfree(p); - pci_release_regions(dev); - - disable_dev: - pci_disable_device(dev); - - out: - return err; -} - -static struct pci_driver vr_nor_pci_driver = { - .name = DRV_NAME, - .probe = vr_nor_pci_probe, - .remove = vr_nor_pci_remove, - .id_table = vr_nor_pci_ids, -}; - -module_pci_driver(vr_nor_pci_driver); - -MODULE_AUTHOR("Andy Lowe"); -MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, vr_nor_pci_ids); -- cgit v1.2.3 From 0e164238bb0752e341f01639438c35822d4488b2 Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Tue, 20 Feb 2024 17:34:06 +0900 Subject: mtd: spi-nor: core: rework struct spi_nor_erase_region Encoding bitmask flags into offset worsen the code readability. The erase type mask and flags should be stored in dedicated members. Also, erase_map.uniform_erase_type can be removed as it is redundant. Signed-off-by: Takahiro Kuwano Suggested-by: Michael Walle Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/8e5e9e4081ed9f16ea9dce30693304a4b54d19b1.1708404584.git.Takahiro.Kuwano@infineon.com [ta: remove spi_nor_region_end()] Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/core.c | 42 ++++++++++++++++-------------------------- drivers/mtd/spi-nor/core.h | 28 ++++++++++------------------ drivers/mtd/spi-nor/debugfs.c | 13 +++++++------ drivers/mtd/spi-nor/sfdp.c | 30 +++++++++++++----------------- 4 files changed, 46 insertions(+), 67 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 4129764fad8c..d526e555e7b3 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1158,7 +1158,7 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode) static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) { - return !!nor->params->erase_map.uniform_erase_type; + return !!nor->params->erase_map.uniform_region.erase_mask; } static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) @@ -1542,7 +1542,6 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, const struct spi_nor_erase_type *erase; u32 rem; int i; - u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; /* * Erase types are ordered by size, with the smallest erase type at @@ -1550,7 +1549,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { /* Does the erase region support the tested erase type? */ - if (!(erase_mask & BIT(i))) + if (!(region->erase_mask & BIT(i))) continue; erase = &map->erase_type[i]; @@ -1558,7 +1557,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, continue; /* Alignment is not mandatory for overlaid regions */ - if (region->offset & SNOR_OVERLAID_REGION && + if (region->flags & SNOR_OVERLAID_REGION && region->size <= len) return erase; @@ -1576,12 +1575,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region) { - return region->offset & SNOR_LAST_REGION; -} - -static u64 spi_nor_region_end(const struct spi_nor_erase_region *region) -{ - return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size; + return region->flags & SNOR_LAST_REGION; } /** @@ -1612,16 +1606,14 @@ static struct spi_nor_erase_region * spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) { struct spi_nor_erase_region *region = map->regions; - u64 region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - u64 region_end = region_start + region->size; + u64 region_end = region->offset + region->size; - while (addr < region_start || addr >= region_end) { + while (addr < region->offset || addr >= region_end) { region = spi_nor_region_next(region); if (!region) return ERR_PTR(-EINVAL); - region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - region_end = region_start + region->size; + region_end = region->offset + region->size; } return region; @@ -1649,7 +1641,7 @@ spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region, cmd->opcode = erase->opcode; cmd->count = 1; - if (region->offset & SNOR_OVERLAID_REGION) + if (region->flags & SNOR_OVERLAID_REGION) cmd->size = region->size; else cmd->size = erase->size; @@ -1699,7 +1691,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, if (IS_ERR(region)) return PTR_ERR(region); - region_end = spi_nor_region_end(region); + region_end = region->offset + region->size; while (len) { erase = spi_nor_find_best_erase_type(map, region, addr, len); @@ -1708,7 +1700,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, if (prev_erase != erase || erase->size != cmd->size || - region->offset & SNOR_OVERLAID_REGION) { + region->flags & SNOR_OVERLAID_REGION) { cmd = spi_nor_init_erase_cmd(region, erase); if (IS_ERR(cmd)) { ret = PTR_ERR(cmd); @@ -1727,7 +1719,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, region = spi_nor_region_next(region); if (!region) goto destroy_erase_cmd_list; - region_end = spi_nor_region_end(region); + region_end = region->offset + region->size; } prev_erase = erase; @@ -2468,12 +2460,11 @@ void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase) void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, u8 erase_mask, u64 flash_size) { - /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */ - map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) | - SNOR_LAST_REGION; + map->uniform_region.offset = 0; map->uniform_region.size = flash_size; + map->uniform_region.erase_mask = erase_mask; + map->uniform_region.flags = SNOR_LAST_REGION; map->regions = &map->uniform_region; - map->uniform_erase_type = erase_mask; } int spi_nor_post_bfpt_fixups(struct spi_nor *nor, @@ -2560,7 +2551,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map) { const struct spi_nor_erase_type *tested_erase, *erase = NULL; int i; - u8 uniform_erase_type = map->uniform_erase_type; + u8 uniform_erase_type = map->uniform_region.erase_mask; /* * Search for the biggest erase size, except for when compiled @@ -2599,8 +2590,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map) return NULL; /* Disable all other Sector Erase commands. */ - map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK; - map->uniform_erase_type |= BIT(erase - map->erase_type); + map->uniform_region.erase_mask = BIT(erase - map->erase_type); return erase; } diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index d36c0e072954..f68ae2fc4a1f 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -240,27 +240,25 @@ struct spi_nor_erase_command { /** * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region * @offset: the offset in the data array of erase region start. - * LSB bits are used as a bitmask encoding flags to - * determine if this region is overlaid, if this region is - * the last in the SPI NOR flash memory and to indicate - * all the supported erase commands inside this region. - * The erase types are sorted in ascending order with the - * smallest Erase Type size being at BIT(0). * @size: the size of the region in bytes. + * @erase_mask: bitmask to indicate all the supported erase commands + * inside this region. The erase types are sorted in + * ascending order with the smallest Erase Type size being + * at BIT(0). + * @flags: flags to determine if this region is overlaid, if this + * region is the last in the SPI NOR flash memory */ struct spi_nor_erase_region { u64 offset; u64 size; + u8 erase_mask; + u8 flags; }; #define SNOR_ERASE_TYPE_MAX 4 -#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0) -#define SNOR_LAST_REGION BIT(4) -#define SNOR_OVERLAID_REGION BIT(5) - -#define SNOR_ERASE_FLAGS_MAX 6 -#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0) +#define SNOR_LAST_REGION BIT(0) +#define SNOR_OVERLAID_REGION BIT(1) /** * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map @@ -273,17 +271,11 @@ struct spi_nor_erase_region { * The erase types are sorted in ascending order, with the * smallest Erase Type size being the first member in the * erase_type array. - * @uniform_erase_type: bitmask encoding erase types that can erase the - * entire memory. This member is completed at init by - * uniform and non-uniform SPI NOR flash memories if they - * support at least one erase type that can erase the - * entire memory. */ struct spi_nor_erase_map { struct spi_nor_erase_region *regions; struct spi_nor_erase_region uniform_region; struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX]; - u8 uniform_erase_type; }; /** diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 2dbda6b6938a..d20bbb531a88 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -147,16 +147,17 @@ static int spi_nor_params_show(struct seq_file *s, void *data) for (region = erase_map->regions; region; region = spi_nor_region_next(region)) { - u64 start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - u64 flags = region->offset & SNOR_ERASE_FLAGS_MASK; + u64 start = region->offset; u64 end = start + region->size - 1; + u8 erase_mask = region->erase_mask; + u8 flags = region->flags; seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", start, end, - flags & BIT(0) ? '0' : ' ', - flags & BIT(1) ? '1' : ' ', - flags & BIT(2) ? '2' : ' ', - flags & BIT(3) ? '3' : ' ', + erase_mask & BIT(0) ? '0' : ' ', + erase_mask & BIT(1) ? '1' : ' ', + erase_mask & BIT(2) ? '2' : ' ', + erase_mask & BIT(3) ? '3' : ' ', flags & SNOR_OVERLAID_REGION ? "overlaid" : ""); } diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 57713de32832..3cf1db6e4026 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -389,17 +389,14 @@ static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask) static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) { struct spi_nor_erase_region *region = map->regions; - u8 region_erase_mask, sorted_erase_mask; + u8 sorted_erase_mask; while (region) { - region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; - sorted_erase_mask = spi_nor_sort_erase_mask(map, - region_erase_mask); + region->erase_mask); /* Overwrite erase mask. */ - region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | - sorted_erase_mask; + region->erase_mask = sorted_erase_mask; region = spi_nor_region_next(region); } @@ -554,8 +551,6 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, * selecting the uniform erase. */ spi_nor_regions_sort_erase_types(map); - map->uniform_erase_type = map->uniform_region.offset & - SNOR_ERASE_TYPE_MASK; /* Stop here if not JESD216 rev A or later. */ if (bfpt_header->length == BFPT_DWORD_MAX_JESD216) @@ -808,12 +803,12 @@ out: static void spi_nor_region_mark_end(struct spi_nor_erase_region *region) { - region->offset |= SNOR_LAST_REGION; + region->flags |= SNOR_LAST_REGION; } static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) { - region->offset |= SNOR_OVERLAID_REGION; + region->flags |= SNOR_OVERLAID_REGION; } /** @@ -875,9 +870,10 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, /* Populate regions. */ for (i = 0; i < region_count; i++) { j = i + 1; /* index for the region dword */ + region[i].offset = offset; region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]); erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]); - region[i].offset = offset | erase_type; + region[i].erase_mask = erase_type; spi_nor_region_check_overlay(®ion[i], erase, erase_type); @@ -893,21 +889,21 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, */ regions_erase_type |= erase_type; - offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + - region[i].size; + offset = region[i].offset + region[i].size; } spi_nor_region_mark_end(®ion[i - 1]); - save_uniform_erase_type = map->uniform_erase_type; - map->uniform_erase_type = spi_nor_sort_erase_mask(map, - uniform_erase_type); + save_uniform_erase_type = map->uniform_region.erase_mask; + map->uniform_region.erase_mask = + spi_nor_sort_erase_mask(map, + uniform_erase_type); if (!regions_erase_type) { /* * Roll back to the previous uniform_erase_type mask, SMPT is * broken. */ - map->uniform_erase_type = save_uniform_erase_type; + map->uniform_region.erase_mask = save_uniform_erase_type; return -EINVAL; } -- cgit v1.2.3 From 9367043f1c02a1e4bc3ee50df2772c7c557ce617 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 9 Feb 2024 17:40:19 +0000 Subject: mtd: rawnand: remove redundant assignment to variable bbtblocks The variable bbtblocks is being assigned a value that is never read. The assignment is redundant and can be removed. Cleans up clang scan build warning: drivers/mtd/nand/raw/nand_bbt.c:579:3: warning: Value stored to 'bbtblocks' is never read [deadcode.DeadStores] Signed-off-by: Colin Ian King Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240209174019.3933233-1-colin.i.king@gmail.com --- drivers/mtd/nand/raw/nand_bbt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index e4664fa6fd9e..a8fba5f39f59 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -576,7 +576,6 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf, startblock &= bbtblocks - 1; } else { chips = 1; - bbtblocks = mtd->size >> this->bbt_erase_shift; } for (i = 0; i < chips; i++) { -- cgit v1.2.3 From ef6f463599e16924cdd02ce5056ab52879dc008c Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Sun, 11 Feb 2024 00:45:51 +0300 Subject: mtd: rawnand: meson: fix scrambling mode value in command macro Scrambling mode is enabled by value (1 << 19). NFC_CMD_SCRAMBLER_ENABLE is already (1 << 19), so there is no need to shift it again in CMDRWGEN macro. Signed-off-by: Arseniy Krasnov Cc: Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240210214551.441610-1-avkrasnov@salutedevices.com --- drivers/mtd/nand/raw/meson_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index cdb58aca59c0..2a96a87cf79c 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -63,7 +63,7 @@ #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ ( \ (cmd_dir) | \ - ((ran) << 19) | \ + (ran) | \ ((bch) << 14) | \ ((short_mode) << 13) | \ (((page_size) & 0x7f) << 6) | \ -- cgit v1.2.3 From e395036504c4e19d15ba64543a4c3beca373f7a9 Mon Sep 17 00:00:00 2001 From: Erick Archer Date: Sun, 11 Feb 2024 10:16:33 +0100 Subject: mtd: rawnand: Prefer struct_size over open coded arithmetic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an effort to get rid of all multiplications from allocation functions in order to prevent integer overflows [1]. As the "chip" variable is a pointer to "struct mtk_nfc_nand_chip" and this structure ends in a flexible array: struct mtk_nfc_nand_chip { [...] u8 sels[] __counted_by(nsels); }; the preferred way in the kernel is to use the struct_size() helper to do the arithmetic instead of the argument "size + count * size" in the devm_kzalloc() function. This way, the code is more readable and safer. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments [1] Link: https://github.com/KSPP/linux/issues/160 [2] Reviewed-by: Gustavo A. R. Silva Signed-off-by: Erick Archer Acked-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Matthias Brugger Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240211091633.4545-1-erick.archer@gmx.com --- drivers/mtd/nand/raw/mtk_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 60198e33d2d5..17477bb2d48f 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1356,7 +1356,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, return -EINVAL; } - chip = devm_kzalloc(dev, sizeof(*chip) + nsels * sizeof(u8), + chip = devm_kzalloc(dev, struct_size(chip, sels, nsels), GFP_KERNEL); if (!chip) return -ENOMEM; -- cgit v1.2.3 From 347b828882e6334690e7003ce5e2fe5f233dc508 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 13 Feb 2024 11:00:09 +0100 Subject: mtd: rawnand: lpc32xx_mlc: fix irq handler prototype clang-16 warns about mismatched function prototypes: drivers/mtd/nand/raw/lpc32xx_mlc.c:783:29: error: cast from 'irqreturn_t (*)(int, struct lpc32xx_nand_host *)' (aka 'enum irqreturn (*)(int, struct lpc32xx_nand_host *)') to 'irq_handler_t' (aka 'enum irqreturn (*)(int, void *)') converts to incompatible function type [-Werror,-Wcast-function-type-strict] Change the interrupt handler to the normal way of just passing a void* pointer and converting it inside the function.. Fixes: 70f7cb78ec53 ("mtd: add LPC32xx MLC NAND driver") Signed-off-by: Arnd Bergmann Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240213100146.455811-1-arnd@kernel.org --- drivers/mtd/nand/raw/lpc32xx_mlc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 488fd452611a..677fcb03f9be 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -303,8 +303,9 @@ static int lpc32xx_nand_device_ready(struct nand_chip *nand_chip) return 0; } -static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host) +static irqreturn_t lpc3xxx_nand_irq(int irq, void *data) { + struct lpc32xx_nand_host *host = data; uint8_t sr; /* Clear interrupt flag by reading status */ @@ -780,7 +781,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) goto release_dma_chan; } - if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq, + if (request_irq(host->irq, &lpc3xxx_nand_irq, IRQF_TRIGGER_HIGH, DRV_NAME, host)) { dev_err(&pdev->dev, "Error requesting NAND IRQ\n"); res = -ENXIO; -- cgit v1.2.3 From c1e04ab409aa0df2f554d7b318d82e8730ac4fa6 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Mon, 19 Feb 2024 15:05:03 +0100 Subject: dt-bindings: mtd: st,stm32: add MP25 support Add a compatible string to support MP25 SoC. FMC2 IP supports up to 4 chip select. On MP1 SoC, only 2 of them are available when on MP25 SoC, the 4 chip select are available. Signed-off-by: Christophe Kerello Reviewed-by: Krzysztof Kozlowski Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240219140505.85794-2-christophe.kerello@foss.st.com --- .../bindings/mtd/st,stm32-fmc2-nand.yaml | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml index e72cb5bacaf0..b8ef9ba88e92 100644 --- a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml @@ -14,10 +14,11 @@ properties: enum: - st,stm32mp15-fmc2 - st,stm32mp1-fmc2-nfc + - st,stm32mp25-fmc2-nfc reg: minItems: 6 - maxItems: 7 + maxItems: 12 interrupts: maxItems: 1 @@ -92,6 +93,28 @@ allOf: - description: Chip select 1 command - description: Chip select 1 address space + - if: + properties: + compatible: + contains: + const: st,stm32mp25-fmc2-nfc + then: + properties: + reg: + items: + - description: Chip select 0 data + - description: Chip select 0 command + - description: Chip select 0 address space + - description: Chip select 1 data + - description: Chip select 1 command + - description: Chip select 1 address space + - description: Chip select 2 data + - description: Chip select 2 command + - description: Chip select 2 address space + - description: Chip select 3 data + - description: Chip select 3 command + - description: Chip select 3 address space + required: - compatible - reg -- cgit v1.2.3 From a9ae475cc60d908dfd232d1c064fc34ec51d3228 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Mon, 19 Feb 2024 15:05:04 +0100 Subject: mtd: rawnand: stm32_fmc2: use dma_get_slave_caps to get DMA max burst Use dma_get_slave_caps API to get the max burst size of a DMA channel. For MP1 SoCs, MDMA is used and the max burst size is 128. For MP25 SoC, DMA3 is used and the max burst size is 64. Signed-off-by: Christophe Kerello Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240219140505.85794-3-christophe.kerello@foss.st.com --- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 88811139aaf5..a7db7b675514 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -264,6 +264,8 @@ struct stm32_fmc2_nfc { struct sg_table dma_ecc_sg; u8 *ecc_buf; int dma_ecc_len; + u32 tx_dma_max_burst; + u32 rx_dma_max_burst; struct completion complete; struct completion dma_data_complete; @@ -347,20 +349,26 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr) stm32_fmc2_nfc_setup(chip); stm32_fmc2_nfc_timings_init(chip); - if (nfc->dma_tx_ch && nfc->dma_rx_ch) { + if (nfc->dma_tx_ch) { memset(&dma_cfg, 0, sizeof(dma_cfg)); - dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; dma_cfg.dst_addr = nfc->data_phys_addr[nfc->cs_sel]; - dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_cfg.src_maxburst = 32; - dma_cfg.dst_maxburst = 32; + dma_cfg.dst_maxburst = nfc->tx_dma_max_burst / + dma_cfg.dst_addr_width; ret = dmaengine_slave_config(nfc->dma_tx_ch, &dma_cfg); if (ret) { dev_err(nfc->dev, "tx DMA engine slave config failed\n"); return ret; } + } + + if (nfc->dma_rx_ch) { + memset(&dma_cfg, 0, sizeof(dma_cfg)); + dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; + dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.src_maxburst = nfc->rx_dma_max_burst / + dma_cfg.src_addr_width; ret = dmaengine_slave_config(nfc->dma_rx_ch, &dma_cfg); if (ret) { @@ -1545,6 +1553,7 @@ static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr, static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) { + struct dma_slave_caps caps; int ret = 0; nfc->dma_tx_ch = dma_request_chan(nfc->dev, "tx"); @@ -1557,6 +1566,11 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) goto err_dma; } + ret = dma_get_slave_caps(nfc->dma_tx_ch, &caps); + if (ret) + return ret; + nfc->tx_dma_max_burst = caps.max_burst; + nfc->dma_rx_ch = dma_request_chan(nfc->dev, "rx"); if (IS_ERR(nfc->dma_rx_ch)) { ret = PTR_ERR(nfc->dma_rx_ch); @@ -1567,6 +1581,11 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) goto err_dma; } + ret = dma_get_slave_caps(nfc->dma_rx_ch, &caps); + if (ret) + return ret; + nfc->rx_dma_max_burst = caps.max_burst; + nfc->dma_ecc_ch = dma_request_chan(nfc->dev, "ecc"); if (IS_ERR(nfc->dma_ecc_ch)) { ret = PTR_ERR(nfc->dma_ecc_ch); -- cgit v1.2.3 From 0bfad3b3561d6f219b768d2a4265642ee9d31b1d Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Mon, 19 Feb 2024 15:05:05 +0100 Subject: mtd: rawnand: stm32_fmc2: add MP25 support FMC2 IP supports up to 4 chip select. On MP1 SoC, only 2 of them are available when on MP25 SoC, the 4 chip select are available. Let's use a platform data structure for parameters that will differ. Signed-off-by: Christophe Kerello Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240219140505.85794-4-christophe.kerello@foss.st.com --- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 54 ++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index a7db7b675514..264556939a00 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,7 @@ #define FMC2_MAX_SG 16 /* Max chip enable */ -#define FMC2_MAX_CE 2 +#define FMC2_MAX_CE 4 /* Max ECC buffer length */ #define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) @@ -243,6 +244,13 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) return container_of(chip, struct stm32_fmc2_nand, chip); } +struct stm32_fmc2_nfc; + +struct stm32_fmc2_nfc_data { + int max_ncs; + int (*set_cdev)(struct stm32_fmc2_nfc *nfc); +}; + struct stm32_fmc2_nfc { struct nand_controller base; struct stm32_fmc2_nand nand; @@ -256,6 +264,7 @@ struct stm32_fmc2_nfc { phys_addr_t data_phys_addr[FMC2_MAX_CE]; struct clk *clk; u8 irq_state; + const struct stm32_fmc2_nfc_data *data; struct dma_chan *dma_tx_ch; struct dma_chan *dma_rx_ch; @@ -1809,7 +1818,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, return ret; } - if (cs >= FMC2_MAX_CE) { + if (cs >= nfc->data->max_ncs) { dev_err(nfc->dev, "invalid reg value: %d\n", cs); return -EINVAL; } @@ -1915,9 +1924,17 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) nand_controller_init(&nfc->base); nfc->base.ops = &stm32_fmc2_nfc_controller_ops; - ret = stm32_fmc2_nfc_set_cdev(nfc); - if (ret) - return ret; + nfc->data = of_device_get_match_data(dev); + if (!nfc->data) + return -EINVAL; + + if (nfc->data->set_cdev) { + ret = nfc->data->set_cdev(nfc); + if (ret) + return ret; + } else { + nfc->cdev = dev->parent; + } ret = stm32_fmc2_nfc_parse_dt(nfc); if (ret) @@ -1936,7 +1953,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) if (nfc->dev == nfc->cdev) start_region = 1; - for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; + for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs; chip_cs++, mem_region += 3) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -2092,7 +2109,7 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) stm32_fmc2_nfc_wp_disable(nand); - for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { + for (chip_cs = 0; chip_cs < nfc->data->max_ncs; chip_cs++) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -2105,9 +2122,28 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend, stm32_fmc2_nfc_resume); +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = { + .max_ncs = 2, + .set_cdev = stm32_fmc2_nfc_set_cdev, +}; + +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = { + .max_ncs = 4, +}; + static const struct of_device_id stm32_fmc2_nfc_match[] = { - {.compatible = "st,stm32mp15-fmc2"}, - {.compatible = "st,stm32mp1-fmc2-nfc"}, + { + .compatible = "st,stm32mp15-fmc2", + .data = &stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp1-fmc2-nfc", + .data = &stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-nfc", + .data = &stm32_fmc2_nfc_mp25_data, + }, {} }; MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match); -- cgit v1.2.3 From d4bba1501f72e8af09f2cde3d327147de1b69f5d Mon Sep 17 00:00:00 2001 From: David Regan Date: Thu, 22 Feb 2024 19:47:46 -0800 Subject: mtd: rawnand: brcmnand: exec_op helper functions return type fixes Fix return types for exec_op reset and status helper functions. Reported-by: Dan Carpenter Closes: http://lists.infradead.org/pipermail/linux-mtd/2023-December/102423.html Fixes: 3c8260ce7663 ("mtd: rawnand: brcmnand: exec_op implementation") Signed-off-by: David Regan Signed-off-by: William Zhang Reviewed-by: William Zhang Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-2-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 8faca43ae1ff..b8e70fc64348 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -625,7 +625,7 @@ enum { /* Only for v7.2 */ #define ACC_CONTROL_ECC_EXT_SHIFT 13 -static u8 brcmnand_status(struct brcmnand_host *host); +static int brcmnand_status(struct brcmnand_host *host); static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl) { @@ -1690,7 +1690,7 @@ static int brcmnand_waitfunc(struct nand_chip *chip) INTFC_FLASH_STATUS; } -static u8 brcmnand_status(struct brcmnand_host *host) +static int brcmnand_status(struct brcmnand_host *host) { struct nand_chip *chip = &host->chip; struct mtd_info *mtd = nand_to_mtd(chip); @@ -1701,7 +1701,7 @@ static u8 brcmnand_status(struct brcmnand_host *host) return brcmnand_waitfunc(chip); } -static u8 brcmnand_reset(struct brcmnand_host *host) +static int brcmnand_reset(struct brcmnand_host *host) { struct nand_chip *chip = &host->chip; @@ -2433,7 +2433,11 @@ static int brcmnand_exec_op(struct nand_chip *chip, if (brcmnand_op_is_status(op)) { status = op->instrs[1].ctx.data.buf.in; - *status = brcmnand_status(host); + ret = brcmnand_status(host); + if (ret < 0) + return ret; + + *status = ret & 0xFF; return 0; } -- cgit v1.2.3 From 8e6070e5a39cb2202d66b78134f8b7681cdf3cd8 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:47 -0800 Subject: mtd: rawnand: brcmnand: fix style issues Fix various style issues. Signed-off-by: David Regan Signed-off-by: William Zhang Reviewed-by: William Zhang Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-3-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index b8e70fc64348..5f34e5a51d25 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2339,7 +2339,7 @@ static int brcmnand_write_oob_raw(struct nand_chip *chip, int page) } static int brcmnand_exec_instr(struct brcmnand_host *host, int i, - const struct nand_operation *op) + const struct nand_operation *op) { const struct nand_op_instr *instr = &op->instrs[i]; struct brcmnand_controller *ctrl = host->ctrl; @@ -2353,7 +2353,7 @@ static int brcmnand_exec_instr(struct brcmnand_host *host, int i, * (WAITRDY excepted). */ last_op = ((i == (op->ninstrs - 1)) && (instr->type != NAND_OP_WAITRDY_INSTR)) || - ((i == (op->ninstrs - 2)) && (op->instrs[i+1].type == NAND_OP_WAITRDY_INSTR)); + ((i == (op->ninstrs - 2)) && (op->instrs[i + 1].type == NAND_OP_WAITRDY_INSTR)); switch (instr->type) { case NAND_OP_CMD_INSTR: @@ -2398,10 +2398,10 @@ static int brcmnand_exec_instr(struct brcmnand_host *host, int i, static int brcmnand_op_is_status(const struct nand_operation *op) { - if ((op->ninstrs == 2) && - (op->instrs[0].type == NAND_OP_CMD_INSTR) && - (op->instrs[0].ctx.cmd.opcode == NAND_CMD_STATUS) && - (op->instrs[1].type == NAND_OP_DATA_IN_INSTR)) + if (op->ninstrs == 2 && + op->instrs[0].type == NAND_OP_CMD_INSTR && + op->instrs[0].ctx.cmd.opcode == NAND_CMD_STATUS && + op->instrs[1].type == NAND_OP_DATA_IN_INSTR) return 1; return 0; @@ -2409,10 +2409,10 @@ static int brcmnand_op_is_status(const struct nand_operation *op) static int brcmnand_op_is_reset(const struct nand_operation *op) { - if ((op->ninstrs == 2) && - (op->instrs[0].type == NAND_OP_CMD_INSTR) && - (op->instrs[0].ctx.cmd.opcode == NAND_CMD_RESET) && - (op->instrs[1].type == NAND_OP_WAITRDY_INSTR)) + if (op->ninstrs == 2 && + op->instrs[0].type == NAND_OP_CMD_INSTR && + op->instrs[0].ctx.cmd.opcode == NAND_CMD_RESET && + op->instrs[1].type == NAND_OP_WAITRDY_INSTR) return 1; return 0; @@ -2440,8 +2440,7 @@ static int brcmnand_exec_op(struct nand_chip *chip, *status = ret & 0xFF; return 0; - } - else if (brcmnand_op_is_reset(op)) { + } else if (brcmnand_op_is_reset(op)) { ret = brcmnand_reset(host); if (ret < 0) return ret; -- cgit v1.2.3 From 5542164bbe4bc33f88e42edec1ff3164d1ea4086 Mon Sep 17 00:00:00 2001 From: David Regan Date: Thu, 22 Feb 2024 19:47:48 -0800 Subject: mtd: rawnand: brcmnand: update log level messages Update log level messages so that more critical messages can be logged to console and help the troubleshooting with field devices. Signed-off-by: David Regan Signed-off-by: William Zhang Reviewed-by: William Zhang Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-4-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 5f34e5a51d25..f1f0de50b5f7 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1084,8 +1084,8 @@ static int bcmnand_ctrl_poll_status(struct brcmnand_host *host, if ((val & mask) == expected_val) return 0; - dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n", - expected_val, val & mask); + dev_err(ctrl->dev, "timeout on status poll (expected %x got %x)\n", + expected_val, val & mask); return -ETIMEDOUT; } @@ -2137,7 +2137,7 @@ try_dmaread: return err; } - dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", + dev_err(ctrl->dev, "uncorrectable error at 0x%llx\n", (unsigned long long)err_addr); mtd->ecc_stats.failed++; /* NAND layer expects zero on ECC errors */ -- cgit v1.2.3 From 59e8c2e011160551124df919c5bd8689760dcea1 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:49 -0800 Subject: dt-bindings: mtd: brcmnand: Updates for bcmbca SoCs Update the descriptions to reflect different families of broadband SoC and use the general name bcmbca for ARM based SoC. Remove the requirement of interrupts property to reflect the driver code and only require interrupt-names when interrupts property present. Also add myself to the list of maintainers. Signed-off-by: William Zhang Reviewed-by: David Regan Reviewed-by: Rob Herring Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-5-william.zhang@broadcom.com --- Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml index f57e96374e67..e54ca08a798a 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml @@ -9,6 +9,7 @@ title: Broadcom STB NAND Controller maintainers: - Brian Norris - Kamal Dasu + - William Zhang description: | The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND @@ -18,9 +19,10 @@ description: | supports basic PROGRAM and READ functions, among other features. This controller was originally designed for STB SoCs (BCM7xxx) but is now - available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and - iProc/Cygnus. Its history includes several similar (but not fully register - compatible) versions. + available on a variety of Broadcom SoCs, including some BCM3xxx, MIPS based + Broadband SoC (BCM63xx), ARM based Broadband SoC (BCMBCA) and iProc/Cygnus. + Its history includes several similar (but not fully register compatible) + versions. -- Additional SoC-specific NAND controller properties -- @@ -53,7 +55,7 @@ properties: - brcm,brcmnand-v7.2 - brcm,brcmnand-v7.3 - const: brcm,brcmnand - - description: BCM63138 SoC-specific NAND controller + - description: BCMBCA SoC-specific NAND controller items: - const: brcm,nand-bcm63138 - enum: @@ -177,6 +179,8 @@ allOf: - const: iproc-idm - const: iproc-ext - if: + required: + - interrupts properties: interrupts: minItems: 2 @@ -189,7 +193,6 @@ unevaluatedProperties: false required: - reg - reg-names - - interrupts examples: - | -- cgit v1.2.3 From 638eff86cf9ae36796d704bec24b83e3a4e348bd Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:50 -0800 Subject: dt-bindings: mtd: brcmnand: Add WP pin connection property Add brcm,wp-not-connected property to have an option for disabling this feature on broadband board design that does not connect WP pin. Signed-off-by: William Zhang Reviewed-by: Conor Dooley Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-6-william.zhang@broadcom.com --- Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml index e54ca08a798a..6a717bcedfd3 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml @@ -113,6 +113,13 @@ properties: earlier versions of this core that include WP type: boolean + brcm,wp-not-connected: + description: + Use this property when WP pin is not physically wired to the NAND chip. + Write protection feature cannot be used. By default, controller assumes + the pin is connected and feature is used. + $ref: /schemas/types.yaml#/definitions/flag + patternProperties: "^nand@[a-f0-9]$": type: object -- cgit v1.2.3 From 280962d413e873c7b2ff82b0767d04c60cbe0615 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:51 -0800 Subject: dt-bindings: mtd: brcmnand: Add ecc strap property Add brcm,nand-ecc-use-strap to get ecc and spare area size settings from board boot strap for broadband board designs because they do not specify ecc setting in dts but rather using the strap setting. Signed-off-by: William Zhang Reviewed-by: Conor Dooley Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-7-william.zhang@broadcom.com --- .../devicetree/bindings/mtd/brcm,brcmnand.yaml | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml index 6a717bcedfd3..064e840aeaa1 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml @@ -146,6 +146,15 @@ patternProperties: layout. $ref: /schemas/types.yaml#/definitions/uint32 + brcm,nand-ecc-use-strap: + description: + This property requires the host system to get the ECC related + settings from the SoC NAND boot strap configuration instead of + the generic NAND ECC settings. This is a common hardware design + on BCMBCA based boards. This strap ECC option and generic NAND + ECC option can not be specified at the same time. + $ref: /schemas/types.yaml#/definitions/flag + unevaluatedProperties: false allOf: @@ -195,6 +204,21 @@ allOf: required: - interrupt-names + - if: + patternProperties: + "^nand@[a-f0-9]$": + required: + - brcm,nand-ecc-use-strap + then: + patternProperties: + "^nand@[a-f0-9]$": + properties: + nand-ecc-strength: false + nand-ecc-step-size: false + nand-ecc-maximize: false + nand-ecc-algo: false + brcm,nand-oob-sector-size: false + unevaluatedProperties: false required: -- cgit v1.2.3 From df6e36edac23f096fae45d0a8fe2efcf0e77aebe Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Tue, 20 Feb 2024 17:34:07 +0900 Subject: mtd: spi-nor: core: get rid of SNOR_LAST_REGION flag Introduce n_regions in spi_nor_erase_map structure and remove SNOR_LAST_REGION flag. Loop logics that depend on the flag are also reworked to use n_regions as loop condition. Signed-off-by: Takahiro Kuwano Suggested-by: Tudor Ambarus Suggested-by: Michael Walle Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/eded84294bd81e966d6f423e578fc2cfb9a4a5b6.1708404584.git.Takahiro.Kuwano@infineon.com [ta: update spi_nor_init_erase_cmd_list() and break the for loop sooner.] Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/core.c | 102 ++++++++++-------------------------------- drivers/mtd/spi-nor/core.h | 10 ++--- drivers/mtd/spi-nor/debugfs.c | 16 +++---- drivers/mtd/spi-nor/sfdp.c | 18 +++----- 4 files changed, 41 insertions(+), 105 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index d526e555e7b3..8dcfb8649f01 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1573,52 +1573,6 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, return NULL; } -static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region) -{ - return region->flags & SNOR_LAST_REGION; -} - -/** - * spi_nor_region_next() - get the next spi nor region - * @region: pointer to a structure that describes a SPI NOR erase region - * - * Return: the next spi nor region or NULL if last region. - */ -struct spi_nor_erase_region * -spi_nor_region_next(struct spi_nor_erase_region *region) -{ - if (spi_nor_region_is_last(region)) - return NULL; - region++; - return region; -} - -/** - * spi_nor_find_erase_region() - find the region of the serial flash memory in - * which the offset fits - * @map: the erase map of the SPI NOR - * @addr: offset in the serial flash memory - * - * Return: a pointer to the spi_nor_erase_region struct, ERR_PTR(-errno) - * otherwise. - */ -static struct spi_nor_erase_region * -spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) -{ - struct spi_nor_erase_region *region = map->regions; - u64 region_end = region->offset + region->size; - - while (addr < region->offset || addr >= region_end) { - region = spi_nor_region_next(region); - if (!region) - return ERR_PTR(-EINVAL); - - region_end = region->offset + region->size; - } - - return region; -} - /** * spi_nor_init_erase_cmd() - initialize an erase command * @region: pointer to a structure that describes a SPI NOR erase region @@ -1685,44 +1639,36 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, struct spi_nor_erase_region *region; struct spi_nor_erase_command *cmd = NULL; u64 region_end; + unsigned int i; int ret = -EINVAL; - region = spi_nor_find_erase_region(map, addr); - if (IS_ERR(region)) - return PTR_ERR(region); - - region_end = region->offset + region->size; + for (i = 0; i < map->n_regions && len; i++) { + region = &map->regions[i]; + region_end = region->offset + region->size; - while (len) { - erase = spi_nor_find_best_erase_type(map, region, addr, len); - if (!erase) - goto destroy_erase_cmd_list; - - if (prev_erase != erase || - erase->size != cmd->size || - region->flags & SNOR_OVERLAID_REGION) { - cmd = spi_nor_init_erase_cmd(region, erase); - if (IS_ERR(cmd)) { - ret = PTR_ERR(cmd); + while (len && addr >= region->offset && addr < region_end) { + erase = spi_nor_find_best_erase_type(map, region, addr, + len); + if (!erase) goto destroy_erase_cmd_list; - } - - list_add_tail(&cmd->list, erase_list); - } else { - cmd->count++; - } - addr += cmd->size; - len -= cmd->size; + if (prev_erase != erase || erase->size != cmd->size || + region->flags & SNOR_OVERLAID_REGION) { + cmd = spi_nor_init_erase_cmd(region, erase); + if (IS_ERR(cmd)) { + ret = PTR_ERR(cmd); + goto destroy_erase_cmd_list; + } + + list_add_tail(&cmd->list, erase_list); + } else { + cmd->count++; + } - if (len && addr >= region_end) { - region = spi_nor_region_next(region); - if (!region) - goto destroy_erase_cmd_list; - region_end = region->offset + region->size; + len -= cmd->size; + addr += cmd->size; + prev_erase = erase; } - - prev_erase = erase; } return 0; @@ -2463,8 +2409,8 @@ void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, map->uniform_region.offset = 0; map->uniform_region.size = flash_size; map->uniform_region.erase_mask = erase_mask; - map->uniform_region.flags = SNOR_LAST_REGION; map->regions = &map->uniform_region; + map->n_regions = 1; } int spi_nor_post_bfpt_fixups(struct spi_nor *nor, diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index f68ae2fc4a1f..38be40a4647b 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -245,8 +245,7 @@ struct spi_nor_erase_command { * inside this region. The erase types are sorted in * ascending order with the smallest Erase Type size being * at BIT(0). - * @flags: flags to determine if this region is overlaid, if this - * region is the last in the SPI NOR flash memory + * @flags: flags to determine if this region is overlaid. */ struct spi_nor_erase_region { u64 offset; @@ -257,8 +256,7 @@ struct spi_nor_erase_region { #define SNOR_ERASE_TYPE_MAX 4 -#define SNOR_LAST_REGION BIT(0) -#define SNOR_OVERLAID_REGION BIT(1) +#define SNOR_OVERLAID_REGION BIT(0) /** * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map @@ -271,11 +269,13 @@ struct spi_nor_erase_region { * The erase types are sorted in ascending order, with the * smallest Erase Type size being the first member in the * erase_type array. + * @n_regions: number of erase regions. */ struct spi_nor_erase_map { struct spi_nor_erase_region *regions; struct spi_nor_erase_region uniform_region; struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX]; + unsigned int n_regions; }; /** @@ -667,8 +667,6 @@ void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode, void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size, u8 opcode); void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase); -struct spi_nor_erase_region * -spi_nor_region_next(struct spi_nor_erase_region *region); void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, u8 erase_mask, u64 flash_size); diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index d20bbb531a88..db050a1f1f37 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -78,10 +78,10 @@ static int spi_nor_params_show(struct seq_file *s, void *data) struct spi_nor *nor = s->private; struct spi_nor_flash_parameter *params = nor->params; struct spi_nor_erase_map *erase_map = ¶ms->erase_map; - struct spi_nor_erase_region *region; + struct spi_nor_erase_region *region = erase_map->regions; const struct flash_info *info = nor->info; char buf[16], *str; - int i; + unsigned int i; seq_printf(s, "name\t\t%s\n", info->name); seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); @@ -144,13 +144,11 @@ static int spi_nor_params_show(struct seq_file *s, void *data) seq_puts(s, "\nsector map\n"); seq_puts(s, " region (in hex) | erase mask | flags\n"); seq_puts(s, " ------------------+------------+----------\n"); - for (region = erase_map->regions; - region; - region = spi_nor_region_next(region)) { - u64 start = region->offset; - u64 end = start + region->size - 1; - u8 erase_mask = region->erase_mask; - u8 flags = region->flags; + for (i = 0; i < erase_map->n_regions; i++) { + u64 start = region[i].offset; + u64 end = start + region[i].size - 1; + u8 erase_mask = region[i].erase_mask; + u8 flags = region[i].flags; seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", start, end, diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 3cf1db6e4026..8d83580207d5 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -390,15 +390,14 @@ static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) { struct spi_nor_erase_region *region = map->regions; u8 sorted_erase_mask; + unsigned int i; - while (region) { - sorted_erase_mask = spi_nor_sort_erase_mask(map, - region->erase_mask); + for (i = 0; i < map->n_regions; i++) { + sorted_erase_mask = + spi_nor_sort_erase_mask(map, region[i].erase_mask); /* Overwrite erase mask. */ - region->erase_mask = sorted_erase_mask; - - region = spi_nor_region_next(region); + region[i].erase_mask = sorted_erase_mask; } } @@ -801,11 +800,6 @@ out: return ret; } -static void spi_nor_region_mark_end(struct spi_nor_erase_region *region) -{ - region->flags |= SNOR_LAST_REGION; -} - static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) { region->flags |= SNOR_OVERLAID_REGION; @@ -863,6 +857,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, if (!region) return -ENOMEM; map->regions = region; + map->n_regions = region_count; uniform_erase_type = 0xff; regions_erase_type = 0; @@ -891,7 +886,6 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, offset = region[i].offset + region[i].size; } - spi_nor_region_mark_end(®ion[i - 1]); save_uniform_erase_type = map->uniform_region.erase_mask; map->uniform_region.erase_mask = -- cgit v1.2.3 From 2865ed0e2c718387457b30a293fe46333694168f Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Tue, 20 Feb 2024 17:34:08 +0900 Subject: mtd: spi-nor: core: get rid of SNOR_OVERLAID_REGION flag Only SNOR_OVERLAID_REGION is defined for flags in the spi_nor_erase_region structure. It can be replaced by a boolean parameter. Signed-off-by: Takahiro Kuwano Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/076416d5dc8328dec72d31db12b9bec96bf0ac66.1708404584.git.Takahiro.Kuwano@infineon.com Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/core.c | 7 +++---- drivers/mtd/spi-nor/core.h | 6 ++---- drivers/mtd/spi-nor/debugfs.c | 5 ++--- drivers/mtd/spi-nor/sfdp.c | 7 +------ 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 8dcfb8649f01..898472538dae 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1557,8 +1557,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, continue; /* Alignment is not mandatory for overlaid regions */ - if (region->flags & SNOR_OVERLAID_REGION && - region->size <= len) + if (region->overlaid && region->size <= len) return erase; /* Don't erase more than what the user has asked for. */ @@ -1595,7 +1594,7 @@ spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region, cmd->opcode = erase->opcode; cmd->count = 1; - if (region->flags & SNOR_OVERLAID_REGION) + if (region->overlaid) cmd->size = region->size; else cmd->size = erase->size; @@ -1653,7 +1652,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, goto destroy_erase_cmd_list; if (prev_erase != erase || erase->size != cmd->size || - region->flags & SNOR_OVERLAID_REGION) { + region->overlaid) { cmd = spi_nor_init_erase_cmd(region, erase); if (IS_ERR(cmd)) { ret = PTR_ERR(cmd); diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 38be40a4647b..442786685515 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -245,19 +245,17 @@ struct spi_nor_erase_command { * inside this region. The erase types are sorted in * ascending order with the smallest Erase Type size being * at BIT(0). - * @flags: flags to determine if this region is overlaid. + * @overlaid: determine if this region is overlaid. */ struct spi_nor_erase_region { u64 offset; u64 size; u8 erase_mask; - u8 flags; + bool overlaid; }; #define SNOR_ERASE_TYPE_MAX 4 -#define SNOR_OVERLAID_REGION BIT(0) - /** * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map * @regions: array of erase regions. The regions are consecutive in diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index db050a1f1f37..fa6956144d2e 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -142,13 +142,12 @@ static int spi_nor_params_show(struct seq_file *s, void *data) } seq_puts(s, "\nsector map\n"); - seq_puts(s, " region (in hex) | erase mask | flags\n"); + seq_puts(s, " region (in hex) | erase mask | overlaid\n"); seq_puts(s, " ------------------+------------+----------\n"); for (i = 0; i < erase_map->n_regions; i++) { u64 start = region[i].offset; u64 end = start + region[i].size - 1; u8 erase_mask = region[i].erase_mask; - u8 flags = region[i].flags; seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", start, end, @@ -156,7 +155,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data) erase_mask & BIT(1) ? '1' : ' ', erase_mask & BIT(2) ? '2' : ' ', erase_mask & BIT(3) ? '3' : ' ', - flags & SNOR_OVERLAID_REGION ? "overlaid" : ""); + region[i].overlaid ? "yes" : "no"); } return 0; diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 8d83580207d5..5b1117265bd2 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -800,11 +800,6 @@ out: return ret; } -static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) -{ - region->flags |= SNOR_OVERLAID_REGION; -} - /** * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid * @region: pointer to a structure that describes a SPI NOR erase region @@ -822,7 +817,7 @@ spi_nor_region_check_overlay(struct spi_nor_erase_region *region, if (!(erase[i].size && erase_type & BIT(erase[i].idx))) continue; if (region->size & erase[i].size_mask) { - spi_nor_region_mark_overlay(region); + region->overlaid = true; return; } } -- cgit v1.2.3 From 6a9eda34418fc4dc05c2a7d6741c475e287d418c Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Tue, 20 Feb 2024 17:34:09 +0900 Subject: mtd: spi-nor: core: set mtd->eraseregions for non-uniform erase map Some of Infineon SPI NOR flash devices support hybrid sector layout that overlays 4KB sectors on a 256KB sector and SPI NOR framework recognizes that by parsing SMPT and construct params->erase_map. The hybrid sector layout is similar to CFI flash devices that have small sectors on top and/or bottom address. In case of CFI flash devices, the erase map information is parsed through CFI table and populated into mtd->eraseregions so that users can create MTD partitions that aligned with small sector boundaries. This patch provides the same capability to SPI NOR flash devices that have non-uniform erase map. Signed-off-by: Takahiro Kuwano Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/35d0962986e493b06c13bdf7ada8130a9966dc02.1708404584.git.Takahiro.Kuwano@infineon.com Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/core.c | 58 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 898472538dae..65b32ea59afc 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -3369,7 +3369,54 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, return info; } -static void spi_nor_set_mtd_info(struct spi_nor *nor) +static u32 +spi_nor_get_region_erasesize(const struct spi_nor_erase_region *region, + const struct spi_nor_erase_type *erase_type) +{ + u8 i; + + if (region->overlaid) + return region->size; + + for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { + if (region->erase_mask & BIT(i)) + return erase_type[i].size; + } + + return 0; +} + +static int spi_nor_set_mtd_eraseregions(struct spi_nor *nor) +{ + const struct spi_nor_erase_map *map = &nor->params->erase_map; + const struct spi_nor_erase_region *region = map->regions; + struct mtd_erase_region_info *mtd_region; + struct mtd_info *mtd = &nor->mtd; + u32 erasesize, i; + + mtd_region = devm_kcalloc(nor->dev, map->n_regions, sizeof(*mtd_region), + GFP_KERNEL); + if (!mtd_region) + return -ENOMEM; + + for (i = 0; i < map->n_regions; i++) { + erasesize = spi_nor_get_region_erasesize(®ion[i], + map->erase_type); + if (!erasesize) + return -EINVAL; + + mtd_region[i].erasesize = erasesize; + mtd_region[i].numblocks = div64_ul(region[i].size, erasesize); + mtd_region[i].offset = region[i].offset; + } + + mtd->numeraseregions = map->n_regions; + mtd->eraseregions = mtd_region; + + return 0; +} + +static int spi_nor_set_mtd_info(struct spi_nor *nor) { struct mtd_info *mtd = &nor->mtd; struct device *dev = nor->dev; @@ -3400,6 +3447,11 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor) mtd->_resume = spi_nor_resume; mtd->_get_device = spi_nor_get_device; mtd->_put_device = spi_nor_put_device; + + if (!spi_nor_has_uniform_erase(nor)) + return spi_nor_set_mtd_eraseregions(nor); + + return 0; } static int spi_nor_hw_reset(struct spi_nor *nor) @@ -3490,7 +3542,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, return ret; /* No mtd_info fields should be used up to this point. */ - spi_nor_set_mtd_info(nor); + ret = spi_nor_set_mtd_info(nor); + if (ret) + return ret; dev_dbg(dev, "Manufacturer and device ID: %*phN\n", SPI_NOR_MAX_ID_LEN, nor->id); -- cgit v1.2.3 From 2842dc9bc1a53893eec62ec9e49beb3b501702d0 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 4 Mar 2024 14:01:03 +0500 Subject: mtd: spi-nor: core: correct type of i The i should be signed to find out the end of the loop. Otherwise, i >= 0 is always true and loop becomes infinite. Make its type to be int. Fixes: 6a9eda34418f ("mtd: spi-nor: core: set mtd->eraseregions for non-uniform erase map") Signed-off-by: Muhammad Usama Anjum Reviewed-by: Tudor Ambarus Reviewed-by: Michael Walle Reviewed-by: Dan Carpenter Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240304090103.818092-1-usama.anjum@collabora.com --- drivers/mtd/spi-nor/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 65b32ea59afc..3e1f1913536b 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -3373,7 +3373,7 @@ static u32 spi_nor_get_region_erasesize(const struct spi_nor_erase_region *region, const struct spi_nor_erase_type *erase_type) { - u8 i; + int i; if (region->overlaid) return region->size; -- cgit v1.2.3 From d42d8e82eb3bd0030d1f8c1c322c33767ac663ae Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:52 -0800 Subject: ARM: dts: broadcom: bcmbca: Add NAND controller node Add support for Broadcom STB NAND controller in BCMBCA ARMv7 chip dts files. Signed-off-by: William Zhang Reviewed-by: David Regan Signed-off-by: Miquel Raynal Acked-by: Florian Fainelli Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-8-william.zhang@broadcom.com --- arch/arm/boot/dts/broadcom/bcm47622.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm63138.dtsi | 7 ++++++- arch/arm/boot/dts/broadcom/bcm63148.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm63178.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm6756.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm6846.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm6855.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm6878.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/broadcom/bcm947622.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm963138.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm963138dvt.dts | 14 +++++++------- arch/arm/boot/dts/broadcom/bcm963148.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm963178.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm96756.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm96846.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm96855.dts | 10 ++++++++++ arch/arm/boot/dts/broadcom/bcm96878.dts | 10 ++++++++++ 17 files changed, 191 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/broadcom/bcm47622.dtsi b/arch/arm/boot/dts/broadcom/bcm47622.dtsi index 7cd38de118c3..485863f9c420 100644 --- a/arch/arm/boot/dts/broadcom/bcm47622.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm47622.dtsi @@ -138,6 +138,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm/boot/dts/broadcom/bcm63138.dtsi b/arch/arm/boot/dts/broadcom/bcm63138.dtsi index 4ef02283612b..e74ba6bf370d 100644 --- a/arch/arm/boot/dts/broadcom/bcm63138.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm63138.dtsi @@ -229,7 +229,12 @@ reg-names = "nand", "nand-int-base"; status = "disabled"; interrupts = ; - interrupt-names = "nand"; + interrupt-names = "nand_ctlrdy"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; }; serial@4400 { diff --git a/arch/arm/boot/dts/broadcom/bcm63148.dtsi b/arch/arm/boot/dts/broadcom/bcm63148.dtsi index 24431de1810e..53703827ee3f 100644 --- a/arch/arm/boot/dts/broadcom/bcm63148.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm63148.dtsi @@ -119,5 +119,19 @@ num-cs = <8>; status = "disabled"; }; + + nand_controller: nand-controller@2000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x2000 0x600>, <0xf0 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; }; }; diff --git a/arch/arm/boot/dts/broadcom/bcm63178.dtsi b/arch/arm/boot/dts/broadcom/bcm63178.dtsi index 3f9aed96babf..6d8d33498983 100644 --- a/arch/arm/boot/dts/broadcom/bcm63178.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm63178.dtsi @@ -129,6 +129,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm/boot/dts/broadcom/bcm6756.dtsi b/arch/arm/boot/dts/broadcom/bcm6756.dtsi index 1d8d957d65dd..6433f8fa5eff 100644 --- a/arch/arm/boot/dts/broadcom/bcm6756.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6756.dtsi @@ -139,6 +139,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm/boot/dts/broadcom/bcm6846.dtsi b/arch/arm/boot/dts/broadcom/bcm6846.dtsi index cf92cf8c4693..ee361cb00b7c 100644 --- a/arch/arm/boot/dts/broadcom/bcm6846.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6846.dtsi @@ -119,5 +119,19 @@ num-cs = <8>; status = "disabled"; }; + + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; }; }; diff --git a/arch/arm/boot/dts/broadcom/bcm6855.dtsi b/arch/arm/boot/dts/broadcom/bcm6855.dtsi index 52d6bc89f9f8..52915ec6f339 100644 --- a/arch/arm/boot/dts/broadcom/bcm6855.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6855.dtsi @@ -129,6 +129,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm/boot/dts/broadcom/bcm6878.dtsi b/arch/arm/boot/dts/broadcom/bcm6878.dtsi index 2c5d706bac7e..70cf23a65fdb 100644 --- a/arch/arm/boot/dts/broadcom/bcm6878.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6878.dtsi @@ -120,6 +120,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm/boot/dts/broadcom/bcm947622.dts b/arch/arm/boot/dts/broadcom/bcm947622.dts index 93b8ce22678d..6241485408d3 100644 --- a/arch/arm/boot/dts/broadcom/bcm947622.dts +++ b/arch/arm/boot/dts/broadcom/bcm947622.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm963138.dts b/arch/arm/boot/dts/broadcom/bcm963138.dts index 1b405c249213..7fd87e05ec20 100644 --- a/arch/arm/boot/dts/broadcom/bcm963138.dts +++ b/arch/arm/boot/dts/broadcom/bcm963138.dts @@ -29,3 +29,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm963138dvt.dts b/arch/arm/boot/dts/broadcom/bcm963138dvt.dts index b5af61853a07..f60d09908ab9 100644 --- a/arch/arm/boot/dts/broadcom/bcm963138dvt.dts +++ b/arch/arm/boot/dts/broadcom/bcm963138dvt.dts @@ -32,15 +32,15 @@ }; &nand_controller { + brcm,wp-not-connected; status = "okay"; +}; - nand@0 { - compatible = "brcm,nandcs"; - reg = <0>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - brcm,nand-oob-sectors-size = <16>; - }; +&nandcs { + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + brcm,nand-oob-sector-size = <16>; + nand-on-flash-bbt; }; &ahci { diff --git a/arch/arm/boot/dts/broadcom/bcm963148.dts b/arch/arm/boot/dts/broadcom/bcm963148.dts index 1f5d6d783f09..44bca063a327 100644 --- a/arch/arm/boot/dts/broadcom/bcm963148.dts +++ b/arch/arm/boot/dts/broadcom/bcm963148.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm963178.dts b/arch/arm/boot/dts/broadcom/bcm963178.dts index d036e99dd8d1..098a222cd71a 100644 --- a/arch/arm/boot/dts/broadcom/bcm963178.dts +++ b/arch/arm/boot/dts/broadcom/bcm963178.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm96756.dts b/arch/arm/boot/dts/broadcom/bcm96756.dts index 8b104f3fb14a..402038d3cd0c 100644 --- a/arch/arm/boot/dts/broadcom/bcm96756.dts +++ b/arch/arm/boot/dts/broadcom/bcm96756.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm96846.dts b/arch/arm/boot/dts/broadcom/bcm96846.dts index 55852c229608..943896afb7cc 100644 --- a/arch/arm/boot/dts/broadcom/bcm96846.dts +++ b/arch/arm/boot/dts/broadcom/bcm96846.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm96855.dts b/arch/arm/boot/dts/broadcom/bcm96855.dts index 2ad880af2104..571663d9a1ea 100644 --- a/arch/arm/boot/dts/broadcom/bcm96855.dts +++ b/arch/arm/boot/dts/broadcom/bcm96855.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm96878.dts b/arch/arm/boot/dts/broadcom/bcm96878.dts index b7af8ade7a9d..8d6eddd54c6e 100644 --- a/arch/arm/boot/dts/broadcom/bcm96878.dts +++ b/arch/arm/boot/dts/broadcom/bcm96878.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; -- cgit v1.2.3 From 5319667c5ee2ecf170f5b2b88797cf5a395533f2 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:53 -0800 Subject: arm64: dts: broadcom: bcmbca: Add NAND controller node Add support for Broadcom STB NAND controller in BCMBCA ARMv8 chip dts files. Signed-off-by: William Zhang Reviewed-by: David Regan Signed-off-by: Miquel Raynal Acked-by: Florian Fainelli Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-9-william.zhang@broadcom.com --- arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi | 4 ++-- arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts | 10 ++++++++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts | 10 ++++++++++ 14 files changed, 156 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi index 2f124b027bbf..336016e334d9 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi @@ -589,7 +589,7 @@ status = "disabled"; }; - nand-controller@1800 { + nand_controller: nand-controller@1800 { #address-cells = <1>; #size-cells = <0>; compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; @@ -597,7 +597,7 @@ reg-names = "nand", "nand-int-base"; interrupts = ; interrupt-names = "nand_ctlrdy"; - status = "okay"; + status = "disabled"; nandcs: nand@0 { compatible = "brcm,nandcs"; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi index d658c81f7285..14b2adfb817c 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi @@ -138,6 +138,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi index 4f474d47022e..589b8a1efc72 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi @@ -119,6 +119,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi index 909f254dc47d..48d618e75866 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi @@ -137,6 +137,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi index 685ae32951c9..1d1303cf90f3 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi @@ -138,6 +138,20 @@ status = "disabled"; }; + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; + uart0: serial@12000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x12000 0x1000>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi index 820553ce541b..00c62c1e5df0 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi @@ -119,5 +119,19 @@ num-cs = <8>; status = "disabled"; }; + + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi index 0eb93c298297..caeaf428dc15 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi @@ -156,5 +156,19 @@ num-cs = <8>; status = "disabled"; }; + + nand_controller: nand-controller@1800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; + reg = <0x1800 0x600>, <0x2000 0x10>; + reg-names = "nand", "nand-int-base"; + status = "disabled"; + + nandcs: nand@0 { + compatible = "brcm,nandcs"; + reg = <0>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts index c4e6e71f6310..030ffa5364fb 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts index e69cd683211a..4b779e6c22e1 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts index db2c82d6dfd8..2851e8e41bf4 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts index 25c12bc63545..17dc594fe83f 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts index faba21f03120..34832a734734 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts index 9808331eede2..e1396b5544b7 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts index 1f561c8e13b0..30bbf6f2917e 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts @@ -32,3 +32,13 @@ &hsspi { status = "okay"; }; + +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + +&nandcs { + nand-on-flash-bbt; + brcm,nand-ecc-use-strap; +}; -- cgit v1.2.3 From 0d7760f230b468c40dbe23a768c8c4a2a61081b2 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:54 -0800 Subject: arm64: dts: broadcom: bcmbca: Update router boards Enable the nand controller and add WP pin connection property in actual board dts as they are board level properties now that they are disabled and moved out from SoC dtsi. Also remove the unnecessary brcm,nand-has-wp property from AC5300 board. This property is only needed for some old controller that this board does not apply. Signed-off-by: William Zhang Signed-off-by: Miquel Raynal Acked-by: Florian Fainelli Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-10-william.zhang@broadcom.com --- arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts | 5 +++++ .../boot/dts/broadcom/bcmbca/bcm4906-tplink-archer-c2300-v1.dts | 5 +++++ arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts index 78204d71ecd2..999d93730240 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts @@ -125,6 +125,11 @@ }; }; +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + &nandcs { nand-ecc-strength = <4>; nand-ecc-step-size = <512>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-tplink-archer-c2300-v1.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-tplink-archer-c2300-v1.dts index fcf092c81b59..19fc03ef47a0 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-tplink-archer-c2300-v1.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-tplink-archer-c2300-v1.dts @@ -155,6 +155,11 @@ }; }; +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + &nandcs { nand-ecc-strength = <4>; nand-ecc-step-size = <512>; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts index d94a53d68320..52f928dbfa3c 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts @@ -166,11 +166,15 @@ }; }; +&nand_controller { + brcm,wp-not-connected; + status = "okay"; +}; + &nandcs { nand-ecc-strength = <4>; nand-ecc-step-size = <512>; nand-on-flash-bbt; - brcm,nand-has-wp; #address-cells = <1>; #size-cells = <0>; -- cgit v1.2.3 From 198eef9f0646b9a15b60274f23b0e27f3387e690 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:55 -0800 Subject: mtd: rawnand: brcmnand: Rename bcm63138 nand driver In preparing to support multiple BCMBCA SoCs, rename bcm63138 to bcmbca in the driver code and driver file name. Signed-off-by: William Zhang Reviewed-by: David Regan Acked-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-11-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/Makefile | 2 +- drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c | 99 --------------------------- drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 99 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 100 deletions(-) delete mode 100644 drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c create mode 100644 drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile index 9907e3ec4bb2..0536568c6467 100644 --- a/drivers/mtd/nand/raw/brcmnand/Makefile +++ b/drivers/mtd/nand/raw/brcmnand/Makefile @@ -2,7 +2,7 @@ # link order matters; don't link the more generic brcmstb_nand.o before the # more specific iproc_nand.o, for instance obj-$(CONFIG_MTD_NAND_BRCMNAND_IPROC) += iproc_nand.o -obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcm63138_nand.o +obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcmbca_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BCM63XX) += bcm6368_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BRCMSTB) += brcmstb_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o diff --git a/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c deleted file mode 100644 index 968c5b674b08..000000000000 --- a/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright © 2015 Broadcom Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "brcmnand.h" - -struct bcm63138_nand_soc { - struct brcmnand_soc soc; - void __iomem *base; -}; - -#define BCM63138_NAND_INT_STATUS 0x00 -#define BCM63138_NAND_INT_EN 0x04 - -enum { - BCM63138_CTLRDY = BIT(4), -}; - -static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc) -{ - struct bcm63138_nand_soc *priv = - container_of(soc, struct bcm63138_nand_soc, soc); - void __iomem *mmio = priv->base + BCM63138_NAND_INT_STATUS; - u32 val = brcmnand_readl(mmio); - - if (val & BCM63138_CTLRDY) { - brcmnand_writel(val & ~BCM63138_CTLRDY, mmio); - return true; - } - - return false; -} - -static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en) -{ - struct bcm63138_nand_soc *priv = - container_of(soc, struct bcm63138_nand_soc, soc); - void __iomem *mmio = priv->base + BCM63138_NAND_INT_EN; - u32 val = brcmnand_readl(mmio); - - if (en) - val |= BCM63138_CTLRDY; - else - val &= ~BCM63138_CTLRDY; - - brcmnand_writel(val, mmio); -} - -static int bcm63138_nand_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct bcm63138_nand_soc *priv; - struct brcmnand_soc *soc; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - soc = &priv->soc; - - priv->base = devm_platform_ioremap_resource_byname(pdev, "nand-int-base"); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - - soc->ctlrdy_ack = bcm63138_nand_intc_ack; - soc->ctlrdy_set_enabled = bcm63138_nand_intc_set; - - return brcmnand_probe(pdev, soc); -} - -static const struct of_device_id bcm63138_nand_of_match[] = { - { .compatible = "brcm,nand-bcm63138" }, - {}, -}; -MODULE_DEVICE_TABLE(of, bcm63138_nand_of_match); - -static struct platform_driver bcm63138_nand_driver = { - .probe = bcm63138_nand_probe, - .remove_new = brcmnand_remove, - .driver = { - .name = "bcm63138_nand", - .pm = &brcmnand_pm_ops, - .of_match_table = bcm63138_nand_of_match, - } -}; -module_platform_driver(bcm63138_nand_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Brian Norris"); -MODULE_DESCRIPTION("NAND driver for BCM63138"); diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c new file mode 100644 index 000000000000..3e2f3b79788d --- /dev/null +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright © 2015 Broadcom Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "brcmnand.h" + +struct bcmbca_nand_soc { + struct brcmnand_soc soc; + void __iomem *base; +}; + +#define BCMBCA_NAND_INT_STATUS 0x00 +#define BCMBCA_NAND_INT_EN 0x04 + +enum { + BCMBCA_CTLRDY = BIT(4), +}; + +static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc) +{ + struct bcmbca_nand_soc *priv = + container_of(soc, struct bcmbca_nand_soc, soc); + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_STATUS; + u32 val = brcmnand_readl(mmio); + + if (val & BCMBCA_CTLRDY) { + brcmnand_writel(val & ~BCMBCA_CTLRDY, mmio); + return true; + } + + return false; +} + +static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en) +{ + struct bcmbca_nand_soc *priv = + container_of(soc, struct bcmbca_nand_soc, soc); + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_EN; + u32 val = brcmnand_readl(mmio); + + if (en) + val |= BCMBCA_CTLRDY; + else + val &= ~BCMBCA_CTLRDY; + + brcmnand_writel(val, mmio); +} + +static int bcmbca_nand_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bcmbca_nand_soc *priv; + struct brcmnand_soc *soc; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + soc = &priv->soc; + + priv->base = devm_platform_ioremap_resource_byname(pdev, "nand-int-base"); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + soc->ctlrdy_ack = bcmbca_nand_intc_ack; + soc->ctlrdy_set_enabled = bcmbca_nand_intc_set; + + return brcmnand_probe(pdev, soc); +} + +static const struct of_device_id bcmbca_nand_of_match[] = { + { .compatible = "brcm,nand-bcm63138" }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcmbca_nand_of_match); + +static struct platform_driver bcmbca_nand_driver = { + .probe = bcmbca_nand_probe, + .remove_new = brcmnand_remove, + .driver = { + .name = "bcmbca_nand", + .pm = &brcmnand_pm_ops, + .of_match_table = bcmbca_nand_of_match, + } +}; +module_platform_driver(bcmbca_nand_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Brian Norris"); +MODULE_DESCRIPTION("NAND driver for BCMBCA"); -- cgit v1.2.3 From 546e425991205f59281e160a0d0daed47b7ca9b3 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:56 -0800 Subject: mtd: rawnand: brcmnand: Add BCMBCA read data bus interface The BCMBCA broadband SoC integrates the NAND controller differently than STB, iProc and other SoCs. It has different endianness for NAND cache data. Add a SoC read data bus shim for BCMBCA to meet the specific SoC need and performance improvement using the optimized memcpy function on NAND cache memory. Signed-off-by: William Zhang Reviewed-by: David Regan Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-12-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 27 +++++++++++++++++++++++++++ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 20 +++++++++++++++++--- drivers/mtd/nand/raw/brcmnand/brcmnand.h | 2 ++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c index 3e2f3b79788d..7ad3e7a98f97 100644 --- a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c @@ -26,6 +26,18 @@ enum { BCMBCA_CTLRDY = BIT(4), }; +#if defined(CONFIG_ARM64) +#define ALIGN_REQ 8 +#else +#define ALIGN_REQ 4 +#endif + +static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer) +{ + return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) && + IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ); +} + static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc) { struct bcmbca_nand_soc *priv = @@ -56,6 +68,20 @@ static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en) brcmnand_writel(val, mmio); } +static void bcmbca_read_data_bus(struct brcmnand_soc *soc, + void __iomem *flash_cache, u32 *buffer, int fc_words) +{ + /* + * memcpy can do unaligned aligned access depending on source + * and dest address, which is incompatible with nand cache. Fallback + * to the memcpy_fromio in such case + */ + if (bcmbca_nand_is_buf_aligned((void *)flash_cache, buffer)) + memcpy((void *)buffer, (void *)flash_cache, fc_words * 4); + else + memcpy_fromio((void *)buffer, flash_cache, fc_words * 4); +} + static int bcmbca_nand_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -73,6 +99,7 @@ static int bcmbca_nand_probe(struct platform_device *pdev) soc->ctlrdy_ack = bcmbca_nand_intc_ack; soc->ctlrdy_set_enabled = bcmbca_nand_intc_set; + soc->read_data_bus = bcmbca_read_data_bus; return brcmnand_probe(pdev, soc); } diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index f1f0de50b5f7..ef7d340475be 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -851,6 +851,20 @@ static inline u32 edu_readl(struct brcmnand_controller *ctrl, return brcmnand_readl(ctrl->edu_base + offs); } +static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl, + void __iomem *flash_cache, u32 *buffer, int fc_words) +{ + struct brcmnand_soc *soc = ctrl->soc; + int i; + + if (soc->read_data_bus) { + soc->read_data_bus(soc, flash_cache, buffer, fc_words); + } else { + for (i = 0; i < fc_words; i++) + buffer[i] = brcmnand_read_fc(ctrl, i); + } +} + static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) { @@ -1975,7 +1989,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, { struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; - int i, j, ret = 0; + int i, ret = 0; brcmnand_clear_ecc_addr(ctrl); @@ -1988,8 +2002,8 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, if (likely(buf)) { brcmnand_soc_data_bus_prepare(ctrl->soc, false); - for (j = 0; j < FC_WORDS; j++, buf++) - *buf = brcmnand_read_fc(ctrl, j); + brcmnand_read_data_bus(ctrl, ctrl->nand_fc, buf, FC_WORDS); + buf += FC_WORDS; brcmnand_soc_data_bus_unprepare(ctrl->soc, false); } diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.h b/drivers/mtd/nand/raw/brcmnand/brcmnand.h index 928114c0be5e..9f171252a2ae 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h @@ -24,6 +24,8 @@ struct brcmnand_soc { void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en); void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare, bool is_param); + void (*read_data_bus)(struct brcmnand_soc *soc, void __iomem *flash_cache, + u32 *buffer, int fc_words); const struct brcmnand_io_ops *ops; }; -- cgit v1.2.3 From 8e7daa85641c9559c113f6b217bdc923397de77c Mon Sep 17 00:00:00 2001 From: William Zhang Date: Thu, 22 Feb 2024 19:47:58 -0800 Subject: mtd: rawnand: brcmnand: Support write protection setting from dts The write protection feature is controlled by the module parameter wp_on with default set to enabled. But not all the board use this feature especially in BCMBCA broadband board. And module parameter is not sufficient as different board can have different option. Add a device tree property and allow this feature to be configured through the board dts on per board basis. Signed-off-by: William Zhang Reviewed-by: Florian Fainelli Reviewed-by: Kamal Dasu Reviewed-by: David Regan Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-14-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ef7d340475be..c9405701925d 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -3152,6 +3152,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) /* Disable XOR addressing */ brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0); + /* Check if the board connects the WP pin */ + if (of_property_read_bool(dn, "brcm,wp-not-connected")) + wp_on = 0; + if (ctrl->features & BRCMNAND_HAS_WP) { /* Permanently disable write protection */ if (wp_on == 2) -- cgit v1.2.3 From 705a1280fb9c6e43713c27c69886a85fe8849a8f Mon Sep 17 00:00:00 2001 From: Varshini Rajendran Date: Fri, 23 Feb 2024 22:55:20 +0530 Subject: dt-bindings: atmel-nand: add microchip,sam9x7-pmecc Add microchip,sam9x7-pmecc to DT bindings documentation. Signed-off-by: Varshini Rajendran Acked-by: Conor Dooley Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223172520.671940-1-varshini.rajendran@microchip.com --- Documentation/devicetree/bindings/mtd/atmel-nand.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index 50645828ac20..4598930851d9 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt @@ -56,6 +56,7 @@ Required properties: "atmel,sama5d4-pmecc" "atmel,sama5d2-pmecc" "microchip,sam9x60-pmecc" + "microchip,sam9x7-pmecc", "atmel,at91sam9g45-pmecc" - reg: should contain 2 register ranges. The first one is pointing to the PMECC block, and the second one to the PMECC_ERRLOC block. -- cgit v1.2.3 From c9692ebf6253c1d7325f287b268c4a1882136393 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 23 Feb 2024 17:46:39 -0800 Subject: mtd: rawnand: hynix: remove @nand_technology kernel-doc description Remove the extraneous kernel-doc description for @nand_technology to eliminate a kernel-doc warning: nand_hynix.c:39: warning: Excess struct member 'nand_technology' description in 'hynix_nand' Signed-off-by: Randy Dunlap Cc: Miquel Raynal Cc: Richard Weinberger Cc: Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240224014639.16145-1-rdunlap@infradead.org --- drivers/mtd/nand/raw/nand_hynix.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 39076735a3fb..a74e64e0cfa3 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -31,7 +31,6 @@ struct hynix_read_retry { /** * struct hynix_nand - private Hynix NAND struct - * @nand_technology: manufacturing process expressed in picometer * @read_retry: read-retry information */ struct hynix_nand { -- cgit v1.2.3 From c7ee7c8d4b60fe46d4861b1200bc1c7ab657960a Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 23 Feb 2024 12:55:43 +0100 Subject: mtd: rawnand: Fix and simplify again the continuous read derivations We need to avoid the first page if we don't read it entirely. We need to avoid the last page if we don't read it entirely. While rather simple, this logic has been failed in the previous fix. This time I wrote about 30 unit tests locally to check each possible condition, hopefully I covered them all. Reported-by: Christophe Kerello Closes: https://lore.kernel.org/linux-mtd/20240221175327.42f7076d@xps-13/T/#m399bacb10db8f58f6b1f0149a1df867ec086bb0a Suggested-by: Christophe Kerello Fixes: 828f6df1bcba ("mtd: rawnand: Clarify conditions to enable continuous reads") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Tested-by: Christophe Kerello Link: https://lore.kernel.org/linux-mtd/20240223115545.354541-2-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3b3ce2926f5d..bcfd99a1699f 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3466,30 +3466,36 @@ static void rawnand_enable_cont_reads(struct nand_chip *chip, unsigned int page, u32 readlen, int col) { struct mtd_info *mtd = nand_to_mtd(chip); - unsigned int end_page, end_col; + unsigned int first_page, last_page; chip->cont_read.ongoing = false; if (!chip->controller->supported_op.cont_read) return; - end_page = DIV_ROUND_UP(col + readlen, mtd->writesize); - end_col = (col + readlen) % mtd->writesize; + /* + * Don't bother making any calculations if the length is too small. + * Side effect: avoids possible integer underflows below. + */ + if (readlen < (2 * mtd->writesize)) + return; + /* Derive the page where continuous read should start (the first full page read) */ + first_page = page; if (col) - page++; - - if (end_col && end_page) - end_page--; + first_page++; - if (page + 1 > end_page) - return; - - chip->cont_read.first_page = page; - chip->cont_read.last_page = end_page; - chip->cont_read.ongoing = true; + /* Derive the page where continuous read should stop (the last full page read) */ + last_page = page + ((col + readlen) / mtd->writesize) - 1; - rawnand_cap_cont_reads(chip); + /* Configure and enable continuous read when suitable */ + if (first_page < last_page) { + chip->cont_read.first_page = first_page; + chip->cont_read.last_page = last_page; + chip->cont_read.ongoing = true; + /* May reset the ongoing flag */ + rawnand_cap_cont_reads(chip); + } } static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page) -- cgit v1.2.3 From df9803bf5a91e3599f12b53c94722f2c4e144a86 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 23 Feb 2024 12:55:44 +0100 Subject: mtd: rawnand: Add a helper for calculating a page index For LUN crossing boundaries, it is handy to know what is the index of the last page in a LUN. This helper will soon be reused. At the same time I rename page_per_lun to ppl in the calling function to clarify the lines. Cc: stable@vger.kernel.org # v6.7 Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223115545.354541-3-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index bcfd99a1699f..d6a27e08b112 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1211,19 +1211,25 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page, return nand_exec_op(chip, &op); } +static unsigned int rawnand_last_page_of_lun(unsigned int pages_per_lun, unsigned int lun) +{ + /* lun is expected to be very small */ + return (lun * pages_per_lun) + pages_per_lun - 1; +} + static void rawnand_cap_cont_reads(struct nand_chip *chip) { struct nand_memory_organization *memorg; - unsigned int pages_per_lun, first_lun, last_lun; + unsigned int ppl, first_lun, last_lun; memorg = nanddev_get_memorg(&chip->base); - pages_per_lun = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun; - first_lun = chip->cont_read.first_page / pages_per_lun; - last_lun = chip->cont_read.last_page / pages_per_lun; + ppl = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun; + first_lun = chip->cont_read.first_page / ppl; + last_lun = chip->cont_read.last_page / ppl; /* Prevent sequential cache reads across LUN boundaries */ if (first_lun != last_lun) - chip->cont_read.pause_page = first_lun * pages_per_lun + pages_per_lun - 1; + chip->cont_read.pause_page = rawnand_last_page_of_lun(ppl, first_lun); else chip->cont_read.pause_page = chip->cont_read.last_page; } -- cgit v1.2.3 From 6fb075fca63c3486612986eeff84ed4179644038 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 23 Feb 2024 12:55:45 +0100 Subject: mtd: rawnand: Ensure all continuous terms are always in sync While crossing a LUN boundary, it is probably safer (and clearer) to keep all members of the continuous read structure aligned, including the pause page (which is the last page of the lun or the last page of the continuous read). Once these members properly in sync, we can use the rawnand_cap_cont_reads() helper everywhere to "prepare" the next continuous read if there is one. Fixes: bbcd80f53a5e ("mtd: rawnand: Prevent crossing LUN boundaries during sequential reads") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240223115545.354541-4-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d6a27e08b112..4d5a663e4e05 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1232,6 +1232,15 @@ static void rawnand_cap_cont_reads(struct nand_chip *chip) chip->cont_read.pause_page = rawnand_last_page_of_lun(ppl, first_lun); else chip->cont_read.pause_page = chip->cont_read.last_page; + + if (chip->cont_read.first_page == chip->cont_read.pause_page) { + chip->cont_read.first_page++; + chip->cont_read.pause_page = min(chip->cont_read.last_page, + rawnand_last_page_of_lun(ppl, first_lun + 1)); + } + + if (chip->cont_read.first_page >= chip->cont_read.last_page) + chip->cont_read.ongoing = false; } static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int page, @@ -1298,12 +1307,11 @@ static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int p if (!chip->cont_read.ongoing) return 0; - if (page == chip->cont_read.pause_page && - page != chip->cont_read.last_page) { - chip->cont_read.first_page = chip->cont_read.pause_page + 1; - rawnand_cap_cont_reads(chip); - } else if (page == chip->cont_read.last_page) { + if (page == chip->cont_read.last_page) { chip->cont_read.ongoing = false; + } else if (page == chip->cont_read.pause_page) { + chip->cont_read.first_page++; + rawnand_cap_cont_reads(chip); } return 0; @@ -3510,10 +3518,7 @@ static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned i return; chip->cont_read.first_page++; - if (chip->cont_read.first_page == chip->cont_read.pause_page) - chip->cont_read.first_page++; - if (chip->cont_read.first_page >= chip->cont_read.last_page) - chip->cont_read.ongoing = false; + rawnand_cap_cont_reads(chip); } /** -- cgit v1.2.3 From 1c60e027ffdebd36f4da766d9c9abbd1ea4dd8f9 Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Mon, 26 Feb 2024 13:25:37 +0100 Subject: mtd: nand: raw: atmel: Fix comment in timings preparation Looks like a copy'n'paste mistake introduced when initially adding the dynamic timings feature with commit f9ce2eddf176 ("mtd: nand: atmel: Add ->setup_data_interface() hooks"). The context around this and especially the code itself suggests 'read' is meant instead of write. Signed-off-by: Alexander Dahl Reviewed-by: Nicolas Ferre Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240226122537.75097-1-ada@thorsis.com --- drivers/mtd/nand/raw/atmel/nand-controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 4cb478bbee4a..dc75d50d52e8 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1378,7 +1378,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, return ret; /* - * The write cycle timing is directly matching tWC, but is also + * The read cycle timing is directly matching tRC, but is also * dependent on the setup and hold timings we calculated earlier, * which gives: * -- cgit v1.2.3 From 29d53c54ae98201224f3e2ddb8e9bbac389cad23 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Tue, 27 Feb 2024 11:02:57 -0800 Subject: mtd: rawnand: brcmnand: fix sparse warnings Fix the following sparse warnings: sparse warnings: (new ones prefixed by >>) >> drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c:79:41: sparse: sparse: cast removes address space '__iomem' of expression drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c:80:17: sparse: sparse: cast removes address space '__iomem' of expression drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c:80:17: sparse: sparse: cast removes address space '__iomem' of expression drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c:80:17: sparse: sparse: cast removes address space '__iomem' of expression Fixes: c52c16d1bee5 ("mtd: rawnand: brcmnand: Add BCMBCA read data bus interface") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202402270940.gmVLVRg0-lkp@intel.com/ Signed-off-by: William Zhang Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240227190258.200929-1-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c index 7ad3e7a98f97..ea534850b97a 100644 --- a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c @@ -76,8 +76,8 @@ static void bcmbca_read_data_bus(struct brcmnand_soc *soc, * and dest address, which is incompatible with nand cache. Fallback * to the memcpy_fromio in such case */ - if (bcmbca_nand_is_buf_aligned((void *)flash_cache, buffer)) - memcpy((void *)buffer, (void *)flash_cache, fc_words * 4); + if (bcmbca_nand_is_buf_aligned((void __force *)flash_cache, buffer)) + memcpy((void *)buffer, (void __force *)flash_cache, fc_words * 4); else memcpy_fromio((void *)buffer, flash_cache, fc_words * 4); } -- cgit v1.2.3 From c2cf7e25eb2a3c915a420fb8ceed8912add7f36c Mon Sep 17 00:00:00 2001 From: William Zhang Date: Fri, 1 Mar 2024 09:33:07 -0800 Subject: mtd: rawnand: brcmnand: Add support for getting ecc setting from strap BCMBCA broadband SoC based board design does not specify ecc setting in dts but rather use the SoC NAND strap info to obtain the ecc strength and spare area size setting. Add brcm,nand-ecc-use-strap dts propety for this purpose and update driver to support this option. However these two options can not be used at the same time. Signed-off-by: William Zhang Reviewed-by: David Regan Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240301173308.226004-1-william.zhang@broadcom.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 83 +++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index c9405701925d..a8d12c71f987 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1038,6 +1038,22 @@ static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl) return -1; } +static bool brcmnand_get_sector_size_1k(struct brcmnand_host *host) +{ + struct brcmnand_controller *ctrl = host->ctrl; + int sector_size_bit = brcmnand_sector_1k_shift(ctrl); + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, + BRCMNAND_CS_ACC_CONTROL); + u32 acc_control; + + if (sector_size_bit < 0) + return false; + + acc_control = nand_readreg(ctrl, acc_control_offs); + + return ((acc_control & BIT(sector_size_bit)) != 0); +} + static void brcmnand_set_sector_size_1k(struct brcmnand_host *host, int val) { struct brcmnand_controller *ctrl = host->ctrl; @@ -1055,6 +1071,43 @@ static void brcmnand_set_sector_size_1k(struct brcmnand_host *host, int val) nand_writereg(ctrl, acc_control_offs, tmp); } +static int brcmnand_get_spare_size(struct brcmnand_host *host) +{ + struct brcmnand_controller *ctrl = host->ctrl; + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, + BRCMNAND_CS_ACC_CONTROL); + u32 acc = nand_readreg(ctrl, acc_control_offs); + + return (acc & brcmnand_spare_area_mask(ctrl)); +} + +static void brcmnand_get_ecc_settings(struct brcmnand_host *host, struct nand_chip *chip) +{ + struct brcmnand_controller *ctrl = host->ctrl; + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, + BRCMNAND_CS_ACC_CONTROL); + bool sector_size_1k = brcmnand_get_sector_size_1k(host); + int spare_area_size, ecc_level; + u32 acc; + + spare_area_size = brcmnand_get_spare_size(host); + acc = nand_readreg(ctrl, acc_control_offs); + ecc_level = (acc & brcmnand_ecc_level_mask(ctrl)) >> ctrl->ecc_level_shift; + if (sector_size_1k) + chip->ecc.strength = ecc_level * 2; + else if (spare_area_size == 16 && ecc_level == 15) + chip->ecc.strength = 1; /* hamming */ + else + chip->ecc.strength = ecc_level; + + if (chip->ecc.size == 0) { + if (sector_size_1k) + chip->ecc.size = 1024; + else + chip->ecc.size = 512; + } +} + /*********************************************************************** * CS_NAND_SELECT ***********************************************************************/ @@ -2625,19 +2678,37 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) nanddev_get_memorg(&chip->base); struct brcmnand_controller *ctrl = host->ctrl; struct brcmnand_cfg *cfg = &host->hwcfg; - char msg[128]; + struct device_node *np = nand_get_flash_node(chip); u32 offs, tmp, oob_sector; + bool use_strap = false; + char msg[128]; int ret; memset(cfg, 0, sizeof(*cfg)); + use_strap = of_property_read_bool(np, "brcm,nand-ecc-use-strap"); - ret = of_property_read_u32(nand_get_flash_node(chip), - "brcm,nand-oob-sector-size", + /* + * Either nand-ecc-xxx or brcm,nand-ecc-use-strap can be set. Error out + * if both exist. + */ + if (chip->ecc.strength && use_strap) { + dev_err(ctrl->dev, + "ECC strap and DT ECC configuration properties are mutually exclusive\n"); + return -EINVAL; + } + + if (use_strap) + brcmnand_get_ecc_settings(host, chip); + + ret = of_property_read_u32(np, "brcm,nand-oob-sector-size", &oob_sector); if (ret) { - /* Use detected size */ - cfg->spare_area_size = mtd->oobsize / - (mtd->writesize >> FC_SHIFT); + if (use_strap) + cfg->spare_area_size = brcmnand_get_spare_size(host); + else + /* Use detected size */ + cfg->spare_area_size = mtd->oobsize / + (mtd->writesize >> FC_SHIFT); } else { cfg->spare_area_size = oob_sector; } -- cgit v1.2.3 From 78ffbefba8d7822b232585570b293de5bc397da6 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 7 Mar 2024 12:53:14 +0100 Subject: mtd: rawnand: Constrain even more when continuous reads are enabled As a matter of fact, continuous reads require additional handling at the operation level in order for them to work properly. The core helpers do have this additional logic now, but any time a controller implements its own page helper, this extra logic is "lost". This means we need another level of per-controller driver checks to ensure they can leverage continuous reads. This is for now unsupported, so in order to ensure continuous reads are enabled only when fully using the core page helpers, we need to add more initial checks. Also, as performance is not relevant during raw accesses, we also prevent these from enabling the feature. This should solve the issue seen with controllers such as the STM32 FMC2 when in sequencer mode. In this case, the continuous read feature would be enabled but not leveraged, and most importantly not disabled, leading to further operations to fail. Reported-by: Christophe Kerello Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Tested-by: Christophe Kerello Link: https://lore.kernel.org/linux-mtd/20240307115315.1942678-1-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 4d5a663e4e05..2479fa98f991 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3594,7 +3594,8 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from, oob = ops->oobbuf; oob_required = oob ? 1 : 0; - rawnand_enable_cont_reads(chip, page, readlen, col); + if (likely(ops->mode != MTD_OPS_RAW)) + rawnand_enable_cont_reads(chip, page, readlen, col); while (1) { struct mtd_ecc_stats ecc_stats = mtd->ecc_stats; @@ -5212,6 +5213,15 @@ static void rawnand_late_check_supported_ops(struct nand_chip *chip) if (!nand_has_exec_op(chip)) return; + /* + * For now, continuous reads can only be used with the core page helpers. + * This can be extended later. + */ + if (!(chip->ecc.read_page == nand_read_page_hwecc || + chip->ecc.read_page == nand_read_page_syndrome || + chip->ecc.read_page == nand_read_page_swecc)) + return; + rawnand_check_cont_read_support(chip); } -- cgit v1.2.3 From 4120aa0e3961f68f1f8cfe6b4c3c809ffea31fdc Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 7 Mar 2024 12:53:15 +0100 Subject: mtd: rawnand: Ensure continuous reads are well disabled The cont_read.ongoing flag should only be enabled at the beginning of a read operation, and also disabled at its end, so we never end up triggering nasty side effects outside of this scope. The mtd core being highly serialized, we should not be bothered by parallel accesses anyway. In case we reach the end of a read operation and the boolean was not properly disabled, it's a bug, but it's totally manageable. So warn, and then fix the boolean state. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20240307115315.1942678-2-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 2479fa98f991..d7dbbd469b89 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3728,6 +3728,9 @@ read_retry: } nand_deselect_target(chip); + if (WARN_ON_ONCE(chip->cont_read.ongoing)) + chip->cont_read.ongoing = false; + ops->retlen = ops->len - (size_t) readlen; if (oob) ops->oobretlen = ops->ooblen - oobreadlen; -- cgit v1.2.3