Commit a36cf686 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mtd/for-4.20' of git://git.infradead.org/linux-mtd

Pull mtd updates from Boris Brezillon:
 "SPI NOR core changes:
   - Support non-uniform erase size
   - Support controllers with limited TX fifo size

 Driver changes:
   - m25p80: Re-issue a WREN command after each write access
   - cadence: Pass a proper dir value to dma_[un]map_single()
   - fsl-qspi: Check fsl_qspi_get_seqid() return val make sure 4B
     addressing opcodes are properly handled
   - intel-spi: Add a new PCI entry for Ice Lake

 Raw NAND core changes:
   - Two batchs of cleanups of the NAND API, including:
      * Deprecating a lot of interfaces (now replaced by ->exec_op()).
      * Moving code in separate drivers (JEDEC, ONFI), in private files
        (internals), in platform drivers, etc.
      * Functions/structures reordering.
      * Exclusive use of the nand_chip structure instead of the MTD one
        all across the subsystem.
   - Addition of the nand_wait_readrdy/rdy_op() helpers.

 Raw NAND controllers drivers changes:
   - Various coccinelle patches.
   - Marvell:
      * Use regmap_update_bits() for syscon access.
      * More documentation.
      * BCH failure path rework.
      * More layouts to be supported.
      * IRQ handler complete() condition fixed.
   - Fsl_ifc:
      * SRAM initialization fixed for newer controller versions.
   - Denali:
      * Fix licenses mismatch and use a SPDX tag.
      * Set SPARE_AREA_SKIP_BYTES register to 8 if unset.
   - Qualcomm:
      * Do not include dma-direct.h.
   - Docg4:
      * Removed.
   - Ams-delta:
      * Use of a GPIO lookup table
      * Internal machinery changes.

 Raw NAND chip drivers changes:
   - Toshiba:
      * Add support for Toshiba memory BENAND
      * Pass a single nand_chip object to the status helper.
   - ESMT:
      * New driver to retrieve the ECC requirements from the 5th ID
        byte.

  MTD changes:
   - physmap cleanups/fixe
   - gpio-addr-flash cleanups/fixes"

* tag 'mtd/for-4.20' of git://git.infradead.org/linux-mtd: (93 commits)
  jffs2: free jffs2_sb_info through jffs2_kill_sb()
  mtd: spi-nor: fsl-quadspi: fix read error for flash size larger than 16MB
  mtd: spi-nor: intel-spi: Add support for Intel Ice Lake SPI serial flash
  mtd: maps: gpio-addr-flash: Convert to gpiod
  mtd: maps: gpio-addr-flash: Replace array with an integer
  mtd: maps: gpio-addr-flash: Use order instead of size
  mtd: spi-nor: fsl-quadspi: Don't let -EINVAL on the bus
  mtd: devices: m25p80: Make sure WRITE_EN is issued before each write
  mtd: spi-nor: Support controllers with limited TX FIFO size
  mtd: spi-nor: cadence-quadspi: Use proper enum for dma_[un]map_single
  mtd: spi-nor: parse SFDP Sector Map Parameter Table
  mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories
  mtd: rawnand: marvell: fix the IRQ handler complete() condition
  mtd: rawnand: denali: set SPARE_AREA_SKIP_BYTES register to 8 if unset
  mtd: rawnand: r852: fix spelling mistake "card_registred" -> "card_registered"
  mtd: rawnand: toshiba: Pass a single nand_chip object to the status helper
  mtd: maps: gpio-addr-flash: Use devm_* functions
  mtd: maps: gpio-addr-flash: Fix ioremapped size
  mtd: maps: gpio-addr-flash: Replace custom printk
  mtd: physmap_of: Release resources on error
  ...
parents b8e445b6 042c1a5a
Loading
Loading
Loading
Loading
+17 −17
Original line number Diff line number Diff line
@@ -180,10 +180,10 @@ by a chip select decoder.
    {
        struct nand_chip *this = mtd_to_nand(mtd);
        switch(cmd){
            case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT;  break;
            case NAND_CTL_CLRCLE: this->IO_ADDR_W &= ~CLE_ADRR_BIT; break;
            case NAND_CTL_SETALE: this->IO_ADDR_W |= ALE_ADRR_BIT;  break;
            case NAND_CTL_CLRALE: this->IO_ADDR_W &= ~ALE_ADRR_BIT; break;
            case NAND_CTL_SETCLE: this->legacy.IO_ADDR_W |= CLE_ADRR_BIT;  break;
            case NAND_CTL_CLRCLE: this->legacy.IO_ADDR_W &= ~CLE_ADRR_BIT; break;
            case NAND_CTL_SETALE: this->legacy.IO_ADDR_W |= ALE_ADRR_BIT;  break;
            case NAND_CTL_CLRALE: this->legacy.IO_ADDR_W &= ~ALE_ADRR_BIT; break;
        }
    }

