aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2026-04-17 21:51:05 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2026-04-17 21:51:05 +0200
commitb2a4fe0960aee9a2c8045cfd26fbeacf30b26efe (patch)
tree7fba799dc9d685058c788a00a1becf640569f9c1
parent357e460a3099702a904f8b164a13305c34d4385d (diff)
parent7866ce992cf0d3c3b50fe8bf4acb1dbb173a2304 (diff)
Merge tag 'nand/for-7.1' into mtd/next
The main changes happened in the SunXi driver in order to support new versions of the Allwinner NAND controller. There are also some DT-binding improvements and cleanups. Finally a couple of actual fixes (Realtek ECC and Winbond SPI NAND), aside with the usual load of misc changes.
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmi-nand.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/mxc-nand.yaml27
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-chip.yaml46
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-controller-legacy.yaml65
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-property.yaml64
-rw-r--r--Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml74
-rw-r--r--Documentation/devicetree/bindings/mtd/raw-nand-property.yaml98
-rw-r--r--drivers/mtd/nand/ecc-realtek.c18
-rw-r--r--drivers/mtd/nand/raw/cafe_nand.c7
-rw-r--r--drivers/mtd/nand/raw/fsl_ifc_nand.c10
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c11
-rw-r--r--drivers/mtd/nand/raw/mxc_nand.c10
-rw-r--r--drivers/mtd/nand/raw/nand_base.c19
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c369
-rw-r--r--drivers/mtd/nand/spi/winbond.c17
-rw-r--r--include/linux/mtd/spinand.h5
17 files changed, 610 insertions, 234 deletions
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml b/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml
index 0badb2e978c7..adb684e3207c 100644
--- a/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.yaml
@@ -101,7 +101,7 @@ required:
unevaluatedProperties: false
allOf:
- - $ref: nand-controller.yaml
+ - $ref: nand-controller-legacy.yaml
- if:
properties:
diff --git a/Documentation/devicetree/bindings/mtd/mxc-nand.yaml b/Documentation/devicetree/bindings/mtd/mxc-nand.yaml
index bd8f7b683953..fbaff7d3eda8 100644
--- a/Documentation/devicetree/bindings/mtd/mxc-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/mxc-nand.yaml
@@ -10,22 +10,43 @@ maintainers:
- Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
allOf:
- - $ref: nand-controller.yaml
+ - $ref: nand-controller-legacy.yaml
properties:
compatible:
oneOf:
- - const: fsl,imx27-nand
+ - enum:
+ - fsl,imx25-nand
+ - fsl,imx27-nand
+ - fsl,imx51-nand
+ - fsl,imx53-nand
+ - items:
+ - enum:
+ - fsl,imx35-nand
+ - const: fsl,imx25-nand
- items:
- enum:
- fsl,imx31-nand
- const: fsl,imx27-nand
reg:
- maxItems: 1
+ minItems: 1
+ items:
+ - description: IP register space
+ - description: Nand flash internal buffer space
interrupts:
maxItems: 1
+ clocks:
+ maxItems: 1
+
+ dmas:
+ maxItems: 1
+
+ dma-names:
+ items:
+ - const: rx-tx
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mtd/nand-chip.yaml b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
index 609d4a4ddd80..8800d1d07266 100644
--- a/Documentation/devicetree/bindings/mtd/nand-chip.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: mtd.yaml#
+ - $ref: nand-property.yaml
description: |
This file covers the generic description of a NAND chip. It implies that the
@@ -22,51 +23,6 @@ properties:
description:
Contains the chip-select IDs.
- nand-ecc-engine:
- description: |
- A phandle on the hardware ECC engine if any. There are
- basically three possibilities:
- 1/ The ECC engine is part of the NAND controller, in this
- case the phandle should reference the parent node.
- 2/ The ECC engine is part of the NAND part (on-die), in this
- case the phandle should reference the node itself.
- 3/ The ECC engine is external, in this case the phandle should
- reference the specific ECC engine node.
- $ref: /schemas/types.yaml#/definitions/phandle
-
- nand-use-soft-ecc-engine:
- description: Use a software ECC engine.
- type: boolean
-
- nand-no-ecc-engine:
- description: Do not use any ECC correction.
- type: boolean
-
- nand-ecc-algo:
- description:
- Desired ECC algorithm.
- $ref: /schemas/types.yaml#/definitions/string
- enum: [hamming, bch, rs]
-
- nand-ecc-strength:
- description:
- Maximum number of bits that can be corrected per ECC step.
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 1
-
- nand-ecc-step-size:
- description:
- Number of data bytes covered by a single ECC step.
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 1
-
- secure-regions:
- description:
- Regions in the NAND chip which are protected using a secure element
- like Trustzone. This property contains the start address and size of
- the secure regions present.
- $ref: /schemas/types.yaml#/definitions/uint64-matrix
-
required:
- reg
diff --git a/Documentation/devicetree/bindings/mtd/nand-controller-legacy.yaml b/Documentation/devicetree/bindings/mtd/nand-controller-legacy.yaml
new file mode 100644
index 000000000000..d6e612413df1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/nand-controller-legacy.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/nand-controller-legacy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NAND Controller Common Properties
+
+maintainers:
+ - Miquel Raynal <miquel.raynal@bootlin.com>
+ - Richard Weinberger <richard@nod.at>
+
+description: >
+ The NAND controller should be represented with its own DT node, and
+ all NAND chips attached to this controller should be defined as
+ children nodes of the NAND controller. This representation should be
+ enforced even for simple controllers supporting only one chip.
+
+ This is only for legacy nand controller, new controller should use
+ nand-controller.yaml
+
+properties:
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ enum: [0, 1]
+
+ ranges: true
+
+ cs-gpios:
+ description:
+ Array of chip-select available to the controller. The first
+ entries are a 1:1 mapping of the available chip-select on the
+ NAND controller (even if they are not used). As many additional
+ chip-select as needed may follow and should be phandles of GPIO
+ lines. 'reg' entries of the NAND chip subnodes become indexes of
+ this array when this property is present.
+ minItems: 1
+ maxItems: 8
+
+ partitions:
+ type: object
+
+ required:
+ - compatible
+
+patternProperties:
+ "^nand@[a-f0-9]$":
+ type: object
+ $ref: raw-nand-chip.yaml#
+
+ "^partition@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/mtd/partitions/partition.yaml#/$defs/partition-node
+ deprecated: true
+
+allOf:
+ - $ref: raw-nand-property.yaml#
+ - $ref: nand-property.yaml#
+
+# This is a generic file other binding inherit from and extend
+additionalProperties: true
+
diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index 28167c0cf271..0aa61d5fa50b 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -16,6 +16,8 @@ description: |
children nodes of the NAND controller. This representation should be
enforced even for simple controllers supporting only one chip.
+select: false
+
properties:
$nodename:
pattern: "^nand-controller(@.*)?"
diff --git a/Documentation/devicetree/bindings/mtd/nand-property.yaml b/Documentation/devicetree/bindings/mtd/nand-property.yaml
new file mode 100644
index 000000000000..55488a4b1548
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/nand-property.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/nand-property.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NAND Chip Common Properties
+
+maintainers:
+ - Miquel Raynal <miquel.raynal@bootlin.com>
+
+description: |
+ This file covers the generic properties of a NAND chip. It implies that the
+ bus interface should not be taken into account: both raw NAND devices and
+ SPI-NAND devices are concerned by this description.
+
+properties:
+ nand-ecc-engine:
+ description: |
+ A phandle on the hardware ECC engine if any. There are
+ basically three possibilities:
+ 1/ The ECC engine is part of the NAND controller, in this
+ case the phandle should reference the parent node.
+ 2/ The ECC engine is part of the NAND part (on-die), in this
+ case the phandle should reference the node itself.
+ 3/ The ECC engine is external, in this case the phandle should
+ reference the specific ECC engine node.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ nand-use-soft-ecc-engine:
+ description: Use a software ECC engine.
+ type: boolean
+
+ nand-no-ecc-engine:
+ description: Do not use any ECC correction.
+ type: boolean
+
+ nand-ecc-algo:
+ description:
+ Desired ECC algorithm.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum: [hamming, bch, rs]
+
+ nand-ecc-strength:
+ description:
+ Maximum number of bits that can be corrected per ECC step.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+
+ nand-ecc-step-size:
+ description:
+ Number of data bytes covered by a single ECC step.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+
+ secure-regions:
+ description:
+ Regions in the NAND chip which are protected using a secure element
+ like Trustzone. This property contains the start address and size of
+ the secure regions present.
+ $ref: /schemas/types.yaml#/definitions/uint64-matrix
+
+# This file can be referenced by more specific devices (like spi-nands)
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml b/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml
index 092448d7bfc5..792de3e3c6ee 100644
--- a/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml
+++ b/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml
@@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: nand-chip.yaml#
+ - $ref: raw-nand-property.yaml#
description: |
The ECC strength and ECC step size properties define the user
@@ -31,79 +32,6 @@ properties:
description:
Contains the chip-select IDs.
- nand-ecc-placement:
- description:
- Location of the ECC bytes. This location is unknown by default
- but can be explicitly set to "oob", if all ECC bytes are
- known to be stored in the OOB area, or "interleaved" if ECC
- bytes will be interleaved with regular data in the main area.
- $ref: /schemas/types.yaml#/definitions/string
- enum: [ oob, interleaved ]
- deprecated: true
-
- nand-ecc-mode:
- description:
- Legacy ECC configuration mixing the ECC engine choice and
- configuration.
- $ref: /schemas/types.yaml#/definitions/string
- enum: [none, soft, soft_bch, hw, hw_syndrome, on-die]
- deprecated: true
-
- nand-bus-width:
- description:
- Bus width to the NAND chip
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [8, 16]
- default: 8
-
- nand-on-flash-bbt:
- description:
- With this property, the OS will search the device for a Bad
- Block Table (BBT). If not found, it will create one, reserve
- a few blocks at the end of the device to store it and update
- it as the device ages. Otherwise, the out-of-band area of a
- few pages of all the blocks will be scanned at boot time to
- find Bad Block Markers (BBM). These markers will help to
- build a volatile BBT in RAM.
- $ref: /schemas/types.yaml#/definitions/flag
-
- nand-ecc-maximize:
- description:
- Whether or not the ECC strength should be maximized. The
- maximum ECC strength is both controller and chip
- dependent. The ECC engine has to select the ECC config
- providing the best strength and taking the OOB area size
- constraint into account. This is particularly useful when
- only the in-band area is used by the upper layers, and you
- want to make your NAND as reliable as possible.
- $ref: /schemas/types.yaml#/definitions/flag
-
- nand-is-boot-medium:
- description:
- Whether or not the NAND chip is a boot medium. Drivers might
- use this information to select ECC algorithms supported by
- the boot ROM or similar restrictions.
- $ref: /schemas/types.yaml#/definitions/flag
-
- nand-rb:
- description:
- Contains the native Ready/Busy IDs.
- $ref: /schemas/types.yaml#/definitions/uint32-array
-
- rb-gpios:
- description:
- Contains one or more GPIO descriptor (the numper of descriptor
- depends on the number of R/B pins exposed by the flash) for the
- Ready/Busy pins. Active state refers to the NAND ready state and
- should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted.
-
- wp-gpios:
- description:
- Contains one GPIO descriptor for the Write Protect pin.
- Active state refers to the NAND Write Protect state and should be
- set to GPIOD_ACTIVE_LOW unless the signal is inverted.
- maxItems: 1
-
required:
- reg
diff --git a/Documentation/devicetree/bindings/mtd/raw-nand-property.yaml b/Documentation/devicetree/bindings/mtd/raw-nand-property.yaml
new file mode 100644
index 000000000000..f853b72426c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/raw-nand-property.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/raw-nand-property.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Raw NAND Chip Common Properties
+
+maintainers:
+ - Miquel Raynal <miquel.raynal@bootlin.com>
+
+description: |
+ The ECC strength and ECC step size properties define the user
+ desires in terms of correction capability of a controller. Together,
+ they request the ECC engine to correct {strength} bit errors per
+ {size} bytes for a particular raw NAND chip.
+
+ The interpretation of these parameters is implementation-defined, so
+ not all implementations must support all possible
+ combinations. However, implementations are encouraged to further
+ specify the value(s) they support.
+
+properties:
+ nand-ecc-placement:
+ description:
+ Location of the ECC bytes. This location is unknown by default
+ but can be explicitly set to "oob", if all ECC bytes are
+ known to be stored in the OOB area, or "interleaved" if ECC
+ bytes will be interleaved with regular data in the main area.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum: [ oob, interleaved ]
+ deprecated: true
+
+ nand-ecc-mode:
+ description:
+ Legacy ECC configuration mixing the ECC engine choice and
+ configuration.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum: [none, soft, soft_bch, hw, hw_syndrome, on-die]
+ deprecated: true
+
+ nand-bus-width:
+ description:
+ Bus width to the NAND chip
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [8, 16]
+ default: 8
+
+ nand-on-flash-bbt:
+ description:
+ With this property, the OS will search the device for a Bad
+ Block Table (BBT). If not found, it will create one, reserve
+ a few blocks at the end of the device to store it and update
+ it as the device ages. Otherwise, the out-of-band area of a
+ few pages of all the blocks will be scanned at boot time to
+ find Bad Block Markers (BBM). These markers will help to
+ build a volatile BBT in RAM.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ nand-ecc-maximize:
+ description:
+ Whether or not the ECC strength should be maximized. The
+ maximum ECC strength is both controller and chip
+ dependent. The ECC engine has to select the ECC config
+ providing the best strength and taking the OOB area size
+ constraint into account. This is particularly useful when
+ only the in-band area is used by the upper layers, and you
+ want to make your NAND as reliable as possible.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ nand-is-boot-medium:
+ description:
+ Whether or not the NAND chip is a boot medium. Drivers might
+ use this information to select ECC algorithms supported by
+ the boot ROM or similar restrictions.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ nand-rb:
+ description:
+ Contains the native Ready/Busy IDs.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
+ rb-gpios:
+ description:
+ Contains one or more GPIO descriptor (the numper of descriptor
+ depends on the number of R/B pins exposed by the flash) for the
+ Ready/Busy pins. Active state refers to the NAND ready state and
+ should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted.
+
+ wp-gpios:
+ description:
+ Contains one GPIO descriptor for the Write Protect pin.
+ Active state refers to the NAND Write Protect state and should be
+ set to GPIOD_ACTIVE_LOW unless the signal is inverted.
+ maxItems: 1
+
+# This is a generic file other binding inherit from and extend
+additionalProperties: true
diff --git a/drivers/mtd/nand/ecc-realtek.c b/drivers/mtd/nand/ecc-realtek.c
index 0046da37ea3e..7d003fd72027 100644
--- a/drivers/mtd/nand/ecc-realtek.c
+++ b/drivers/mtd/nand/ecc-realtek.c
@@ -17,10 +17,12 @@
* - BCH12 : Generate 20 ECC bytes from 512 data bytes plus 6 free bytes
*
* It can run for arbitrary NAND flash chips with different block and OOB sizes. Currently there
- * are only two known devices in the wild that have NAND flash and make use of this ECC engine
- * (Linksys LGS328C & LGS352C). To keep compatibility with vendor firmware, new modes can only
- * be added when new data layouts have been analyzed. For now allow BCH6 on flash with 2048 byte
- * blocks and 64 bytes oob.
+ * are a few known devices in the wild that make use of this ECC engine
+ * (Linksys LGS328C, LGS352C & Netlink HG323DAC). To keep compatibility with vendor firmware,
+ * new modes can only be added when new data layouts have been analyzed. For now allow BCH6 on
+ * flash with 2048 byte blocks and at least 64 bytes oob. Some vendors make use of
+ * 128 bytes OOB NAND chips (e.g. Macronix MX35LF1G24AD) but only use BCH6 and thus the first
+ * 64 bytes of the OOB area. In this case the engine leaves any extra bytes unused.
*
* This driver aligns with kernel ECC naming conventions. Neverthless a short notice on the
* Realtek naming conventions for the different structures in the OOB area.
@@ -39,7 +41,7 @@
*/
#define RTL_ECC_ALLOWED_PAGE_SIZE 2048
-#define RTL_ECC_ALLOWED_OOB_SIZE 64
+#define RTL_ECC_ALLOWED_MIN_OOB_SIZE 64
#define RTL_ECC_ALLOWED_STRENGTH 6
#define RTL_ECC_BLOCK_SIZE 512
@@ -310,10 +312,10 @@ static int rtl_ecc_check_support(struct nand_device *nand)
struct mtd_info *mtd = nanddev_to_mtd(nand);
struct device *dev = nand->ecc.engine->dev;
- if (mtd->oobsize != RTL_ECC_ALLOWED_OOB_SIZE ||
+ if (mtd->oobsize < RTL_ECC_ALLOWED_MIN_OOB_SIZE ||
mtd->writesize != RTL_ECC_ALLOWED_PAGE_SIZE) {
- dev_err(dev, "only flash geometry data=%d, oob=%d supported\n",
- RTL_ECC_ALLOWED_PAGE_SIZE, RTL_ECC_ALLOWED_OOB_SIZE);
+ dev_err(dev, "only flash geometry data=%d, oob>=%d supported\n",
+ RTL_ECC_ALLOWED_PAGE_SIZE, RTL_ECC_ALLOWED_MIN_OOB_SIZE);
return -EINVAL;
}
diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 65a36d5de742..c4018bc59670 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -837,9 +837,10 @@ static const struct pci_device_id cafe_nand_tbl[] = {
MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
-static int cafe_nand_resume(struct pci_dev *pdev)
+static int cafe_nand_resume(struct device *dev)
{
uint32_t ctrl;
+ struct pci_dev *pdev = to_pci_dev(dev);
struct mtd_info *mtd = pci_get_drvdata(pdev);
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
@@ -877,12 +878,14 @@ static int cafe_nand_resume(struct pci_dev *pdev)
return 0;
}
+static DEFINE_SIMPLE_DEV_PM_OPS(cafe_nand_ops, NULL, cafe_nand_resume);
+
static struct pci_driver cafe_nand_pci_driver = {
.name = "CAFÉ NAND",
.id_table = cafe_nand_tbl,
.probe = cafe_nand_probe,
.remove = cafe_nand_remove,
- .resume = cafe_nand_resume,
+ .driver.pm = &cafe_nand_ops,
};
module_pci_driver(cafe_nand_pci_driver);
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index dd88b22a91bd..fad0334f759d 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -7,6 +7,7 @@
* Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
*/
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -863,7 +864,14 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
/* Fill in fsl_ifc_mtd structure */
mtd->dev.parent = priv->dev;
- nand_set_flash_node(chip, priv->dev->of_node);
+
+ struct device_node *np __free(device_node) =
+ of_get_next_child_with_prefix(priv->dev->of_node, NULL, "nand");
+
+ if (np)
+ nand_set_flash_node(chip, np);
+ else
+ nand_set_flash_node(chip, priv->dev->of_node);
/* fill in nand_chip structure */
/* set up function call table */
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 51f595fbc834..c1f766cb225a 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -5,6 +5,7 @@
* Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
*/
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -2688,7 +2689,15 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
nand_set_controller_data(chip, this);
- nand_set_flash_node(chip, this->pdev->dev.of_node);
+
+ struct device_node *np __free(device_node) =
+ of_get_next_child_with_prefix(this->pdev->dev.of_node, NULL, "nand");
+
+ if (np)
+ nand_set_flash_node(chip, np);
+ else
+ nand_set_flash_node(chip, this->pdev->dev.of_node);
+
chip->legacy.block_markbad = gpmi_block_markbad;
chip->badblock_pattern = &gpmi_bbt_descr;
chip->options |= NAND_NO_SUBPAGE_WRITE;
diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index 8c56b685bf91..4d8b92e7e672 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -4,6 +4,7 @@
* Copyright 2008 Sascha Hauer, kernel@pengutronix.de
*/
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -1714,7 +1715,14 @@ static int mxcnd_probe(struct platform_device *pdev)
this->legacy.chip_delay = 5;
nand_set_controller_data(this, host);
- nand_set_flash_node(this, pdev->dev.of_node);
+
+ struct device_node *np __free(device_node) =
+ of_get_next_child_with_prefix(pdev->dev.of_node, NULL, "nand");
+
+ if (np)
+ nand_set_flash_node(this, np);
+ else
+ nand_set_flash_node(this, pdev->dev.of_node);
host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk))
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 38429363251c..5c8951741855 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -43,6 +43,7 @@
#include <linux/mtd/partitions.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
+#include <linux/cleanup.h>
#include "internals.h"
@@ -4704,16 +4705,16 @@ static void nand_resume(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- mutex_lock(&chip->lock);
- if (chip->suspended) {
- if (chip->ops.resume)
- chip->ops.resume(chip);
- chip->suspended = 0;
- } else {
- pr_err("%s called for a chip which is not in suspended state\n",
- __func__);
+ scoped_guard(mutex, &chip->lock) {
+ if (chip->suspended) {
+ if (chip->ops.resume)
+ chip->ops.resume(chip);
+ chip->suspended = 0;
+ } else {
+ pr_err("%s called for a chip which is not in suspended state\n",
+ __func__);
+ }
}
- mutex_unlock(&chip->lock);
wake_up_all(&chip->resume_wq);
}
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index e66adfcca7cd..02647565c8ba 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -209,9 +209,8 @@
/*
* On A10/A23, this is the size of the NDFC User Data Register, containing the
- * mandatory user data bytes following the ECC for each ECC step.
+ * mandatory user data bytes preceding the ECC for each ECC step.
* Thus, for each ECC step, we need the ECC bytes + USER_DATA_SZ.
- * Those bits are currently unsused, and kept as default value 0xffffffff.
*
* On H6/H616, this size became configurable, from 0 bytes to 32, via the
* USER_DATA_LEN registers.
@@ -249,6 +248,7 @@ struct sunxi_nand_hw_ecc {
* @timing_ctl: TIMING_CTL register value for this NAND chip
* @nsels: number of CS lines required by the NAND chip
* @sels: array of CS lines descriptions
+ * @user_data_bytes: array of user data lengths for all ECC steps
*/
struct sunxi_nand_chip {
struct list_head node;
@@ -257,6 +257,7 @@ struct sunxi_nand_chip {
unsigned long clk_rate;
u32 timing_cfg;
u32 timing_ctl;
+ u8 *user_data_bytes;
int nsels;
struct sunxi_nand_chip_sel sels[] __counted_by(nsels);
};
@@ -272,9 +273,11 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
*
* @has_mdma: Use mbus dma mode, otherwise general dma
* through MBUS on A23/A33 needs extra configuration.
- * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
+ * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chunks
* @has_ecc_clk: If the controller needs an ECC clock.
* @has_mbus_clk: If the controller needs a mbus clock.
+ * @legacy_max_strength:If the maximize strength function was off by 2 bytes
+ * NB: this should not be used in new controllers
* @reg_io_data: I/O data register
* @reg_ecc_err_cnt: ECC error counter register
* @reg_user_data: User data register
@@ -292,7 +295,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
* @nstrengths: Size of @ecc_strengths
* @max_ecc_steps: Maximum supported steps for ECC, this is also the
* number of user data registers
- * @user_data_len_tab: Table of lenghts supported by USER_DATA_LEN register
+ * @user_data_len_tab: Table of lengths supported by USER_DATA_LEN register
* The table index is the value to set in NFC_USER_DATA_LEN
* registers, and the corresponding value is the number of
* bytes to write
@@ -304,6 +307,7 @@ struct sunxi_nfc_caps {
bool has_ecc_block_512;
bool has_ecc_clk;
bool has_mbus_clk;
+ bool legacy_max_strength;
unsigned int reg_io_data;
unsigned int reg_ecc_err_cnt;
unsigned int reg_user_data;
@@ -820,12 +824,50 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
}
+static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step)
+{
+ if (!sunxi_nand->user_data_bytes)
+ return USER_DATA_SZ;
+
+ return sunxi_nand->user_data_bytes[step];
+}
+
static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
- int step, bool bbm, int page)
+ int step, bool bbm, int page,
+ unsigned int user_data_sz)
{
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+ u32 user_data;
- sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)), oob);
+ if (!nfc->caps->reg_user_data_len) {
+ /*
+ * For A10, the user data for step n is in the nth
+ * REG_USER_DATA
+ */
+ user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, step));
+ sunxi_nfc_user_data_to_buf(user_data, oob);
+ } else {
+ /*
+ * For H6 NAND controller, the user data for all steps is
+ * contained in 32 user data registers, but not at a specific
+ * offset for each step, they are just concatenated.
+ */
+ unsigned int user_data_off = 0;
+ unsigned int reg_off;
+ u8 *ptr = oob;
+ unsigned int i;
+
+ for (i = 0; i < step; i++)
+ user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i);
+
+ user_data_off /= 4;
+ for (i = 0; i < user_data_sz / 4; i++, ptr += 4) {
+ reg_off = NFC_REG_USER_DATA(nfc, user_data_off + i);
+ user_data = readl(nfc->regs + reg_off);
+ sunxi_nfc_user_data_to_buf(user_data, ptr);
+ }
+ }
/* De-randomize the Bad Block Marker. */
if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
@@ -884,17 +926,46 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
bool bbm, int page)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
- u8 user_data[USER_DATA_SZ];
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+ unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step);
+ u8 *user_data = NULL;
/* Randomize the Bad Block Marker. */
if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
- memcpy(user_data, oob, sizeof(user_data));
+ user_data = kmalloc(user_data_sz, GFP_KERNEL);
+ memcpy(user_data, oob, user_data_sz);
sunxi_nfc_randomize_bbm(nand, page, user_data);
oob = user_data;
}
- writel(sunxi_nfc_buf_to_user_data(oob),
- nfc->regs + NFC_REG_USER_DATA(nfc, step));
+ if (!nfc->caps->reg_user_data_len) {
+ /*
+ * For A10, the user data for step n is in the nth
+ * REG_USER_DATA
+ */
+ writel(sunxi_nfc_buf_to_user_data(oob),
+ nfc->regs + NFC_REG_USER_DATA(nfc, step));
+ } else {
+ /*
+ * For H6 NAND controller, the user data for all steps is
+ * contained in 32 user data registers, but not at a specific
+ * offset for each step, they are just concatenated.
+ */
+ unsigned int user_data_off = 0;
+ const u8 *ptr = oob;
+ unsigned int i;
+
+ for (i = 0; i < step; i++)
+ user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i);
+
+ user_data_off /= 4;
+ for (i = 0; i < user_data_sz / 4; i++, ptr += 4) {
+ writel(sunxi_nfc_buf_to_user_data(ptr),
+ nfc->regs + NF