Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mtd/for-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD updates from Miquel Raynal:
"MTD:

- The Carillo Ranch driver has been removed

- Top level mtd bindings have received a couple of improvements
(references, selects)

- The ssfdc driver received few minor adjustments

- The usual load of misc/small improvements and fixes

Raw NAND:

- The main series brought is an update of the Broadcom support to
support all BCMBCA SoCs and their specificity (ECC, write
protection, configuration straps), plus a few misc fixes and
changes in the main driver. Device tree updates are also part of
this PR, initially because of a misunderstanding on my side.

- The STM32_FMC2 controller driver is also upgraded to properly
support MP1 and MP25 SoCs.

- A new compatible is added for an Atmel flavor.

- Among all these feature changes, there is as well a load of
continuous read related fixes, avoiding more corner conditions and
clarifying the logic. Finally a few miscellaneous fixes are made to
the core, the lpx32xx_mlc, fsl_lbc, Meson and Atmel controller
driver, as well as final one in the Hynix vendor driver.

SPI-NAND:

- The ESMT support has been extended to match 5 bytes ID to avoid
collisions. Winbond support on its side receives support for
W25N04KV chips.

SPI NOR:

- SPI NOR gets the non uniform erase code cleaned. We stopped using
bitmasks for erase types and flags, and instead introduced
dedicated members. We then passed the SPI NOR erase map to MTD.
Users can now determine the erase regions and make informed
decisions on partitions size.

- An optional interrupt property is now described in the bindings"

* tag 'mtd/for-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (50 commits)
mtd: rawnand: Ensure continuous reads are well disabled
mtd: rawnand: Constrain even more when continuous reads are enabled
mtd: rawnand: brcmnand: Add support for getting ecc setting from strap
mtd: rawnand: brcmnand: fix sparse warnings
mtd: nand: raw: atmel: Fix comment in timings preparation
mtd: rawnand: Ensure all continuous terms are always in sync
mtd: rawnand: Add a helper for calculating a page index
mtd: rawnand: Fix and simplify again the continuous read derivations
mtd: rawnand: hynix: remove @nand_technology kernel-doc description
dt-bindings: atmel-nand: add microchip,sam9x7-pmecc
mtd: rawnand: brcmnand: Support write protection setting from dts
mtd: rawnand: brcmnand: Add BCMBCA read data bus interface
mtd: rawnand: brcmnand: Rename bcm63138 nand driver
arm64: dts: broadcom: bcmbca: Update router boards
arm64: dts: broadcom: bcmbca: Add NAND controller node
ARM: dts: broadcom: bcmbca: Add NAND controller node
mtd: spi-nor: core: correct type of i
mtd: spi-nor: core: set mtd->eraseregions for non-uniform erase map
mtd: spi-nor: core: get rid of SNOR_OVERLAID_REGION flag
mtd: spi-nor: core: get rid of SNOR_LAST_REGION flag
...