@@ -197,7 +197,7 @@ to read back the state of the pin. The function has no arguments and
should return 0, if the device is busy (R/B pin is low) and 1, if the
device is ready (R/B pin is high). If the hardware interface does not
give access to the ready busy pin, then the function must not be defined
and the function pointer this->dev_ready is set to NULL.
and the function pointer this->legacy.dev_ready is set to NULL.

Init function
-------------
@@ -235,18 +235,18 @@ necessary information about the device.
        }

        /* Set address of NAND IO lines */
        this->IO_ADDR_R = baseaddr;
        this->IO_ADDR_W = baseaddr;
        this->legacy.IO_ADDR_R = baseaddr;
        this->legacy.IO_ADDR_W = baseaddr;
        /* Reference hardware control function */
        this->hwcontrol = board_hwcontrol;
        /* Set command delay time, see datasheet for correct value */
        this->chip_delay = CHIP_DEPENDEND_COMMAND_DELAY;
        this->legacy.chip_delay = CHIP_DEPENDEND_COMMAND_DELAY;
        /* Assign the device ready function, if available */
        this->dev_ready = board_dev_ready;
        this->legacy.dev_ready = board_dev_ready;
        this->eccmode = NAND_ECC_SOFT;

        /* Scan to find existence of the device */
        if (nand_scan (board_mtd, 1)) {
        if (nand_scan (this, 1)) {
            err = -ENXIO;
            goto out_ior;
        }
@@ -277,7 +277,7 @@ unregisters the partitions in the MTD layer.
    static void __exit board_cleanup (void)
    {
        /* Release resources, unregister device */
        nand_release (board_mtd);
        nand_release (mtd_to_nand(board_mtd));

        /* unmap physical address */
        iounmap(baseaddr);
@@ -336,17 +336,17 @@ connected to an address decoder.
        struct nand_chip *this = mtd_to_nand(mtd);

        /* Deselect all chips */
        this->IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK;
        this->IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK;
        this->legacy.IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK;
        this->legacy.IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK;
        switch (chip) {
        case 0:
            this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0;
            this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0;
            this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0;
            this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0;
            break;
        ....
        case n:
            this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn;
            this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn;
            this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn;
            this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn;
            break;
        }
    }
+0 −113
Original line number Diff line number Diff line

About this document
===================

Some notes about Marvell's NAND controller available in PXA and Armada 370/XP
SoC (aka NFCv1 and NFCv2), with an emphasis on the latter.

NFCv2 controller background
===========================

The controller has a 2176 bytes FIFO buffer. Therefore, in order to support
larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of
chunked transfers.

For instance, if we choose a 2048 data chunk and set "BCH" ECC (see below)
we'll have this layout in the pages:

  ------------------------------------------------------------------------------
  | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... |
  ------------------------------------------------------------------------------

The driver reads the data and spare portions independently and builds an internal
buffer with this layout (in the 4 KiB page case):

  ------------------------------------------
  |     4096B data     |     64B spare     |
  ------------------------------------------

Also, for the READOOB command the driver disables the ECC and reads a 'spare + ECC'
OOB, one per chunk read.

  -------------------------------------------------------------------
  |     4096B data     |  32B spare | 30B ECC | 32B spare | 30B ECC |
  -------------------------------------------------------------------

So, in order to achieve reading (for instance), we issue several READ0 commands
(with some additional controller-specific magic) and read two chunks of 2080B
(2048 data + 32 spare) each.
The driver accommodates this data to expose the NAND core a contiguous buffer
(4096 data + spare) or (4096 + spare + ECC + spare + ECC).

ECC
===

The controller has built-in hardware ECC capabilities. In addition it is
configurable between two modes: 1) Hamming, 2) BCH.

Note that the actual BCH mode: BCH-4 or BCH-8 will depend on the way
the controller is configured to transfer the data.

In the BCH mode the ECC code will be calculated for each transferred chunk
and expected to be located (when reading/programming) right after the spare
bytes as the figure above shows.

So, repeating the above scheme, a 2048B data chunk will be followed by 32B
spare, and then the ECC controller will read/write the ECC code (30B in
this case):

  ------------------------------------
  | 2048B data | 32B spare | 30B ECC |
  ------------------------------------

If the ECC mode is 'BCH' then the ECC is *always* 30 bytes long.
If the ECC mode is 'Hamming' the ECC is 6 bytes long, for each 512B block.
So in Hamming mode, a 2048B page will have a 24B ECC.

Despite all of the above, the controller requires the driver to only read or
write in multiples of 8-bytes, because the data buffer is 64-bits.

OOB
===

Because of the above scheme, and because the "spare" OOB is really located in
the middle of a page, spare OOB cannot be read or write independently of the
data area. In other words, in order to read the OOB (aka READOOB), the entire
page (aka READ0) has to be read.

In the same sense, in order to write to the spare OOB the driver has to write
an *entire* page.

Factory bad blocks handling
===========================

Given the ECC BCH requires to layout the device's pages in a split
data/OOB/data/OOB way, the controller has a view of the flash page that's
different from the specified (aka the manufacturer's) view. In other words,

Factory view:

  -----------------------------------------------
  |                    Data           |x  OOB   |
  -----------------------------------------------

Driver's view:

  -----------------------------------------------
  |      Data      | OOB |      Data   x  | OOB |
  -----------------------------------------------

It can be seen from the above, that the factory bad block marker must be
searched within the 'data' region, and not in the usual OOB region.

In addition, this means under regular usage the driver will write such
position (since it belongs to the data region) and every used block is
likely to be marked as bad.

For this reason, marking the block as bad in the OOB is explicitly
disabled by using the NAND_BBT_NO_OOB_BBM option in the driver. The rationale
for this is that there's no point in marking a block as bad, because good
blocks are also 'marked as bad' (in the OOB BBM sense) under normal usage.

Instead, the driver relies on the bad block table alone, and should only perform
the bad block scan on the very first time (when the device hasn't been used).
+6 −9
Original line number Diff line number Diff line
@@ -23,8 +23,7 @@
#include <linux/i2c.h>
#include <linux/fb.h>

#include <linux/mtd/partitions.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>

#include <mach/hardware.h>
#include <linux/platform_data/video-ep93xx.h>
@@ -43,12 +42,11 @@
#define SNAPPERCL15_NAND_CEN	(1 << 11) /* Chip enable (active low) */
#define SNAPPERCL15_NAND_RDY	(1 << 14) /* Device ready */

#define NAND_CTRL_ADDR(chip) 	(chip->IO_ADDR_W + 0x40)
#define NAND_CTRL_ADDR(chip) 	(chip->legacy.IO_ADDR_W + 0x40)

static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void snappercl15_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
				      unsigned int ctrl)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	static u16 nand_state = SNAPPERCL15_NAND_WPN;
	u16 set;

@@ -70,13 +68,12 @@ static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
	}

	if (cmd != NAND_CMD_NONE)
		__raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W);
		__raw_writew((cmd & 0xff) | nand_state,
			     chip->legacy.IO_ADDR_W);
}

static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
static int snappercl15_nand_dev_ready(struct nand_chip *chip)
{
	struct nand_chip *chip = mtd_to_nand(mtd);

	return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
}

+6 −10
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/spi/mmc_spi.h>
@@ -76,13 +75,11 @@ static void __init ts72xx_map_io(void)
#define TS72XX_NAND_CONTROL_ADDR_LINE	22	/* 0xN0400000 */
#define TS72XX_NAND_BUSY_ADDR_LINE	23	/* 0xN0800000 */

static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
static void ts72xx_nand_hwcontrol(struct nand_chip *chip,
				  int cmd, unsigned int ctrl)
{
	struct nand_chip *chip = mtd_to_nand(mtd);

	if (ctrl & NAND_CTRL_CHANGE) {
		void __iomem *addr = chip->IO_ADDR_R;
		void __iomem *addr = chip->legacy.IO_ADDR_R;
		unsigned char bits;

		addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
@@ -96,13 +93,12 @@ static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
	}

	if (cmd != NAND_CMD_NONE)
		__raw_writeb(cmd, chip->IO_ADDR_W);
		__raw_writeb(cmd, chip->legacy.IO_ADDR_W);
}

static int ts72xx_nand_device_ready(struct mtd_info *mtd)
static int ts72xx_nand_device_ready(struct nand_chip *chip)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	void __iomem *addr = chip->IO_ADDR_R;
	void __iomem *addr = chip->legacy.IO_ADDR_R;

	addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);

+8 −9
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
#include <linux/memory.h>
#include <linux/platform_device.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>
#include <linux/gpio.h>

#include <asm/mach-types.h>
@@ -129,30 +129,29 @@ static void qong_init_nor_mtd(void)
/*
 * Hardware specific access to control-lines
 */
static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void qong_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd,
			       unsigned int ctrl)
{
	struct nand_chip *nand_chip = mtd_to_nand(mtd);

	if (cmd == NAND_CMD_NONE)
		return;

	if (ctrl & NAND_CLE)
		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24));
		writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 24));
	else
		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23));
		writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 23));
}

/*
 * Read the Device Ready pin.
 */
static int qong_nand_device_ready(struct mtd_info *mtd)
static int qong_nand_device_ready(struct nand_chip *chip)
{
	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
}

static void qong_nand_select_chip(struct mtd_info *mtd, int chip)
static void qong_nand_select_chip(struct nand_chip *chip, int cs)
{
	if (chip >= 0)
	if (cs >= 0)
		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
	else
		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
Loading