Commit da85e7ed authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MTD updates from Richard Weinberger:
 "MTD core changes:
   - Convert list_for_each to entry variant
   - Use MTD_DEVICE_ATTR_RO/RW() helper macros
   - Remove unnecessary OOM messages
   - Potential NULL dereference in mtd_otp_size()
   - Fix freeing of otp_info buffer
   - Create partname and partid debug files for child MTDs
   - tests:
      - Remove redundant assignment to err
      - Fix error return code in mtd_oobtest_init()
   - Add OTP NVMEM provider support
   - Allow specifying of_node
   - Convert sysfs sprintf/snprintf family to sysfs_emit

  Bindings changes:
   - Convert ti,am654-hbmc.txt to YAML schema
   - spi-nor: add otp property
   - Add OTP bindings
   - add YAML schema for the generic MTD bindings
   - Add brcm,trx-magic

  MTD device drivers changes:
   - Add support for microchip 48l640 EERAM
   - Remove superfluous "break"
   - sm_ftl:
      - Fix alignment of block comment
   - nftl:
      - Return -ENOMEM when kmalloc failed
   - nftlcore:
      - Remove set but rewrite variables
   - phram:
      - Fix error return code in phram_setup()
   - plat-ram:
      - Remove redundant dev_err call in platram_probe()

  MTD parsers changes:
   - Qcom:
      - Fix leaking of partition name
   - Redboot:
      - Fix style issues
      - Seek fis-index-block in the right node
   - trx:
      - Allow to use TRX parser on Mediatek SoCs
      - Allow to specify brcm, trx-magic in DT

  Raw NAND core:
   - Allow SDR timings to be nacked
   - Bring support for NV-DDR timings which involved a number of small
     preparation changes to bring new helpers, properly introduce NV-DDR
     structures, fill them, differenciate them and pick the best timing
     set.
   - Add the necessary infrastructure to parse the new gpio-cs property
     which aims at enlarging the number of available CS when a hardware
     controller is too constrained.
   - Update dead URL
   - Silence static checker warning in nand_setup_interface()
   - BBT:
      - Fix corner case in bad block table handling
   - onfi:
      - Use more recent ONFI specification wording
      - Use the BIT() macro when possible

  Raw NAND controller drivers:
   - Atmel:
      - Ensure the data interface is supported.
   - Arasan:
      - Finer grain NV-DDR configuration
      - Rename the data interface register
      - Use the right DMA mask
      - Leverage additional GPIO CS
      - Ensure proper configuration for the asserted target
      - Add support for the NV-DDR interface
      - Fix a macro parameter
   - brcmnand:
      - Convert bindings to json-schema
   - OMAP:
      - Various fixes and style improvements
      - Add larger page NAND chips support
   - PL35X:
      - New driver
   - QCOM:
      - Avoid writing to obsolete register
      - Delete an unneeded bool conversion
      - Allow override of partition parser
   - Marvell:
      - Minor documentation correction
      - Add missing clk_disable_unprepare() on error in
        marvell_nfc_resume()
   - R852:
      - Use DEVICE_ATTR_RO() helper macro
   - MTK:
      - Remove redundant dev_err call in mtk_ecc_probe()
   - HISI504:
      - Remove redundant dev_err call in probe

  SPI-NAND core:
   - Light reorganisation for the introduction of a core resume handler
   - Fix double counting of ECC stats

  SPI-NAND manufacturer drivers:
   - Macronix:
      - Add support for serial NAND flash

  SPI NOR core changes:
   - Ability to dump SFDP tables via sysfs
   - Support for erasing OTP regions on Winbond and similar flashes
   - Few API doc updates and fixes
   - Locking support for MX25L12805D

  SPI NOR controller drivers changes:
   - Use SPI_MODE_X_MASK in nxp-spifi
   - Intel Alder Lake-M SPI serial flash support"

* tag 'mtd/for-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (125 commits)
  mtd: spi-nor: remove redundant continue statement
  mtd: rawnand: omap: Add larger page NAND chips support
  mtd: rawnand: omap: Various style fixes
  mtd: rawnand: omap: Check return values
  mtd: rawnand: omap: Rename a macro
  mtd: rawnand: omap: Aggregate the HW configuration of the ELM
  mtd: rawnand: pl353: Add support for the ARM PL353 SMC NAND controller
  dt-bindings: mtd: pl353-nand: Describe this hardware controller
  MAINTAINERS: Add PL353 NAND controller entry
  mtd: rawnand: qcom: avoid writing to obsolete register
  mtd: rawnand: marvell: Minor documentation correction
  mtd: rawnand: r852: use DEVICE_ATTR_RO() helper macro
  mtd: spinand: add SPI-NAND MTD resume handler
  mtd: spinand: Add spinand_init_flash() helper
  mtd: spinand: add spinand_read_cfg() helper
  mtd: rawnand: marvell: add missing clk_disable_unprepare() on error in marvell_nfc_resume()
  mtd: rawnand: arasan: Finer grain NV-DDR configuration
  mtd: rawnand: arasan: Rename the data interface register
  mtd: rawnand: onfi: Fix endianness when reading NV-DDR values
  mtd: rawnand: arasan: Use the right DMA mask
  ...
