summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor6
-rw-r--r--Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml34
-rw-r--r--Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml5
-rw-r--r--Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml32
-rw-r--r--Documentation/devicetree/bindings/mtd/atmel-nand.txt6
-rw-r--r--Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml96
-rw-r--r--Documentation/devicetree/bindings/mtd/denali,nand.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/ingenic,nand.yaml146
-rw-r--r--Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml50
-rw-r--r--Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml20
-rw-r--r--Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml16
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd-physmap.yaml7
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd.yaml24
-rw-r--r--Documentation/devicetree/bindings/mtd/mtk-nand.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-chip.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partition.txt33
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml30
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/partition.yaml5
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/partitions.yaml41
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml38
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml6
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml57
-rw-r--r--Documentation/devicetree/bindings/mtd/qcom,nandc.yaml131
-rw-r--r--Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml47
-rw-r--r--Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml36
-rw-r--r--Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml3
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/mtd/devices/Kconfig8
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/lart.c682
-rw-r--r--drivers/mtd/inftlcore.c2
-rw-r--r--drivers/mtd/lpddr/lpddr2_nvm.c2
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c2
-rw-r--r--drivers/mtd/mtdcore.c55
-rw-r--r--drivers/mtd/mtdoops.c109
-rw-r--r--drivers/mtd/nand/core.c3
-rw-r--r--drivers/mtd/nand/raw/Kconfig6
-rw-r--r--drivers/mtd/nand/raw/cadence-nand-controller.c70
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c12
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_mlc.c46
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_slc.c43
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c4
-rw-r--r--drivers/mtd/nand/raw/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/nand/spi/winbond.c79
-rw-r--r--drivers/mtd/parsers/Kconfig19
-rw-r--r--drivers/mtd/parsers/Makefile1
-rw-r--r--drivers/mtd/parsers/tplink_safeloader.c150
-rw-r--r--drivers/mtd/spi-nor/core.c85
-rw-r--r--drivers/mtd/spi-nor/core.h5
-rw-r--r--drivers/mtd/spi-nor/debugfs.c2
-rw-r--r--drivers/mtd/spi-nor/gigadevice.c24
-rw-r--r--drivers/mtd/spi-nor/issi.c5
-rw-r--r--drivers/mtd/spi-nor/micron-st.c12
-rw-r--r--drivers/mtd/spi-nor/sfdp.c37
-rw-r--r--drivers/mtd/spi-nor/sfdp.h2
-rw-r--r--drivers/mtd/spi-nor/spansion.c61
-rw-r--r--drivers/mtd/spi-nor/sysfs.c20
-rw-r--r--drivers/mtd/spi-nor/winbond.c3
-rw-r--r--include/linux/mtd/nand.h1
-rw-r--r--include/linux/mtd/spi-nor.h3
69 files changed, 1177 insertions, 1280 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
index d76cd3946434..c800621eff95 100644
--- a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
+++ b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
@@ -5,6 +5,9 @@ Contact: linux-mtd@lists.infradead.org
Description: (RO) The JEDEC ID of the SPI NOR flash as reported by the
flash device.
+ The attribute is not present if the flash doesn't support
+ the "Read JEDEC ID" command (9Fh). This is the case for
+ non-JEDEC compliant flashes.
What: /sys/bus/spi/devices/.../spi-nor/manufacturer
Date: April 2021
@@ -12,6 +15,9 @@ KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) Manufacturer of the SPI NOR flash.
+ The attribute is not present if the flash device isn't
+ known to the kernel and is only probed by its SFDP
+ tables.
What: /sys/bus/spi/devices/.../spi-nor/partname
Date: April 2021
diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
index 4741864da48e..e7ec0c59bca6 100644
--- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
@@ -14,9 +14,6 @@ maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
- "#address-cells": true
- "#size-cells": true
-
compatible:
enum:
- allwinner,sun4i-a10-nand
@@ -49,12 +46,8 @@ properties:
dma-names:
const: rxtx
- pinctrl-names: true
-
patternProperties:
- "^pinctrl-[0-9]+$": true
-
- "^nand@[a-f0-9]+$":
+ "^nand@[a-f0-9]$":
type: object
properties:
reg:
@@ -91,6 +84,29 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/sun6i-rtc.h>
+ #include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
+ #include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
+
+ nand-controller@1c03000 {
+ compatible = "allwinner,sun8i-a23-nand-controller";
+ reg = <0x01c03000 0x1000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_NAND>;
+ reset-names = "ahb";
+ dmas = <&dma 5>;
+ dma-names = "rxtx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins &nand_cs0_pin &nand_rb0_pin>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
...
diff --git a/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
index f013fb976d95..d028269cdbaa 100644
--- a/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
@@ -35,9 +35,6 @@ properties:
interrupts:
maxItems: 1
- "#address-cells": true
- "#size-cells": true
-
required:
- compatible
- reg
@@ -45,7 +42,7 @@ required:
- clock-names
- interrupts
-additionalProperties: true
+unevaluatedProperties: true
examples:
- |
diff --git a/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml b/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
index 023f3ef0fa13..e552875040e2 100644
--- a/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
+++ b/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
@@ -34,20 +34,20 @@ unevaluatedProperties: false
examples:
- |
smcc: memory-controller@e000e000 {
- compatible = "arm,pl353-smc-r2p1", "arm,primecell";
- reg = <0xe000e000 0x0001000>;
- clock-names = "memclk", "apb_pclk";
- clocks = <&clkc 11>, <&clkc 44>;
- ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
- 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
- 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
- #address-cells = <2>;
- #size-cells = <1>;
-
- nfc0: nand-controller@0,0 {
- compatible = "arm,pl353-nand-r2p1";
- reg = <0 0 0x1000000>;
- #address-cells = <1>;
- #size-cells = <0>;
- };
+ compatible = "arm,pl353-smc-r2p1", "arm,primecell";
+ reg = <0xe000e000 0x0001000>;
+ clock-names = "memclk", "apb_pclk";
+ clocks = <&clkc 11>, <&clkc 44>;
+ ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
+ 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
+ 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ nfc0: nand-controller@0,0 {
+ compatible = "arm,pl353-nand-r2p1";
+ reg = <0 0 0x1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index 3aa297c97ab6..50645828ac20 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -45,10 +45,8 @@ Optional properties:
- atmel,rb: an integer identifying the native Ready/Busy pin. Only meaningful
on sama5 SoCs.
-All generic properties described in
-Documentation/devicetree/bindings/mtd/{common,nand}.txt also apply to the NAND
-device node, and NAND partitions should be defined under the NAND node as
-described in Documentation/devicetree/bindings/mtd/partition.txt.
+All generic properties are described in the generic yaml files under
+Documentation/devicetree/bindings/mtd/.
* ECC engine (PMECC) bindings:
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
index dd5a64969e37..1571024aa119 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
@@ -86,15 +86,15 @@ properties:
minItems: 1
items:
- description: NAND CTLRDY interrupt
- - description: FLASH_DMA_DONE if flash DMA is available
- - description: FLASH_EDU_DONE if EDU is available
+ - description: FLASH_DMA_DONE (if flash DMA is available) or FLASH_EDU_DONE (if EDU is available)
interrupt-names:
minItems: 1
items:
- const: nand_ctlrdy
- - const: flash_dma_done
- - const: flash_edu_done
+ - enum:
+ - flash_dma_done
+ - flash_edu_done
clocks:
maxItems: 1
@@ -173,6 +173,13 @@ allOf:
- const: nand
- const: iproc-idm
- const: iproc-ext
+ - if:
+ properties:
+ interrupts:
+ minItems: 2
+ then:
+ required:
+ - interrupt-names
unevaluatedProperties: false
@@ -184,51 +191,52 @@ required:
examples:
- |
nand-controller@f0442800 {
- compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand";
- reg = <0xf0442800 0x600>,
- <0xf0443000 0x100>;
- reg-names = "nand", "flash-dma";
- interrupt-parent = <&hif_intr2_intc>;
- interrupts = <24>, <4>;
+ compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand";
+ reg = <0xf0442800 0x600>,
+ <0xf0443000 0x100>;
+ reg-names = "nand", "flash-dma";
+ interrupt-parent = <&hif_intr2_intc>;
+ interrupts = <24>, <4>;
+ interrupt-names = "nand_ctlrdy", "flash_dma_done";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@1 {
+ compatible = "brcm,nandcs";
+ reg = <1>; // Chip select 1
+ nand-on-flash-bbt;
+ nand-ecc-strength = <12>;
+ nand-ecc-step-size = <512>;
#address-cells = <1>;
- #size-cells = <0>;
-
- nand@1 {
- compatible = "brcm,nandcs";
- reg = <1>; // Chip select 1
- nand-on-flash-bbt;
- nand-ecc-strength = <12>;
- nand-ecc-step-size = <512>;
-
- #address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <1>;
+ };
};
- |
nand-controller@10000200 {
- compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
- "brcm,brcmnand-v4.0", "brcm,brcmnand";
- reg = <0x10000200 0x180>,
- <0x100000b0 0x10>,
- <0x10000600 0x200>;
- reg-names = "nand", "nand-int-base", "nand-cache";
- interrupt-parent = <&periph_intc>;
- interrupts = <50>;
- clocks = <&periph_clk 20>;
- clock-names = "nand";
+ compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
+ "brcm,brcmnand-v4.0", "brcm,brcmnand";
+ reg = <0x10000200 0x180>,
+ <0x100000b0 0x10>,
+ <0x10000600 0x200>;
+ reg-names = "nand", "nand-int-base", "nand-cache";
+ interrupt-parent = <&periph_intc>;
+ interrupts = <50>;
+ clocks = <&periph_clk 20>;
+ clock-names = "nand";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ compatible = "brcm,nandcs";
+ reg = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <1>;
+ nand-ecc-step-size = <512>;
#address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- compatible = "brcm,nandcs";
- reg = <0>;
- nand-on-flash-bbt;
- nand-ecc-strength = <1>;
- nand-ecc-step-size = <512>;
-
- #address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <1>;
+ };
};
diff --git a/Documentation/devicetree/bindings/mtd/denali,nand.yaml b/Documentation/devicetree/bindings/mtd/denali,nand.yaml
index 1307ed7e7fc6..0be83ad42970 100644
--- a/Documentation/devicetree/bindings/mtd/denali,nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/denali,nand.yaml
@@ -145,6 +145,6 @@ examples:
#size-cells = <0>;
nand@0 {
- reg = <0>;
+ reg = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
index 8c272c842bfd..a811a512ecc5 100644
--- a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
@@ -32,9 +32,9 @@ properties:
partitions:
type: object
+ deprecated: true
description:
Node containing description of fixed partitions.
- See Documentation/devicetree/bindings/mtd/partition.txt
patternProperties:
"^nand@[a-f0-9]$":
@@ -58,78 +58,78 @@ examples:
- |
#include <dt-bindings/clock/ingenic,jz4780-cgu.h>
memory-controller@13410000 {
- compatible = "ingenic,jz4780-nemc";
- reg = <0x13410000 0x10000>;
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <1 0 0x1b000000 0x1000000>,
- <2 0 0x1a000000 0x1000000>,
- <3 0 0x19000000 0x1000000>,
- <4 0 0x18000000 0x1000000>,
- <5 0 0x17000000 0x1000000>,
- <6 0 0x16000000 0x1000000>;
-
- clocks = <&cgu JZ4780_CLK_NEMC>;
-
- nand-controller@1 {
- compatible = "ingenic,jz4780-nand";
- reg = <1 0 0x1000000>;
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- ecc-engine = <&bch>;
-
- ingenic,nemc-tAS = <10>;
- ingenic,nemc-tAH = <5>;
- ingenic,nemc-tBP = <10>;
- ingenic,nemc-tAW = <15>;
- ingenic,nemc-tSTRV = <100>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pins_nemc>;
-
- nand@1 {
- reg = <1>;
-
- nand-ecc-step-size = <1024>;
- nand-ecc-strength = <24>;
- nand-ecc-mode = "hw";
- nand-on-flash-bbt;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pins_nemc_cs1>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <2>;
- #size-cells = <2>;
-
- partition@0 {
- label = "u-boot-spl";
- reg = <0x0 0x0 0x0 0x800000>;
+ compatible = "ingenic,jz4780-nemc";
+ reg = <0x13410000 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0x1b000000 0x1000000>,
+ <2 0 0x1a000000 0x1000000>,
+ <3 0 0x19000000 0x1000000>,
+ <4 0 0x18000000 0x1000000>,
+ <5 0 0x17000000 0x1000000>,
+ <6 0 0x16000000 0x1000000>;
+
+ clocks = <&cgu JZ4780_CLK_NEMC>;
+
+ nand-controller@1 {
+ compatible = "ingenic,jz4780-nand";
+ reg = <1 0 0x1000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ecc-engine = <&bch>;
+
+ ingenic,nemc-tAS = <10>;
+ ingenic,nemc-tAH = <5>;
+ ingenic,nemc-tBP = <10>;
+ ingenic,nemc-tAW = <15>;
+ ingenic,nemc-tSTRV = <100>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc>;
+
+ nand@1 {
+ reg = <1>;
+
+ nand-ecc-step-size = <1024>;
+ nand-ecc-strength = <24>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc_cs1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ partition@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x0 0x0 0x800000>;
+ };
+
+ partition@800000 {
+ label = "u-boot";
+ reg = <0x0 0x800000 0x0 0x200000>;
+ };
+
+ partition@a00000 {
+ label = "u-boot-env";
+ reg = <0x0 0xa00000 0x0 0x200000>;
+ };
+
+ partition@c00000 {
+ label = "boot";
+ reg = <0x0 0xc00000 0x0 0x4000000>;
+ };
+
+ partition@4c00000 {
+ label = "system";
+ reg = <0x0 0x4c00000 0x1 0xfb400000>;
+ };
+ };
};
-
- partition@800000 {
- label = "u-boot";
- reg = <0x0 0x800000 0x0 0x200000>;
- };
-
- partition@a00000 {
- label = "u-boot-env";
- reg = <0x0 0xa00000 0x0 0x200000>;
- };
-
- partition@c00000 {
- label = "boot";
- reg = <0x0 0xc00000 0x0 0x4000000>;
- };
-
- partition@4c00000 {
- label = "system";
- reg = <0x0 0x4c00000 0x1 0xfb400000>;
- };
- };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
index 741c66ee06c3..8c62c7d3d0cd 100644
--- a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
+++ b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
@@ -39,14 +39,8 @@ properties:
- const: tx
- const: rx
- "#address-cells":
- const: 1
-
- "#size-cells":
- const: 0
-
patternProperties:
- "^nand@[a-f0-9]+$":
+ "^nand@[a-f0-9]$":
type: object
properties:
reg:
@@ -67,33 +61,31 @@ required:
- clocks
- dmas
- dma-names
- - "#address-cells"
- - "#size-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
nand-controller@e0f00000 {
- compatible = "intel,lgm-ebunand";
- reg = <0xe0f00000 0x100>,
- <0xe1000000 0x300>,
- <0xe1400000 0x8000>,
- <0xe1c00000 0x1000>,
- <0x17400000 0x4>,
- <0x17c00000 0x4>;
- reg-names = "ebunand", "hsnand", "nand_cs0", "nand_cs1",
- "addr_sel0", "addr_sel1";
- clocks = <&cgu0 125>;
- dmas = <&dma0 8>, <&dma0 9>;
- dma-names = "tx", "rx";
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-ecc-mode = "hw";
- };
+ compatible = "intel,lgm-ebunand";
+ reg = <0xe0f00000 0x100>,
+ <0xe1000000 0x300>,
+ <0xe1400000 0x8000>,
+ <0xe1c00000 0x1000>,
+ <0x17400000 0x4>,
+ <0x17c00000 0x4>;
+ reg-names = "ebunand", "hsnand", "nand_cs0", "nand_cs1",
+ "addr_sel0", "addr_sel1";
+ clocks = <&cgu0 125>;
+ dmas = <&dma0 8>, <&dma0 9>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-ecc-mode = "hw";
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
index 7149784a36ac..3fe981b14e2c 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
@@ -70,24 +70,17 @@ properties:
be used on such systems, to denote the absence of a reliable reset
mechanism.
- partitions:
- type: object
-
- '#address-cells': true
- '#size-cells': true
-
-patternProperties:
- # Note: use 'partitions' node for new users
- '^partition@':
- type: object
-
- "^otp(-[0-9]+)?$":
- type: object
+ reset-gpios:
+ description:
+ A GPIO line connected to the RESET (active low) signal of the device.
+ If "broken-flash-reset" is present then having this property does not
+ make any difference.
unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
@@ -97,6 +90,7 @@ examples:
reg = <0>;
spi-max-frequency = <40000000>;
m25p,fast-read;
+ reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
};
};
...
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
index 6d60bc3063f5..64c06aa05ac7 100644
--- a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
@@ -19,7 +19,7 @@ accuracy:)
- nxp,wr_low: WR_LOW
Optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
index d94edc0fc554..39f17630a301 100644
--- a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
@@ -20,7 +20,7 @@ clock speed:)
- nxp,rsetup: Read setup time (R_SETUP)
Optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
diff --git a/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml b/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
index 8cc2a7ceb5fb..ea9450fe7c9f 100644
--- a/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
+++ b/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
@@ -34,13 +34,13 @@ unevaluatedProperties: false
examples:
- |
spi {
- #address-cells = <1>;
- #size-cells = <0>;
-
- eeram@0 {
- compatible = "microchip,48l640";
- reg = <0>;
- spi-max-frequency = <20000000>;
- };
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeram@0 {
+ compatible = "microchip,48l640";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
index 82eb4e0f453b..5df94953c34e 100644
--- a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
@@ -13,6 +13,9 @@ description: |
Flash chips (Memory Technology Devices) are often used for solid state
file systems on embedded devices.
+allOf:
+ - $ref: "mtd.yaml#"
+
properties:
compatible:
oneOf:
@@ -121,10 +124,6 @@ properties:
big-endian: true
little-endian: true
-patternProperties:
- '@[0-9a-f]+$':
- $ref: partitions/partition.yaml
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mtd/mtd.yaml b/Documentation/devicetree/bindings/mtd/mtd.yaml
index 3498e485679b..78da129e9985 100644
--- a/Documentation/devicetree/bindings/mtd/mtd.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd.yaml
@@ -12,7 +12,7 @@ maintainers:
properties:
$nodename:
- pattern: "^flash(@.*)?$"
+ pattern: "^(flash|.*sram)(@.*)?$"
label:
description:
@@ -21,9 +21,28 @@ properties:
based name) in order to ease flash device identification and/or
describe what they are used for.
+ '#address-cells':
+ deprecated: true
+
+ '#size-cells':
+ deprecated: true
+
+ partitions:
+ $ref: /schemas/mtd/partitions/partitions.yaml
+
+ required:
+ - compatible
+
patternProperties:
+ "@[0-9a-f]+$":
+ $ref: partitions/partition.yaml
+ deprecated: true
+
+ "^partition@[0-9a-f]+":
+ $ref: partitions/partition.yaml
+ deprecated: true
+
"^otp(-[0-9]+)?$":
- type: object
$ref: ../nvmem/nvmem.yaml#
description: |
@@ -40,6 +59,7 @@ patternProperties:
required:
- compatible
+# This is a generic file other binding inherit from
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
index 4d3ec5e4ff8a..839ea2f93d04 100644
--- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
@@ -131,7 +131,7 @@ Example:
};
NAND chip optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
nand@0 {
diff --git a/Documentation/devicetree/bindings/mtd/nand-chip.yaml b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
index 97ac3a3fbb52..6e2dc025d694 100644
--- a/Documentation/devicetree/bindings/mtd/nand-chip.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
@@ -9,6 +9,9 @@ title: NAND Chip and NAND Controller Generic Binding
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
+allOf:
+ - $ref: "mtd.yaml#"
+
description: |
This file covers the generic description of a NAND chip. It implies that the
bus interface should not be taken into account: both raw NAND devices and
@@ -67,4 +70,5 @@ properties:
required:
- reg
+# This file can be referenced by more specific devices (like spi-nands)
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index 359a015d4e5a..220aa2c8c0b5 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -51,7 +51,6 @@ properties:
patternProperties:
"^nand@[a-f0-9]$":
- type: object
$ref: "nand-chip.yaml#"
properties:
@@ -130,6 +129,7 @@ required:
- "#address-cells"
- "#size-cells"
+# This is a generic file other binding inherit from and extend
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
deleted file mode 100644
index ead90e8274d6..000000000000
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Flash partitions in device tree
-===============================
-
-Flash devices can be partitioned into one or more functional ranges (e.g. "boot
-code", "nvram", "kernel").
-
-Different devices may be partitioned in a different ways. Some may use a fixed
-flash layout set at production time. Some may use on-flash table that describes
-the geometry and naming/purpose of each functional region. It is also possible
-to see these methods mixed.
-
-To assist system software in locating partitions, we allow describing which
-method is used for a given flash device. To describe the method there should be
-a subnode of the flash device that is named 'partitions'. It must have a
-'compatible' property, which is used to identify the method to use.
-
-When a single partition is represented with a DT node (it depends on a used
-format) it may also be described using above rules ('compatible' and optionally
-some extra properties / subnodes). It allows describing more complex,
-hierarchical (multi-level) layouts and should be used if there is some
-significant relation between partitions or some partition internally uses
-another partitioning method.
-
-Available bindings are listed in the "partitions" subdirectory.
-
-
-Deprecated: partitions defined in flash node
-============================================
-
-For backwards compatibility partitions as direct subnodes of the flash device are
-supported. This use is discouraged.
-NOTE: also for backwards compatibility, direct subnodes that have a compatible
-string are not considered partitions, as they may be used for other bindings.
diff --git a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
index 76c88027b6d2..97618847ee35 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
@@ -9,6 +9,8 @@ title: ARM Firmware Suite (AFS) Partitions
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
+select: false
+
description: |
The ARM Firmware Suite is a flash partitioning system found on the
ARM reference designs: Integrator AP, Integrator CP, Versatile AB,
diff --git a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
index 7b113e5e3421..5bbb1c01ddee 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
@@ -17,6 +17,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: brcm,bcm4908-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
index 3484e06d6bcb..939e7b50db22 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
@@ -35,6 +35,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: brcm,bcm947xx-cfe-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
index ad3ccd250802..331e564f29dc 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
@@ -31,24 +31,17 @@ properties:
patternProperties:
"@[0-9a-f]+$":
- allOf:
- - $ref: "partition.yaml#"
- - if:
- properties:
- compatible:
- contains:
- const: sercomm,sc-partitions
- then:
- properties:
- sercomm,scpart-id:
- description: Partition id in Sercomm partition map. Mtd
- parser uses this id to find a record in the partition map
- containing offset and size of the current partition. The
- values from partition map overrides partition offset and
- size defined in reg property of the dts. Frequently these
- values are the same, but may differ if device has bad
- eraseblocks on a flash.
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: partition.yaml#
+
+ properties:
+ sercomm,scpart-id:
+ description: Partition id in Sercomm partition map. Mtd parser
+ uses this id to find a record in the partition map containing
+ offset and size of the current partition. The values from
+ partition map overrides partition offset and size defined in
+ reg property of the dts. Frequently these values are the same,
+ but may differ if device has bad eraseblocks on a flash.
+ $ref: /schemas/types.yaml#/definitions/uint32
required:
- "#address-cells"
@@ -84,6 +77,7 @@ examples:
partition@0 {
label = "filesystem";
reg = <0x00000000 0x1 0x00000000>;
+ linux,rootfs;
};
};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
index 99249cdfbfb3..213858f60375 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
@@ -18,6 +18,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: linksys,ns-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
index 5cdd2efa9132..5474d63268dc 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
@@ -17,6 +17,7 @@ maintainers:
- Ansuel Smith <ansuelsmth@gmail.com>
allOf:
+ - $ref: /schemas/mtd/partitions/partition.yaml#
- $ref: /schemas/nvmem/nvmem.yaml#
properties:
@@ -26,7 +27,7 @@ properties:
required:
- compatible
-additionalProperties: true
+unevaluatedProperties: false
examples:
- |
@@ -84,7 +85,6 @@ examples:
compatible = "nvmem-cells";
label = "calibration";
reg = <0xf00000 0x100000>;
- ranges = <0 0xf00000 0x100000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
index f1a02d840b12..cdffbb9cedc2 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
@@ -52,6 +52,10 @@ properties:
immune to paired-pages corruptions
type: boolean
+ linux,rootfs:
+ description: Marks partition that contains root filesystem to mount and boot
+ user space from
+
if:
not:
required: [ reg ]
@@ -60,4 +64,5 @@ then:
$nodename:
pattern: '^partition-.*$'
+# This is a generic file other binding inherit from and extend
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml
new file mode 100644
index 000000000000..9aca4e6c6047
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/partitions/partitions.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Partitions
+
+description: |
+ This binding is generic and describes the content of the partitions container
+ node. All partition parsers must be referenced here.
+
+maintainers:
+ - Miquel Raynal <miquel.raynal@bootlin.com>
+
+oneOf:
+ - $ref: arm,arm-firmware-suite.yaml
+ - $ref: brcm,bcm4908-partitions.yaml
+ - $ref: brcm,bcm947xx-cfe-partitions.yaml
+ - $ref: fixed-partitions.yaml
+ - $ref: linksys,ns-partitions.yaml
+ - $ref: qcom,smem-part.yaml
+ - $ref: redboot-fis.yaml
+
+properties:
+ compatible: true
+
+ '#address-cells':
+ enum: [1, 2]
+
+ '#size-cells':
+ enum: [1, 2]
+
+patternProperties:
+ "partition(-.+|@[0-9a-f]+)":
+ $ref: partition.yaml
+
+required:
+ - compatible
+
+unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml b/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
index dc07909af023..61d12bda356e 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
@@ -15,13 +15,15 @@ description: |
varies between partition table revisions. V3 supports maximum 16 partitions
and V4 supports 48 partitions.
+select: false
+
properties:
compatible:
const: qcom,smem-part
patternProperties:
"^partition-[0-9a-z]+$":
- $ref: partition.yaml#
+ $ref: nvmem-cells.yaml
required:
- compatible
@@ -39,22 +41,22 @@ examples:
- |
/* Example declaring dynamic partition */
flash {
- partitions {
- compatible = "qcom,smem-part";
-
- partition-art {
- compatible = "nvmem-cells";
- #address-cells = <1>;
- #size-cells = <1>;
- label = "0:art";
-
- macaddr_art_0: macaddr@0 {
- reg = <0x0 0x6>;
- };
-
- macaddr_art_6: macaddr@6 {
- reg = <0x6 0x6>;
- };
+ partitions {
+ compatible = "qcom,smem-part";
+
+ partition-art {
+ compatible = "nvmem-cells";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "0:art";
+
+ macaddr_art_0: macaddr@0 {
+ reg = <0x0 0x6>;
+ };
+
+ macaddr_art_6: macaddr@6 {
+ reg = <0x6 0x6>;
+ };
+ };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
index fee8d81b5276..ba7445cd69e8 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
@@ -16,6 +16,8 @@ description: The FLASH Image System (FIS) directory is a flash description
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
+select: false
+
properties:
compatible:
const: redboot-fis
@@ -26,6 +28,10 @@ properties:
device. On a flash memory with 32KB eraseblocks, 0 means the first
eraseblock at 0x00000000, 1 means the second eraseblock at 0x00008000 and so on.
+ '#address-cells': false
+
+ '#size-cells': false
+
required:
- compatible
- fis-index-block
diff --git a/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml
new file mode 100644
index 000000000000..a24bbaac3a90
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/partitions/tplink,safeloader-partitions.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TP-Link SafeLoader partitions
+
+description: |
+ TP-Link home routers store various data on flash (e.g. bootloader,
+ flash layout, firmware, product info, configuration, calibration
+ data). That requires flash partitioning.
+
+ Flash space layout of TP-Link devices is stored on flash itself using
+ a custom ASCII-based format. That format was first found in TP-Link
+ devices with a custom SafeLoader bootloader. Later it was adapted to
+ CFE and U-Boot bootloaders.
+
+ Partitions specified in partitions table cover whole flash space. Some
+ contain static data that shouldn't get modified (device's MAC or WiFi
+ calibration data). Others are semi-static (like kernel). Finally some
+ partitions contain fully changeable content (like rootfs).
+
+ This binding describes partitioning method and defines offset of ASCII
+ based partitions table. That offset is picked at manufacturing process
+ and doesn't change.
+
+maintainers:
+ - Rafał Miłecki <rafal@milecki.pl>
+
+properties:
+ compatible:
+ const: tplink,safeloader-partitions
+
+ partitions-table-offset:
+ description: Flash offset of partitions table
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+patternProperties:
+ "^partition-.*$":
+ $ref: partition.yaml#
+
+required:
+ - partitions-table-offset
+
+additionalProperties: false
+
+examples:
+ - |
+ partitions {
+ compatible = "tplink,safeloader-partitions";
+ partitions-table-offset = <0x100000>;
+
+ partition-file-system {
+ linux,rootfs;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
index 482a2c068740..07024ee45951 100644
--- a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
+++ b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
@@ -31,9 +31,6 @@ properties:
- const: core
- const: aon
- "#address-cells": true
- "#size-cells": true
-
patternProperties:
"^nand@[a-f0-9]$":
type: object
@@ -139,85 +136,85 @@ examples:
- |
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
nand-controller@1ac00000 {
- compatible = "qcom,ipq806x-nand";
- reg = <0x1ac00000 0x800>;
+ compatible = "qcom,ipq806x-nand";
+ reg = <0x1ac00000 0x800>;
- clocks = <&gcc EBI2_CLK>,
- <&gcc EBI2_AON_CLK>;
- clock-names = "core", "aon";
+ clocks = <&gcc EBI2_CLK>,
+ <&gcc EBI2_AON_CLK>;
+ clock-names = "core", "aon";
- dmas = <&adm_dma 3>;
- dma-names = "rxtx";
- qcom,cmd-crci = <15>;
- qcom,data-crci = <3>;
+ dmas = <&adm_dma 3>;
+ dma-names = "rxtx";
+ qcom,cmd-crci = <15>;
+ qcom,data-crci = <3>;
- #address-cells = <1>;
- #size-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- nand@0 {
- reg = <0>;
+ nand@0 {
+ reg = <0>;
- nand-ecc-strength = <4>;
- nand-bus-width = <8>;
+ nand-ecc-strength = <4>;
+ nand-bus-width = <8>;
- qcom,boot-partitions = <0x0 0x58a0000>;
+ qcom,boot-partitions = <0x0 0x58a0000>;
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
- partition@0 {
- label = "boot-nand";
- reg = <0 0x58a0000>;
- };
+ partition@0 {
+ label = "boot-nand";
+ reg = <0 0x58a0000>;
+ };
- partition@58a0000 {
- label = "fs-nand";
- reg = <0x58a0000 0x4000000>;
- };
+ partition@58a0000 {
+ label = "fs-nand";
+ reg = <0x58a0000 0x4000000>;
+ };
+ };
};
- };
};
#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
nand-controller@79b0000 {
- compatible = "qcom,ipq4019-nand";
- reg = <0x79b0000 0x1000>;
-
- clocks = <&gcc GCC_QPIC_CLK>,
- <&gcc GCC_QPIC_AHB_CLK>;
- clock-names = "core", "aon";
-
- dmas = <&qpicbam 0>,
- <&qpicbam 1>,
- <&qpicbam 2>;
- dma-names = "tx", "rx", "cmd";
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-ecc-strength = <4>;
- nand-bus-width = <8>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "boot-nand";
- reg = <0 0x58a0000>;
- };
-
- partition@58a0000 {
- label = "fs-nand";
- reg = <0x58a0000 0x4000000>;
- };
+ compatible = "qcom,ipq4019-nand";
+ reg = <0x79b0000 0x1000>;
+
+ clocks = <&gcc GCC_QPIC_CLK>,
+ <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "core", "aon";
+
+ dmas = <&qpicbam 0>,
+ <&qpicbam 1>,
+ <&qpicbam 2>;
+ dma-names = "tx", "rx", "cmd";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-ecc-strength = <4>;
+ nand-bus-width = <8>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "boot-nand";
+ reg = <0 0x58a0000>;
+ };
+
+ partition@58a0000 {
+ label = "fs-nand";
+ reg = <0x58a0000 0x4000000>;
+ };
+ };
};
- };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
index d681a4676f06..566f330851f7 100644
--- a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
@@ -19,7 +19,9 @@ properties:
- const: rockchip,rk2928-nfc
- const: rockchip,rv1108-nfc
- items:
- - const: rockchip,rk3036-nfc
+ - enum:
+ - rockchip,rk3036-nfc
+ - rockchip,rk3128-nfc
- const: rockchip,rk2928-nfc
- items:
- const: rockchip,rk3308-nfc
diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
index eab8ea3da1fa..8cbfa1504a0f 100644
--- a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
@@ -101,31 +101,32 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
+
nand-controller@58002000 {
- compatible = "st,stm32mp15-fmc2";
- reg = <0x58002000 0x1000>,
- <0x80000000 0x1000>,
- <0x88010000 0x1000>,
- <0x88020000 0x1000>,
- <0x81000000 0x1000>,
- <0x89010000 0x1000>,
- <0x89020000 0x1000>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
- <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
- <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
- dma-names = "tx", "rx", "ecc";
- clocks = <&rcc FMC_K>;
- resets = <&rcc FMC_R>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-on-flash-bbt;
+ compatible = "st,stm32mp15-fmc2";
+ reg = <0x58002000 0x1000>,
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+ <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+ dma-names = "tx", "rx", "ecc";
+ clocks = <&rcc FMC_K>;
+ resets = <&rcc FMC_R>;
#address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
index 30b458c41cac..4774c92e7fc4 100644
--- a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
+++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
@@ -44,26 +44,26 @@ additionalProperties: false
examples:
- |
bus {
- #address-cells = <2>;
- #size-cells = <2>;
-
- hbmc: memory-controller@47034000 {
- compatible = "ti,am654-hbmc";
- reg = <0x0 0x47034000 0x0 0x100>,
- <0x5 0x00000000 0x1 0x0000000>;
- ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */
- <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */
- clocks = <&k3_clks 102 0>;
#address-cells = <2>;
- #size-cells = <1>;
- power-domains = <&k3_pds 55>;
- mux-controls = <&hbmc_mux 0>;
+ #size-cells = <2>;
- flash@0,0 {
- compatible = "cypress,hyperflash", "cfi-flash";
- reg = <0x0 0x0 0x4000000>;
- #address-cells = <1>;
+ hbmc: memory-controller@47034000 {
+ compatible = "ti,am654-hbmc";
+ reg = <0x0 0x47034000 0x0 0x100>,
+ <0x5 0x00000000 0x1 0x0000000>;
+ ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */
+ <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */
+ clocks = <&k3_clks 102 0>;
+ #address-cells = <2>;
#size-cells = <1>;
+ power-domains = <&k3_pds 55>;
+ mux-controls = <&hbmc_mux 0>;
+
+ flash@0,0 {
+ compatible = "cypress,hyperflash", "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
index a953f7397c40..8a79ad300216 100644
--- a/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
+++ b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
@@ -15,6 +15,9 @@ description:
as child nodes of the GPMC controller.
properties:
+ $nodename:
+ pattern: "^onenand@[0-9],[0,9]$"
+
compatible:
const: ti,omap2-onenand
diff --git a/MAINTAINERS b/MAINTAINERS
index 6d766c5fb2cc..de46dc69922a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13464,7 +13464,7 @@ MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS
M: Liang Yang <liang.yang@amlogic.com>
L: linux-mtd@lists.infradead.org
S: Maintained
-F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
+F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml
F: drivers/mtd/nand/raw/meson_*
MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 79cb981ececc..ff2f9e55ef28 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -136,14 +136,6 @@ config MTD_PHRAM
doesn't have access to, memory beyond the mem=xxx limit, nvram,
memory on the video card, etc...
-config MTD_LART
- tristate "28F160xx flash driver for LART"
- depends on SA1100_LART
- help
- This enables the flash driver for LART. Please note that you do
- not need any mapping/chip driver for LART. This one does it all
- for you, so go disable all of those if you enabled some of them (:
-
config MTD_MTDRAM
tristate "Test driver using RAM"
help
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 0362cf6bdc67..d11eb2b8b6f8 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MTD_PHRAM) += phram.o
obj-$(CONFIG_MTD_PMC551) += pmc551.o
obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
-obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
deleted file mode 100644
index aecd441e4183..000000000000
--- a/drivers/mtd/devices/lart.c
+++ /dev/null
@@ -1,682 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-/*
- * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
- *
- * Author: Abraham vd Merwe <abraham@2d3d.co.za>
- *
- * Copyright (c) 2001, 2d3D, Inc.
- *
- * References:
- *
- * [1] 3 Volt Fast Boot Block Flash Memory" Intel Datasheet
- * - Order Number: 290644-005
- * - January 2000
- *
- * [2] MTD internal API documentation
- * - http://www.linux-mtd.infradead.org/
- *
- * Limitations:
- *
- * Even though this driver is written for 3 Volt Fast Boot
- * Block Flash Memory, it is rather specific to LART. With
- * Minor modifications, notably the without data/address line
- * mangling and different bus settings, etc. it should be
- * trivial to adapt to other platforms.
- *
- * If somebody would sponsor me a different board, I'll
- * adapt the driver (:
- */
-
-/* debugging */
-//#define LART_DEBUG
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#ifndef CONFIG_SA1100_LART
-#error This is for LART architecture only
-#endif
-
-static char module_name[] = "lart";
-
-/*
- * These values is specific to 28Fxxxx3 flash memory.
- * See section 2.3.1 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
- */
-#define FLASH_BLOCKSIZE_PARAM (4096 * BUSWIDTH)
-#define FLASH_NUMBLOCKS_16m_PARAM 8
-#define FLASH_NUMBLOCKS_8m_PARAM 8
-
-/*
- * These values is specific to 28Fxxxx3 flash memory.
- * See section 2.3.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
- */
-#define FLASH_BLOCKSIZE_MAIN (32768 * BUSWIDTH)
-#define FLASH_NUMBLOCKS_16m_MAIN 31
-#define FLASH_NUMBLOCKS_8m_MAIN 15
-
-/*
- * These values are specific to LART
- */
-
-/* general */
-#define BUSWIDTH 4 /* don't change this - a lot of the code _will_ break if you change this */
-#define FLASH_OFFSET 0xe8000000 /* see linux/arch/arm/mach-sa1100/lart.c */
-
-/* blob */
-#define NUM_BLOB_BLOCKS FLASH_NUMBLOCKS_16m_PARAM
-#define PART_BLOB_START 0x00000000
-#define PART_BLOB_LEN (NUM_BLOB_BLOCKS * FLASH_BLOCKSIZE_PARAM)
-
-/* kernel */
-#define NUM_KERNEL_BLOCKS 7
-#define PART_KERNEL_START (PART_BLOB_START + PART_BLOB_LEN)
-#define PART_KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE_MAIN)
-
-/* initial ramdisk */
-#define NUM_INITRD_BLOCKS 24
-#define PART_INITRD_START (PART_KERNEL_START + PART_KERNEL_LEN)
-#define PART_INITRD_LEN (NUM_INITRD_BLOCKS * FLASH_BLOCKSIZE_MAIN)
-
-/*
- * See section 4.0 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
- */
-#define READ_ARRAY 0x00FF00FF /* Read Array/Reset */
-#define READ_ID_CODES 0x00900090 /* Read Identifier Codes */
-#define ERASE_SETUP 0x00200020 /* Block Erase */
-#define ERASE_CONFIRM 0x00D000D0 /* Block Erase and Program Resume */
-#define PGM_SETUP 0x00400040 /* Program */
-#define STATUS_READ 0x00700070 /* Read Status Register */
-#define STATUS_CLEAR 0x00500050 /* Clear Status Register */
-#define STATUS_BUSY 0x00800080 /* Write State Machine Status (WSMS) */
-#define STATUS_ERASE_ERR 0x00200020 /* Erase Status (ES) */
-#define STATUS_PGM_ERR 0x00100010 /* Program Status (PS) */
-
-/*
- * See section 4.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
- */
-#define FLASH_MANUFACTURER 0x00890089
-#define FLASH_DEVICE_8mbit_TOP 0x88f188f1
-#define FLASH_DEVICE_8mbit_BOTTOM 0x88f288f2
-#define FLASH_DEVICE_16mbit_TOP 0x88f388f3
-#define FLASH_DEVICE_16mbit_BOTTOM 0x88f488f4
-
-/***************************************************************************************************/
-
-/*
- * The data line mapping on LART is as follows:
- *
- * U2 CPU | U3 CPU
- * -------------------
- * 0 20 | 0 12
- * 1 22 | 1 14
- * 2 19 | 2 11
- * 3 17 | 3 9
- * 4 24 | 4 0
- * 5 26 | 5 2
- * 6 31 | 6 7
- * 7 29 | 7 5
- * 8 21 | 8 13
- * 9 23 | 9 15
- * 10 18 | 10 10
- * 11 16 | 11 8
- * 12 25 | 12 1
- * 13 27 | 13 3
- * 14 30 | 14 6
- * 15 28 | 15 4
- */
-
-/* Mangle data (x) */
-#define DATA_TO_FLASH(x) \
- ( \
- (((x) & 0x08009000) >> 11) + \
- (((x) & 0x00002000) >> 10) + \
- (((x) & 0x04004000) >> 8) + \
- (((x) & 0x00000010) >> 4) + \
- (((x) & 0x91000820) >> 3) + \
- (((x) & 0x22080080) >> 2) + \
- ((x) & 0x40000400) + \
- (((x) & 0x00040040) << 1) + \
- (((x) & 0x00110000) << 4) + \
- (((x) & 0x00220100) << 5) + \
- (((x) & 0x00800208) << 6) + \
- (((x) & 0x00400004) << 9) + \
- (((x) & 0x00000001) << 12) + \
- (((x) & 0x00000002) << 13) \
- )
-
-/* Unmangle data (x) */
-#define FLASH_TO_DATA(x) \
- ( \
- (((x) & 0x00010012) << 11) + \
- (((x) & 0x00000008) << 10) + \
- (((x) & 0x00040040) << 8) + \
- (((x) & 0x00000001) << 4) + \
- (((x) & 0x12200104) << 3) + \
- (((x) & 0x08820020) << 2) + \
- ((x) & 0x40000400) + \
- (((x) & 0x00080080) >> 1) + \
- (((x) & 0x01100000) >> 4) + \
- (((x) & 0x04402000) >> 5) + \
- (((x) & 0x20008200) >> 6) + \
- (((x) & 0x80000800) >> 9) + \
- (((x) & 0x00001000) >> 12) + \
- (((x) & 0x00004000) >> 13) \
- )
-
-/*
- * The address line mapping on LART is as follows:
- *
- * U3 CPU | U2 CPU
- * -------------------
- * 0 2 | 0 2
- * 1 3 | 1 3
- * 2 9 | 2 9
- * 3 13 | 3 8
- * 4 8 | 4 7
- * 5 12 | 5 6
- * 6 11 | 6 5
- * 7 10 | 7 4
- * 8 4 | 8 10
- * 9 5 | 9 11
- * 10 6 | 10 12
- * 11 7 | 11 13
- *
- * BOOT BLOCK BOUNDARY
- *
- * 12 15 | 12 15
- * 13 14 | 13 14
- * 14 16 | 14 16
- *
- * MAIN BLOCK BOUNDARY
- *
- * 15 17 | 15 18
- * 16 18 | 16 17
- * 17 20 | 17 20
- * 18 19 | 18 19
- * 19 21 | 19 21
- *
- * As we can see from above, the addresses aren't mangled across
- * block boundaries, so we don't need to worry about address
- * translations except for sending/reading commands during
- * initialization
- */
-
-/* Mangle address (x) on chip U2 */
-#define ADDR_TO_FLASH_U2(x) \
- ( \
- (((x) & 0x00000f00) >> 4) + \
- (((x) & 0x00042000) << 1) + \
- (((x) & 0x0009c003) << 2) + \
- (((x) & 0x00021080) << 3) + \
- (((x) & 0x00000010) << 4) + \
- (((x) & 0x00000040) << 5) + \
- (((x) & 0x00000024) << 7) + \
- (((x) & 0x00000008) << 10) \
- )
-
-/* Unmangle address (x) on chip U2 */
-#define FLASH_U2_TO_ADDR(x) \
- ( \
- (((x) << 4) & 0x00000f00) + \
- (((x) >> 1) & 0x00042000) + \
- (((x) >> 2) & 0x0009c003) + \
- (((x) >> 3) & 0x00021080) + \
- (((x) >> 4) & 0x00000010) + \
- (((x) >> 5) & 0x00000040) + \
- (((x) >> 7) & 0x00000024) + \
- (((x) >> 10) & 0x00000008) \
- )
-
-/* Mangle address (x) on chip U3 */
-#define ADDR_TO_FLASH_U3(x) \
- ( \
- (((x) & 0x00000080) >> 3) + \
- (((x) & 0x00000040) >> 1) + \
- (((x) & 0x00052020) << 1) + \
- (((x) & 0x00084f03) << 2) + \
- (((x) & 0x00029010) << 3) + \
- (((x) & 0x00000008) << 5) + \
- (((x) & 0x00000004) << 7) \
- )
-
-/* Unmangle address (x) on chip U3 */
-#define FLASH_U3_TO_ADDR(x) \
- ( \
- (((x) << 3) & 0x00000080) + \
- (((x) << 1) & 0x00000040) + \
- (((x) >> 1) & 0x00052020) + \
- (((x) >> 2) & 0x00084f03) + \
- (((x) >> 3) & 0x00029010) + \
- (((x) >> 5) & 0x00000008) + \
- (((x) >> 7) & 0x00000004) \
- )
-
-/***************************************************************************************************/
-
-static __u8 read8 (__u32 offset)
-{
- volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
-#endif
- return (*data);
-}
-
-static __u32 read32 (__u32 offset)
-{
- volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
-#endif
- return (*data);
-}
-
-static void write32 (__u32 x,__u32 offset)
-{
- volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
- *data = x;
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
-#endif
-}
-
-/***************************************************************************************************/
-
-/*
- * Probe for 16mbit flash memory on a LART board without doing
- * too much damage. Since we need to write 1 dword to memory,
- * we're f**cked if this happens to be DRAM since we can't
- * restore the memory (otherwise we might exit Read Array mode).
- *
- * Returns 1 if we found 16mbit flash memory on LART, 0 otherwise.
- */
-static int flash_probe (void)
-{
- __u32 manufacturer,devtype;
-
- /* setup "Read Identifier Codes" mode */
- write32 (DATA_TO_FLASH (READ_ID_CODES),0x00000000);
-
- /* probe U2. U2/U3 returns the same data since the first 3
- * address lines is mangled in the same way */
- manufacturer = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000000)));
- devtype = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000001)));
-
- /* put the flash back into command mode */
- write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
-
- return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || devtype == FLASH_DEVICE_16mbit_BOTTOM));
-}
-
-/*
- * Erase one block of flash memory at offset ``offset'' which is any
- * address within the block which should be erased.
- *
- * Returns 1 if successful, 0 otherwise.
- */
-static inline int erase_block (__u32 offset)
-{
- __u32 status;
-
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
-#endif
-
- /* erase and confirm */
- write32 (DATA_TO_FLASH (ERASE_SETUP),offset);
- write32 (DATA_TO_FLASH (ERASE_CONFIRM),offset);
-
- /* wait for block erase to finish */
- do
- {
- write32 (DATA_TO_FLASH (STATUS_READ),offset);
- status = FLASH_TO_DATA (read32 (offset));
- }
- while ((~status & STATUS_BUSY) != 0);
-
- /* put the flash back into command mode */
- write32 (DATA_TO_FLASH (READ_ARRAY),offset);
-
- /* was the erase successful? */
- if ((status & STATUS_ERASE_ERR))
- {
- printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset);
- return (0);
- }
-
- return (1);
-}
-
-static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
-{
- __u32 addr,len;
- int i,first;
-
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
-#endif
-
- /*
- * check that both start and end of the requested erase are
- * aligned with the erasesize at the appropriate addresses.
- *
- * skip all erase regions which are ended before the start of
- * the requested erase. Actually, to save on the calculations,
- * we skip to the first erase region which starts after the
- * start of the requested erase, and then go back one.
- */
- for (i = 0; i < mtd->numeraseregions && instr->addr >= mtd->eraseregions[i].offset; i++) ;
- i--;
-
- /*
- * ok, now i is pointing at the erase region in which this
- * erase request starts. Check the start of the requested
- * erase range is aligned with the erase size which is in
- * effect here.
- */
- if (i < 0 || (instr->addr & (mtd->eraseregions[i].erasesize - 1)))
- return -EINVAL;
-
- /* Remember the erase region we start on */
- first = i;
-
- /*
- * next, check that the end of the requested erase is aligned
- * with the erase region at that address.
- *
- * as before, drop back one to point at the region in which
- * the address actually falls
- */
- for (; i < mtd->numeraseregions && instr->addr + instr->len >= mtd->eraseregions[i].offset; i++) ;
- i--;
-
- /* is the end aligned on a block boundary? */
- if (i < 0 || ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1)))
- return -EINVAL;
-
- addr = instr->addr;
- len = instr->len;
-
- i = first;
-
- /* now erase those blocks */
- while (len)
- {
- if (!erase_block (addr))
- return (-EIO);
-
- addr += mtd->eraseregions[i].erasesize;
- len -= mtd->eraseregions[i].erasesize;
-
- if (addr == mtd->eraseregions[i].offset + (mtd->eraseregions[i].erasesize * mtd->eraseregions[i].numblocks)) i++;
- }
-
- return (0);
-}
-
-static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
-{
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
-#endif
-
- /* we always read len bytes */
- *retlen = len;
-
- /* first, we read bytes until we reach a dword boundary */
- if (from & (BUSWIDTH - 1))
- {
- int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
-
- while (len && gap--) {
- *buf++ = read8 (from++);
- len--;
- }
- }
-
- /* now we read dwords until we reach a non-dword boundary */
- while (len >= BUSWIDTH)
- {
- *((__u32 *) buf) = read32 (from);
-
- buf += BUSWIDTH;
- from += BUSWIDTH;
- len -= BUSWIDTH;
- }
-
- /* top up the last unaligned bytes */
- if (len & (BUSWIDTH - 1))
- while (len--) *buf++ = read8 (from++);
-
- return (0);
-}
-
-/*
- * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
- * must be 32 bits, i.e. it must be on a dword boundary.
- *
- * Returns 1 if successful, 0 otherwise.
- */
-static inline int write_dword (__u32 offset,__u32 x)
-{
- __u32 status;
-
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
-#endif
-
- /* setup writing */
- write32 (DATA_TO_FLASH (PGM_SETUP),offset);
-
- /* write the data */
- write32 (x,offset);
-
- /* wait for the write to finish */
- do
- {
- write32 (DATA_TO_FLASH (STATUS_READ),offset);
- status = FLASH_TO_DATA (read32 (offset));
- }
- while ((~status & STATUS_BUSY) != 0);
-
- /* put the flash back into command mode */
- write32 (DATA_TO_FLASH (READ_ARRAY),offset);
-
- /* was the write successful? */
- if ((status & STATUS_PGM_ERR) || read32 (offset) != x)
- {
- printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset);
- return (0);
- }
-
- return (1);
-}
-
-static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
-{
- __u8 tmp[4];
- int i,n;
-
-#ifdef LART_DEBUG
- printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
-#endif
-
- /* sanity checks */
- if (!len) return (0);
-
- /* first, we write a 0xFF.... padded byte until we reach a dword boundary */
- if (to & (BUSWIDTH - 1))
- {
- __u32 aligned = to & ~(BUSWIDTH - 1);
- int gap = to - aligned;
-
- i = n = 0;
-
- while (gap--) tmp[i++] = 0xFF;
- while (len && i < BUSWIDTH) {
- tmp[i++] = buf[n++];
- len--;
- }
- while (i < BUSWIDTH) tmp[i++] = 0xFF;
-
- if (!write_dword (aligned,*((__u32 *) tmp))) return (-EIO);
-
- to += n;
- buf += n;
- *retlen += n;
- }
-
- /* now we write dwords until we reach a non-dword boundary */
- while (len >= BUSWIDTH)
- {
- if (!write_dword (to,*((__u32 *) buf))) return (-EIO);
-
- to += BUSWIDTH;
- buf += BUSWIDTH;
- *retlen += BUSWIDTH;
- len -= BUSWIDTH;
- }
-
- /* top up the last unaligned bytes, padded with 0xFF.... */
- if (len & (BUSWIDTH - 1))
- {
- i = n = 0;
-
- while (len--) tmp[i++] = buf[n++];
- while (i < BUSWIDTH) tmp[i++] = 0xFF;
-
- if (!write_dword (to,*((__u32 *) tmp))) return (-EIO);
-
- *retlen += n;
- }
-
- return (0);
-}
-
-/***************************************************************************************************/
-
-static struct mtd_info mtd;
-
-static struct mtd_erase_region_info erase_regions[] = {
- /* parameter blocks */
- {
- .offset = 0x00000000,
- .erasesize = FLASH_BLOCKSIZE_PARAM,
- .numblocks = FLASH_NUMBLOCKS_16m_PARAM,
- },
- /* main blocks */
- {
- .offset = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM,
- .erasesize = FLASH_BLOCKSIZE_MAIN,
- .numblocks = FLASH_NUMBLOCKS_16m_MAIN,
- }
-};
-
-static const struct mtd_partition lart_partitions[] = {
- /* blob */
- {
- .name = "blob",
- .offset = PART_BLOB_START,
- .size = PART_BLOB_LEN,
- },
- /* kernel */
- {
- .name = "kernel",
- .offset = PART_KERNEL_START, /* MTDPART_OFS_APPEND */
- .size = PART_KERNEL_LEN,
- },
- /* initial ramdisk / file system */
- {
- .name = "file system",
- .offset = PART_INITRD_START, /* MTDPART_OFS_APPEND */
- .size = PART_INITRD_LEN, /* MTDPART_SIZ_FULL */
- }
-};
-#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
-
-static int __init lart_flash_init (void)
-{
- int result;
- memset (&mtd,0,sizeof (mtd));
- printk ("MTD driver for LART. Written by Abraham vd Merwe <abraham@2d3d.co.za>\n");
- printk ("%s: Probing for 28F160x3 flash on LART...\n",module_name);
- if (!flash_probe ())
- {
- printk (KERN_WARNING "%s: Found no LART compatible flash device\n",module_name);
- return (-ENXIO);
- }
- printk ("%s: This looks like a LART board to me.\n",module_name);
- mtd.name = module_name;
- mtd.type = MTD_NORFLASH;
- mtd.writesize = 1;
- mtd.writebufsize = 4;
- mtd.flags = MTD_CAP_NORFLASH;
- mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
- mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
- mtd.numeraseregions = ARRAY_SIZE(erase_regions);
- mtd.eraseregions = erase_regions;
- mtd._erase = flash_erase;
- mtd._read = flash_read;
- mtd._write = flash_write;
- mtd.owner = THIS_MODULE;
-
-#ifdef LART_DEBUG
- printk (KERN_DEBUG
- "mtd.name = %s\n"
- "mtd.size = 0x%.8x (%uM)\n"
- "mtd.erasesize = 0x%.8x (%uK)\n"
- "mtd.numeraseregions = %d\n",
- mtd.name,
- mtd.size,mtd.size / (1024*1024),
- mtd.erasesize,mtd.erasesize / 1024,
- mtd.numeraseregions);
-
- if (mtd.numeraseregions)
- for (result = 0; result < mtd.numeraseregions; result++)
- printk (KERN_DEBUG
- "\n\n"
- "mtd.eraseregions[%d].offset = 0x%.8x\n"
- "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
- "mtd.eraseregions[%d].numblocks = %d\n",
- result,mtd.eraseregions[result].offset,
- result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
- result,mtd.eraseregions[result].numblocks);
-
- printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
-
- for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
- printk (KERN_DEBUG
- "\n\n"
- "lart_partitions[%d].name = %s\n"
- "lart_partitions[%d].offset = 0x%.8x\n"
- "lart_partitions[%d].size = 0x%.8x (%uK)\n",
- result,lart_partitions[result].name,
- result,lart_partitions[result].offset,
- result,lart_partitions[result].size,lart_partitions[result].size / 1024);
-#endif
-
- result = mtd_device_register(&mtd, lart_partitions,
- ARRAY_SIZE(lart_partitions));
-
- return (result);
-}
-
-static void __exit lart_flash_exit (void)
-{
- mtd_device_unregister(&mtd);
-}
-
-module_init (lart_flash_init);
-module_exit (lart_flash_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
-MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 58ca1c21ebe6..9739387cff8c 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -356,7 +356,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
* Newest unit in chain now contains data from _all_ older units.
* So go through and erase each unit in chain, oldest first. (This
* is important, by doing oldest first if we crash/reboot then it
- * it is relatively simple to clean up the mess).
+ * is relatively simple to clean up the mess).
*/
pr_debug("INFTL: want to erase virtual chain %d\n", thisVUC);
diff --git a/drivers/mtd/lpddr/lpddr2_nvm.c b/drivers/mtd/lpddr/lpddr2_nvm.c
index 367e2d906de0..e71af4c49096 100644
--- a/drivers/mtd/lpddr/lpddr2_nvm.c
+++ b/drivers/mtd/lpddr/lpddr2_nvm.c
@@ -433,6 +433,8 @@ static int lpddr2_nvm_probe(struct platform_device *pdev)
/* lpddr2_nvm address range */
add_range = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!add_range)
+ return -ENODEV;
/* Populate map_info data structure */
*map = (struct map_info) {
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 1749dbbacc13..62a5bf41a6d7 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -64,6 +64,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
if (!info->map.virt) {
printk(KERN_WARNING "Failed to ioremap %s\n",
info->map.name);
+ kfree(info);
return -ENOMEM;
}
info->map.cached = ioremap_cache(info->map.phys, info->map.size);
@@ -85,6 +86,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
iounmap((void *)info->map.virt);
if (info->map.cached)
iounmap(info->map.cached);
+ kfree(info);
return -EIO;
}
info->mtd->dev.parent = &pdev->dev;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 0b4ca0aa4132..0feacb9fbdac 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -28,6 +28,7 @@
#include <linux/leds.h>
#include <linux/debugfs.h>
#include <linux/nvmem-provider.h>
+#include <linux/root_dev.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@@ -551,22 +552,22 @@ static void mtd_check_of_node(struct mtd_info *mtd)
struct device_node *partitions, *parent_dn, *mtd_dn = NULL;
const char *pname, *prefix = "partition-";
int plen, mtd_name_len, offset, prefix_len;
- struct mtd_info *parent;
- bool found = false;
/* Check if MTD already has a device node */
- if (dev_of_node(&mtd->dev))
+ if (mtd_get_of_node(mtd))
return;
- /* Check if a partitions node exist */
if (!mtd_is_partition(mtd))
return;
- parent = mtd->parent;
- parent_dn = of_node_get(dev_of_node(&parent->dev));
+
+ parent_dn = of_node_get(mtd_get_of_node(mtd->parent));
if (!parent_dn)
return;
- partitions = of_get_child_by_name(parent_dn, "partitions");
+ if (mtd_is_partition(mtd->parent))
+ partitions = of_node_get(parent_dn);
+ else
+ partitions = of_get_child_by_name(parent_dn, "partitions");
if (!partitions)
goto exit_parent;
@@ -575,34 +576,26 @@ static void mtd_check_of_node(struct mtd_info *mtd)
/* Search if a partition is defined with the same name */
for_each_child_of_node(partitions, mtd_dn) {
- offset = 0;
-
/* Skip partition with no/wrong prefix */
- if (!of_node_name_prefix(mtd_dn, "partition-"))
+ if (!of_node_name_prefix(mtd_dn, prefix))
continue;
/* Label have priority. Check that first */
- if (of_property_read_string(mtd_dn, "label", &pname)) {
- of_property_read_string(mtd_dn, "name", &pname);
+ if (!of_property_read_string(mtd_dn, "label", &pname)) {
+ offset = 0;
+ } else {
+ pname = mtd_dn->name;
offset = prefix_len;
}
plen = strlen(pname) - offset;
if (plen == mtd_name_len &&
!strncmp(mtd->name, pname + offset, plen)) {
- found = true;
+ mtd_set_of_node(mtd, mtd_dn);
break;
}
}
- if (!found)
- goto exit_partitions;
-
- /* Set of_node only for nvmem */
- if (of_device_is_compatible(mtd_dn, "nvmem-cells"))
- mtd_set_of_node(mtd, mtd_dn);
-
-exit_partitions:
of_node_put(partitions);
exit_parent:
of_node_put(parent_dn);
@@ -723,8 +716,10 @@ int add_mtd_device(struct mtd_info *mtd)
mtd_check_of_node(mtd);
of_node_get(mtd_get_of_node(mtd));
error = device_register(&mtd->dev);
- if (error)
+ if (error) {
+ put_device(&mtd->dev);
goto fail_added;
+ }
/* Add the nvmem provider */
error = mtd_nvmem_add(mtd);
@@ -743,6 +738,17 @@ int add_mtd_device(struct mtd_info *mtd)
not->add(mtd);
mutex_unlock(&mtd_table_mutex);
+
+ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) {
+ if (IS_BUILTIN(CONFIG_MTD)) {
+ pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name);
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
+ } else {
+ pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n",
+ mtd->index, mtd->name);
+ }
+ }
+
/* We _know_ we aren't being removed, because
our caller is still holding us here. So none
of this try_ nonsense, and no bitching about it
@@ -774,6 +780,7 @@ int del_mtd_device(struct mtd_info *mtd)
{
int ret;
struct mtd_notifier *not;
+ struct device_node *mtd_of_node;
mutex_lock(&mtd_table_mutex);
@@ -792,6 +799,7 @@ int del_mtd_device(struct mtd_info *mtd)
mtd->index, mtd->name, mtd->usecount);
ret = -EBUSY;
} else {
+ mtd_of_node = mtd_get_of_node(mtd);
debugfs_remove_recursive(mtd->dbg.dfs_dir);
/* Try to remove the NVMEM provider */
@@ -803,7 +811,7 @@ int del_mtd_device(struct mtd_info *mtd)
memset(&mtd->dev, 0, sizeof(mtd->dev));
idr_remove(&mtd_idr, mtd->index);
- of_node_put(mtd_get_of_node(mtd));
+ of_node_put(mtd_of_node);
module_put(THIS_MODULE);
ret = 0;
@@ -2483,6 +2491,7 @@ static int __init init_mtd(void)
out_procfs:
if (proc_mtd)
remove_proc_entry("mtd", NULL);
+ bdi_unregister(mtd_bdi);
bdi_put(mtd_bdi);
err_bdi:
class_unregister(&mtd_class);
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 3d4a2ffb5b01..2f11585b5613 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -7,6 +7,8 @@
* Author: Richard Purdie <rpurdie@openedhand.com>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/console.h>
@@ -93,9 +95,9 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
ret = mtd_erase(mtd, &erase);
if (ret) {
- printk(KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] on \"%s\" failed\n",
- (unsigned long long)erase.addr,
- (unsigned long long)erase.len, mtddev);
+ pr_warn("erase of region [0x%llx, 0x%llx] on \"%s\" failed\n",
+ (unsigned long long)erase.addr,
+ (unsigned long long)erase.len, mtddev);
return ret;
}
@@ -106,29 +108,8 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
return 0;
}
-static void mtdoops_inc_counter(struct mtdoops_context *cxt)
-{
- cxt->nextpage++;
- if (cxt->nextpage >= cxt->oops_pages)
- cxt->nextpage = 0;
- cxt->nextcount++;
- if (cxt->nextcount == 0xffffffff)
- cxt->nextcount = 0;
-
- if (page_is_used(cxt, cxt->nextpage)) {
- schedule_work(&cxt->work_erase);
- return;
- }
-
- printk(KERN_DEBUG "mtdoops: ready %d, %d (no erase)\n",
- cxt->nextpage, cxt->nextcount);
-}
-
-/* Scheduled work - when we can't proceed without erasing a block */
-static void mtdoops_workfunc_erase(struct work_struct *work)
+static void mtdoops_erase(struct mtdoops_context *cxt)
{
- struct mtdoops_context *cxt =
- container_of(work, struct mtdoops_context, work_erase);
struct mtd_info *mtd = cxt->mtd;
int i = 0, j, ret, mod;
@@ -145,20 +126,20 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
while ((ret = mtd_block_isbad(mtd, cxt->nextpage * record_size)) > 0) {
badblock:
- printk(KERN_WARNING "mtdoops: bad block at %08lx\n",
- cxt->nextpage * record_size);
+ pr_warn("bad block at %08lx\n",
+ cxt->nextpage * record_size);
i++;
cxt->nextpage = cxt->nextpage + (mtd->erasesize / record_size);
if (cxt->nextpage >= cxt->oops_pages)
cxt->nextpage = 0;
if (i == cxt->oops_pages / (mtd->erasesize / record_size)) {
- printk(KERN_ERR "mtdoops: all blocks bad!\n");
+ pr_err("all blocks bad!\n");
return;
}
}
if (ret < 0) {
- printk(KERN_ERR "mtdoops: mtd_block_isbad failed, aborting\n");
+ pr_err("mtd_block_isbad failed, aborting\n");
return;
}
@@ -166,21 +147,55 @@ badblock:
ret = mtdoops_erase_block(cxt, cxt->nextpage * record_size);
if (ret >= 0) {
- printk(KERN_DEBUG "mtdoops: ready %d, %d\n",
- cxt->nextpage, cxt->nextcount);
+ pr_debug("ready %d, %d\n",
+ cxt->nextpage, cxt->nextcount);
return;
}
if (ret == -EIO) {
ret = mtd_block_markbad(mtd, cxt->nextpage * record_size);
if (ret < 0 && ret != -EOPNOTSUPP) {
- printk(KERN_ERR "mtdoops: block_markbad failed, aborting\n");
+ pr_err("block_markbad failed, aborting\n");
return;
}
}
goto badblock;
}
+/* Scheduled work - when we can't proceed without erasing a block */
+static void mtdoops_workfunc_erase(struct work_struct *work)
+{
+ struct mtdoops_context *cxt =
+ container_of(work, struct mtdoops_context, work_erase);
+ mtdoops_erase(cxt);
+}
+
+static void mtdoops_inc_counter(struct mtdoops_context *cxt, int panic)
+{
+ cxt->nextpage++;
+ if (cxt->nextpage >= cxt->oops_pages)
+ cxt->nextpage = 0;
+ cxt->nextcount++;
+ if (cxt->nextcount == 0xffffffff)
+ cxt->nextcount = 0;
+
+ if (page_is_used(cxt, cxt->nextpage)) {
+ pr_debug("not ready %d, %d (erase %s)\n",
+ cxt->nextpage, cxt->nextcount,
+ panic ? "immediately" : "scheduled");
+ if (panic) {
+ /* In case of panic, erase immediately */
+ mtdoops_erase(cxt);
+ } else {
+ /* Otherwise, schedule work to erase it "nicely" */
+ schedule_work(&cxt->work_erase);
+ }
+ } else {
+ pr_debug("ready %d, %d (no erase)\n",
+ cxt->nextpage, cxt->nextcount);
+ }
+}
+
static void mtdoops_write(struct mtdoops_context *cxt, int panic)
{
struct mtd_info *mtd = cxt->mtd;
@@ -201,7 +216,7 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
ret = mtd_panic_write(mtd, cxt->nextpage * record_size,
record_size, &retlen, cxt->oops_buf);
if (ret == -EOPNOTSUPP) {
- printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
+ pr_err("Cannot write from panic without panic_write\n");
goto out;
}
} else
@@ -209,12 +224,12 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
record_size, &retlen, cxt->oops_buf);
if (retlen != record_size || ret < 0)
- printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n",
+ pr_err("write failure at %ld (%td of %ld written), error %d\n",
cxt->nextpage * record_size, retlen, record_size, ret);
mark_page_used(cxt, cxt->nextpage);
memset(cxt->oops_buf, 0xff, record_size);
- mtdoops_inc_counter(cxt);
+ mtdoops_inc_counter(cxt, panic);
out:
clear_bit(0, &cxt->oops_buf_busy);
}
@@ -244,7 +259,7 @@ static void find_next_position(struct mtdoops_context *cxt)
&retlen, (u_char *)&hdr);
if (retlen != sizeof(hdr) ||
(ret < 0 && !mtd_is_bitflip(ret))) {
- printk(KERN_ERR "mtdoops: read failure at %ld (%zu of %zu read), err %d\n",
+ pr_err("read failure at %ld (%zu of %zu read), err %d\n",
page * record_size, retlen, sizeof(hdr), ret);
continue;
}
@@ -279,7 +294,7 @@ static void find_next_position(struct mtdoops_context *cxt)
cxt->nextcount = maxcount;
}
- mtdoops_inc_counter(cxt);
+ mtdoops_inc_counter(cxt, 0);
}
static void mtdoops_do_dump(struct kmsg_dumper *dumper,
@@ -324,17 +339,17 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
return;
if (mtd->size < mtd->erasesize * 2) {
- printk(KERN_ERR "mtdoops: MTD partition %d not big enough for mtdoops\n",
+ pr_err("MTD partition %d not big enough for mtdoops\n",
mtd->index);
return;
}
if (mtd->erasesize < record_size) {
- printk(KERN_ERR "mtdoops: eraseblock size of MTD partition %d too small\n",
+ pr_err("eraseblock size of MTD partition %d too small\n",
mtd->index);
return;
}
if (mtd->size > MTDOOPS_MAX_MTD_SIZE) {
- printk(KERN_ERR "mtdoops: mtd%d is too large (limit is %d MiB)\n",
+ pr_err("mtd%d is too large (limit is %d MiB)\n",
mtd->index, MTDOOPS_MAX_MTD_SIZE / 1024 / 1024);
return;
}
@@ -345,7 +360,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
DIV_ROUND_UP(mtdoops_pages,
BITS_PER_LONG)));
if (!cxt->oops_page_used) {
- printk(KERN_ERR "mtdoops: could not allocate page array\n");
+ pr_err("could not allocate page array\n");
return;
}
@@ -353,7 +368,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
cxt->dump.dump = mtdoops_do_dump;
err = kmsg_dump_register(&cxt->dump);
if (err) {
- printk(KERN_ERR "mtdoops: registering kmsg dumper failed, error %d\n", err);
+ pr_err("registering kmsg dumper failed, error %d\n", err);
vfree(cxt->oops_page_used);
cxt->oops_page_used = NULL;
return;
@@ -362,7 +377,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
cxt->mtd = mtd;
cxt->oops_pages = (int)mtd->size / record_size;
find_next_position(cxt);
- printk(KERN_INFO "mtdoops: Attached to MTD device %d\n", mtd->index);
+ pr_info("Attached to MTD device %d\n", mtd->index);
}
static void mtdoops_notify_remove(struct mtd_info *mtd)
@@ -373,7 +388,7 @@ static void mtdoops_notify_remove(struct mtd_info *mtd)
return;
if (kmsg_dump_unregister(&cxt->dump) < 0)
- printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n");
+ pr_warn("could not unregister kmsg_dumper\n");
cxt->mtd = NULL;
flush_work(&cxt->work_erase);
@@ -393,15 +408,15 @@ static int __init mtdoops_init(void)
char *endp;
if (strlen(mtddev) == 0) {
- printk(KERN_ERR "mtdoops: mtd device (mtddev=name/number) must be supplied\n");
+ pr_err("mtd device (mtddev=name/number) must be supplied\n");
return -EINVAL;
}
if ((record_size & 4095) != 0) {
- printk(KERN_ERR "mtdoops: record_size must be a multiple of 4096\n");
+ pr_err("record_size must be a multiple of 4096\n");
return -EINVAL;
}
if (record_size < 4096) {
- printk(KERN_ERR "mtdoops: record_size must be over 4096 bytes\n");
+ pr_err("record_size must be over 4096 bytes\n");
return -EINVAL;
}
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index dbd7b06524b3..7737b1a4a177 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -126,7 +126,7 @@ EXPORT_SYMBOL_GPL(nanddev_isreserved);
*
* Return: 0 in case of success, a negative error code otherwise.
*/
-int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
+static int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
{
if (nanddev_isbad(nand, pos) || nanddev_isreserved(nand, pos)) {
pr_warn("attempt to erase a bad/reserved block @%llx\n",
@@ -136,7 +136,6 @@ int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
return nand->ops->erase(nand, pos);
}
-EXPORT_SYMBOL_GPL(nanddev_erase);
/**
* nanddev_mtd_erase() - Generic mtd->_erase() implementation for NAND devices
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 4cd40af362de..98ea1c9e65c8 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -415,7 +415,7 @@ config MTD_NAND_PLATFORM
config MTD_NAND_CADENCE
tristate "Support Cadence NAND (HPNFC) controller"
- depends on (OF || COMPILE_TEST) && HAS_IOMEM
+ depends on OF && HAS_IOMEM
help
Enable the driver for NAND flash on platforms using a Cadence NAND
controller.
@@ -430,7 +430,7 @@ config MTD_NAND_ARASAN
config MTD_NAND_INTEL_LGM
tristate "Support for NAND controller on Intel LGM SoC"
- depends on OF || COMPILE_TEST
+ depends on OF
depends on HAS_IOMEM
help
Enables support for NAND Flash chips on Intel's LGM SoC.
@@ -450,7 +450,7 @@ config MTD_NAND_ROCKCHIP
config MTD_NAND_PL35X
tristate "ARM PL35X NAND controller"
- depends on OF || COMPILE_TEST
+ depends on OF
depends on PL353_SMC
help
Enables support for PrimeCell SMC PL351 and PL353 NAND
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index 9dac3ca69d57..7661a5cf1883 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -1184,6 +1184,14 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
if (cadence_nand_read_bch_caps(cdns_ctrl))
return -EIO;
+#ifndef CONFIG_64BIT
+ if (cdns_ctrl->caps2.data_dma_width == 8) {
+ dev_err(cdns_ctrl->dev,
+ "cannot access 64-bit dma on !64-bit architectures");
+ return -EIO;
+ }
+#endif
+
/*
* Set IO width access to 8.
* It is because during SW device discovering width access
@@ -1882,17 +1890,36 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl,
return status;
if (!cdns_ctrl->caps1->has_dma) {
- int len_in_words = len >> 2;
+ u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
+
+ int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
/* read alingment data */
- ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
+ if (data_dma_width == 4)
+ ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
+#ifdef CONFIG_64BIT
+ else
+ readsq(cdns_ctrl->io.virt, buf, len_in_words);
+#endif
+
if (sdma_size > len) {
+ int read_bytes = (data_dma_width == 4) ?
+ len_in_words << 2 : len_in_words << 3;
+
/* read rest data from slave DMA interface if any */
- ioread32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
- sdma_size / 4 - len_in_words);
+ if (data_dma_width == 4)
+ ioread32_rep(cdns_ctrl->io.virt,
+ cdns_ctrl->buf,
+ sdma_size / 4 - len_in_words);
+#ifdef CONFIG_64BIT
+ else
+ readsq(cdns_ctrl->io.virt, cdns_ctrl->buf,
+ sdma_size / 8 - len_in_words);
+#endif
+
/* copy rest of data */
- memcpy(buf + (len_in_words << 2), cdns_ctrl->buf,
- len - (len_in_words << 2));
+ memcpy(buf + read_bytes, cdns_ctrl->buf,
+ len - read_bytes);
}
return 0;
}
@@ -1936,16 +1963,35 @@ static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl,
return status;
if (!cdns_ctrl->caps1->has_dma) {
- int len_in_words = len >> 2;
+ u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
+
+ int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
+
+ if (data_dma_width == 4)
+ iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
+#ifdef CONFIG_64BIT
+ else
+ writesq(cdns_ctrl->io.virt, buf, len_in_words);
+#endif
- iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
if (sdma_size > len) {
+ int written_bytes = (data_dma_width == 4) ?
+ len_in_words << 2 : len_in_words << 3;
+
/* copy rest of data */
- memcpy(cdns_ctrl->buf, buf + (len_in_words << 2),
- len - (len_in_words << 2));
+ memcpy(cdns_ctrl->buf, buf + written_bytes,
+ len - written_bytes);
+
/* write all expected by nand controller data */
- iowrite32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
- sdma_size / 4 - len_in_words);
+ if (data_dma_width == 4)
+ iowrite32_rep(cdns_ctrl->io.virt,
+ cdns_ctrl->buf,
+ sdma_size / 4 - len_in_words);
+#ifdef CONFIG_64BIT
+ else
+ writesq(cdns_ctrl->io.virt, cdns_ctrl->buf,
+ sdma_size / 8 - len_in_words);
+#endif
}
return 0;
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 01ccbde748f3..ada83344b0f9 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -148,11 +148,9 @@ static int gpmi_init(struct gpmi_nand_data *this)
struct resources *r = &this->resources;
int ret;
- ret = pm_runtime_get_sync(this->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(this->dev);
+ ret = pm_runtime_resume_and_get(this->dev);
+ if (ret < 0)
return ret;
- }
ret = gpmi_reset_block(r->gpmi_regs, false);
if (ret)
@@ -2504,11 +2502,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
for (i = 0; i < GPMI_MAX_TRANSFERS; i++)
this->transfers[i].direction = DMA_NONE;
- ret = pm_runtime_get_sync(this->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(this->dev);
+ ret = pm_runtime_resume_and_get(this->dev);
+ if (ret < 0)
return ret;
- }
/*
* This driver currently supports only one NAND chip. Plus, dies share
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 452ecaf7775a..ae7f6429a5f6 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -25,7 +25,7 @@
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/mtd/lpc32xx_mlc.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -122,7 +122,6 @@ struct lpc32xx_nand_cfg_mlc {
uint32_t rd_low;
uint32_t wr_high;
uint32_t wr_low;
- int wp_gpio;
struct mtd_partition *parts;
unsigned num_parts;
};
@@ -177,6 +176,7 @@ struct lpc32xx_nand_host {
struct nand_chip nand_chip;
struct lpc32xx_mlc_platform_data *pdata;
struct clk *clk;
+ struct gpio_desc *wp_gpio;
void __iomem *io_base;
int irq;
struct lpc32xx_nand_cfg_mlc *ncfg;
@@ -370,8 +370,8 @@ static int lpc32xx_waitfunc(struct nand_chip *chip)
*/
static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
{
- if (gpio_is_valid(host->ncfg->wp_gpio))
- gpio_set_value(host->ncfg->wp_gpio, 0);
+ if (host->wp_gpio)
+ gpiod_set_value_cansleep(host->wp_gpio, 1);
}
/*
@@ -379,8 +379,8 @@ static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
*/
static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
{
- if (gpio_is_valid(host->ncfg->wp_gpio))
- gpio_set_value(host->ncfg->wp_gpio, 1);
+ if (host->wp_gpio)
+ gpiod_set_value_cansleep(host->wp_gpio, 0);
}
static void lpc32xx_dma_complete_func(void *completion)
@@ -636,8 +636,6 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
return NULL;
}
- ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
-
return ncfg;
}
@@ -713,14 +711,18 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
"Missing or bad NAND config from device tree\n");
return -ENOENT;
}
- if (host->ncfg->wp_gpio == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- if (gpio_is_valid(host->ncfg->wp_gpio) &&
- gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
- dev_err(&pdev->dev, "GPIO not available\n");
- return -EBUSY;
+
+ /* Start with WP disabled, if available */
+ host->wp_gpio = gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW);
+ res = PTR_ERR_OR_ZERO(host->wp_gpio);
+ if (res) {
+ if (res != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "WP GPIO is not available: %d\n",
+ res);
+ return res;
}
- lpc32xx_wp_disable(host);
+
+ gpiod_set_consumer_name(host->wp_gpio, "NAND WP");
host->pdata = dev_get_platdata(&pdev->dev);
@@ -817,7 +819,7 @@ put_clk:
clk_put(host->clk);
free_gpio:
lpc32xx_wp_enable(host);
- gpio_free(host->ncfg->wp_gpio);
+ gpiod_put(host->wp_gpio);
return res;
}
@@ -843,12 +845,11 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
clk_put(host->clk);
lpc32xx_wp_enable(host);
- gpio_free(host->ncfg->wp_gpio);
+ gpiod_put(host->wp_gpio);
return 0;
}
-#ifdef CONFIG_PM
static int lpc32xx_nand_resume(struct platform_device *pdev)
{
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
@@ -880,11 +881,6 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
return 0;
}
-#else
-#define lpc32xx_nand_resume NULL
-#define lpc32xx_nand_suspend NULL
-#endif
-
static const struct of_device_id lpc32xx_nand_match[] = {
{ .compatible = "nxp,lpc3220-mlc" },
{ /* sentinel */ },
@@ -894,8 +890,8 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
.remove = lpc32xx_nand_remove,
- .resume = lpc32xx_nand_resume,
- .suspend = lpc32xx_nand_suspend,
+ .resume = pm_ptr(lpc32xx_nand_resume),
+ .suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {
.name = DRV_NAME,
.of_match_table = lpc32xx_nand_match,
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index 6b7269cfb7d8..6918737346c9 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -23,9 +23,8 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/mtd/lpc32xx_slc.h>
#define LPC32XX_MODNAME "lpc32xx-nand"
@@ -208,7 +207,6 @@ struct lpc32xx_nand_cfg_slc {
uint32_t rwidth;
uint32_t rhold;
uint32_t rsetup;
- int wp_gpio;
struct mtd_partition *parts;
unsigned num_parts;
};
@@ -217,6 +215,7 @@ struct lpc32xx_nand_host {
struct nand_chip nand_chip;
struct lpc32xx_slc_platform_data *pdata;
struct clk *clk;
+ struct gpio_desc *wp_gpio;
void __iomem *io_base;
struct lpc32xx_nand_cfg_slc *ncfg;
@@ -309,8 +308,8 @@ static int lpc32xx_nand_device_ready(struct nand_chip *chip)
*/
static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
{
- if (gpio_is_valid(host->ncfg->wp_gpio))
- gpio_set_value(host->ncfg->wp_gpio, 0);
+ if (host->wp_gpio)
+ gpiod_set_value_cansleep(host->wp_gpio, 1);
}
/*
@@ -318,8 +317,8 @@ static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
*/
static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
{
- if (gpio_is_valid(host->ncfg->wp_gpio))
- gpio_set_value(host->ncfg->wp_gpio, 1);
+ if (host->wp_gpio)
+ gpiod_set_value_cansleep(host->wp_gpio, 0);
}
/*
@@ -764,8 +763,6 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
return NULL;
}
- ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
-
return ncfg;
}
@@ -852,14 +849,18 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
"Missing or bad NAND config from device tree\n");
return -ENOENT;
}
- if (host->ncfg->wp_gpio == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- if (gpio_is_valid(host->ncfg->wp_gpio) && devm_gpio_request(&pdev->dev,
- host->ncfg->wp_gpio, "NAND WP")) {
- dev_err(&pdev->dev, "GPIO not available\n");
- return -EBUSY;
+
+ /* Start with WP disabled, if available */
+ host->wp_gpio = gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW);
+ res = PTR_ERR_OR_ZERO(host->wp_gpio);
+ if (res) {
+ if (res != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "WP GPIO is not available: %d\n",
+ res);
+ return res;
}
- lpc32xx_wp_disable(host);
+
+ gpiod_set_consumer_name(host->wp_gpio, "NAND WP");
host->pdata = dev_get_platdata(&pdev->dev);
@@ -968,7 +969,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
static int lpc32xx_nand_resume(struct platform_device *pdev)
{
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
@@ -1007,11 +1007,6 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
return 0;
}
-#else
-#define lpc32xx_nand_resume NULL
-#define lpc32xx_nand_suspend NULL
-#endif
-
static const struct of_device_id lpc32xx_nand_match[] = {
{ .compatible = "nxp,lpc3220-slc" },
{ /* sentinel */ },
@@ -1021,8 +1016,8 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
.remove = lpc32xx_nand_remove,
- .resume = lpc32xx_nand_resume,
- .suspend = lpc32xx_nand_suspend,
+ .resume = pm_ptr(lpc32xx_nand_resume),
+ .suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {
.name = LPC32XX_MODNAME,
.of_match_table = lpc32xx_nand_match,
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index b9d1e96e3334..42c64dcea767 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -114,6 +114,7 @@
#define GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST BIT(20)
#define GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST BIT(21)
#define GENCONF_SOC_DEVICE_MUX_NFC_INT_EN BIT(25)
+#define GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN BIT(27)
#define GENCONF_CLK_GATING_CTRL 0x220
#define GENCONF_CLK_GATING_CTRL_ND_GATE BIT(2)
#define GENCONF_ND_CLK_CTRL 0x700
@@ -2880,7 +2881,8 @@ static int marvell_nfc_init(struct marvell_nfc *nfc)
GENCONF_SOC_DEVICE_MUX_NFC_EN |
GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST |
GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST |
- GENCONF_SOC_DEVICE_MUX_NFC_INT_EN);
+ GENCONF_SOC_DEVICE_MUX_NFC_INT_EN |
+ GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN);
regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL,
GENCONF_CLK_GATING_CTRL_ND_GATE,
diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
index 800d774aed8e..f68349cb7824 100644
--- a/drivers/mtd/nand/raw/mpc5121_nfc.c
+++ b/drivers/mtd/nand/raw/mpc5121_nfc.c
@@ -663,7 +663,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
}
prv->irq = irq_of_parse_and_map(dn, 0);
- if (prv->irq == NO_IRQ) {
+ if (!prv->irq) {
dev_err(dev, "Error mapping IRQ!\n");
return -EINVAL;
}
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 76684428354e..3ad58cd284d8 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -74,9 +74,75 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
return spi_mem_exec_op(spinand->spimem, &op);
}
+static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section > 3)
+ return -ERANGE;
+
+ region->offset = 64 + (16 * section);
+ region->length = 13;
+
+ return 0;
+}
+
+static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section > 3)
+ return -ERANGE;
+
+ region->offset = (16 * section) + 2;
+ region->length = 14;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
+ .ecc = w25n02kv_ooblayout_ecc,
+ .free = w25n02kv_ooblayout_free,
+};
+
+static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+ u8 mbf = 0;
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+
+ switch (status & STATUS_ECC_MASK) {
+ case STATUS_ECC_NO_BITFLIPS:
+ return 0;
+
+ case STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+
+ case STATUS_ECC_HAS_BITFLIPS:
+ /*
+ * Let's try to retrieve the real maximum number of bitflips
+ * in order to avoid forcing the wear-leveling layer to move
+ * data around if it's not necessary.
+ */
+ if (spi_mem_exec_op(spinand->spimem, &op))
+ return nanddev_get_ecc_conf(nand)->strength;
+
+ mbf >>= 4;
+
+ if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
+ return nanddev_get_ecc_conf(nand)->strength;
+
+ return mbf;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
static const struct spinand_info winbond_spinand_table[] = {
SPINAND_INFO("W25M02GV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
@@ -86,7 +152,7 @@ static const struct spinand_info winbond_spinand_table[] = {
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
SPINAND_SELECT_TARGET(w25m02gv_select_target)),
SPINAND_INFO("W25N01GV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
@@ -94,6 +160,15 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ SPINAND_INFO("W25N02KV",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 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)
diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig
index aaa06050c9bc..b20e0c38b517 100644
--- a/drivers/mtd/parsers/Kconfig
+++ b/drivers/mtd/parsers/Kconfig
@@ -22,7 +22,7 @@ config MTD_BCM63XX_PARTS
config MTD_BRCM_U_BOOT
tristate "Broadcom's U-Boot partition parser"
- depends on ARCH_BCM4908 || COMPILE_TEST
+ depends on ARCH_BCMBCA || COMPILE_TEST
help
Broadcom uses a custom way of storing U-Boot environment variables.
They are placed inside U-Boot partition itself at unspecified offset.
@@ -75,7 +75,7 @@ config MTD_OF_PARTS
This provides a open firmware device tree partition parser
which derives the partition map from the children of the
flash memory node, as described in
- Documentation/devicetree/bindings/mtd/partition.txt.
+ Documentation/devicetree/bindings/mtd/mtd.yaml.
config MTD_OF_PARTS_BCM4908
bool "BCM4908 partitioning support"
@@ -123,6 +123,21 @@ config MTD_AFS_PARTS
for your particular device. It won't happen automatically. The
'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
+config MTD_PARSER_TPLINK_SAFELOADER
+ tristate "TP-Link Safeloader partitions parser"
+ depends on MTD && (ARCH_BCM_5301X || ATH79 || SOC_MT7620 || SOC_MT7621 || COMPILE_TEST)
+ help
+ TP-Link home routers use flash partitions to store various data. Info
+ about flash space layout is stored in a partitions table using a
+ custom ASCII-based format.
+
+ That format was first found in devices with SafeLoader bootloader and
+ was named after it. Later it was adapted to CFE and U-Boot
+ bootloaders.
+
+ This driver reads partitions table, parses it and creates MTD
+ partitions.
+
config MTD_PARSER_TRX
tristate "Parser for TRX format partitions"
depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST)
diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile
index 23fa4de4016f..0e70b621a1d8 100644
--- a/drivers/mtd/parsers/Makefile
+++ b/drivers/mtd/parsers/Makefile
@@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
+obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o
obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
diff --git a/drivers/mtd/parsers/tplink_safeloader.c b/drivers/mtd/parsers/tplink_safeloader.c
new file mode 100644
index 000000000000..f601e7bd8627
--- /dev/null
+++ b/drivers/mtd/parsers/tplink_safeloader.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2022 Rafał Miłecki <rafal@milecki.pl>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define TPLINK_SAFELOADER_DATA_OFFSET 4
+#define TPLINK_SAFELOADER_MAX_PARTS 32
+
+struct safeloader_cmn_header {
+ __be32 size;
+ uint32_t unused;
+} __packed;
+
+static void *mtd_parser_tplink_safeloader_read_table(struct mtd_info *mtd)
+{
+ struct safeloader_cmn_header hdr;
+ struct device_node *np;
+ size_t bytes_read;
+ size_t size;
+ u32 offset;
+ char *buf;
+ int err;
+
+ np = mtd_get_of_node(mtd);
+ if (mtd_is_partition(mtd))
+ of_node_get(np);
+ else
+ np = of_get_child_by_name(np, "partitions");
+
+ if (of_property_read_u32(np, "partitions-table-offset", &offset)) {
+ pr_err("Failed to get partitions table offset\n");
+ goto err_put;
+ }
+
+ err = mtd_read(mtd, offset, sizeof(hdr), &bytes_read, (uint8_t *)&hdr);
+ if (err && !mtd_is_bitflip(err)) {
+ pr_err("Failed to read from %s at 0x%x\n", mtd->name, offset);
+ goto err_put;
+ }
+
+ size = be32_to_cpu(hdr.size);
+
+ buf = kmalloc(size + 1, GFP_KERNEL);
+ if (!buf)
+ goto err_put;
+
+ err = mtd_read(mtd, offset + sizeof(hdr), size, &bytes_read, buf);
+ if (err && !mtd_is_bitflip(err)) {
+ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset + sizeof(hdr));
+ goto err_kfree;
+ }
+
+ buf[size] = '\0';
+
+ of_node_put(np);
+
+ return buf;
+
+err_kfree:
+ kfree(buf);
+err_put:
+ of_node_put(np);
+ return NULL;
+}
+
+static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd,
+ const struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ struct mtd_partition *parts;
+ char name[65];
+ size_t offset;
+ size_t bytes;
+ char *buf;
+ int idx;
+ int err;
+
+ parts = kcalloc(TPLINK_SAFELOADER_MAX_PARTS, sizeof(*parts), GFP_KERNEL);
+ if (!parts) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ buf = mtd_parser_tplink_safeloader_read_table(mtd);
+ if (!buf) {
+ err = -ENOENT;
+ goto err_out;
+ }
+
+ for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET;
+ idx < TPLINK_SAFELOADER_MAX_PARTS &&
+ sscanf(buf + offset, "partition %64s base 0x%llx size 0x%llx%zn\n",
+ name, &parts[idx].offset, &parts[idx].size, &bytes) == 3;
+ idx++, offset += bytes + 1) {
+ parts[idx].name = kstrdup(name, GFP_KERNEL);
+ if (!parts[idx].name) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+ }
+
+ if (idx == TPLINK_SAFELOADER_MAX_PARTS)
+ pr_warn("Reached maximum number of partitions!\n");
+
+ kfree(buf);
+
+ *pparts = parts;
+
+ return idx;
+
+err_free:
+ for (idx -= 1; idx >= 0; idx--)
+ kfree(parts[idx].name);
+err_out:
+ return err;
+};
+
+static void mtd_parser_tplink_safeloader_cleanup(const struct mtd_partition *pparts,
+ int nr_parts)
+{
+ int i;
+
+ for (i = 0; i < nr_parts; i++)
+ kfree(pparts[i].name);
+
+ kfree(pparts);
+}
+
+static const struct of_device_id mtd_parser_tplink_safeloader_of_match_table[] = {
+ { .compatible = "tplink,safeloader-partitions" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtd_parser_tplink_safeloader_of_match_table);
+
+static struct mtd_part_parser mtd_parser_tplink_safeloader = {
+ .parse_fn = mtd_parser_tplink_safeloader_parse,
+ .cleanup = mtd_parser_tplink_safeloader_cleanup,
+ .name = "tplink-safeloader",
+ .of_match_table = mtd_parser_tplink_safeloader_of_match_table,
+};
+module_mtd_part_parser(mtd_parser_tplink_safeloader);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index bee8fc4c9f07..d8703d7dfd0a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1184,6 +1184,8 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
continue;
erase = &map->erase_type[i];
+ if (!erase->size)
+ continue;
/* Alignment is not mandatory for overlaid regions */
if (region->offset & SNOR_OVERLAID_REGION &&
@@ -1632,6 +1634,16 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_xmc,
};
+static const struct flash_info spi_nor_generic_flash = {
+ .name = "spi-nor-generic",
+ /*
+ * JESD216 rev A doesn't specify the page size, therefore we need a
+ * sane default.
+ */
+ .page_size = 256,
+ .parse_sfdp = true,
+};
+
static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
const u8 *id)
{
@@ -1664,7 +1676,20 @@ static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
return ERR_PTR(ret);
}
+ /* Cache the complete flash ID. */
+ nor->id = devm_kmemdup(nor->dev, id, SPI_NOR_MAX_ID_LEN, GFP_KERNEL);
+ if (!nor->id)
+ return ERR_PTR(-ENOMEM);
+
info = spi_nor_match_id(nor, id);
+
+ /* Fallback to a generic flash described only by its SFDP data. */
+ if (!info) {
+ ret = spi_nor_check_sfdp_signature(nor);
+ if (!ret)
+ info = &spi_nor_generic_flash;
+ }
+
if (!info) {
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
SPI_NOR_MAX_ID_LEN, id);
@@ -1914,7 +1939,8 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
spi_nor_spimem_setup_op(nor, &op, read->proto);
/* convert the dummy cycles to the number of bytes */
- op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
+ op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
+ op.dummy.buswidth / 8;
if (spi_nor_protocol_is_dtr(nor->read_proto))
op.dummy.nbytes *= 2;
@@ -2091,8 +2117,12 @@ static int spi_nor_select_pp(struct spi_nor *nor,
* spi_nor_select_uniform_erase() - select optimum uniform erase type
* @map: the erase map of the SPI NOR
* @wanted_size: the erase type size to search for. Contains the value of
- * info->sector_size or of the "small sector" size in case
- * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
+ * info->sector_size, the "small sector" size in case
+ * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined or 0 if
+ * there is no information about the sector size. The
+ * latter is the case if the flash parameters are parsed
+ * solely by SFDP, then the largest supported erase type
+ * is selected.
*
* Once the optimum uniform sector erase command is found, disable all the
* other.
@@ -2113,6 +2143,10 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
tested_erase = &map->erase_type[i];
+ /* Skip masked erase types. */
+ if (!tested_erase->size)
+ continue;
+
/*
* If the current erase size is the one, stop here:
* we have found the right uniform Sector Erase command.
@@ -2565,6 +2599,12 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
params->hwcaps.mask |= SNOR_HWCAPS_PP;
spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
SPINOR_OP_PP, SNOR_PROTO_1_1_1);
+
+ if (info->flags & SPI_NOR_QUAD_PP) {
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
+ spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_1_1_4],
+ SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4);
+ }
}
/**
@@ -2840,10 +2880,20 @@ static void spi_nor_put_device(struct mtd_info *mtd)
void spi_nor_restore(struct spi_nor *nor)
{
+ int ret;
+
/* restore the addressing mode */
if (nor->addr_nbytes == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
- nor->flags & SNOR_F_BROKEN_RESET)
- nor->params->set_4byte_addr_mode(nor, false);
+ nor->flags & SNOR_F_BROKEN_RESET) {
+ ret = nor->params->set_4byte_addr_mode(nor, false);
+ if (ret)
+ /*
+ * Do not stop the execution in the hope that the flash
+ * will default to the 3-byte address mode after the
+ * software reset.
+ */
+ dev_err(nor->dev, "Failed to exit 4-byte address mode, err = %d\n", ret);
+ }
if (nor->flags & SNOR_F_SOFT_RESET)
spi_nor_soft_reset(nor);
@@ -2935,6 +2985,27 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
mtd->_put_device = spi_nor_put_device;
}
+static int spi_nor_hw_reset(struct spi_nor *nor)
+{
+ struct gpio_desc *reset;
+
+ reset = devm_gpiod_get_optional(nor->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR_OR_NULL(reset))
+ return PTR_ERR_OR_ZERO(reset);
+
+ /*
+ * Experimental delay values by looking at different flash device
+ * vendors datasheets.
+ */
+ usleep_range(1, 5);
+ gpiod_set_value_cansleep(reset, 1);
+ usleep_range(100, 150);
+ gpiod_set_value_cansleep(reset, 0);
+ usleep_range(1000, 1200);
+
+ return 0;
+}
+
int spi_nor_scan(struct spi_nor *nor, const char *name,
const struct spi_nor_hwcaps *hwcaps)
{
@@ -2967,6 +3038,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
if (!nor->bouncebuf)
return -ENOMEM;
+ ret = spi_nor_hw_reset(nor);
+ if (ret)
+ return ret;
+
info = spi_nor_get_flash_info(nor, name);
if (IS_ERR(info))
return PTR_ERR(info);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 85b0cf254e97..f03b55cf7e6f 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -458,6 +458,7 @@ struct spi_nor_fixups {
* SPI_NOR_NO_ERASE: no erase command needed.
* NO_CHIP_ERASE: chip does not support chip erase.
* SPI_NOR_NO_FR: can't do fastread.
+ * SPI_NOR_QUAD_PP: flash supports Quad Input Page Program.
*
* @no_sfdp_flags: flags that indicate support that can be discovered via SFDP.
* Used when SFDP tables are not defined in the flash. These
@@ -507,6 +508,7 @@ struct flash_info {
#define SPI_NOR_NO_ERASE BIT(6)
#define NO_CHIP_ERASE BIT(7)
#define SPI_NOR_NO_FR BIT(8)
+#define SPI_NOR_QUAD_PP BIT(9)
u8 no_sfdp_flags;
#define SPI_NOR_SKIP_SFDP BIT(0)
@@ -701,6 +703,9 @@ int spi_nor_controller_ops_read_reg(struct spi_nor *nor, u8 opcode,
int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
const u8 *buf, size_t len);
+int spi_nor_check_sfdp_signature(struct spi_nor *nor);
+int spi_nor_parse_sfdp(struct spi_nor *nor);
+
static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
{
return container_of(mtd, struct spi_nor, mtd);
diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c
index df76cb5de3f9..ff895f6758ea 100644
--- a/drivers/mtd/spi-nor/debugfs.c
+++ b/drivers/mtd/spi-nor/debugfs.c
@@ -81,7 +81,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
int i;
seq_printf(s, "name\t\t%s\n", info->name);
- seq_printf(s, "id\t\t%*ph\n", info->id_len, info->id);
+ seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id);
string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf));
seq_printf(s, "size\t\t%s\n", buf);
seq_printf(s, "write size\t%u\n", params->writesize);
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index 119b38e6fc2a..d57ddaf1525b 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -8,19 +8,29 @@
#include "core.h"
-static void gd25q256_default_init(struct spi_nor *nor)
+static int
+gd25q256_post_bfpt(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt)
{
/*
- * Some manufacturer like GigaDevice may use different
- * bit to set QE on different memories, so the MFR can't
- * indicate the quad_enable method for this case, we need
- * to set it in the default_init fixup hook.
+ * GD25Q256C supports the first version of JESD216 which does not define
+ * the Quad Enable methods. Overwrite the default Quad Enable method.
+ *
+ * GD25Q256 GENERATION | SFDP MAJOR VERSION | SFDP MINOR VERSION
+ * GD25Q256C | SFDP_JESD216_MAJOR | SFDP_JESD216_MINOR
+ * GD25Q256D | SFDP_JESD216_MAJOR | SFDP_JESD216B_MINOR
+ * GD25Q256E | SFDP_JESD216_MAJOR | SFDP_JESD216B_MINOR
*/
- nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+ if (bfpt_header->major == SFDP_JESD216_MAJOR &&
+ bfpt_header->minor == SFDP_JESD216_MINOR)
+ nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+
+ return 0;
}
static const struct spi_nor_fixups gd25q256_fixups = {
- .default_init = gd25q256_default_init,
+ .post_bfpt = gd25q256_post_bfpt,
};
static const struct flash_info gigadevice_nor_parts[] = {
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 89a66a19d754..a0ddad2afffc 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -70,9 +70,10 @@ static const struct flash_info issi_nor_parts[] = {
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256)
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512)
- NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
+ { "is25wp256", INFO(0x9d7019, 0, 0, 0)
+ PARSE_SFDP
FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
+ FLAGS(SPI_NOR_QUAD_PP)
.fixups = &is25lp256_fixups },
/* PMC */
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 3c9681a3f7a3..7bb86df52f0b 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -52,18 +52,21 @@ static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
struct spi_mem_op op;
u8 *buf = nor->bouncebuf;
int ret;
+ u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
/* Use 20 dummy cycles for memory array reads. */
*buf = 20;
op = (struct spi_mem_op)
- MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
+ MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
+ SPINOR_REG_MT_CFR1V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
buf[0] = SPINOR_MT_OCT_DTR;
op = (struct spi_mem_op)
- MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
+ MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
+ SPINOR_REG_MT_CFR0V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
@@ -98,7 +101,8 @@ static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
buf[0] = SPINOR_MT_EXSPI;
buf[1] = SPINOR_REG_MT_CFR1V_DEF;
op = (struct spi_mem_op)
- MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
+ MICRON_ST_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
+ SPINOR_REG_MT_CFR0V, 2, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
if (ret)
return ret;
@@ -201,6 +205,8 @@ static const struct flash_info st_nor_parts[] = {
MFR_FLAGS(USE_FSR)
},
{ "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512)
+ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6)
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
MFR_FLAGS(USE_FSR)
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 2257f1b4c2e2..8434f654eca1 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -135,8 +135,7 @@ struct sfdp_4bait {
/**
* spi_nor_read_raw() - raw read of serial flash memory. read_opcode,
* addr_nbytes and read_dummy members of the struct spi_nor
- * should be previously
- * set.
+ * should be previously set.
* @nor: pointer to a 'struct spi_nor'
* @addr: offset in the serial flash memory
* @len: number of bytes to read
@@ -1183,10 +1182,17 @@ static int spi_nor_parse_profile1(struct spi_nor *nor,
dummy = round_up(dummy, 2);
/* Update the fast read settings. */
+ nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
spi_nor_set_read_settings(&nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
0, dummy, opcode,
SNOR_PROTO_8_8_8_DTR);
+ /*
+ * Page Program is "Required Command" in the xSPI Profile 1.0. Update
+ * the params->hwcaps.mask here.
+ */
+ nor->params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
out:
kfree(dwords);
return ret;
@@ -1250,6 +1256,33 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
}
/**
+ * spi_nor_check_sfdp_signature() - check for a valid SFDP signature
+ * @nor: pointer to a 'struct spi_nor'
+ *
+ * Used to detect if the flash supports the RDSFDP command as well as the
+ * presence of a valid SFDP table.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_check_sfdp_signature(struct spi_nor *nor)
+{
+ u32 signature;
+ int err;
+
+ /* Get the SFDP header. */
+ err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(signature),
+ &signature);
+ if (err < 0)
+ return err;
+
+ /* Check the SFDP signature. */
+ if (le32_to_cpu(signature) != SFDP_SIGNATURE)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
*
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index bbf80d2990ab..c1969f0a2f46 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -107,6 +107,4 @@ struct sfdp_parameter_header {
u8 id_msb;
};
-int spi_nor_parse_sfdp(struct spi_nor *nor);
-
#endif /* __LINUX_MTD_SFDP_H */
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 0150049007be..b621cdfd506f 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -49,11 +49,13 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
struct spi_mem_op op;
u8 *buf = nor->bouncebuf;
int ret;
+ u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
/* Use 24 dummy cycles for memory array reads. */
*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
op = (struct spi_mem_op)
- CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR2V, 1, buf);
+ CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
+ SPINOR_REG_CYPRESS_CFR2V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
@@ -64,14 +66,16 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
/* Set the octal and DTR enable bits. */
buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
op = (struct spi_mem_op)
- CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR5V, 1, buf);
+ CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
+ SPINOR_REG_CYPRESS_CFR5V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
/* Read flash ID to make sure the switch was successful. */
- ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
+ ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf,
+ SNOR_PROTO_8_8_8_DTR);
if (ret) {
dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
return ret;
@@ -97,7 +101,8 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
buf[1] = 0;
op = (struct spi_mem_op)
- CYPRESS_NOR_WR_ANY_REG_OP(4, SPINOR_REG_CYPRESS_CFR5V, 2, buf);
+ CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
+ SPINOR_REG_CYPRESS_CFR5V, 2, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
if (ret)
return ret;
@@ -191,7 +196,8 @@ static int cypress_nor_quad_enable_volatile(struct spi_nor *nor)
static int cypress_nor_set_page_size(struct spi_nor *nor)
{
struct spi_mem_op op =
- CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR3V,
+ CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,
+ SPINOR_REG_CYPRESS_CFR3V,
nor->bouncebuf);
int ret;
@@ -275,13 +281,7 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
cypress_nor_octal_dtr_dis(nor);
}
-static void s28hs512t_default_init(struct spi_nor *nor)
-{
- nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
- nor->params->writesize = 16;
-}
-
-static void s28hs512t_post_sfdp_fixup(struct spi_nor *nor)
+static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor)
{
/*
* On older versions of the flash the xSPI Profile 1.0 table has the
@@ -309,17 +309,23 @@ static void s28hs512t_post_sfdp_fixup(struct spi_nor *nor)
nor->params->rdsr_addr_nbytes = 4;
}
-static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
- const struct sfdp_parameter_header *bfpt_header,
- const struct sfdp_bfpt *bfpt)
+static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt)
{
return cypress_nor_set_page_size(nor);
}
-static const struct spi_nor_fixups s28hs512t_fixups = {
- .default_init = s28hs512t_default_init,
- .post_sfdp = s28hs512t_post_sfdp_fixup,
- .post_bfpt = s28hs512t_post_bfpt_fixup,
+static void s28hx_t_late_init(struct spi_nor *nor)
+{
+ nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
+ nor->params->writesize = 16;
+}
+
+static const struct spi_nor_fixups s28hx_t_fixups = {
+ .post_sfdp = s28hx_t_post_sfdp_fixup,
+ .post_bfpt = s28hx_t_post_bfpt_fixup,
+ .late_init = s28hx_t_late_init,
};
static int
@@ -453,10 +459,21 @@ static const struct flash_info spansion_nor_parts[] = {
.fixups = &s25hx_t_fixups },
{ "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
FLAGS(SPI_NOR_NO_ERASE) },
+ { "s28hl512t", INFO(0x345a1a, 0, 256 * 1024, 256)
+ PARSE_SFDP
+ .fixups = &s28hx_t_fixups,
+ },
+ { "s28hl01gt", INFO(0x345a1b, 0, 256 * 1024, 512)
+ PARSE_SFDP
+ .fixups = &s28hx_t_fixups,
+ },
{ "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)
- NO_SFDP_FLAGS(SECT_4K | SPI_NOR_OCTAL_DTR_READ |
- SPI_NOR_OCTAL_DTR_PP)
- .fixups = &s28hs512t_fixups,
+ PARSE_SFDP
+ .fixups = &s28hx_t_fixups,
+ },
+ { "s28hs01gt", INFO(0x345b1b, 0, 256 * 1024, 512)
+ PARSE_SFDP
+ .fixups = &s28hx_t_fixups,
},
};
diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c
index 9aec9d8a98ad..c09bb832b3b9 100644
--- a/drivers/mtd/spi-nor/sysfs.c
+++ b/drivers/mtd/spi-nor/sysfs.c
@@ -35,8 +35,10 @@ static ssize_t jedec_id_show(struct device *dev,
struct spi_device *spi = to_spi_device(dev);
struct spi_mem *spimem = spi_get_drvdata(spi);
struct spi_nor *nor = spi_mem_get_drvdata(spimem);
+ const u8 *id = nor->info->id_len ? nor->info->id : nor->id;
+ u8 id_len = nor->info->id_len ?: SPI_NOR_MAX_ID_LEN;
- return sysfs_emit(buf, "%*phN\n", nor->info->id_len, nor->info->id);
+ return sysfs_emit(buf, "%*phN\n", id_len, id);
}
static DEVICE_ATTR_RO(jedec_id);
@@ -67,6 +69,21 @@ static struct bin_attribute *spi_nor_sysfs_bin_entries[] = {
NULL
};
+static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct spi_device *spi = to_spi_device(kobj_to_dev(kobj));
+ struct spi_mem *spimem = spi_get_drvdata(spi);
+ struct spi_nor *nor = spi_mem_get_drvdata(spimem);
+
+ if (attr == &dev_attr_manufacturer.attr && !nor->manufacturer)
+ return 0;
+ if (attr == &dev_attr_jedec_id.attr && !nor->info->id_len && !nor->id)
+ return 0;
+
+ return 0444;
+}
+
static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj,
struct bin_attribute *attr, int n)
{
@@ -82,6 +99,7 @@ static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj,
static const struct attribute_group spi_nor_sysfs_group = {
.name = "spi-nor",
+ .is_visible = spi_nor_sysfs_is_visible,
.is_bin_visible = spi_nor_sysfs_is_bin_visible,
.attrs = spi_nor_sysfs_entries,
.bin_attrs = spi_nor_sysfs_bin_entries,
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index ffaa24055259..ca39acf4112c 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -133,6 +133,9 @@ static const struct flash_info winbond_nor_parts[] = {
{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024)
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ |
SPI_NOR_DUAL_READ) },
+ { "w25q512nwq", INFO(0xef6020, 0, 0, 0)
+ PARSE_SFDP
+ OTP_INFO(256, 3, 0x1000, 0x1000) },
{ "w25q512nwm", INFO(0xef8020, 0, 64 * 1024, 1024)
PARSE_SFDP
OTP_INFO(256, 3, 0x1000, 0x1000) },
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c3693bb87b4c..b2996dc987ff 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -999,7 +999,6 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand,
bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
-int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
/* ECC related functions */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 42218a1164f6..25765556223a 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -349,6 +349,8 @@ struct spi_nor_flash_parameter;
* @bouncebuf: bounce buffer used when the buffer passed by the MTD
* layer is not DMA-able
* @bouncebuf_size: size of the bounce buffer
+ * @id: The flash's ID bytes. Always contains
+ * SPI_NOR_MAX_ID_LEN bytes.
* @info: SPI NOR part JEDEC MFR ID and other info
* @manufacturer: SPI NOR manufacturer
* @addr_nbytes: number of address bytes
@@ -379,6 +381,7 @@ struct spi_nor {
struct spi_mem *spimem;
u8 *bouncebuf;
size_t bouncebuf_size;
+ u8 *id;
const struct flash_info *info;
const struct spi_nor_manufacturer *manufacturer;
u8 addr_nbytes;