+981 -657
+1
Documentation/devicetree/bindings/mtd/atmel-nand.txt
··· 56 56 "atmel,sama5d4-pmecc" 57 57 "atmel,sama5d2-pmecc" 58 58 "microchip,sam9x60-pmecc" 59 + "microchip,sam9x7-pmecc", "atmel,at91sam9g45-pmecc" 59 60 - reg: should contain 2 register ranges. The first one is pointing to the PMECC 60 61 block, and the second one to the PMECC_ERRLOC block. 61 62
+39 -5
Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
··· 9 9 maintainers: 10 10 - Brian Norris <computersforpeace@gmail.com> 11 11 - Kamal Dasu <kdasu.kdev@gmail.com> 12 + - William Zhang <william.zhang@broadcom.com> 12 13 13 14 description: | 14 15 The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND ··· 19 18 supports basic PROGRAM and READ functions, among other features. 20 19 21 20 This controller was originally designed for STB SoCs (BCM7xxx) but is now 22 - available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and 23 - iProc/Cygnus. Its history includes several similar (but not fully register 24 - compatible) versions. 21 + available on a variety of Broadcom SoCs, including some BCM3xxx, MIPS based 22 + Broadband SoC (BCM63xx), ARM based Broadband SoC (BCMBCA) and iProc/Cygnus. 23 + Its history includes several similar (but not fully register compatible) 24 + versions. 25 25 26 26 -- Additional SoC-specific NAND controller properties -- 27 27 ··· 55 53 - brcm,brcmnand-v7.2 56 54 - brcm,brcmnand-v7.3 57 55 - const: brcm,brcmnand 58 - - description: BCM63138 SoC-specific NAND controller 56 + - description: BCMBCA SoC-specific NAND controller 59 57 items: 60 58 - const: brcm,nand-bcm63138 61 59 - enum: ··· 113 111 earlier versions of this core that include WP 114 112 type: boolean 115 113 114 + brcm,wp-not-connected: 115 + description: 116 + Use this property when WP pin is not physically wired to the NAND chip. 117 + Write protection feature cannot be used. By default, controller assumes 118 + the pin is connected and feature is used. 119 + $ref: /schemas/types.yaml#/definitions/flag 120 + 116 121 patternProperties: 117 122 "^nand@[a-f0-9]$": 118 123 type: object ··· 145 136 number of available options for its default ECC 146 137 layout. 147 138 $ref: /schemas/types.yaml#/definitions/uint32 139 + 140 + brcm,nand-ecc-use-strap: 141 + description: 142 + This property requires the host system to get the ECC related 143 + settings from the SoC NAND boot strap configuration instead of 144 + the generic NAND ECC settings. This is a common hardware design 145 + on BCMBCA based boards. This strap ECC option and generic NAND 146 + ECC option can not be specified at the same time. 147 + $ref: /schemas/types.yaml#/definitions/flag 148 148 149 149 unevaluatedProperties: false 150 150 ··· 195 177 - const: iproc-idm 196 178 - const: iproc-ext 197 179 - if: 180 + required: 181 + - interrupts 198 182 properties: 199 183 interrupts: 200 184 minItems: 2 ··· 204 184 required: 205 185 - interrupt-names 206 186 187 + - if: 188 + patternProperties: 189 + "^nand@[a-f0-9]$": 190 + required: 191 + - brcm,nand-ecc-use-strap 192 + then: 193 + patternProperties: 194 + "^nand@[a-f0-9]$": 195 + properties: 196 + nand-ecc-strength: false 197 + nand-ecc-step-size: false 198 + nand-ecc-maximize: false 199 + nand-ecc-algo: false 200 + brcm,nand-oob-sector-size: false 201 + 207 202 unevaluatedProperties: false 208 203 209 204 required: 210 205 - reg 211 206 - reg-names 212 - - interrupts 213 207 214 208 examples: 215 209 - |
+1 -1
Documentation/devicetree/bindings/mtd/davinci-nand.txt
··· 68 68 false. 69 69 70 70 Nand device bindings may contain additional sub-nodes describing partitions of 71 - the address space. See partition.txt for more detail. The NAND Flash timing 71 + the address space. See mtd.yaml for more detail. The NAND Flash timing 72 72 values must be programmed in the chip select’s node of AEMIF 73 73 memory-controller (see Documentation/devicetree/bindings/memory-controllers/ 74 74 davinci-aemif.txt).
+1 -1
Documentation/devicetree/bindings/mtd/flctl-nand.txt
··· 15 15 completing the bindings. 16 16 17 17 The device tree may optionally contain sub-nodes describing partitions of the 18 - address space. See partition.txt for more detail. 18 + address space. See mtd.yaml for more detail. 19 19 20 20 Example: 21 21
+1 -1
Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt
··· 22 22 (R/B# pins not connected). 23 23 24 24 Each flash chip described may optionally contain additional sub-nodes 25 - describing partitions of the address space. See partition.txt for more 25 + describing partitions of the address space. See mtd.yaml for more 26 26 detail. 27 27 28 28 Examples:
+1 -1
Documentation/devicetree/bindings/mtd/gpio-control-nand.txt
··· 26 26 read to ensure that the GPIO accesses have completed. 27 27 28 28 The device tree may optionally contain sub-nodes describing partitions of the 29 - address space. See partition.txt for more detail. 29 + address space. See mtd.yaml for more detail. 30 30 31 31 Examples: 32 32
+1 -1
Documentation/devicetree/bindings/mtd/gpmi-nand.yaml
··· 12 12 description: | 13 13 The GPMI nand controller provides an interface to control the NAND 14 14 flash chips. The device tree may optionally contain sub-nodes 15 - describing partitions of the address space. See partition.txt for 15 + describing partitions of the address space. See mtd.yaml for 16 16 more detail. 17 17 18 18 properties:
+1 -1
Documentation/devicetree/bindings/mtd/hisi504-nand.txt
··· 22 22 - nand-ecc-strength = <16>, nand-ecc-step-size = <1024> 23 23 24 24 Flash chip may optionally contain additional sub-nodes describing partitions of 25 - the address space. See partition.txt for more detail. 25 + the address space. See mtd.yaml for more detail. 26 26 27 27 Example: 28 28
+3
Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
··· 52 52 minItems: 1 53 53 maxItems: 2 54 54 55 + interrupts: 56 + maxItems: 1 57 + 55 58 m25p,fast-read: 56 59 type: boolean 57 60 description:
+2
Documentation/devicetree/bindings/mtd/mtd.yaml
··· 10 10 - Miquel Raynal <miquel.raynal@bootlin.com> 11 11 - Richard Weinberger <richard@nod.at> 12 12 13 + select: false 14 + 13 15 properties: 14 16 $nodename: 15 17 pattern: "^(flash|.*sram|nand)(@.*)?$"
+1 -1
Documentation/devicetree/bindings/mtd/nvidia-tegra20-nand.txt
··· 39 39 - wp-gpios: GPIO specifier for the write protect pin. 40 40 41 41 Optional child node of NAND chip nodes: 42 - Partitions: see partition.txt 42 + Partitions: see mtd.yaml 43 43 44 44 Example: 45 45 nand-controller@70008000 {
+1 -1
Documentation/devicetree/bindings/mtd/orion-nand.txt
··· 13 13 registers in usecs 14 14 15 15 The device tree may optionally contain sub-nodes describing partitions of the 16 - address space. See partition.txt for more detail. 16 + address space. See mtd.yaml for more detail. 17 17 18 18 Example: 19 19
+1 -1
Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
··· 19 19 20 20 Each child device node may optionally contain a 'partitions' sub-node, 21 21 which further contains sub-nodes describing the flash partition mapping. 22 - See partition.txt for more detail. 22 + See mtd.yaml for more detail. 23 23 24 24 Example: 25 25
+24 -1
Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
··· 14 14 enum: 15 15 - st,stm32mp15-fmc2 16 16 - st,stm32mp1-fmc2-nfc 17 + - st,stm32mp25-fmc2-nfc 17 18 18 19 reg: 19 20 minItems: 6 20 - maxItems: 7 21 + maxItems: 12 21 22 22 23 interrupts: 23 24 maxItems: 1 ··· 92 91 - description: Chip select 1 data 93 92 - description: Chip select 1 command 94 93 - description: Chip select 1 address space 94 + 95 + - if: 96 + properties: 97 + compatible: 98 + contains: 99 + const: st,stm32mp25-fmc2-nfc 100 + then: 101 + properties: 102 + reg: 103 + items: 104 + - description: Chip select 0 data 105 + - description: Chip select 0 command 106 + - description: Chip select 0 address space 107 + - description: Chip select 1 data 108 + - description: Chip select 1 command 109 + - description: Chip select 1 address space 110 + - description: Chip select 2 data 111 + - description: Chip select 2 command 112 + - description: Chip select 2 address space 113 + - description: Chip select 3 data 114 + - description: Chip select 3 command 115 + - description: Chip select 3 address space 95 116 96 117 required: 97 118 - compatible
+14
arch/arm/boot/dts/broadcom/bcm47622.dtsi
··· 138 138 status = "disabled"; 139 139 }; 140 140 141 + nand_controller: nand-controller@1800 { 142 + #address-cells = <1>; 143 + #size-cells = <0>; 144 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 145 + reg = <0x1800 0x600>, <0x2000 0x10>; 146 + reg-names = "nand", "nand-int-base"; 147 + status = "disabled"; 148 + 149 + nandcs: nand@0 { 150 + compatible = "brcm,nandcs"; 151 + reg = <0>; 152 + }; 153 + }; 154 + 141 155 uart0: serial@12000 { 142 156 compatible = "arm,pl011", "arm,primecell"; 143 157 reg = <0x12000 0x1000>;
+6 -1
arch/arm/boot/dts/broadcom/bcm63138.dtsi
··· 229 229 reg-names = "nand", "nand-int-base"; 230 230 status = "disabled"; 231 231 interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; 232 - interrupt-names = "nand"; 232 + interrupt-names = "nand_ctlrdy"; 233 + 234 + nandcs: nand@0 { 235 + compatible = "brcm,nandcs"; 236 + reg = <0>; 237 + }; 233 238 }; 234 239 235 240 serial@4400 {
+14
arch/arm/boot/dts/broadcom/bcm63148.dtsi
··· 119 119 num-cs = <8>; 120 120 status = "disabled"; 121 121 }; 122 + 123 + nand_controller: nand-controller@2000 { 124 + #address-cells = <1>; 125 + #size-cells = <0>; 126 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 127 + reg = <0x2000 0x600>, <0xf0 0x10>; 128 + reg-names = "nand", "nand-int-base"; 129 + status = "disabled"; 130 + 131 + nandcs: nand@0 { 132 + compatible = "brcm,nandcs"; 133 + reg = <0>; 134 + }; 135 + }; 122 136 }; 123 137 };
+14
arch/arm/boot/dts/broadcom/bcm63178.dtsi
··· 129 129 status = "disabled"; 130 130 }; 131 131 132 + nand_controller: nand-controller@1800 { 133 + #address-cells = <1>; 134 + #size-cells = <0>; 135 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 136 + reg = <0x1800 0x600>, <0x2000 0x10>; 137 + reg-names = "nand", "nand-int-base"; 138 + status = "disabled"; 139 + 140 + nandcs: nand@0 { 141 + compatible = "brcm,nandcs"; 142 + reg = <0>; 143 + }; 144 + }; 145 + 132 146 uart0: serial@12000 { 133 147 compatible = "arm,pl011", "arm,primecell"; 134 148 reg = <0x12000 0x1000>;
+14
arch/arm/boot/dts/broadcom/bcm6756.dtsi
··· 139 139 status = "disabled"; 140 140 }; 141 141 142 + nand_controller: nand-controller@1800 { 143 + #address-cells = <1>; 144 + #size-cells = <0>; 145 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 146 + reg = <0x1800 0x600>, <0x2000 0x10>; 147 + reg-names = "nand", "nand-int-base"; 148 + status = "disabled"; 149 + 150 + nandcs: nand@0 { 151 + compatible = "brcm,nandcs"; 152 + reg = <0>; 153 + }; 154 + }; 155 + 142 156 uart0: serial@12000 { 143 157 compatible = "arm,pl011", "arm,primecell"; 144 158 reg = <0x12000 0x1000>;
+14
arch/arm/boot/dts/broadcom/bcm6846.dtsi
··· 119 119 num-cs = <8>; 120 120 status = "disabled"; 121 121 }; 122 + 123 + nand_controller: nand-controller@1800 { 124 + #address-cells = <1>; 125 + #size-cells = <0>; 126 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 127 + reg = <0x1800 0x600>, <0x2000 0x10>; 128 + reg-names = "nand", "nand-int-base"; 129 + status = "disabled"; 130 + 131 + nandcs: nand@0 { 132 + compatible = "brcm,nandcs"; 133 + reg = <0>; 134 + }; 135 + }; 122 136 }; 123 137 };
+14
arch/arm/boot/dts/broadcom/bcm6855.dtsi
··· 129 129 status = "disabled"; 130 130 }; 131 131 132 + nand_controller: nand-controller@1800 { 133 + #address-cells = <1>; 134 + #size-cells = <0>; 135 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 136 + reg = <0x1800 0x600>, <0x2000 0x10>; 137 + reg-names = "nand", "nand-int-base"; 138 + status = "disabled"; 139 + 140 + nandcs: nand@0 { 141 + compatible = "brcm,nandcs"; 142 + reg = <0>; 143 + }; 144 + }; 145 + 132 146 uart0: serial@12000 { 133 147 compatible = "arm,pl011", "arm,primecell"; 134 148 reg = <0x12000 0x1000>;
+14
arch/arm/boot/dts/broadcom/bcm6878.dtsi
··· 120 120 status = "disabled"; 121 121 }; 122 122 123 + nand_controller: nand-controller@1800 { 124 + #address-cells = <1>; 125 + #size-cells = <0>; 126 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 127 + reg = <0x1800 0x600>, <0x2000 0x10>; 128 + reg-names = "nand", "nand-int-base"; 129 + status = "disabled"; 130 + 131 + nandcs: nand@0 { 132 + compatible = "brcm,nandcs"; 133 + reg = <0>; 134 + }; 135 + }; 136 + 123 137 uart0: serial@12000 { 124 138 compatible = "arm,pl011", "arm,primecell"; 125 139 reg = <0x12000 0x1000>;
+10
arch/arm/boot/dts/broadcom/bcm947622.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm963138.dts
··· 29 29 &hsspi { 30 30 status = "okay"; 31 31 }; 32 + 33 + &nand_controller { 34 + brcm,wp-not-connected; 35 + status = "okay"; 36 + }; 37 + 38 + &nandcs { 39 + nand-on-flash-bbt; 40 + brcm,nand-ecc-use-strap; 41 + };
+7 -7
arch/arm/boot/dts/broadcom/bcm963138dvt.dts
··· 32 32 }; 33 33 34 34 &nand_controller { 35 + brcm,wp-not-connected; 35 36 status = "okay"; 37 + }; 36 38 37 - nand@0 { 38 - compatible = "brcm,nandcs"; 39 - reg = <0>; 40 - nand-ecc-strength = <4>; 41 - nand-ecc-step-size = <512>; 42 - brcm,nand-oob-sectors-size = <16>; 43 - }; 39 + &nandcs { 40 + nand-ecc-strength = <4>; 41 + nand-ecc-step-size = <512>; 42 + brcm,nand-oob-sector-size = <16>; 43 + nand-on-flash-bbt; 44 44 }; 45 45 46 46 &ahci {
+10
arch/arm/boot/dts/broadcom/bcm963148.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm963178.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm96756.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm96846.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm96855.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm/boot/dts/broadcom/bcm96878.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+5
arch/arm64/boot/dts/broadcom/bcmbca/bcm4906-netgear-r8000p.dts
··· 125 125 }; 126 126 }; 127 127 128 + &nand_controller { 129 + brcm,wp-not-connected; 130 + status = "okay"; 131 + }; 132 + 128 133 &nandcs { 129 134 nand-ecc-strength = <4>; 130 135 nand-ecc-step-size = <512>;
+5 -1
arch/arm64/boot/dts/broadcom/bcmbca/bcm4908-asus-gt-ac5300.dts
··· 166 166 }; 167 167 }; 168 168 169 + &nand_controller { 170 + brcm,wp-not-connected; 171 + status = "okay"; 172 + }; 173 + 169 174 &nandcs { 170 175 nand-ecc-strength = <4>; 171 176 nand-ecc-step-size = <512>; 172 177 nand-on-flash-bbt; 173 - brcm,nand-has-wp; 174 178 175 179 #address-cells = <1>; 176 180 #size-cells = <0>;
+2 -2
arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
··· 589 589 status = "disabled"; 590 590 }; 591 591 592 - nand-controller@1800 { 592 + nand_controller: nand-controller@1800 { 593 593 #address-cells = <1>; 594 594 #size-cells = <0>; 595 595 compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; ··· 597 597 reg-names = "nand", "nand-int-base"; 598 598 interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; 599 599 interrupt-names = "nand_ctlrdy"; 600 - status = "okay"; 600 + status = "disabled"; 601 601 602 602 nandcs: nand@0 { 603 603 compatible = "brcm,nandcs";
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi
··· 138 138 status = "disabled"; 139 139 }; 140 140 141 + nand_controller: nand-controller@1800 { 142 + #address-cells = <1>; 143 + #size-cells = <0>; 144 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 145 + reg = <0x1800 0x600>, <0x2000 0x10>; 146 + reg-names = "nand", "nand-int-base"; 147 + status = "disabled"; 148 + 149 + nandcs: nand@0 { 150 + compatible = "brcm,nandcs"; 151 + reg = <0>; 152 + }; 153 + }; 154 + 141 155 uart0: serial@12000 { 142 156 compatible = "arm,pl011", "arm,primecell"; 143 157 reg = <0x12000 0x1000>;
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi
··· 119 119 status = "disabled"; 120 120 }; 121 121 122 + nand_controller: nand-controller@1800 { 123 + #address-cells = <1>; 124 + #size-cells = <0>; 125 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 126 + reg = <0x1800 0x600>, <0x2000 0x10>; 127 + reg-names = "nand", "nand-int-base"; 128 + status = "disabled"; 129 + 130 + nandcs: nand@0 { 131 + compatible = "brcm,nandcs"; 132 + reg = <0>; 133 + }; 134 + }; 135 + 122 136 uart0: serial@12000 { 123 137 compatible = "arm,pl011", "arm,primecell"; 124 138 reg = <0x12000 0x1000>;
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi
··· 137 137 status = "disabled"; 138 138 }; 139 139 140 + nand_controller: nand-controller@1800 { 141 + #address-cells = <1>; 142 + #size-cells = <0>; 143 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 144 + reg = <0x1800 0x600>, <0x2000 0x10>; 145 + reg-names = "nand", "nand-int-base"; 146 + status = "disabled"; 147 + 148 + nandcs: nand@0 { 149 + compatible = "brcm,nandcs"; 150 + reg = <0>; 151 + }; 152 + }; 153 + 140 154 uart0: serial@12000 { 141 155 compatible = "arm,pl011", "arm,primecell"; 142 156 reg = <0x12000 0x1000>;
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi
··· 138 138 status = "disabled"; 139 139 }; 140 140 141 + nand_controller: nand-controller@1800 { 142 + #address-cells = <1>; 143 + #size-cells = <0>; 144 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 145 + reg = <0x1800 0x600>, <0x2000 0x10>; 146 + reg-names = "nand", "nand-int-base"; 147 + status = "disabled"; 148 + 149 + nandcs: nand@0 { 150 + compatible = "brcm,nandcs"; 151 + reg = <0>; 152 + }; 153 + }; 154 + 141 155 uart0: serial@12000 { 142 156 compatible = "arm,pl011", "arm,primecell"; 143 157 reg = <0x12000 0x1000>;
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi
··· 119 119 num-cs = <8>; 120 120 status = "disabled"; 121 121 }; 122 + 123 + nand_controller: nand-controller@1800 { 124 + #address-cells = <1>; 125 + #size-cells = <0>; 126 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 127 + reg = <0x1800 0x600>, <0x2000 0x10>; 128 + reg-names = "nand", "nand-int-base"; 129 + status = "disabled"; 130 + 131 + nandcs: nand@0 { 132 + compatible = "brcm,nandcs"; 133 + reg = <0>; 134 + }; 135 + }; 122 136 }; 123 137 };
+14
arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi
··· 156 156 num-cs = <8>; 157 157 status = "disabled"; 158 158 }; 159 + 160 + nand_controller: nand-controller@1800 { 161 + #address-cells = <1>; 162 + #size-cells = <0>; 163 + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; 164 + reg = <0x1800 0x600>, <0x2000 0x10>; 165 + reg-names = "nand", "nand-int-base"; 166 + status = "disabled"; 167 + 168 + nandcs: nand@0 { 169 + compatible = "brcm,nandcs"; 170 + reg = <0>; 171 + }; 172 + }; 159 173 }; 160 174 };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm94908.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm94912.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm963146.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm963158.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm96813.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm96856.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+10
arch/arm64/boot/dts/broadcom/bcmbca/bcm96858.dts
··· 32 32 &hsspi { 33 33 status = "okay"; 34 34 }; 35 + 36 + &nand_controller { 37 + brcm,wp-not-connected; 38 + status = "okay"; 39 + }; 40 + 41 + &nandcs { 42 + nand-on-flash-bbt; 43 + brcm,nand-ecc-use-strap; 44 + };
+2 -2
drivers/mtd/chips/cfi_cmdset_0002.c
··· 2411 2411 static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) 2412 2412 { 2413 2413 struct cfi_private *cfi = map->fldrv_priv; 2414 - unsigned long timeo = jiffies + HZ; 2414 + unsigned long timeo; 2415 2415 unsigned long int adr; 2416 2416 DECLARE_WAITQUEUE(wait, current); 2417 2417 int ret; ··· 2512 2512 static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) 2513 2513 { 2514 2514 struct cfi_private *cfi = map->fldrv_priv; 2515 - unsigned long timeo = jiffies + HZ; 2515 + unsigned long timeo; 2516 2516 DECLARE_WAITQUEUE(wait, current); 2517 2517 int ret; 2518 2518 int retry_cnt = 0;
-7
drivers/mtd/maps/Kconfig
··· 341 341 help 342 342 Map driver to support image based filesystems for uClinux. 343 343 344 - config MTD_INTEL_VR_NOR 345 - tristate "NOR flash on Intel Vermilion Range Expansion Bus CS0" 346 - depends on PCI 347 - help 348 - Map driver for a NOR flash bank located on the Expansion Bus of the 349 - Intel Vermilion Range chipset. 350 - 351 344 config MTD_PLATRAM 352 345 tristate "Map driver for platform device RAM (mtd-ram)" 353 346 select MTD_RAM
-1
drivers/mtd/maps/Makefile
··· 40 40 obj-$(CONFIG_MTD_NETtel) += nettel.o 41 41 obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o 42 42 obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o 43 - obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o 44 43 obj-$(CONFIG_MTD_VMU) += vmu-flash.o 45 44 obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
-265
drivers/mtd/maps/intel_vr_nor.c
··· 1 - /* 2 - * drivers/mtd/maps/intel_vr_nor.c 3 - * 4 - * An MTD map driver for a NOR flash bank on the Expansion Bus of the Intel 5 - * Vermilion Range chipset. 6 - * 7 - * The Vermilion Range Expansion Bus supports four chip selects, each of which 8 - * has 64MiB of address space. The 2nd BAR of the Expansion Bus PCI Device 9 - * is a 256MiB memory region containing the address spaces for all four of the 10 - * chip selects, with start addresses hardcoded on 64MiB boundaries. 11 - * 12 - * This map driver only supports NOR flash on chip select 0. The buswidth 13 - * (either 8 bits or 16 bits) is determined by reading the Expansion Bus Timing 14 - * and Control Register for Chip Select 0 (EXP_TIMING_CS0). This driver does 15 - * not modify the value in the EXP_TIMING_CS0 register except to enable writing 16 - * and disable boot acceleration. The timing parameters in the register are 17 - * assumed to have been properly initialized by the BIOS. The reset default 18 - * timing parameters are maximally conservative (slow), so access to the flash 19 - * will be slower than it should be if the BIOS has not initialized the timing 20 - * parameters. 21 - * 22 - * Author: Andy Lowe <alowe@mvista.com> 23 - * 24 - * 2006 (c) MontaVista Software, Inc. This file is licensed under 25 - * the terms of the GNU General Public License version 2. This program 26 - * is licensed "as is" without any warranty of any kind, whether express 27 - * or implied. 28 - */ 29 - 30 - #include <linux/module.h> 31 - #include <linux/kernel.h> 32 - #include <linux/slab.h> 33 - #include <linux/pci.h> 34 - #include <linux/mtd/mtd.h> 35 - #include <linux/mtd/map.h> 36 - #include <linux/mtd/partitions.h> 37 - #include <linux/mtd/cfi.h> 38 - #include <linux/mtd/flashchip.h> 39 - 40 - #define DRV_NAME "vr_nor" 41 - 42 - struct vr_nor_mtd { 43 - void __iomem *csr_base; 44 - struct map_info map; 45 - struct mtd_info *info; 46 - struct pci_dev *dev; 47 - }; 48 - 49 - /* Expansion Bus Configuration and Status Registers are in BAR 0 */ 50 - #define EXP_CSR_MBAR 0 51 - /* Expansion Bus Memory Window is BAR 1 */ 52 - #define EXP_WIN_MBAR 1 53 - /* Maximum address space for Chip Select 0 is 64MiB */ 54 - #define CS0_SIZE 0x04000000 55 - /* Chip Select 0 is at offset 0 in the Memory Window */ 56 - #define CS0_START 0x0 57 - /* Chip Select 0 Timing Register is at offset 0 in CSR */ 58 - #define EXP_TIMING_CS0 0x00 59 - #define TIMING_CS_EN (1 << 31) /* Chip Select Enable */ 60 - #define TIMING_BOOT_ACCEL_DIS (1 << 8) /* Boot Acceleration Disable */ 61 - #define TIMING_WR_EN (1 << 1) /* Write Enable */ 62 - #define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ 63 - #define TIMING_MASK 0x3FFF0000 64 - 65 - static void vr_nor_destroy_partitions(struct vr_nor_mtd *p) 66 - { 67 - mtd_device_unregister(p->info); 68 - } 69 - 70 - static int vr_nor_init_partitions(struct vr_nor_mtd *p) 71 - { 72 - /* register the flash bank */ 73 - /* partition the flash bank */ 74 - return mtd_device_register(p->info, NULL, 0); 75 - } 76 - 77 - static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) 78 - { 79 - map_destroy(p->info); 80 - } 81 - 82 - static int vr_nor_mtd_setup(struct vr_nor_mtd *p) 83 - { 84 - static const char * const probe_types[] = 85 - { "cfi_probe", "jedec_probe", NULL }; 86 - const char * const *type; 87 - 88 - for (type = probe_types; !p->info && *type; type++) 89 - p->info = do_map_probe(*type, &p->map); 90 - if (!p->info) 91 - return -ENODEV; 92 - 93 - p->info->dev.parent = &p->dev->dev; 94 - 95 - return 0; 96 - } 97 - 98 - static void vr_nor_destroy_maps(struct vr_nor_mtd *p) 99 - { 100 - unsigned int exp_timing_cs0; 101 - 102 - /* write-protect the flash bank */ 103 - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); 104 - exp_timing_cs0 &= ~TIMING_WR_EN; 105 - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); 106 - 107 - /* unmap the flash window */ 108 - iounmap(p->map.virt); 109 - 110 - /* unmap the csr window */ 111 - iounmap(p->csr_base); 112 - } 113 - 114 - /* 115 - * Initialize the map_info structure and map the flash. 116 - * Returns 0 on success, nonzero otherwise. 117 - */ 118 - static int vr_nor_init_maps(struct vr_nor_mtd *p) 119 - { 120 - unsigned long csr_phys, csr_len; 121 - unsigned long win_phys, win_len; 122 - unsigned int exp_timing_cs0; 123 - int err; 124 - 125 - csr_phys = pci_resource_start(p->dev, EXP_CSR_MBAR); 126 - csr_len = pci_resource_len(p->dev, EXP_CSR_MBAR); 127 - win_phys = pci_resource_start(p->dev, EXP_WIN_MBAR); 128 - win_len = pci_resource_len(p->dev, EXP_WIN_MBAR); 129 - 130 - if (!csr_phys || !csr_len || !win_phys || !win_len) 131 - return -ENODEV; 132 - 133 - if (win_len < (CS0_START + CS0_SIZE)) 134 - return -ENXIO; 135 - 136 - p->csr_base = ioremap(csr_phys, csr_len); 137 - if (!p->csr_base) 138 - return -ENOMEM; 139 - 140 - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); 141 - if (!(exp_timing_cs0 & TIMING_CS_EN)) { 142 - dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " 143 - "is disabled.\n"); 144 - err = -ENODEV; 145 - goto release; 146 - } 147 - if ((exp_timing_cs0 & TIMING_MASK) == TIMING_MASK) { 148 - dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " 149 - "is configured for maximally slow access times.\n"); 150 - } 151 - p->map.name = DRV_NAME; 152 - p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2; 153 - p->map.phys = win_phys + CS0_START; 154 - p->map.size = CS0_SIZE; 155 - p->map.virt = ioremap(p->map.phys, p->map.size); 156 - if (!p->map.virt) { 157 - err = -ENOMEM; 158 - goto release; 159 - } 160 - simple_map_init(&p->map); 161 - 162 - /* Enable writes to flash bank */ 163 - exp_timing_cs0 |= TIMING_BOOT_ACCEL_DIS | TIMING_WR_EN; 164 - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); 165 - 166 - return 0; 167 - 168 - release: 169 - iounmap(p->csr_base); 170 - return err; 171 - } 172 - 173 - static const struct pci_device_id vr_nor_pci_ids[] = { 174 - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)}, 175 - {0,} 176 - }; 177 - 178 - static void vr_nor_pci_remove(struct pci_dev *dev) 179 - { 180 - struct vr_nor_mtd *p = pci_get_drvdata(dev); 181 - 182 - vr_nor_destroy_partitions(p); 183 - vr_nor_destroy_mtd_setup(p); 184 - vr_nor_destroy_maps(p); 185 - kfree(p); 186 - pci_release_regions(dev); 187 - pci_disable_device(dev); 188 - } 189 - 190 - static int vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 191 - { 192 - struct vr_nor_mtd *p = NULL; 193 - unsigned int exp_timing_cs0; 194 - int err; 195 - 196 - err = pci_enable_device(dev); 197 - if (err) 198 - goto out; 199 - 200 - err = pci_request_regions(dev, DRV_NAME); 201 - if (err) 202 - goto disable_dev; 203 - 204 - p = kzalloc(sizeof(*p), GFP_KERNEL); 205 - err = -ENOMEM; 206 - if (!p) 207 - goto release; 208 - 209 - p->dev = dev; 210 - 211 - err = vr_nor_init_maps(p); 212 - if (err) 213 - goto release; 214 - 215 - err = vr_nor_mtd_setup(p); 216 - if (err) 217 - goto destroy_maps; 218 - 219 - err = vr_nor_init_partitions(p); 220 - if (err) 221 - goto destroy_mtd_setup; 222 - 223 - pci_set_drvdata(dev, p); 224 - 225 - return 0; 226 - 227 - destroy_mtd_setup: 228 - map_destroy(p->info); 229 - 230 - destroy_maps: 231 - /* write-protect the flash bank */ 232 - exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); 233 - exp_timing_cs0 &= ~TIMING_WR_EN; 234 - writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); 235 - 236 - /* unmap the flash window */ 237 - iounmap(p->map.virt); 238 - 239 - /* unmap the csr window */ 240 - iounmap(p->csr_base); 241 - 242 - release: 243 - kfree(p); 244 - pci_release_regions(dev); 245 - 246 - disable_dev: 247 - pci_disable_device(dev); 248 - 249 - out: 250 - return err; 251 - } 252 - 253 - static struct pci_driver vr_nor_pci_driver = { 254 - .name = DRV_NAME, 255 - .probe = vr_nor_pci_probe, 256 - .remove = vr_nor_pci_remove, 257 - .id_table = vr_nor_pci_ids, 258 - }; 259 - 260 - module_pci_driver(vr_nor_pci_driver); 261 - 262 - MODULE_AUTHOR("Andy Lowe"); 263 - MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); 264 - MODULE_LICENSE("GPL"); 265 - MODULE_DEVICE_TABLE(pci, vr_nor_pci_ids);
+1 -1
drivers/mtd/maps/physmap-core.c
··· 518 518 if (!info->maps[i].phys) 519 519 info->maps[i].phys = res->start; 520 520 521 - info->win_order = get_bitmask_order(resource_size(res)) - 1; 521 + info->win_order = fls64(resource_size(res)) - 1; 522 522 info->maps[i].size = BIT(info->win_order + 523 523 (info->gpios ? 524 524 info->gpios->ndescs : 0));
+1 -1
drivers/mtd/nand/raw/atmel/nand-controller.c
··· 1378 1378 return ret; 1379 1379 1380 1380 /* 1381 - * The write cycle timing is directly matching tWC, but is also 1381 + * The read cycle timing is directly matching tRC, but is also 1382 1382 * dependent on the setup and hold timings we calculated earlier, 1383 1383 * which gives: 1384 1384 *
+1 -1
drivers/mtd/nand/raw/brcmnand/Makefile
··· 2 2 # link order matters; don't link the more generic brcmstb_nand.o before the 3 3 # more specific iproc_nand.o, for instance 4 4 obj-$(CONFIG_MTD_NAND_BRCMNAND_IPROC) += iproc_nand.o 5 - obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcm63138_nand.o 5 + obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcmbca_nand.o 6 6 obj-$(CONFIG_MTD_NAND_BRCMNAND_BCM63XX) += bcm6368_nand.o 7 7 obj-$(CONFIG_MTD_NAND_BRCMNAND_BRCMSTB) += brcmstb_nand.o 8 8 obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
-99
drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Copyright © 2015 Broadcom Corporation 4 - */ 5 - 6 - #include <linux/device.h> 7 - #include <linux/io.h> 8 - #include <linux/ioport.h> 9 - #include <linux/module.h> 10 - #include <linux/of.h> 11 - #include <linux/of_address.h> 12 - #include <linux/platform_device.h> 13 - #include <linux/slab.h> 14 - 15 - #include "brcmnand.h" 16 - 17 - struct bcm63138_nand_soc { 18 - struct brcmnand_soc soc; 19 - void __iomem *base; 20 - }; 21 - 22 - #define BCM63138_NAND_INT_STATUS 0x00 23 - #define BCM63138_NAND_INT_EN 0x04 24 - 25 - enum { 26 - BCM63138_CTLRDY = BIT(4), 27 - }; 28 - 29 - static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc) 30 - { 31 - struct bcm63138_nand_soc *priv = 32 - container_of(soc, struct bcm63138_nand_soc, soc); 33 - void __iomem *mmio = priv->base + BCM63138_NAND_INT_STATUS; 34 - u32 val = brcmnand_readl(mmio); 35 - 36 - if (val & BCM63138_CTLRDY) { 37 - brcmnand_writel(val & ~BCM63138_CTLRDY, mmio); 38 - return true; 39 - } 40 - 41 - return false; 42 - } 43 - 44 - static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en) 45 - { 46 - struct bcm63138_nand_soc *priv = 47 - container_of(soc, struct bcm63138_nand_soc, soc); 48 - void __iomem *mmio = priv->base + BCM63138_NAND_INT_EN; 49 - u32 val = brcmnand_readl(mmio); 50 - 51 - if (en) 52 - val |= BCM63138_CTLRDY; 53 - else 54 - val &= ~BCM63138_CTLRDY; 55 - 56 - brcmnand_writel(val, mmio); 57 - } 58 - 59 - static int bcm63138_nand_probe(struct platform_device *pdev) 60 - { 61 - struct device *dev = &pdev->dev; 62 - struct bcm63138_nand_soc *priv; 63 - struct brcmnand_soc *soc; 64 - 65 - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 66 - if (!priv) 67 - return -ENOMEM; 68 - soc = &priv->soc; 69 - 70 - priv->base = devm_platform_ioremap_resource_byname(pdev, "nand-int-base"); 71 - if (IS_ERR(priv->base)) 72 - return PTR_ERR(priv->base); 73 - 74 - soc->ctlrdy_ack = bcm63138_nand_intc_ack; 75 - soc->ctlrdy_set_enabled = bcm63138_nand_intc_set; 76 - 77 - return brcmnand_probe(pdev, soc); 78 - } 79 - 80 - static const struct of_device_id bcm63138_nand_of_match[] = { 81 - { .compatible = "brcm,nand-bcm63138" }, 82 - {}, 83 - }; 84 - MODULE_DEVICE_TABLE(of, bcm63138_nand_of_match); 85 - 86 - static struct platform_driver bcm63138_nand_driver = { 87 - .probe = bcm63138_nand_probe, 88 - .remove_new = brcmnand_remove, 89 - .driver = { 90 - .name = "bcm63138_nand", 91 - .pm = &brcmnand_pm_ops, 92 - .of_match_table = bcm63138_nand_of_match, 93 - } 94 - }; 95 - module_platform_driver(bcm63138_nand_driver); 96 - 97 - MODULE_LICENSE("GPL v2"); 98 - MODULE_AUTHOR("Brian Norris"); 99 - MODULE_DESCRIPTION("NAND driver for BCM63138");
+126
drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright © 2015 Broadcom Corporation 4 + */ 5 + 6 + #include <linux/device.h> 7 + #include <linux/io.h> 8 + #include <linux/ioport.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/of_address.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/slab.h> 14 + 15 + #include "brcmnand.h" 16 + 17 + struct bcmbca_nand_soc { 18 + struct brcmnand_soc soc; 19 + void __iomem *base; 20 + }; 21 + 22 + #define BCMBCA_NAND_INT_STATUS 0x00 23 + #define BCMBCA_NAND_INT_EN 0x04 24 + 25 + enum { 26 + BCMBCA_CTLRDY = BIT(4), 27 + }; 28 + 29 + #if defined(CONFIG_ARM64) 30 + #define ALIGN_REQ 8 31 + #else 32 + #define ALIGN_REQ 4 33 + #endif 34 + 35 + static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer) 36 + { 37 + return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) && 38 + IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ); 39 + } 40 + 41 + static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc) 42 + { 43 + struct bcmbca_nand_soc *priv = 44 + container_of(soc, struct bcmbca_nand_soc, soc); 45 + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_STATUS; 46 + u32 val = brcmnand_readl(mmio); 47 + 48 + if (val & BCMBCA_CTLRDY) { 49 + brcmnand_writel(val & ~BCMBCA_CTLRDY, mmio); 50 + return true; 51 + } 52 + 53 + return false; 54 + } 55 + 56 + static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en) 57 + { 58 + struct bcmbca_nand_soc *priv = 59 + container_of(soc, struct bcmbca_nand_soc, soc); 60 + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_EN; 61 + u32 val = brcmnand_readl(mmio); 62 + 63 + if (en) 64 + val |= BCMBCA_CTLRDY; 65 + else 66 + val &= ~BCMBCA_CTLRDY; 67 + 68 + brcmnand_writel(val, mmio); 69 + } 70 + 71 + static void bcmbca_read_data_bus(struct brcmnand_soc *soc, 72 + void __iomem *flash_cache, u32 *buffer, int fc_words) 73 + { 74 + /* 75 + * memcpy can do unaligned aligned access depending on source 76 + * and dest address, which is incompatible with nand cache. Fallback 77 + * to the memcpy_fromio in such case 78 + */ 79 + if (bcmbca_nand_is_buf_aligned((void __force *)flash_cache, buffer)) 80 + memcpy((void *)buffer, (void __force *)flash_cache, fc_words * 4); 81 + else 82 + memcpy_fromio((void *)buffer, flash_cache, fc_words * 4); 83 + } 84 + 85 + static int bcmbca_nand_probe(struct platform_device *pdev) 86 + { 87 + struct device *dev = &pdev->dev; 88 + struct bcmbca_nand_soc *priv; 89 + struct brcmnand_soc *soc; 90 + 91 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 92 + if (!priv) 93 + return -ENOMEM; 94 + soc = &priv->soc; 95 + 96 + priv->base = devm_platform_ioremap_resource_byname(pdev, "nand-int-base"); 97 + if (IS_ERR(priv->base)) 98 + return PTR_ERR(priv->base); 99 + 100 + soc->ctlrdy_ack = bcmbca_nand_intc_ack; 101 + soc->ctlrdy_set_enabled = bcmbca_nand_intc_set; 102 + soc->read_data_bus = bcmbca_read_data_bus; 103 + 104 + return brcmnand_probe(pdev, soc); 105 + } 106 + 107 + static const struct of_device_id bcmbca_nand_of_match[] = { 108 + { .compatible = "brcm,nand-bcm63138" }, 109 + {}, 110 + }; 111 + MODULE_DEVICE_TABLE(of, bcmbca_nand_of_match); 112 + 113 + static struct platform_driver bcmbca_nand_driver = { 114 + .probe = bcmbca_nand_probe, 115 + .remove_new = brcmnand_remove, 116 + .driver = { 117 + .name = "bcmbca_nand", 118 + .pm = &brcmnand_pm_ops, 119 + .of_match_table = bcmbca_nand_of_match, 120 + } 121 + }; 122 + module_platform_driver(bcmbca_nand_driver); 123 + 124 + MODULE_LICENSE("GPL v2"); 125 + MODULE_AUTHOR("Brian Norris"); 126 + MODULE_DESCRIPTION("NAND driver for BCMBCA");
+120 -28
drivers/mtd/nand/raw/brcmnand/brcmnand.c
··· 625 625 /* Only for v7.2 */ 626 626 #define ACC_CONTROL_ECC_EXT_SHIFT 13 627 627 628 - static u8 brcmnand_status(struct brcmnand_host *host); 628 + static int brcmnand_status(struct brcmnand_host *host); 629 629 630 630 static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl) 631 631 { ··· 851 851 return brcmnand_readl(ctrl->edu_base + offs); 852 852 } 853 853 854 + static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl, 855 + void __iomem *flash_cache, u32 *buffer, int fc_words) 856 + { 857 + struct brcmnand_soc *soc = ctrl->soc; 858 + int i; 859 + 860 + if (soc->read_data_bus) { 861 + soc->read_data_bus(soc, flash_cache, buffer, fc_words); 862 + } else { 863 + for (i = 0; i < fc_words; i++) 864 + buffer[i] = brcmnand_read_fc(ctrl, i); 865 + } 866 + } 867 + 854 868 static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) 855 869 { 856 870 ··· 1038 1024 return -1; 1039 1025 } 1040 1026 1027 + static bool brcmnand_get_sector_size_1k(struct brcmnand_host *host) 1028 + { 1029 + struct brcmnand_controller *ctrl = host->ctrl; 1030 + int sector_size_bit = brcmnand_sector_1k_shift(ctrl); 1031 + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, 1032 + BRCMNAND_CS_ACC_CONTROL); 1033 + u32 acc_control; 1034 + 1035 + if (sector_size_bit < 0) 1036 + return false; 1037 + 1038 + acc_control = nand_readreg(ctrl, acc_control_offs); 1039 + 1040 + return ((acc_control & BIT(sector_size_bit)) != 0); 1041 + } 1042 + 1041 1043 static void brcmnand_set_sector_size_1k(struct brcmnand_host *host, int val) 1042 1044 { 1043 1045 struct brcmnand_controller *ctrl = host->ctrl; ··· 1069 1039 tmp &= ~(1 << shift); 1070 1040 tmp |= (!!val) << shift; 1071 1041 nand_writereg(ctrl, acc_control_offs, tmp); 1042 + } 1043 + 1044 + static int brcmnand_get_spare_size(struct brcmnand_host *host) 1045 + { 1046 + struct brcmnand_controller *ctrl = host->ctrl; 1047 + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, 1048 + BRCMNAND_CS_ACC_CONTROL); 1049 + u32 acc = nand_readreg(ctrl, acc_control_offs); 1050 + 1051 + return (acc & brcmnand_spare_area_mask(ctrl)); 1052 + } 1053 + 1054 + static void brcmnand_get_ecc_settings(struct brcmnand_host *host, struct nand_chip *chip) 1055 + { 1056 + struct brcmnand_controller *ctrl = host->ctrl; 1057 + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, 1058 + BRCMNAND_CS_ACC_CONTROL); 1059 + bool sector_size_1k = brcmnand_get_sector_size_1k(host); 1060 + int spare_area_size, ecc_level; 1061 + u32 acc; 1062 + 1063 + spare_area_size = brcmnand_get_spare_size(host); 1064 + acc = nand_readreg(ctrl, acc_control_offs); 1065 + ecc_level = (acc & brcmnand_ecc_level_mask(ctrl)) >> ctrl->ecc_level_shift; 1066 + if (sector_size_1k) 1067 + chip->ecc.strength = ecc_level * 2; 1068 + else if (spare_area_size == 16 && ecc_level == 15) 1069 + chip->ecc.strength = 1; /* hamming */ 1070 + else 1071 + chip->ecc.strength = ecc_level; 1072 + 1073 + if (chip->ecc.size == 0) { 1074 + if (sector_size_1k) 1075 + chip->ecc.size = 1024; 1076 + else 1077 + chip->ecc.size = 512; 1078 + } 1072 1079 } 1073 1080 1074 1081 /*********************************************************************** ··· 1151 1084 if ((val & mask) == expected_val) 1152 1085 return 0; 1153 1086 1154 - dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n", 1155 - expected_val, val & mask); 1087 + dev_err(ctrl->dev, "timeout on status poll (expected %x got %x)\n", 1088 + expected_val, val & mask); 1156 1089 1157 1090 return -ETIMEDOUT; 1158 1091 } ··· 1757 1690 INTFC_FLASH_STATUS; 1758 1691 } 1759 1692 1760 - static u8 brcmnand_status(struct brcmnand_host *host) 1693 + static int brcmnand_status(struct brcmnand_host *host) 1761 1694 { 1762 1695 struct nand_chip *chip = &host->chip; 1763 1696 struct mtd_info *mtd = nand_to_mtd(chip); ··· 1768 1701 return brcmnand_waitfunc(chip); 1769 1702 } 1770 1703 1771 - static u8 brcmnand_reset(struct brcmnand_host *host) 1704 + static int brcmnand_reset(struct brcmnand_host *host) 1772 1705 { 1773 1706 struct nand_chip *chip = &host->chip; 1774 1707 ··· 2042 1975 { 2043 1976 struct brcmnand_host *host = nand_get_controller_data(chip); 2044 1977 struct brcmnand_controller *ctrl = host->ctrl; 2045 - int i, j, ret = 0; 1978 + int i, ret = 0; 2046 1979 2047 1980 brcmnand_clear_ecc_addr(ctrl); 2048 1981 ··· 2055 1988 if (likely(buf)) { 2056 1989 brcmnand_soc_data_bus_prepare(ctrl->soc, false); 2057 1990 2058 - for (j = 0; j < FC_WORDS; j++, buf++) 2059 - *buf = brcmnand_read_fc(ctrl, j); 1991 + brcmnand_read_data_bus(ctrl, ctrl->nand_fc, buf, FC_WORDS); 1992 + buf += FC_WORDS; 2060 1993 2061 1994 brcmnand_soc_data_bus_unprepare(ctrl->soc, false); 2062 1995 } ··· 2204 2137 return err; 2205 2138 } 2206 2139 2207 - dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", 2140 + dev_err(ctrl->dev, "uncorrectable error at 0x%llx\n", 2208 2141 (unsigned long long)err_addr); 2209 2142 mtd->ecc_stats.failed++; 2210 2143 /* NAND layer expects zero on ECC errors */ ··· 2406 2339 } 2407 2340 2408 2341 static int brcmnand_exec_instr(struct brcmnand_host *host, int i, 2409 - const struct nand_operation *op) 2342 + const struct nand_operation *op) 2410 2343 { 2411 2344 const struct nand_op_instr *instr = &op->instrs[i]; 2412 2345 struct brcmnand_controller *ctrl = host->ctrl; ··· 2420 2353 * (WAITRDY excepted). 2421 2354 */ 2422 2355 last_op = ((i == (op->ninstrs - 1)) && (instr->type != NAND_OP_WAITRDY_INSTR)) || 2423 - ((i == (op->ninstrs - 2)) && (op->instrs[i+1].type == NAND_OP_WAITRDY_INSTR)); 2356 + ((i == (op->ninstrs - 2)) && (op->instrs[i + 1].type == NAND_OP_WAITRDY_INSTR)); 2424 2357 2425 2358 switch (instr->type) { 2426 2359 case NAND_OP_CMD_INSTR: ··· 2465 2398 2466 2399 static int brcmnand_op_is_status(const struct nand_operation *op) 2467 2400 { 2468 - if ((op->ninstrs == 2) && 2469 - (op->instrs[0].type == NAND_OP_CMD_INSTR) && 2470 - (op->instrs[0].ctx.cmd.opcode == NAND_CMD_STATUS) && 2471 - (op->instrs[1].type == NAND_OP_DATA_IN_INSTR)) 2401 + if (op->ninstrs == 2 && 2402 + op->instrs[0].type == NAND_OP_CMD_INSTR && 2403 + op->instrs[0].ctx.cmd.opcode == NAND_CMD_STATUS && 2404 + op->instrs[1].type == NAND_OP_DATA_IN_INSTR) 2472 2405 return 1; 2473 2406 2474 2407 return 0; ··· 2476 2409 2477 2410 static int brcmnand_op_is_reset(const struct nand_operation *op) 2478 2411 { 2479 - if ((op->ninstrs == 2) && 2480 - (op->instrs[0].type == NAND_OP_CMD_INSTR) && 2481 - (op->instrs[0].ctx.cmd.opcode == NAND_CMD_RESET) && 2482 - (op->instrs[1].type == NAND_OP_WAITRDY_INSTR)) 2412 + if (op->ninstrs == 2 && 2413 + op->instrs[0].type == NAND_OP_CMD_INSTR && 2414 + op->instrs[0].ctx.cmd.opcode == NAND_CMD_RESET && 2415 + op->instrs[1].type == NAND_OP_WAITRDY_INSTR) 2483 2416 return 1; 2484 2417 2485 2418 return 0; ··· 2500 2433 2501 2434 if (brcmnand_op_is_status(op)) { 2502 2435 status = op->instrs[1].ctx.data.buf.in; 2503 - *status = brcmnand_status(host); 2436 + ret = brcmnand_status(host); 2437 + if (ret < 0) 2438 + return ret; 2439 + 2440 + *status = ret & 0xFF; 2504 2441 2505 2442 return 0; 2506 - } 2507 - else if (brcmnand_op_is_reset(op)) { 2443 + } else if (brcmnand_op_is_reset(op)) { 2508 2444 ret = brcmnand_reset(host); 2509 2445 if (ret < 0) 2510 2446 return ret; ··· 2678 2608 nanddev_get_memorg(&chip->base); 2679 2609 struct brcmnand_controller *ctrl = host->ctrl; 2680 2610 struct brcmnand_cfg *cfg = &host->hwcfg; 2681 - char msg[128]; 2611 + struct device_node *np = nand_get_flash_node(chip); 2682 2612 u32 offs, tmp, oob_sector; 2613 + bool use_strap = false; 2614 + char msg[128]; 2683 2615 int ret; 2684 2616 2685 2617 memset(cfg, 0, sizeof(*cfg)); 2618 + use_strap = of_property_read_bool(np, "brcm,nand-ecc-use-strap"); 2686 2619 2687 - ret = of_property_read_u32(nand_get_flash_node(chip), 2688 - "brcm,nand-oob-sector-size", 2620 + /* 2621 + * Either nand-ecc-xxx or brcm,nand-ecc-use-strap can be set. Error out 2622 + * if both exist. 2623 + */ 2624 + if (chip->ecc.strength && use_strap) { 2625 + dev_err(ctrl->dev, 2626 + "ECC strap and DT ECC configuration properties are mutually exclusive\n"); 2627 + return -EINVAL; 2628 + } 2629 + 2630 + if (use_strap) 2631 + brcmnand_get_ecc_settings(host, chip); 2632 + 2633 + ret = of_property_read_u32(np, "brcm,nand-oob-sector-size", 2689 2634 &oob_sector); 2690 2635 if (ret) { 2691 - /* Use detected size */ 2692 - cfg->spare_area_size = mtd->oobsize / 2693 - (mtd->writesize >> FC_SHIFT); 2636 + if (use_strap) 2637 + cfg->spare_area_size = brcmnand_get_spare_size(host); 2638 + else 2639 + /* Use detected size */ 2640 + cfg->spare_area_size = mtd->oobsize / 2641 + (mtd->writesize >> FC_SHIFT); 2694 2642 } else { 2695 2643 cfg->spare_area_size = oob_sector; 2696 2644 } ··· 3222 3134 CS_SELECT_AUTO_DEVICE_ID_CFG | 0xff, 0, 0); 3223 3135 /* Disable XOR addressing */ 3224 3136 brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0); 3137 + 3138 + /* Check if the board connects the WP pin */ 3139 + if (of_property_read_bool(dn, "brcm,wp-not-connected")) 3140 + wp_on = 0; 3225 3141 3226 3142 if (ctrl->features & BRCMNAND_HAS_WP) { 3227 3143 /* Permanently disable write protection */
+2
drivers/mtd/nand/raw/brcmnand/brcmnand.h
··· 24 24 void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en); 25 25 void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare, 26 26 bool is_param); 27 + void (*read_data_bus)(struct brcmnand_soc *soc, void __iomem *flash_cache, 28 + u32 *buffer, int fc_words); 27 29 const struct brcmnand_io_ops *ops; 28 30 }; 29 31
+2 -1
drivers/mtd/nand/raw/fsl_elbc_nand.c
··· 869 869 struct mtd_info *mtd; 870 870 871 871 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) 872 - return -ENODEV; 872 + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "lbc_ctrl_dev missing\n"); 873 + 873 874 lbc = fsl_lbc_ctrl_dev->regs; 874 875 dev = fsl_lbc_ctrl_dev->dev; 875 876
+3 -2
drivers/mtd/nand/raw/lpc32xx_mlc.c
··· 303 303 return 0; 304 304 } 305 305 306 - static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host) 306 + static irqreturn_t lpc3xxx_nand_irq(int irq, void *data) 307 307 { 308 + struct lpc32xx_nand_host *host = data; 308 309 uint8_t sr; 309 310 310 311 /* Clear interrupt flag by reading status */ ··· 781 780 goto release_dma_chan; 782 781 } 783 782 784 - if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq, 783 + if (request_irq(host->irq, &lpc3xxx_nand_irq, 785 784 IRQF_TRIGGER_HIGH, DRV_NAME, host)) { 786 785 dev_err(&pdev->dev, "Error requesting NAND IRQ\n"); 787 786 res = -ENXIO;
+1 -1
drivers/mtd/nand/raw/meson_nand.c
··· 63 63 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ 64 64 ( \ 65 65 (cmd_dir) | \ 66 - ((ran) << 19) | \ 66 + (ran) | \ 67 67 ((bch) << 14) | \ 68 68 ((short_mode) << 13) | \ 69 69 (((page_size) & 0x7f) << 6) | \
+1 -1
drivers/mtd/nand/raw/mtk_nand.c
··· 1356 1356 return -EINVAL; 1357 1357 } 1358 1358 1359 - chip = devm_kzalloc(dev, sizeof(*chip) + nsels * sizeof(u8), 1359 + chip = devm_kzalloc(dev, struct_size(chip, sels, nsels), 1360 1360 GFP_KERNEL); 1361 1361 if (!chip) 1362 1362 return -ENOMEM;
+60 -30
drivers/mtd/nand/raw/nand_base.c
··· 1211 1211 return nand_exec_op(chip, &op); 1212 1212 } 1213 1213 1214 + static unsigned int rawnand_last_page_of_lun(unsigned int pages_per_lun, unsigned int lun) 1215 + { 1216 + /* lun is expected to be very small */ 1217 + return (lun * pages_per_lun) + pages_per_lun - 1; 1218 + } 1219 + 1214 1220 static void rawnand_cap_cont_reads(struct nand_chip *chip) 1215 1221 { 1216 1222 struct nand_memory_organization *memorg; 1217 - unsigned int pages_per_lun, first_lun, last_lun; 1223 + unsigned int ppl, first_lun, last_lun; 1218 1224 1219 1225 memorg = nanddev_get_memorg(&chip->base); 1220 - pages_per_lun = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun; 1221 - first_lun = chip->cont_read.first_page / pages_per_lun; 1222 - last_lun = chip->cont_read.last_page / pages_per_lun; 1226 + ppl = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun; 1227 + first_lun = chip->cont_read.first_page / ppl; 1228 + last_lun = chip->cont_read.last_page / ppl; 1223 1229 1224 1230 /* Prevent sequential cache reads across LUN boundaries */ 1225 1231 if (first_lun != last_lun) 1226 - chip->cont_read.pause_page = first_lun * pages_per_lun + pages_per_lun - 1; 1232 + chip->cont_read.pause_page = rawnand_last_page_of_lun(ppl, first_lun); 1227 1233 else 1228 1234 chip->cont_read.pause_page = chip->cont_read.last_page; 1235 + 1236 + if (chip->cont_read.first_page == chip->cont_read.pause_page) { 1237 + chip->cont_read.first_page++; 1238 + chip->cont_read.pause_page = min(chip->cont_read.last_page, 1239 + rawnand_last_page_of_lun(ppl, first_lun + 1)); 1240 + } 1241 + 1242 + if (chip->cont_read.first_page >= chip->cont_read.last_page) 1243 + chip->cont_read.ongoing = false; 1229 1244 } 1230 1245 1231 1246 static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int page, ··· 1307 1292 if (!chip->cont_read.ongoing) 1308 1293 return 0; 1309 1294 1310 - if (page == chip->cont_read.pause_page && 1311 - page != chip->cont_read.last_page) { 1312 - chip->cont_read.first_page = chip->cont_read.pause_page + 1; 1313 - rawnand_cap_cont_reads(chip); 1314 - } else if (page == chip->cont_read.last_page) { 1295 + if (page == chip->cont_read.last_page) { 1315 1296 chip->cont_read.ongoing = false; 1297 + } else if (page == chip->cont_read.pause_page) { 1298 + chip->cont_read.first_page++; 1299 + rawnand_cap_cont_reads(chip); 1316 1300 } 1317 1301 1318 1302 return 0; ··· 3480 3466 u32 readlen, int col) 3481 3467 { 3482 3468 struct mtd_info *mtd = nand_to_mtd(chip); 3483 - unsigned int end_page, end_col; 3469 + unsigned int first_page, last_page; 3484 3470 3485 3471 chip->cont_read.ongoing = false; 3486 3472 3487 3473 if (!chip->controller->supported_op.cont_read) 3488 3474 return; 3489 3475 3490 - end_page = DIV_ROUND_UP(col + readlen, mtd->writesize); 3491 - end_col = (col + readlen) % mtd->writesize; 3492 - 3493 - if (col) 3494 - page++; 3495 - 3496 - if (end_col && end_page) 3497 - end_page--; 3498 - 3499 - if (page + 1 > end_page) 3476 + /* 3477 + * Don't bother making any calculations if the length is too small. 3478 + * Side effect: avoids possible integer underflows below. 3479 + */ 3480 + if (readlen < (2 * mtd->writesize)) 3500 3481 return; 3501 3482 3502 - chip->cont_read.first_page = page; 3503 - chip->cont_read.last_page = end_page; 3504 - chip->cont_read.ongoing = true; 3483 + /* Derive the page where continuous read should start (the first full page read) */ 3484 + first_page = page; 3485 + if (col) 3486 + first_page++; 3505 3487 3506 - rawnand_cap_cont_reads(chip); 3488 + /* Derive the page where continuous read should stop (the last full page read) */ 3489 + last_page = page + ((col + readlen) / mtd->writesize) - 1; 3490 + 3491 + /* Configure and enable continuous read when suitable */ 3492 + if (first_page < last_page) { 3493 + chip->cont_read.first_page = first_page; 3494 + chip->cont_read.last_page = last_page; 3495 + chip->cont_read.ongoing = true; 3496 + /* May reset the ongoing flag */ 3497 + rawnand_cap_cont_reads(chip); 3498 + } 3507 3499 } 3508 3500 3509 3501 static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page) ··· 3518 3498 return; 3519 3499 3520 3500 chip->cont_read.first_page++; 3521 - if (chip->cont_read.first_page == chip->cont_read.pause_page) 3522 - chip->cont_read.first_page++; 3523 - if (chip->cont_read.first_page >= chip->cont_read.last_page) 3524 - chip->cont_read.ongoing = false; 3501 + rawnand_cap_cont_reads(chip); 3525 3502 } 3526 3503 3527 3504 /** ··· 3594 3577 oob = ops->oobbuf; 3595 3578 oob_required = oob ? 1 : 0; 3596 3579 3597 - rawnand_enable_cont_reads(chip, page, readlen, col); 3580 + if (likely(ops->mode != MTD_OPS_RAW)) 3581 + rawnand_enable_cont_reads(chip, page, readlen, col); 3598 3582 3599 3583 while (1) { 3600 3584 struct mtd_ecc_stats ecc_stats = mtd->ecc_stats; ··· 3727 3709 } 3728 3710 } 3729 3711 nand_deselect_target(chip); 3712 + 3713 + if (WARN_ON_ONCE(chip->cont_read.ongoing)) 3714 + chip->cont_read.ongoing = false; 3730 3715 3731 3716 ops->retlen = ops->len - (size_t) readlen; 3732 3717 if (oob) ··· 5214 5193 return; 5215 5194 5216 5195 if (!nand_has_exec_op(chip)) 5196 + return; 5197 + 5198 + /* 5199 + * For now, continuous reads can only be used with the core page helpers. 5200 + * This can be extended later. 5201 + */ 5202 + if (!(chip->ecc.read_page == nand_read_page_hwecc || 5203 + chip->ecc.read_page == nand_read_page_syndrome || 5204 + chip->ecc.read_page == nand_read_page_swecc)) 5217 5205 return; 5218 5206 5219 5207 rawnand_check_cont_read_support(chip);
-1
drivers/mtd/nand/raw/nand_bbt.c
··· 576 576 startblock &= bbtblocks - 1; 577 577 } else { 578 578 chips = 1; 579 - bbtblocks = mtd->size >> this->bbt_erase_shift; 580 579 } 581 580 582 581 for (i = 0; i < chips; i++) {
-1
drivers/mtd/nand/raw/nand_hynix.c
··· 31 31 32 32 /** 33 33 * struct hynix_nand - private Hynix NAND struct 34 - * @nand_technology: manufacturing process expressed in picometer 35 34 * @read_retry: read-retry information 36 35 */ 37 36 struct hynix_nand {
+69 -14
drivers/mtd/nand/raw/stm32_fmc2_nand.c
··· 16 16 #include <linux/module.h> 17 17 #include <linux/mtd/rawnand.h> 18 18 #include <linux/of_address.h> 19 + #include <linux/of_device.h> 19 20 #include <linux/pinctrl/consumer.h> 20 21 #include <linux/platform_device.h> 21 22 #include <linux/regmap.h> ··· 38 37 #define FMC2_MAX_SG 16 39 38 40 39 /* Max chip enable */ 41 - #define FMC2_MAX_CE 2 40 + #define FMC2_MAX_CE 4 42 41 43 42 /* Max ECC buffer length */ 44 43 #define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) ··· 244 243 return container_of(chip, struct stm32_fmc2_nand, chip); 245 244 } 246 245 246 + struct stm32_fmc2_nfc; 247 + 248 + struct stm32_fmc2_nfc_data { 249 + int max_ncs; 250 + int (*set_cdev)(struct stm32_fmc2_nfc *nfc); 251 + }; 252 + 247 253 struct stm32_fmc2_nfc { 248 254 struct nand_controller base; 249 255 struct stm32_fmc2_nand nand; ··· 264 256 phys_addr_t data_phys_addr[FMC2_MAX_CE]; 265 257 struct clk *clk; 266 258 u8 irq_state; 259 + const struct stm32_fmc2_nfc_data *data; 267 260 268 261 struct dma_chan *dma_tx_ch; 269 262 struct dma_chan *dma_rx_ch; ··· 273 264 struct sg_table dma_ecc_sg; 274 265 u8 *ecc_buf; 275 266 int dma_ecc_len; 267 + u32 tx_dma_max_burst; 268 + u32 rx_dma_max_burst; 276 269 277 270 struct completion complete; 278 271 struct completion dma_data_complete; ··· 358 347 stm32_fmc2_nfc_setup(chip); 359 348 stm32_fmc2_nfc_timings_init(chip); 360 349 361 - if (nfc->dma_tx_ch && nfc->dma_rx_ch) { 350 + if (nfc->dma_tx_ch) { 362 351 memset(&dma_cfg, 0, sizeof(dma_cfg)); 363 - dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; 364 352 dma_cfg.dst_addr = nfc->data_phys_addr[nfc->cs_sel]; 365 - dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 366 353 dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 367 - dma_cfg.src_maxburst = 32; 368 - dma_cfg.dst_maxburst = 32; 354 + dma_cfg.dst_maxburst = nfc->tx_dma_max_burst / 355 + dma_cfg.dst_addr_width; 369 356 370 357 ret = dmaengine_slave_config(nfc->dma_tx_ch, &dma_cfg); 371 358 if (ret) { 372 359 dev_err(nfc->dev, "tx DMA engine slave config failed\n"); 373 360 return ret; 374 361 } 362 + } 363 + 364 + if (nfc->dma_rx_ch) { 365 + memset(&dma_cfg, 0, sizeof(dma_cfg)); 366 + dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; 367 + dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 368 + dma_cfg.src_maxburst = nfc->rx_dma_max_burst / 369 + dma_cfg.src_addr_width; 375 370 376 371 ret = dmaengine_slave_config(nfc->dma_rx_ch, &dma_cfg); 377 372 if (ret) { ··· 1562 1545 1563 1546 static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) 1564 1547 { 1548 + struct dma_slave_caps caps; 1565 1549 int ret = 0; 1566 1550 1567 1551 nfc->dma_tx_ch = dma_request_chan(nfc->dev, "tx"); ··· 1575 1557 goto err_dma; 1576 1558 } 1577 1559 1560 + ret = dma_get_slave_caps(nfc->dma_tx_ch, &caps); 1561 + if (ret) 1562 + return ret; 1563 + nfc->tx_dma_max_burst = caps.max_burst; 1564 + 1578 1565 nfc->dma_rx_ch = dma_request_chan(nfc->dev, "rx"); 1579 1566 if (IS_ERR(nfc->dma_rx_ch)) { 1580 1567 ret = PTR_ERR(nfc->dma_rx_ch); ··· 1589 1566 nfc->dma_rx_ch = NULL; 1590 1567 goto err_dma; 1591 1568 } 1569 + 1570 + ret = dma_get_slave_caps(nfc->dma_rx_ch, &caps); 1571 + if (ret) 1572 + return ret; 1573 + nfc->rx_dma_max_burst = caps.max_burst; 1592 1574 1593 1575 nfc->dma_ecc_ch = dma_request_chan(nfc->dev, "ecc"); 1594 1576 if (IS_ERR(nfc->dma_ecc_ch)) { ··· 1818 1790 return ret; 1819 1791 } 1820 1792 1821 - if (cs >= FMC2_MAX_CE) { 1793 + if (cs >= nfc->data->max_ncs) { 1822 1794 dev_err(nfc->dev, "invalid reg value: %d\n", cs); 1823 1795 return -EINVAL; 1824 1796 } ··· 1924 1896 nand_controller_init(&nfc->base); 1925 1897 nfc->base.ops = &stm32_fmc2_nfc_controller_ops; 1926 1898 1927 - ret = stm32_fmc2_nfc_set_cdev(nfc); 1928 - if (ret) 1929 - return ret; 1899 + nfc->data = of_device_get_match_data(dev); 1900 + if (!nfc->data) 1901 + return -EINVAL; 1902 + 1903 + if (nfc->data->set_cdev) { 1904 + ret = nfc->data->set_cdev(nfc); 1905 + if (ret) 1906 + return ret; 1907 + } else { 1908 + nfc->cdev = dev->parent; 1909 + } 1930 1910 1931 1911 ret = stm32_fmc2_nfc_parse_dt(nfc); 1932 1912 if (ret) ··· 1953 1917 if (nfc->dev == nfc->cdev) 1954 1918 start_region = 1; 1955 1919 1956 - for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; 1920 + for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs; 1957 1921 chip_cs++, mem_region += 3) { 1958 1922 if (!(nfc->cs_assigned & BIT(chip_cs))) 1959 1923 continue; ··· 2109 2073 2110 2074 stm32_fmc2_nfc_wp_disable(nand); 2111 2075 2112 - for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { 2076 + for (chip_cs = 0; chip_cs < nfc->data->max_ncs; chip_cs++) { 2113 2077 if (!(nfc->cs_assigned & BIT(chip_cs))) 2114 2078 continue; 2115 2079 ··· 2122 2086 static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend, 2123 2087 stm32_fmc2_nfc_resume); 2124 2088 2089 + static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = { 2090 + .max_ncs = 2, 2091 + .set_cdev = stm32_fmc2_nfc_set_cdev, 2092 + }; 2093 + 2094 + static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = { 2095 + .max_ncs = 4, 2096 + }; 2097 + 2125 2098 static const struct of_device_id stm32_fmc2_nfc_match[] = { 2126 - {.compatible = "st,stm32mp15-fmc2"}, 2127 - {.compatible = "st,stm32mp1-fmc2-nfc"}, 2099 + { 2100 + .compatible = "st,stm32mp15-fmc2", 2101 + .data = &stm32_fmc2_nfc_mp1_data, 2102 + }, 2103 + { 2104 + .compatible = "st,stm32mp1-fmc2-nfc", 2105 + .data = &stm32_fmc2_nfc_mp1_data, 2106 + }, 2107 + { 2108 + .compatible = "st,stm32mp25-fmc2-nfc", 2109 + .data = &stm32_fmc2_nfc_mp25_data, 2110 + }, 2128 2111 {} 2129 2112 }; 2130 2113 MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
+6 -3
drivers/mtd/nand/spi/esmt.c
··· 104 104 105 105 static const struct spinand_info esmt_c8_spinand_table[] = { 106 106 SPINAND_INFO("F50L1G41LB", 107 - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), 107 + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01, 0x7f, 108 + 0x7f, 0x7f), 108 109 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 109 110 NAND_ECCREQ(1, 512), 110 111 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ··· 114 113 0, 115 114 SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), 116 115 SPINAND_INFO("F50D1G41LB", 117 - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11), 116 + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11, 0x7f, 117 + 0x7f, 0x7f), 118 118 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 119 119 NAND_ECCREQ(1, 512), 120 120 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ··· 124 122 0, 125 123 SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), 126 124 SPINAND_INFO("F50D2G41KA", 127 - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51), 125 + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51, 0x7f, 126 + 0x7f, 0x7f), 128 127 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 129 128 NAND_ECCREQ(8, 512), 130 129 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+12
drivers/mtd/nand/spi/winbond.c
··· 15 15 16 16 #define WINBOND_CFG_BUF_READ BIT(3) 17 17 18 + #define W25N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) 19 + 18 20 static SPINAND_OP_VARIANTS(read_cache_variants, 19 21 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 20 22 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ··· 120 118 return -EBADMSG; 121 119 122 120 case STATUS_ECC_HAS_BITFLIPS: 121 + case W25N04KV_STATUS_ECC_5_8_BITFLIPS: 123 122 /* 124 123 * Let's try to retrieve the real maximum number of bitflips 125 124 * in order to avoid forcing the wear-leveling layer to move ··· 217 214 &update_cache_variants), 218 215 0, 219 216 SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)), 217 + SPINAND_INFO("W25N04KV", 218 + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), 219 + NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1), 220 + NAND_ECCREQ(8, 512), 221 + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 222 + &write_cache_variants, 223 + &update_cache_variants), 224 + 0, 225 + SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), 220 226 }; 221 227 222 228 static int winbond_spinand_init(struct spinand_device *spinand)
+88 -99
drivers/mtd/spi-nor/core.c
··· 1158 1158 1159 1159 static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) 1160 1160 { 1161 - return !!nor->params->erase_map.uniform_erase_type; 1161 + return !!nor->params->erase_map.uniform_region.erase_mask; 1162 1162 } 1163 1163 1164 1164 static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) ··· 1542 1542 const struct spi_nor_erase_type *erase; 1543 1543 u32 rem; 1544 1544 int i; 1545 - u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; 1546 1545 1547 1546 /* 1548 1547 * Erase types are ordered by size, with the smallest erase type at ··· 1549 1550 */ 1550 1551 for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { 1551 1552 /* Does the erase region support the tested erase type? */ 1552 - if (!(erase_mask & BIT(i))) 1553 + if (!(region->erase_mask & BIT(i))) 1553 1554 continue; 1554 1555 1555 1556 erase = &map->erase_type[i]; ··· 1557 1558 continue; 1558 1559 1559 1560 /* Alignment is not mandatory for overlaid regions */ 1560 - if (region->offset & SNOR_OVERLAID_REGION && 1561 - region->size <= len) 1561 + if (region->overlaid && region->size <= len) 1562 1562 return erase; 1563 1563 1564 1564 /* Don't erase more than what the user has asked for. */ ··· 1570 1572 } 1571 1573 1572 1574 return NULL; 1573 - } 1574 - 1575 - static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region) 1576 - { 1577 - return region->offset & SNOR_LAST_REGION; 1578 - } 1579 - 1580 - static u64 spi_nor_region_end(const struct spi_nor_erase_region *region) 1581 - { 1582 - return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size; 1583 - } 1584 - 1585 - /** 1586 - * spi_nor_region_next() - get the next spi nor region 1587 - * @region: pointer to a structure that describes a SPI NOR erase region 1588 - * 1589 - * Return: the next spi nor region or NULL if last region. 1590 - */ 1591 - struct spi_nor_erase_region * 1592 - spi_nor_region_next(struct spi_nor_erase_region *region) 1593 - { 1594 - if (spi_nor_region_is_last(region)) 1595 - return NULL; 1596 - region++; 1597 - return region; 1598 - } 1599 - 1600 - /** 1601 - * spi_nor_find_erase_region() - find the region of the serial flash memory in 1602 - * which the offset fits 1603 - * @map: the erase map of the SPI NOR 1604 - * @addr: offset in the serial flash memory 1605 - * 1606 - * Return: a pointer to the spi_nor_erase_region struct, ERR_PTR(-errno) 1607 - * otherwise. 1608 - */ 1609 - static struct spi_nor_erase_region * 1610 - spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) 1611 - { 1612 - struct spi_nor_erase_region *region = map->regions; 1613 - u64 region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 1614 - u64 region_end = region_start + region->size; 1615 - 1616 - while (addr < region_start || addr >= region_end) { 1617 - region = spi_nor_region_next(region); 1618 - if (!region) 1619 - return ERR_PTR(-EINVAL); 1620 - 1621 - region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 1622 - region_end = region_start + region->size; 1623 - } 1624 - 1625 - return region; 1626 1575 } 1627 1576 1628 1577 /** ··· 1594 1649 cmd->opcode = erase->opcode; 1595 1650 cmd->count = 1; 1596 1651 1597 - if (region->offset & SNOR_OVERLAID_REGION) 1652 + if (region->overlaid) 1598 1653 cmd->size = region->size; 1599 1654 else 1600 1655 cmd->size = erase->size; ··· 1638 1693 struct spi_nor_erase_region *region; 1639 1694 struct spi_nor_erase_command *cmd = NULL; 1640 1695 u64 region_end; 1696 + unsigned int i; 1641 1697 int ret = -EINVAL; 1642 1698 1643 - region = spi_nor_find_erase_region(map, addr); 1644 - if (IS_ERR(region)) 1645 - return PTR_ERR(region); 1699 + for (i = 0; i < map->n_regions && len; i++) { 1700 + region = &map->regions[i]; 1701 + region_end = region->offset + region->size; 1646 1702 1647 - region_end = spi_nor_region_end(region); 1648 - 1649 - while (len) { 1650 - erase = spi_nor_find_best_erase_type(map, region, addr, len); 1651 - if (!erase) 1652 - goto destroy_erase_cmd_list; 1653 - 1654 - if (prev_erase != erase || 1655 - erase->size != cmd->size || 1656 - region->offset & SNOR_OVERLAID_REGION) { 1657 - cmd = spi_nor_init_erase_cmd(region, erase); 1658 - if (IS_ERR(cmd)) { 1659 - ret = PTR_ERR(cmd); 1703 + while (len && addr >= region->offset && addr < region_end) { 1704 + erase = spi_nor_find_best_erase_type(map, region, addr, 1705 + len); 1706 + if (!erase) 1660 1707 goto destroy_erase_cmd_list; 1708 + 1709 + if (prev_erase != erase || erase->size != cmd->size || 1710 + region->overlaid) { 1711 + cmd = spi_nor_init_erase_cmd(region, erase); 1712 + if (IS_ERR(cmd)) { 1713 + ret = PTR_ERR(cmd); 1714 + goto destroy_erase_cmd_list; 1715 + } 1716 + 1717 + list_add_tail(&cmd->list, erase_list); 1718 + } else { 1719 + cmd->count++; 1661 1720 } 1662 1721 1663 - list_add_tail(&cmd->list, erase_list); 1664 - } else { 1665 - cmd->count++; 1722 + len -= cmd->size; 1723 + addr += cmd->size; 1724 + prev_erase = erase; 1666 1725 } 1667 - 1668 - addr += cmd->size; 1669 - len -= cmd->size; 1670 - 1671 - if (len && addr >= region_end) { 1672 - region = spi_nor_region_next(region); 1673 - if (!region) 1674 - goto destroy_erase_cmd_list; 1675 - region_end = spi_nor_region_end(region); 1676 - } 1677 - 1678 - prev_erase = erase; 1679 1726 } 1680 1727 1681 1728 return 0; ··· 2405 2468 void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, 2406 2469 u8 erase_mask, u64 flash_size) 2407 2470 { 2408 - /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */ 2409 - map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) | 2410 - SNOR_LAST_REGION; 2471 + map->uniform_region.offset = 0; 2411 2472 map->uniform_region.size = flash_size; 2473 + map->uniform_region.erase_mask = erase_mask; 2412 2474 map->regions = &map->uniform_region; 2413 - map->uniform_erase_type = erase_mask; 2475 + map->n_regions = 1; 2414 2476 } 2415 2477 2416 2478 int spi_nor_post_bfpt_fixups(struct spi_nor *nor, ··· 2496 2560 { 2497 2561 const struct spi_nor_erase_type *tested_erase, *erase = NULL; 2498 2562 int i; 2499 - u8 uniform_erase_type = map->uniform_erase_type; 2563 + u8 uniform_erase_type = map->uniform_region.erase_mask; 2500 2564 2501 2565 /* 2502 2566 * Search for the biggest erase size, except for when compiled ··· 2535 2599 return NULL; 2536 2600 2537 2601 /* Disable all other Sector Erase commands. */ 2538 - map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK; 2539 - map->uniform_erase_type |= BIT(erase - map->erase_type); 2602 + map->uniform_region.erase_mask = BIT(erase - map->erase_type); 2540 2603 return erase; 2541 2604 } 2542 2605 ··· 3369 3434 return info; 3370 3435 } 3371 3436 3372 - static void spi_nor_set_mtd_info(struct spi_nor *nor) 3437 + static u32 3438 + spi_nor_get_region_erasesize(const struct spi_nor_erase_region *region, 3439 + const struct spi_nor_erase_type *erase_type) 3440 + { 3441 + int i; 3442 + 3443 + if (region->overlaid) 3444 + return region->size; 3445 + 3446 + for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { 3447 + if (region->erase_mask & BIT(i)) 3448 + return erase_type[i].size; 3449 + } 3450 + 3451 + return 0; 3452 + } 3453 + 3454 + static int spi_nor_set_mtd_eraseregions(struct spi_nor *nor) 3455 + { 3456 + const struct spi_nor_erase_map *map = &nor->params->erase_map; 3457 + const struct spi_nor_erase_region *region = map->regions; 3458 + struct mtd_erase_region_info *mtd_region; 3459 + struct mtd_info *mtd = &nor->mtd; 3460 + u32 erasesize, i; 3461 + 3462 + mtd_region = devm_kcalloc(nor->dev, map->n_regions, sizeof(*mtd_region), 3463 + GFP_KERNEL); 3464 + if (!mtd_region) 3465 + return -ENOMEM; 3466 + 3467 + for (i = 0; i < map->n_regions; i++) { 3468 + erasesize = spi_nor_get_region_erasesize(&region[i], 3469 + map->erase_type); 3470 + if (!erasesize) 3471 + return -EINVAL; 3472 + 3473 + mtd_region[i].erasesize = erasesize; 3474 + mtd_region[i].numblocks = div64_ul(region[i].size, erasesize); 3475 + mtd_region[i].offset = region[i].offset; 3476 + } 3477 + 3478 + mtd->numeraseregions = map->n_regions; 3479 + mtd->eraseregions = mtd_region; 3480 + 3481 + return 0; 3482 + } 3483 + 3484 + static int spi_nor_set_mtd_info(struct spi_nor *nor) 3373 3485 { 3374 3486 struct mtd_info *mtd = &nor->mtd; 3375 3487 struct device *dev = nor->dev; ··· 3447 3465 mtd->_resume = spi_nor_resume; 3448 3466 mtd->_get_device = spi_nor_get_device; 3449 3467 mtd->_put_device = spi_nor_put_device; 3468 + 3469 + if (!spi_nor_has_uniform_erase(nor)) 3470 + return spi_nor_set_mtd_eraseregions(nor); 3471 + 3472 + return 0; 3450 3473 } 3451 3474 3452 3475 static int spi_nor_hw_reset(struct spi_nor *nor) ··· 3542 3555 return ret; 3543 3556 3544 3557 /* No mtd_info fields should be used up to this point. */ 3545 - spi_nor_set_mtd_info(nor); 3558 + ret = spi_nor_set_mtd_info(nor); 3559 + if (ret) 3560 + return ret; 3546 3561 3547 3562 dev_dbg(dev, "Manufacturer and device ID: %*phN\n", 3548 3563 SPI_NOR_MAX_ID_LEN, nor->id);
+9 -21
drivers/mtd/spi-nor/core.h
··· 240 240 /** 241 241 * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region 242 242 * @offset: the offset in the data array of erase region start. 243 - * LSB bits are used as a bitmask encoding flags to 244 - * determine if this region is overlaid, if this region is 245 - * the last in the SPI NOR flash memory and to indicate 246 - * all the supported erase commands inside this region. 247 - * The erase types are sorted in ascending order with the 248 - * smallest Erase Type size being at BIT(0). 249 243 * @size: the size of the region in bytes. 244 + * @erase_mask: bitmask to indicate all the supported erase commands 245 + * inside this region. The erase types are sorted in 246 + * ascending order with the smallest Erase Type size being 247 + * at BIT(0). 248 + * @overlaid: determine if this region is overlaid. 250 249 */ 251 250 struct spi_nor_erase_region { 252 251 u64 offset; 253 252 u64 size; 253 + u8 erase_mask; 254 + bool overlaid; 254 255 }; 255 256 256 257 #define SNOR_ERASE_TYPE_MAX 4 257 - #define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0) 258 - 259 - #define SNOR_LAST_REGION BIT(4) 260 - #define SNOR_OVERLAID_REGION BIT(5) 261 - 262 - #define SNOR_ERASE_FLAGS_MAX 6 263 - #define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0) 264 258 265 259 /** 266 260 * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map ··· 267 273 * The erase types are sorted in ascending order, with the 268 274 * smallest Erase Type size being the first member in the 269 275 * erase_type array. 270 - * @uniform_erase_type: bitmask encoding erase types that can erase the 271 - * entire memory. This member is completed at init by 272 - * uniform and non-uniform SPI NOR flash memories if they 273 - * support at least one erase type that can erase the 274 - * entire memory. 276 + * @n_regions: number of erase regions. 275 277 */ 276 278 struct spi_nor_erase_map { 277 279 struct spi_nor_erase_region *regions; 278 280 struct spi_nor_erase_region uniform_region; 279 281 struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX]; 280 - u8 uniform_erase_type; 282 + unsigned int n_regions; 281 283 }; 282 284 283 285 /** ··· 665 675 void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size, 666 676 u8 opcode); 667 677 void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase); 668 - struct spi_nor_erase_region * 669 - spi_nor_region_next(struct spi_nor_erase_region *region); 670 678 void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, 671 679 u8 erase_mask, u64 flash_size); 672 680
+12 -14
drivers/mtd/spi-nor/debugfs.c
··· 78 78 struct spi_nor *nor = s->private; 79 79 struct spi_nor_flash_parameter *params = nor->params; 80 80 struct spi_nor_erase_map *erase_map = &params->erase_map; 81 - struct spi_nor_erase_region *region; 81 + struct spi_nor_erase_region *region = erase_map->regions; 82 82 const struct flash_info *info = nor->info; 83 83 char buf[16], *str; 84 - int i; 84 + unsigned int i; 85 85 86 86 seq_printf(s, "name\t\t%s\n", info->name); 87 87 seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); ··· 142 142 } 143 143 144 144 seq_puts(s, "\nsector map\n"); 145 - seq_puts(s, " region (in hex) | erase mask | flags\n"); 145 + seq_puts(s, " region (in hex) | erase mask | overlaid\n"); 146 146 seq_puts(s, " ------------------+------------+----------\n"); 147 - for (region = erase_map->regions; 148 - region; 149 - region = spi_nor_region_next(region)) { 150 - u64 start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 151 - u64 flags = region->offset & SNOR_ERASE_FLAGS_MASK; 152 - u64 end = start + region->size - 1; 147 + for (i = 0; i < erase_map->n_regions; i++) { 148 + u64 start = region[i].offset; 149 + u64 end = start + region[i].size - 1; 150 + u8 erase_mask = region[i].erase_mask; 153 151 154 152 seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", 155 153 start, end, 156 - flags & BIT(0) ? '0' : ' ', 157 - flags & BIT(1) ? '1' : ' ', 158 - flags & BIT(2) ? '2' : ' ', 159 - flags & BIT(3) ? '3' : ' ', 160 - flags & SNOR_OVERLAID_REGION ? "overlaid" : ""); 154 + erase_mask & BIT(0) ? '0' : ' ', 155 + erase_mask & BIT(1) ? '1' : ' ', 156 + erase_mask & BIT(2) ? '2' : ' ', 157 + erase_mask & BIT(3) ? '3' : ' ', 158 + region[i].overlaid ? "yes" : "no"); 161 159 } 162 160 163 161 return 0;
+16 -31
drivers/mtd/spi-nor/sfdp.c
··· 389 389 static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) 390 390 { 391 391 struct spi_nor_erase_region *region = map->regions; 392 - u8 region_erase_mask, sorted_erase_mask; 392 + u8 sorted_erase_mask; 393 + unsigned int i; 393 394 394 - while (region) { 395 - region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; 396 - 397 - sorted_erase_mask = spi_nor_sort_erase_mask(map, 398 - region_erase_mask); 395 + for (i = 0; i < map->n_regions; i++) { 396 + sorted_erase_mask = 397 + spi_nor_sort_erase_mask(map, region[i].erase_mask); 399 398 400 399 /* Overwrite erase mask. */ 401 - region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | 402 - sorted_erase_mask; 403 - 404 - region = spi_nor_region_next(region); 400 + region[i].erase_mask = sorted_erase_mask; 405 401 } 406 402 } 407 403 ··· 550 554 * selecting the uniform erase. 551 555 */ 552 556 spi_nor_regions_sort_erase_types(map); 553 - map->uniform_erase_type = map->uniform_region.offset & 554 - SNOR_ERASE_TYPE_MASK; 555 557 556 558 /* Stop here if not JESD216 rev A or later. */ 557 559 if (bfpt_header->length == BFPT_DWORD_MAX_JESD216) ··· 800 806 return ret; 801 807 } 802 808 803 - static void spi_nor_region_mark_end(struct spi_nor_erase_region *region) 804 - { 805 - region->offset |= SNOR_LAST_REGION; 806 - } 807 - 808 - static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) 809 - { 810 - region->offset |= SNOR_OVERLAID_REGION; 811 - } 812 - 813 809 /** 814 810 * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid 815 811 * @region: pointer to a structure that describes a SPI NOR erase region ··· 817 833 if (!(erase[i].size && erase_type & BIT(erase[i].idx))) 818 834 continue; 819 835 if (region->size & erase[i].size_mask) { 820 - spi_nor_region_mark_overlay(region); 836 + region->overlaid = true; 821 837 return; 822 838 } 823 839 } ··· 852 868 if (!region) 853 869 return -ENOMEM; 854 870 map->regions = region; 871 + map->n_regions = region_count; 855 872 856 873 uniform_erase_type = 0xff; 857 874 regions_erase_type = 0; ··· 860 875 /* Populate regions. */ 861 876 for (i = 0; i < region_count; i++) { 862 877 j = i + 1; /* index for the region dword */ 878 + region[i].offset = offset; 863 879 region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]); 864 880 erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]); 865 - region[i].offset = offset | erase_type; 881 + region[i].erase_mask = erase_type; 866 882 867 883 spi_nor_region_check_overlay(&region[i], erase, erase_type); 868 884 ··· 879 893 */ 880 894 regions_erase_type |= erase_type; 881 895 882 - offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + 883 - region[i].size; 896 + offset = region[i].offset + region[i].size; 884 897 } 885 - spi_nor_region_mark_end(&region[i - 1]); 886 898 887 - save_uniform_erase_type = map->uniform_erase_type; 888 - map->uniform_erase_type = spi_nor_sort_erase_mask(map, 889 - uniform_erase_type); 899 + save_uniform_erase_type = map->uniform_region.erase_mask; 900 + map->uniform_region.erase_mask = 901 + spi_nor_sort_erase_mask(map, 902 + uniform_erase_type); 890 903 891 904 if (!regions_erase_type) { 892 905 /* 893 906 * Roll back to the previous uniform_erase_type mask, SMPT is 894 907 * broken. 895 908 */ 896 - map->uniform_erase_type = save_uniform_erase_type; 909 + map->uniform_region.erase_mask = save_uniform_erase_type; 897 910 return -EINVAL; 898 911 } 899 912
+4 -3
drivers/mtd/ssfdc.c
··· 295 295 if (cis_sector == -1) 296 296 return; 297 297 298 - ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL); 298 + ssfdc = kzalloc(sizeof(*ssfdc), GFP_KERNEL); 299 299 if (!ssfdc) 300 300 return; 301 301 ··· 332 332 kmalloc_array(ssfdc->map_len, 333 333 sizeof(ssfdc->logic_block_map[0]), GFP_KERNEL); 334 334 if (!ssfdc->logic_block_map) 335 - goto out_err; 335 + goto out_free_ssfdc; 336 336 memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * 337 337 ssfdc->map_len); 338 338 ··· 350 350 351 351 out_err: 352 352 kfree(ssfdc->logic_block_map); 353 - kfree(ssfdc); 353 + out_free_ssfdc: 354 + kfree(ssfdc); 354 355 } 355 356 356 357 static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev)
+1
include/linux/mtd/flashchip.h
··· 13 13 */ 14 14 #include <linux/sched.h> 15 15 #include <linux/mutex.h> 16 + #include <linux/wait.h> 16 17 17 18 typedef enum { 18 19 FL_READY,
+1 -1
include/linux/mtd/lpc32xx_mlc.h
··· 11 11 #include <linux/dmaengine.h> 12 12 13 13 struct lpc32xx_mlc_platform_data { 14 - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); 14 + dma_filter_fn dma_filter; 15 15 }; 16 16 17 17 #endif /* __LINUX_MTD_LPC32XX_MLC_H */
+1 -1
include/linux/mtd/lpc32xx_slc.h
··· 11 11 #include <linux/dmaengine.h> 12 12 13 13 struct lpc32xx_slc_platform_data { 14 - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); 14 + dma_filter_fn dma_filter; 15 15 }; 16 16 17 17 #endif /* __LINUX_MTD_LPC32XX_SLC_H */
+1 -1
include/linux/mtd/mtd.h
··· 223 223 * @partitions_lock: lock protecting accesses to the partition list. Protects 224 224 * not only the master partition list, but also all 225 225 * sub-partitions. 226 - * @suspended: et to 1 when the device is suspended, 0 otherwise 226 + * @suspended: set to 1 when the device is suspended, 0 otherwise 227 227 * 228 228 * This struct is embedded in mtd_info and contains master-specific 229 229 * properties/fields. The master is the root MTD device from the MTD partition
+1 -1
include/linux/mtd/spinand.h
··· 169 169 struct spinand_op; 170 170 struct spinand_device; 171 171 172 - #define SPINAND_MAX_ID_LEN 4 172 + #define SPINAND_MAX_ID_LEN 5 173 173 /* 174 174 * For erase, write and read operation, we got the following timings : 175 175 * tBERS (erase) 1ms to 4ms