parents 8fc4fb17 0bcc3939
What: /sys/bus/spi/devices/.../spi-nor/jedec_id
Date: April 2021
KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) The JEDEC ID of the SPI NOR flash as reported by the
flash device.
What: /sys/bus/spi/devices/.../spi-nor/manufacturer
Date: April 2021
KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) Manufacturer of the SPI NOR flash.
What: /sys/bus/spi/devices/.../spi-nor/partname
Date: April 2021
KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) Part name of the SPI NOR flash.
What: /sys/bus/spi/devices/.../spi-nor/sfdp
Date: April 2021
KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) This attribute is only present if the SPI NOR flash
device supports the "Read SFDP" command (5Ah).
If present, it contains the complete SFDP (serial flash
discoverable parameters) binary data of the flash.
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/arm,pl353-smc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PL353 Static Memory Controller (SMC) device-tree bindings
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
- Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
description:
The PL353 Static Memory Controller is a bus where you can connect two kinds
of memory interfaces, which are NAND and memory mapped interfaces (such as
SRAM or NOR).
# We need a select here so we don't match all nodes with 'arm,primecell'
select:
properties:
compatible:
contains:
const: arm,pl353-smc-r2p1
required:
- compatible
properties:
$nodename:
pattern: "^memory-controller@[0-9a-f]+$"
compatible:
items:
- const: arm,pl353-smc-r2p1
- const: arm,primecell
"#address-cells":
const: 2
"#size-cells":
const: 1
reg:
items:
- description:
Configuration registers for the host and sub-controllers.
The three chip select regions are defined in 'ranges'.
clocks:
items:
- description: clock for the memory device bus
- description: main clock of the SMC
clock-names:
items:
- const: memclk
- const: apb_pclk
ranges:
minItems: 1
maxItems: 3
description: |
Memory bus areas for interacting with the devices. Reflects
the memory layout with four integer values following:
<cs-number> 0 <offset> <size>
items:
- description: NAND bank 0
- description: NOR/SRAM bank 0
- description: NOR/SRAM bank 1
interrupts: true
patternProperties:
"@[0-3],[a-f0-9]+$":
type: object
description: |
The child device node represents the controller connected to the SMC
bus. The controller can be a NAND controller or a pair of any memory
mapped controllers such as NOR and SRAM controllers.
properties:
compatible:
description:
Compatible of memory controller.
reg:
items:
- items:
- description: |
Chip-select ID, as in the parent range property.
minimum: 0
maximum: 2
- description: |
Offset of the memory region requested by the device.
- description: |
Length of the memory region requested by the device.
required:
- compatible
- reg
required:
- compatible
- reg
- clock-names
- clocks
- "#address-cells"
- "#size-cells"
- ranges
additionalProperties: 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>;
};
};
Device tree bindings for ARM PL353 static memory controller
PL353 static memory controller supports two kinds of memory
interfaces.i.e NAND and SRAM/NOR interfaces.
The actual devices are instantiated from the child nodes of pl353 smc node.
Required properties:
- compatible : Should be "arm,pl353-smc-r2p1", "arm,primecell".
- reg : Controller registers map and length.
- clock-names : List of input clock names - "memclk", "apb_pclk"
(See clock bindings for details).
- clocks : Clock phandles (see clock bindings for details).
- address-cells : Must be 2.
- size-cells : Must be 1.
Child nodes:
For NAND the "arm,pl353-nand-r2p1" and for NOR the "cfi-flash" drivers are
supported as child nodes.
for NAND partition information please refer the below file
Documentation/devicetree/bindings/mtd/partition.txt
Example:
smcc: memory-controller@e000e000
compatible = "arm,pl353-smc-r2p1", "arm,primecell";
clock-names = "memclk", "apb_pclk";
clocks = <&clkc 11>, <&clkc 44>;
reg = <0xe000e000 0x1000>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0x0 0x0 0xe1000000 0x1000000 //Nand CS Region
0x1 0x0 0xe2000000 0x2000000 //SRAM/NOR CS Region
0x2 0x0 0xe4000000 0x2000000>; //SRAM/NOR CS Region
nand_0: flash@e1000000 {
compatible = "arm,pl353-nand-r2p1"
reg = <0 0 0x1000000>;
(...)
};
nor0: flash@e2000000 {
compatible = "cfi-flash";
reg = <1 0 0x2000000>;
};
nor1: flash@e4000000 {
compatible = "cfi-flash";
reg = <2 0 0x2000000>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/arm,pl353-nand-r2p1.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: PL353 NAND Controller device tree bindings
allOf:
- $ref: "nand-controller.yaml"
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
- Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
properties:
compatible:
items:
- const: arm,pl353-nand-r2p1
reg:
items:
- items:
- description: CS with regard to the parent ranges property
- description: Offset of the memory region requested by the device
- description: Length of the memory region requested by the device
required:
- compatible
- reg
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>;
};
};
* Broadcom STB NAND Controller
The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND
flash chips. It has a memory-mapped register interface for both control
registers and for its data input/output buffer. On some SoCs, this controller is
paired with a custom DMA engine (inventively named "Flash DMA") which supports
basic PROGRAM and READ functions, among other features.
This controller was originally designed for STB SoCs (BCM7xxx) but is now
available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and
iProc/Cygnus. Its history includes several similar (but not fully register
compatible) versions.
Required properties:
- compatible : May contain an SoC-specific compatibility string (see below)
to account for any SoC-specific hardware bits that may be
added on top of the base core controller.
In addition, must contain compatibility information about
the core NAND controller, of the following form:
"brcm,brcmnand" and an appropriate version compatibility
string, like "brcm,brcmnand-v7.0"
Possible values:
brcm,brcmnand-v2.1
brcm,brcmnand-v2.2
brcm,brcmnand-v4.0
brcm,brcmnand-v5.0
brcm,brcmnand-v6.0
brcm,brcmnand-v6.1
brcm,brcmnand-v6.2
brcm,brcmnand-v7.0
brcm,brcmnand-v7.1
brcm,brcmnand-v7.2
brcm,brcmnand-v7.3
brcm,brcmnand
- reg : the register start and length for NAND register region.
(optional) Flash DMA register range (if present)
(optional) NAND flash cache range (if at non-standard offset)
- reg-names : a list of the names corresponding to the previous register
ranges. Should contain "nand" and (optionally)
"flash-dma" or "flash-edu" and/or "nand-cache".
- interrupts : The NAND CTLRDY interrupt, (if Flash DMA is available)
FLASH_DMA_DONE and if EDU is avaialble and used FLASH_EDU_DONE
- interrupt-names : May be "nand_ctlrdy" or "flash_dma_done" or "flash_edu_done",
if broken out as individual interrupts.
May be "nand", if the SoC has the individual NAND
interrupts multiplexed behind another custom piece of
hardware
- #address-cells : <1> - subnodes give the chip-select number
- #size-cells : <0>
Optional properties:
- clock : reference to the clock for the NAND controller
- clock-names : "nand" (required for the above clock)
- brcm,nand-has-wp : Some versions of this IP include a write-protect
(WP) control bit. It is always available on >=
v7.0. Use this property to describe the rare
earlier versions of this core that include WP
-- Additional SoC-specific NAND controller properties --
The NAND controller is integrated differently on the variety of SoCs on which it
is found. Part of this integration involves providing status and enable bits
with which to control the 8 exposed NAND interrupts, as well as hardware for
configuring the endianness of the data bus. On some SoCs, these features are
handled via standard, modular components (e.g., their interrupts look like a
normal IRQ chip), but on others, they are controlled in unique and interesting
ways, sometimes with registers that lump multiple NAND-related functions
together. The former case can be described simply by the standard interrupts
properties in the main controller node. But for the latter exceptional cases,
we define additional 'compatible' properties and associated register resources within the NAND controller node above.
- compatible: Can be one of several SoC-specific strings. Each SoC may have
different requirements for its additional properties, as described below each
bullet point below.
* "brcm,nand-bcm63138"
- reg: (required) the 'NAND_INT_BASE' register range, with separate status
and enable registers
- reg-names: (required) "nand-int-base"
* "brcm,nand-bcm6368"
- compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm6368"
- reg: (required) the 'NAND_INTR_BASE' register range, with combined status
and enable registers, and boot address registers
- reg-names: (required) "nand-int-base"
* "brcm,nand-iproc"
- reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
for interrupt status/ack.
- reg-names: (required) a list of the names corresponding to the previous
register ranges. Should contain "iproc-idm" and "iproc-ext".
* NAND chip-select
Each controller (compatible: "brcm,brcmnand") may contain one or more subnodes
to represent enabled chip-selects which (may) contain NAND flash chips. Their
properties are as follows.
Required properties:
- compatible : should contain "brcm,nandcs"
- reg : a single integer representing the chip-select
number (e.g., 0, 1, 2, etc.)
- #address-cells : see partition.txt
- #size-cells : see partition.txt
Optional properties:
- nand-ecc-strength : see nand-controller.yaml
- nand-ecc-step-size : must be 512 or 1024. See nand-controller.yaml
- nand-on-flash-bbt : boolean, to enable the on-flash BBT for this
chip-select. See nand-controller.yaml
- brcm,nand-oob-sector-size : integer, to denote the spare area sector size
expected for the ECC layout in use. This size, in
addition to the strength and step-size,
determines how the hardware BCH engine will lay
out the parity bytes it stores on the flash.
This property can be automatically determined by
the flash geometry (particularly the NAND page
and OOB size) in many cases, but when booting
from NAND, the boot controller has only a limited
number of available options for its default ECC
layout.
Each nandcs device node may optionally contain sub-nodes describing the flash
partition mapping. See partition.txt for more detail.
Example:
nand@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>;
#address-cells = <1>;
#size-cells = <0>;
nandcs@1 {
compatible = "brcm,nandcs";
reg = <1>; // Chip select 1
nand-on-flash-bbt;
nand-ecc-strength = <12>;
nand-ecc-step-size = <512>;
// Partitions
#address-cells = <1>; // <2>, for 64-bit offset
#size-cells = <1>; // <2>, for 64-bit length
flash0.rootfs@0 {
reg = <0 0x10000000>;
};
flash0@0 {
reg = <0 0>; // MTDPART_SIZ_FULL
};
flash0.kernel@10000000 {
reg = <0x10000000 0x400000>;
};
};
};
nand@10000200 {
compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
"brcm,brcmnand-v4.0", "brcm,brcmnand";
reg = <0x10000200 0x180>,
<0x10000600 0x200>,
<0x100000b0 0x10>;
reg-names = "nand", "nand-cache", "nand-int-base";
interrupt-parent = <&periph_intc>;
interrupts = <50>;
clocks = <&periph_clk 20>;
clock-names = "nand";
#address-cells = <1>;
#size-cells = <0>;
nand0: nandcs@0 {
compatible = "brcm,nandcs";
reg = <0>;
nand-on-flash-bbt;
nand-ecc-strength = <1>;
nand-ecc-step-size = <512>;
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/brcm,brcmnand.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom STB NAND Controller
maintainers:
- Brian Norris <computersforpeace@gmail.com>
- Kamal Dasu <kdasu.kdev@gmail.com>
description: |
The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND
flash chips. It has a memory-mapped register interface for both control
registers and for its data input/output buffer. On some SoCs, this controller
is paired with a custom DMA engine (inventively named "Flash DMA") which
supports basic PROGRAM and READ functions, among other features.
This controller was originally designed for STB SoCs (BCM7xxx) but is now
available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and
iProc/Cygnus. Its history includes several similar (but not fully register
compatible) versions.
-- Additional SoC-specific NAND controller properties --
The NAND controller is integrated differently on the variety of SoCs on which
it is found. Part of this integration involves providing status and enable
bits with which to control the 8 exposed NAND interrupts, as well as hardware
for configuring the endianness of the data bus. On some SoCs, these features
are handled via standard, modular components (e.g., their interrupts look like
a normal IRQ chip), but on others, they are controlled in unique and
interesting ways, sometimes with registers that lump multiple NAND-related
functions together. The former case can be described simply by the standard
interrupts properties in the main controller node. But for the latter
exceptional cases, we define additional 'compatible' properties and associated
register resources within the NAND controller node above.
properties:
compatible:
oneOf:
- items:
- enum:
- brcm,brcmnand-v2.1
- brcm,brcmnand-v2.2
- brcm,brcmnand-v4.0
- brcm,brcmnand-v5.0
- brcm,brcmnand-v6.0
- brcm,brcmnand-v6.1
- brcm,brcmnand-v6.2
- brcm,brcmnand-v7.0
- brcm,brcmnand-v7.1
- brcm,brcmnand-v7.2
- brcm,brcmnand-v7.3
- const: brcm,brcmnand
- description: BCM63138 SoC-specific NAND controller
items:
- const: brcm,nand-bcm63138
- enum:
- brcm,brcmnand-v7.0
- brcm,brcmnand-v7.1
- const: brcm,brcmnand
- description: iProc SoC-specific NAND controller
items:
- const: brcm,nand-iproc
- const: brcm,brcmnand-v6.1
- const: brcm,brcmnand
- description: BCM63168 SoC-specific NAND controller
items:
- const: brcm,nand-bcm63168
- const: brcm,nand-bcm6368
- const: brcm,brcmnand-v4.0
- const: brcm,brcmnand
reg:
minItems: 1
maxItems: 6
reg-names:
minItems: 1
maxItems: 6
items:
enum: [ nand, flash-dma, flash-edu, nand-cache, nand-int-base, iproc-idm, iproc-ext ]
interrupts:
minItems: 1
maxItems: 3
items:
- description: NAND CTLRDY interrupt
- description: FLASH_DMA_DONE if flash DMA is available
- description: FLASH_EDU_DONE if EDU is available
interrupt-names:
minItems: 1
maxItems: 3
items:
- const: nand_ctlrdy
- const: flash_dma_done
- const: flash_edu_done
clocks:
maxItems: 1
description: reference to the clock for the NAND controller
clock-names:
const: nand
brcm,nand-has-wp:
description: >
Some versions of this IP include a write-protect
(WP) control bit. It is always available on >=
v7.0. Use this property to describe the rare
earlier versions of this core that include WP
type: boolean
patternProperties:
"^nand@[a-f0-9]$":
type: object
properties:
compatible:
const: brcm,nandcs
nand-ecc-step-size:
enum: [ 512, 1024 ]
brcm,nand-oob-sector-size:
description: |
integer, to denote the spare area sector size
expected for the ECC layout in use. This size, in
addition to the strength and step-size,
determines how the hardware BCH engine will lay
out the parity bytes it stores on the flash.
This property can be automatically determined by
the flash geometry (particularly the NAND page
and OOB size) in many cases, but when booting
from NAND, the boot controller has only a limited
number of available options for its default ECC
layout.
$ref: /schemas/types.yaml#/definitions/uint32
allOf:
- $ref: nand-controller.yaml#
- if:
properties:
compatible:
contains:
const: brcm,nand-bcm63138
then:
properties:
reg-names:
minItems: 2
maxItems: 2
items:
- const: nand
- const: nand-int-base
- if:
properties:
compatible:
contains:
const: brcm,nand-bcm6368
then:
properties:
reg-names:
minItems: 3
maxItems: 3
items:
- const: nand
- const: nand-int-base
- const: nand-cache
- if:
properties:
compatible:
contains:
const: brcm,nand-iproc
then:
properties:
reg-names:
minItems: 3
maxItems: 3
items:
- const: nand
- const: iproc-idm
- const: iproc-ext
unevaluatedProperties: false
required:
- reg
- reg-names
- interrupts
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>;
#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>;
};
};
- |
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";
#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>;
};
};
* Common properties of all MTD devices This file has been moved to mtd.yaml.
Optional properties:
- label: user-defined MTD device name. Can be used to assign user
friendly names to MTD devices (instead of the flash model or flash
controller based name) in order to ease flash device identification
and/or describe what they are used for.
Example:
flash@0 {
label = "System-firmware";
/* flash type specific properties */
};
...@@ -9,6 +9,9 @@ title: SPI NOR flash ST M25Pxx (and similar) serial flash chips ...@@ -9,6 +9,9 @@ title: SPI NOR flash ST M25Pxx (and similar) serial flash chips
maintainers: maintainers:
- Rob Herring <robh@kernel.org> - Rob Herring <robh@kernel.org>
allOf:
- $ref: "mtd.yaml#"
properties: properties:
compatible: compatible:
oneOf: oneOf:
...@@ -82,6 +85,9 @@ patternProperties: ...@@ -82,6 +85,9 @@ patternProperties:
'^partition@': '^partition@':
type: object type: object
"^otp(-[0-9]+)?$":
type: object
additionalProperties: false additionalProperties: false
examples: examples:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/mtd/microchip,mchp48l640.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Microchip 48l640 (and similar) serial EERAM bindings
maintainers:
- Heiko Schocher <hs@denx.de>
description: |
The Microchip 48l640 is a 8KByte EERAM connected via SPI.
datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20006055B.pdf
properties:
compatible:
items:
- const: microchip,48l640
reg:
maxItems: 1
spi-max-frequency: true
required:
- compatible
- reg
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
eeram@0 {
compatible = "microchip,48l640";
reg = <0>;
spi-max-frequency = <20000000>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/mtd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MTD (Memory Technology Device) Device Tree Bindings
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
- Richard Weinberger <richard@nod.at>
properties:
$nodename:
pattern: "^flash(@.*)?$"
label:
description:
User-defined MTD device name. Can be used to assign user friendly
names to MTD devices (instead of the flash model or flash controller
based name) in order to ease flash device identification and/or
describe what they are used for.
patternProperties:
"^otp(-[0-9]+)?$":
type: object
$ref: ../nvmem/nvmem.yaml#
description: |
An OTP memory region. Some flashes provide a one-time-programmable
memory whose content can either be programmed by a user or is already
pre-programmed by the factory. Some flashes might provide both.
properties:
compatible:
enum:
- user-otp
- factory-otp
required:
- compatible
additionalProperties: true
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
reg = <0>;
compatible = "jedec,spi-nor";
label = "System-firmware";
};
};
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
reg = <0>;
compatible = "jedec,spi-nor";
otp-1 {
compatible = "factory-otp";
#address-cells = <1>;
#size-cells = <1>;
electronic-serial-number@0 {
reg = <0 8>;
};
};
otp-2 {
compatible = "user-otp";
#address-cells = <1>;
#size-cells = <1>;
mac-address@0 {
reg = <0 6>;
};
};
};
};
...
...@@ -38,6 +38,17 @@ properties: ...@@ -38,6 +38,17 @@ properties:
ranges: true ranges: true
cs-gpios:
minItems: 1
maxItems: 8
description:
Array of chip-select available to the controller. The first
entries are a 1:1 mapping of the available chip-select on the
NAND controller (even if they are not used). As many additional
chip-select as needed may follow and should be phandles of GPIO
lines. 'reg' entries of the NAND chip subnodes become indexes of
this array when this property is present.
patternProperties: patternProperties:
"^nand@[a-f0-9]$": "^nand@[a-f0-9]$":
type: object type: object
...@@ -164,14 +175,19 @@ examples: ...@@ -164,14 +175,19 @@ examples:
nand-controller { nand-controller {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
cs-gpios = <0>, <&gpioA 1>; /* A single native CS is available */
/* controller specific properties */ /* controller specific properties */
nand@0 { nand@0 {
reg = <0>; reg = <0>; /* Native CS */
nand-use-soft-ecc-engine; nand-use-soft-ecc-engine;
nand-ecc-algo = "bch"; nand-ecc-algo = "bch";
/* controller specific properties */ /* controller specific properties */
}; };
nand@1 {
reg = <1>; /* GPIO CS */
};
}; };
...@@ -28,6 +28,11 @@ detected by a software parsing TRX header. ...@@ -28,6 +28,11 @@ detected by a software parsing TRX header.
Required properties: Required properties:
- compatible : (required) must be "brcm,trx" - compatible : (required) must be "brcm,trx"
Optional properties:
- brcm,trx-magic: TRX magic, if it is different from the default magic
0x30524448 as a u32.
Example: Example:
flash@0 { flash@0 {
......
Bindings for HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs
Required properties:
- compatible : "ti,am654-hbmc" for AM654 SoC
- reg : Two entries:
First entry pointed to the register space of HBMC controller
Second entry pointing to the memory map region dedicated for
MMIO access to attached flash devices
- ranges : Address translation from offset within CS to allocated MMIO
space in SoC
Optional properties:
- mux-controls : phandle to the multiplexer that controls selection of
HBMC vs OSPI inside Flash SubSystem (FSS). Default is OSPI,
if property is absent.
See Documentation/devicetree/bindings/mux/reg-mux.yaml
for mmio-mux binding details
Example:
system-controller@47000000 {
compatible = "syscon", "simple-mfd";
reg = <0x0 0x47000000 0x0 0x100>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
hbmc_mux: multiplexer {
compatible = "mmio-mux";
#mux-control-cells = <1>;
mux-reg-masks = <0x4 0x2>; /* 0: reg 0x4, bit 1 */
};
};
hbmc: hyperbus@47034000 {
compatible = "ti,am654-hbmc";
reg = <0x0 0x47034000 0x0 0x100>,
<0x5 0x00000000 0x1 0x0000000>;
power-domains = <&k3_pds 55>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */
<0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */
mux-controls = <&hbmc_mux 0>;
/* Slave flash node */
flash@0,0 {
compatible = "cypress,hyperflash", "cfi-flash";
reg = <0x0 0x0 0x4000000>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/ti,am654-hbmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HyperBus Memory Controller (HBMC) on TI's K3 family of SoCs
maintainers:
- Vignesh Raghavendra <vigneshr@ti.com>
properties:
compatible:
const: ti,am654-hbmc
reg:
maxItems: 2
power-domains: true
'#address-cells': true
'#size-cells': true
ranges: true
mux-controls:
description: MMIO mux controller node to select b/w OSPI and HBMC.
clocks:
maxItems: 1
patternProperties:
"^flash@[0-1],[0-9a-f]+$":
type: object
required:
- compatible
- reg
- ranges
- clocks
- '#address-cells'
- '#size-cells'
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>;
flash@0,0 {
compatible = "cypress,hyperflash", "cfi-flash";
reg = <0x0 0x0 0x4000000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
};
...@@ -1319,6 +1319,7 @@ W: http://www.aquantia.com ...@@ -1319,6 +1319,7 @@ W: http://www.aquantia.com
F: drivers/net/ethernet/aquantia/atlantic/aq_ptp* F: drivers/net/ethernet/aquantia/atlantic/aq_ptp*
ARASAN NAND CONTROLLER DRIVER ARASAN NAND CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com> M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-mtd@lists.infradead.org L: linux-mtd@lists.infradead.org
S: Maintained S: Maintained
...@@ -1460,6 +1461,22 @@ S: Odd Fixes ...@@ -1460,6 +1461,22 @@ S: Odd Fixes
F: drivers/amba/ F: drivers/amba/
F: include/linux/amba/bus.h F: include/linux/amba/bus.h
ARM PRIMECELL PL35X NAND CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-mtd@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
F: drivers/mtd/nand/raw/pl35x-nand-controller.c
ARM PRIMECELL PL35X SMC DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/mtd/arm,pl353-smc.yaml
F: drivers/memory/pl353-smc.c
ARM PRIMECELL CLCD PL110 DRIVER ARM PRIMECELL CLCD PL110 DRIVER
M: Russell King <linux@armlinux.org.uk> M: Russell King <linux@armlinux.org.uk>
S: Odd Fixes S: Odd Fixes
......
This diff is collapsed.
...@@ -31,14 +31,11 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *drv) ...@@ -31,14 +31,11 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *drv)
static struct mtd_chip_driver *get_mtd_chip_driver (const char *name) static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{ {
struct list_head *pos;
struct mtd_chip_driver *ret = NULL, *this; struct mtd_chip_driver *ret = NULL, *this;
spin_lock(&chip_drvs_lock); spin_lock(&chip_drvs_lock);
list_for_each(pos, &chip_drvs_list) { list_for_each_entry(this, &chip_drvs_list, list) {
this = list_entry(pos, typeof(*this), list);
if (!strcmp(this->name, name)) { if (!strcmp(this->name, name)) {
ret = this; ret = this;
break; break;
......
...@@ -89,6 +89,12 @@ config MTD_MCHP23K256 ...@@ -89,6 +89,12 @@ config MTD_MCHP23K256
platform data, or a device tree description if you want to platform data, or a device tree description if you want to
specify device partitioning specify device partitioning
config MTD_MCHP48L640
tristate "Microchip 48L640 EERAM"
depends on SPI_MASTER
help
This enables access to Microchip 48L640 EERAM chips, using SPI.
config MTD_SPEAR_SMI config MTD_SPEAR_SMI
tristate "SPEAR MTD NOR Support through SMI controller" tristate "SPEAR MTD NOR Support through SMI controller"
depends on PLAT_SPEAR || COMPILE_TEST depends on PLAT_SPEAR || COMPILE_TEST
......
...@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_LART) += lart.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o
obj-$(CONFIG_MTD_MCHP48L640) += mchp48l640.o
obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_SST25L) += sst25l.o
obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Microchip 48L640 64 Kb SPI Serial EERAM
*
* Copyright Heiko Schocher <hs@denx.de>
*
* datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20006055B.pdf
*
* we set continuous mode but reading/writing more bytes than
* pagesize seems to bring chip into state where readden values
* are wrong ... no idea why.
*
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/sizes.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/of_device.h>
struct mchp48_caps {
unsigned int size;
unsigned int page_size;
};
struct mchp48l640_flash {
struct spi_device *spi;
struct mutex lock;
struct mtd_info mtd;
const struct mchp48_caps *caps;
};
#define MCHP48L640_CMD_WREN 0x06
#define MCHP48L640_CMD_WRDI 0x04
#define MCHP48L640_CMD_WRITE 0x02
#define MCHP48L640_CMD_READ 0x03
#define MCHP48L640_CMD_WRSR 0x01
#define MCHP48L640_CMD_RDSR 0x05
#define MCHP48L640_STATUS_RDY 0x01
#define MCHP48L640_STATUS_WEL 0x02
#define MCHP48L640_STATUS_BP0 0x04
#define MCHP48L640_STATUS_BP1 0x08
#define MCHP48L640_STATUS_SWM 0x10
#define MCHP48L640_STATUS_PRO 0x20
#define MCHP48L640_STATUS_ASE 0x40
#define MCHP48L640_TIMEOUT 100
#define MAX_CMD_SIZE 0x10
#define to_mchp48l640_flash(x) container_of(x, struct mchp48l640_flash, mtd)
static int mchp48l640_mkcmd(struct mchp48l640_flash *flash, u8 cmd, loff_t addr, char *buf)
{
buf[0] = cmd;
buf[1] = addr >> 8;
buf[2] = addr;
return 3;
}
static int mchp48l640_read_status(struct mchp48l640_flash *flash, int *status)
{
unsigned char cmd[2];
int ret;
cmd[0] = MCHP48L640_CMD_RDSR;
cmd[1] = 0x00;
mutex_lock(&flash->lock);
ret = spi_write_then_read(flash->spi, &cmd[0], 1, &cmd[1], 1);
mutex_unlock(&flash->lock);
if (!ret)
*status = cmd[1];
dev_dbg(&flash->spi->dev, "read status ret: %d status: %x", ret, *status);
return ret;
}
static int mchp48l640_waitforbit(struct mchp48l640_flash *flash, int bit, bool set)
{
int ret, status;
unsigned long deadline;
deadline = jiffies + msecs_to_jiffies(MCHP48L640_TIMEOUT);
do {
ret = mchp48l640_read_status(flash, &status);
dev_dbg(&flash->spi->dev, "read status ret: %d bit: %x %sset status: %x",
ret, bit, (set ? "" : "not"), status);
if (ret)
return ret;
if (set) {
if ((status & bit) == bit)
return 0;
} else {
if ((status & bit) == 0)
return 0;
}
usleep_range(1000, 2000);
} while (!time_after_eq(jiffies, deadline));
dev_err(&flash->spi->dev, "Timeout waiting for bit %x %s set in status register.",
bit, (set ? "" : "not"));
return -ETIMEDOUT;
}
static int mchp48l640_write_prepare(struct mchp48l640_flash *flash, bool enable)
{
unsigned char cmd[2];
int ret;
if (enable)
cmd[0] = MCHP48L640_CMD_WREN;
else
cmd[0] = MCHP48L640_CMD_WRDI;
mutex_lock(&flash->lock);
ret = spi_write(flash->spi, cmd, 1);
mutex_unlock(&flash->lock);
if (ret)
dev_err(&flash->spi->dev, "write %sable failed ret: %d",
(enable ? "en" : "dis"), ret);
dev_dbg(&flash->spi->dev, "write %sable success ret: %d",
(enable ? "en" : "dis"), ret);
if (enable)
return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, true);
return ret;
}
static int mchp48l640_set_mode(struct mchp48l640_flash *flash)
{
unsigned char cmd[2];
int ret;
ret = mchp48l640_write_prepare(flash, true);
if (ret)
return ret;
cmd[0] = MCHP48L640_CMD_WRSR;
cmd[1] = MCHP48L640_STATUS_PRO;
mutex_lock(&flash->lock);
ret = spi_write(flash->spi, cmd, 2);
mutex_unlock(&flash->lock);
if (ret)
dev_err(&flash->spi->dev, "Could not set continuous mode ret: %d", ret);
return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_PRO, true);
}
static int mchp48l640_wait_rdy(struct mchp48l640_flash *flash)
{
return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_RDY, false);
};
static int mchp48l640_write_page(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const unsigned char *buf)
{
struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
unsigned char *cmd;
int ret;
int cmdlen;
cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA);
if (!cmd)
return -ENOMEM;
ret = mchp48l640_wait_rdy(flash);
if (ret)
goto fail;
ret = mchp48l640_write_prepare(flash, true);
if (ret)
goto fail;
mutex_lock(&flash->lock);
cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_WRITE, to, cmd);
memcpy(&cmd[cmdlen], buf, len);
ret = spi_write(flash->spi, cmd, cmdlen + len);
mutex_unlock(&flash->lock);
if (!ret)
*retlen += len;
else
goto fail;
ret = mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, false);
if (ret)
goto fail;
kfree(cmd);
return 0;
fail:
kfree(cmd);
dev_err(&flash->spi->dev, "write fail with: %d", ret);
return ret;
};
static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const unsigned char *buf)
{
struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
int ret;
size_t wlen = 0;
loff_t woff = to;
size_t ws;
size_t page_sz = flash->caps->page_size;
/*
* we set PRO bit (page rollover), but writing length > page size
* does result in total chaos, so write in 32 byte chunks.
*/
while (wlen < len) {
ws = min((len - wlen), page_sz);
ret = mchp48l640_write_page(mtd, woff, ws, retlen, &buf[wlen]);
if (ret)
return ret;
wlen += ws;
woff += ws;
}
return ret;
}
static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, unsigned char *buf)
{
struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
unsigned char *cmd;
int ret;
int cmdlen;
cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA);
if (!cmd)
return -ENOMEM;
ret = mchp48l640_wait_rdy(flash);
if (ret)
goto fail;
mutex_lock(&flash->lock);
cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_READ, from, cmd);
ret = spi_write_then_read(flash->spi, cmd, cmdlen, buf, len);
mutex_unlock(&flash->lock);
if (!ret)
*retlen += len;
return ret;
fail:
kfree(cmd);
dev_err(&flash->spi->dev, "read fail with: %d", ret);
return ret;
}
static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, unsigned char *buf)
{
struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
int ret;
size_t wlen = 0;
loff_t woff = from;
size_t ws;
size_t page_sz = flash->caps->page_size;
/*
* we set PRO bit (page rollover), but if read length > page size
* does result in total chaos in result ...
*/
while (wlen < len) {
ws = min((len - wlen), page_sz);
ret = mchp48l640_read_page(mtd, woff, ws, retlen, &buf[wlen]);
if (ret)
return ret;
wlen += ws;
woff += ws;
}
return ret;
};
static const struct mchp48_caps mchp48l640_caps = {
.size = SZ_8K,
.page_size = 32,
};
static int mchp48l640_probe(struct spi_device *spi)
{
struct mchp48l640_flash *flash;
struct flash_platform_data *data;
int err;
int status;
flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
if (!flash)
return -ENOMEM;
flash->spi = spi;
mutex_init(&flash->lock);
spi_set_drvdata(spi, flash);
err = mchp48l640_read_status(flash, &status);
if (err)
return err;
err = mchp48l640_set_mode(flash);
if (err)
return err;
data = dev_get_platdata(&spi->dev);
flash->caps = of_device_get_match_data(&spi->dev);
if (!flash->caps)
flash->caps = &mchp48l640_caps;
mtd_set_of_node(&flash->mtd, spi->dev.of_node);
flash->mtd.dev.parent = &spi->dev;
flash->mtd.type = MTD_RAM;
flash->mtd.flags = MTD_CAP_RAM;
flash->mtd.writesize = flash->caps->page_size;
flash->mtd.size = flash->caps->size;
flash->mtd._read = mchp48l640_read;
flash->mtd._write = mchp48l640_write;
err = mtd_device_register(&flash->mtd, data ? data->parts : NULL,
data ? data->nr_parts : 0);
if (err)
return err;
return 0;
}
static int mchp48l640_remove(struct spi_device *spi)
{
struct mchp48l640_flash *flash = spi_get_drvdata(spi);
return mtd_device_unregister(&flash->mtd);
}
static const struct of_device_id mchp48l640_of_table[] = {
{
.compatible = "microchip,48l640",
.data = &mchp48l640_caps,
},
{}
};
MODULE_DEVICE_TABLE(of, mchp48l640_of_table);
static struct spi_driver mchp48l640_driver = {
.driver = {
.name = "mchp48l640",
.of_match_table = of_match_ptr(mchp48l640_of_table),
},
.probe = mchp48l640_probe,
.remove = mchp48l640_remove,
};
module_spi_driver(mchp48l640_driver);
MODULE_DESCRIPTION("MTD SPI driver for Microchip 48l640 EERAM chips");
MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:mchp48l640");
...@@ -286,7 +286,6 @@ static int __init ms02nv_init(void) ...@@ -286,7 +286,6 @@ static int __init ms02nv_init(void)
break; break;
default: default:
return -ENODEV; return -ENODEV;
break;
} }
for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++) for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++)
......
...@@ -270,6 +270,7 @@ static int phram_setup(const char *val) ...@@ -270,6 +270,7 @@ static int phram_setup(const char *val)
if (len == 0 || erasesize == 0 || erasesize > len if (len == 0 || erasesize == 0 || erasesize > len
|| erasesize > UINT_MAX || rem) { || erasesize > UINT_MAX || rem) {
parse_err("illegal erasesize or len\n"); parse_err("illegal erasesize or len\n");
ret = -EINVAL;
goto error; goto error;
} }
......
...@@ -259,20 +259,13 @@ static int find_boot_record(struct INFTLrecord *inftl) ...@@ -259,20 +259,13 @@ static int find_boot_record(struct INFTLrecord *inftl)
/* Memory alloc */ /* Memory alloc */
inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
GFP_KERNEL); GFP_KERNEL);
if (!inftl->PUtable) { if (!inftl->PUtable)
printk(KERN_WARNING "INFTL: allocation of PUtable "
"failed (%zd bytes)\n",
inftl->nb_blocks * sizeof(u16));
return -ENOMEM; return -ENOMEM;
}
inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
GFP_KERNEL); GFP_KERNEL);
if (!inftl->VUtable) { if (!inftl->VUtable) {
kfree(inftl->PUtable); kfree(inftl->PUtable);
printk(KERN_WARNING "INFTL: allocation of VUtable "
"failed (%zd bytes)\n",
inftl->nb_blocks * sizeof(u16));
return -ENOMEM; return -ENOMEM;
} }
...@@ -330,7 +323,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, ...@@ -330,7 +323,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL); buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
if (!buf) if (!buf)
return -1; return -ENOMEM;
ret = -1; ret = -1;
for (i = 0; i < len; i += SECTORSIZE) { for (i = 0; i < len; i += SECTORSIZE) {
...@@ -558,12 +551,8 @@ int INFTL_mount(struct INFTLrecord *s) ...@@ -558,12 +551,8 @@ int INFTL_mount(struct INFTLrecord *s)
/* Temporary buffer to store ANAC numbers. */ /* Temporary buffer to store ANAC numbers. */
ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL); ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL);
if (!ANACtable) { if (!ANACtable)
printk(KERN_WARNING "INFTL: allocation of ANACtable "
"failed (%zd bytes)\n",
s->nb_blocks * sizeof(u8));
return -ENOMEM; return -ENOMEM;
}
/* /*
* First pass is to explore each physical unit, and construct the * First pass is to explore each physical unit, and construct the
......
...@@ -189,10 +189,8 @@ static int amd76xrom_init_one(struct pci_dev *pdev, ...@@ -189,10 +189,8 @@ static int amd76xrom_init_one(struct pci_dev *pdev,
if (!map) { if (!map) {
map = kmalloc(sizeof(*map), GFP_KERNEL); map = kmalloc(sizeof(*map), GFP_KERNEL);
} if (!map)
if (!map) { goto out;
printk(KERN_ERR MOD_NAME ": kmalloc failed");
goto out;
} }
memset(map, 0, sizeof(*map)); memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list); INIT_LIST_HEAD(&map->list);
......
...@@ -217,12 +217,10 @@ static int __init ck804xrom_init_one(struct pci_dev *pdev, ...@@ -217,12 +217,10 @@ static int __init ck804xrom_init_one(struct pci_dev *pdev,
unsigned long offset; unsigned long offset;
int i; int i;
if (!map)
map = kmalloc(sizeof(*map), GFP_KERNEL);
if (!map) { if (!map) {
printk(KERN_ERR MOD_NAME ": kmalloc failed"); map = kmalloc(sizeof(*map), GFP_KERNEL);
goto out; if (!map)
goto out;
} }
memset(map, 0, sizeof(*map)); memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list); INIT_LIST_HEAD(&map->list);
......
...@@ -277,11 +277,10 @@ static int __init esb2rom_init_one(struct pci_dev *pdev, ...@@ -277,11 +277,10 @@ static int __init esb2rom_init_one(struct pci_dev *pdev,
unsigned long offset; unsigned long offset;
int i; int i;
if (!map)
map = kmalloc(sizeof(*map), GFP_KERNEL);
if (!map) { if (!map) {
printk(KERN_ERR MOD_NAME ": kmalloc failed"); map = kmalloc(sizeof(*map), GFP_KERNEL);
goto out; if (!map)
goto out;
} }
memset(map, 0, sizeof(*map)); memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list); INIT_LIST_HEAD(&map->list);
......
...@@ -213,10 +213,8 @@ static int __init ichxrom_init_one(struct pci_dev *pdev, ...@@ -213,10 +213,8 @@ static int __init ichxrom_init_one(struct pci_dev *pdev,
if (!map) { if (!map) {
map = kmalloc(sizeof(*map), GFP_KERNEL); map = kmalloc(sizeof(*map), GFP_KERNEL);
} if (!map)
if (!map) { goto out;
printk(KERN_ERR MOD_NAME ": kmalloc failed");
goto out;
} }
memset(map, 0, sizeof(*map)); memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list); INIT_LIST_HEAD(&map->list);
......
...@@ -127,7 +127,6 @@ static int platram_probe(struct platform_device *pdev) ...@@ -127,7 +127,6 @@ static int platram_probe(struct platform_device *pdev)
info->map.virt = devm_ioremap_resource(&pdev->dev, res); info->map.virt = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->map.virt)) { if (IS_ERR(info->map.virt)) {
err = PTR_ERR(info->map.virt); err = PTR_ERR(info->map.virt);
dev_err(&pdev->dev, "failed to ioremap() region\n");
goto exit_free; goto exit_free;
} }
......
...@@ -62,10 +62,8 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp) ...@@ -62,10 +62,8 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
} }
up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL);
if (!up) { if (!up)
printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n");
return -ENOMEM; return -ENOMEM;
}
/* copy defaults and tweak parameters */ /* copy defaults and tweak parameters */
memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ));
......
This diff is collapsed.
...@@ -401,10 +401,8 @@ static int __init mtdoops_init(void) ...@@ -401,10 +401,8 @@ static int __init mtdoops_init(void)
cxt->mtd_index = mtd_index; cxt->mtd_index = mtd_index;
cxt->oops_buf = vmalloc(record_size); cxt->oops_buf = vmalloc(record_size);
if (!cxt->oops_buf) { if (!cxt->oops_buf)
printk(KERN_ERR "mtdoops: failed to allocate buffer workspace\n");
return -ENOMEM; return -ENOMEM;
}
memset(cxt->oops_buf, 0xff, record_size); memset(cxt->oops_buf, 0xff, record_size);
cxt->oops_buf_busy = 0; cxt->oops_buf_busy = 0;
......
...@@ -212,15 +212,14 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent, ...@@ -212,15 +212,14 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
return child; return child;
} }
static ssize_t mtd_partition_offset_show(struct device *dev, static ssize_t offset_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mtd_info *mtd = dev_get_drvdata(dev); struct mtd_info *mtd = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%lld\n", mtd->part.offset); return sysfs_emit(buf, "%lld\n", mtd->part.offset);
} }
static DEVICE_ATTR_RO(offset); /* mtd partition offset */
static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL);
static const struct attribute *mtd_partition_attrs[] = { static const struct attribute *mtd_partition_attrs[] = {
&dev_attr_offset.attr, &dev_attr_offset.attr,
......
...@@ -123,7 +123,7 @@ int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry, ...@@ -123,7 +123,7 @@ int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
unsigned int rbits = bits_per_block + offs - BITS_PER_LONG; unsigned int rbits = bits_per_block + offs - BITS_PER_LONG;
pos[1] &= ~GENMASK(rbits - 1, 0); pos[1] &= ~GENMASK(rbits - 1, 0);
pos[1] |= val >> rbits; pos[1] |= val >> (bits_per_block - rbits);
} }
return 0; return 0;
......
...@@ -453,6 +453,14 @@ config MTD_NAND_ROCKCHIP ...@@ -453,6 +453,14 @@ config MTD_NAND_ROCKCHIP
NFC v800: RK3308, RV1108 NFC v800: RK3308, RV1108
NFC v900: PX30, RK3326 NFC v900: PX30, RK3326
config MTD_NAND_PL35X
tristate "ARM PL35X NAND controller"
depends on OF || COMPILE_TEST
depends on PL353_SMC
help
Enables support for PrimeCell SMC PL351 and PL353 NAND
controller found on Zynq7000.
comment "Misc" comment "Misc"
config MTD_SM_COMMON config MTD_SM_COMMON
......
...@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o ...@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o
obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o
obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o nand-objs += nand_onfi.o
......
...@@ -1246,7 +1246,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, ...@@ -1246,7 +1246,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
nc = to_nand_controller(nand->base.controller); nc = to_nand_controller(nand->base.controller);
/* DDR interface not supported. */ /* DDR interface not supported. */
if (conf->type != NAND_SDR_IFACE) if (!nand_interface_is_sdr(conf))
return -ENOTSUPP; return -ENOTSUPP;
/* /*
...@@ -1524,8 +1524,13 @@ static int atmel_nand_setup_interface(struct nand_chip *chip, int csline, ...@@ -1524,8 +1524,13 @@ static int atmel_nand_setup_interface(struct nand_chip *chip, int csline,
const struct nand_interface_config *conf) const struct nand_interface_config *conf)
{ {
struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand *nand = to_atmel_nand(chip);
const struct nand_sdr_timings *sdr;
struct atmel_nand_controller *nc; struct atmel_nand_controller *nc;
sdr = nand_get_sdr_timings(conf);
if (IS_ERR(sdr))
return PTR_ERR(sdr);
nc = to_nand_controller(nand->base.controller); nc = to_nand_controller(nand->base.controller);
if (csline >= nand->numcs || if (csline >= nand->numcs ||
...@@ -1629,10 +1634,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, ...@@ -1629,10 +1634,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
} }
nand = devm_kzalloc(nc->dev, struct_size(nand, cs, numcs), GFP_KERNEL); nand = devm_kzalloc(nc->dev, struct_size(nand, cs, numcs), GFP_KERNEL);
if (!nand) { if (!nand)
dev_err(nc->dev, "Failed to allocate NAND object\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
nand->numcs = numcs; nand->numcs = numcs;
......
...@@ -2348,9 +2348,9 @@ cadence_nand_setup_interface(struct nand_chip *chip, int chipnr, ...@@ -2348,9 +2348,9 @@ cadence_nand_setup_interface(struct nand_chip *chip, int chipnr,
* for tRP and tRH timings. If it is NOT possible to sample data * for tRP and tRH timings. If it is NOT possible to sample data
* with optimal tRP/tRH settings, the parameters will be extended. * with optimal tRP/tRH settings, the parameters will be extended.
* If clk_period is 50ns (the lowest value) this condition is met * If clk_period is 50ns (the lowest value) this condition is met
* for asynchronous timing modes 1, 2, 3, 4 and 5. * for SDR timing modes 1, 2, 3, 4 and 5.
* If clk_period is 20ns the condition is met only * If clk_period is 20ns the condition is met only for SDR timing
* for asynchronous timing mode 5. * mode 5.
*/ */
if (sdr->tRC_min <= clk_period && if (sdr->tRC_min <= clk_period &&
sdr->tRP_min <= (clk_period / 2) && sdr->tRP_min <= (clk_period / 2) &&
......
...@@ -79,7 +79,7 @@ enum gpmi_type { ...@@ -79,7 +79,7 @@ enum gpmi_type {
struct gpmi_devdata { struct gpmi_devdata {
enum gpmi_type type; enum gpmi_type type;
int bch_max_ecc_strength; int bch_max_ecc_strength;
int max_chain_delay; /* See the async EDO mode */ int max_chain_delay; /* See the SDR EDO mode */
const char * const *clks; const char * const *clks;
const int clks_count; const int clks_count;
}; };
......
...@@ -761,10 +761,8 @@ static int hisi_nfc_probe(struct platform_device *pdev) ...@@ -761,10 +761,8 @@ static int hisi_nfc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
host->mmio = devm_ioremap_resource(dev, res); host->mmio = devm_ioremap_resource(dev, res);
if (IS_ERR(host->mmio)) { if (IS_ERR(host->mmio))
dev_err(dev, "devm_ioremap_resource[1] fail\n");
return PTR_ERR(host->mmio); return PTR_ERR(host->mmio);
}
mtd->name = "hisi_nand"; mtd->name = "hisi_nand";
mtd->dev.parent = &pdev->dev; mtd->dev.parent = &pdev->dev;
......
...@@ -90,9 +90,14 @@ void onfi_fill_interface_config(struct nand_chip *chip, ...@@ -90,9 +90,14 @@ void onfi_fill_interface_config(struct nand_chip *chip,
unsigned int timing_mode); unsigned int timing_mode);
unsigned int unsigned int
onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
unsigned int
onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings);
int nand_choose_best_sdr_timings(struct nand_chip *chip, int nand_choose_best_sdr_timings(struct nand_chip *chip,
struct nand_interface_config *iface, struct nand_interface_config *iface,
struct nand_sdr_timings *spec_timings); struct nand_sdr_timings *spec_timings);
int nand_choose_best_nvddr_timings(struct nand_chip *chip,
struct nand_interface_config *iface,
struct nand_nvddr_timings *spec_timings);
const struct nand_interface_config *nand_get_reset_interface_config(void); const struct nand_interface_config *nand_get_reset_interface_config(void);
int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
......
...@@ -451,7 +451,7 @@ struct marvell_nfc_timings { ...@@ -451,7 +451,7 @@ struct marvell_nfc_timings {
}; };
/** /**
* Derives a duration in numbers of clock cycles. * TO_CYCLES() - Derives a duration in numbers of clock cycles.
* *
* @ps: Duration in pico-seconds * @ps: Duration in pico-seconds
* @period_ns: Clock period in nano-seconds * @period_ns: Clock period in nano-seconds
...@@ -3030,8 +3030,10 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev) ...@@ -3030,8 +3030,10 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev)
return ret; return ret;
ret = clk_prepare_enable(nfc->reg_clk); ret = clk_prepare_enable(nfc->reg_clk);
if (ret < 0) if (ret < 0) {
clk_disable_unprepare(nfc->core_clk);
return ret; return ret;
}
/* /*
* Reset nfc->selected_chip so the next command will cause the timing * Reset nfc->selected_chip so the next command will cause the timing
......
...@@ -515,10 +515,8 @@ static int mtk_ecc_probe(struct platform_device *pdev) ...@@ -515,10 +515,8 @@ static int mtk_ecc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ecc->regs = devm_ioremap_resource(dev, res); ecc->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(ecc->regs)) { if (IS_ERR(ecc->regs))
dev_err(dev, "failed to map regs: %ld\n", PTR_ERR(ecc->regs));
return PTR_ERR(ecc->regs); return PTR_ERR(ecc->regs);
}
ecc->clk = devm_clk_get(dev, NULL); ecc->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ecc->clk)) { if (IS_ERR(ecc->clk)) {
......
This diff is collapsed.
...@@ -369,7 +369,7 @@ static void nand_ccs_delay(struct nand_chip *chip) ...@@ -369,7 +369,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
* Wait tCCS_min if it is correctly defined, otherwise wait 500ns * Wait tCCS_min if it is correctly defined, otherwise wait 500ns
* (which should be safe for all NANDs). * (which should be safe for all NANDs).
*/ */
if (nand_controller_can_setup_interface(chip)) if (!IS_ERR(sdr) && nand_controller_can_setup_interface(chip))
ndelay(sdr->tCCS_min / 1000); ndelay(sdr->tCCS_min / 1000);
else else
ndelay(500); ndelay(500);
......
...@@ -315,7 +315,10 @@ int nand_onfi_detect(struct nand_chip *chip) ...@@ -315,7 +315,10 @@ int nand_onfi_detect(struct nand_chip *chip)
onfi->tBERS = le16_to_cpu(p->t_bers); onfi->tBERS = le16_to_cpu(p->t_bers);
onfi->tR = le16_to_cpu(p->t_r); onfi->tR = le16_to_cpu(p->t_r);
onfi->tCCS = le16_to_cpu(p->t_ccs); onfi->tCCS = le16_to_cpu(p->t_ccs);
onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode); onfi->fast_tCAD = le16_to_cpu(p->nvddr_nvddr2_features) & BIT(0);
onfi->sdr_timing_modes = le16_to_cpu(p->sdr_timing_modes);
if (le16_to_cpu(p->features) & ONFI_FEATURE_NV_DDR)
onfi->nvddr_timing_modes = le16_to_cpu(p->nvddr_timing_modes);
onfi->vendor_revision = le16_to_cpu(p->vendor_revision); onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
memcpy(onfi->vendor, p->vendor, sizeof(p->vendor)); memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
chip->parameters.onfi = onfi; chip->parameters.onfi = onfi;
......
This diff is collapsed.
This diff is collapsed.
...@@ -116,7 +116,7 @@ int elm_config(struct device *dev, enum bch_ecc bch_type, ...@@ -116,7 +116,7 @@ int elm_config(struct device *dev, enum bch_ecc bch_type,
return -EINVAL; return -EINVAL;
} }
/* ELM support 8 error syndrome process */ /* ELM support 8 error syndrome process */
if (ecc_steps > ERROR_VECTOR_MAX) { if (ecc_steps > ERROR_VECTOR_MAX && ecc_steps % ERROR_VECTOR_MAX) {
dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps); dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps);
return -EINVAL; return -EINVAL;
} }
......
This diff is collapsed.
...@@ -734,6 +734,7 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i ...@@ -734,6 +734,7 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i
{ {
struct nand_chip *chip = &host->chip; struct nand_chip *chip = &host->chip;
u32 cmd, cfg0, cfg1, ecc_bch_cfg; u32 cmd, cfg0, cfg1, ecc_bch_cfg;
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
if (read) { if (read) {
if (host->use_ecc) if (host->use_ecc)
...@@ -762,7 +763,8 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i ...@@ -762,7 +763,8 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i
nandc_set_reg(chip, NAND_DEV0_CFG0, cfg0); nandc_set_reg(chip, NAND_DEV0_CFG0, cfg0);
nandc_set_reg(chip, NAND_DEV0_CFG1, cfg1); nandc_set_reg(chip, NAND_DEV0_CFG1, cfg1);
nandc_set_reg(chip, NAND_DEV0_ECC_CFG, ecc_bch_cfg); nandc_set_reg(chip, NAND_DEV0_ECC_CFG, ecc_bch_cfg);
nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg); if (!nandc->props->qpic_v2)
nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg);
nandc_set_reg(chip, NAND_FLASH_STATUS, host->clrflashstatus); nandc_set_reg(chip, NAND_FLASH_STATUS, host->clrflashstatus);
nandc_set_reg(chip, NAND_READ_STATUS, host->clrreadstatus); nandc_set_reg(chip, NAND_READ_STATUS, host->clrreadstatus);
nandc_set_reg(chip, NAND_EXEC_CMD, 1); nandc_set_reg(chip, NAND_EXEC_CMD, 1);
...@@ -1133,7 +1135,8 @@ static void config_nand_page_read(struct nand_chip *chip) ...@@ -1133,7 +1135,8 @@ static void config_nand_page_read(struct nand_chip *chip)
write_reg_dma(nandc, NAND_ADDR0, 2, 0); write_reg_dma(nandc, NAND_ADDR0, 2, 0);
write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0); if (!nandc->props->qpic_v2)
write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0);
write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0); write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0);
write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1,
NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
...@@ -1191,8 +1194,9 @@ static void config_nand_page_write(struct nand_chip *chip) ...@@ -1191,8 +1194,9 @@ static void config_nand_page_write(struct nand_chip *chip)
write_reg_dma(nandc, NAND_ADDR0, 2, 0); write_reg_dma(nandc, NAND_ADDR0, 2, 0);
write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, if (!nandc->props->qpic_v2)
NAND_BAM_NEXT_SGL); write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1,
NAND_BAM_NEXT_SGL);
} }
/* /*
...@@ -1248,7 +1252,8 @@ static int nandc_param(struct qcom_nand_host *host) ...@@ -1248,7 +1252,8 @@ static int nandc_param(struct qcom_nand_host *host)
| 2 << WR_RD_BSY_GAP | 2 << WR_RD_BSY_GAP
| 0 << WIDE_FLASH | 0 << WIDE_FLASH
| 1 << DEV0_CFG1_ECC_DISABLE); | 1 << DEV0_CFG1_ECC_DISABLE);
nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE); if (!nandc->props->qpic_v2)
nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE);
/* configure CMD1 and VLD for ONFI param probing in QPIC v1 */ /* configure CMD1 and VLD for ONFI param probing in QPIC v1 */
if (!nandc->props->qpic_v2) { if (!nandc->props->qpic_v2) {
...@@ -1850,8 +1855,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf, ...@@ -1850,8 +1855,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
* ERASED_CW bits are set. * ERASED_CW bits are set.
*/ */
if (host->bch_enabled) { if (host->bch_enabled) {
erased = (erased_cw & ERASED_CW) == ERASED_CW ? erased = (erased_cw & ERASED_CW) == ERASED_CW;
true : false;
/* /*
* For RS ECC, HW reports the erased CW by placing * For RS ECC, HW reports the erased CW by placing
* special characters at certain offsets in the buffer. * special characters at certain offsets in the buffer.
...@@ -2689,7 +2693,8 @@ static int qcom_nand_attach_chip(struct nand_chip *chip) ...@@ -2689,7 +2693,8 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
| ecc_mode << ECC_MODE | ecc_mode << ECC_MODE
| host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH; | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH;
host->ecc_buf_cfg = 0x203 << NUM_STEPS; if (!nandc->props->qpic_v2)
host->ecc_buf_cfg = 0x203 << NUM_STEPS;
host->clrflashstatus = FS_READY_BSY_N; host->clrflashstatus = FS_READY_BSY_N;
host->clrreadstatus = 0xc0; host->clrreadstatus = 0xc0;
...@@ -2882,7 +2887,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) ...@@ -2882,7 +2887,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
return 0; return 0;
} }
static const char * const probes[] = { "qcomsmem", NULL }; static const char * const probes[] = { "cmdlinepart", "ofpart", "qcomsmem", NULL };
static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
struct qcom_nand_host *host, struct qcom_nand_host *host,
......
...@@ -583,8 +583,8 @@ static void r852_update_card_detect(struct r852_device *dev) ...@@ -583,8 +583,8 @@ static void r852_update_card_detect(struct r852_device *dev)
r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg); r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg);
} }
static ssize_t r852_media_type_show(struct device *sys_dev, static ssize_t media_type_show(struct device *sys_dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mtd_info *mtd = container_of(sys_dev, struct mtd_info, dev); struct mtd_info *mtd = container_of(sys_dev, struct mtd_info, dev);
struct r852_device *dev = r852_get_dev(mtd); struct r852_device *dev = r852_get_dev(mtd);
...@@ -593,8 +593,7 @@ static ssize_t r852_media_type_show(struct device *sys_dev, ...@@ -593,8 +593,7 @@ static ssize_t r852_media_type_show(struct device *sys_dev,
strcpy(buf, data); strcpy(buf, data);
return strlen(data); return strlen(data);
} }
static DEVICE_ATTR_RO(media_type);
static DEVICE_ATTR(media_type, S_IRUGO, r852_media_type_show, NULL);
/* Detect properties of card in slot */ /* Detect properties of card in slot */
......
...@@ -1972,10 +1972,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, ...@@ -1972,10 +1972,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels), sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels),
GFP_KERNEL); GFP_KERNEL);
if (!sunxi_nand) { if (!sunxi_nand)
dev_err(dev, "could not allocate chip\n");
return -ENOMEM; return -ENOMEM;
}
sunxi_nand->nsels = nsels; sunxi_nand->nsels = nsels;
......
...@@ -138,20 +138,12 @@ int spinand_select_target(struct spinand_device *spinand, unsigned int target) ...@@ -138,20 +138,12 @@ int spinand_select_target(struct spinand_device *spinand, unsigned int target)
return 0; return 0;
} }
static int spinand_init_cfg_cache(struct spinand_device *spinand) static int spinand_read_cfg(struct spinand_device *spinand)
{ {
struct nand_device *nand = spinand_to_nand(spinand); struct nand_device *nand = spinand_to_nand(spinand);
struct device *dev = &spinand->spimem->spi->dev;
unsigned int target; unsigned int target;
int ret; int ret;
spinand->cfg_cache = devm_kcalloc(dev,
nand->memorg.ntargets,
sizeof(*spinand->cfg_cache),
GFP_KERNEL);
if (!spinand->cfg_cache)
return -ENOMEM;
for (target = 0; target < nand->memorg.ntargets; target++) { for (target = 0; target < nand->memorg.ntargets; target++) {
ret = spinand_select_target(spinand, target); ret = spinand_select_target(spinand, target);
if (ret) if (ret)
...@@ -170,6 +162,21 @@ static int spinand_init_cfg_cache(struct spinand_device *spinand) ...@@ -170,6 +162,21 @@ static int spinand_init_cfg_cache(struct spinand_device *spinand)
return 0; return 0;
} }
static int spinand_init_cfg_cache(struct spinand_device *spinand)
{
struct nand_device *nand = spinand_to_nand(spinand);
struct device *dev = &spinand->spimem->spi->dev;
spinand->cfg_cache = devm_kcalloc(dev,
nand->memorg.ntargets,
sizeof(*spinand->cfg_cache),
GFP_KERNEL);
if (!spinand->cfg_cache)
return -ENOMEM;
return 0;
}
static int spinand_init_quad_enable(struct spinand_device *spinand) static int spinand_init_quad_enable(struct spinand_device *spinand)
{ {
bool enable = false; bool enable = false;
...@@ -290,6 +297,8 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, ...@@ -290,6 +297,8 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
{ {
struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv; struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv;
struct spinand_device *spinand = nand_to_spinand(nand); struct spinand_device *spinand = nand_to_spinand(nand);
struct mtd_info *mtd = spinand_to_mtd(spinand);
int ret;
if (req->mode == MTD_OPS_RAW) if (req->mode == MTD_OPS_RAW)
return 0; return 0;
...@@ -299,7 +308,13 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, ...@@ -299,7 +308,13 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
return 0; return 0;
/* Finish a page write: check the status, report errors/bitflips */ /* Finish a page write: check the status, report errors/bitflips */
return spinand_check_ecc_status(spinand, engine_conf->status); ret = spinand_check_ecc_status(spinand, engine_conf->status);
if (ret == -EBADMSG)
mtd->ecc_stats.failed++;
else if (ret > 0)
mtd->ecc_stats.corrected += ret;
return ret;
} }
static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = { static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
...@@ -635,13 +650,10 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, ...@@ -635,13 +650,10 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
if (ret < 0 && ret != -EBADMSG) if (ret < 0 && ret != -EBADMSG)
break; break;
if (ret == -EBADMSG) { if (ret == -EBADMSG)
ecc_failed = true; ecc_failed = true;
mtd->ecc_stats.failed++; else
} else {
mtd->ecc_stats.corrected += ret;
max_bitflips = max_t(unsigned int, max_bitflips, ret); max_bitflips = max_t(unsigned int, max_bitflips, ret);
}
ret = 0; ret = 0;
ops->retlen += iter.req.datalen; ops->retlen += iter.req.datalen;
...@@ -1093,12 +1105,71 @@ static int spinand_detect(struct spinand_device *spinand) ...@@ -1093,12 +1105,71 @@ static int spinand_detect(struct spinand_device *spinand)
return 0; return 0;
} }
static int spinand_init_flash(struct spinand_device *spinand)
{
struct device *dev = &spinand->spimem->spi->dev;
struct nand_device *nand = spinand_to_nand(spinand);
int ret, i;
ret = spinand_read_cfg(spinand);
if (ret)
return ret;
ret = spinand_init_quad_enable(spinand);
if (ret)
return ret;
ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0);
if (ret)
return ret;
ret = spinand_manufacturer_init(spinand);
if (ret) {
dev_err(dev,
"Failed to initialize the SPI NAND chip (err = %d)\n",
ret);
return ret;
}
/* After power up, all blocks are locked, so unlock them here. */
for (i = 0; i < nand->memorg.ntargets; i++) {
ret = spinand_select_target(spinand, i);
if (ret)
break;
ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
if (ret)
break;
}
if (ret)
spinand_manufacturer_cleanup(spinand);
return ret;
}
static void spinand_mtd_resume(struct mtd_info *mtd)
{
struct spinand_device *spinand = mtd_to_spinand(mtd);
int ret;
ret = spinand_reset_op(spinand);
if (ret)
return;
ret = spinand_init_flash(spinand);
if (ret)
return;
spinand_ecc_enable(spinand, false);
}
static int spinand_init(struct spinand_device *spinand) static int spinand_init(struct spinand_device *spinand)
{ {
struct device *dev = &spinand->spimem->spi->dev; struct device *dev = &spinand->spimem->spi->dev;
struct mtd_info *mtd = spinand_to_mtd(spinand); struct mtd_info *mtd = spinand_to_mtd(spinand);
struct nand_device *nand = mtd_to_nanddev(mtd); struct nand_device *nand = mtd_to_nanddev(mtd);
int ret, i; int ret;
/* /*
* We need a scratch buffer because the spi_mem interface requires that * We need a scratch buffer because the spi_mem interface requires that
...@@ -1131,22 +1202,10 @@ static int spinand_init(struct spinand_device *spinand) ...@@ -1131,22 +1202,10 @@ static int spinand_init(struct spinand_device *spinand)
if (ret) if (ret)
goto err_free_bufs; goto err_free_bufs;
ret = spinand_init_quad_enable(spinand); ret = spinand_init_flash(spinand);
if (ret) if (ret)
goto err_free_bufs; goto err_free_bufs;
ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0);
if (ret)
goto err_free_bufs;
ret = spinand_manufacturer_init(spinand);
if (ret) {
dev_err(dev,
"Failed to initialize the SPI NAND chip (err = %d)\n",
ret);
goto err_free_bufs;
}
ret = spinand_create_dirmaps(spinand); ret = spinand_create_dirmaps(spinand);
if (ret) { if (ret) {
dev_err(dev, dev_err(dev,
...@@ -1155,17 +1214,6 @@ static int spinand_init(struct spinand_device *spinand) ...@@ -1155,17 +1214,6 @@ static int spinand_init(struct spinand_device *spinand)
goto err_manuf_cleanup; goto err_manuf_cleanup;
} }
/* After power up, all blocks are locked, so unlock them here. */
for (i = 0; i < nand->memorg.ntargets; i++) {
ret = spinand_select_target(spinand, i);
if (ret)
goto err_manuf_cleanup;
ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
if (ret)
goto err_manuf_cleanup;
}
ret = nanddev_init(nand, &spinand_ops, THIS_MODULE); ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
if (ret) if (ret)
goto err_manuf_cleanup; goto err_manuf_cleanup;
...@@ -1186,6 +1234,7 @@ static int spinand_init(struct spinand_device *spinand) ...@@ -1186,6 +1234,7 @@ static int spinand_init(struct spinand_device *spinand)
mtd->_block_isreserved = spinand_mtd_block_isreserved; mtd->_block_isreserved = spinand_mtd_block_isreserved;
mtd->_erase = spinand_mtd_erase; mtd->_erase = spinand_mtd_erase;
mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks; mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
mtd->_resume = spinand_mtd_resume;
if (nand->ecc.engine) { if (nand->ecc.engine) {
ret = mtd_ooblayout_count_freebytes(mtd); ret = mtd_ooblayout_count_freebytes(mtd);
......
...@@ -186,6 +186,118 @@ static const struct spinand_info macronix_spinand_table[] = { ...@@ -186,6 +186,118 @@ static const struct spinand_info macronix_spinand_table[] = {
0 /*SPINAND_HAS_QE_BIT*/, 0 /*SPINAND_HAS_QE_BIT*/,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)), mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35LF2G14AC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF4G24AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5),
NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF4GE4AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7),
NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF2G14AC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF2G24AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4),
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF2GE4AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6),
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),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF2GE4AC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2),
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF1G14AC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF1G24AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94),
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF1GE4AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96),
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35UF1GE4AC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
}; };
static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
......
...@@ -619,7 +619,6 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) ...@@ -619,7 +619,6 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
return BLOCK_NIL; return BLOCK_NIL;
} }
//printk("Restarting scan\n"); //printk("Restarting scan\n");
lastEUN = BLOCK_NIL;
continue; continue;
} }
......
...@@ -188,17 +188,14 @@ device is already correct. ...@@ -188,17 +188,14 @@ device is already correct.
/* memory alloc */ /* memory alloc */
nftl->EUNtable = kmalloc_array(nftl->nb_blocks, sizeof(u16), nftl->EUNtable = kmalloc_array(nftl->nb_blocks, sizeof(u16),
GFP_KERNEL); GFP_KERNEL);
if (!nftl->EUNtable) { if (!nftl->EUNtable)
printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
return -ENOMEM; return -ENOMEM;
}
nftl->ReplUnitTable = kmalloc_array(nftl->nb_blocks, nftl->ReplUnitTable = kmalloc_array(nftl->nb_blocks,
sizeof(u16), sizeof(u16),
GFP_KERNEL); GFP_KERNEL);
if (!nftl->ReplUnitTable) { if (!nftl->ReplUnitTable) {
kfree(nftl->EUNtable); kfree(nftl->EUNtable);
printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -269,7 +266,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int ...@@ -269,7 +266,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int
buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL); buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
if (!buf) if (!buf)
return -1; return -ENOMEM;
ret = -1; ret = -1;
for (i = 0; i < len; i += SECTORSIZE) { for (i = 0; i < len; i += SECTORSIZE) {
......
...@@ -115,7 +115,7 @@ config MTD_AFS_PARTS ...@@ -115,7 +115,7 @@ config MTD_AFS_PARTS
config MTD_PARSER_TRX config MTD_PARSER_TRX
tristate "Parser for TRX format partitions" tristate "Parser for TRX format partitions"
depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST)
help help
TRX is a firmware format used by Broadcom on their devices. It TRX is a firmware format used by Broadcom on their devices. It
may contain up to 3/4 partitions (depending on the version). may contain up to 3/4 partitions (depending on the version).
......
...@@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_info *mtd, ...@@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_info *mtd,
const struct mtd_partition **pparts, const struct mtd_partition **pparts,
struct mtd_part_parser_data *data) struct mtd_part_parser_data *data)
{ {
struct device_node *np = mtd_get_of_node(mtd);
struct mtd_partition *parts; struct mtd_partition *parts;
struct mtd_partition *part; struct mtd_partition *part;
struct trx_header trx; struct trx_header trx;
size_t bytes_read; size_t bytes_read;
uint8_t curr_part = 0, i = 0; uint8_t curr_part = 0, i = 0;
uint32_t trx_magic = TRX_MAGIC;
int err; int err;
/* Get different magic from device tree if specified */
err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic);
if (err != 0 && err != -EINVAL)
pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err);
parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition),
GFP_KERNEL); GFP_KERNEL);
if (!parts) if (!parts)
...@@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_info *mtd, ...@@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_info *mtd,
return err; return err;
} }
if (trx.magic != TRX_MAGIC) { if (trx.magic != trx_magic) {
kfree(parts); kfree(parts);
return -ENOENT; return -ENOENT;
} }
......
...@@ -159,6 +159,15 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, ...@@ -159,6 +159,15 @@ static int parse_qcomsmem_part(struct mtd_info *mtd,
return ret; return ret;
} }
static void parse_qcomsmem_cleanup(const struct mtd_partition *pparts,
int nr_parts)
{
int i;
for (i = 0; i < nr_parts; i++)
kfree(pparts[i].name);
}
static const struct of_device_id qcomsmem_of_match_table[] = { static const struct of_device_id qcomsmem_of_match_table[] = {
{ .compatible = "qcom,smem-part" }, { .compatible = "qcom,smem-part" },
{}, {},
...@@ -167,6 +176,7 @@ MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table); ...@@ -167,6 +176,7 @@ MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table);
static struct mtd_part_parser mtd_parser_qcomsmem = { static struct mtd_part_parser mtd_parser_qcomsmem = {
.parse_fn = parse_qcomsmem_part, .parse_fn = parse_qcomsmem_part,
.cleanup = parse_qcomsmem_cleanup,
.name = "qcomsmem", .name = "qcomsmem",
.of_match_table = qcomsmem_of_match_table, .of_match_table = qcomsmem_of_match_table,
}; };
......
This diff is collapsed.
...@@ -192,11 +192,8 @@ static int scan_header(struct partition *part) ...@@ -192,11 +192,8 @@ static int scan_header(struct partition *part)
part->sector_map = vmalloc(array_size(sizeof(u_long), part->sector_map = vmalloc(array_size(sizeof(u_long),
part->sector_count)); part->sector_count));
if (!part->sector_map) { if (!part->sector_map)
printk(KERN_ERR PREFIX "'%s': unable to allocate memory for "
"sector map", part->mbd.mtd->name);
goto err; goto err;
}
for (i=0; i<part->sector_count; i++) for (i=0; i<part->sector_count; i++)
part->sector_map[i] = -1; part->sector_map[i] = -1;
......
This diff is collapsed.
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
spi-nor-objs := core.o sfdp.o swp.o otp.o spi-nor-objs := core.o sfdp.o swp.o otp.o sysfs.o
spi-nor-objs += atmel.o spi-nor-objs += atmel.o
spi-nor-objs += catalyst.o spi-nor-objs += catalyst.o
spi-nor-objs += eon.o spi-nor-objs += eon.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment