1
0
Fork 0

SPI NOR changes:

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
 
 NAND changes:
  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
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCgA6FiEEKmCqpbOU668PNA69Ze02AX4ItwAFAlvNmJocHGJvcmlzLmJy
 ZXppbGxvbkBib290bGluLmNvbQAKCRBl7TYBfgi3AKr+D/4pH0gYSGDUstZsqUHW
 gZsPRU4jmOA+OCRbSxE03bOZOYR0UPgdoUYLfAKhZ5qxc7wHd3b47wykP0kUEviu
 lC8QhSs4DUA+EuMVPDVS4FlXRT0e3dMV7jh/IK6nInshD2YkaovyCqa6GvgwFEcM
 7BCizxRhtHV8+fo7GVQWuMLb9ZfbEvz42D0sYOu6hIsF1SnRDvHOvfdDUFEXpJoF
 a2mC9ove65ChEzc2iZ/r260iZ4aoJYb9XJRJKWxmYeITZSmLNmcrUyGqAaNQ7NRc
 AIuPXASbeHGjrIuEfXpKYW07AE5MV1nJFSk3v4u5FjgoohOoobPp7npk+Lz/qwe3
 y8/uW9qOQ/iEOsRnkvMGNu4Yjhw41L1a+J5wVvUvzmwHy1xMCrRHYB/8gXoZzemR
 A7XmCPwjAFVWv1WeKV2cs5MLW9yZq9QNMtGLlNs5OgFR6CccLk67/tHIkYLsJ/l9
 IDXFhd/YKhTeF361u6Iimmgb427TwM71P9N+OMpv4nk46DxurpxkgGle3nslzKNU
 DOFNFlMGiPIx3h4X96AKER6u7cxiOXnLGq+XeHa/y8tIrziy3jg03YoTh0RSwKxV
 J3EXwh1sFLaeebwWEgpE3Ag1LOxpRCqJ2ED71SPzS/DR/938HBVsEoPqUEHNf1in
 jwsUB3cRzNwf+XX68DRCVT5GFA==
 =7w4w
 -----END PGP SIGNATURE-----

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-10-23 01:09:22 +01:00
commit a36cf68651
119 changed files with 5375 additions and 5999 deletions

View File

@ -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;
}
}

View File

@ -1,113 +0,0 @@
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).

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -20,6 +20,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <asm/types.h>
@ -75,9 +76,8 @@ static struct mtd_partition ixdp425_partitions[] = {
};
static void
ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
ixdp425_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
int offset = (int)nand_get_controller_data(this);
if (ctrl & NAND_CTRL_CHANGE) {
@ -93,7 +93,7 @@ ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W + offset);
writeb(cmd, this->legacy.IO_ADDR_W + offset);
}
static struct platform_nand_data ixdp425_flash_nand_data = {

View File

@ -16,8 +16,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/smc91x.h>
@ -186,7 +185,7 @@ static struct platform_device nor_device = {
#define FSAMPLE_NAND_RB_GPIO_PIN 62
static int nand_dev_ready(struct mtd_info *mtd)
static int nand_dev_ready(struct nand_chip *chip)
{
return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN);
}

View File

@ -24,8 +24,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/mfd/tps65010.h>
@ -182,7 +181,7 @@ static struct mtd_partition h2_nand_partitions[] = {
#define H2_NAND_RB_GPIO_PIN 62
static int h2_nand_dev_ready(struct mtd_info *mtd)
static int h2_nand_dev_ready(struct nand_chip *chip)
{
return gpio_get_value(H2_NAND_RB_GPIO_PIN);
}

View File

@ -23,7 +23,7 @@
#include <linux/workqueue.h>
#include <linux/i2c.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
@ -185,7 +185,7 @@ static struct mtd_partition nand_partitions[] = {
#define H3_NAND_RB_GPIO_PIN 10
static int nand_dev_ready(struct mtd_info *mtd)
static int nand_dev_ready(struct nand_chip *chip)
{
return gpio_get_value(H3_NAND_RB_GPIO_PIN);
}

View File

@ -20,9 +20,8 @@
#include "common.h"
void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
void omap1_nand_cmd_ctl(struct nand_chip *this, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long mask;
if (cmd == NAND_CMD_NONE)
@ -32,6 +31,6 @@ void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
if (ctrl & NAND_ALE)
mask |= 0x04;
writeb(cmd, this->IO_ADDR_W + mask);
writeb(cmd, this->legacy.IO_ADDR_W + mask);
}

View File

@ -16,8 +16,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/smc91x.h>
@ -144,7 +143,7 @@ static struct platform_device nor_device = {
#define P2_NAND_RB_GPIO_PIN 62
static int nand_dev_ready(struct mtd_info *mtd)
static int nand_dev_ready(struct nand_chip *chip)
{
return gpio_get_value(P2_NAND_RB_GPIO_PIN);
}

View File

@ -26,7 +26,6 @@
#ifndef __ARCH_ARM_MACH_OMAP1_COMMON_H
#define __ARCH_ARM_MACH_OMAP1_COMMON_H
#include <linux/mtd/mtd.h>
#include <linux/platform_data/i2c-omap.h>
#include <linux/reboot.h>
@ -82,7 +81,8 @@ void omap1_restart(enum reboot_mode, const char *);
extern void __init omap_check_revision(void);
extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
struct nand_chip;
extern void omap1_nand_cmd_ctl(struct nand_chip *this, int cmd,
unsigned int ctrl);
extern void omap1_timer_init(void);

View File

@ -16,8 +16,7 @@
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/timeriomem-rng.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -131,11 +130,9 @@ static void ts78xx_ts_rtc_unload(void)
* NAND_CLE: bit 1 -> bit 1
* NAND_ALE: bit 2 -> bit 0
*/
static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void ts78xx_ts_nand_cmd_ctrl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
if (ctrl & NAND_CTRL_CHANGE) {
unsigned char bits;
@ -147,19 +144,18 @@ static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W);
writeb(cmd, this->legacy.IO_ADDR_W);
}
static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip)
{
return readb(TS_NAND_CTRL) & 0x20;
}
static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
static void ts78xx_ts_nand_write_buf(struct nand_chip *chip,
const uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
void __iomem *io_base = chip->IO_ADDR_W;
void __iomem *io_base = chip->legacy.IO_ADDR_W;
unsigned long off = ((unsigned long)buf & 3);
int sz;
@ -182,11 +178,10 @@ static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
writesb(io_base, buf, len);
}
static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
uint8_t *buf, int len)
static void ts78xx_ts_nand_read_buf(struct nand_chip *chip,
uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
void __iomem *io_base = chip->IO_ADDR_R;
void __iomem *io_base = chip->legacy.IO_ADDR_R;
unsigned long off = ((unsigned long)buf & 3);
int sz;

View File

@ -25,11 +25,10 @@
#include <linux/ioport.h>
#include <linux/ucb1400.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/types.h>
#include <linux/platform_data/pcf857x.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/regulator/max1586.h>
@ -571,9 +570,9 @@ static inline void balloon3_i2c_init(void) {}
* NAND
******************************************************************************/
#if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void balloon3_nand_cmd_ctl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
if (ctrl & NAND_CTRL_CHANGE) {
@ -597,10 +596,10 @@ static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ct
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W);
writeb(cmd, this->legacy.IO_ADDR_W);
}
static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
static void balloon3_nand_select_chip(struct nand_chip *this, int chip)
{
if (chip < 0 || chip > 3)
return;
@ -616,7 +615,7 @@ static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
BALLOON3_NAND_CONTROL_REG);
}
static int balloon3_nand_dev_ready(struct mtd_info *mtd)
static int balloon3_nand_dev_ready(struct nand_chip *this)
{
return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB;
}

View File

@ -15,8 +15,7 @@
#include <linux/dm9000.h>
#include <linux/platform_data/rtc-v3020.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
@ -285,11 +284,10 @@ static void nand_cs_off(void)
}
/* hardware specific access to control-lines */
static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
static void em_x270_nand_cmd_ctl(struct nand_chip *this, int dat,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
unsigned long nandaddr = (unsigned long)this->legacy.IO_ADDR_W;
dsb();
@ -309,15 +307,15 @@ static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
}
dsb();
this->IO_ADDR_W = (void __iomem *)nandaddr;
this->legacy.IO_ADDR_W = (void __iomem *)nandaddr;
if (dat != NAND_CMD_NONE)
writel(dat, this->IO_ADDR_W);
writel(dat, this->legacy.IO_ADDR_W);
dsb();
}
/* read device ready pin */
static int em_x270_nand_device_ready(struct mtd_info *mtd)
static int em_x270_nand_device_ready(struct nand_chip *this)
{
dsb();

View File

@ -403,36 +403,6 @@ static void __init palmtreo_leds_init(void)
platform_device_register(&palmtreo_leds);
}
/******************************************************************************
* diskonchip docg4 flash
******************************************************************************/
#if defined(CONFIG_MACH_TREO680)
/* REVISIT: does the centro have this device also? */
#if IS_ENABLED(CONFIG_MTD_NAND_DOCG4)
static struct resource docg4_resources[] = {
{
.start = 0x00000000,
.end = 0x00001FFF,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device treo680_docg4_flash = {
.name = "docg4",
.id = -1,
.resource = docg4_resources,
.num_resources = ARRAY_SIZE(docg4_resources),
};
static void __init treo680_docg4_flash_init(void)
{
platform_device_register(&treo680_docg4_flash);
}
#else
static inline void treo680_docg4_flash_init(void) {}
#endif
#endif
/******************************************************************************
* Machine init
******************************************************************************/
@ -517,7 +487,6 @@ static void __init treo680_init(void)
treo680_gpio_init();
palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
GPIO_NR_TREO680_SD_POWER, 0);
treo680_docg4_flash_init();
}
#endif

View File

@ -28,8 +28,7 @@
#include <linux/wm97xx.h>
#include <linux/power_supply.h>
#include <linux/usb/gpio_vbus.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h>
@ -247,11 +246,10 @@ static inline void palmtx_keys_init(void) {}
******************************************************************************/
#if defined(CONFIG_MTD_NAND_PLATFORM) || \
defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void palmtx_nand_cmd_ctl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
char __iomem *nandaddr = this->IO_ADDR_W;
char __iomem *nandaddr = this->legacy.IO_ADDR_W;
if (cmd == NAND_CMD_NONE)
return;

View File

@ -29,8 +29,7 @@
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/spi/spi.h>
@ -197,11 +196,10 @@ static struct i2c_board_info db1200_i2c_devs[] __initdata = {
/**********************************************************************/
static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void au1200_nand_cmd_ctrl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W;
ioaddr &= 0xffffff00;
@ -213,14 +211,14 @@ static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/* assume we want to r/w real data by default */
ioaddr += MEM_STNAND_DATA;
}
this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr;
this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr;
if (cmd != NAND_CMD_NONE) {
__raw_writeb(cmd, this->IO_ADDR_W);
__raw_writeb(cmd, this->legacy.IO_ADDR_W);
wmb();
}
}
static int au1200_nand_device_ready(struct mtd_info *mtd)
static int au1200_nand_device_ready(struct nand_chip *this)
{
return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}

View File

@ -19,8 +19,7 @@
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/platform_device.h>
#include <linux/smsc911x.h>
#include <linux/wm97xx.h>
@ -149,11 +148,10 @@ static void __init db1300_gpio_config(void)
/**********************************************************************/
static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void au1300_nand_cmd_ctrl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W;
ioaddr &= 0xffffff00;
@ -165,14 +163,14 @@ static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/* assume we want to r/w real data by default */
ioaddr += MEM_STNAND_DATA;
}
this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr;
this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr;
if (cmd != NAND_CMD_NONE) {
__raw_writeb(cmd, this->IO_ADDR_W);
__raw_writeb(cmd, this->legacy.IO_ADDR_W);
wmb();
}
}
static int au1300_nand_device_ready(struct mtd_info *mtd)
static int au1300_nand_device_ready(struct nand_chip *this)
{
return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}

View File

@ -13,8 +13,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
@ -126,11 +125,10 @@ static struct i2c_board_info db1550_i2c_devs[] __initdata = {
/**********************************************************************/
static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void au1550_nand_cmd_ctrl(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W;
ioaddr &= 0xffffff00;
@ -142,14 +140,14 @@ static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/* assume we want to r/w real data by default */
ioaddr += MEM_STNAND_DATA;
}
this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr;
this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr;
if (cmd != NAND_CMD_NONE) {
__raw_writeb(cmd, this->IO_ADDR_W);
__raw_writeb(cmd, this->legacy.IO_ADDR_W);
wmb();
}
}
static int au1550_nand_device_ready(struct mtd_info *mtd)
static int au1550_nand_device_ready(struct nand_chip *this)
{
return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}

View File

@ -19,8 +19,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlr/iomap.h>
@ -92,8 +91,8 @@ struct xlr_nand_flash_priv {
static struct xlr_nand_flash_priv nand_priv;
static void xlr_nand_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void xlr_nand_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
if (ctrl & NAND_CLE)
nlm_write_reg(nand_priv.flash_mmio,

View File

@ -30,8 +30,7 @@
#include <linux/resource.h>
#include <linux/serial.h>
#include <linux/serial_pnx8xxx.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
#include <irq.h>
#include <irq-mapping.h>
@ -178,10 +177,9 @@ static struct platform_device pnx833x_sata_device = {
};
static void
pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
pnx833x_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
unsigned long nandaddr = (unsigned long)this->legacy.IO_ADDR_W;
if (cmd == NAND_CMD_NONE)
return;

View File

@ -20,9 +20,8 @@
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
@ -141,14 +140,13 @@ static struct platform_device cf_slot0 = {
};
/* Resources and device for NAND */
static int rb532_dev_ready(struct mtd_info *mtd)
static int rb532_dev_ready(struct nand_chip *chip)
{
return gpio_get_value(GPIO_RDY);
}
static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void rb532_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
unsigned char orbits, nandbits;
if (ctrl & NAND_CTRL_CHANGE) {
@ -161,7 +159,7 @@ static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
set_latch_u5(orbits, nandbits);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
writeb(cmd, chip->legacy.IO_ADDR_W);
}
static struct resource nand_slot0_res[] = {

View File

@ -14,7 +14,7 @@
#include <linux/mmc/host.h>
#include <linux/mtd/physmap.h>
#include <linux/mfd/tmio.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/platnand.h>
#include <linux/i2c.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
@ -165,23 +165,21 @@ static struct mtd_partition migor_nand_flash_partitions[] = {
},
};
static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
static void migor_nand_flash_cmd_ctl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE)
writeb(cmd, chip->IO_ADDR_W + 0x00400000);
writeb(cmd, chip->legacy.IO_ADDR_W + 0x00400000);
else if (ctrl & NAND_ALE)
writeb(cmd, chip->IO_ADDR_W + 0x00800000);
writeb(cmd, chip->legacy.IO_ADDR_W + 0x00800000);
else
writeb(cmd, chip->IO_ADDR_W);
writeb(cmd, chip->legacy.IO_ADDR_W);
}
static int migor_nand_flash_ready(struct mtd_info *mtd)
static int migor_nand_flash_ready(struct nand_chip *chip)
{
return gpio_get_value(GPIO_PTA1); /* NAND_RBn */
}

View File

@ -90,7 +90,6 @@ static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(len, buf, 1));
size_t remaining = len;
int ret;
/* get transfer protocols. */
@ -101,22 +100,16 @@ static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
op.addr.nbytes = 0;
while (remaining) {
op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
ret = spi_mem_adjust_op_size(flash->spimem, &op);
if (ret)
return ret;
ret = spi_mem_adjust_op_size(flash->spimem, &op);
if (ret)
return ret;
op.data.nbytes = len < op.data.nbytes ? len : op.data.nbytes;
ret = spi_mem_exec_op(flash->spimem, &op);
if (ret)
return ret;
ret = spi_mem_exec_op(flash->spimem, &op);
if (ret)
return ret;
op.addr.val += op.data.nbytes;
remaining -= op.data.nbytes;
op.data.buf.out += op.data.nbytes;
}
return len;
return op.data.nbytes;
}
/*

View File

@ -14,6 +14,7 @@
*/
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@ -25,28 +26,24 @@
#include <linux/slab.h>
#include <linux/types.h>
#define pr_devinit(fmt, args...) \
({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
#define win_mask(x) ((BIT(x)) - 1)
#define DRIVER_NAME "gpio-addr-flash"
#define PFX DRIVER_NAME ": "
/**
* struct async_state - keep GPIO flash state
* @mtd: MTD state for this mapping
* @map: MTD map state for this flash
* @gpio_count: number of GPIOs used to address
* @gpio_addrs: array of GPIOs to twiddle
* @gpios: Struct containing the array of GPIO descriptors
* @gpio_values: cached GPIO values
* @win_size: dedicated memory size (if no GPIOs)
* @win_order: dedicated memory size (if no GPIOs)
*/
struct async_state {
struct mtd_info *mtd;
struct map_info map;
size_t gpio_count;
unsigned *gpio_addrs;
int *gpio_values;
unsigned long win_size;
struct gpio_descs *gpios;
unsigned int gpio_values;
unsigned int win_order;
};
#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1)
@ -57,21 +54,25 @@ struct async_state {
*
* Rather than call the GPIO framework every time, cache the last-programmed
* value. This speeds up sequential accesses (which are by far the most common
* type). We rely on the GPIO framework to treat non-zero value as high so
* that we don't have to normalize the bits.
* type).
*/
static void gf_set_gpios(struct async_state *state, unsigned long ofs)
{
size_t i = 0;
int value;
ofs /= state->win_size;
do {
value = ofs & (1 << i);
if (state->gpio_values[i] != value) {
gpio_set_value(state->gpio_addrs[i], value);
state->gpio_values[i] = value;
}
} while (++i < state->gpio_count);
int i;
ofs >>= state->win_order;
if (ofs == state->gpio_values)
return;
for (i = 0; i < state->gpios->ndescs; i++) {
if ((ofs & BIT(i)) == (state->gpio_values & BIT(i)))
continue;
gpiod_set_value(state->gpios->desc[i], !!(ofs & BIT(i)));
}
state->gpio_values = ofs;
}
/**
@ -87,7 +88,7 @@ static map_word gf_read(struct map_info *map, unsigned long ofs)
gf_set_gpios(state, ofs);
word = readw(map->virt + (ofs % state->win_size));
word = readw(map->virt + (ofs & win_mask(state->win_order)));
test.x[0] = word;
return test;
}
@ -109,14 +110,14 @@ static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssi
int this_len;
while (len) {
if ((from % state->win_size) + len > state->win_size)
this_len = state->win_size - (from % state->win_size);
else
this_len = len;
this_len = from & win_mask(state->win_order);
this_len = BIT(state->win_order) - this_len;
this_len = min_t(int, len, this_len);
gf_set_gpios(state, from);
memcpy_fromio(to, map->virt + (from % state->win_size),
this_len);
memcpy_fromio(to,
map->virt + (from & win_mask(state->win_order)),
this_len);
len -= this_len;
from += this_len;
to += this_len;
@ -136,7 +137,7 @@ static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
gf_set_gpios(state, ofs);
d = d1.x[0];
writew(d, map->virt + (ofs % state->win_size));
writew(d, map->virt + (ofs & win_mask(state->win_order)));
}
/**
@ -156,13 +157,13 @@ static void gf_copy_to(struct map_info *map, unsigned long to,
int this_len;
while (len) {
if ((to % state->win_size) + len > state->win_size)
this_len = state->win_size - (to % state->win_size);
else
this_len = len;
this_len = to & win_mask(state->win_order);
this_len = BIT(state->win_order) - this_len;
this_len = min_t(int, len, this_len);
gf_set_gpios(state, to);
memcpy_toio(map->virt + (to % state->win_size), from, len);
memcpy_toio(map->virt + (to & win_mask(state->win_order)),
from, len);
len -= this_len;
to += this_len;
@ -180,18 +181,22 @@ static const char * const part_probe_types[] = {
* The platform resource layout expected looks something like:
* struct mtd_partition partitions[] = { ... };
* struct physmap_flash_data flash_data = { ... };
* unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... };
* static struct gpiod_lookup_table addr_flash_gpios = {
* .dev_id = "gpio-addr-flash.0",
* .table = {
* GPIO_LOOKUP_IDX("gpio.0", 15, "addr", 0, GPIO_ACTIVE_HIGH),
* GPIO_LOOKUP_IDX("gpio.0", 16, "addr", 1, GPIO_ACTIVE_HIGH),
* );
* };
* gpiod_add_lookup_table(&addr_flash_gpios);
*
* struct resource flash_resource[] = {
* {
* .name = "cfi_probe",
* .start = 0x20000000,
* .end = 0x201fffff,
* .flags = IORESOURCE_MEM,
* }, {
* .start = (unsigned long)flash_gpios,
* .end = ARRAY_SIZE(flash_gpios),
* .flags = IORESOURCE_IRQ,
* }
* },
* };
* struct platform_device flash_device = {
* .name = "gpio-addr-flash",
@ -203,33 +208,25 @@ static const char * const part_probe_types[] = {
*/
static int gpio_flash_probe(struct platform_device *pdev)
{
size_t i, arr_size;
struct physmap_flash_data *pdata;
struct resource *memory;
struct resource *gpios;
struct async_state *state;
pdata = dev_get_platdata(&pdev->dev);
memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!memory || !gpios || !gpios->end)
if (!memory)
return -EINVAL;
arr_size = sizeof(int) * gpios->end;
state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL);
state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
/*
* We cast start/end to known types in the boards file, so cast
* away their pointer types here to the known types (gpios->xxx).
*/
state->gpio_count = gpios->end;
state->gpio_addrs = (void *)(unsigned long)gpios->start;
state->gpio_values = (void *)(state + 1);
state->win_size = resource_size(memory);
memset(state->gpio_values, 0xff, arr_size);
state->gpios = devm_gpiod_get_array(&pdev->dev, "addr", GPIOD_OUT_LOW);
if (IS_ERR(state->gpios))
return PTR_ERR(state->gpios);
state->win_order = get_bitmask_order(resource_size(memory)) - 1;
state->map.name = DRIVER_NAME;
state->map.read = gf_read;
@ -237,38 +234,21 @@ static int gpio_flash_probe(struct platform_device *pdev)
state->map.write = gf_write;
state->map.copy_to = gf_copy_to;
state->map.bankwidth = pdata->width;
state->map.size = state->win_size * (1 << state->gpio_count);
state->map.virt = ioremap_nocache(memory->start, state->map.size);
if (!state->map.virt)
return -ENOMEM;
state->map.size = BIT(state->win_order + state->gpios->ndescs);
state->map.virt = devm_ioremap_resource(&pdev->dev, memory);
if (IS_ERR(state->map.virt))
return PTR_ERR(state->map.virt);
state->map.phys = NO_XIP;
state->map.map_priv_1 = (unsigned long)state;
platform_set_drvdata(pdev, state);
i = 0;
do {
if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) {
pr_devinit(KERN_ERR PFX "failed to request gpio %d\n",
state->gpio_addrs[i]);
while (i--)
gpio_free(state->gpio_addrs[i]);
kfree(state);
return -EBUSY;
}
gpio_direction_output(state->gpio_addrs[i], 0);
} while (++i < state->gpio_count);
pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n",
state->map.bankwidth * 8);
dev_notice(&pdev->dev, "probing %d-bit flash bus\n",
state->map.bankwidth * 8);
state->mtd = do_map_probe(memory->name, &state->map);
if (!state->mtd) {
for (i = 0; i < state->gpio_count; ++i)
gpio_free(state->gpio_addrs[i]);
kfree(state);
if (!state->mtd)
return -ENXIO;
}
state->mtd->dev.parent = &pdev->dev;
mtd_device_parse_register(state->mtd, part_probe_types, NULL,
@ -280,13 +260,9 @@ static int gpio_flash_probe(struct platform_device *pdev)
static int gpio_flash_remove(struct platform_device *pdev)
{
struct async_state *state = platform_get_drvdata(pdev);
size_t i = 0;
do {
gpio_free(state->gpio_addrs[i]);
} while (++i < state->gpio_count);
mtd_device_unregister(state->mtd);
map_destroy(state->mtd);
kfree(state);
return 0;
}

View File

@ -31,7 +31,6 @@
struct of_flash_list {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
};
struct of_flash {
@ -56,18 +55,10 @@ static int of_flash_remove(struct platform_device *dev)
mtd_concat_destroy(info->cmtd);
}
for (i = 0; i < info->list_size; i++) {
for (i = 0; i < info->list_size; i++)
if (info->list[i].mtd)
map_destroy(info->list[i].mtd);
if (info->list[i].map.virt)
iounmap(info->list[i].map.virt);
if (info->list[i].res) {
release_resource(info->list[i].res);
kfree(info->list[i].res);
}
}
return 0;
}
@ -215,10 +206,11 @@ static int of_flash_probe(struct platform_device *dev)
err = -EBUSY;
res_size = resource_size(&res);
info->list[i].res = request_mem_region(res.start, res_size,
dev_name(&dev->dev));
if (!info->list[i].res)
info->list[i].map.virt = devm_ioremap_resource(&dev->dev, &res);
if (IS_ERR(info->list[i].map.virt)) {
err = PTR_ERR(info->list[i].map.virt);
goto err_out;
}
err = -ENXIO;
width = of_get_property(dp, "bank-width", NULL);
@ -246,15 +238,6 @@ static int of_flash_probe(struct platform_device *dev)
if (err)
goto err_out;
err = -ENOMEM;
info->list[i].map.virt = ioremap(info->list[i].map.phys,
info->list[i].map.size);
if (!info->list[i].map.virt) {
dev_err(&dev->dev, "Failed to ioremap() flash"
" region\n");
goto err_out;
}
simple_map_init(&info->list[i].map);
/*

View File

@ -44,11 +44,6 @@
#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */
static const struct of_device_id syscon_match[] = {
{ .compatible = "cortina,gemini-syscon" },
{ },
};
int of_flash_probe_gemini(struct platform_device *pdev,
struct device_node *np,
struct map_info *map)

View File

@ -227,26 +227,6 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
load time (assuming you build diskonchip as a module) with the module
parameter "inftl_bbt_write=1".
config MTD_NAND_DOCG4
tristate "Support for DiskOnChip G4"
depends on HAS_IOMEM
select BCH
select BITREVERSE
help
Support for diskonchip G4 nand flash, found in various smartphones and
PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba
Portege G900, Asus P526, and O2 XDA Zinc.
With this driver you will be able to use UBI and create a ubifs on the
device, so you may wish to consider enabling UBI and UBIFS as well.
These devices ship with the Mys/Sandisk SAFTL formatting, for which
there is currently no mtd parser, so you may want to use command line
partitioning to segregate write-protected blocks. On the Treo680, the
first five erase blocks (256KiB each) are write-protected, followed
by the block containing the saftl partition table. This is probably
typical.
config MTD_NAND_SHARPSL
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
depends on ARCH_PXA || COMPILE_TEST

View File

@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o
obj-$(CONFIG_MTD_NAND_TANGO) += tango_nand.o
obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o
obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
obj-$(CONFIG_MTD_NAND_DOCG4) += docg4.o
obj-$(CONFIG_MTD_NAND_FSMC) += fsmc_nand.o
obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o
obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
@ -58,8 +57,11 @@ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o
obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o
nand-objs := nand_base.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_jedec.o
nand-objs += nand_amd.o
nand-objs += nand_esmt.o
nand-objs += nand_hynix.o
nand-objs += nand_macronix.o
nand-objs += nand_micron.o

View File

@ -20,23 +20,33 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <mach/board-ams-delta.h>
#include <mach/hardware.h>
/*
* MTD structure for E3 (Delta)
*/
static struct mtd_info *ams_delta_mtd = NULL;
struct ams_delta_nand {
struct nand_chip nand_chip;
struct gpio_desc *gpiod_rdy;
struct gpio_desc *gpiod_nce;
struct gpio_desc *gpiod_nre;
struct gpio_desc *gpiod_nwp;
struct gpio_desc *gpiod_nwe;
struct gpio_desc *gpiod_ale;
struct gpio_desc *gpiod_cle;
void __iomem *io_base;
bool data_in;
};
/*
* Define partitions for flash devices
@ -63,48 +73,64 @@ static const struct mtd_partition partition_info[] = {
.size = 3 * SZ_256K },
};
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
static void ams_delta_io_write(struct ams_delta_nand *priv, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
writew(byte, priv->nand_chip.legacy.IO_ADDR_W);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
gpiod_set_value(priv->gpiod_nwe, 1);
}
static u_char ams_delta_read_byte(struct mtd_info *mtd)
static u_char ams_delta_io_read(struct ams_delta_nand *priv)
{
u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
res = readw(priv->nand_chip.legacy.IO_ADDR_R);
gpiod_set_value(priv->gpiod_nre, 1);
return res;
}
static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
static void ams_delta_dir_input(struct ams_delta_nand *priv, bool in)
{
int i;
for (i=0; i<len; i++)
ams_delta_write_byte(mtd, buf[i]);
writew(in ? ~0 : 0, priv->io_base + OMAP_MPUIO_IO_CNTL);
priv->data_in = in;
}
static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void ams_delta_write_buf(struct nand_chip *this, const u_char *buf,
int len)
{
struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
for (i=0; i<len; i++)
buf[i] = ams_delta_read_byte(mtd);
if (priv->data_in)
ams_delta_dir_input(priv, false);
for (i = 0; i < len; i++)
ams_delta_io_write(priv, buf[i]);
}
static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len)
{
struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
if (!priv->data_in)
ams_delta_dir_input(priv, true);
for (i = 0; i < len; i++)
buf[i] = ams_delta_io_read(priv);
}
static u_char ams_delta_read_byte(struct nand_chip *this)
{
u_char res;
ams_delta_read_buf(this, &res, 1);
return res;
}
/*
@ -115,67 +141,40 @@ static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
* NAND_CLE: bit 1 -> bit 7
* NAND_ALE: bit 2 -> bit 6
*/
static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
static void ams_delta_hwcontrol(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct ams_delta_nand *priv = nand_get_controller_data(this);
if (ctrl & NAND_CTRL_CHANGE) {
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
(ctrl & NAND_NCE) == 0);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
(ctrl & NAND_CLE) != 0);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
(ctrl & NAND_ALE) != 0);
gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
}
if (cmd != NAND_CMD_NONE)
ams_delta_write_byte(mtd, cmd);
if (cmd != NAND_CMD_NONE) {
u_char byte = cmd;
ams_delta_write_buf(this, &byte, 1);
}
}
static int ams_delta_nand_ready(struct mtd_info *mtd)
static int ams_delta_nand_ready(struct nand_chip *this)
{
return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
struct ams_delta_nand *priv = nand_get_controller_data(this);
return gpiod_get_value(priv->gpiod_rdy);
}
static const struct gpio _mandatory_gpio[] = {
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NCE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nce",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NRE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nre",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NWP,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nwp",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NWE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nwe",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_ALE,
.flags = GPIOF_OUT_INIT_LOW,
.label = "nand_ale",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_CLE,
.flags = GPIOF_OUT_INIT_LOW,
.label = "nand_cle",
},
};
/*
* Main initialization routine
*/
static int ams_delta_init(struct platform_device *pdev)
{
struct ams_delta_nand *priv;
struct nand_chip *this;
struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
int err = 0;
@ -184,15 +183,16 @@ static int ams_delta_init(struct platform_device *pdev)
return -ENXIO;
/* Allocate memory for MTD device structure and private data */
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
if (!this) {
priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand),
GFP_KERNEL);
if (!priv) {
pr_warn("Unable to allocate E3 NAND MTD device structure.\n");
err = -ENOMEM;
goto out;
return -ENOMEM;
}
this = &priv->nand_chip;
ams_delta_mtd = nand_to_mtd(this);
ams_delta_mtd->owner = THIS_MODULE;
mtd = nand_to_mtd(this);
mtd->dev.parent = &pdev->dev;
/*
* Don't try to request the memory region from here,
@ -207,51 +207,93 @@ static int ams_delta_init(struct platform_device *pdev)
goto out_free;
}
nand_set_controller_data(this, (void *)io_base);
priv->io_base = io_base;
nand_set_controller_data(this, priv);
/* Set address of NAND IO lines */
this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
this->read_byte = ams_delta_read_byte;
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf;
this->cmd_ctrl = ams_delta_hwcontrol;
if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
this->dev_ready = ams_delta_nand_ready;
} else {
this->dev_ready = NULL;
pr_notice("Couldn't request gpio for Delta NAND ready.\n");
this->legacy.IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
this->legacy.IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
this->legacy.read_byte = ams_delta_read_byte;
this->legacy.write_buf = ams_delta_write_buf;
this->legacy.read_buf = ams_delta_read_buf;
this->legacy.cmd_ctrl = ams_delta_hwcontrol;
priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
if (IS_ERR(priv->gpiod_rdy)) {
err = PTR_ERR(priv->gpiod_rdy);
dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err);
goto out_mtd;
}
if (priv->gpiod_rdy)
this->legacy.dev_ready = ams_delta_nand_ready;
/* 25 us command delay time */
this->chip_delay = 30;
this->legacy.chip_delay = 30;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
platform_set_drvdata(pdev, io_base);
platform_set_drvdata(pdev, priv);
/* Set chip enabled, but */
err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
if (err)
goto out_gpio;
priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH);
if (IS_ERR(priv->gpiod_nwp)) {
err = PTR_ERR(priv->gpiod_nwp);
dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err);
goto out_mtd;
}
priv->gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH);
if (IS_ERR(priv->gpiod_nce)) {
err = PTR_ERR(priv->gpiod_nce);
dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err);
goto out_mtd;
}
priv->gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH);
if (IS_ERR(priv->gpiod_nre)) {
err = PTR_ERR(priv->gpiod_nre);
dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err);
goto out_mtd;
}
priv->gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH);
if (IS_ERR(priv->gpiod_nwe)) {
err = PTR_ERR(priv->gpiod_nwe);
dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err);
goto out_mtd;
}
priv->gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW);
if (IS_ERR(priv->gpiod_ale)) {
err = PTR_ERR(priv->gpiod_ale);
dev_err(&pdev->dev, "ALE GPIO request failed (%d)\n", err);
goto out_mtd;
}
priv->gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW);
if (IS_ERR(priv->gpiod_cle)) {
err = PTR_ERR(priv->gpiod_cle);
dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
goto out_mtd;
}
/* Initialize data port direction to a known state */
ams_delta_dir_input(priv, true);
/* Scan to find existence of the device */
err = nand_scan(ams_delta_mtd, 1);
err = nand_scan(this, 1);
if (err)
goto out_mtd;
/* Register the partitions */
mtd_device_register(ams_delta_mtd, partition_info,
ARRAY_SIZE(partition_info));
mtd_device_register(mtd, partition_info, ARRAY_SIZE(partition_info));
goto out;
out_mtd:
gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
out_gpio:
gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
out_free:
kfree(this);
out:
return err;
}
@ -261,18 +303,15 @@ out_free:
*/
static int ams_delta_cleanup(struct platform_device *pdev)
{
void __iomem *io_base = platform_get_drvdata(pdev);
struct ams_delta_nand *priv = platform_get_drvdata(pdev);
struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip);
void __iomem *io_base = priv->io_base;
/* Release resources, unregister device */
nand_release(ams_delta_mtd);
nand_release(mtd_to_nand(mtd));
gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
/* Free the MTD device structure */
kfree(mtd_to_nand(ams_delta_mtd));
return 0;
}

View File

@ -410,25 +410,15 @@ err:
return -EIO;
}
static u8 atmel_nand_read_byte(struct mtd_info *mtd)
static u8 atmel_nand_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
return ioread8(nand->activecs->io.virt);
}
static u16 atmel_nand_read_word(struct mtd_info *mtd)
static void atmel_nand_write_byte(struct nand_chip *chip, u8 byte)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
return ioread16(nand->activecs->io.virt);
}
static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
if (chip->options & NAND_BUSWIDTH_16)
@ -437,9 +427,8 @@ static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
iowrite8(byte, nand->activecs->io.virt);
}
static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void atmel_nand_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_nand_controller *nc;
@ -462,9 +451,8 @@ static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
ioread8_rep(nand->activecs->io.virt, buf, len);
}
static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void atmel_nand_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_nand_controller *nc;
@ -487,34 +475,31 @@ static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
iowrite8_rep(nand->activecs->io.virt, buf, len);
}
static int atmel_nand_dev_ready(struct mtd_info *mtd)
static int atmel_nand_dev_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
return gpiod_get_value(nand->activecs->rb.gpio);
}
static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
static void atmel_nand_select_chip(struct nand_chip *chip, int cs)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
if (cs < 0 || cs >= nand->numcs) {
nand->activecs = NULL;
chip->dev_ready = NULL;
chip->legacy.dev_ready = NULL;
return;
}
nand->activecs = &nand->cs[cs];
if (nand->activecs->rb.type == ATMEL_NAND_GPIO_RB)
chip->dev_ready = atmel_nand_dev_ready;
chip->legacy.dev_ready = atmel_nand_dev_ready;
}
static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
static int atmel_hsmc_nand_dev_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_hsmc_nand_controller *nc;
u32 status;
@ -526,15 +511,15 @@ static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
return status & ATMEL_HSMC_NFC_SR_RBEDGE(nand->activecs->rb.id);
}
static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
static void atmel_hsmc_nand_select_chip(struct nand_chip *chip, int cs)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_hsmc_nand_controller *nc;
nc = to_hsmc_nand_controller(chip->controller);
atmel_nand_select_chip(mtd, cs);
atmel_nand_select_chip(chip, cs);
if (!nand->activecs) {
regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL,
@ -543,7 +528,7 @@ static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
}
if (nand->activecs->rb.type == ATMEL_NAND_NATIVE_RB)
chip->dev_ready = atmel_hsmc_nand_dev_ready;
chip->legacy.dev_ready = atmel_hsmc_nand_dev_ready;
regmap_update_bits(nc->base.smc, ATMEL_HSMC_NFC_CFG,
ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK |
@ -607,10 +592,9 @@ static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
return ret;
}
static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
static void atmel_hsmc_nand_cmd_ctrl(struct nand_chip *chip, int dat,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_hsmc_nand_controller *nc;
@ -634,10 +618,9 @@ static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
}
}
static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void atmel_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_nand_controller *nc;
@ -851,7 +834,7 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
if (ret)
return ret;
atmel_nand_write_buf(mtd, buf, mtd->writesize);
atmel_nand_write_buf(chip, buf, mtd->writesize);
ret = atmel_nand_pmecc_generate_eccbytes(chip, raw);
if (ret) {
@ -861,20 +844,18 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
atmel_nand_pmecc_disable(chip, raw);
atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
atmel_nand_write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip, const u8 *buf,
static int atmel_nand_pmecc_write_page(struct nand_chip *chip, const u8 *buf,
int oob_required, int page)
{
return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, false);
}
static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int atmel_nand_pmecc_write_page_raw(struct nand_chip *chip,
const u8 *buf, int oob_required,
int page)
{
@ -893,8 +874,8 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
if (ret)
return ret;
atmel_nand_read_buf(mtd, buf, mtd->writesize);
atmel_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
atmel_nand_read_buf(chip, buf, mtd->writesize);
atmel_nand_read_buf(chip, chip->oob_poi, mtd->oobsize);
ret = atmel_nand_pmecc_correct_data(chip, buf, raw);
@ -903,15 +884,13 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
return ret;
}
static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int atmel_nand_pmecc_read_page(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, false);
}
static int atmel_nand_pmecc_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int atmel_nand_pmecc_read_page_raw(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, true);
@ -956,7 +935,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
if (ret)
return ret;
atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
atmel_nand_write_buf(chip, chip->oob_poi, mtd->oobsize);
nc->op.cmds[0] = NAND_CMD_PAGEPROG;
nc->op.ncmds = 1;
@ -966,15 +945,14 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
dev_err(nc->base.dev, "Failed to program NAND page (err = %d)\n",
ret);
status = chip->waitfunc(mtd, chip);
status = chip->legacy.waitfunc(chip);
if (status & NAND_STATUS_FAIL)
return -EIO;
return ret;
}
static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
static int atmel_hsmc_nand_pmecc_write_page(struct nand_chip *chip,
const u8 *buf, int oob_required,
int page)
{
@ -982,8 +960,7 @@ static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd,
false);
}
static int atmel_hsmc_nand_pmecc_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int atmel_hsmc_nand_pmecc_write_page_raw(struct nand_chip *chip,
const u8 *buf,
int oob_required, int page)
{
@ -1045,16 +1022,14 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
return ret;
}
static int atmel_hsmc_nand_pmecc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int atmel_hsmc_nand_pmecc_read_page(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page,
false);
}
static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip,
u8 *buf, int oob_required,
int page)
{
@ -1473,10 +1448,9 @@ static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand,
return 0;
}
static int atmel_nand_setup_data_interface(struct mtd_info *mtd, int csline,
static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct atmel_nand *nand = to_atmel_nand(chip);
struct atmel_nand_controller *nc;
@ -1498,19 +1472,18 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
mtd->dev.parent = nc->dev;
nand->base.controller = &nc->base;
chip->cmd_ctrl = atmel_nand_cmd_ctrl;
chip->read_byte = atmel_nand_read_byte;
chip->read_word = atmel_nand_read_word;
chip->write_byte = atmel_nand_write_byte;
chip->read_buf = atmel_nand_read_buf;
chip->write_buf = atmel_nand_write_buf;
chip->legacy.cmd_ctrl = atmel_nand_cmd_ctrl;
chip->legacy.read_byte = atmel_nand_read_byte;
chip->legacy.write_byte = atmel_nand_write_byte;
chip->legacy.read_buf = atmel_nand_read_buf;
chip->legacy.write_buf = atmel_nand_write_buf;
chip->select_chip = atmel_nand_select_chip;
if (nc->mck && nc->caps->ops->setup_data_interface)
chip->setup_data_interface = atmel_nand_setup_data_interface;
/* Some NANDs require a longer delay than the default one (20us). */
chip->chip_delay = 40;
chip->legacy.chip_delay = 40;
/*
* Use a bounce buffer when the buffer passed by the MTD user is not
@ -1551,7 +1524,7 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
atmel_nand_init(nc, nand);
/* Overload some methods for the HSMC controller. */
chip->cmd_ctrl = atmel_hsmc_nand_cmd_ctrl;
chip->legacy.cmd_ctrl = atmel_hsmc_nand_cmd_ctrl;
chip->select_chip = atmel_hsmc_nand_select_chip;
}
@ -1586,9 +1559,7 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
return ERR_PTR(-EINVAL);
}
nand = devm_kzalloc(nc->dev,
sizeof(*nand) + (numcs * sizeof(*nand->cs)),
GFP_KERNEL);
nand = devm_kzalloc(nc->dev, struct_size(nand, cs, numcs), GFP_KERNEL);
if (!nand) {
dev_err(nc->dev, "Failed to allocate NAND object\n");
return ERR_PTR(-ENOMEM);
@ -1694,7 +1665,7 @@ atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
nc->caps->ops->nand_init(nc, nand);
ret = nand_scan(mtd, nand->numcs);
ret = nand_scan(chip, nand->numcs);
if (ret) {
dev_err(nc->dev, "NAND scan failed: %d\n", ret);
return ret;
@ -2063,6 +2034,10 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
nand_np = dev->of_node;
nfc_np = of_find_compatible_node(dev->of_node, NULL,
"atmel,sama5d3-nfc");
if (!nfc_np) {
dev_err(dev, "Could not find device node for sama5d3-nfc\n");
return -ENODEV;
}
nc->clk = of_clk_get(nfc_np, 0);
if (IS_ERR(nc->clk)) {

View File

@ -24,134 +24,113 @@ struct au1550nd_ctx {
int cs;
void __iomem *base;
void (*write_byte)(struct mtd_info *, u_char);
void (*write_byte)(struct nand_chip *, u_char);
};
/**
* au_read_byte - read one byte from the chip
* @mtd: MTD device structure
* @this: NAND chip object
*
* read function for 8bit buswidth
*/
static u_char au_read_byte(struct mtd_info *mtd)
static u_char au_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
u_char ret = readb(this->IO_ADDR_R);
u_char ret = readb(this->legacy.IO_ADDR_R);
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_byte - write one byte to the chip
* @mtd: MTD device structure
* @this: NAND chip object
* @byte: pointer to data byte to write
*
* write function for 8it buswidth
*/
static void au_write_byte(struct mtd_info *mtd, u_char byte)
static void au_write_byte(struct nand_chip *this, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
writeb(byte, this->IO_ADDR_W);
writeb(byte, this->legacy.IO_ADDR_W);
wmb(); /* drain writebuffer */
}
/**
* au_read_byte16 - read one byte endianness aware from the chip
* @mtd: MTD device structure
* @this: NAND chip object
*
* read function for 16bit buswidth with endianness conversion
*/
static u_char au_read_byte16(struct mtd_info *mtd)
static u_char au_read_byte16(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
u_char ret = (u_char) cpu_to_le16(readw(this->legacy.IO_ADDR_R));
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_byte16 - write one byte endianness aware to the chip
* @mtd: MTD device structure
* @this: NAND chip object
* @byte: pointer to data byte to write
*
* write function for 16bit buswidth with endianness conversion
*/
static void au_write_byte16(struct mtd_info *mtd, u_char byte)
static void au_write_byte16(struct nand_chip *this, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
writew(le16_to_cpu((u16) byte), this->legacy.IO_ADDR_W);
wmb(); /* drain writebuffer */
}
/**
* au_read_word - read one word from the chip
* @mtd: MTD device structure
*
* read function for 16bit buswidth without endianness conversion
*/
static u16 au_read_word(struct mtd_info *mtd)
{
struct nand_chip *this = mtd_to_nand(mtd);
u16 ret = readw(this->IO_ADDR_R);
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_buf - write buffer to chip
* @mtd: MTD device structure
* @this: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*
* write function for 8bit buswidth
*/
static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void au_write_buf(struct nand_chip *this, const u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
for (i = 0; i < len; i++) {
writeb(buf[i], this->IO_ADDR_W);
writeb(buf[i], this->legacy.IO_ADDR_W);
wmb(); /* drain writebuffer */
}
}
/**
* au_read_buf - read chip data into buffer
* @mtd: MTD device structure
* @this: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*
* read function for 8bit buswidth
*/
static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void au_read_buf(struct nand_chip *this, u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
for (i = 0; i < len; i++) {
buf[i] = readb(this->IO_ADDR_R);
buf[i] = readb(this->legacy.IO_ADDR_R);
wmb(); /* drain writebuffer */
}
}
/**
* au_write_buf16 - write buffer to chip
* @mtd: MTD device structure
* @this: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*
* write function for 16bit buswidth
*/
static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
static void au_write_buf16(struct nand_chip *this, const u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
u16 *p = (u16 *) buf;
len >>= 1;
for (i = 0; i < len; i++) {
writew(p[i], this->IO_ADDR_W);
writew(p[i], this->legacy.IO_ADDR_W);
wmb(); /* drain writebuffer */
}
@ -173,7 +152,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
len >>= 1;
for (i = 0; i < len; i++) {
p[i] = readw(this->IO_ADDR_R);
p[i] = readw(this->legacy.IO_ADDR_R);
wmb(); /* drain writebuffer */
}
}
@ -200,19 +179,19 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
switch (cmd) {
case NAND_CTL_SETCLE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
break;
case NAND_CTL_CLRCLE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
break;
case NAND_CTL_SETALE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
break;
case NAND_CTL_CLRALE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
/* FIXME: Nobody knows why this is necessary,
* but it works only that way */
udelay(1);
@ -229,12 +208,12 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
break;
}
this->IO_ADDR_R = this->IO_ADDR_W;
this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W;
wmb(); /* Drain the writebuffer */
}
int au1550_device_ready(struct mtd_info *mtd)
int au1550_device_ready(struct nand_chip *this)
{
return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
}
@ -248,23 +227,24 @@ int au1550_device_ready(struct mtd_info *mtd)
* chip needs it to be asserted during chip not ready time but the NAND
* controller keeps it released.
*
* @mtd: MTD device structure
* @this: NAND chip object
* @chip: chipnumber to select, -1 for deselect
*/
static void au1550_select_chip(struct mtd_info *mtd, int chip)
static void au1550_select_chip(struct nand_chip *this, int chip)
{
}
/**
* au1550_command - Send command to NAND device
* @mtd: MTD device structure
* @this: NAND chip object
* @command: the command to be sent
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*/
static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
static void au1550_command(struct nand_chip *this, unsigned command,
int column, int page_addr)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(this);
struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
chip);
int ce_override = 0, i;
@ -289,9 +269,9 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
column -= 256;
readcmd = NAND_CMD_READ1;
}
ctx->write_byte(mtd, readcmd);
ctx->write_byte(this, readcmd);
}
ctx->write_byte(mtd, command);
ctx->write_byte(this, command);
/* Set ALE and clear CLE to start address cycle */
au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
@ -305,10 +285,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
if (this->options & NAND_BUSWIDTH_16 &&
!nand_opcode_8bits(command))
column >>= 1;
ctx->write_byte(mtd, column);
ctx->write_byte(this, column);
}
if (page_addr != -1) {
ctx->write_byte(mtd, (u8)(page_addr & 0xff));
ctx->write_byte(this, (u8)(page_addr & 0xff));
if (command == NAND_CMD_READ0 ||
command == NAND_CMD_READ1 ||
@ -326,10 +306,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
}
ctx->write_byte(mtd, (u8)(page_addr >> 8));
ctx->write_byte(this, (u8)(page_addr >> 8));
if (this->options & NAND_ROW_ADDR_3)
ctx->write_byte(mtd,
ctx->write_byte(this,
((page_addr >> 16) & 0x0f));
}
/* Latch in address */
@ -362,7 +342,8 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
/* Apply a short delay always to ensure that we do wait tWB. */
ndelay(100);
/* Wait for a chip to become ready... */
for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
for (i = this->legacy.chip_delay;
!this->legacy.dev_ready(this) && i > 0; --i)
udelay(1);
/* Release -CE and re-enable interrupts. */
@ -373,7 +354,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
/* Apply this short delay always to ensure that we do wait tWB. */
ndelay(100);
while(!this->dev_ready(mtd));
while(!this->legacy.dev_ready(this));
}
static int find_nand_cs(unsigned long nand_base)
@ -448,25 +429,24 @@ static int au1550nd_probe(struct platform_device *pdev)
}
ctx->cs = cs;
this->dev_ready = au1550_device_ready;
this->legacy.dev_ready = au1550_device_ready;
this->select_chip = au1550_select_chip;
this->cmdfunc = au1550_command;
this->legacy.cmdfunc = au1550_command;
/* 30 us command delay time */
this->chip_delay = 30;
this->legacy.chip_delay = 30;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
if (pd->devwidth)
this->options |= NAND_BUSWIDTH_16;
this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
this->legacy.read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte;
this->read_word = au_read_word;
this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
this->legacy.write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
this->legacy.read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
ret = nand_scan(mtd, 1);
ret = nand_scan(this, 1);
if (ret) {
dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
goto out3;
@ -492,7 +472,7 @@ static int au1550nd_remove(struct platform_device *pdev)
struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
nand_release(nand_to_mtd(&ctx->chip));
nand_release(&ctx->chip);
iounmap(ctx->base);
release_mem_region(r->start, 0x1000);
kfree(ctx);

View File

@ -65,7 +65,7 @@ static int bcm47xxnflash_remove(struct platform_device *pdev)
{
struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&nflash->nand_chip));
nand_release(&nflash->nand_chip);
return 0;
}

View File

@ -170,10 +170,9 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
* NAND chip ops
**************************************************/
static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct nand_chip *nand_chip,
int cmd, unsigned int ctrl)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
u32 code = 0;
@ -191,15 +190,14 @@ static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
}
/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
int chip)
static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip,
int cs)
{
return;
}
static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
@ -212,11 +210,11 @@ static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
* registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
* standard commands would be much more complicated.
*/
static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip *nand_chip,
unsigned command, int column,
int page_addr)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand_chip);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
struct bcma_drv_cc *cc = b47n->cc;
u32 ctlcode;
@ -229,10 +227,10 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
switch (command) {
case NAND_CMD_RESET:
nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE);
nand_chip->legacy.cmd_ctrl(nand_chip, command, NAND_CTRL_CLE);
ndelay(100);
nand_wait_ready(mtd);
nand_wait_ready(nand_chip);
break;
case NAND_CMD_READID:
ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
@ -310,9 +308,9 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
b47n->curr_command = command;
}
static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip *nand_chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand_chip);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
struct bcma_drv_cc *cc = b47n->cc;
u32 tmp = 0;
@ -338,31 +336,31 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
return 0;
}
static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip,
uint8_t *buf, int len)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
switch (b47n->curr_command) {
case NAND_CMD_READ0:
case NAND_CMD_READOOB:
bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
bcm47xxnflash_ops_bcm4706_read(nand_to_mtd(nand_chip), buf,
len);
return;
}
pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
}
static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip,
const uint8_t *buf, int len)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
switch (b47n->curr_command) {
case NAND_CMD_SEQIN:
bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf,
len);
return;
}
@ -386,16 +384,16 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
u32 val;
b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
b47n->nand_chip.set_features = nand_get_set_features_notsupp;
b47n->nand_chip.get_features = nand_get_set_features_notsupp;
nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
nand_chip->legacy.dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp;
b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp;
nand_chip->chip_delay = 50;
nand_chip->legacy.chip_delay = 50;
b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
@ -423,7 +421,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
/* Scan NAND */
err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
err = nand_scan(&b47n->nand_chip, 1);
if (err) {
pr_err("Could not scan NAND flash: %d\n", err);
goto exit;

View File

@ -1231,15 +1231,14 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
* NAND MTD API: read/program/erase
***********************************************************************/
static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat,
unsigned int ctrl)
static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat,
unsigned int ctrl)
{
/* intentionally left blank */
}
static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
static int brcmnand_waitfunc(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_controller *ctrl = host->ctrl;
unsigned long timeo = msecs_to_jiffies(100);
@ -1274,7 +1273,6 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
enum brcmnand_llop_type type, u32 data,
bool last_op)
{
struct mtd_info *mtd = nand_to_mtd(&host->chip);
struct nand_chip *chip = &host->chip;
struct brcmnand_controller *ctrl = host->ctrl;
u32 tmp;
@ -1307,13 +1305,13 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
(void)brcmnand_read_reg(ctrl, BRCMNAND_LL_OP);
brcmnand_send_cmd(host, CMD_LOW_LEVEL_OP);
return brcmnand_waitfunc(mtd, chip);
return brcmnand_waitfunc(chip);
}
static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command,
int column, int page_addr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_controller *ctrl = host->ctrl;
u64 addr = (u64)page_addr << chip->page_shift;
@ -1383,7 +1381,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
brcmnand_send_cmd(host, native_cmd);
brcmnand_waitfunc(mtd, chip);
brcmnand_waitfunc(chip);
if (native_cmd == CMD_PARAMETER_READ ||
native_cmd == CMD_PARAMETER_CHANGE_COL) {
@ -1417,9 +1415,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
brcmnand_wp(mtd, 1);
}
static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
static uint8_t brcmnand_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_controller *ctrl = host->ctrl;
uint8_t ret = 0;
@ -1474,19 +1471,18 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
return ret;
}
static void brcmnand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void brcmnand_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++, buf++)
*buf = brcmnand_read_byte(mtd);
*buf = brcmnand_read_byte(chip);
}
static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
int len)
static void brcmnand_write_buf(struct nand_chip *chip, const uint8_t *buf,
int len)
{
int i;
struct nand_chip *chip = mtd_to_nand(mtd);
struct brcmnand_host *host = nand_get_controller_data(chip);
switch (host->last_cmd) {
@ -1617,7 +1613,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
brcmnand_send_cmd(host, CMD_PAGE_READ);
brcmnand_waitfunc(mtd, chip);
brcmnand_waitfunc(chip);
if (likely(buf)) {
brcmnand_soc_data_bus_prepare(ctrl->soc, false);
@ -1689,7 +1685,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
sas = mtd->oobsize / chip->ecc.steps;
/* read without ecc for verification */
ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
ret = chip->ecc.read_page_raw(chip, buf, true, page);
if (ret)
return ret;
@ -1786,9 +1782,10 @@ try_dmaread:
return 0;
}
static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int brcmnand_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
@ -1798,10 +1795,11 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
mtd->writesize >> FC_SHIFT, (u32 *)buf, oob);
}
static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int brcmnand_read_page_raw(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct brcmnand_host *host = nand_get_controller_data(chip);
struct mtd_info *mtd = nand_to_mtd(chip);
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
int ret;
@ -1814,17 +1812,18 @@ static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return ret;
}
static int brcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int brcmnand_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return brcmnand_read(mtd, chip, (u64)page << chip->page_shift,
mtd->writesize >> FC_SHIFT,
NULL, (u8 *)chip->oob_poi);
}
static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int brcmnand_read_oob_raw(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
brcmnand_set_ecc_enabled(host, 0);
@ -1892,7 +1891,7 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
/* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */
brcmnand_send_cmd(host, CMD_PROGRAM_PAGE);
status = brcmnand_waitfunc(mtd, chip);
status = brcmnand_waitfunc(chip);
if (status & NAND_STATUS_FAIL) {
dev_info(ctrl->dev, "program failed at %llx\n",
@ -1906,9 +1905,10 @@ out:
return ret;
}
static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int brcmnand_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
void *oob = oob_required ? chip->oob_poi : NULL;
@ -1918,10 +1918,10 @@ static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
return nand_prog_page_end_op(chip);
}
static int brcmnand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf,
static int brcmnand_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
void *oob = oob_required ? chip->oob_poi : NULL;
@ -1933,16 +1933,16 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd,
return nand_prog_page_end_op(chip);
}
static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int brcmnand_write_oob(struct nand_chip *chip, int page)
{
return brcmnand_write(mtd, chip, (u64)page << chip->page_shift,
NULL, chip->oob_poi);
return brcmnand_write(nand_to_mtd(chip), chip,
(u64)page << chip->page_shift, NULL,
chip->oob_poi);
}
static int brcmnand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int brcmnand_write_oob_raw(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct brcmnand_host *host = nand_get_controller_data(chip);
int ret;
@ -2270,15 +2270,12 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
mtd->owner = THIS_MODULE;
mtd->dev.parent = &pdev->dev;
chip->IO_ADDR_R = (void __iomem *)0xdeadbeef;
chip->IO_ADDR_W = (void __iomem *)0xdeadbeef;
chip->cmd_ctrl = brcmnand_cmd_ctrl;
chip->cmdfunc = brcmnand_cmdfunc;
chip->waitfunc = brcmnand_waitfunc;
chip->read_byte = brcmnand_read_byte;
chip->read_buf = brcmnand_read_buf;
chip->write_buf = brcmnand_write_buf;
chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl;
chip->legacy.cmdfunc = brcmnand_cmdfunc;
chip->legacy.waitfunc = brcmnand_waitfunc;
chip->legacy.read_byte = brcmnand_read_byte;
chip->legacy.read_buf = brcmnand_read_buf;
chip->legacy.write_buf = brcmnand_write_buf;
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.read_page = brcmnand_read_page;
@ -2301,7 +2298,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
nand_writereg(ctrl, cfg_offs,
nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
return ret;
@ -2616,7 +2613,7 @@ int brcmnand_remove(struct platform_device *pdev)
struct brcmnand_host *host;
list_for_each_entry(host, &ctrl->host_list, node)
nand_release(nand_to_mtd(&host->chip));
nand_release(&host->chip);
clk_disable_unprepare(ctrl->clk);

View File

@ -100,9 +100,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
#define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr)
#define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr)
static int cafe_device_ready(struct mtd_info *mtd)
static int cafe_device_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
@ -117,9 +116,8 @@ static int cafe_device_ready(struct mtd_info *mtd)
}
static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
if (cafe->usedma)
@ -133,9 +131,8 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
len, cafe->datalen);
}
static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
if (cafe->usedma)
@ -148,22 +145,21 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
cafe->datalen += len;
}
static uint8_t cafe_read_byte(struct mtd_info *mtd)
static uint8_t cafe_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
uint8_t d;
cafe_read_buf(mtd, &d, 1);
cafe_read_buf(chip, &d, 1);
cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
return d;
}
static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
int column, int page_addr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct cafe_priv *cafe = nand_get_controller_data(chip);
int adrbytes = 0;
uint32_t ctl1;
@ -313,13 +309,12 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
return;
}
nand_wait_ready(mtd);
nand_wait_ready(chip);
cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
}
static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
static void cafe_select_chip(struct nand_chip *chip, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct cafe_priv *cafe = nand_get_controller_data(chip);
cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
@ -346,17 +341,19 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id)
return IRQ_HANDLED;
}
static int cafe_nand_write_oob(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int cafe_nand_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
mtd->oobsize);
}
/* Don't use -- use nand_read_oob_std for now */
static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int cafe_nand_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
}
/**
@ -369,9 +366,10 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
* The hw generator calculates the error syndrome automatically. Therefore
* we need a special oob layout and handling.
*/
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct cafe_priv *cafe = nand_get_controller_data(chip);
unsigned int max_bitflips = 0;
@ -380,7 +378,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
cafe_readl(cafe, NAND_ECC_SYN01));
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
unsigned short syn[8], pat[4];
@ -531,15 +529,15 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
};
static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
static int cafe_nand_write_page_lowlevel(struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct cafe_priv *cafe = nand_get_controller_data(chip);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
/* Set up ECC autogeneration */
cafe->ctl2 |= (1<<30);
@ -547,7 +545,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
return nand_prog_page_end_op(chip);
}
static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
static int cafe_nand_block_bad(struct nand_chip *chip, loff_t ofs)
{
return 0;
}
@ -705,23 +703,23 @@ static int cafe_nand_probe(struct pci_dev *pdev,
goto out_ior;
}
cafe->nand.cmdfunc = cafe_nand_cmdfunc;
cafe->nand.dev_ready = cafe_device_ready;
cafe->nand.read_byte = cafe_read_byte;
cafe->nand.read_buf = cafe_read_buf;
cafe->nand.write_buf = cafe_write_buf;
cafe->nand.legacy.cmdfunc = cafe_nand_cmdfunc;
cafe->nand.legacy.dev_ready = cafe_device_ready;
cafe->nand.legacy.read_byte = cafe_read_byte;
cafe->nand.legacy.read_buf = cafe_read_buf;
cafe->nand.legacy.write_buf = cafe_write_buf;
cafe->nand.select_chip = cafe_select_chip;
cafe->nand.set_features = nand_get_set_features_notsupp;
cafe->nand.get_features = nand_get_set_features_notsupp;
cafe->nand.legacy.set_features = nand_get_set_features_notsupp;
cafe->nand.legacy.get_features = nand_get_set_features_notsupp;
cafe->nand.chip_delay = 0;
cafe->nand.legacy.chip_delay = 0;
/* Enable the following for a flash based bad block table */
cafe->nand.bbt_options = NAND_BBT_USE_FLASH;
if (skipbbt) {
cafe->nand.options |= NAND_SKIP_BBTSCAN;
cafe->nand.block_bad = cafe_nand_block_bad;
cafe->nand.legacy.block_bad = cafe_nand_block_bad;
}
if (numtimings && numtimings != 3) {
@ -783,7 +781,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
/* Scan to find existence of the device */
cafe->nand.dummy_controller.ops = &cafe_nand_controller_ops;
err = nand_scan(mtd, 2);
err = nand_scan(&cafe->nand, 2);
if (err)
goto out_irq;
@ -819,7 +817,7 @@ static void cafe_nand_remove(struct pci_dev *pdev)
/* Disable NAND IRQ in global IRQ mask register */
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
free_irq(pdev->irq, mtd);
nand_release(mtd);
nand_release(chip);
free_rs(cafe->rs);
pci_iounmap(pdev, cafe->mmio);
dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);

View File

@ -49,29 +49,26 @@ static const struct mtd_partition partition_info[] = {
};
#define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
static u_char cmx270_read_byte(struct mtd_info *mtd)
static u_char cmx270_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
return (readl(this->IO_ADDR_R) >> 16);
return (readl(this->legacy.IO_ADDR_R) >> 16);
}
static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void cmx270_write_buf(struct nand_chip *this, const u_char *buf,
int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
for (i=0; i<len; i++)
writel((*buf++ << 16), this->IO_ADDR_W);
writel((*buf++ << 16), this->legacy.IO_ADDR_W);
}
static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void cmx270_read_buf(struct nand_chip *this, u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
for (i=0; i<len; i++)
*buf++ = readl(this->IO_ADDR_R) >> 16;
*buf++ = readl(this->legacy.IO_ADDR_R) >> 16;
}
static inline void nand_cs_on(void)
@ -89,11 +86,10 @@ static void nand_cs_off(void)
/*
* hardware specific access to control-lines
*/
static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
static void cmx270_hwcontrol(struct nand_chip *this, int dat,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
unsigned int nandaddr = (unsigned int)this->legacy.IO_ADDR_W;
dsb();
@ -113,9 +109,9 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
}
dsb();
this->IO_ADDR_W = (void __iomem*)nandaddr;
this->legacy.IO_ADDR_W = (void __iomem*)nandaddr;
if (dat != NAND_CMD_NONE)
writel((dat << 16), this->IO_ADDR_W);
writel((dat << 16), this->legacy.IO_ADDR_W);
dsb();
}
@ -123,7 +119,7 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
/*
* read device ready pin
*/
static int cmx270_device_ready(struct mtd_info *mtd)
static int cmx270_device_ready(struct nand_chip *this)
{
dsb();
@ -177,23 +173,23 @@ static int __init cmx270_init(void)
cmx270_nand_mtd->owner = THIS_MODULE;
/* insert callbacks */
this->IO_ADDR_R = cmx270_nand_io;
this->IO_ADDR_W = cmx270_nand_io;
this->cmd_ctrl = cmx270_hwcontrol;
this->dev_ready = cmx270_device_ready;
this->legacy.IO_ADDR_R = cmx270_nand_io;
this->legacy.IO_ADDR_W = cmx270_nand_io;
this->legacy.cmd_ctrl = cmx270_hwcontrol;
this->legacy.dev_ready = cmx270_device_ready;
/* 15 us command delay time */
this->chip_delay = 20;
this->legacy.chip_delay = 20;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
/* read/write functions */
this->read_byte = cmx270_read_byte;
this->read_buf = cmx270_read_buf;
this->write_buf = cmx270_write_buf;
this->legacy.read_byte = cmx270_read_byte;
this->legacy.read_buf = cmx270_read_buf;
this->legacy.write_buf = cmx270_write_buf;
/* Scan to find existence of the device */
ret = nand_scan(cmx270_nand_mtd, 1);
ret = nand_scan(this, 1);
if (ret) {
pr_notice("No NAND device\n");
goto err_scan;
@ -228,7 +224,7 @@ module_init(cmx270_init);
static void __exit cmx270_cleanup(void)
{
/* Release resources, unregister device */
nand_release(cmx270_nand_mtd);
nand_release(mtd_to_nand(cmx270_nand_mtd));
gpio_free(GPIO_NAND_RB);
gpio_free(GPIO_NAND_CS);

View File

@ -93,83 +93,74 @@
#define CS_NAND_ECC_CLRECC (1<<1)
#define CS_NAND_ECC_ENECC (1<<0)
static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void cs553x_read_buf(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
while (unlikely(len > 0x800)) {
memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
memcpy_fromio(buf, this->legacy.IO_ADDR_R, 0x800);
buf += 0x800;
len -= 0x800;
}
memcpy_fromio(buf, this->IO_ADDR_R, len);
memcpy_fromio(buf, this->legacy.IO_ADDR_R, len);
}
static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void cs553x_write_buf(struct nand_chip *this, const u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
while (unlikely(len > 0x800)) {
memcpy_toio(this->IO_ADDR_R, buf, 0x800);
memcpy_toio(this->legacy.IO_ADDR_R, buf, 0x800);
buf += 0x800;
len -= 0x800;
}
memcpy_toio(this->IO_ADDR_R, buf, len);
memcpy_toio(this->legacy.IO_ADDR_R, buf, len);
}
static unsigned char cs553x_read_byte(struct mtd_info *mtd)
static unsigned char cs553x_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
return readb(this->IO_ADDR_R);
return readb(this->legacy.IO_ADDR_R);
}
static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
static void cs553x_write_byte(struct nand_chip *this, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
int i = 100000;
while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
while (i && readb(this->legacy.IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
udelay(1);
i--;
}
writeb(byte, this->IO_ADDR_W + 0x801);
writeb(byte, this->legacy.IO_ADDR_W + 0x801);
}
static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
static void cs553x_hwcontrol(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *mmio_base = this->IO_ADDR_R;
void __iomem *mmio_base = this->legacy.IO_ADDR_R;
if (ctrl & NAND_CTRL_CHANGE) {
unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
writeb(ctl, mmio_base + MM_NAND_CTL);
}
if (cmd != NAND_CMD_NONE)
cs553x_write_byte(mtd, cmd);
cs553x_write_byte(this, cmd);
}
static int cs553x_device_ready(struct mtd_info *mtd)
static int cs553x_device_ready(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *mmio_base = this->IO_ADDR_R;
void __iomem *mmio_base = this->legacy.IO_ADDR_R;
unsigned char foo = readb(mmio_base + MM_NAND_STS);
return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
}
static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
static void cs_enable_hwecc(struct nand_chip *this, int mode)
{
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *mmio_base = this->IO_ADDR_R;
void __iomem *mmio_base = this->legacy.IO_ADDR_R;
writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
}
static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat,
u_char *ecc_code)
{
uint32_t ecc;
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *mmio_base = this->IO_ADDR_R;
void __iomem *mmio_base = this->legacy.IO_ADDR_R;
ecc = readl(mmio_base + MM_NAND_STS);
@ -208,20 +199,20 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
new_mtd->owner = THIS_MODULE;
/* map physical address */
this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096);
if (!this->IO_ADDR_R) {
this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = ioremap(adr, 4096);
if (!this->legacy.IO_ADDR_R) {
pr_warn("ioremap cs553x NAND @0x%08lx failed\n", adr);
err = -EIO;
goto out_mtd;
}
this->cmd_ctrl = cs553x_hwcontrol;
this->dev_ready = cs553x_device_ready;
this->read_byte = cs553x_read_byte;
this->read_buf = cs553x_read_buf;
this->write_buf = cs553x_write_buf;
this->legacy.cmd_ctrl = cs553x_hwcontrol;
this->legacy.dev_ready = cs553x_device_ready;
this->legacy.read_byte = cs553x_read_byte;
this->legacy.read_buf = cs553x_read_buf;
this->legacy.write_buf = cs553x_write_buf;
this->chip_delay = 0;
this->legacy.chip_delay = 0;
this->ecc.mode = NAND_ECC_HW;
this->ecc.size = 256;
@ -241,7 +232,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
}
/* Scan to find existence of the device */
err = nand_scan(new_mtd, 1);
err = nand_scan(this, 1);
if (err)
goto out_free;
@ -251,7 +242,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
out_free:
kfree(new_mtd->name);
out_ior:
iounmap(this->IO_ADDR_R);
iounmap(this->legacy.IO_ADDR_R);
out_mtd:
kfree(this);
out:
@ -333,10 +324,10 @@ static void __exit cs553x_cleanup(void)
continue;
this = mtd_to_nand(mtd);
mmio_base = this->IO_ADDR_R;
mmio_base = this->legacy.IO_ADDR_R;
/* Release resources, unregister device */
nand_release(mtd);
nand_release(this);
kfree(mtd->name);
cs553x_mtd[i] = NULL;

View File

@ -97,12 +97,11 @@ static inline void davinci_nand_writel(struct davinci_nand_info *info,
* Access to hardware control lines: ALE, CLE, secondary chipselect.
*/
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
static void nand_davinci_hwcontrol(struct nand_chip *nand, int cmd,
unsigned int ctrl)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(nand));
void __iomem *addr = info->current_cs;
struct nand_chip *nand = mtd_to_nand(mtd);
/* Did the control lines change? */
if (ctrl & NAND_CTRL_CHANGE) {
@ -111,16 +110,16 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
else if ((ctrl & NAND_CTRL_ALE) == NAND_CTRL_ALE)
addr += info->mask_ale;
nand->IO_ADDR_W = addr;
nand->legacy.IO_ADDR_W = addr;
}
if (cmd != NAND_CMD_NONE)
iowrite8(cmd, nand->IO_ADDR_W);
iowrite8(cmd, nand->legacy.IO_ADDR_W);
}
static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
static void nand_davinci_select_chip(struct nand_chip *nand, int chip)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(nand));
info->current_cs = info->vaddr;
@ -128,8 +127,8 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
if (chip > 0)
info->current_cs += info->mask_chipsel;
info->chip.IO_ADDR_W = info->current_cs;
info->chip.IO_ADDR_R = info->chip.IO_ADDR_W;
info->chip.legacy.IO_ADDR_W = info->current_cs;
info->chip.legacy.IO_ADDR_R = info->chip.legacy.IO_ADDR_W;
}
/*----------------------------------------------------------------------*/
@ -146,16 +145,16 @@ static inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd)
+ 4 * info->core_chipsel);
}
static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
static void nand_davinci_hwctl_1bit(struct nand_chip *chip, int mode)
{
struct davinci_nand_info *info;
uint32_t nandcfr;
unsigned long flags;
info = to_davinci_nand(mtd);
info = to_davinci_nand(nand_to_mtd(chip));
/* Reset ECC hardware */
nand_davinci_readecc_1bit(mtd);
nand_davinci_readecc_1bit(nand_to_mtd(chip));
spin_lock_irqsave(&davinci_nand_lock, flags);
@ -170,10 +169,10 @@ static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode)
/*
* Read hardware ECC value and pack into three bytes
*/
static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code)
static int nand_davinci_calculate_1bit(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
unsigned int ecc_val = nand_davinci_readecc_1bit(mtd);
unsigned int ecc_val = nand_davinci_readecc_1bit(nand_to_mtd(chip));
unsigned int ecc24 = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4);
/* invert so that erased block ecc is correct */
@ -185,10 +184,9 @@ static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
return 0;
}
static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
static int nand_davinci_correct_1bit(struct nand_chip *chip, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
(read_ecc[2] << 16);
uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
@ -231,9 +229,9 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
* OOB without recomputing ECC.
*/
static void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode)
static void nand_davinci_hwctl_4bit(struct nand_chip *chip, int mode)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip));
unsigned long flags;
u32 val;
@ -266,10 +264,10 @@ nand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4])
}
/* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */
static int nand_davinci_calculate_4bit(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code)
static int nand_davinci_calculate_4bit(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip));
u32 raw_ecc[4], *p;
unsigned i;
@ -303,11 +301,11 @@ static int nand_davinci_calculate_4bit(struct mtd_info *mtd,
/* Correct up to 4 bits in data we just read, using state left in the
* hardware plus the ecc_code computed when it was first written.
*/
static int nand_davinci_correct_4bit(struct mtd_info *mtd,
u_char *data, u_char *ecc_code, u_char *null)
static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
u_char *ecc_code, u_char *null)
{
int i;
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip));
unsigned short ecc10[8];
unsigned short *ecc16;
u32 syndrome[4];
@ -436,38 +434,35 @@ correct:
* the two LSBs for NAND access ... so we can issue 32-bit reads/writes
* and have that transparently morphed into multiple NAND operations.
*/
static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void nand_davinci_read_buf(struct nand_chip *chip, uint8_t *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0)
ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
ioread32_rep(chip->legacy.IO_ADDR_R, buf, len >> 2);
else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0)
ioread16_rep(chip->IO_ADDR_R, buf, len >> 1);
ioread16_rep(chip->legacy.IO_ADDR_R, buf, len >> 1);
else
ioread8_rep(chip->IO_ADDR_R, buf, len);
ioread8_rep(chip->legacy.IO_ADDR_R, buf, len);
}
static void nand_davinci_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
static void nand_davinci_write_buf(struct nand_chip *chip, const uint8_t *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0)
iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
iowrite32_rep(chip->legacy.IO_ADDR_R, buf, len >> 2);
else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0)
iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1);
iowrite16_rep(chip->legacy.IO_ADDR_R, buf, len >> 1);
else
iowrite8_rep(chip->IO_ADDR_R, buf, len);
iowrite8_rep(chip->legacy.IO_ADDR_R, buf, len);
}
/*
* Check hardware register for wait status. Returns 1 if device is ready,
* 0 if it is still busy.
*/
static int nand_davinci_dev_ready(struct mtd_info *mtd)
static int nand_davinci_dev_ready(struct nand_chip *chip)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip));
return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
}
@ -764,9 +759,9 @@ static int nand_davinci_probe(struct platform_device *pdev)
mtd->dev.parent = &pdev->dev;
nand_set_flash_node(&info->chip, pdev->dev.of_node);
info->chip.IO_ADDR_R = vaddr;
info->chip.IO_ADDR_W = vaddr;
info->chip.chip_delay = 0;
info->chip.legacy.IO_ADDR_R = vaddr;
info->chip.legacy.IO_ADDR_W = vaddr;
info->chip.legacy.chip_delay = 0;
info->chip.select_chip = nand_davinci_select_chip;
/* options such as NAND_BBT_USE_FLASH */
@ -786,12 +781,12 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->mask_cle = pdata->mask_cle ? : MASK_CLE;
/* Set address of hardware control function */
info->chip.cmd_ctrl = nand_davinci_hwcontrol;
info->chip.dev_ready = nand_davinci_dev_ready;
info->chip.legacy.cmd_ctrl = nand_davinci_hwcontrol;
info->chip.legacy.dev_ready = nand_davinci_dev_ready;
/* Speed up buffer I/O */
info->chip.read_buf = nand_davinci_read_buf;
info->chip.write_buf = nand_davinci_write_buf;
info->chip.legacy.read_buf = nand_davinci_read_buf;
info->chip.legacy.write_buf = nand_davinci_write_buf;
/* Use board-specific ECC config */
info->chip.ecc.mode = pdata->ecc_mode;
@ -807,7 +802,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
/* Scan to find existence of the device(s) */
info->chip.dummy_controller.ops = &davinci_nand_controller_ops;
ret = nand_scan(mtd, pdata->mask_chipsel ? 2 : 1);
ret = nand_scan(&info->chip, pdata->mask_chipsel ? 2 : 1);
if (ret < 0) {
dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
return ret;
@ -841,7 +836,7 @@ static int nand_davinci_remove(struct platform_device *pdev)
ecc4_busy = false;
spin_unlock_irq(&davinci_nand_lock);
nand_release(nand_to_mtd(&info->chip));
nand_release(&info->chip);
return 0;
}

View File

@ -1,15 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
* NAND Flash Controller Device Driver
* Copyright © 2009-2010, Intel Corporation and its suppliers.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* Copyright (c) 2017 Socionext Inc.
* Reworked by Masahiro Yamada <yamada.masahiro@socionext.com>
*/
#include <linux/bitfield.h>
@ -25,9 +20,8 @@
#include "denali.h"
MODULE_LICENSE("GPL");
#define DENALI_NAND_NAME "denali-nand"
#define DENALI_DEFAULT_OOB_SKIP_BYTES 8
/* for Indexed Addressing */
#define DENALI_INDEXED_CTRL 0x00
@ -222,8 +216,9 @@ static uint32_t denali_check_irq(struct denali_nand_info *denali)
return irq_status;
}
static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void denali_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
int i;
@ -232,9 +227,10 @@ static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
buf[i] = denali->host_read(denali, addr);
}
static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void denali_write_buf(struct nand_chip *chip, const uint8_t *buf,
int len)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
int i;
@ -242,9 +238,9 @@ static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
denali->host_write(denali, addr, buf[i]);
}
static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
static void denali_read_buf16(struct nand_chip *chip, uint8_t *buf, int len)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
uint16_t *buf16 = (uint16_t *)buf;
int i;
@ -253,10 +249,10 @@ static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
buf16[i] = denali->host_read(denali, addr);
}
static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf,
static void denali_write_buf16(struct nand_chip *chip, const uint8_t *buf,
int len)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
const uint16_t *buf16 = (const uint16_t *)buf;
int i;
@ -265,32 +261,23 @@ static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf,
denali->host_write(denali, addr, buf16[i]);
}
static uint8_t denali_read_byte(struct mtd_info *mtd)
static uint8_t denali_read_byte(struct nand_chip *chip)
{
uint8_t byte;
denali_read_buf(mtd, &byte, 1);
denali_read_buf(chip, &byte, 1);
return byte;
}
static void denali_write_byte(struct mtd_info *mtd, uint8_t byte)
static void denali_write_byte(struct nand_chip *chip, uint8_t byte)
{
denali_write_buf(mtd, &byte, 1);
denali_write_buf(chip, &byte, 1);
}
static uint16_t denali_read_word(struct mtd_info *mtd)
static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl)
{
uint16_t word;
denali_read_buf16(mtd, (uint8_t *)&word, 2);
return word;
}
static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
uint32_t type;
if (ctrl & NAND_CLE)
@ -301,7 +288,8 @@ static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
return;
/*
* Some commands are followed by chip->dev_ready or chip->waitfunc.
* Some commands are followed by chip->legacy.dev_ready or
* chip->legacy.waitfunc.
* irq_status must be cleared here to catch the R/B# interrupt later.
*/
if (ctrl & NAND_CTRL_CHANGE)
@ -310,9 +298,9 @@ static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
denali->host_write(denali, DENALI_BANK(denali) | type, dat);
}
static int denali_dev_ready(struct mtd_info *mtd)
static int denali_dev_ready(struct nand_chip *chip)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
return !!(denali_check_irq(denali) & INTR__INT_ACT);
}
@ -698,9 +686,10 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
false);
}
static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
int writesize = mtd->writesize;
int oobsize = mtd->oobsize;
@ -773,17 +762,18 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int denali_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
denali_oob_xfer(mtd, chip, page, 0);
return 0;
}
static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int denali_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
denali_reset_irq(denali);
@ -793,9 +783,10 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
return nand_prog_page_end_op(chip);
}
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int denali_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
unsigned long uncor_ecc_flags = 0;
int stat = 0;
@ -814,7 +805,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return stat;
if (uncor_ecc_flags) {
ret = denali_read_oob(mtd, chip, page);
ret = denali_read_oob(chip, page);
if (ret)
return ret;
@ -825,9 +816,10 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return stat;
}
static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
int writesize = mtd->writesize;
int oobsize = mtd->oobsize;
@ -903,25 +895,26 @@ static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return denali_data_xfer(denali, tmp_buf, size, page, 1, 1);
}
static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int denali_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = mtd_to_denali(mtd);
return denali_data_xfer(denali, (void *)buf, mtd->writesize,
page, 0, 1);
}
static void denali_select_chip(struct mtd_info *mtd, int chip)
static void denali_select_chip(struct nand_chip *chip, int cs)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
denali->active_bank = chip;
denali->active_bank = cs;
}
static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
static int denali_waitfunc(struct nand_chip *chip)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
uint32_t irq_status;
/* R/B# pin transitioned from low to high? */
@ -930,9 +923,9 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL;
}
static int denali_erase(struct mtd_info *mtd, int page)
static int denali_erase(struct nand_chip *chip, int page)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
uint32_t irq_status;
denali_reset_irq(denali);
@ -947,10 +940,10 @@ static int denali_erase(struct mtd_info *mtd, int page)
return irq_status & INTR__ERASE_COMP ? 0 : -EIO;
}
static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
static int denali_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip));
const struct nand_sdr_timings *timings;
unsigned long t_x, mult_x;
int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data;
@ -1105,12 +1098,17 @@ static void denali_hw_init(struct denali_nand_info *denali)
denali->revision = swab16(ioread32(denali->reg + REVISION));
/*
* tell driver how many bit controller will skip before
* writing ECC code in OOB, this register may be already
* set by firmware. So we read this value out.
* if this value is 0, just let it be.
* Set how many bytes should be skipped before writing data in OOB.
* If a non-zero value has already been set (by firmware or something),
* just use it. Otherwise, set the driver default.
*/
denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES);
if (!denali->oob_skip_bytes) {
denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES;
iowrite32(denali->oob_skip_bytes,
denali->reg + SPARE_AREA_SKIP_BYTES);
}
denali_detect_max_banks(denali);
iowrite32(0x0F, denali->reg + RB_PIN_ENABLED);
iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE);
@ -1277,11 +1275,11 @@ static int denali_attach_chip(struct nand_chip *chip)
mtd_set_ooblayout(mtd, &denali_ooblayout_ops);
if (chip->options & NAND_BUSWIDTH_16) {
chip->read_buf = denali_read_buf16;
chip->write_buf = denali_write_buf16;
chip->legacy.read_buf = denali_read_buf16;
chip->legacy.write_buf = denali_write_buf16;
} else {
chip->read_buf = denali_read_buf;
chip->write_buf = denali_write_buf;
chip->legacy.read_buf = denali_read_buf;
chip->legacy.write_buf = denali_write_buf;
}
chip->ecc.read_page = denali_read_page;
chip->ecc.read_page_raw = denali_read_page_raw;
@ -1289,7 +1287,7 @@ static int denali_attach_chip(struct nand_chip *chip)
chip->ecc.write_page_raw = denali_write_page_raw;
chip->ecc.read_oob = denali_read_oob;
chip->ecc.write_oob = denali_write_oob;
chip->erase = denali_erase;
chip->legacy.erase = denali_erase;
ret = denali_multidev_fixup(denali);
if (ret)
@ -1358,12 +1356,11 @@ int denali_init(struct denali_nand_info *denali)
mtd->name = "denali-nand";
chip->select_chip = denali_select_chip;
chip->read_byte = denali_read_byte;
chip->write_byte = denali_write_byte;
chip->read_word = denali_read_word;
chip->cmd_ctrl = denali_cmd_ctrl;
chip->dev_ready = denali_dev_ready;
chip->waitfunc = denali_waitfunc;
chip->legacy.read_byte = denali_read_byte;
chip->legacy.write_byte = denali_write_byte;
chip->legacy.cmd_ctrl = denali_cmd_ctrl;
chip->legacy.dev_ready = denali_dev_ready;
chip->legacy.waitfunc = denali_waitfunc;
if (features & FEATURES__INDEX_ADDR) {
denali->host_read = denali_indexed_read;
@ -1378,7 +1375,7 @@ int denali_init(struct denali_nand_info *denali)
chip->setup_data_interface = denali_setup_data_interface;
chip->dummy_controller.ops = &denali_controller_ops;
ret = nand_scan(mtd, denali->max_banks);
ret = nand_scan(chip, denali->max_banks);
if (ret)
goto disable_irq;
@ -1401,9 +1398,11 @@ EXPORT_SYMBOL(denali_init);
void denali_remove(struct denali_nand_info *denali)
{
struct mtd_info *mtd = nand_to_mtd(&denali->nand);
nand_release(mtd);
nand_release(&denali->nand);
denali_disable_irq(denali);
}
EXPORT_SYMBOL(denali_remove);
MODULE_DESCRIPTION("Driver core for Denali NAND controller");
MODULE_AUTHOR("Intel Corporation and its suppliers");
MODULE_LICENSE("GPL v2");

View File

@ -1,15 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* NAND Flash Controller Device Driver
* Copyright (c) 2009 - 2010, Intel Corporation and its suppliers.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __DENALI_H__

View File

@ -1,16 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/*
* NAND Flash Controller Device Driver for DT
*
* Copyright © 2011, Picochip.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/clk.h>
@ -202,6 +194,6 @@ static struct platform_driver denali_dt_driver = {
};
module_platform_driver(denali_dt_driver);
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Jamie Iles");
MODULE_DESCRIPTION("DT driver for Denali NAND controller");

View File

@ -1,15 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* NAND Flash Controller Device Driver
* Copyright © 2009-2010, Intel Corporation and its suppliers.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/errno.h>

View File

@ -83,9 +83,9 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
static void doc200x_hwcontrol(struct nand_chip *this, int cmd,
unsigned int bitmask);
static void doc200x_select_chip(struct mtd_info *mtd, int chip);
static void doc200x_select_chip(struct nand_chip *this, int chip);
static int debug = 0;
module_param(debug, int, 0);
@ -290,9 +290,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
return ret;
}
static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
static void doc2000_write_byte(struct nand_chip *this, u_char datum)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -302,9 +301,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
WriteDOC(datum, docptr, 2k_CDSN_IO);
}
static u_char doc2000_read_byte(struct mtd_info *mtd)
static u_char doc2000_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
u_char ret;
@ -317,9 +315,9 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
return ret;
}
static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
static void doc2000_writebuf(struct nand_chip *this, const u_char *buf,
int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -334,9 +332,8 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
printk("\n");
}
static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
static void doc2000_readbuf(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -344,14 +341,12 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
if (debug)
printk("readbuf of %d bytes: ", len);
for (i = 0; i < len; i++) {
for (i = 0; i < len; i++)
buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
}
}
static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
static void doc2000_readbuf_dword(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -376,19 +371,19 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
struct doc_priv *doc = nand_get_controller_data(this);
uint16_t ret;
doc200x_select_chip(mtd, nr);
doc200x_hwcontrol(mtd, NAND_CMD_READID,
doc200x_select_chip(this, nr);
doc200x_hwcontrol(this, NAND_CMD_READID,
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(this, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/* We can't use dev_ready here, but at least we wait for the
* command to complete
*/
udelay(50);
ret = this->read_byte(mtd) << 8;
ret |= this->read_byte(mtd);
ret = this->legacy.read_byte(this) << 8;
ret |= this->legacy.read_byte(this);
if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) {
/* First chip probe. See if we get same results by 32-bit access */
@ -398,10 +393,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
} ident;
void __iomem *docptr = doc->virtadr;
doc200x_hwcontrol(mtd, NAND_CMD_READID,
doc200x_hwcontrol(this, NAND_CMD_READID,
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(mtd, NAND_CMD_NONE,
doc200x_hwcontrol(this, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(this, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
udelay(50);
@ -409,7 +404,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
ident.dword = readl(docptr + DoC_2k_CDSN_IO);
if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {
pr_info("DiskOnChip 2000 responds to DWORD access\n");
this->read_buf = &doc2000_readbuf_dword;
this->legacy.read_buf = &doc2000_readbuf_dword;
}
}
@ -438,7 +433,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd)
pr_debug("Detected %d chips per floor.\n", i);
}
static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
static int doc200x_wait(struct nand_chip *this)
{
struct doc_priv *doc = nand_get_controller_data(this);
@ -447,14 +442,13 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
DoC_WaitReady(doc);
nand_status_op(this, NULL);
DoC_WaitReady(doc);
status = (int)this->read_byte(mtd);
status = (int)this->legacy.read_byte(this);
return status;
}
static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
static void doc2001_write_byte(struct nand_chip *this, u_char datum)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -463,9 +457,8 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
WriteDOC(datum, docptr, WritePipeTerm);
}
static u_char doc2001_read_byte(struct mtd_info *mtd)
static u_char doc2001_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -477,9 +470,8 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
return ReadDOC(docptr, LastDataRead);
}
static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
static void doc2001_writebuf(struct nand_chip *this, const u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -490,9 +482,8 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
WriteDOC(0x00, docptr, WritePipeTerm);
}
static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
static void doc2001_readbuf(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -507,9 +498,8 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
buf[i] = ReadDOC(docptr, LastDataRead);
}
static u_char doc2001plus_read_byte(struct mtd_info *mtd)
static u_char doc2001plus_read_byte(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
u_char ret;
@ -522,9 +512,8 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
return ret;
}
static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
static void doc2001plus_writebuf(struct nand_chip *this, const u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -540,9 +529,8 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le
printk("\n");
}
static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
static void doc2001plus_readbuf(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -571,9 +559,8 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
printk("\n");
}
static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
static void doc2001plus_select_chip(struct nand_chip *this, int chip)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int floor = 0;
@ -598,9 +585,8 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
doc->curfloor = floor;
}
static void doc200x_select_chip(struct mtd_info *mtd, int chip)
static void doc200x_select_chip(struct nand_chip *this, int chip)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int floor = 0;
@ -615,12 +601,12 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
chip -= (floor * doc->chips_per_floor);
/* 11.4.4 -- deassert CE before changing chip */
doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
doc200x_hwcontrol(this, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
WriteDOC(floor, docptr, FloorSelect);
WriteDOC(chip, docptr, CDSNDeviceSelect);
doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
doc200x_hwcontrol(this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
doc->curchip = chip;
doc->curfloor = floor;
@ -628,10 +614,9 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
static void doc200x_hwcontrol(struct nand_chip *this, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -646,15 +631,16 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
}
if (cmd != NAND_CMD_NONE) {
if (DoC_is_2000(doc))
doc2000_write_byte(mtd, cmd);
doc2000_write_byte(this, cmd);
else
doc2001_write_byte(mtd, cmd);
doc2001_write_byte(this, cmd);
}
}
static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
static void doc2001plus_command(struct nand_chip *this, unsigned command,
int column, int page_addr)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(this);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -729,13 +715,13 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
return;
case NAND_CMD_RESET:
if (this->dev_ready)
if (this->legacy.dev_ready)
break;
udelay(this->chip_delay);
udelay(this->legacy.chip_delay);
WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd);
WriteDOC(0, docptr, Mplus_WritePipeTerm);
WriteDOC(0, docptr, Mplus_WritePipeTerm);
while (!(this->read_byte(mtd) & 0x40)) ;
while (!(this->legacy.read_byte(this) & 0x40)) ;
return;
/* This applies to read commands */
@ -744,8 +730,8 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
* If we don't have access to the busy pin, we apply the given
* command delay
*/
if (!this->dev_ready) {
udelay(this->chip_delay);
if (!this->legacy.dev_ready) {
udelay(this->legacy.chip_delay);
return;
}
}
@ -754,12 +740,11 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
* any case on any machine. */
ndelay(100);
/* wait until command is processed */
while (!this->dev_ready(mtd)) ;
while (!this->legacy.dev_ready(this)) ;
}
static int doc200x_dev_ready(struct mtd_info *mtd)
static int doc200x_dev_ready(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -790,16 +775,15 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
}
}
static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs)
static int doc200x_block_bad(struct nand_chip *this, loff_t ofs)
{
/* This is our last resort if we couldn't find or create a BBT. Just
pretend all blocks are good. */
return 0;
}
static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
static void doc200x_enable_hwecc(struct nand_chip *this, int mode)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -816,9 +800,8 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
}
}
static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
static void doc2001plus_enable_hwecc(struct nand_chip *this, int mode)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
@ -836,9 +819,9 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
}
/* This code is only called on write */
static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
static int doc200x_calculate_ecc(struct nand_chip *this, const u_char *dat,
unsigned char *ecc_code)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
int i;
@ -895,11 +878,10 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsign
return 0;
}
static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
static int doc200x_correct_data(struct nand_chip *this, u_char *dat,
u_char *read_ecc, u_char *isnull)
{
int i, ret = 0;
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
void __iomem *docptr = doc->virtadr;
uint8_t calc_ecc[6];
@ -1357,9 +1339,9 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
this->read_byte = doc2000_read_byte;
this->write_buf = doc2000_writebuf;
this->read_buf = doc2000_readbuf;
this->legacy.read_byte = doc2000_read_byte;
this->legacy.write_buf = doc2000_writebuf;
this->legacy.read_buf = doc2000_readbuf;
doc->late_init = nftl_scan_bbt;
doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO;
@ -1373,9 +1355,9 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
this->read_byte = doc2001_read_byte;
this->write_buf = doc2001_writebuf;
this->read_buf = doc2001_readbuf;
this->legacy.read_byte = doc2001_read_byte;
this->legacy.write_buf = doc2001_writebuf;
this->legacy.read_buf = doc2001_readbuf;
ReadDOC(doc->virtadr, ChipID);
ReadDOC(doc->virtadr, ChipID);
@ -1403,13 +1385,13 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
struct doc_priv *doc = nand_get_controller_data(this);
this->read_byte = doc2001plus_read_byte;
this->write_buf = doc2001plus_writebuf;
this->read_buf = doc2001plus_readbuf;
this->legacy.read_byte = doc2001plus_read_byte;
this->legacy.write_buf = doc2001plus_writebuf;
this->legacy.read_buf = doc2001plus_readbuf;
doc->late_init = inftl_scan_bbt;
this->cmd_ctrl = NULL;
this->legacy.cmd_ctrl = NULL;
this->select_chip = doc2001plus_select_chip;
this->cmdfunc = doc2001plus_command;
this->legacy.cmdfunc = doc2001plus_command;
this->ecc.hwctl = doc2001plus_enable_hwecc;
doc->chips_per_floor = 1;
@ -1587,10 +1569,10 @@ static int __init doc_probe(unsigned long physadr)
nand_set_controller_data(nand, doc);
nand->select_chip = doc200x_select_chip;
nand->cmd_ctrl = doc200x_hwcontrol;
nand->dev_ready = doc200x_dev_ready;
nand->waitfunc = doc200x_wait;
nand->block_bad = doc200x_block_bad;
nand->legacy.cmd_ctrl = doc200x_hwcontrol;
nand->legacy.dev_ready = doc200x_dev_ready;
nand->legacy.waitfunc = doc200x_wait;
nand->legacy.block_bad = doc200x_block_bad;
nand->ecc.hwctl = doc200x_enable_hwecc;
nand->ecc.calculate = doc200x_calculate_ecc;
nand->ecc.correct = doc200x_correct_data;
@ -1620,14 +1602,14 @@ static int __init doc_probe(unsigned long physadr)
else
numchips = doc2001_init(mtd);
if ((ret = nand_scan(mtd, numchips)) || (ret = doc->late_init(mtd))) {
if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) {
/* DBB note: i believe nand_release is necessary here, as
buffers may have been allocated in nand_base. Check with
Thomas. FIX ME! */
/* nand_release will call mtd_device_unregister, but we
haven't yet added it. This is handled without incident by
mtd_device_unregister, as far as I can tell. */
nand_release(mtd);
nand_release(nand);
goto fail;
}
@ -1662,7 +1644,7 @@ static void release_nanddoc(void)
doc = nand_get_controller_data(nand);
nextmtd = doc->nextdoc;
nand_release(mtd);
nand_release(nand);
iounmap(doc->virtadr);
release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
free_rs(doc->rs_decoder);

File diff suppressed because it is too large Load Diff

View File

@ -317,10 +317,10 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
}
/* cmdfunc send commands to the FCM */
static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command,
int column, int page_addr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
@ -533,7 +533,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
}
}
static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
static void fsl_elbc_select_chip(struct nand_chip *chip, int cs)
{
/* The hardware does not seem to support multiple
* chips per bank.
@ -543,9 +543,9 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
/*
* Write buf to the FCM Controller Data Buffer
*/
static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
@ -581,9 +581,8 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
* read a byte from either the FCM hardware buffer if it has any data left
* otherwise issue a command to read a single byte.
*/
static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
static u8 fsl_elbc_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
@ -598,9 +597,8 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
/*
* Read from the FCM Controller Data Buffer
*/
static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int avail;
@ -623,7 +621,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
/* This function is called after Program and Erase Operations to
* check for success or failure.
*/
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int fsl_elbc_wait(struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
@ -660,8 +658,8 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip)
chip->chipsize);
dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
chip->pagemask);
dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
chip->chip_delay);
dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n",
chip->legacy.chip_delay);
dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
chip->badblockpos);
dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
@ -710,18 +708,19 @@ static const struct nand_controller_ops fsl_elbc_controller_ops = {
.attach_chip = fsl_elbc_attach_chip,
};
static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize);
if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL)
mtd->ecc_stats.failed++;
return elbc_fcm_ctrl->max_bitflips;
@ -730,11 +729,13 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
/* ECC will be calculated automatically, and errors will be detected in
* waitfunc.
*/
static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -742,13 +743,15 @@ static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
/* ECC will be calculated automatically, and errors will be detected in
* waitfunc.
*/
static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, uint32_t data_len,
const uint8_t *buf, int oob_required, int page)
static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset,
uint32_t data_len, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_elbc_write_buf(chip, buf, mtd->writesize);
fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -773,14 +776,14 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
/* fill in nand_chip structure */
/* set up function call table */
chip->read_byte = fsl_elbc_read_byte;
chip->write_buf = fsl_elbc_write_buf;
chip->read_buf = fsl_elbc_read_buf;
chip->legacy.read_byte = fsl_elbc_read_byte;
chip->legacy.write_buf = fsl_elbc_write_buf;
chip->legacy.read_buf = fsl_elbc_read_buf;
chip->select_chip = fsl_elbc_select_chip;
chip->cmdfunc = fsl_elbc_cmdfunc;
chip->waitfunc = fsl_elbc_wait;
chip->set_features = nand_get_set_features_notsupp;
chip->get_features = nand_get_set_features_notsupp;
chip->legacy.cmdfunc = fsl_elbc_cmdfunc;
chip->legacy.waitfunc = fsl_elbc_wait;
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
chip->bbt_td = &bbt_main_descr;
chip->bbt_md = &bbt_mirror_descr;
@ -915,7 +918,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
goto err;
priv->chip.controller->ops = &fsl_elbc_controller_ops;
ret = nand_scan(mtd, 1);
ret = nand_scan(&priv->chip, 1);
if (ret)
goto err;
@ -942,9 +945,8 @@ static int fsl_elbc_nand_remove(struct platform_device *pdev)
{
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev);
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
nand_release(mtd);
nand_release(&priv->chip);
fsl_elbc_chip_remove(priv);
mutex_lock(&fsl_elbc_nand_mutex);

View File

@ -30,6 +30,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/fsl_ifc.h>
#include <linux/iopoll.h>
#define ERR_BYTE 0xFF /* Value returned for read
bytes when read failed */
@ -300,9 +301,9 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
}
/* cmdfunc send commands to the IFC NAND Machine */
static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
int column, int page_addr) {
struct nand_chip *chip = mtd_to_nand(mtd);
static void fsl_ifc_cmdfunc(struct nand_chip *chip, unsigned int command,
int column, int page_addr) {
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
@ -508,7 +509,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
}
}
static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
static void fsl_ifc_select_chip(struct nand_chip *chip, int cs)
{
/* The hardware does not seem to support multiple
* chips per bank.
@ -518,9 +519,9 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
/*
* Write buf to the IFC NAND Controller Data Buffer
*/
static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void fsl_ifc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
unsigned int bufsize = mtd->writesize + mtd->oobsize;
@ -544,9 +545,8 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
* Read a byte from either the IFC hardware buffer
* read function for 8-bit buswidth
*/
static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
static uint8_t fsl_ifc_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
unsigned int offset;
@ -567,9 +567,8 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
* Read two bytes from the IFC hardware buffer
* read function for 16-bit buswith
*/
static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
static uint8_t fsl_ifc_read_byte16(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
uint16_t data;
@ -590,9 +589,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
/*
* Read from the IFC Controller Data Buffer
*/
static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void fsl_ifc_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
int avail;
@ -616,8 +614,9 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
* This function is called after Program and Erase Operations to
* check for success or failure.
*/
static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int fsl_ifc_wait(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
@ -678,20 +677,21 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
return bitflips;
}
static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) {
if (!oob_required)
fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
return check_erased_page(chip, buf);
}
@ -705,11 +705,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
/* ECC will be calculated automatically, and errors will be detected in
* waitfunc.
*/
static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int fsl_ifc_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
fsl_ifc_write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -725,8 +727,8 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip)
chip->chipsize);
dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__,
chip->pagemask);
dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__,
chip->chip_delay);
dev_dbg(priv->dev, "%s: nand->legacy.chip_delay = %d\n", __func__,
chip->legacy.chip_delay);
dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__,
chip->badblockpos);
dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__,
@ -761,7 +763,7 @@ static const struct nand_controller_ops fsl_ifc_controller_ops = {
.attach_chip = fsl_ifc_attach_chip,
};
static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
{
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs;
@ -769,6 +771,27 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
uint32_t csor = 0, csor_8k = 0, csor_ext = 0;
uint32_t cs = priv->bank;
if (ctrl->version < FSL_IFC_VERSION_1_1_0)
return 0;
if (ctrl->version > FSL_IFC_VERSION_1_1_0) {
u32 ncfgr, status;
int ret;
/* Trigger auto initialization */
ncfgr = ifc_in32(&ifc_runtime->ifc_nand.ncfgr);
ifc_out32(ncfgr | IFC_NAND_NCFGR_SRAM_INIT_EN, &ifc_runtime->ifc_nand.ncfgr);
/* Wait until done */
ret = readx_poll_timeout(ifc_in32, &ifc_runtime->ifc_nand.ncfgr,
status, !(status & IFC_NAND_NCFGR_SRAM_INIT_EN),
10, IFC_TIMEOUT_MSECS * 1000);
if (ret)
dev_err(priv->dev, "Failed to initialize SRAM!\n");
return ret;
}
/* Save CSOR and CSOR_ext */
csor = ifc_in32(&ifc_global->csor_cs[cs].csor);
csor_ext = ifc_in32(&ifc_global->csor_cs[cs].csor_ext);
@ -805,12 +828,16 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
msecs_to_jiffies(IFC_TIMEOUT_MSECS));
if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) {
pr_err("fsl-ifc: Failed to Initialise SRAM\n");
return -ETIMEDOUT;
}
/* Restore CSOR and CSOR_ext */
ifc_out32(csor, &ifc_global->csor_cs[cs].csor);
ifc_out32(csor_ext, &ifc_global->csor_cs[cs].csor_ext);
return 0;
}
static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
@ -821,6 +848,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
struct nand_chip *chip = &priv->chip;
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
u32 csor;
int ret;
/* Fill in fsl_ifc_mtd structure */
mtd->dev.parent = priv->dev;
@ -830,17 +858,17 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
/* set up function call table */
if ((ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr))
& CSPR_PORT_SIZE_16)
chip->read_byte = fsl_ifc_read_byte16;
chip->legacy.read_byte = fsl_ifc_read_byte16;
else
chip->read_byte = fsl_ifc_read_byte;
chip->legacy.read_byte = fsl_ifc_read_byte;
chip->write_buf = fsl_ifc_write_buf;
chip->read_buf = fsl_ifc_read_buf;
chip->legacy.write_buf = fsl_ifc_write_buf;
chip->legacy.read_buf = fsl_ifc_read_buf;
chip->select_chip = fsl_ifc_select_chip;
chip->cmdfunc = fsl_ifc_cmdfunc;
chip->waitfunc = fsl_ifc_wait;
chip->set_features = nand_get_set_features_notsupp;
chip->get_features = nand_get_set_features_notsupp;
chip->legacy.cmdfunc = fsl_ifc_cmdfunc;
chip->legacy.waitfunc = fsl_ifc_wait;
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
chip->bbt_td = &bbt_main_descr;
chip->bbt_md = &bbt_mirror_descr;
@ -853,10 +881,10 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
if (ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr)
& CSPR_PORT_SIZE_16) {
chip->read_byte = fsl_ifc_read_byte16;
chip->legacy.read_byte = fsl_ifc_read_byte16;
chip->options |= NAND_BUSWIDTH_16;
} else {
chip->read_byte = fsl_ifc_read_byte;
chip->legacy.read_byte = fsl_ifc_read_byte;
}
chip->controller = &ifc_nand_ctrl->controller;
@ -914,8 +942,9 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
chip->ecc.algo = NAND_ECC_HAMMING;
}
if (ctrl->version >= FSL_IFC_VERSION_1_1_0)
fsl_ifc_sram_init(priv);
ret = fsl_ifc_sram_init(priv);
if (ret)
return ret;
/*
* As IFC version 2.0.0 has 16KB of internal SRAM as compared to older
@ -1051,7 +1080,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
goto err;
priv->chip.controller->ops = &fsl_ifc_controller_ops;
ret = nand_scan(mtd, 1);
ret = nand_scan(&priv->chip, 1);
if (ret)
goto err;
@ -1077,9 +1106,8 @@ err:
static int fsl_ifc_nand_remove(struct platform_device *dev)
{
struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev);
struct mtd_info *mtd = nand_to_mtd(&priv->chip);
nand_release(mtd);
nand_release(&priv->chip);
fsl_ifc_chip_remove(priv);
mutex_lock(&fsl_ifc_nand_mutex);

View File

@ -52,9 +52,9 @@ static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo)
chip);
}
static int fun_chip_ready(struct mtd_info *mtd)
static int fun_chip_ready(struct nand_chip *chip)
{
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
if (gpio_get_value(fun->rnb_gpio[fun->mchip_number]))
return 1;
@ -69,7 +69,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
struct mtd_info *mtd = nand_to_mtd(&fun->chip);
int cnt = 1000000;
while (--cnt && !fun_chip_ready(mtd))
while (--cnt && !fun_chip_ready(&fun->chip))
cpu_relax();
if (!cnt)
dev_err(fun->dev, "tired waiting for RNB\n");
@ -78,10 +78,9 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
}
}
static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void fun_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
u32 mar;
if (!(ctrl & fun->last_ctrl)) {
@ -102,51 +101,50 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
mar = (cmd << (32 - fun->upm.width)) |
fun->mchip_offsets[fun->mchip_number];
fsl_upm_run_pattern(&fun->upm, chip->IO_ADDR_R, mar);
fsl_upm_run_pattern(&fun->upm, chip->legacy.IO_ADDR_R, mar);
if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN)
fun_wait_rnb(fun);
}
static void fun_select_chip(struct mtd_info *mtd, int mchip_nr)
static void fun_select_chip(struct nand_chip *chip, int mchip_nr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
if (mchip_nr == -1) {
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
} else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) {
fun->mchip_number = mchip_nr;
chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr];
chip->IO_ADDR_W = chip->IO_ADDR_R;
chip->legacy.IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr];
chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R;
} else {
BUG();
}
}
static uint8_t fun_read_byte(struct mtd_info *mtd)
static uint8_t fun_read_byte(struct nand_chip *chip)
{
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
return in_8(fun->chip.IO_ADDR_R);
return in_8(fun->chip.legacy.IO_ADDR_R);
}
static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
int i;
for (i = 0; i < len; i++)
buf[i] = in_8(fun->chip.IO_ADDR_R);
buf[i] = in_8(fun->chip.legacy.IO_ADDR_R);
}
static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip));
int i;
for (i = 0; i < len; i++) {
out_8(fun->chip.IO_ADDR_W, buf[i]);
out_8(fun->chip.legacy.IO_ADDR_W, buf[i]);
if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE)
fun_wait_rnb(fun);
}
@ -162,20 +160,20 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
int ret;
struct device_node *flash_np;
fun->chip.IO_ADDR_R = fun->io_base;
fun->chip.IO_ADDR_W = fun->io_base;
fun->chip.cmd_ctrl = fun_cmd_ctrl;
fun->chip.chip_delay = fun->chip_delay;
fun->chip.read_byte = fun_read_byte;
fun->chip.read_buf = fun_read_buf;
fun->chip.write_buf = fun_write_buf;
fun->chip.legacy.IO_ADDR_R = fun->io_base;
fun->chip.legacy.IO_ADDR_W = fun->io_base;
fun->chip.legacy.cmd_ctrl = fun_cmd_ctrl;
fun->chip.legacy.chip_delay = fun->chip_delay;
fun->chip.legacy.read_byte = fun_read_byte;
fun->chip.legacy.read_buf = fun_read_buf;
fun->chip.legacy.write_buf = fun_write_buf;
fun->chip.ecc.mode = NAND_ECC_SOFT;
fun->chip.ecc.algo = NAND_ECC_HAMMING;
if (fun->mchip_count > 1)
fun->chip.select_chip = fun_select_chip;
if (fun->rnb_gpio[0] >= 0)
fun->chip.dev_ready = fun_chip_ready;
fun->chip.legacy.dev_ready = fun_chip_ready;
mtd->dev.parent = fun->dev;
@ -184,14 +182,14 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
return -ENODEV;
nand_set_flash_node(&fun->chip, flash_np);
mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start,
flash_np->name);
mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%pOFn", (u64)io_res->start,
flash_np);
if (!mtd->name) {
ret = -ENOMEM;
goto err;
}
ret = nand_scan(mtd, fun->mchip_count);
ret = nand_scan(&fun->chip, fun->mchip_count);
if (ret)
goto err;
@ -326,7 +324,7 @@ static int fun_remove(struct platform_device *ofdev)
struct mtd_info *mtd = nand_to_mtd(&fun->chip);
int i;
nand_release(mtd);
nand_release(&fun->chip);
kfree(mtd->name);
for (i = 0; i < fun->mchip_count; i++) {

View File

@ -340,10 +340,9 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
return 0;
}
static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
static int fsmc_setup_data_interface(struct nand_chip *nand, int csline,
const struct nand_data_interface *conf)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct fsmc_nand_data *host = nand_get_controller_data(nand);
struct fsmc_nand_timings tims;
const struct nand_sdr_timings *sdrt;
@ -368,9 +367,9 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
/*
* fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers
*/
static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
static void fsmc_enable_hwecc(struct nand_chip *chip, int mode)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip));
writel_relaxed(readl(host->regs_va + FSMC_PC) & ~FSMC_ECCPLEN_256,
host->regs_va + FSMC_PC);
@ -385,10 +384,10 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
* FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to
* max of 8-bits)
*/
static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
static int fsmc_read_hwecc_ecc4(struct nand_chip *chip, const uint8_t *data,
uint8_t *ecc)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip));
uint32_t ecc_tmp;
unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
@ -433,10 +432,10 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
* FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to
* max of 1-bit)
*/
static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
static int fsmc_read_hwecc_ecc1(struct nand_chip *chip, const uint8_t *data,
uint8_t *ecc)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip));
uint32_t ecc_tmp;
ecc_tmp = readl_relaxed(host->regs_va + ECC1);
@ -610,9 +609,9 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
}
/* fsmc_select_chip - assert or deassert nCE */
static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
static void fsmc_select_chip(struct nand_chip *chip, int chipnr)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip));
u32 pc;
/* Support only one CS */
@ -707,7 +706,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
/*
* fsmc_read_page_hwecc
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
@ -719,9 +717,10 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
* After this read, fsmc hardware generates and reports error data bits(up to a
* max of 8 bits)
*/
static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int fsmc_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int i, j, s, stat, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
@ -740,7 +739,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
nand_read_page_op(chip, page, s * eccsize, NULL, 0);
chip->ecc.hwctl(mtd, NAND_ECC_READ);
chip->ecc.hwctl(chip, NAND_ECC_READ);
nand_read_data_op(chip, p, eccsize, false);
for (j = 0; j < eccbytes;) {
@ -767,9 +766,9 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
memcpy(&ecc_code[i], oob, chip->ecc.bytes);
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
chip->ecc.calculate(chip, p, &ecc_calc[i]);
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]);
if (stat < 0) {
mtd->ecc_stats.failed++;
} else {
@ -791,11 +790,10 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* calc_ecc is a 104 bit information containing maximum of 8 error
* offset informations of 13 bits each in 512 bytes of read data.
*/
static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
static int fsmc_bch8_correct_data(struct nand_chip *chip, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip));
uint32_t err_idx[8];
uint32_t num_err, i;
uint32_t ecc1, ecc2, ecc3, ecc4;
@ -951,6 +949,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
nand->ecc.correct = nand_correct_data;
nand->ecc.bytes = 3;
nand->ecc.strength = 1;
nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER;
break;
case NAND_ECC_SOFT:
@ -1082,7 +1081,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
mtd->dev.parent = &pdev->dev;
nand->exec_op = fsmc_exec_op;
nand->select_chip = fsmc_select_chip;
nand->chip_delay = 30;
/*
* Setup default ECC mode. nand_dt_init() called from nand_scan_ident()
@ -1125,7 +1123,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
* Scan to find existence of the device
*/
nand->dummy_controller.ops = &fsmc_nand_controller_ops;
ret = nand_scan(mtd, 1);
ret = nand_scan(nand, 1);
if (ret)
goto release_dma_write_chan;
@ -1161,7 +1159,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
struct fsmc_nand_data *host = platform_get_drvdata(pdev);
if (host) {
nand_release(nand_to_mtd(&host->nand));
nand_release(&host->nand);
if (host->mode == USE_DMA_ACCESS) {
dma_release_channel(host->write_dma_chan);

View File

@ -73,9 +73,10 @@ static void gpio_nand_dosync(struct gpiomtd *gpiomtd)
static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {}
#endif
static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
gpio_nand_dosync(gpiomtd);
@ -89,13 +90,13 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
if (cmd == NAND_CMD_NONE)
return;
writeb(cmd, gpiomtd->nand_chip.IO_ADDR_W);
writeb(cmd, gpiomtd->nand_chip.legacy.IO_ADDR_W);
gpio_nand_dosync(gpiomtd);
}
static int gpio_nand_devready(struct mtd_info *mtd)
static int gpio_nand_devready(struct nand_chip *chip)
{
struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
return gpiod_get_value(gpiomtd->rdy);
}
@ -194,7 +195,7 @@ static int gpio_nand_remove(struct platform_device *pdev)
{
struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&gpiomtd->nand_chip));
nand_release(&gpiomtd->nand_chip);
/* Enable write protection and disable the chip */
if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
@ -224,9 +225,9 @@ static int gpio_nand_probe(struct platform_device *pdev)
chip = &gpiomtd->nand_chip;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
chip->IO_ADDR_R = devm_ioremap_resource(dev, res);
if (IS_ERR(chip->IO_ADDR_R))
return PTR_ERR(chip->IO_ADDR_R);
chip->legacy.IO_ADDR_R = devm_ioremap_resource(dev, res);
if (IS_ERR(chip->legacy.IO_ADDR_R))
return PTR_ERR(chip->legacy.IO_ADDR_R);
res = gpio_nand_get_io_sync(pdev);
if (res) {
@ -270,15 +271,15 @@ static int gpio_nand_probe(struct platform_device *pdev)
}
/* Using RDY pin */
if (gpiomtd->rdy)
chip->dev_ready = gpio_nand_devready;
chip->legacy.dev_ready = gpio_nand_devready;
nand_set_flash_node(chip, pdev->dev.of_node);
chip->IO_ADDR_W = chip->IO_ADDR_R;
chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
chip->options = gpiomtd->plat.options;
chip->chip_delay = gpiomtd->plat.chip_delay;
chip->cmd_ctrl = gpio_nand_cmd_ctrl;
chip->legacy.chip_delay = gpiomtd->plat.chip_delay;
chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl;
mtd = nand_to_mtd(chip);
mtd->dev.parent = dev;
@ -289,7 +290,7 @@ static int gpio_nand_probe(struct platform_device *pdev)
if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
gpiod_direction_output(gpiomtd->nwp, 1);
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
goto err_wp;

View File

@ -471,10 +471,9 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
udelay(dll_wait_time_us);
}
int gpmi_setup_data_interface(struct mtd_info *mtd, int chipnr,
int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
const struct nand_sdr_timings *sdr;

View File

@ -783,9 +783,8 @@ error_alloc:
return -ENOMEM;
}
static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
static void gpmi_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
int ret;
@ -817,17 +816,15 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
this->command_length = 0;
}
static int gpmi_dev_ready(struct mtd_info *mtd)
static int gpmi_dev_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
return gpmi_is_ready(this, this->current_chip);
}
static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
static void gpmi_select_chip(struct nand_chip *chip, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
int ret;
@ -859,9 +856,8 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
this->current_chip = chipnr;
}
static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void gpmi_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
dev_dbg(this->dev, "len is %d\n", len);
@ -869,9 +865,8 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
gpmi_read_data(this, buf, len);
}
static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void gpmi_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
dev_dbg(this->dev, "len is %d\n", len);
@ -879,13 +874,12 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
gpmi_send_data(this, buf, len);
}
static uint8_t gpmi_read_byte(struct mtd_info *mtd)
static uint8_t gpmi_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
uint8_t *buf = this->data_buffer_dma;
gpmi_read_buf(mtd, buf, 1);
gpmi_read_buf(chip, buf, 1);
return buf[0];
}
@ -1085,8 +1079,8 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
return max_bitflips;
}
static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int gpmi_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
nand_read_page_op(chip, page, 0, NULL, 0);
@ -1094,8 +1088,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
}
/* Fake a virtual small page for the subpage read */
static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offs, uint32_t len, uint8_t *buf, int page)
static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
uint32_t len, uint8_t *buf, int page)
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
void __iomem *bch_regs = this->resources.bch_regs;
@ -1130,7 +1124,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
dev_dbg(this->dev,
"page:%d, first:%d, last:%d, marker at:%d\n",
page, first, last, marker_pos);
return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
return gpmi_ecc_read_page(chip, buf, 0, page);
}
}
@ -1182,9 +1176,10 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
return max_bitflips;
}
static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int gpmi_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
const void *payload_virt;
@ -1324,9 +1319,9 @@ exit_auxiliary:
* ECC-based or raw view of the page is implicit in which function it calls
* (there is a similar pair of ECC-based/raw functions for writing).
*/
static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int gpmi_ecc_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
dev_dbg(this->dev, "page number is %d\n", page);
@ -1335,7 +1330,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
/* Read out the conventional OOB. */
nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
/*
* Now, we want to make sure the block mark is correct. In the
@ -1345,15 +1340,15 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
if (GPMI_IS_MX23(this)) {
/* Read the block mark into the first byte of the OOB buffer. */
nand_read_page_op(chip, page, 0, NULL, 0);
chip->oob_poi[0] = chip->read_byte(mtd);
chip->oob_poi[0] = chip->legacy.read_byte(chip);
}
return 0;
}
static int
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
static int gpmi_ecc_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtd_oob_region of = { };
/* Do we have available oob area? */
@ -1380,10 +1375,10 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
* See set_geometry_by_ecc_info inline comments to have a full description
* of the layout used by the GPMI controller.
*/
static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf,
static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
int eccsize = nfc_geo->ecc_chunk_size;
@ -1464,11 +1459,10 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
* See set_geometry_by_ecc_info inline comments to have a full description
* of the layout used by the GPMI controller.
*/
static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
static int gpmi_ecc_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
int eccsize = nfc_geo->ecc_chunk_size;
@ -1536,28 +1530,26 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
mtd->writesize + mtd->oobsize);
}
static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int gpmi_ecc_read_oob_raw(struct nand_chip *chip, int page)
{
return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page);
return gpmi_ecc_read_page_raw(chip, NULL, 1, page);
}
static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int gpmi_ecc_write_oob_raw(struct nand_chip *chip, int page)
{
return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
return gpmi_ecc_write_page_raw(chip, NULL, 1, page);
}
static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
static int gpmi_block_markbad(struct nand_chip *chip, loff_t ofs)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
int ret = 0;
uint8_t *block_mark;
int column, page, chipnr;
chipnr = (int)(ofs >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
chip->select_chip(chip, chipnr);
column = !GPMI_IS_MX23(this) ? mtd->writesize : 0;
@ -1570,7 +1562,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
ret = nand_prog_page_op(chip, page, column, block_mark, 1);
chip->select_chip(mtd, -1);
chip->select_chip(chip, -1);
return ret;
}
@ -1607,7 +1599,6 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
struct boot_rom_geometry *rom_geo = &this->rom_geometry;
struct device *dev = this->dev;
struct nand_chip *chip = &this->nand;
struct mtd_info *mtd = nand_to_mtd(chip);
unsigned int search_area_size_in_strides;
unsigned int stride;
unsigned int page;
@ -1619,7 +1610,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
saved_chip_number = this->current_chip;
chip->select_chip(mtd, 0);
chip->select_chip(chip, 0);
/*
* Loop through the first search area, looking for the NCB fingerprint.
@ -1637,7 +1628,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
* and starts in the 12th byte of the page.
*/
nand_read_page_op(chip, page, 12, NULL, 0);
chip->read_buf(mtd, buffer, strlen(fingerprint));
chip->legacy.read_buf(chip, buffer, strlen(fingerprint));
/* Look for the fingerprint. */
if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
@ -1647,7 +1638,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
}
chip->select_chip(mtd, saved_chip_number);
chip->select_chip(chip, saved_chip_number);
if (found_an_ncb_fingerprint)
dev_dbg(dev, "\tFound a fingerprint\n");
@ -1690,7 +1681,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Select chip 0. */
saved_chip_number = this->current_chip;
chip->select_chip(mtd, 0);
chip->select_chip(chip, 0);
/* Loop over blocks in the first search area, erasing them. */
dev_dbg(dev, "Erasing the search area...\n");
@ -1716,13 +1707,13 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
status = chip->ecc.write_page_raw(chip, buffer, 0, page);
if (status)
dev_err(dev, "[%s] Write failed.\n", __func__);
}
/* Deselect chip 0. */
chip->select_chip(mtd, saved_chip_number);
chip->select_chip(chip, saved_chip_number);
return 0;
}
@ -1771,10 +1762,10 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
byte = block << chip->phys_erase_shift;
/* Send the command to read the conventional block mark. */
chip->select_chip(mtd, chipnr);
chip->select_chip(chip, chipnr);
nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
block_mark = chip->read_byte(mtd);
chip->select_chip(mtd, -1);
block_mark = chip->legacy.read_byte(chip);
chip->select_chip(chip, -1);
/*
* Check if the block is marked bad. If so, we need to mark it
@ -1783,7 +1774,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
*/
if (block_mark != 0xff) {
dev_dbg(dev, "Transcribing mark in block %u\n", block);
ret = chip->block_markbad(mtd, byte);
ret = chip->legacy.block_markbad(chip, byte);
if (ret)
dev_err(dev,
"Failed to mark block bad with ret %d\n",
@ -1911,13 +1902,13 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
nand_set_flash_node(chip, this->pdev->dev.of_node);
chip->select_chip = gpmi_select_chip;
chip->setup_data_interface = gpmi_setup_data_interface;
chip->cmd_ctrl = gpmi_cmd_ctrl;
chip->dev_ready = gpmi_dev_ready;
chip->read_byte = gpmi_read_byte;
chip->read_buf = gpmi_read_buf;
chip->write_buf = gpmi_write_buf;
chip->legacy.cmd_ctrl = gpmi_cmd_ctrl;
chip->legacy.dev_ready = gpmi_dev_ready;
chip->legacy.read_byte = gpmi_read_byte;
chip->legacy.read_buf = gpmi_read_buf;
chip->legacy.write_buf = gpmi_write_buf;
chip->badblock_pattern = &gpmi_bbt_descr;
chip->block_markbad = gpmi_block_markbad;
chip->legacy.block_markbad = gpmi_block_markbad;
chip->options |= NAND_NO_SUBPAGE_WRITE;
/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
@ -1934,7 +1925,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
goto err_out;
chip->dummy_controller.ops = &gpmi_nand_controller_ops;
ret = nand_scan(mtd, GPMI_IS_MX6(this) ? 2 : 1);
ret = nand_scan(chip, GPMI_IS_MX6(this) ? 2 : 1);
if (ret)
goto err_out;
@ -2026,7 +2017,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
{
struct gpmi_nand_data *this = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&this->nand));
nand_release(&this->nand);
gpmi_free_dma_buffer(this);
release_resources(this);
return 0;

View File

@ -178,7 +178,7 @@ int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
int gpmi_send_command(struct gpmi_nand_data *);
int gpmi_enable_clk(struct gpmi_nand_data *this);
int gpmi_disable_clk(struct gpmi_nand_data *this);
int gpmi_setup_data_interface(struct mtd_info *mtd, int chipnr,
int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf);
void gpmi_nfc_apply_timings(struct gpmi_nand_data *this);
int gpmi_read_data(struct gpmi_nand_data *, void *buf, int len);

View File

@ -353,9 +353,8 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect)
return 0;
}
static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
static void hisi_nfc_select_chip(struct nand_chip *chip, int chipselect)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hinfc_host *host = nand_get_controller_data(chip);
if (chipselect < 0)
@ -364,9 +363,8 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
host->chipselect = chipselect;
}
static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
static uint8_t hisi_nfc_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hinfc_host *host = nand_get_controller_data(chip);
if (host->command == NAND_CMD_STATUS)
@ -380,28 +378,17 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
return *(uint8_t *)(host->buffer + host->offset - 1);
}
static u16 hisi_nfc_read_word(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hinfc_host *host = nand_get_controller_data(chip);
host->offset += 2;
return *(u16 *)(host->buffer + host->offset - 2);
}
static void
hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
hisi_nfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hinfc_host *host = nand_get_controller_data(chip);
memcpy(host->buffer + host->offset, buf, len);
host->offset += len;
}
static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void hisi_nfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hinfc_host *host = nand_get_controller_data(chip);
memcpy(buf, host->buffer + host->offset, len);
@ -442,10 +429,10 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
}
}
static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column,
int page_addr)
static void hisi_nfc_cmdfunc(struct nand_chip *chip, unsigned command,
int column, int page_addr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct hinfc_host *host = nand_get_controller_data(chip);
int is_cache_invalid = 1;
unsigned int flag = 0;
@ -537,15 +524,16 @@ static irqreturn_t hinfc_irq_handle(int irq, void *devid)
return IRQ_HANDLED;
}
static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
static int hisi_nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct hinfc_host *host = nand_get_controller_data(chip);
int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc;
int stat_1, stat_2;
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
/* errors which can not be corrected by ECC */
if (host->irq_status & HINFC504_INTS_UE) {
@ -569,9 +557,9 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
return max_bitflips;
}
static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int hisi_nand_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct hinfc_host *host = nand_get_controller_data(chip);
nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
@ -585,13 +573,15 @@ static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
static int hisi_nand_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, int oob_required,
int page)
static int hisi_nand_write_page_hwecc(struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -792,15 +782,14 @@ static int hisi_nfc_probe(struct platform_device *pdev)
nand_set_controller_data(chip, host);
nand_set_flash_node(chip, np);
chip->cmdfunc = hisi_nfc_cmdfunc;
chip->legacy.cmdfunc = hisi_nfc_cmdfunc;
chip->select_chip = hisi_nfc_select_chip;
chip->read_byte = hisi_nfc_read_byte;
chip->read_word = hisi_nfc_read_word;
chip->write_buf = hisi_nfc_write_buf;
chip->read_buf = hisi_nfc_read_buf;
chip->chip_delay = HINFC504_CHIP_DELAY;
chip->set_features = nand_get_set_features_notsupp;
chip->get_features = nand_get_set_features_notsupp;
chip->legacy.read_byte = hisi_nfc_read_byte;
chip->legacy.write_buf = hisi_nfc_write_buf;
chip->legacy.read_buf = hisi_nfc_read_buf;
chip->legacy.chip_delay = HINFC504_CHIP_DELAY;
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
hisi_nfc_host_init(host);
@ -811,7 +800,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
}
chip->dummy_controller.ops = &hisi_nfc_controller_ops;
ret = nand_scan(mtd, max_chips);
ret = nand_scan(chip, max_chips);
if (ret)
return ret;
@ -828,9 +817,8 @@ static int hisi_nfc_probe(struct platform_device *pdev)
static int hisi_nfc_remove(struct platform_device *pdev)
{
struct hinfc_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = nand_to_mtd(&host->chip);
nand_release(mtd);
nand_release(&host->chip);
return 0;
}

View File

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018 - Bootlin
*
* Author: Boris Brezillon <boris.brezillon@bootlin.com>
*
* Header containing internal definitions to be used only by core files.
* NAND controller drivers should not include this file.
*/
#ifndef __LINUX_RAWNAND_INTERNALS
#define __LINUX_RAWNAND_INTERNALS
#include <linux/mtd/rawnand.h>
/*
* NAND Flash Manufacturer ID Codes
*/
#define NAND_MFR_AMD 0x01
#define NAND_MFR_ATO 0x9b
#define NAND_MFR_EON 0x92
#define NAND_MFR_ESMT 0xc8
#define NAND_MFR_FUJITSU 0x04
#define NAND_MFR_HYNIX 0xad
#define NAND_MFR_INTEL 0x89
#define NAND_MFR_MACRONIX 0xc2
#define NAND_MFR_MICRON 0x2c
#define NAND_MFR_NATIONAL 0x8f
#define NAND_MFR_RENESAS 0x07
#define NAND_MFR_SAMSUNG 0xec
#define NAND_MFR_SANDISK 0x45
#define NAND_MFR_STMICRO 0x20
#define NAND_MFR_TOSHIBA 0x98
#define NAND_MFR_WINBOND 0xef
/**
* struct nand_manufacturer_ops - NAND Manufacturer operations
* @detect: detect the NAND memory organization and capabilities
* @init: initialize all vendor specific fields (like the ->read_retry()
* implementation) if any.
* @cleanup: the ->init() function may have allocated resources, ->cleanup()
* is here to let vendor specific code release those resources.
* @fixup_onfi_param_page: apply vendor specific fixups to the ONFI parameter
* page. This is called after the checksum is verified.
*/
struct nand_manufacturer_ops {
void (*detect)(struct nand_chip *chip);
int (*init)(struct nand_chip *chip);
void (*cleanup)(struct nand_chip *chip);
void (*fixup_onfi_param_page)(struct nand_chip *chip,
struct nand_onfi_params *p);
};
/**
* struct nand_manufacturer - NAND Flash Manufacturer structure
* @name: Manufacturer name
* @id: manufacturer ID code of device.
* @ops: manufacturer operations
*/
struct nand_manufacturer {
int id;
char *name;
const struct nand_manufacturer_ops *ops;
};
extern struct nand_flash_dev nand_flash_ids[];
extern const struct nand_manufacturer_ops amd_nand_manuf_ops;
extern const struct nand_manufacturer_ops esmt_nand_manuf_ops;
extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
extern const struct nand_manufacturer_ops macronix_nand_manuf_ops;
extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
/* Core functions */
const struct nand_manufacturer *nand_get_manufacturer(u8 id);
int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
int allowbbt);
int onfi_fill_data_interface(struct nand_chip *chip,
enum nand_data_interface_type type,
int timing_mode);
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_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
int oob_required, int page);
int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf,
int oob_required, int page);
int nand_exit_status_op(struct nand_chip *chip);
int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
unsigned int len);
void nand_decode_ext_id(struct nand_chip *chip);
void panic_nand_wait(struct nand_chip *chip, unsigned long timeo);
void sanitize_string(uint8_t *s, size_t len);
/* BBT functions */
int nand_markbad_bbt(struct nand_chip *chip, loff_t offs);
int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs);
int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt);
/* Legacy */
void nand_legacy_set_defaults(struct nand_chip *chip);
void nand_legacy_adjust_cmdfunc(struct nand_chip *chip);
int nand_legacy_check_hooks(struct nand_chip *chip);
/* ONFI functions */
u16 onfi_crc16(u16 crc, u8 const *p, size_t len);
int nand_onfi_detect(struct nand_chip *chip);
/* JEDEC functions */
int nand_jedec_detect(struct nand_chip *chip);
#endif /* __LINUX_RAWNAND_INTERNALS */

View File

@ -78,10 +78,9 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
return container_of(mtd_to_nand(mtd), struct jz_nand, chip);
}
static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
static void jz_nand_select_chip(struct nand_chip *chip, int chipnr)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct nand_chip *chip = mtd_to_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
uint32_t ctrl;
int banknr;
@ -92,18 +91,18 @@ static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
banknr = -1;
} else {
banknr = nand->banks[chipnr] - 1;
chip->IO_ADDR_R = nand->bank_base[banknr];
chip->IO_ADDR_W = nand->bank_base[banknr];
chip->legacy.IO_ADDR_R = nand->bank_base[banknr];
chip->legacy.IO_ADDR_W = nand->bank_base[banknr];
}
writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
nand->selected_bank = banknr;
}
static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
static void jz_nand_cmd_ctrl(struct nand_chip *chip, int dat,
unsigned int ctrl)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct nand_chip *chip = mtd_to_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
uint32_t reg;
void __iomem *bank_base = nand->bank_base[nand->selected_bank];
@ -115,7 +114,7 @@ static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
bank_base += JZ_NAND_MEM_ADDR_OFFSET;
else if (ctrl & NAND_CLE)
bank_base += JZ_NAND_MEM_CMD_OFFSET;
chip->IO_ADDR_W = bank_base;
chip->legacy.IO_ADDR_W = bank_base;
reg = readl(nand->base + JZ_REG_NAND_CTRL);
if (ctrl & NAND_NCE)
@ -125,18 +124,18 @@ static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
writel(reg, nand->base + JZ_REG_NAND_CTRL);
}
if (dat != NAND_CMD_NONE)
writeb(dat, chip->IO_ADDR_W);
writeb(dat, chip->legacy.IO_ADDR_W);
}
static int jz_nand_dev_ready(struct mtd_info *mtd)
static int jz_nand_dev_ready(struct nand_chip *chip)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
return gpiod_get_value_cansleep(nand->busy_gpio);
}
static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
static void jz_nand_hwctl(struct nand_chip *chip, int mode)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
uint32_t reg;
writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
@ -162,10 +161,10 @@ static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
}
static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
static int jz_nand_calculate_ecc_rs(struct nand_chip *chip, const uint8_t *dat,
uint8_t *ecc_code)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
uint32_t reg, status;
int i;
unsigned int timeout = 1000;
@ -215,10 +214,10 @@ static void jz_nand_correct_data(uint8_t *dat, int index, int mask)
dat[index+1] = (data >> 8) & 0xff;
}
static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip));
int i, error_count, index;
uint32_t reg, status, error;
unsigned int timeout = 1000;
@ -331,19 +330,19 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
if (chipnr == 0) {
/* Detect first chip. */
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
goto notfound_id;
/* Retrieve the IDs from the first chip. */
chip->select_chip(mtd, 0);
chip->select_chip(chip, 0);
nand_reset_op(chip);
nand_readid_op(chip, 0, id, sizeof(id));
*nand_maf_id = id[0];
*nand_dev_id = id[1];
} else {
/* Detect additional chip. */
chip->select_chip(mtd, chipnr);
chip->select_chip(chip, chipnr);
nand_reset_op(chip);
nand_readid_op(chip, 0, id, sizeof(id));
if (*nand_maf_id != id[0] || *nand_dev_id != id[1]) {
@ -426,13 +425,13 @@ static int jz_nand_probe(struct platform_device *pdev)
chip->ecc.strength = 4;
chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
chip->chip_delay = 50;
chip->cmd_ctrl = jz_nand_cmd_ctrl;
chip->legacy.chip_delay = 50;
chip->legacy.cmd_ctrl = jz_nand_cmd_ctrl;
chip->select_chip = jz_nand_select_chip;
chip->dummy_controller.ops = &jz_nand_controller_ops;
if (nand->busy_gpio)
chip->dev_ready = jz_nand_dev_ready;
chip->legacy.dev_ready = jz_nand_dev_ready;
platform_set_drvdata(pdev, nand);
@ -507,7 +506,7 @@ static int jz_nand_remove(struct platform_device *pdev)
struct jz_nand *nand = platform_get_drvdata(pdev);
size_t i;
nand_release(nand_to_mtd(&nand->chip));
nand_release(&nand->chip);
/* Deassert and disable all chips */
writel(0, nand->base + JZ_REG_NAND_CTRL);

View File

@ -71,9 +71,9 @@ static inline struct jz4780_nand_controller
return container_of(ctrl, struct jz4780_nand_controller, controller);
}
static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr)
static void jz4780_nand_select_chip(struct nand_chip *chip, int chipnr)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
struct jz4780_nand_cs *cs;
@ -86,10 +86,10 @@ static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr)
nfc->selected = chipnr;
}
static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void jz4780_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
struct jz4780_nand_cs *cs;
@ -109,24 +109,24 @@ static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
writeb(cmd, cs->base + OFFSET_CMD);
}
static int jz4780_nand_dev_ready(struct mtd_info *mtd)
static int jz4780_nand_dev_ready(struct nand_chip *chip)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
return !gpiod_get_value_cansleep(nand->busy_gpio);
}
static void jz4780_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
static void jz4780_nand_ecc_hwctl(struct nand_chip *chip, int mode)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
nand->reading = (mode == NAND_ECC_READ);
}
static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat,
static int jz4780_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat,
u8 *ecc_code)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
struct jz4780_bch_params params;
@ -144,10 +144,10 @@ static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat,
return jz4780_bch_calculate(nfc->bch, &params, dat, ecc_code);
}
static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
static int jz4780_nand_ecc_correct(struct nand_chip *chip, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
{
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd);
struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip));
struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller);
struct jz4780_bch_params params;
@ -256,7 +256,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
dev_err(dev, "failed to request busy GPIO: %d\n", ret);
return ret;
} else if (nand->busy_gpio) {
nand->chip.dev_ready = jz4780_nand_dev_ready;
nand->chip.legacy.dev_ready = jz4780_nand_dev_ready;
}
nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
@ -275,24 +275,24 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
return -ENOMEM;
mtd->dev.parent = dev;
chip->IO_ADDR_R = cs->base + OFFSET_DATA;
chip->IO_ADDR_W = cs->base + OFFSET_DATA;
chip->chip_delay = RB_DELAY_US;
chip->legacy.IO_ADDR_R = cs->base + OFFSET_DATA;
chip->legacy.IO_ADDR_W = cs->base + OFFSET_DATA;
chip->legacy.chip_delay = RB_DELAY_US;
chip->options = NAND_NO_SUBPAGE_WRITE;
chip->select_chip = jz4780_nand_select_chip;
chip->cmd_ctrl = jz4780_nand_cmd_ctrl;
chip->legacy.cmd_ctrl = jz4780_nand_cmd_ctrl;
chip->ecc.mode = NAND_ECC_HW;
chip->controller = &nfc->controller;
nand_set_flash_node(chip, np);
chip->controller->ops = &jz4780_nand_controller_ops;
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
return ret;
ret = mtd_device_register(mtd, NULL, 0);
if (ret) {
nand_release(mtd);
nand_release(chip);
return ret;
}
@ -307,7 +307,7 @@ static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc)
while (!list_empty(&nfc->chips)) {
chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list);
nand_release(nand_to_mtd(&chip->chip));
nand_release(&chip->chip);
list_del(&chip->chip_list);
}
}
@ -352,7 +352,7 @@ static int jz4780_nand_probe(struct platform_device *pdev)
return -ENODEV;
}
nfc = devm_kzalloc(dev, sizeof(*nfc) + (sizeof(nfc->cs[0]) * num_banks), GFP_KERNEL);
nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL);
if (!nfc)
return -ENOMEM;

View File

@ -286,10 +286,9 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
/*
* Hardware specific access to control lines
*/
static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void lpc32xx_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
if (cmd != NAND_CMD_NONE) {
@ -303,9 +302,8 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/*
* Read Device Ready (NAND device _and_ controller ready)
*/
static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
static int lpc32xx_nand_device_ready(struct nand_chip *nand_chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
if ((readb(MLC_ISR(host->io_base)) &
@ -330,8 +328,9 @@ static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host)
return IRQ_HANDLED;
}
static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip)
static int lpc32xx_waitfunc_nand(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY)
@ -349,9 +348,9 @@ exit:
return NAND_STATUS_READY;
}
static int lpc32xx_waitfunc_controller(struct mtd_info *mtd,
struct nand_chip *chip)
static int lpc32xx_waitfunc_controller(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY)
@ -369,10 +368,10 @@ exit:
return NAND_STATUS_READY;
}
static int lpc32xx_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
static int lpc32xx_waitfunc(struct nand_chip *chip)
{
lpc32xx_waitfunc_nand(mtd, chip);
lpc32xx_waitfunc_controller(mtd, chip);
lpc32xx_waitfunc_nand(chip);
lpc32xx_waitfunc_controller(chip);
return NAND_STATUS_READY;
}
@ -442,9 +441,10 @@ out1:
return -ENXIO;
}
static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
int i, j;
uint8_t *oobbuf = chip->oob_poi;
@ -470,7 +470,7 @@ static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
writeb(0x00, MLC_ECC_AUTO_DEC_REG(host->io_base));
/* Wait for Controller Ready */
lpc32xx_waitfunc_controller(mtd, chip);
lpc32xx_waitfunc_controller(chip);
/* Check ECC Error status */
mlc_isr = readl(MLC_ISR(host->io_base));
@ -507,11 +507,11 @@ static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip,
static int lpc32xx_write_page_lowlevel(struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
const uint8_t *oobbuf = chip->oob_poi;
uint8_t *dma_buf = (uint8_t *)buf;
@ -551,32 +551,30 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
writeb(0x00, MLC_ECC_AUTO_ENC_REG(host->io_base));
/* Wait for Controller Ready */
lpc32xx_waitfunc_controller(mtd, chip);
lpc32xx_waitfunc_controller(chip);
}
return nand_prog_page_end_op(chip);
}
static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int lpc32xx_read_oob(struct nand_chip *chip, int page)
{
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
/* Read whole page - necessary with MLC controller! */
lpc32xx_read_page(mtd, chip, host->dummy_buf, 1, page);
lpc32xx_read_page(chip, host->dummy_buf, 1, page);
return 0;
}
static int lpc32xx_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int lpc32xx_write_oob(struct nand_chip *chip, int page)
{
/* None, write_oob conflicts with the automatic LPC MLC ECC decoder! */
return 0;
}
/* Prepares MLC for transfers with H/W ECC enabled: always enabled anyway */
static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode)
static void lpc32xx_ecc_enable(struct nand_chip *chip, int mode)
{
/* Always enabled! */
}
@ -741,11 +739,11 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
if (res)
goto put_clk;
nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
nand_chip->dev_ready = lpc32xx_nand_device_ready;
nand_chip->chip_delay = 25; /* us */
nand_chip->IO_ADDR_R = MLC_DATA(host->io_base);
nand_chip->IO_ADDR_W = MLC_DATA(host->io_base);
nand_chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl;
nand_chip->legacy.dev_ready = lpc32xx_nand_device_ready;
nand_chip->legacy.chip_delay = 25; /* us */
nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base);
nand_chip->legacy.IO_ADDR_W = MLC_DATA(host->io_base);
/* Init NAND controller */
lpc32xx_nand_setup(host);
@ -762,7 +760,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
nand_chip->ecc.read_oob = lpc32xx_read_oob;
nand_chip->ecc.strength = 4;
nand_chip->ecc.bytes = 10;
nand_chip->waitfunc = lpc32xx_waitfunc;
nand_chip->legacy.waitfunc = lpc32xx_waitfunc;
nand_chip->options = NAND_NO_SUBPAGE_WRITE;
nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
@ -802,7 +800,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
* SMALL block or LARGE block.
*/
nand_chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
res = nand_scan(mtd, 1);
res = nand_scan(nand_chip, 1);
if (res)
goto free_irq;
@ -839,9 +837,8 @@ free_gpio:
static int lpc32xx_nand_remove(struct platform_device *pdev)
{
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
nand_release(mtd);
nand_release(&host->nand_chip);
free_irq(host->irq, host);
if (use_dma)
dma_release_channel(host->dma_chan);

View File

@ -278,11 +278,10 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
/*
* Hardware specific access to control lines
*/
static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void lpc32xx_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
uint32_t tmp;
struct nand_chip *chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
/* Does CE state need to be changed? */
@ -304,9 +303,8 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/*
* Read the Device Ready pin
*/
static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
static int lpc32xx_nand_device_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
int rdy = 0;
@ -337,7 +335,7 @@ static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
/*
* Prepares SLC for transfers with H/W ECC enabled
*/
static void lpc32xx_nand_ecc_enable(struct mtd_info *mtd, int mode)
static void lpc32xx_nand_ecc_enable(struct nand_chip *chip, int mode)
{
/* Hardware ECC is enabled automatically in hardware as needed */
}
@ -345,7 +343,7 @@ static void lpc32xx_nand_ecc_enable(struct mtd_info *mtd, int mode)
/*
* Calculates the ECC for the data
*/
static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
static int lpc32xx_nand_ecc_calculate(struct nand_chip *chip,
const unsigned char *buf,
unsigned char *code)
{
@ -359,9 +357,8 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
/*
* Read a single byte from NAND device
*/
static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
static uint8_t lpc32xx_nand_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
return (uint8_t)readl(SLC_DATA(host->io_base));
@ -370,9 +367,8 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
/*
* Simple device read without ECC
*/
static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void lpc32xx_nand_read_buf(struct nand_chip *chip, u_char *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
/* Direct device read with no ECC */
@ -383,9 +379,9 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
/*
* Simple device write without ECC
*/
static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void lpc32xx_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
/* Direct device write with no ECC */
@ -396,18 +392,20 @@ static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int
/*
* Read the OOB data from the device without ECC using FIFO method
*/
static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int lpc32xx_nand_read_oob_syndrome(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
}
/*
* Write the OOB data to the device without ECC using FIFO method
*/
static int lpc32xx_nand_write_oob_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int lpc32xx_nand_write_oob_syndrome(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
mtd->oobsize);
}
@ -610,10 +608,10 @@ static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages,
* Read the data and OOB data from the device, use ECC correction with the
* data, disable ECC for the OOB data
*/
static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf,
static int lpc32xx_nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
struct mtd_oob_region oobregion = { };
int stat, i, status, error;
@ -626,7 +624,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1);
/* Get OOB data */
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
/* Convert to stored ECC format */
lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps);
@ -639,7 +637,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
oobecc = chip->oob_poi + oobregion.offset;
for (i = 0; i < chip->ecc.steps; i++) {
stat = chip->ecc.correct(mtd, buf, oobecc,
stat = chip->ecc.correct(chip, buf, oobecc,
&tmpecc[i * chip->ecc.bytes]);
if (stat < 0)
mtd->ecc_stats.failed++;
@ -657,17 +655,18 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
* Read the data and OOB data from the device, no ECC correction with the
* data or OOB data
*/
static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
static int lpc32xx_nand_read_page_raw_syndrome(struct nand_chip *chip,
uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Issue read command */
nand_read_page_op(chip, page, 0, NULL, 0);
/* Raw reads can just use the FIFO interface */
chip->read_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, buf, chip->ecc.size * chip->ecc.steps);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
return 0;
}
@ -676,11 +675,11 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd,
* Write the data and OOB data to the device, use ECC with the data,
* disable ECC for the OOB data
*/
static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
static int lpc32xx_nand_write_page_syndrome(struct nand_chip *chip,
const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
struct mtd_oob_region oobregion = { };
uint8_t *pb;
@ -705,7 +704,7 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps);
/* Write ECC data to device */
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -714,15 +713,16 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
* Write the data and OOB data to the device, no ECC correction with the
* data or OOB data
*/
static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
static int lpc32xx_nand_write_page_raw_syndrome(struct nand_chip *chip,
const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Raw writes can just use the FIFO interface */
nand_prog_page_begin_op(chip, page, 0, buf,
chip->ecc.size * chip->ecc.steps);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -878,11 +878,11 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
goto enable_wp;
/* Set NAND IO addresses and command/ready functions */
chip->IO_ADDR_R = SLC_DATA(host->io_base);
chip->IO_ADDR_W = SLC_DATA(host->io_base);
chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
chip->dev_ready = lpc32xx_nand_device_ready;
chip->chip_delay = 20; /* 20us command delay time */
chip->legacy.IO_ADDR_R = SLC_DATA(host->io_base);
chip->legacy.IO_ADDR_W = SLC_DATA(host->io_base);
chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl;
chip->legacy.dev_ready = lpc32xx_nand_device_ready;
chip->legacy.chip_delay = 20; /* 20us command delay time */
/* Init NAND controller */
lpc32xx_nand_setup(host);
@ -891,9 +891,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
/* NAND callbacks for LPC32xx SLC hardware */
chip->ecc.mode = NAND_ECC_HW_SYNDROME;
chip->read_byte = lpc32xx_nand_read_byte;
chip->read_buf = lpc32xx_nand_read_buf;
chip->write_buf = lpc32xx_nand_write_buf;
chip->legacy.read_byte = lpc32xx_nand_read_byte;
chip->legacy.read_buf = lpc32xx_nand_read_buf;
chip->legacy.write_buf = lpc32xx_nand_write_buf;
chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
@ -925,7 +925,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
/* Find NAND device */
chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
res = nand_scan(mtd, 1);
res = nand_scan(chip, 1);
if (res)
goto release_dma;
@ -956,9 +956,8 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
{
uint32_t tmp;
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
nand_release(mtd);
nand_release(&host->nand_chip);
dma_release_channel(host->dma_chan);
/* Force CE high */

View File

@ -5,6 +5,73 @@
* Copyright (C) 2017 Marvell
* Author: Miquel RAYNAL <miquel.raynal@free-electrons.com>
*
*
* This NAND controller driver handles two versions of the hardware,
* one is called NFCv1 and is available on PXA SoCs and the other is
* called NFCv2 and is available on Armada SoCs.
*
* The main visible difference is that NFCv1 only has Hamming ECC
* capabilities, while NFCv2 also embeds a BCH ECC engine. Also, DMA
* is not used with NFCv2.
*
* The ECC layouts are depicted in details in Marvell AN-379, but here
* is a brief description.
*
* When using Hamming, the data is split in 512B chunks (either 1, 2
* or 4) and each chunk will have its own ECC "digest" of 6B at the
* beginning of the OOB area and eventually the remaining free OOB
* bytes (also called "spare" bytes in the driver). This engine
* corrects up to 1 bit per chunk and detects reliably an error if
* there are at most 2 bitflips. Here is the page layout used by the
* controller when Hamming is chosen:
*
* +-------------------------------------------------------------+
* | Data 1 | ... | Data N | ECC 1 | ... | ECCN | Free OOB bytes |
* +-------------------------------------------------------------+
*
* When using the BCH engine, there are N identical (data + free OOB +
* ECC) sections and potentially an extra one to deal with
* configurations where the chosen (data + free OOB + ECC) sizes do
* not align with the page (data + OOB) size. ECC bytes are always
* 30B per ECC chunk. Here is the page layout used by the controller
* when BCH is chosen:
*
* +-----------------------------------------
* | Data 1 | Free OOB bytes 1 | ECC 1 | ...
* +-----------------------------------------
*
* -------------------------------------------
* ... | Data N | Free OOB bytes N | ECC N |
* -------------------------------------------
*
* --------------------------------------------+
* Last Data | Last Free OOB bytes | Last ECC |
* --------------------------------------------+
*
* In both cases, the layout seen by the user is always: all data
* first, then all free OOB bytes and finally all ECC bytes. With BCH,
* ECC bytes are 30B long and are padded with 0xFF to align on 32
* bytes.
*
* The controller has certain limitations that are handled by the
* driver:
* - It can only read 2k at a time. To overcome this limitation, the
* driver issues data cycles on the bus, without issuing new
* CMD + ADDR cycles. The Marvell term is "naked" operations.
* - The ECC strength in BCH mode cannot be tuned. It is fixed 16
* bits. What can be tuned is the ECC block size as long as it
* stays between 512B and 2kiB. It's usually chosen based on the
* chip ECC requirements. For instance, using 2kiB ECC chunks
* provides 4b/512B correctability.
* - The controller will always treat data bytes, free OOB bytes
* and ECC bytes in that order, no matter what the real layout is
* (which is usually all data then all OOB bytes). The
* marvell_nfc_layouts array below contains the currently
* supported layouts.
* - Because of these weird layouts, the Bad Block Markers can be
* located in data section. In this case, the NAND_BBT_NO_OOB_BBM
* option must be set to prevent scanning/writing bad block
* markers.
*/
#include <linux/module.h>
@ -217,8 +284,11 @@ static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = {
MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30),
MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
MARVELL_LAYOUT( 8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0),
MARVELL_LAYOUT( 8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30),
};
/**
@ -634,9 +704,8 @@ static int marvell_nfc_wait_op(struct nand_chip *chip, unsigned int timeout_ms)
return 0;
}
static void marvell_nfc_select_chip(struct mtd_info *mtd, int die_nr)
static void marvell_nfc_select_chip(struct nand_chip *chip, int die_nr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
u32 ndcr_generic;
@ -686,7 +755,7 @@ static irqreturn_t marvell_nfc_isr(int irq, void *dev_id)
marvell_nfc_disable_int(nfc, st & NDCR_ALL_INT);
if (!(st & (NDSR_RDDREQ | NDSR_WRDREQ | NDSR_WRCMDREQ)))
if (st & (NDSR_RDY(0) | NDSR_RDY(1)))
complete(&nfc->complete);
return IRQ_HANDLED;
@ -959,18 +1028,15 @@ static int marvell_nfc_hw_ecc_hmg_do_read_page(struct nand_chip *chip,
return ret;
}
static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
return marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi,
true, page);
}
static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd,
struct nand_chip *chip,
u8 *buf, int oob_required,
int page)
static int marvell_nfc_hw_ecc_hmg_read_page(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
unsigned int full_sz = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes;
@ -1008,8 +1074,7 @@ static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd,
* it appears before the ECC bytes when reading), the ->read_oob_raw() function
* also stands for ->read_oob().
*/
static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct nand_chip *chip, int page)
{
/* Invalidate page cache */
chip->pagebuf = -1;
@ -1073,8 +1138,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
return ret;
}
static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip,
const u8 *buf,
int oob_required, int page)
{
@ -1082,8 +1146,7 @@ static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct mtd_info *mtd,
true, page);
}
static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_hmg_write_page(struct nand_chip *chip,
const u8 *buf,
int oob_required, int page)
{
@ -1102,10 +1165,11 @@ static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd,
* it appears before the ECC bytes when reading), the ->write_oob_raw() function
* also stands for ->write_oob().
*/
static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct nand_chip *chip,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Invalidate page cache */
chip->pagebuf = -1;
@ -1116,10 +1180,10 @@ static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct mtd_info *mtd,
}
/* BCH read helpers */
static int marvell_nfc_hw_ecc_bch_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int marvell_nfc_hw_ecc_bch_read_page_raw(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
u8 *oob = chip->oob_poi;
int chunk_size = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes;
@ -1228,17 +1292,17 @@ static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk,
}
}
static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip,
u8 *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
int data_len = lt->data_bytes, spare_len = lt->spare_bytes, ecc_len;
u8 *data = buf, *spare = chip->oob_poi, *ecc;
int data_len = lt->data_bytes, spare_len = lt->spare_bytes;
u8 *data = buf, *spare = chip->oob_poi;
int max_bitflips = 0;
u32 failure_mask = 0;
int chunk, ecc_offset_in_page, ret;
int chunk, ret;
/*
* With BCH, OOB is not fully used (and thus not read entirely), not
@ -1279,73 +1343,98 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd,
* the controller in normal mode and must be re-read in raw mode. To
* avoid dropping the performances, we prefer not to include them. The
* user should re-read the page in raw mode if ECC bytes are required.
*/
/*
* In case there is any subpage read error reported by ->correct(), we
* usually re-read only ECC bytes in raw mode and check if the whole
* page is empty. In this case, it is normal that the ECC check failed
* and we just ignore the error.
*
* However, for any subpage read error reported by ->correct(), the ECC
* bytes must be read in raw mode and the full subpage must be checked
* to see if it is entirely empty of if there was an actual error.
* However, it has been empirically observed that for some layouts (e.g
* 2k page, 8b strength per 512B chunk), the controller tries to correct
* bits and may create itself bitflips in the erased area. To overcome
* this strange behavior, the whole page is re-read in raw mode, not
* only the ECC bytes.
*/
for (chunk = 0; chunk < lt->nchunks; chunk++) {
int data_off_in_page, spare_off_in_page, ecc_off_in_page;
int data_off, spare_off, ecc_off;
int data_len, spare_len, ecc_len;
/* No failure reported for this chunk, move to the next one */
if (!(failure_mask & BIT(chunk)))
continue;
/* Derive ECC bytes positions (in page/buffer) and length */
ecc = chip->oob_poi +
(lt->full_chunk_cnt * lt->spare_bytes) +
lt->last_spare_bytes +
(chunk * ALIGN(lt->ecc_bytes, 32));
ecc_offset_in_page =
(chunk * (lt->data_bytes + lt->spare_bytes +
lt->ecc_bytes)) +
(chunk < lt->full_chunk_cnt ?
lt->data_bytes + lt->spare_bytes :
lt->last_data_bytes + lt->last_spare_bytes);
ecc_len = chunk < lt->full_chunk_cnt ?
lt->ecc_bytes : lt->last_ecc_bytes;
data_off_in_page = chunk * (lt->data_bytes + lt->spare_bytes +
lt->ecc_bytes);
spare_off_in_page = data_off_in_page +
(chunk < lt->full_chunk_cnt ? lt->data_bytes :
lt->last_data_bytes);
ecc_off_in_page = spare_off_in_page +
(chunk < lt->full_chunk_cnt ? lt->spare_bytes :
lt->last_spare_bytes);
/* Do the actual raw read of the ECC bytes */
nand_change_read_column_op(chip, ecc_offset_in_page,
ecc, ecc_len, false);
data_off = chunk * lt->data_bytes;
spare_off = chunk * lt->spare_bytes;
ecc_off = (lt->full_chunk_cnt * lt->spare_bytes) +
lt->last_spare_bytes +
(chunk * (lt->ecc_bytes + 2));
/* Derive data/spare bytes positions (in buffer) and length */
data = buf + (chunk * lt->data_bytes);
data_len = chunk < lt->full_chunk_cnt ?
lt->data_bytes : lt->last_data_bytes;
spare = chip->oob_poi + (chunk * (lt->spare_bytes +
lt->ecc_bytes));
spare_len = chunk < lt->full_chunk_cnt ?
lt->spare_bytes : lt->last_spare_bytes;
data_len = chunk < lt->full_chunk_cnt ? lt->data_bytes :
lt->last_data_bytes;
spare_len = chunk < lt->full_chunk_cnt ? lt->spare_bytes :
lt->last_spare_bytes;
ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes :
lt->last_ecc_bytes;
/*
* Only re-read the ECC bytes, unless we are using the 2k/8b
* layout which is buggy in the sense that the ECC engine will
* try to correct data bytes anyway, creating bitflips. In this
* case, re-read the entire page.
*/
if (lt->writesize == 2048 && lt->strength == 8) {
nand_change_read_column_op(chip, data_off_in_page,
buf + data_off, data_len,
false);
nand_change_read_column_op(chip, spare_off_in_page,
chip->oob_poi + spare_off, spare_len,
false);
}
nand_change_read_column_op(chip, ecc_off_in_page,
chip->oob_poi + ecc_off, ecc_len,
false);
/* Check the entire chunk (data + spare + ecc) for emptyness */
marvell_nfc_check_empty_chunk(chip, data, data_len, spare,
spare_len, ecc, ecc_len,
marvell_nfc_check_empty_chunk(chip, buf + data_off, data_len,
chip->oob_poi + spare_off, spare_len,
chip->oob_poi + ecc_off, ecc_len,
&max_bitflips);
}
return max_bitflips;
}
static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct nand_chip *chip, int page)
{
/* Invalidate page cache */
chip->pagebuf = -1;
return chip->ecc.read_page_raw(mtd, chip, chip->data_buf, true, page);
return chip->ecc.read_page_raw(chip, chip->data_buf, true, page);
}
static int marvell_nfc_hw_ecc_bch_read_oob(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page)
{
/* Invalidate page cache */
chip->pagebuf = -1;
return chip->ecc.read_page(mtd, chip, chip->data_buf, true, page);
return chip->ecc.read_page(chip, chip->data_buf, true, page);
}
/* BCH write helpers */
static int marvell_nfc_hw_ecc_bch_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_bch_write_page_raw(struct nand_chip *chip,
const u8 *buf,
int oob_required, int page)
{
@ -1458,11 +1547,11 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk,
return 0;
}
static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
const u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
const u8 *data = buf;
const u8 *spare = chip->oob_poi;
@ -1507,27 +1596,29 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd,
return 0;
}
static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct mtd_info *mtd,
struct nand_chip *chip,
static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct nand_chip *chip,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Invalidate page cache */
chip->pagebuf = -1;
memset(chip->data_buf, 0xFF, mtd->writesize);
return chip->ecc.write_page_raw(mtd, chip, chip->data_buf, true, page);
return chip->ecc.write_page_raw(chip, chip->data_buf, true, page);
}
static int marvell_nfc_hw_ecc_bch_write_oob(struct mtd_info *mtd,
struct nand_chip *chip, int page)
static int marvell_nfc_hw_ecc_bch_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Invalidate page cache */
chip->pagebuf = -1;
memset(chip->data_buf, 0xFF, mtd->writesize);
return chip->ecc.write_page(mtd, chip, chip->data_buf, true, page);
return chip->ecc.write_page(chip, chip->data_buf, true, page);
}
/* NAND framework ->exec_op() hooks and related helpers */
@ -2097,6 +2188,16 @@ static int marvell_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
return -ENOTSUPP;
}
/* Special care for the layout 2k/8-bit/512B */
if (l->writesize == 2048 && l->strength == 8) {
if (mtd->oobsize < 128) {
dev_err(nfc->dev, "Requested layout needs at least 128 OOB bytes\n");
return -ENOTSUPP;
} else {
chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
}
}
mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops);
ecc->steps = l->nchunks;
ecc->size = l->data_bytes;
@ -2192,11 +2293,10 @@ static struct nand_bbt_descr bbt_mirror_descr = {
.pattern = bbt_mirror_pattern
};
static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
static int marvell_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface
*conf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
unsigned int period_ns = 1000000000 / clk_get_rate(nfc->core_clk) * 2;
@ -2540,7 +2640,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
chip->options |= NAND_BUSWIDTH_AUTO;
ret = nand_scan(mtd, marvell_nand->nsels);
ret = nand_scan(chip, marvell_nand->nsels);
if (ret) {
dev_err(dev, "could not scan the nand chip\n");
return ret;
@ -2553,7 +2653,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
ret = mtd_device_register(mtd, NULL, 0);
if (ret) {
dev_err(dev, "failed to register mtd device: %d\n", ret);
nand_release(mtd);
nand_release(chip);
return ret;
}
@ -2608,7 +2708,7 @@ static void marvell_nand_chips_cleanup(struct marvell_nfc *nfc)
struct marvell_nand_chip *entry, *temp;
list_for_each_entry_safe(entry, temp, &nfc->chips, node) {
nand_release(nand_to_mtd(&entry->chip));
nand_release(&entry->chip);
list_del(&entry->node);
}
}
@ -2699,24 +2799,23 @@ static int marvell_nfc_init(struct marvell_nfc *nfc)
struct regmap *sysctrl_base =
syscon_regmap_lookup_by_phandle(np,
"marvell,system-controller");
u32 reg;
if (IS_ERR(sysctrl_base))
return PTR_ERR(sysctrl_base);
reg = GENCONF_SOC_DEVICE_MUX_NFC_EN |
GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST |
GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST |
GENCONF_SOC_DEVICE_MUX_NFC_INT_EN;
regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg);
regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX,
GENCONF_SOC_DEVICE_MUX_NFC_EN |
GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST |
GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST |
GENCONF_SOC_DEVICE_MUX_NFC_INT_EN);
regmap_read(sysctrl_base, GENCONF_CLK_GATING_CTRL, &reg);
reg |= GENCONF_CLK_GATING_CTRL_ND_GATE;
regmap_write(sysctrl_base, GENCONF_CLK_GATING_CTRL, reg);
regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL,
GENCONF_CLK_GATING_CTRL_ND_GATE,
GENCONF_CLK_GATING_CTRL_ND_GATE);
regmap_read(sysctrl_base, GENCONF_ND_CLK_CTRL, &reg);
reg |= GENCONF_ND_CLK_CTRL_EN;
regmap_write(sysctrl_base, GENCONF_ND_CLK_CTRL, reg);
regmap_update_bits(sysctrl_base, GENCONF_ND_CLK_CTRL,
GENCONF_ND_CLK_CTRL_EN,
GENCONF_ND_CLK_CTRL_EN);
}
/* Configure the DMA if appropriate */

View File

@ -263,8 +263,10 @@ static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
}
/* Control chip select signals */
static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
static void mpc5121_nfc_select_chip(struct nand_chip *nand, int chip)
{
struct mtd_info *mtd = nand_to_mtd(nand);
if (chip < 0) {
nfc_clear(mtd, NFC_CONFIG1, NFC_CE);
return;
@ -299,9 +301,9 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
}
/* Control chips select signal on ADS5121 board */
static void ads5121_select_chip(struct mtd_info *mtd, int chip)
static void ads5121_select_chip(struct nand_chip *nand, int chip)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand);
struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
u8 v;
@ -309,16 +311,16 @@ static void ads5121_select_chip(struct mtd_info *mtd, int chip)
v |= 0x0F;
if (chip >= 0) {
mpc5121_nfc_select_chip(mtd, 0);
mpc5121_nfc_select_chip(nand, 0);
v &= ~(1 << chip);
} else
mpc5121_nfc_select_chip(mtd, -1);
mpc5121_nfc_select_chip(nand, -1);
out_8(prv->csreg, v);
}
/* Read NAND Ready/Busy signal */
static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
static int mpc5121_nfc_dev_ready(struct nand_chip *nand)
{
/*
* NFC handles ready/busy signal internally. Therefore, this function
@ -328,10 +330,10 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
}
/* Write command to NAND flash */
static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
int column, int page)
static void mpc5121_nfc_command(struct nand_chip *chip, unsigned command,
int column, int page)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
prv->column = (column >= 0) ? column : 0;
@ -362,7 +364,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
break;
case NAND_CMD_SEQIN:
mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page);
mpc5121_nfc_command(chip, NAND_CMD_READ0, column, page);
column = 0;
break;
@ -493,34 +495,24 @@ static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
}
/* Read data from NFC buffers */
static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void mpc5121_nfc_read_buf(struct nand_chip *chip, u_char *buf, int len)
{
mpc5121_nfc_buf_copy(mtd, buf, len, 0);
mpc5121_nfc_buf_copy(nand_to_mtd(chip), buf, len, 0);
}
/* Write data to NFC buffers */
static void mpc5121_nfc_write_buf(struct mtd_info *mtd,
const u_char *buf, int len)
static void mpc5121_nfc_write_buf(struct nand_chip *chip, const u_char *buf,
int len)
{
mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
mpc5121_nfc_buf_copy(nand_to_mtd(chip), (u_char *)buf, len, 1);
}
/* Read byte from NFC buffers */
static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd)
static u8 mpc5121_nfc_read_byte(struct nand_chip *chip)
{
u8 tmp;
mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp));
return tmp;
}
/* Read word from NFC buffers */
static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
{
u16 tmp;
mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
mpc5121_nfc_read_buf(chip, &tmp, sizeof(tmp));
return tmp;
}
@ -700,15 +692,14 @@ static int mpc5121_nfc_probe(struct platform_device *op)
}
mtd->name = "MPC5121 NAND";
chip->dev_ready = mpc5121_nfc_dev_ready;
chip->cmdfunc = mpc5121_nfc_command;
chip->read_byte = mpc5121_nfc_read_byte;
chip->read_word = mpc5121_nfc_read_word;
chip->read_buf = mpc5121_nfc_read_buf;
chip->write_buf = mpc5121_nfc_write_buf;
chip->legacy.dev_ready = mpc5121_nfc_dev_ready;
chip->legacy.cmdfunc = mpc5121_nfc_command;
chip->legacy.read_byte = mpc5121_nfc_read_byte;
chip->legacy.read_buf = mpc5121_nfc_read_buf;
chip->legacy.write_buf = mpc5121_nfc_write_buf;
chip->select_chip = mpc5121_nfc_select_chip;
chip->set_features = nand_get_set_features_notsupp;
chip->get_features = nand_get_set_features_notsupp;
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
chip->bbt_options = NAND_BBT_USE_FLASH;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
@ -778,7 +769,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
}
/* Detect NAND chips */
retval = nand_scan(mtd, be32_to_cpup(chips_no));
retval = nand_scan(chip, be32_to_cpup(chips_no));
if (retval) {
dev_err(dev, "NAND Flash not found !\n");
goto error;
@ -828,7 +819,7 @@ static int mpc5121_nfc_remove(struct platform_device *op)
struct device *dev = &op->dev;
struct mtd_info *mtd = dev_get_drvdata(dev);
nand_release(mtd);
nand_release(mtd_to_nand(mtd));
mpc5121_nfc_free(dev, mtd);
return 0;

View File

@ -389,23 +389,22 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
return 0;
}
static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip)
static void mtk_nfc_select_chip(struct nand_chip *nand, int chip)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct mtk_nfc *nfc = nand_get_controller_data(nand);
struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand);
if (chip < 0)
return;
mtk_nfc_hw_runtime_config(mtd);
mtk_nfc_hw_runtime_config(nand_to_mtd(nand));
nfi_writel(nfc, mtk_nand->sels[chip], NFI_CSEL);
}
static int mtk_nfc_dev_ready(struct mtd_info *mtd)
static int mtk_nfc_dev_ready(struct nand_chip *nand)
{
struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
struct mtk_nfc *nfc = nand_get_controller_data(nand);
if (nfi_readl(nfc, NFI_STA) & STA_BUSY)
return 0;
@ -413,9 +412,10 @@ static int mtk_nfc_dev_ready(struct mtd_info *mtd)
return 1;
}
static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
static void mtk_nfc_cmd_ctrl(struct nand_chip *chip, int dat,
unsigned int ctrl)
{
struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
struct mtk_nfc *nfc = nand_get_controller_data(chip);
if (ctrl & NAND_ALE) {
mtk_nfc_send_address(nfc, dat);
@ -438,9 +438,8 @@ static inline void mtk_nfc_wait_ioready(struct mtk_nfc *nfc)
dev_err(nfc->dev, "data not ready\n");
}
static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd)
static inline u8 mtk_nfc_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtk_nfc *nfc = nand_get_controller_data(chip);
u32 reg;
@ -467,17 +466,17 @@ static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd)
return nfi_readb(nfc, NFI_DATAR);
}
static void mtk_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void mtk_nfc_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
int i;
for (i = 0; i < len; i++)
buf[i] = mtk_nfc_read_byte(mtd);
buf[i] = mtk_nfc_read_byte(chip);
}
static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte)
static void mtk_nfc_write_byte(struct nand_chip *chip, u8 byte)
{
struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
struct mtk_nfc *nfc = nand_get_controller_data(chip);
u32 reg;
reg = nfi_readl(nfc, NFI_STA) & NFI_FSM_MASK;
@ -496,18 +495,18 @@ static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte)
nfi_writeb(nfc, byte, NFI_DATAW);
}
static void mtk_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void mtk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
int i;
for (i = 0; i < len; i++)
mtk_nfc_write_byte(mtd, buf[i]);
mtk_nfc_write_byte(chip, buf[i]);
}
static int mtk_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
struct mtk_nfc *nfc = nand_get_controller_data(chip);
const struct nand_sdr_timings *timings;
u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt;
@ -807,27 +806,27 @@ static int mtk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
return nand_prog_page_end_op(chip);
}
static int mtk_nfc_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const u8 *buf,
static int mtk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
int oob_on, int page)
{
return mtk_nfc_write_page(mtd, chip, buf, page, 0);
return mtk_nfc_write_page(nand_to_mtd(chip), chip, buf, page, 0);
}
static int mtk_nfc_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const u8 *buf, int oob_on, int pg)
static int mtk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf,
int oob_on, int pg)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtk_nfc *nfc = nand_get_controller_data(chip);
mtk_nfc_format_page(mtd, buf);
return mtk_nfc_write_page(mtd, chip, nfc->buffer, pg, 1);
}
static int mtk_nfc_write_subpage_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, u32 offset,
static int mtk_nfc_write_subpage_hwecc(struct nand_chip *chip, u32 offset,
u32 data_len, const u8 *buf,
int oob_on, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtk_nfc *nfc = nand_get_controller_data(chip);
int ret;
@ -839,10 +838,9 @@ static int mtk_nfc_write_subpage_hwecc(struct mtd_info *mtd,
return mtk_nfc_write_page(mtd, chip, nfc->buffer, page, 1);
}
static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int mtk_nfc_write_oob_std(struct nand_chip *chip, int page)
{
return mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page);
return mtk_nfc_write_page_raw(chip, NULL, 1, page);
}
static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
@ -969,23 +967,25 @@ done:
return bitflips;
}
static int mtk_nfc_read_subpage_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, u32 off,
static int mtk_nfc_read_subpage_hwecc(struct nand_chip *chip, u32 off,
u32 len, u8 *p, int pg)
{
return mtk_nfc_read_subpage(mtd, chip, off, len, p, pg, 0);
return mtk_nfc_read_subpage(nand_to_mtd(chip), chip, off, len, p, pg,
0);
}
static int mtk_nfc_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, u8 *p,
int oob_on, int pg)
static int mtk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *p, int oob_on,
int pg)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return mtk_nfc_read_subpage(mtd, chip, 0, mtd->writesize, p, pg, 0);
}
static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
u8 *buf, int oob_on, int page)
static int mtk_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_on,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
struct mtk_nfc *nfc = nand_get_controller_data(chip);
struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
@ -1011,10 +1011,9 @@ static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return ret;
}
static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int mtk_nfc_read_oob_std(struct nand_chip *chip, int page)
{
return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page);
return mtk_nfc_read_page_raw(chip, NULL, 1, page);
}
static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc)
@ -1333,13 +1332,13 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
nand_set_controller_data(nand, nfc);
nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_SUBPAGE_READ;
nand->dev_ready = mtk_nfc_dev_ready;
nand->legacy.dev_ready = mtk_nfc_dev_ready;
nand->select_chip = mtk_nfc_select_chip;
nand->write_byte = mtk_nfc_write_byte;
nand->write_buf = mtk_nfc_write_buf;
nand->read_byte = mtk_nfc_read_byte;
nand->read_buf = mtk_nfc_read_buf;
nand->cmd_ctrl = mtk_nfc_cmd_ctrl;
nand->legacy.write_byte = mtk_nfc_write_byte;
nand->legacy.write_buf = mtk_nfc_write_buf;
nand->legacy.read_byte = mtk_nfc_read_byte;
nand->legacy.read_buf = mtk_nfc_read_buf;
nand->legacy.cmd_ctrl = mtk_nfc_cmd_ctrl;
nand->setup_data_interface = mtk_nfc_setup_data_interface;
/* set default mode in case dt entry is missing */
@ -1365,14 +1364,14 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
mtk_nfc_hw_init(nfc);
ret = nand_scan(mtd, nsels);
ret = nand_scan(nand, nsels);
if (ret)
return ret;
ret = mtd_device_register(mtd, NULL, 0);
if (ret) {
dev_err(dev, "mtd parse partition error\n");
nand_release(mtd);
nand_release(nand);
return ret;
}
@ -1538,7 +1537,7 @@ static int mtk_nfc_remove(struct platform_device *pdev)
while (!list_empty(&nfc->chips)) {
chip = list_first_entry(&nfc->chips, struct mtk_nfc_nand_chip,
node);
nand_release(nand_to_mtd(&chip->nand));
nand_release(&chip->nand);
list_del(&chip->node);
}

View File

@ -136,8 +136,8 @@ struct mxc_nand_devtype_data {
void (*irq_control)(struct mxc_nand_host *, int);
u32 (*get_ecc_status)(struct mxc_nand_host *);
const struct mtd_ooblayout_ops *ooblayout;
void (*select_chip)(struct mtd_info *mtd, int chip);
int (*setup_data_interface)(struct mtd_info *mtd, int csline,
void (*select_chip)(struct nand_chip *chip, int cs);
int (*setup_data_interface)(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf);
void (*enable_hwecc)(struct nand_chip *chip, bool enable);
@ -701,7 +701,7 @@ static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable)
}
/* This functions is used by upper layer to checks if device is ready */
static int mxc_nand_dev_ready(struct mtd_info *mtd)
static int mxc_nand_dev_ready(struct nand_chip *chip)
{
/*
* NFC handles R/B internally. Therefore, this function
@ -816,8 +816,8 @@ static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf,
return max_bitflips;
}
static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mxc_nand_host *host = nand_get_controller_data(chip);
void *oob_buf;
@ -830,8 +830,8 @@ static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return host->devtype_data->read_page(chip, buf, oob_buf, 1, page);
}
static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int mxc_nand_read_page_raw(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mxc_nand_host *host = nand_get_controller_data(chip);
void *oob_buf;
@ -844,8 +844,7 @@ static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return host->devtype_data->read_page(chip, buf, oob_buf, 0, page);
}
static int mxc_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int mxc_nand_read_oob(struct nand_chip *chip, int page)
{
struct mxc_nand_host *host = nand_get_controller_data(chip);
@ -874,22 +873,21 @@ static int mxc_nand_write_page(struct nand_chip *chip, const uint8_t *buf,
return 0;
}
static int mxc_nand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
static int mxc_nand_write_page_ecc(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
return mxc_nand_write_page(chip, buf, true, page);
}
static int mxc_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int mxc_nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
return mxc_nand_write_page(chip, buf, false, page);
}
static int mxc_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int mxc_nand_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mxc_nand_host *host = nand_get_controller_data(chip);
memset(host->data_buf, 0xff, mtd->writesize);
@ -897,9 +895,8 @@ static int mxc_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
return mxc_nand_write_page(chip, host->data_buf, false, page);
}
static u_char mxc_nand_read_byte(struct mtd_info *mtd)
static u_char mxc_nand_read_byte(struct nand_chip *nand_chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
uint8_t ret;
@ -921,25 +918,13 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
return ret;
}
static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
uint16_t ret;
ret = *(uint16_t *)(host->data_buf + host->buf_start);
host->buf_start += 2;
return ret;
}
/* Write data of length len to buffer buf. The data to be
* written on NAND Flash is first copied to RAMbuffer. After the Data Input
* Operation by the NFC, the data is written to NAND Flash */
static void mxc_nand_write_buf(struct mtd_info *mtd,
const u_char *buf, int len)
static void mxc_nand_write_buf(struct nand_chip *nand_chip, const u_char *buf,
int len)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand_chip);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
u16 col = host->buf_start;
int n = mtd->oobsize + mtd->writesize - col;
@ -955,9 +940,10 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
* Flash first the data output cycle is initiated by the NFC, which copies
* the data to RAMbuffer. This data of length len is then copied to buffer buf.
*/
static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void mxc_nand_read_buf(struct nand_chip *nand_chip, u_char *buf,
int len)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand_chip);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
u16 col = host->buf_start;
int n = mtd->oobsize + mtd->writesize - col;
@ -971,9 +957,8 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
/* This function is used by upper layer for select and
* deselect of the NAND chip */
static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
static void mxc_nand_select_chip_v1_v3(struct nand_chip *nand_chip, int chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
if (chip == -1) {
@ -992,9 +977,8 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
}
}
static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
static void mxc_nand_select_chip_v2(struct nand_chip *nand_chip, int chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
if (chip == -1) {
@ -1155,11 +1139,10 @@ static void preset_v1(struct mtd_info *mtd)
writew(0x4, NFC_V1_V2_WRPROT);
}
static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, int csline,
static int mxc_nand_v2_setup_data_interface(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
struct mxc_nand_host *host = nand_get_controller_data(chip);
int tRC_min_ns, tRC_ps, ret;
unsigned long rate, rate_round;
const struct nand_sdr_timings *timings;
@ -1349,10 +1332,10 @@ static void preset_v3(struct mtd_info *mtd)
/* Used by the upper layer to write command to NAND Flash for
* different operations to be carried out on NAND Flash */
static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
int column, int page_addr)
static void mxc_nand_command(struct nand_chip *nand_chip, unsigned command,
int column, int page_addr)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand_chip);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
@ -1409,17 +1392,17 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
}
}
static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip,
int addr, u8 *subfeature_param)
static int mxc_nand_set_features(struct nand_chip *chip, int addr,
u8 *subfeature_param)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
struct mtd_info *mtd = nand_to_mtd(chip);
struct mxc_nand_host *host = nand_get_controller_data(chip);
int i;
host->buf_start = 0;
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
chip->write_byte(mtd, subfeature_param[i]);
chip->legacy.write_byte(chip, subfeature_param[i]);
memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
host->devtype_data->send_cmd(host, NAND_CMD_SET_FEATURES, false);
@ -1429,11 +1412,11 @@ static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
static int mxc_nand_get_features(struct mtd_info *mtd, struct nand_chip *chip,
int addr, u8 *subfeature_param)
static int mxc_nand_get_features(struct nand_chip *chip, int addr,
u8 *subfeature_param)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
struct mtd_info *mtd = nand_to_mtd(chip);
struct mxc_nand_host *host = nand_get_controller_data(chip);
int i;
host->devtype_data->send_cmd(host, NAND_CMD_GET_FEATURES, false);
@ -1443,7 +1426,7 @@ static int mxc_nand_get_features(struct mtd_info *mtd, struct nand_chip *chip,
host->buf_start = 0;
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
*subfeature_param++ = chip->read_byte(mtd);
*subfeature_param++ = chip->legacy.read_byte(chip);
return 0;
}
@ -1786,18 +1769,17 @@ static int mxcnd_probe(struct platform_device *pdev)
mtd->name = DRIVER_NAME;
/* 50 us command delay time */
this->chip_delay = 5;
this->legacy.chip_delay = 5;
nand_set_controller_data(this, host);
nand_set_flash_node(this, pdev->dev.of_node),
this->dev_ready = mxc_nand_dev_ready;
this->cmdfunc = mxc_nand_command;
this->read_byte = mxc_nand_read_byte;
this->read_word = mxc_nand_read_word;
this->write_buf = mxc_nand_write_buf;
this->read_buf = mxc_nand_read_buf;
this->set_features = mxc_nand_set_features;
this->get_features = mxc_nand_get_features;
this->legacy.dev_ready = mxc_nand_dev_ready;
this->legacy.cmdfunc = mxc_nand_command;
this->legacy.read_byte = mxc_nand_read_byte;
this->legacy.write_buf = mxc_nand_write_buf;
this->legacy.read_buf = mxc_nand_read_buf;
this->legacy.set_features = mxc_nand_set_features;
this->legacy.get_features = mxc_nand_get_features;
host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk))
@ -1900,7 +1882,7 @@ static int mxcnd_probe(struct platform_device *pdev)
/* Scan the NAND device */
this->dummy_controller.ops = &mxcnd_controller_ops;
err = nand_scan(mtd, is_imx25_nfc(host) ? 4 : 1);
err = nand_scan(this, is_imx25_nfc(host) ? 4 : 1);
if (err)
goto escan;
@ -1928,7 +1910,7 @@ static int mxcnd_remove(struct platform_device *pdev)
{
struct mxc_nand_host *host = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&host->nand));
nand_release(&host->nand);
if (host->clk_act)
clk_disable_unprepare(host->clk);

View File

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include "internals.h"
static void amd_nand_decode_id(struct nand_chip *chip)
{

File diff suppressed because it is too large Load Diff

View File

@ -61,13 +61,14 @@
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/bbm.h>
#include <linux/mtd/rawnand.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/string.h>
#include "internals.h"
#define BBT_BLOCK_GOOD 0x00
#define BBT_BLOCK_WORN 0x01
#define BBT_BLOCK_RESERVED 0x02
@ -683,14 +684,13 @@ static void mark_bbt_block_bad(struct nand_chip *this,
struct nand_bbt_descr *td,
int chip, int block)
{
struct mtd_info *mtd = nand_to_mtd(this);
loff_t to;
int res;
bbt_mark_entry(this, block, BBT_BLOCK_WORN);
to = (loff_t)block << this->bbt_erase_shift;
res = this->block_markbad(mtd, to);
res = nand_markbad_bbm(this, to);
if (res)
pr_warn("nand_bbt: error %d while marking block %d bad\n",
res, block);
@ -854,7 +854,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
memset(&einfo, 0, sizeof(einfo));
einfo.addr = to;
einfo.len = 1 << this->bbt_erase_shift;
res = nand_erase_nand(mtd, &einfo, 1);
res = nand_erase_nand(this, &einfo, 1);
if (res < 0) {
pr_warn("nand_bbt: error while erasing BBT block %d\n",
res);
@ -1388,12 +1388,11 @@ EXPORT_SYMBOL(nand_create_bbt);
/**
* nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
* @mtd: MTD device structure
* @this: NAND chip object
* @offs: offset in the device
*/
int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
int nand_isreserved_bbt(struct nand_chip *this, loff_t offs)
{
struct nand_chip *this = mtd_to_nand(mtd);
int block;
block = (int)(offs >> this->bbt_erase_shift);
@ -1402,13 +1401,12 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
/**
* nand_isbad_bbt - [NAND Interface] Check if a block is bad
* @mtd: MTD device structure
* @this: NAND chip object
* @offs: offset in the device
* @allowbbt: allow access to bad block table region
*/
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)
{
struct nand_chip *this = mtd_to_nand(mtd);
int block, res;
block = (int)(offs >> this->bbt_erase_shift);
@ -1430,12 +1428,12 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
/**
* nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
* @mtd: MTD device structure
* @this: NAND chip object
* @offs: offset of the bad block
*/
int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
int nand_markbad_bbt(struct nand_chip *this, loff_t offs)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(this);
int block, ret = 0;
block = (int)(offs >> this->bbt_erase_shift);

View File

@ -43,14 +43,13 @@ struct nand_bch_control {
/**
* nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block
* @mtd: MTD block structure
* @chip: NAND chip object
* @buf: input buffer with raw data
* @code: output buffer with ECC
*/
int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
int nand_bch_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
unsigned char *code)
{
const struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int i;
@ -67,17 +66,16 @@ EXPORT_SYMBOL(nand_bch_calculate_ecc);
/**
* nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
* @mtd: MTD block structure
* @chip: NAND chip object
* @buf: raw data read from the chip
* @read_ecc: ECC from the chip
* @calc_ecc: the ECC calculated from raw data
*
* Detect and correct bit errors for a data byte block
*/
int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
const struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int *errloc = nbc->errloc;
int i, count;

View File

@ -132,9 +132,10 @@ static const char addressbits[256] = {
* @buf: input buffer with raw data
* @eccsize: data bytes per ECC step (256 or 512)
* @code: output buffer with ECC
* @sm_order: Smart Media byte ordering
*/
void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
unsigned char *code)
unsigned char *code, bool sm_order)
{
int i;
const uint32_t *bp = (uint32_t *)buf;
@ -330,45 +331,26 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
* possible, but benchmarks showed that on the system this is developed
* the code below is the fastest
*/
#ifdef CONFIG_MTD_NAND_ECC_SMC
code[0] =
(invparity[rp7] << 7) |
(invparity[rp6] << 6) |
(invparity[rp5] << 5) |
(invparity[rp4] << 4) |
(invparity[rp3] << 3) |
(invparity[rp2] << 2) |
(invparity[rp1] << 1) |
(invparity[rp0]);
code[1] =
(invparity[rp15] << 7) |
(invparity[rp14] << 6) |
(invparity[rp13] << 5) |
(invparity[rp12] << 4) |
(invparity[rp11] << 3) |
(invparity[rp10] << 2) |
(invparity[rp9] << 1) |
(invparity[rp8]);
#else
code[1] =
(invparity[rp7] << 7) |
(invparity[rp6] << 6) |
(invparity[rp5] << 5) |
(invparity[rp4] << 4) |
(invparity[rp3] << 3) |
(invparity[rp2] << 2) |
(invparity[rp1] << 1) |
(invparity[rp0]);
code[0] =
(invparity[rp15] << 7) |
(invparity[rp14] << 6) |
(invparity[rp13] << 5) |
(invparity[rp12] << 4) |
(invparity[rp11] << 3) |
(invparity[rp10] << 2) |
(invparity[rp9] << 1) |
(invparity[rp8]);
#endif
if (sm_order) {
code[0] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
(invparity[rp5] << 5) | (invparity[rp4] << 4) |
(invparity[rp3] << 3) | (invparity[rp2] << 2) |
(invparity[rp1] << 1) | (invparity[rp0]);
code[1] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
(invparity[rp13] << 5) | (invparity[rp12] << 4) |
(invparity[rp11] << 3) | (invparity[rp10] << 2) |
(invparity[rp9] << 1) | (invparity[rp8]);
} else {
code[1] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
(invparity[rp5] << 5) | (invparity[rp4] << 4) |
(invparity[rp3] << 3) | (invparity[rp2] << 2) |
(invparity[rp1] << 1) | (invparity[rp0]);
code[0] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
(invparity[rp13] << 5) | (invparity[rp12] << 4) |
(invparity[rp11] << 3) | (invparity[rp10] << 2) |
(invparity[rp9] << 1) | (invparity[rp8]);
}
if (eccsize_mult == 1)
code[2] =
(invparity[par & 0xf0] << 7) |
@ -394,15 +376,16 @@ EXPORT_SYMBOL(__nand_calculate_ecc);
/**
* nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
* block
* @mtd: MTD block structure
* @chip: NAND chip object
* @buf: input buffer with raw data
* @code: output buffer with ECC
*/
int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
unsigned char *code)
{
__nand_calculate_ecc(buf,
mtd_to_nand(mtd)->ecc.size, code);
bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
__nand_calculate_ecc(buf, chip->ecc.size, code, sm_order);
return 0;
}
@ -414,12 +397,13 @@ EXPORT_SYMBOL(nand_calculate_ecc);
* @read_ecc: ECC from the chip
* @calc_ecc: the ECC calculated from raw data
* @eccsize: data bytes per ECC step (256 or 512)
* @sm_order: Smart Media byte order
*
* Detect and correct a 1 bit error for eccsize byte block
*/
int __nand_correct_data(unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc,
unsigned int eccsize)
unsigned int eccsize, bool sm_order)
{
unsigned char b0, b1, b2, bit_addr;
unsigned int byte_addr;
@ -431,13 +415,14 @@ int __nand_correct_data(unsigned char *buf,
* we might need the xor result more than once,
* so keep them in a local var
*/
#ifdef CONFIG_MTD_NAND_ECC_SMC
b0 = read_ecc[0] ^ calc_ecc[0];
b1 = read_ecc[1] ^ calc_ecc[1];
#else
b0 = read_ecc[1] ^ calc_ecc[1];
b1 = read_ecc[0] ^ calc_ecc[0];
#endif
if (sm_order) {
b0 = read_ecc[0] ^ calc_ecc[0];
b1 = read_ecc[1] ^ calc_ecc[1];
} else {
b0 = read_ecc[1] ^ calc_ecc[1];
b1 = read_ecc[0] ^ calc_ecc[0];
}
b2 = read_ecc[2] ^ calc_ecc[2];
/* check if there are any bitfaults */
@ -491,18 +476,20 @@ EXPORT_SYMBOL(__nand_correct_data);
/**
* nand_correct_data - [NAND Interface] Detect and correct bit error(s)
* @mtd: MTD block structure
* @chip: NAND chip object
* @buf: raw data read from the chip
* @read_ecc: ECC from the chip
* @calc_ecc: the ECC calculated from raw data
*
* Detect and correct a 1 bit error for 256/512 byte block
*/
int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
int nand_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
return __nand_correct_data(buf, read_ecc, calc_ecc,
mtd_to_nand(mtd)->ecc.size);
bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size,
sm_order);
}
EXPORT_SYMBOL(nand_correct_data);

View File

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Toradex AG
*
* Author: Marcel Ziswiler <marcel.ziswiler@toradex.com>
*/
#include <linux/mtd/rawnand.h>
#include "internals.h"
static void esmt_nand_decode_id(struct nand_chip *chip)
{
nand_decode_ext_id(chip);
/* Extract ECC requirements from 5th id byte. */
if (chip->id.len >= 5 && nand_is_slc(chip)) {
chip->ecc_step_ds = 512;
switch (chip->id.data[4] & 0x3) {
case 0x0:
chip->ecc_strength_ds = 4;
break;
case 0x1:
chip->ecc_strength_ds = 2;
break;
case 0x2:
chip->ecc_strength_ds = 1;
break;
default:
WARN(1, "Could not get ECC info");
chip->ecc_step_ds = 0;
break;
}
}
}
static int esmt_nand_init(struct nand_chip *chip)
{
if (nand_is_slc(chip))
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
return 0;
}
const struct nand_manufacturer_ops esmt_nand_manuf_ops = {
.detect = esmt_nand_decode_id,
.init = esmt_nand_init,
};

View File

@ -15,10 +15,11 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include "internals.h"
#define NAND_HYNIX_CMD_SET_PARAMS 0x36
#define NAND_HYNIX_CMD_APPLY_PARAMS 0x16
@ -79,8 +80,6 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd)
{
struct mtd_info *mtd = nand_to_mtd(chip);
if (chip->exec_op) {
struct nand_op_instr instrs[] = {
NAND_OP_CMD(cmd, 0),
@ -90,14 +89,13 @@ static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd)
return nand_exec_op(chip, &op);
}
chip->cmdfunc(mtd, cmd, -1, -1);
chip->legacy.cmdfunc(chip, cmd, -1, -1);
return 0;
}
static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val)
{
struct mtd_info *mtd = nand_to_mtd(chip);
u16 column = ((u16)addr << 8) | addr;
if (chip->exec_op) {
@ -110,15 +108,14 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val)
return nand_exec_op(chip, &op);
}
chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
chip->write_byte(mtd, val);
chip->legacy.cmdfunc(chip, NAND_CMD_NONE, column, -1);
chip->legacy.write_byte(chip, val);
return 0;
}
static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
static int hynix_nand_setup_read_retry(struct nand_chip *chip, int retry_mode)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
const u8 *values;
int i, ret;

View File

@ -6,9 +6,11 @@
* published by the Free Software Foundation.
*
*/
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#include "internals.h"
#define LP_OPTIONS 0
#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
@ -169,21 +171,21 @@ struct nand_flash_dev nand_flash_ids[] = {
/* Manufacturer IDs */
static const struct nand_manufacturer nand_manufacturers[] = {
{NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops},
{NAND_MFR_ESMT, "ESMT"},
{NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
{NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
{NAND_MFR_ATO, "ATO"},
{NAND_MFR_EON, "Eon"},
{NAND_MFR_ESMT, "ESMT", &esmt_nand_manuf_ops},
{NAND_MFR_FUJITSU, "Fujitsu"},
{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
{NAND_MFR_INTEL, "Intel"},
{NAND_MFR_MACRONIX, "Macronix", &macronix_nand_manuf_ops},
{NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
{NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
{NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
{NAND_MFR_MACRONIX, "Macronix", &macronix_nand_manuf_ops},
{NAND_MFR_EON, "Eon"},
{NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
{NAND_MFR_SANDISK, "SanDisk"},
{NAND_MFR_INTEL, "Intel"},
{NAND_MFR_ATO, "ATO"},
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops},
{NAND_MFR_WINBOND, "Winbond"},
};

View File

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
*
* Credits:
* David Woodhouse for adding multichip support
*
* Aleph One Ltd. and Toby Churchill Ltd. for supporting the
* rework for 2K page size chips
*
* This file contains all ONFI helpers.
*/
#include <linux/slab.h>
#include "internals.h"
/*
* Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
*/
int nand_jedec_detect(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_jedec_params *p;
struct jedec_ecc_info *ecc;
int jedec_version = 0;
char id[5];
int i, val, ret;
/* Try JEDEC for unknown chip or LP */
ret = nand_readid_op(chip, 0x40, id, sizeof(id));
if (ret || strncmp(id, "JEDEC", sizeof(id)))
return 0;
/* JEDEC chip: allocate a buffer to hold its parameter page */
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
ret = nand_read_param_page_op(chip, 0x40, NULL, 0);
if (ret) {
ret = 0;
goto free_jedec_param_page;
}
for (i = 0; i < 3; i++) {
ret = nand_read_data_op(chip, p, sizeof(*p), true);
if (ret) {
ret = 0;
goto free_jedec_param_page;
}
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) ==
le16_to_cpu(p->crc))
break;
}
if (i == 3) {
pr_err("Could not find valid JEDEC parameter page; aborting\n");
goto free_jedec_param_page;
}
/* Check version */
val = le16_to_cpu(p->revision);
if (val & (1 << 2))
jedec_version = 10;
else if (val & (1 << 1))
jedec_version = 1; /* vendor specific version */
if (!jedec_version) {
pr_info("unsupported JEDEC version: %d\n", val);
goto free_jedec_param_page;
}
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
sanitize_string(p->model, sizeof(p->model));
chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
if (!chip->parameters.model) {
ret = -ENOMEM;
goto free_jedec_param_page;
}
mtd->writesize = le32_to_cpu(p->byte_per_page);
/* Please reference to the comment for nand_flash_detect_onfi. */
mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
mtd->erasesize *= mtd->writesize;
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
/* Please reference to the comment for nand_flash_detect_onfi. */
chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
chip->bits_per_cell = p->bits_per_cell;
if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS)
chip->options |= NAND_BUSWIDTH_16;
/* ECC info */
ecc = &p->ecc_info[0];
if (ecc->codeword_size >= 9) {
chip->ecc_strength_ds = ecc->ecc_bits;
chip->ecc_step_ds = 1 << ecc->codeword_size;
} else {
pr_warn("Invalid codeword size\n");
}
free_jedec_param_page:
kfree(p);
return ret;
}

View File

@ -0,0 +1,642 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
*
* Credits:
* David Woodhouse for adding multichip support
*
* Aleph One Ltd. and Toby Churchill Ltd. for supporting the
* rework for 2K page size chips
*
* This file contains all legacy helpers/code that should be removed
* at some point.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/nmi.h>
#include "internals.h"
/**
* nand_read_byte - [DEFAULT] read one byte from the chip
* @chip: NAND chip object
*
* Default read function for 8bit buswidth
*/
static uint8_t nand_read_byte(struct nand_chip *chip)
{
return readb(chip->legacy.IO_ADDR_R);
}
/**
* nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
* @chip: NAND chip object
*
* Default read function for 16bit buswidth with endianness conversion.
*
*/
static uint8_t nand_read_byte16(struct nand_chip *chip)
{
return (uint8_t) cpu_to_le16(readw(chip->legacy.IO_ADDR_R));
}
/**
* nand_select_chip - [DEFAULT] control CE line
* @chip: NAND chip object
* @chipnr: chipnumber to select, -1 for deselect
*
* Default select function for 1 chip devices.
*/
static void nand_select_chip(struct nand_chip *chip, int chipnr)
{
switch (chipnr) {
case -1:
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
0 | NAND_CTRL_CHANGE);
break;
case 0:
break;
default:
BUG();
}
}
/**
* nand_write_byte - [DEFAULT] write single byte to chip
* @chip: NAND chip object
* @byte: value to write
*
* Default function to write a byte to I/O[7:0]
*/
static void nand_write_byte(struct nand_chip *chip, uint8_t byte)
{
chip->legacy.write_buf(chip, &byte, 1);
}
/**
* nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
* @chip: NAND chip object
* @byte: value to write
*
* Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
*/
static void nand_write_byte16(struct nand_chip *chip, uint8_t byte)
{
uint16_t word = byte;
/*
* It's not entirely clear what should happen to I/O[15:8] when writing
* a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
*
* When the host supports a 16-bit bus width, only data is
* transferred at the 16-bit width. All address and command line
* transfers shall use only the lower 8-bits of the data bus. During
* command transfers, the host may place any value on the upper
* 8-bits of the data bus. During address transfers, the host shall
* set the upper 8-bits of the data bus to 00h.
*
* One user of the write_byte callback is nand_set_features. The
* four parameters are specified to be written to I/O[7:0], but this is
* neither an address nor a command transfer. Let's assume a 0 on the
* upper I/O lines is OK.
*/
chip->legacy.write_buf(chip, (uint8_t *)&word, 2);
}
/**
* nand_write_buf - [DEFAULT] write buffer to chip
* @chip: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*
* Default write function for 8bit buswidth.
*/
static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
iowrite8_rep(chip->legacy.IO_ADDR_W, buf, len);
}
/**
* nand_read_buf - [DEFAULT] read chip data into buffer
* @chip: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*
* Default read function for 8bit buswidth.
*/
static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
ioread8_rep(chip->legacy.IO_ADDR_R, buf, len);
}
/**
* nand_write_buf16 - [DEFAULT] write buffer to chip
* @chip: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*
* Default write function for 16bit buswidth.
*/
static void nand_write_buf16(struct nand_chip *chip, const uint8_t *buf,
int len)
{
u16 *p = (u16 *) buf;
iowrite16_rep(chip->legacy.IO_ADDR_W, p, len >> 1);
}
/**
* nand_read_buf16 - [DEFAULT] read chip data into buffer
* @chip: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*
* Default read function for 16bit buswidth.
*/
static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len)
{
u16 *p = (u16 *) buf;
ioread16_rep(chip->legacy.IO_ADDR_R, p, len >> 1);
}
/**
* panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
* @mtd: MTD device structure
* @timeo: Timeout
*
* Helper function for nand_wait_ready used when needing to wait in interrupt
* context.
*/
static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
{
struct nand_chip *chip = mtd_to_nand(mtd);
int i;
/* Wait for the device to get ready */
for (i = 0; i < timeo; i++) {
if (chip->legacy.dev_ready(chip))
break;
touch_softlockup_watchdog();
mdelay(1);
}
}
/**
* nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
* @chip: NAND chip object
*
* Wait for the ready pin after a command, and warn if a timeout occurs.
*/
void nand_wait_ready(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
unsigned long timeo = 400;
if (in_interrupt() || oops_in_progress)
return panic_nand_wait_ready(mtd, timeo);
/* Wait until command is processed or timeout occurs */
timeo = jiffies + msecs_to_jiffies(timeo);
do {
if (chip->legacy.dev_ready(chip))
return;
cond_resched();
} while (time_before(jiffies, timeo));
if (!chip->legacy.dev_ready(chip))
pr_warn_ratelimited("timeout while waiting for chip to become ready\n");
}
EXPORT_SYMBOL_GPL(nand_wait_ready);
/**
* nand_wait_status_ready - [GENERIC] Wait for the ready status after commands.
* @mtd: MTD device structure
* @timeo: Timeout in ms
*
* Wait for status ready (i.e. command done) or timeout.
*/
static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
{
register struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
timeo = jiffies + msecs_to_jiffies(timeo);
do {
u8 status;
ret = nand_read_data_op(chip, &status, sizeof(status), true);
if (ret)
return;
if (status & NAND_STATUS_READY)
break;
touch_softlockup_watchdog();
} while (time_before(jiffies, timeo));
};
/**
* nand_command - [DEFAULT] Send command to NAND device
* @chip: NAND chip object
* @command: the command to be sent
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*
* Send command to NAND device. This function is used for small page devices
* (512 Bytes per page).
*/
static void nand_command(struct nand_chip *chip, unsigned int command,
int column, int page_addr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
/* Write out the command to the device */
if (command == NAND_CMD_SEQIN) {
int readcmd;
if (column >= mtd->writesize) {
/* OOB area */
column -= mtd->writesize;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
readcmd = NAND_CMD_READ0;
} else {
column -= 256;
readcmd = NAND_CMD_READ1;
}
chip->legacy.cmd_ctrl(chip, readcmd, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
}
if (command != NAND_CMD_NONE)
chip->legacy.cmd_ctrl(chip, command, ctrl);
/* Address cycle, when necessary */
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (chip->options & NAND_BUSWIDTH_16 &&
!nand_opcode_8bits(command))
column >>= 1;
chip->legacy.cmd_ctrl(chip, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
}
if (page_addr != -1) {
chip->legacy.cmd_ctrl(chip, page_addr, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
chip->legacy.cmd_ctrl(chip, page_addr >> 8, ctrl);
if (chip->options & NAND_ROW_ADDR_3)
chip->legacy.cmd_ctrl(chip, page_addr >> 16, ctrl);
}
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
/*
* Program and erase have their own busy handlers status and sequential
* in needs no delay
*/
switch (command) {
case NAND_CMD_NONE:
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
case NAND_CMD_READID:
case NAND_CMD_SET_FEATURES:
return;
case NAND_CMD_RESET:
if (chip->legacy.dev_ready)
break;
udelay(chip->legacy.chip_delay);
chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS,
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
/* EZ-NAND can take upto 250ms as per ONFi v4.0 */
nand_wait_status_ready(mtd, 250);
return;
/* This applies to read commands */
case NAND_CMD_READ0:
/*
* READ0 is sometimes used to exit GET STATUS mode. When this
* is the case no address cycles are requested, and we can use
* this information to detect that we should not wait for the
* device to be ready.
*/
if (column == -1 && page_addr == -1)
return;
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
*/
if (!chip->legacy.dev_ready) {
udelay(chip->legacy.chip_delay);
return;
}
}
/*
* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine.
*/
ndelay(100);
nand_wait_ready(chip);
}
static void nand_ccs_delay(struct nand_chip *chip)
{
/*
* The controller already takes care of waiting for tCCS when the RNDIN
* or RNDOUT command is sent, return directly.
*/
if (!(chip->options & NAND_WAIT_TCCS))
return;
/*
* Wait tCCS_min if it is correctly defined, otherwise wait 500ns
* (which should be safe for all NANDs).
*/
if (chip->setup_data_interface)
ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
else
ndelay(500);
}
/**
* nand_command_lp - [DEFAULT] Send command to NAND large page device
* @chip: NAND chip object
* @command: the command to be sent
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*
* Send command to NAND device. This is the version for the new large page
* devices. We don't have the separate regions as we have in the small page
* devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
*/
static void nand_command_lp(struct nand_chip *chip, unsigned int command,
int column, int page_addr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Emulate NAND_CMD_READOOB */
if (command == NAND_CMD_READOOB) {
column += mtd->writesize;
command = NAND_CMD_READ0;
}
/* Command latch cycle */
if (command != NAND_CMD_NONE)
chip->legacy.cmd_ctrl(chip, command,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
if (column != -1 || page_addr != -1) {
int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (chip->options & NAND_BUSWIDTH_16 &&
!nand_opcode_8bits(command))
column >>= 1;
chip->legacy.cmd_ctrl(chip, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
/* Only output a single addr cycle for 8bits opcodes. */
if (!nand_opcode_8bits(command))
chip->legacy.cmd_ctrl(chip, column >> 8, ctrl);
}
if (page_addr != -1) {
chip->legacy.cmd_ctrl(chip, page_addr, ctrl);
chip->legacy.cmd_ctrl(chip, page_addr >> 8,
NAND_NCE | NAND_ALE);
if (chip->options & NAND_ROW_ADDR_3)
chip->legacy.cmd_ctrl(chip, page_addr >> 16,
NAND_NCE | NAND_ALE);
}
}
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
/*
* Program and erase have their own busy handlers status, sequential
* in and status need no delay.
*/
switch (command) {
case NAND_CMD_NONE:
case NAND_CMD_CACHEDPROG:
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
case NAND_CMD_READID:
case NAND_CMD_SET_FEATURES:
return;
case NAND_CMD_RNDIN:
nand_ccs_delay(chip);
return;
case NAND_CMD_RESET:
if (chip->legacy.dev_ready)
break;
udelay(chip->legacy.chip_delay);
chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
/* EZ-NAND can take upto 250ms as per ONFi v4.0 */
nand_wait_status_ready(mtd, 250);
return;
case NAND_CMD_RNDOUT:
/* No ready / busy check necessary */
chip->legacy.cmd_ctrl(chip, NAND_CMD_RNDOUTSTART,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
nand_ccs_delay(chip);
return;
case NAND_CMD_READ0:
/*
* READ0 is sometimes used to exit GET STATUS mode. When this
* is the case no address cycles are requested, and we can use
* this information to detect that READSTART should not be
* issued.
*/
if (column == -1 && page_addr == -1)
return;
chip->legacy.cmd_ctrl(chip, NAND_CMD_READSTART,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE);
/* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay.
*/
if (!chip->legacy.dev_ready) {
udelay(chip->legacy.chip_delay);
return;
}
}
/*
* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine.
*/
ndelay(100);
nand_wait_ready(chip);
}
/**
* nand_get_set_features_notsupp - set/get features stub returning -ENOTSUPP
* @chip: nand chip info structure
* @addr: feature address.
* @subfeature_param: the subfeature parameters, a four bytes array.
*
* Should be used by NAND controller drivers that do not support the SET/GET
* FEATURES operations.
*/
int nand_get_set_features_notsupp(struct nand_chip *chip, int addr,
u8 *subfeature_param)
{
return -ENOTSUPP;
}
EXPORT_SYMBOL(nand_get_set_features_notsupp);
/**
* nand_wait - [DEFAULT] wait until the command is done
* @mtd: MTD device structure
* @chip: NAND chip structure
*
* Wait for command done. This applies to erase and program only.
*/
static int nand_wait(struct nand_chip *chip)
{
unsigned long timeo = 400;
u8 status;
int ret;
/*
* Apply this short delay always to ensure that we do wait tWB in any
* case on any machine.
*/
ndelay(100);
ret = nand_status_op(chip, NULL);
if (ret)
return ret;
if (in_interrupt() || oops_in_progress)
panic_nand_wait(chip, timeo);
else {
timeo = jiffies + msecs_to_jiffies(timeo);
do {
if (chip->legacy.dev_ready) {
if (chip->legacy.dev_ready(chip))
break;
} else {
ret = nand_read_data_op(chip, &status,
sizeof(status), true);
if (ret)
return ret;
if (status & NAND_STATUS_READY)
break;
}
cond_resched();
} while (time_before(jiffies, timeo));
}
ret = nand_read_data_op(chip, &status, sizeof(status), true);
if (ret)
return ret;
/* This can happen if in case of timeout or buggy dev_ready */
WARN_ON(!(status & NAND_STATUS_READY));
return status;
}
void nand_legacy_set_defaults(struct nand_chip *chip)
{
unsigned int busw = chip->options & NAND_BUSWIDTH_16;
if (chip->exec_op)
return;
/* check for proper chip_delay setup, set 20us if not */
if (!chip->legacy.chip_delay)
chip->legacy.chip_delay = 20;
/* check, if a user supplied command function given */
if (!chip->legacy.cmdfunc && !chip->exec_op)
chip->legacy.cmdfunc = nand_command;
/* check, if a user supplied wait function given */
if (chip->legacy.waitfunc == NULL)
chip->legacy.waitfunc = nand_wait;
if (!chip->select_chip)
chip->select_chip = nand_select_chip;
/* If called twice, pointers that depend on busw may need to be reset */
if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte)
chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte;
if (!chip->legacy.write_buf || chip->legacy.write_buf == nand_write_buf)
chip->legacy.write_buf = busw ? nand_write_buf16 : nand_write_buf;
if (!chip->legacy.write_byte || chip->legacy.write_byte == nand_write_byte)
chip->legacy.write_byte = busw ? nand_write_byte16 : nand_write_byte;
if (!chip->legacy.read_buf || chip->legacy.read_buf == nand_read_buf)
chip->legacy.read_buf = busw ? nand_read_buf16 : nand_read_buf;
}
void nand_legacy_adjust_cmdfunc(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/* Do not replace user supplied command function! */
if (mtd->writesize > 512 && chip->legacy.cmdfunc == nand_command)
chip->legacy.cmdfunc = nand_command_lp;
}
int nand_legacy_check_hooks(struct nand_chip *chip)
{
/*
* ->legacy.cmdfunc() is legacy and will only be used if ->exec_op() is
* not populated.
*/
if (chip->exec_op)
return 0;
/*
* Default functions assigned for ->legacy.cmdfunc() and
* ->select_chip() both expect ->legacy.cmd_ctrl() to be populated.
*/
if ((!chip->legacy.cmdfunc || !chip->select_chip) &&
!chip->legacy.cmd_ctrl) {
pr_err("->legacy.cmd_ctrl() should be provided\n");
return -EINVAL;
}
return 0;
}

View File

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include "internals.h"
/*
* Macronix AC series does not support using SET/GET_FEATURES to change

View File

@ -15,9 +15,10 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include <linux/slab.h>
#include "internals.h"
/*
* Special Micron status bit 3 indicates that the block has been
* corrected by on-die ECC and should be rewritten.
@ -74,9 +75,8 @@ struct micron_nand {
struct micron_on_die_ecc ecc;
};
static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
static int micron_nand_setup_read_retry(struct nand_chip *chip, int retry_mode)
{
struct nand_chip *chip = mtd_to_nand(mtd);
u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
@ -290,10 +290,10 @@ static int micron_nand_on_die_ecc_status_8(struct nand_chip *chip, u8 status)
}
static int
micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required,
int page)
micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
u8 status;
int ret, max_bitflips = 0;
@ -332,9 +332,8 @@ out:
}
static int
micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
micron_nand_write_page_on_die_ecc(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
int ret;
@ -342,7 +341,7 @@ micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
if (ret)
return ret;
ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
ret = nand_write_page_raw(chip, buf, oob_required, page);
micron_nand_on_die_ecc_setup(chip, false);
return ret;

View File

@ -0,0 +1,305 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
*
* Credits:
* David Woodhouse for adding multichip support
*
* Aleph One Ltd. and Toby Churchill Ltd. for supporting the
* rework for 2K page size chips
*
* This file contains all ONFI helpers.
*/
#include <linux/slab.h>
#include "internals.h"
u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
{
int i;
while (len--) {
crc ^= *p++ << 8;
for (i = 0; i < 8; i++)
crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
}
return crc;
}
/* Parse the Extended Parameter Page. */
static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
struct nand_onfi_params *p)
{
struct onfi_ext_param_page *ep;
struct onfi_ext_section *s;
struct onfi_ext_ecc_info *ecc;
uint8_t *cursor;
int ret;
int len;
int i;
len = le16_to_cpu(p->ext_param_page_length) * 16;
ep = kmalloc(len, GFP_KERNEL);
if (!ep)
return -ENOMEM;
/* Send our own NAND_CMD_PARAM. */
ret = nand_read_param_page_op(chip, 0, NULL, 0);
if (ret)
goto ext_out;
/* Use the Change Read Column command to skip the ONFI param pages. */
ret = nand_change_read_column_op(chip,
sizeof(*p) * p->num_of_param_pages,
ep, len, true);
if (ret)
goto ext_out;
ret = -EINVAL;
if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
!= le16_to_cpu(ep->crc))) {
pr_debug("fail in the CRC.\n");
goto ext_out;
}
/*
* Check the signature.
* Do not strictly follow the ONFI spec, maybe changed in future.
*/
if (strncmp(ep->sig, "EPPS", 4)) {
pr_debug("The signature is invalid.\n");
goto ext_out;
}
/* find the ECC section. */
cursor = (uint8_t *)(ep + 1);
for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) {
s = ep->sections + i;
if (s->type == ONFI_SECTION_TYPE_2)
break;
cursor += s->length * 16;
}
if (i == ONFI_EXT_SECTION_MAX) {
pr_debug("We can not find the ECC section.\n");
goto ext_out;
}
/* get the info we want. */
ecc = (struct onfi_ext_ecc_info *)cursor;
if (!ecc->codeword_size) {
pr_debug("Invalid codeword size\n");
goto ext_out;
}
chip->ecc_strength_ds = ecc->ecc_bits;
chip->ecc_step_ds = 1 << ecc->codeword_size;
ret = 0;
ext_out:
kfree(ep);
return ret;
}
/*
* Recover data with bit-wise majority
*/
static void nand_bit_wise_majority(const void **srcbufs,
unsigned int nsrcbufs,
void *dstbuf,
unsigned int bufsize)
{
int i, j, k;
for (i = 0; i < bufsize; i++) {
u8 val = 0;
for (j = 0; j < 8; j++) {
unsigned int cnt = 0;
for (k = 0; k < nsrcbufs; k++) {
const u8 *srcbuf = srcbufs[k];
if (srcbuf[i] & BIT(j))
cnt++;
}
if (cnt > nsrcbufs / 2)
val |= BIT(j);
}
((u8 *)dstbuf)[i] = val;
}
}
/*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
*/
int nand_onfi_detect(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_onfi_params *p;
struct onfi_params *onfi;
int onfi_version = 0;
char id[4];
int i, ret, val;
/* Try ONFI for unknown chip or LP */
ret = nand_readid_op(chip, 0x20, id, sizeof(id));
if (ret || strncmp(id, "ONFI", 4))
return 0;
/* ONFI chip: allocate a buffer to hold its parameter page */
p = kzalloc((sizeof(*p) * 3), GFP_KERNEL);
if (!p)
return -ENOMEM;
ret = nand_read_param_page_op(chip, 0, NULL, 0);
if (ret) {
ret = 0;
goto free_onfi_param_page;
}
for (i = 0; i < 3; i++) {
ret = nand_read_data_op(chip, &p[i], sizeof(*p), true);
if (ret) {
ret = 0;
goto free_onfi_param_page;
}
if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) ==
le16_to_cpu(p->crc)) {
if (i)
memcpy(p, &p[i], sizeof(*p));
break;
}
}
if (i == 3) {
const void *srcbufs[3] = {p, p + 1, p + 2};
pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n");
nand_bit_wise_majority(srcbufs, ARRAY_SIZE(srcbufs), p,
sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (u8 *)p, 254) !=
le16_to_cpu(p->crc)) {
pr_err("ONFI parameter recovery failed, aborting\n");
goto free_onfi_param_page;
}
}
if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
chip->manufacturer.desc->ops->fixup_onfi_param_page)
chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p);
/* Check version */
val = le16_to_cpu(p->revision);
if (val & ONFI_VERSION_2_3)
onfi_version = 23;
else if (val & ONFI_VERSION_2_2)
onfi_version = 22;
else if (val & ONFI_VERSION_2_1)
onfi_version = 21;
else if (val & ONFI_VERSION_2_0)
onfi_version = 20;
else if (val & ONFI_VERSION_1_0)
onfi_version = 10;
if (!onfi_version) {
pr_info("unsupported ONFI version: %d\n", val);
goto free_onfi_param_page;
}
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
sanitize_string(p->model, sizeof(p->model));
chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
if (!chip->parameters.model) {
ret = -ENOMEM;
goto free_onfi_param_page;
}
mtd->writesize = le32_to_cpu(p->byte_per_page);
/*
* pages_per_block and blocks_per_lun may not be a power-of-2 size
* (don't ask me who thought of this...). MTD assumes that these
* dimensions will be power-of-2, so just truncate the remaining area.
*/
mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
mtd->erasesize *= mtd->writesize;
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
/* See erasesize comment */
chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
chip->bits_per_cell = p->bits_per_cell;
chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);
if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS)
chip->options |= NAND_BUSWIDTH_16;
if (p->ecc_bits != 0xff) {
chip->ecc_strength_ds = p->ecc_bits;
chip->ecc_step_ds = 512;
} else if (onfi_version >= 21 &&
(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
/*
* The nand_flash_detect_ext_param_page() uses the
* Change Read Column command which maybe not supported
* by the chip->legacy.cmdfunc. So try to update the
* chip->legacy.cmdfunc now. We do not replace user supplied
* command function.
*/
nand_legacy_adjust_cmdfunc(chip);
/* The Extended Parameter Page is supported since ONFI 2.1. */
if (nand_flash_detect_ext_param_page(chip, p))
pr_warn("Failed to detect ONFI extended param page\n");
} else {
pr_warn("Could not retrieve ONFI ECC requirements\n");
}
/* Save some parameters from the parameter page for future use */
if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) {
chip->parameters.supports_set_get_features = true;
bitmap_set(chip->parameters.get_feature_list,
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
bitmap_set(chip->parameters.set_feature_list,
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
}
onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
if (!onfi) {
ret = -ENOMEM;
goto free_model;
}
onfi->version = onfi_version;
onfi->tPROG = le16_to_cpu(p->t_prog);
onfi->tBERS = le16_to_cpu(p->t_bers);
onfi->tR = le16_to_cpu(p->t_r);
onfi->tCCS = le16_to_cpu(p->t_ccs);
onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
chip->parameters.onfi = onfi;
/* Identification done, free the full ONFI parameter page and exit */
kfree(p);
return 1;
free_model:
kfree(chip->parameters.model);
free_onfi_param_page:
kfree(p);
return ret;
}

View File

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include "internals.h"
static void samsung_nand_decode_id(struct nand_chip *chip)
{

View File

@ -11,7 +11,8 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/mtd/rawnand.h>
#include "internals.h"
#define ONFI_DYN_TIMING_MAX U16_MAX
@ -270,20 +271,6 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
},
};
/**
* onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
* timings according to the given ONFI timing mode
* @mode: ONFI timing mode
*/
const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
{
if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
return ERR_PTR(-EINVAL);
return &onfi_sdr_timings[mode].timings.sdr;
}
EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
/**
* onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
* given ONFI mode
@ -339,4 +326,3 @@ int onfi_fill_data_interface(struct nand_chip *chip,
return 0;
}
EXPORT_SYMBOL(onfi_fill_data_interface);

View File

@ -15,7 +15,88 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/rawnand.h>
#include "internals.h"
/* Bit for detecting BENAND */
#define TOSHIBA_NAND_ID4_IS_BENAND BIT(7)
/* Recommended to rewrite for BENAND */
#define TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED BIT(3)
static int toshiba_nand_benand_eccstatus(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
unsigned int max_bitflips = 0;
u8 status;
/* Check Status */
ret = nand_status_op(chip, &status);
if (ret)
return ret;
if (status & NAND_STATUS_FAIL) {
/* uncorrected */
mtd->ecc_stats.failed++;
} else if (status & TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED) {
/* corrected */
max_bitflips = mtd->bitflip_threshold;
mtd->ecc_stats.corrected += max_bitflips;
}
return max_bitflips;
}
static int
toshiba_nand_read_page_benand(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
int ret;
ret = nand_read_page_raw(chip, buf, oob_required, page);
if (ret)
return ret;
return toshiba_nand_benand_eccstatus(chip);
}
static int
toshiba_nand_read_subpage_benand(struct nand_chip *chip, uint32_t data_offs,
uint32_t readlen, uint8_t *bufpoi, int page)
{
int ret;
ret = nand_read_page_op(chip, page, data_offs,
bufpoi + data_offs, readlen);
if (ret)
return ret;
return toshiba_nand_benand_eccstatus(chip);
}
static void toshiba_nand_benand_init(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
/*
* On BENAND, the entire OOB region can be used by the MTD user.
* The calculated ECC bytes are stored into other isolated
* area which is not accessible to users.
* This is why chip->ecc.bytes = 0.
*/
chip->ecc.bytes = 0;
chip->ecc.size = 512;
chip->ecc.strength = 8;
chip->ecc.read_page = toshiba_nand_read_page_benand;
chip->ecc.read_subpage = toshiba_nand_read_subpage_benand;
chip->ecc.write_page = nand_write_page_raw;
chip->ecc.read_page_raw = nand_read_page_raw_notsupp;
chip->ecc.write_page_raw = nand_write_page_raw_notsupp;
chip->options |= NAND_SUBPAGE_READ;
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
}
static void toshiba_nand_decode_id(struct nand_chip *chip)
{
@ -68,6 +149,11 @@ static int toshiba_nand_init(struct nand_chip *chip)
if (nand_is_slc(chip))
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
/* Check that chip is BENAND and ECC mode is on-die */
if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
chip->id.data[4] & TOSHIBA_NAND_ID4_IS_BENAND)
toshiba_nand_benand_init(chip);
return 0;
}

View File

@ -656,7 +656,7 @@ static int __init init_nandsim(struct mtd_info *mtd)
}
/* Force mtd to not do delays */
chip->chip_delay = 0;
chip->legacy.chip_delay = 0;
/* Initialize the NAND flash parameters */
ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
@ -1872,9 +1872,8 @@ static void switch_state(struct nandsim *ns)
}
}
static u_char ns_nand_read_byte(struct mtd_info *mtd)
static u_char ns_nand_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nandsim *ns = nand_get_controller_data(chip);
u_char outb = 0x00;
@ -1934,9 +1933,8 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
return outb;
}
static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
static void ns_nand_write_byte(struct nand_chip *chip, u_char byte)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nandsim *ns = nand_get_controller_data(chip);
/* Sanity and correctness checks */
@ -2089,9 +2087,8 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
return;
}
static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
static void ns_hwcontrol(struct nand_chip *chip, int cmd, unsigned int bitmask)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nandsim *ns = nand_get_controller_data(chip);
ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
@ -2099,27 +2096,18 @@ static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
if (cmd != NAND_CMD_NONE)
ns_nand_write_byte(mtd, cmd);
ns_nand_write_byte(chip, cmd);
}
static int ns_device_ready(struct mtd_info *mtd)
static int ns_device_ready(struct nand_chip *chip)
{
NS_DBG("device_ready\n");
return 1;
}
static uint16_t ns_nand_read_word(struct mtd_info *mtd)
static void ns_nand_write_buf(struct nand_chip *chip, const u_char *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
NS_DBG("read_word\n");
return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
}
static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nandsim *ns = nand_get_controller_data(chip);
/* Check that chip is expecting data input */
@ -2145,9 +2133,8 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
}
}
static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void ns_nand_read_buf(struct nand_chip *chip, u_char *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nandsim *ns = nand_get_controller_data(chip);
/* Sanity and correctness checks */
@ -2169,7 +2156,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
int i;
for (i = 0; i < len; i++)
buf[i] = mtd_to_nand(mtd)->read_byte(mtd);
buf[i] = chip->legacy.read_byte(chip);
return;
}
@ -2262,12 +2249,11 @@ static int __init ns_init_module(void)
/*
* Register simulator's callbacks.
*/
chip->cmd_ctrl = ns_hwcontrol;
chip->read_byte = ns_nand_read_byte;
chip->dev_ready = ns_device_ready;
chip->write_buf = ns_nand_write_buf;
chip->read_buf = ns_nand_read_buf;
chip->read_word = ns_nand_read_word;
chip->legacy.cmd_ctrl = ns_hwcontrol;
chip->legacy.read_byte = ns_nand_read_byte;
chip->legacy.dev_ready = ns_device_ready;
chip->legacy.write_buf = ns_nand_write_buf;
chip->legacy.read_buf = ns_nand_read_buf;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
/* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */
@ -2319,7 +2305,7 @@ static int __init ns_init_module(void)
goto error;
chip->dummy_controller.ops = &ns_controller_ops;
retval = nand_scan(nsmtd, 1);
retval = nand_scan(chip, 1);
if (retval) {
NS_ERR("Could not scan NAND Simulator device\n");
goto error;
@ -2364,7 +2350,7 @@ static int __init ns_init_module(void)
err_exit:
free_nandsim(nand);
nand_release(nsmtd);
nand_release(chip);
for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
kfree(nand->partitions[i].name);
error:
@ -2386,7 +2372,7 @@ static void __exit ns_cleanup_module(void)
int i;
free_nandsim(ns); /* Free nandsim private resources */
nand_release(nsmtd); /* Unregister driver */
nand_release(chip); /* Unregister driver */
for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
kfree(ns->partitions[i].name);
kfree(mtd_to_nand(nsmtd)); /* Free other structures */

View File

@ -44,10 +44,9 @@ struct ndfc_controller {
static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
static void ndfc_select_chip(struct mtd_info *mtd, int chip)
static void ndfc_select_chip(struct nand_chip *nchip, int chip)
{
uint32_t ccr;
struct nand_chip *nchip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(nchip);
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
@ -59,9 +58,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void ndfc_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
if (cmd == NAND_CMD_NONE)
@ -73,18 +71,16 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
}
static int ndfc_ready(struct mtd_info *mtd)
static int ndfc_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
}
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
static void ndfc_enable_hwecc(struct nand_chip *chip, int mode)
{
uint32_t ccr;
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
@ -93,10 +89,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
wmb();
}
static int ndfc_calculate_ecc(struct mtd_info *mtd,
static int ndfc_calculate_ecc(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
uint32_t ecc;
uint8_t *p = (uint8_t *)&ecc;
@ -118,9 +113,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
* functions. No further checking, as nand_base will always read/write
* page aligned.
*/
static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void ndfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
uint32_t *p = (uint32_t *) buf;
@ -128,9 +122,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
*p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
}
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void ndfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct ndfc_controller *ndfc = nand_get_controller_data(chip);
uint32_t *p = (uint32_t *) buf;
@ -149,15 +142,15 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
chip->cmd_ctrl = ndfc_hwcontrol;
chip->dev_ready = ndfc_ready;
chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
chip->legacy.cmd_ctrl = ndfc_hwcontrol;
chip->legacy.dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
chip->legacy.chip_delay = 50;
chip->controller = &ndfc->ndfc_control;
chip->read_buf = ndfc_read_buf;
chip->write_buf = ndfc_write_buf;
chip->legacy.read_buf = ndfc_read_buf;
chip->legacy.write_buf = ndfc_write_buf;
chip->ecc.correct = nand_correct_data;
chip->ecc.hwctl = ndfc_enable_hwecc;
chip->ecc.calculate = ndfc_calculate_ecc;
@ -174,14 +167,14 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
return -ENODEV;
nand_set_flash_node(chip, flash_np);
mtd->name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev),
flash_np->name);
mtd->name = kasprintf(GFP_KERNEL, "%s.%pOFn", dev_name(&ndfc->ofdev->dev),
flash_np);
if (!mtd->name) {
ret = -ENOMEM;
goto err;
}
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
goto err;
@ -258,7 +251,7 @@ static int ndfc_remove(struct platform_device *ofdev)
struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
struct mtd_info *mtd = nand_to_mtd(&ndfc->chip);
nand_release(mtd);
nand_release(&ndfc->chip);
kfree(mtd->name);
return 0;

View File

@ -79,31 +79,31 @@ static const struct mtd_partition partitions[] = {
}
};
static unsigned char nuc900_nand_read_byte(struct mtd_info *mtd)
static unsigned char nuc900_nand_read_byte(struct nand_chip *chip)
{
unsigned char ret;
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
ret = (unsigned char)read_data_reg(nand);
return ret;
}
static void nuc900_nand_read_buf(struct mtd_info *mtd,
static void nuc900_nand_read_buf(struct nand_chip *chip,
unsigned char *buf, int len)
{
int i;
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
for (i = 0; i < len; i++)
buf[i] = (unsigned char)read_data_reg(nand);
}
static void nuc900_nand_write_buf(struct mtd_info *mtd,
static void nuc900_nand_write_buf(struct nand_chip *chip,
const unsigned char *buf, int len)
{
int i;
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
for (i = 0; i < len; i++)
write_data_reg(nand, buf[i]);
@ -120,19 +120,20 @@ static int nuc900_check_rb(struct nuc900_nand *nand)
return val;
}
static int nuc900_nand_devready(struct mtd_info *mtd)
static int nuc900_nand_devready(struct nand_chip *chip)
{
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
int ready;
ready = (nuc900_check_rb(nand)) ? 1 : 0;
return ready;
}
static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
static void nuc900_nand_command_lp(struct nand_chip *chip,
unsigned int command,
int column, int page_addr)
{
register struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
if (command == NAND_CMD_READOOB) {
@ -174,9 +175,9 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
return;
case NAND_CMD_RESET:
if (chip->dev_ready)
if (chip->legacy.dev_ready)
break;
udelay(chip->chip_delay);
udelay(chip->legacy.chip_delay);
write_cmd_reg(nand, NAND_CMD_STATUS);
write_cmd_reg(nand, command);
@ -195,8 +196,8 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
write_cmd_reg(nand, NAND_CMD_READSTART);
default:
if (!chip->dev_ready) {
udelay(chip->chip_delay);
if (!chip->legacy.dev_ready) {
udelay(chip->legacy.chip_delay);
return;
}
}
@ -205,7 +206,7 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
* any case on any machine. */
ndelay(100);
while (!chip->dev_ready(mtd))
while (!chip->legacy.dev_ready(chip))
;
}
@ -253,12 +254,12 @@ static int nuc900_nand_probe(struct platform_device *pdev)
return -ENOENT;
clk_enable(nuc900_nand->clk);
chip->cmdfunc = nuc900_nand_command_lp;
chip->dev_ready = nuc900_nand_devready;
chip->read_byte = nuc900_nand_read_byte;
chip->write_buf = nuc900_nand_write_buf;
chip->read_buf = nuc900_nand_read_buf;
chip->chip_delay = 50;
chip->legacy.cmdfunc = nuc900_nand_command_lp;
chip->legacy.dev_ready = nuc900_nand_devready;
chip->legacy.read_byte = nuc900_nand_read_byte;
chip->legacy.write_buf = nuc900_nand_write_buf;
chip->legacy.read_buf = nuc900_nand_read_buf;
chip->legacy.chip_delay = 50;
chip->options = 0;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
@ -270,7 +271,7 @@ static int nuc900_nand_probe(struct platform_device *pdev)
nuc900_nand_enable(nuc900_nand);
if (nand_scan(mtd, 1))
if (nand_scan(chip, 1))
return -ENXIO;
mtd_device_register(mtd, partitions, ARRAY_SIZE(partitions));
@ -284,7 +285,7 @@ static int nuc900_nand_remove(struct platform_device *pdev)
{
struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&nuc900_nand->chip));
nand_release(&nuc900_nand->chip);
clk_disable(nuc900_nand->clk);
return 0;

View File

@ -240,7 +240,7 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
/**
* omap_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure
* @chip: NAND chip object
* @cmd: command to device
* @ctrl:
* NAND_NCE: bit 0 -> don't care
@ -249,9 +249,9 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
*
* NOTE: boards may use different bits for these!!
*/
static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void omap_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
if (cmd != NAND_CMD_NONE) {
if (ctrl & NAND_CLE)
@ -275,7 +275,7 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
{
struct nand_chip *nand = mtd_to_nand(mtd);
ioread8_rep(nand->IO_ADDR_R, buf, len);
ioread8_rep(nand->legacy.IO_ADDR_R, buf, len);
}
/**
@ -291,7 +291,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
bool status;
while (len--) {
iowrite8(*p++, info->nand.IO_ADDR_W);
iowrite8(*p++, info->nand.legacy.IO_ADDR_W);
/* wait until buffer is available for write */
do {
status = info->ops->nand_writebuffer_empty();
@ -309,7 +309,7 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
{
struct nand_chip *nand = mtd_to_nand(mtd);
ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
ioread16_rep(nand->legacy.IO_ADDR_R, buf, len / 2);
}
/**
@ -327,7 +327,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
len >>= 1;
while (len--) {
iowrite16(*p++, info->nand.IO_ADDR_W);
iowrite16(*p++, info->nand.legacy.IO_ADDR_W);
/* wait until buffer is available for write */
do {
status = info->ops->nand_writebuffer_empty();
@ -337,12 +337,13 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
/**
* omap_read_buf_pref - read data from NAND controller into buffer
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*/
static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
static void omap_read_buf_pref(struct nand_chip *chip, u_char *buf, int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct omap_nand_info *info = mtd_to_omap(mtd);
uint32_t r_count = 0;
int ret = 0;
@ -372,7 +373,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
r_count = readl(info->reg.gpmc_prefetch_status);
r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
r_count = r_count >> 2;
ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
ioread32_rep(info->nand.legacy.IO_ADDR_R, p, r_count);
p += r_count;
len -= r_count << 2;
} while (len);
@ -383,13 +384,14 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
/**
* omap_write_buf_pref - write buffer to NAND controller
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*/
static void omap_write_buf_pref(struct mtd_info *mtd,
const u_char *buf, int len)
static void omap_write_buf_pref(struct nand_chip *chip, const u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct omap_nand_info *info = mtd_to_omap(mtd);
uint32_t w_count = 0;
int i = 0, ret = 0;
@ -399,7 +401,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
/* take care of subpage writes */
if (len % 2 != 0) {
writeb(*buf, info->nand.IO_ADDR_W);
writeb(*buf, info->nand.legacy.IO_ADDR_W);
p = (u16 *)(buf + 1);
len--;
}
@ -419,7 +421,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
iowrite16(*p++, info->nand.IO_ADDR_W);
iowrite16(*p++, info->nand.legacy.IO_ADDR_W);
}
/* wait for data to flushed-out before reset the prefetch */
tim = 0;
@ -528,14 +530,17 @@ out_copy:
/**
* omap_read_buf_dma_pref - read data from NAND controller into buffer
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*/
static void omap_read_buf_dma_pref(struct mtd_info *mtd, u_char *buf, int len)
static void omap_read_buf_dma_pref(struct nand_chip *chip, u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
if (len <= mtd->oobsize)
omap_read_buf_pref(mtd, buf, len);
omap_read_buf_pref(chip, buf, len);
else
/* start transfer in DMA mode */
omap_nand_dma_transfer(mtd, buf, len, 0x0);
@ -543,18 +548,20 @@ static void omap_read_buf_dma_pref(struct mtd_info *mtd, u_char *buf, int len)
/**
* omap_write_buf_dma_pref - write buffer to NAND controller
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*/
static void omap_write_buf_dma_pref(struct mtd_info *mtd,
const u_char *buf, int len)
static void omap_write_buf_dma_pref(struct nand_chip *chip, const u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
if (len <= mtd->oobsize)
omap_write_buf_pref(mtd, buf, len);
omap_write_buf_pref(chip, buf, len);
else
/* start transfer in DMA mode */
omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
omap_nand_dma_transfer(mtd, (u_char *)buf, len, 0x1);
}
/*
@ -578,14 +585,14 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
bytes = info->buf_len;
else if (!info->buf_len)
bytes = 0;
iowrite32_rep(info->nand.IO_ADDR_W,
(u32 *)info->buf, bytes >> 2);
iowrite32_rep(info->nand.legacy.IO_ADDR_W, (u32 *)info->buf,
bytes >> 2);
info->buf = info->buf + bytes;
info->buf_len -= bytes;
} else {
ioread32_rep(info->nand.IO_ADDR_R,
(u32 *)info->buf, bytes >> 2);
ioread32_rep(info->nand.legacy.IO_ADDR_R, (u32 *)info->buf,
bytes >> 2);
info->buf = info->buf + bytes;
if (this_irq == info->gpmc_irq_count)
@ -605,17 +612,19 @@ done:
/*
* omap_read_buf_irq_pref - read data from NAND controller into buffer
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*/
static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
static void omap_read_buf_irq_pref(struct nand_chip *chip, u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct omap_nand_info *info = mtd_to_omap(mtd);
int ret = 0;
if (len <= mtd->oobsize) {
omap_read_buf_pref(mtd, buf, len);
omap_read_buf_pref(chip, buf, len);
return;
}
@ -651,20 +660,21 @@ out_copy:
/*
* omap_write_buf_irq_pref - write buffer to NAND controller
* @mtd: MTD device structure
* @chip: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*/
static void omap_write_buf_irq_pref(struct mtd_info *mtd,
const u_char *buf, int len)
static void omap_write_buf_irq_pref(struct nand_chip *chip, const u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct omap_nand_info *info = mtd_to_omap(mtd);
int ret = 0;
unsigned long tim, limit;
u32 val;
if (len <= mtd->oobsize) {
omap_write_buf_pref(mtd, buf, len);
omap_write_buf_pref(chip, buf, len);
return;
}
@ -857,7 +867,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
/**
* omap_correct_data - Compares the ECC read with HW generated ECC
* @mtd: MTD device structure
* @chip: NAND chip object
* @dat: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
@ -869,10 +879,10 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
* corrected errors is returned. If uncorrectable errors exist, %-1 is
* returned.
*/
static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
static int omap_correct_data(struct nand_chip *chip, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
int blockCnt = 0, i = 0, ret = 0;
int stat = 0;
@ -900,7 +910,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
/**
* omap_calcuate_ecc - Generate non-inverted ECC bytes.
* @mtd: MTD device structure
* @chip: NAND chip object
* @dat: The pointer to data on which ecc is computed
* @ecc_code: The ecc_code buffer
*
@ -910,10 +920,10 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
* an erased page will produce an ECC mismatch between generated and read
* ECC bytes that has to be dealt with separately.
*/
static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
static int omap_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
u32 val;
val = readl(info->reg.gpmc_ecc_config);
@ -935,10 +945,9 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
* @mtd: MTD device structure
* @mode: Read/Write mode
*/
static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
static void omap_enable_hwecc(struct nand_chip *chip, int mode)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct nand_chip *chip = mtd_to_nand(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
u32 val;
@ -972,8 +981,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
/**
* omap_wait - wait until the command is done
* @mtd: MTD device structure
* @chip: NAND Chip structure
* @this: NAND Chip structure
*
* Wait function is called during Program and erase operations and
* the way it is called from MTD layer, we should wait till the NAND
@ -982,10 +990,9 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
* Erase can take up to 400ms and program up to 20ms according to
* general NAND and SmartMedia specs
*/
static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int omap_wait(struct nand_chip *this)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(this));
unsigned long timeo = jiffies;
int status, state = this->state;
@ -1012,9 +1019,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*
* Returns true if ready and false if busy.
*/
static int omap_dev_ready(struct mtd_info *mtd)
static int omap_dev_ready(struct nand_chip *chip)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
return gpiod_get_value(info->ready_gpiod);
}
@ -1030,13 +1037,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
* eccsize0 = 0 (no additional protected byte in spare area)
* eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
*/
static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
static void __maybe_unused omap_enable_hwecc_bch(struct nand_chip *chip,
int mode)
{
unsigned int bch_type;
unsigned int dev_width, nsectors;
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
enum omap_ecc ecc_opt = info->ecc_opt;
struct nand_chip *chip = mtd_to_nand(mtd);
u32 val, wr_mode;
unsigned int ecc_size1, ecc_size0;
@ -1256,7 +1263,7 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd,
/**
* omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction
* @mtd: MTD device structure
* @chip: NAND chip object
* @dat: The pointer to data on which ecc is computed
* @ecc_code: The ecc_code buffer
*
@ -1264,10 +1271,10 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd,
* when SW based correction is required as ECC is required for one sector
* at a time.
*/
static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd,
static int omap_calculate_ecc_bch_sw(struct nand_chip *chip,
const u_char *dat, u_char *ecc_calc)
{
return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0);
return _omap_calculate_ecc_bch(nand_to_mtd(chip), dat, ecc_calc, 0);
}
/**
@ -1339,7 +1346,7 @@ static int erased_sector_bitflips(u_char *data, u_char *oob,
/**
* omap_elm_correct_data - corrects page data area in case error reported
* @mtd: MTD device structure
* @chip: NAND chip object
* @data: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
@ -1348,10 +1355,10 @@ static int erased_sector_bitflips(u_char *data, u_char *oob,
* In case of non-zero ecc vector, first filter out erased-pages, and
* then process data via ELM to detect bit-flips.
*/
static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
static int omap_elm_correct_data(struct nand_chip *chip, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
{
struct omap_nand_info *info = mtd_to_omap(mtd);
struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip));
struct nand_ecc_ctrl *ecc = &info->nand.ecc;
int eccsteps = info->nand.ecc.steps;
int i , j, stat = 0;
@ -1512,7 +1519,6 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
/**
* omap_write_page_bch - BCH ecc based write page function for entire page
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
@ -1520,19 +1526,20 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
*
* Custom write page method evolved to support multi sector writing in one shot
*/
static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
uint8_t *ecc_calc = chip->ecc.calc_buf;
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
/* Enable GPMC ecc engine */
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
chip->ecc.hwctl(chip, NAND_ECC_WRITE);
/* Write data */
chip->write_buf(mtd, buf, mtd->writesize);
chip->legacy.write_buf(chip, buf, mtd->writesize);
/* Update ecc vector from GPMC result registers */
omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]);
@ -1543,14 +1550,13 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
return ret;
/* Write ecc vector to OOB area */
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
/**
* omap_write_subpage_bch - BCH hardware ECC based subpage write
* @mtd: mtd info structure
* @chip: nand chip info structure
* @offset: column address of subpage within the page
* @data_len: data length
@ -1560,11 +1566,11 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
*
* OMAP optimized subpage write method.
*/
static int omap_write_subpage_bch(struct mtd_info *mtd,
struct nand_chip *chip, u32 offset,
static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset,
u32 data_len, const u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
u8 *ecc_calc = chip->ecc.calc_buf;
int ecc_size = chip->ecc.size;
int ecc_bytes = chip->ecc.bytes;
@ -1582,10 +1588,10 @@ static int omap_write_subpage_bch(struct mtd_info *mtd,
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
/* Enable GPMC ECC engine */
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
chip->ecc.hwctl(chip, NAND_ECC_WRITE);
/* Write data */
chip->write_buf(mtd, buf, mtd->writesize);
chip->legacy.write_buf(chip, buf, mtd->writesize);
for (step = 0; step < ecc_steps; step++) {
/* mask ECC of un-touched subpages by padding 0xFF */
@ -1610,14 +1616,13 @@ static int omap_write_subpage_bch(struct mtd_info *mtd,
return ret;
/* write OOB buffer to NAND device */
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
/**
* omap_read_page_bch - BCH ecc based page read function for entire page
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
@ -1630,9 +1635,10 @@ static int omap_write_subpage_bch(struct mtd_info *mtd,
* ecc engine enabled. ecc vector updated after read of OOB data.
* For non error pages ecc vector reported as zero.
*/
static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
uint8_t *ecc_calc = chip->ecc.calc_buf;
uint8_t *ecc_code = chip->ecc.code_buf;
int stat, ret;
@ -1641,10 +1647,10 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
nand_read_page_op(chip, page, 0, NULL, 0);
/* Enable GPMC ecc engine */
chip->ecc.hwctl(mtd, NAND_ECC_READ);
chip->ecc.hwctl(chip, NAND_ECC_READ);
/* Read data */
chip->read_buf(mtd, buf, mtd->writesize);
chip->legacy.read_buf(chip, buf, mtd->writesize);
/* Read oob bytes */
nand_change_read_column_op(chip,
@ -1660,7 +1666,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
if (ret)
return ret;
stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc);
stat = chip->ecc.correct(chip, buf, ecc_code, ecc_calc);
if (stat < 0) {
mtd->ecc_stats.failed++;
@ -1927,8 +1933,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
/* Re-populate low-level callbacks based on xfer modes */
switch (info->xfer_type) {
case NAND_OMAP_PREFETCH_POLLED:
chip->read_buf = omap_read_buf_pref;
chip->write_buf = omap_write_buf_pref;
chip->legacy.read_buf = omap_read_buf_pref;
chip->legacy.write_buf = omap_write_buf_pref;
break;
case NAND_OMAP_POLLED:
@ -1960,8 +1966,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
err);
return err;
}
chip->read_buf = omap_read_buf_dma_pref;
chip->write_buf = omap_write_buf_dma_pref;
chip->legacy.read_buf = omap_read_buf_dma_pref;
chip->legacy.write_buf = omap_write_buf_dma_pref;
}
break;
@ -1996,8 +2002,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
return err;
}
chip->read_buf = omap_read_buf_irq_pref;
chip->write_buf = omap_write_buf_irq_pref;
chip->legacy.read_buf = omap_read_buf_irq_pref;
chip->legacy.write_buf = omap_write_buf_irq_pref;
break;
@ -2215,16 +2221,16 @@ static int omap_nand_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(nand_chip->IO_ADDR_R))
return PTR_ERR(nand_chip->IO_ADDR_R);
nand_chip->legacy.IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(nand_chip->legacy.IO_ADDR_R))
return PTR_ERR(nand_chip->legacy.IO_ADDR_R);
info->phys_base = res->start;
nand_chip->controller = &omap_gpmc_controller;
nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
nand_chip->cmd_ctrl = omap_hwcontrol;
nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R;
nand_chip->legacy.cmd_ctrl = omap_hwcontrol;
info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb",
GPIOD_IN);
@ -2241,11 +2247,11 @@ static int omap_nand_probe(struct platform_device *pdev)
* device and read status register until you get a failure or success
*/
if (info->ready_gpiod) {
nand_chip->dev_ready = omap_dev_ready;
nand_chip->chip_delay = 0;
nand_chip->legacy.dev_ready = omap_dev_ready;
nand_chip->legacy.chip_delay = 0;
} else {
nand_chip->waitfunc = omap_wait;
nand_chip->chip_delay = 50;
nand_chip->legacy.waitfunc = omap_wait;
nand_chip->legacy.chip_delay = 50;
}
if (info->flash_bbt)
@ -2254,7 +2260,7 @@ static int omap_nand_probe(struct platform_device *pdev)
/* scan NAND device connected to chip controller */
nand_chip->options |= info->devsize & NAND_BUSWIDTH_16;
err = nand_scan(mtd, 1);
err = nand_scan(nand_chip, 1);
if (err)
goto return_error;
@ -2290,7 +2296,7 @@ static int omap_nand_remove(struct platform_device *pdev)
}
if (info->dma)
dma_release_channel(info->dma);
nand_release(mtd);
nand_release(nand_chip);
return 0;
}

View File

@ -26,9 +26,9 @@ struct orion_nand_info {
struct clk *clk;
};
static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static void orion_nand_cmd_ctrl(struct nand_chip *nc, int cmd,
unsigned int ctrl)
{
struct nand_chip *nc = mtd_to_nand(mtd);
struct orion_nand_data *board = nand_get_controller_data(nc);
u32 offs;
@ -45,13 +45,12 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
if (nc->options & NAND_BUSWIDTH_16)
offs <<= 1;
writeb(cmd, nc->IO_ADDR_W + offs);
writeb(cmd, nc->legacy.IO_ADDR_W + offs);
}
static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
void __iomem *io_base = chip->IO_ADDR_R;
void __iomem *io_base = chip->legacy.IO_ADDR_R;
#if defined(__LINUX_ARM_ARCH__) && __LINUX_ARM_ARCH__ >= 5
uint64_t *buf64;
#endif
@ -137,14 +136,14 @@ static int __init orion_nand_probe(struct platform_device *pdev)
nand_set_controller_data(nc, board);
nand_set_flash_node(nc, pdev->dev.of_node);
nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
nc->cmd_ctrl = orion_nand_cmd_ctrl;
nc->read_buf = orion_nand_read_buf;
nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base;
nc->legacy.cmd_ctrl = orion_nand_cmd_ctrl;
nc->legacy.read_buf = orion_nand_read_buf;
nc->ecc.mode = NAND_ECC_SOFT;
nc->ecc.algo = NAND_ECC_HAMMING;
if (board->chip_delay)
nc->chip_delay = board->chip_delay;
nc->legacy.chip_delay = board->chip_delay;
WARN(board->width > 16,
"%d bit bus width out of range",
@ -174,14 +173,14 @@ static int __init orion_nand_probe(struct platform_device *pdev)
return ret;
}
ret = nand_scan(mtd, 1);
ret = nand_scan(nc, 1);
if (ret)
goto no_dev;
mtd->name = "orion_nand";
ret = mtd_device_register(mtd, board->parts, board->nr_parts);
if (ret) {
nand_release(mtd);
nand_release(nc);
goto no_dev;
}
@ -196,9 +195,8 @@ static int orion_nand_remove(struct platform_device *pdev)
{
struct orion_nand_info *info = platform_get_drvdata(pdev);
struct nand_chip *chip = &info->chip;
struct mtd_info *mtd = nand_to_mtd(chip);
nand_release(mtd);
nand_release(chip);
clk_disable_unprepare(info->clk);

View File

@ -38,35 +38,32 @@ struct oxnas_nand_ctrl {
struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS];
};
static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
static uint8_t oxnas_nand_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
return readb(oxnas->io_base);
}
static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void oxnas_nand_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
ioread8_rep(oxnas->io_base, buf, len);
}
static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void oxnas_nand_write_buf(struct nand_chip *chip, const u8 *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
iowrite8_rep(oxnas->io_base, buf, len);
}
/* Single CS command control */
static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void oxnas_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
if (ctrl & NAND_CLE)
@ -135,20 +132,20 @@ static int oxnas_nand_probe(struct platform_device *pdev)
mtd->dev.parent = &pdev->dev;
mtd->priv = chip;
chip->cmd_ctrl = oxnas_nand_cmd_ctrl;
chip->read_buf = oxnas_nand_read_buf;
chip->read_byte = oxnas_nand_read_byte;
chip->write_buf = oxnas_nand_write_buf;
chip->chip_delay = 30;
chip->legacy.cmd_ctrl = oxnas_nand_cmd_ctrl;
chip->legacy.read_buf = oxnas_nand_read_buf;
chip->legacy.read_byte = oxnas_nand_read_byte;
chip->legacy.write_buf = oxnas_nand_write_buf;
chip->legacy.chip_delay = 30;
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
err = nand_scan(chip, 1);
if (err)
goto err_clk_unprepare;
err = mtd_device_register(mtd, NULL, 0);
if (err) {
nand_release(mtd);
nand_release(chip);
goto err_clk_unprepare;
}
@ -176,7 +173,7 @@ static int oxnas_nand_remove(struct platform_device *pdev)
struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
if (oxnas->chips[0])
nand_release(nand_to_mtd(oxnas->chips[0]));
nand_release(oxnas->chips[0]);
clk_disable_unprepare(oxnas->clk);

View File

@ -43,49 +43,44 @@ static unsigned int lpcctl;
static struct mtd_info *pasemi_nand_mtd;
static const char driver_name[] = "pasemi-nand";
static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
while (len > 0x800) {
memcpy_fromio(buf, chip->IO_ADDR_R, 0x800);
memcpy_fromio(buf, chip->legacy.IO_ADDR_R, 0x800);
buf += 0x800;
len -= 0x800;
}
memcpy_fromio(buf, chip->IO_ADDR_R, len);
memcpy_fromio(buf, chip->legacy.IO_ADDR_R, len);
}
static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void pasemi_write_buf(struct nand_chip *chip, const u_char *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
while (len > 0x800) {
memcpy_toio(chip->IO_ADDR_R, buf, 0x800);
memcpy_toio(chip->legacy.IO_ADDR_R, buf, 0x800);
buf += 0x800;
len -= 0x800;
}
memcpy_toio(chip->IO_ADDR_R, buf, len);
memcpy_toio(chip->legacy.IO_ADDR_R, buf, len);
}
static void pasemi_hwcontrol(struct mtd_info *mtd, int cmd,
static void pasemi_hwcontrol(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE)
out_8(chip->IO_ADDR_W + (1 << CLE_PIN_CTL), cmd);
out_8(chip->legacy.IO_ADDR_W + (1 << CLE_PIN_CTL), cmd);
else
out_8(chip->IO_ADDR_W + (1 << ALE_PIN_CTL), cmd);
out_8(chip->legacy.IO_ADDR_W + (1 << ALE_PIN_CTL), cmd);
/* Push out posted writes */
eieio();
inl(lpcctl);
}
int pasemi_device_ready(struct mtd_info *mtd)
int pasemi_device_ready(struct nand_chip *chip)
{
return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
}
@ -122,10 +117,10 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
/* Link the private data with the MTD structure */
pasemi_nand_mtd->dev.parent = dev;
chip->IO_ADDR_R = of_iomap(np, 0);
chip->IO_ADDR_W = chip->IO_ADDR_R;
chip->legacy.IO_ADDR_R = of_iomap(np, 0);
chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R;
if (!chip->IO_ADDR_R) {
if (!chip->legacy.IO_ADDR_R) {
err = -EIO;
goto out_mtd;
}
@ -144,11 +139,11 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
goto out_ior;
}
chip->cmd_ctrl = pasemi_hwcontrol;
chip->dev_ready = pasemi_device_ready;
chip->read_buf = pasemi_read_buf;
chip->write_buf = pasemi_write_buf;
chip->chip_delay = 0;
chip->legacy.cmd_ctrl = pasemi_hwcontrol;
chip->legacy.dev_ready = pasemi_device_ready;
chip->legacy.read_buf = pasemi_read_buf;
chip->legacy.write_buf = pasemi_write_buf;
chip->legacy.chip_delay = 0;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
@ -156,7 +151,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
chip->bbt_options = NAND_BBT_USE_FLASH;
/* Scan to find existence of the device */
err = nand_scan(pasemi_nand_mtd, 1);
err = nand_scan(chip, 1);
if (err)
goto out_lpc;
@ -174,7 +169,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
out_lpc:
release_region(lpcctl, 4);
out_ior:
iounmap(chip->IO_ADDR_R);
iounmap(chip->legacy.IO_ADDR_R);
out_mtd:
kfree(chip);
out:
@ -191,11 +186,11 @@ static int pasemi_nand_remove(struct platform_device *ofdev)
chip = mtd_to_nand(pasemi_nand_mtd);
/* Release resources, unregister device */
nand_release(pasemi_nand_mtd);
nand_release(chip);
release_region(lpcctl, 4);
iounmap(chip->IO_ADDR_R);
iounmap(chip->legacy.IO_ADDR_R);
/* Free the MTD device structure */
kfree(chip);

View File

@ -15,8 +15,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/platnand.h>
struct plat_nand_data {
struct nand_chip chip;
@ -60,14 +59,14 @@ static int plat_nand_probe(struct platform_device *pdev)
mtd = nand_to_mtd(&data->chip);
mtd->dev.parent = &pdev->dev;
data->chip.IO_ADDR_R = data->io_base;
data->chip.IO_ADDR_W = data->io_base;
data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
data->chip.dev_ready = pdata->ctrl.dev_ready;
data->chip.legacy.IO_ADDR_R = data->io_base;
data->chip.legacy.IO_ADDR_W = data->io_base;
data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl;
data->chip.legacy.dev_ready = pdata->ctrl.dev_ready;
data->chip.select_chip = pdata->ctrl.select_chip;
data->chip.write_buf = pdata->ctrl.write_buf;
data->chip.read_buf = pdata->ctrl.read_buf;
data->chip.chip_delay = pdata->chip.chip_delay;
data->chip.legacy.write_buf = pdata->ctrl.write_buf;
data->chip.legacy.read_buf = pdata->ctrl.read_buf;
data->chip.legacy.chip_delay = pdata->chip.chip_delay;
data->chip.options |= pdata->chip.options;
data->chip.bbt_options |= pdata->chip.bbt_options;
@ -84,7 +83,7 @@ static int plat_nand_probe(struct platform_device *pdev)
}
/* Scan to find existence of the device */
err = nand_scan(mtd, pdata->chip.nr_chips);
err = nand_scan(&data->chip, pdata->chip.nr_chips);
if (err)
goto out;
@ -97,7 +96,7 @@ static int plat_nand_probe(struct platform_device *pdev)
if (!err)
return err;
nand_release(mtd);
nand_release(&data->chip);
out:
if (pdata->ctrl.remove)
pdata->ctrl.remove(pdev);
@ -112,7 +111,7 @@ static int plat_nand_remove(struct platform_device *pdev)
struct plat_nand_data *data = platform_get_drvdata(pdev);
struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
nand_release(nand_to_mtd(&data->chip));
nand_release(&data->chip);
if (pdata->ctrl.remove)
pdata->ctrl.remove(pdev);

View File

@ -23,7 +23,6 @@
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/dma/qcom_bam_dma.h>
#include <linux/dma-direct.h> /* XXX: drivers shall never use this directly! */
/* NANDc reg offsets */
#define NAND_FLASH_CMD 0x00
@ -350,7 +349,8 @@ struct nandc_regs {
* @data_buffer: our local DMA buffer for page read/writes,
* used when we can't use the buffer provided
* by upper layers directly
* @buf_size/count/start: markers for chip->read_buf/write_buf functions
* @buf_size/count/start: markers for chip->legacy.read_buf/write_buf
* functions
* @reg_read_buf: local buffer for reading back registers via DMA
* @reg_read_dma: contains dma address for register read buffer
* @reg_read_pos: marker for data read in reg_read_buf
@ -1155,8 +1155,8 @@ static void config_nand_cw_write(struct qcom_nand_controller *nandc)
}
/*
* the following functions are used within chip->cmdfunc() to perform different
* NAND_CMD_* commands
* the following functions are used within chip->legacy.cmdfunc() to
* perform different NAND_CMD_* commands
*/
/* sets up descriptors for NAND_CMD_PARAM */
@ -1436,15 +1436,14 @@ static void post_command(struct qcom_nand_host *host, int command)
}
/*
* Implements chip->cmdfunc. It's only used for a limited set of commands.
* The rest of the commands wouldn't be called by upper layers. For example,
* NAND_CMD_READOOB would never be called because we have our own versions
* of read_oob ops for nand_ecc_ctrl.
* Implements chip->legacy.cmdfunc. It's only used for a limited set of
* commands. The rest of the commands wouldn't be called by upper layers.
* For example, NAND_CMD_READOOB would never be called because we have our own
* versions of read_oob ops for nand_ecc_ctrl.
*/
static void qcom_nandc_command(struct mtd_info *mtd, unsigned int command,
static void qcom_nandc_command(struct nand_chip *chip, unsigned int command,
int column, int page_addr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
@ -1949,8 +1948,8 @@ static int copy_last_cw(struct qcom_nand_host *host, int page)
}
/* implements ecc->read_page() */
static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int qcom_nandc_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
@ -1966,10 +1965,10 @@ static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
}
/* implements ecc->read_page_raw() */
static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf,
static int qcom_nandc_read_page_raw(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int cw, ret;
@ -1989,8 +1988,7 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
}
/* implements ecc->read_oob() */
static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int qcom_nandc_read_oob(struct nand_chip *chip, int page)
{
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
@ -2007,8 +2005,8 @@ static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
}
/* implements ecc->write_page() */
static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
static int qcom_nandc_write_page(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
@ -2077,10 +2075,11 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
}
/* implements ecc->write_page_raw() */
static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
static int qcom_nandc_write_page_raw(struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
@ -2155,9 +2154,9 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
* since ECC is calculated for the combined codeword. So update the OOB from
* chip->oob_poi, and pad the data area with OxFF before writing.
*/
static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int qcom_nandc_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
@ -2197,9 +2196,9 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
return nand_prog_page_end_op(chip);
}
static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
static int qcom_nandc_block_bad(struct nand_chip *chip, loff_t ofs)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(chip);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
@ -2235,9 +2234,8 @@ err:
return bad;
}
static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
static int qcom_nandc_block_markbad(struct nand_chip *chip, loff_t ofs)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
@ -2278,14 +2276,13 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
}
/*
* the three functions below implement chip->read_byte(), chip->read_buf()
* and chip->write_buf() respectively. these aren't used for
* reading/writing page data, they are used for smaller data like reading
* id, status etc
* the three functions below implement chip->legacy.read_byte(),
* chip->legacy.read_buf() and chip->legacy.write_buf() respectively. these
* aren't used for reading/writing page data, they are used for smaller data
* like reading id, status etc
*/
static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
static uint8_t qcom_nandc_read_byte(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
u8 *buf = nandc->data_buffer;
@ -2305,9 +2302,8 @@ static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
return ret;
}
static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void qcom_nandc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
@ -2315,10 +2311,9 @@ static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
nandc->buf_start += real_len;
}
static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
static void qcom_nandc_write_buf(struct nand_chip *chip, const uint8_t *buf,
int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
@ -2328,9 +2323,8 @@ static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
}
/* we support only one external chip for now */
static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
static void qcom_nandc_select_chip(struct nand_chip *chip, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
if (chipnr <= 0)
@ -2809,13 +2803,13 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
mtd->owner = THIS_MODULE;
mtd->dev.parent = dev;
chip->cmdfunc = qcom_nandc_command;
chip->legacy.cmdfunc = qcom_nandc_command;
chip->select_chip = qcom_nandc_select_chip;
chip->read_byte = qcom_nandc_read_byte;
chip->read_buf = qcom_nandc_read_buf;
chip->write_buf = qcom_nandc_write_buf;
chip->set_features = nand_get_set_features_notsupp;
chip->get_features = nand_get_set_features_notsupp;
chip->legacy.read_byte = qcom_nandc_read_byte;
chip->legacy.read_buf = qcom_nandc_read_buf;
chip->legacy.write_buf = qcom_nandc_write_buf;
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
/*
* the bad block marker is readable only when we read the last codeword
@ -2825,8 +2819,8 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
* and block_markbad helpers until we permanently switch to using
* MTD_OPS_RAW for all drivers (with the help of badblockbits)
*/
chip->block_bad = qcom_nandc_block_bad;
chip->block_markbad = qcom_nandc_block_markbad;
chip->legacy.block_bad = qcom_nandc_block_bad;
chip->legacy.block_markbad = qcom_nandc_block_markbad;
chip->controller = &nandc->controller;
chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER |
@ -2835,7 +2829,7 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
/* set up initial status value */
host->status = NAND_STATUS_READY | NAND_STATUS_WP;
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
return ret;
@ -3000,7 +2994,7 @@ static int qcom_nandc_remove(struct platform_device *pdev)
struct qcom_nand_host *host;
list_for_each_entry(host, &nandc->host_list, node)
nand_release(nand_to_mtd(&host->chip));
nand_release(&host->chip);
qcom_nandc_unalloc(nandc);

View File

@ -232,9 +232,9 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
/*
* Program data lines of the nand chip to send data to it
*/
static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void r852_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
uint32_t reg;
/* Don't allow any access to hardware if we suspect card removal */
@ -266,9 +266,9 @@ static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
/*
* Read data lines of the nand chip to retrieve data
*/
static void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void r852_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
uint32_t reg;
if (dev->card_unstable) {
@ -303,9 +303,9 @@ static void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
/*
* Read one byte from nand chip
*/
static uint8_t r852_read_byte(struct mtd_info *mtd)
static uint8_t r852_read_byte(struct nand_chip *chip)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
/* Same problem as in r852_read_buf.... */
if (dev->card_unstable)
@ -317,9 +317,9 @@ static uint8_t r852_read_byte(struct mtd_info *mtd)
/*
* Control several chip lines & send commands
*/
static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
static void r852_cmdctl(struct nand_chip *chip, int dat, unsigned int ctrl)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
if (dev->card_unstable)
return;
@ -362,7 +362,7 @@ static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
* Wait till card is ready.
* based on nand_wait, but returns errors on DMA error
*/
static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int r852_wait(struct nand_chip *chip)
{
struct r852_device *dev = nand_get_controller_data(chip);
@ -373,7 +373,7 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
msecs_to_jiffies(400) : msecs_to_jiffies(20));
while (time_before(jiffies, timeout))
if (chip->dev_ready(mtd))
if (chip->legacy.dev_ready(chip))
break;
nand_status_op(chip, &status);
@ -390,9 +390,9 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
* Check if card is ready
*/
static int r852_ready(struct mtd_info *mtd)
static int r852_ready(struct nand_chip *chip)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY);
}
@ -401,9 +401,9 @@ static int r852_ready(struct mtd_info *mtd)
* Set ECC engine mode
*/
static void r852_ecc_hwctl(struct mtd_info *mtd, int mode)
static void r852_ecc_hwctl(struct nand_chip *chip, int mode)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
if (dev->card_unstable)
return;
@ -433,10 +433,10 @@ static void r852_ecc_hwctl(struct mtd_info *mtd, int mode)
* Calculate ECC, only used for writes
*/
static int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
static int r852_ecc_calculate(struct nand_chip *chip, const uint8_t *dat,
uint8_t *ecc_code)
{
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
struct sm_oob *oob = (struct sm_oob *)ecc_code;
uint32_t ecc1, ecc2;
@ -465,14 +465,14 @@ static int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
* Correct the data using ECC, hw did almost everything for us
*/
static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
static int r852_ecc_correct(struct nand_chip *chip, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
uint32_t ecc_reg;
uint8_t ecc_status, err_byte;
int i, error = 0;
struct r852_device *dev = r852_get_dev(mtd);
struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
if (dev->card_unstable)
return 0;
@ -521,9 +521,10 @@ exit:
* This is copy of nand_read_oob_std
* nand_read_oob_syndrome assumes we can send column address - we can't
*/
static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int r852_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
}
@ -636,7 +637,7 @@ static int r852_register_nand_device(struct r852_device *dev)
{
struct mtd_info *mtd = nand_to_mtd(dev->chip);
WARN_ON(dev->card_registred);
WARN_ON(dev->card_registered);
mtd->dev.parent = &dev->pci_dev->dev;
@ -653,10 +654,10 @@ static int r852_register_nand_device(struct r852_device *dev)
goto error3;
}
dev->card_registred = 1;
dev->card_registered = 1;
return 0;
error3:
nand_release(mtd);
nand_release(dev->chip);
error1:
/* Force card redetect */
dev->card_detected = 0;
@ -671,13 +672,13 @@ static void r852_unregister_nand_device(struct r852_device *dev)
{
struct mtd_info *mtd = nand_to_mtd(dev->chip);
if (!dev->card_registred)
if (!dev->card_registered)
return;
device_remove_file(&mtd->dev, &dev_attr_media_type);
nand_release(mtd);
nand_release(dev->chip);
r852_engine_disable(dev);
dev->card_registred = 0;
dev->card_registered = 0;
}
/* Card state updater */
@ -691,7 +692,7 @@ static void r852_card_detect_work(struct work_struct *work)
dev->card_unstable = 0;
/* False alarm */
if (dev->card_detected == dev->card_registred)
if (dev->card_detected == dev->card_registered)
goto exit;
/* Read media properties */
@ -852,14 +853,14 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
goto error4;
/* commands */
chip->cmd_ctrl = r852_cmdctl;
chip->waitfunc = r852_wait;
chip->dev_ready = r852_ready;
chip->legacy.cmd_ctrl = r852_cmdctl;
chip->legacy.waitfunc = r852_wait;
chip->legacy.dev_ready = r852_ready;
/* I/O */
chip->read_byte = r852_read_byte;
chip->read_buf = r852_read_buf;
chip->write_buf = r852_write_buf;
chip->legacy.read_byte = r852_read_byte;
chip->legacy.read_buf = r852_read_buf;
chip->legacy.write_buf = r852_write_buf;
/* ecc */
chip->ecc.mode = NAND_ECC_HW_SYNDROME;
@ -1025,7 +1026,6 @@ static int r852_suspend(struct device *device)
static int r852_resume(struct device *device)
{
struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
struct mtd_info *mtd = nand_to_mtd(dev->chip);
r852_disable_irqs(dev);
r852_card_update_present(dev);
@ -1033,7 +1033,7 @@ static int r852_resume(struct device *device)
/* If card status changed, just do the work */
if (dev->card_detected != dev->card_registred) {
if (dev->card_detected != dev->card_registered) {
dbg("card was %s during low power state",
dev->card_detected ? "added" : "removed");
@ -1043,11 +1043,11 @@ static int r852_resume(struct device *device)
}
/* Otherwise, initialize the card */
if (dev->card_registred) {
if (dev->card_registered) {
r852_engine_enable(dev);
dev->chip->select_chip(mtd, 0);
dev->chip->select_chip(dev->chip, 0);
nand_reset_op(dev->chip);
dev->chip->select_chip(mtd, -1);
dev->chip->select_chip(dev->chip, -1);
}
/* Program card detection IRQ */

View File

@ -129,7 +129,7 @@ struct r852_device {
/* card status area */
struct delayed_work card_detect_work;
struct workqueue_struct *card_workqueue;
int card_registred; /* card registered with mtd */
int card_registered; /* card registered with mtd */
int card_detected; /* card detected in slot */
int card_unstable; /* whenever the card is inserted,
is not known yet */

View File

@ -404,7 +404,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
/**
* s3c2410_nand_select_chip - select the given nand chip
* @mtd: The MTD instance for this chip.
* @this: NAND chip object.
* @chip: The chip number.
*
* This is called by the MTD layer to either select a given chip for the
@ -415,11 +415,10 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
* platform specific selection code is called to route nFCE to the specific
* chip.
*/
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
static void s3c2410_nand_select_chip(struct nand_chip *this, int chip)
{
struct s3c2410_nand_info *info;
struct s3c2410_nand_mtd *nmtd;
struct nand_chip *this = mtd_to_nand(mtd);
unsigned long cur;
nmtd = nand_get_controller_data(this);
@ -457,9 +456,10 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
* Issue command and address cycles to the chip
*/
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
static void s3c2410_nand_hwcontrol(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
if (cmd == NAND_CMD_NONE)
@ -473,9 +473,10 @@ static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
/* command and control functions */
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
static void s3c2440_nand_hwcontrol(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
if (cmd == NAND_CMD_NONE)
@ -492,29 +493,33 @@ static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2410_nand_devready(struct mtd_info *mtd)
static int s3c2410_nand_devready(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
}
static int s3c2440_nand_devready(struct mtd_info *mtd)
static int s3c2440_nand_devready(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
}
static int s3c2412_nand_devready(struct mtd_info *mtd)
static int s3c2412_nand_devready(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
}
/* ECC handling functions */
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
static int s3c2410_nand_correct_data(struct nand_chip *chip, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
unsigned int diff0, diff1, diff2;
unsigned int bit, byte;
@ -591,38 +596,42 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
* generator block to ECC the data as it passes through]
*/
static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
static void s3c2410_nand_enable_hwecc(struct nand_chip *chip, int mode)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct s3c2410_nand_info *info;
unsigned long ctrl;
info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
ctrl = readl(info->regs + S3C2410_NFCONF);
ctrl |= S3C2410_NFCONF_INITECC;
writel(ctrl, info->regs + S3C2410_NFCONF);
}
static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode)
static void s3c2412_nand_enable_hwecc(struct nand_chip *chip, int mode)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct s3c2410_nand_info *info;
unsigned long ctrl;
info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
ctrl = readl(info->regs + S3C2440_NFCONT);
writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC,
info->regs + S3C2440_NFCONT);
}
static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
static void s3c2440_nand_enable_hwecc(struct nand_chip *chip, int mode)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct s3c2410_nand_info *info;
unsigned long ctrl;
info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
ctrl = readl(info->regs + S3C2440_NFCONT);
writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
}
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
static int s3c2410_nand_calculate_ecc(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0);
@ -634,9 +643,10 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
return 0;
}
static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
static int s3c2412_nand_calculate_ecc(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
@ -649,9 +659,10 @@ static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
return 0;
}
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
static int s3c2440_nand_calculate_ecc(struct nand_chip *chip,
const u_char *dat, u_char *ecc_code)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
@ -668,14 +679,14 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
* use read/write block to move the data buffers to/from the controller
*/
static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void s3c2410_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
readsb(this->IO_ADDR_R, buf, len);
readsb(this->legacy.IO_ADDR_R, buf, len);
}
static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
{
struct mtd_info *mtd = nand_to_mtd(this);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
@ -689,16 +700,16 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
}
}
static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
static void s3c2410_nand_write_buf(struct nand_chip *this, const u_char *buf,
int len)
{
struct nand_chip *this = mtd_to_nand(mtd);
writesb(this->IO_ADDR_W, buf, len);
writesb(this->legacy.IO_ADDR_W, buf, len);
}
static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
static void s3c2440_nand_write_buf(struct nand_chip *this, const u_char *buf,
int len)
{
struct mtd_info *mtd = nand_to_mtd(this);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
@ -781,7 +792,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
nand_release(nand_to_mtd(&ptr->chip));
nand_release(&ptr->chip);
}
}
@ -809,9 +820,10 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
return -ENODEV;
}
static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd, int csline,
static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct s3c2410_platform_nand *pdata = info->platform;
const struct nand_sdr_timings *timings;
@ -852,10 +864,10 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
nand_set_flash_node(chip, set->of_node);
chip->write_buf = s3c2410_nand_write_buf;
chip->read_buf = s3c2410_nand_read_buf;
chip->legacy.write_buf = s3c2410_nand_write_buf;
chip->legacy.read_buf = s3c2410_nand_read_buf;
chip->select_chip = s3c2410_nand_select_chip;
chip->chip_delay = 50;
chip->legacy.chip_delay = 50;
nand_set_controller_data(chip, nmtd);
chip->options = set->options;
chip->controller = &info->controller;
@ -869,29 +881,29 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
switch (info->cpu_type) {
case TYPE_S3C2410:
chip->IO_ADDR_W = regs + S3C2410_NFDATA;
chip->legacy.IO_ADDR_W = regs + S3C2410_NFDATA;
info->sel_reg = regs + S3C2410_NFCONF;
info->sel_bit = S3C2410_NFCONF_nFCE;
chip->cmd_ctrl = s3c2410_nand_hwcontrol;
chip->dev_ready = s3c2410_nand_devready;
chip->legacy.cmd_ctrl = s3c2410_nand_hwcontrol;
chip->legacy.dev_ready = s3c2410_nand_devready;
break;
case TYPE_S3C2440:
chip->IO_ADDR_W = regs + S3C2440_NFDATA;
chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
info->sel_reg = regs + S3C2440_NFCONT;
info->sel_bit = S3C2440_NFCONT_nFCE;
chip->cmd_ctrl = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
chip->read_buf = s3c2440_nand_read_buf;
chip->write_buf = s3c2440_nand_write_buf;
chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol;
chip->legacy.dev_ready = s3c2440_nand_devready;
chip->legacy.read_buf = s3c2440_nand_read_buf;
chip->legacy.write_buf = s3c2440_nand_write_buf;
break;
case TYPE_S3C2412:
chip->IO_ADDR_W = regs + S3C2440_NFDATA;
chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
info->sel_reg = regs + S3C2440_NFCONT;
info->sel_bit = S3C2412_NFCONT_nFCE0;
chip->cmd_ctrl = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2412_nand_devready;
chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol;
chip->legacy.dev_ready = s3c2412_nand_devready;
if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
dev_info(info->device, "System booted from NAND\n");
@ -899,7 +911,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
break;
}
chip->IO_ADDR_R = chip->IO_ADDR_W;
chip->legacy.IO_ADDR_R = chip->legacy.IO_ADDR_W;
nmtd->info = info;
nmtd->set = set;
@ -1170,7 +1182,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
mtd->dev.parent = &pdev->dev;
s3c2410_nand_init_chip(info, nmtd, sets);
err = nand_scan(mtd, sets ? sets->nr_chips : 1);
err = nand_scan(&nmtd->chip, sets ? sets->nr_chips : 1);
if (err)
goto exit_error;

View File

@ -480,7 +480,7 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
/* initiate DMA transfer */
if (flctl->chan_fifo0_rx && rlen >= 32 &&
flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0)
flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0)
goto convert; /* DMA success */
/* do polling transfer */
@ -539,7 +539,7 @@ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen,
/* initiate DMA transfer */
if (flctl->chan_fifo0_tx && rlen >= 32 &&
flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0)
flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0)
return; /* DMA success */
/* do polling transfer */
@ -611,21 +611,24 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
writel(flcmcdr_val, FLCMCDR(flctl));
}
static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
static int flctl_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
return 0;
}
static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
static int flctl_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
@ -747,9 +750,10 @@ static void execmd_write_oob(struct mtd_info *mtd)
}
}
static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command,
static void flctl_cmdfunc(struct nand_chip *chip, unsigned int command,
int column, int page_addr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct sh_flctl *flctl = mtd_to_flctl(mtd);
uint32_t read_cmd = 0;
@ -923,9 +927,9 @@ runtime_exit:
return;
}
static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
static void flctl_select_chip(struct nand_chip *chip, int chipnr)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip));
int ret;
switch (chipnr) {
@ -967,17 +971,17 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
}
}
static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
static void flctl_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip));
memcpy(&flctl->done_buff[flctl->index], buf, len);
flctl->index += len;
}
static uint8_t flctl_read_byte(struct mtd_info *mtd)
static uint8_t flctl_read_byte(struct nand_chip *chip)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip));
uint8_t data;
data = flctl->done_buff[flctl->index];
@ -985,18 +989,9 @@ static uint8_t flctl_read_byte(struct mtd_info *mtd)
return data;
}
static uint16_t flctl_read_word(struct mtd_info *mtd)
static void flctl_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index];
flctl->index += 2;
return *buf;
}
static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip));
memcpy(buf, &flctl->done_buff[flctl->index], len);
flctl->index += len;
@ -1183,16 +1178,15 @@ static int flctl_probe(struct platform_device *pdev)
/* Set address of hardware control function */
/* 20 us command delay time */
nand->chip_delay = 20;
nand->legacy.chip_delay = 20;
nand->read_byte = flctl_read_byte;
nand->read_word = flctl_read_word;
nand->write_buf = flctl_write_buf;
nand->read_buf = flctl_read_buf;
nand->legacy.read_byte = flctl_read_byte;
nand->legacy.write_buf = flctl_write_buf;
nand->legacy.read_buf = flctl_read_buf;
nand->select_chip = flctl_select_chip;
nand->cmdfunc = flctl_cmdfunc;
nand->set_features = nand_get_set_features_notsupp;
nand->get_features = nand_get_set_features_notsupp;
nand->legacy.cmdfunc = flctl_cmdfunc;
nand->legacy.set_features = nand_get_set_features_notsupp;
nand->legacy.get_features = nand_get_set_features_notsupp;
if (pdata->flcmncr_val & SEL_16BIT)
nand->options |= NAND_BUSWIDTH_16;
@ -1203,7 +1197,7 @@ static int flctl_probe(struct platform_device *pdev)
flctl_setup_dma(flctl);
nand->dummy_controller.ops = &flctl_nand_controller_ops;
ret = nand_scan(flctl_mtd, 1);
ret = nand_scan(nand, 1);
if (ret)
goto err_chip;
@ -1226,7 +1220,7 @@ static int flctl_remove(struct platform_device *pdev)
struct sh_flctl *flctl = platform_get_drvdata(pdev);
flctl_release_dma(flctl);
nand_release(nand_to_mtd(&flctl->chip));
nand_release(&flctl->chip);
pm_runtime_disable(&pdev->dev);
return 0;

View File

@ -59,11 +59,10 @@ static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd)
* NAND_ALE: bit 2 -> bit 2
*
*/
static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
static void sharpsl_nand_hwcontrol(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
struct nand_chip *chip = mtd_to_nand(mtd);
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip));
if (ctrl & NAND_CTRL_CHANGE) {
unsigned char bits = ctrl & 0x07;
@ -76,24 +75,25 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
writeb(cmd, chip->legacy.IO_ADDR_W);
}
static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
static int sharpsl_nand_dev_ready(struct nand_chip *chip)
{
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip));
return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0);
}
static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
static void sharpsl_nand_enable_hwecc(struct nand_chip *chip, int mode)
{
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip));
writeb(0, sharpsl->io + ECCCLRR);
}
static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
static int sharpsl_nand_calculate_ecc(struct nand_chip *chip,
const u_char * dat, u_char * ecc_code)
{
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip));
ecc_code[0] = ~readb(sharpsl->io + ECCLPUB);
ecc_code[1] = ~readb(sharpsl->io + ECCLPLB);
ecc_code[2] = (~readb(sharpsl->io + ECCCP) << 2) | 0x03;
@ -153,13 +153,13 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL);
/* Set address of NAND IO lines */
this->IO_ADDR_R = sharpsl->io + FLASHIO;
this->IO_ADDR_W = sharpsl->io + FLASHIO;
this->legacy.IO_ADDR_R = sharpsl->io + FLASHIO;
this->legacy.IO_ADDR_W = sharpsl->io + FLASHIO;
/* Set address of hardware control function */
this->cmd_ctrl = sharpsl_nand_hwcontrol;
this->dev_ready = sharpsl_nand_dev_ready;
this->legacy.cmd_ctrl = sharpsl_nand_hwcontrol;
this->legacy.dev_ready = sharpsl_nand_dev_ready;
/* 15 us command delay time */
this->chip_delay = 15;
this->legacy.chip_delay = 15;
/* set eccmode using hardware ECC */
this->ecc.mode = NAND_ECC_HW;
this->ecc.size = 256;
@ -171,7 +171,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
this->ecc.correct = nand_correct_data;
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
err = nand_scan(this, 1);
if (err)
goto err_scan;
@ -187,7 +187,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
return 0;
err_add:
nand_release(mtd);
nand_release(this);
err_scan:
iounmap(sharpsl->io);
@ -205,7 +205,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev)
struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
/* Release resources, unregister device */
nand_release(nand_to_mtd(&sharpsl->chip));
nand_release(&sharpsl->chip);
iounmap(sharpsl->io);

View File

@ -99,8 +99,9 @@ static const struct mtd_ooblayout_ops oob_sm_small_ops = {
.free = oob_sm_small_ooblayout_free,
};
static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
static int sm_block_markbad(struct nand_chip *chip, loff_t ofs)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtd_oob_ops ops;
struct sm_oob oob;
int ret;
@ -167,7 +168,7 @@ static int sm_attach_chip(struct nand_chip *chip)
/* Bad block marker position */
chip->badblockpos = 0x05;
chip->badblockbits = 7;
chip->block_markbad = sm_block_markbad;
chip->legacy.block_markbad = sm_block_markbad;
/* ECC layout */
if (mtd->writesize == SM_SECTOR_SIZE)
@ -195,7 +196,7 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia)
/* Scan for card properties */
chip->dummy_controller.ops = &sm_controller_ops;
flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids;
ret = nand_scan_with_ids(mtd, 1, flash_ids);
ret = nand_scan_with_ids(chip, 1, flash_ids);
if (ret)
return ret;

View File

@ -34,15 +34,14 @@ struct socrates_nand_host {
/**
* socrates_nand_write_buf - write buffer to chip
* @mtd: MTD device structure
* @this: NAND chip object
* @buf: data buffer
* @len: number of bytes to write
*/
static void socrates_nand_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
static void socrates_nand_write_buf(struct nand_chip *this, const uint8_t *buf,
int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
struct socrates_nand_host *host = nand_get_controller_data(this);
for (i = 0; i < len; i++) {
@ -54,14 +53,14 @@ static void socrates_nand_write_buf(struct mtd_info *mtd,
/**
* socrates_nand_read_buf - read chip data into buffer
* @mtd: MTD device structure
* @this: NAND chip object
* @buf: buffer to store date
* @len: number of bytes to read
*/
static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void socrates_nand_read_buf(struct nand_chip *this, uint8_t *buf,
int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
struct socrates_nand_host *host = nand_get_controller_data(this);
uint32_t val;
@ -78,31 +77,19 @@ static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
* socrates_nand_read_byte - read one byte from the chip
* @mtd: MTD device structure
*/
static uint8_t socrates_nand_read_byte(struct mtd_info *mtd)
static uint8_t socrates_nand_read_byte(struct nand_chip *this)
{
uint8_t byte;
socrates_nand_read_buf(mtd, &byte, sizeof(byte));
socrates_nand_read_buf(this, &byte, sizeof(byte));
return byte;
}
/**
* socrates_nand_read_word - read one word from the chip
* @mtd: MTD device structure
*/
static uint16_t socrates_nand_read_word(struct mtd_info *mtd)
{
uint16_t word;
socrates_nand_read_buf(mtd, (uint8_t *)&word, sizeof(word));
return word;
}
/*
* Hardware specific access to control-lines
*/
static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void socrates_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd,
unsigned int ctrl)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
uint32_t val;
@ -125,9 +112,8 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
/*
* Read the Device Ready pin.
*/
static int socrates_nand_device_ready(struct mtd_info *mtd)
static int socrates_nand_device_ready(struct nand_chip *nand_chip)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
if (in_be32(host->io_base) & FPGA_NAND_BUSY)
@ -166,26 +152,21 @@ static int socrates_nand_probe(struct platform_device *ofdev)
mtd->name = "socrates_nand";
mtd->dev.parent = &ofdev->dev;
/*should never be accessed directly */
nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
nand_chip->IO_ADDR_W = (void *)0xdeadbeef;
nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl;
nand_chip->read_byte = socrates_nand_read_byte;
nand_chip->read_word = socrates_nand_read_word;
nand_chip->write_buf = socrates_nand_write_buf;
nand_chip->read_buf = socrates_nand_read_buf;
nand_chip->dev_ready = socrates_nand_device_ready;
nand_chip->legacy.cmd_ctrl = socrates_nand_cmd_ctrl;
nand_chip->legacy.read_byte = socrates_nand_read_byte;
nand_chip->legacy.write_buf = socrates_nand_write_buf;
nand_chip->legacy.read_buf = socrates_nand_read_buf;
nand_chip->legacy.dev_ready = socrates_nand_device_ready;
nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
nand_chip->ecc.algo = NAND_ECC_HAMMING;
/* TODO: I have no idea what real delay is. */
nand_chip->chip_delay = 20; /* 20us command delay time */
nand_chip->legacy.chip_delay = 20; /* 20us command delay time */
dev_set_drvdata(&ofdev->dev, host);
res = nand_scan(mtd, 1);
res = nand_scan(nand_chip, 1);
if (res)
goto out;
@ -193,7 +174,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
if (!res)
return res;
nand_release(mtd);
nand_release(nand_chip);
out:
iounmap(host->io_base);
@ -206,9 +187,8 @@ out:
static int socrates_nand_remove(struct platform_device *ofdev)
{
struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev);
struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
nand_release(mtd);
nand_release(&host->nand_chip);
iounmap(host->io_base);

View File

@ -400,9 +400,8 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
nfc->regs + NFC_REG_CTL);
}
static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
static int sunxi_nfc_dev_ready(struct nand_chip *nand)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
u32 mask;
@ -420,9 +419,9 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
return !!(readl(nfc->regs + NFC_REG_ST) & mask);
}
static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct mtd_info *mtd = nand_to_mtd(nand);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
struct sunxi_nand_chip_sel *sel;
@ -443,9 +442,9 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
NFC_PAGE_SHIFT(nand->page_shift);
if (sel->rb < 0) {
nand->dev_ready = NULL;
nand->legacy.dev_ready = NULL;
} else {
nand->dev_ready = sunxi_nfc_dev_ready;
nand->legacy.dev_ready = sunxi_nfc_dev_ready;
ctl |= NFC_RB_SEL(sel->rb);
}
@ -464,9 +463,8 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
sunxi_nand->selected = chip;
}
static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
int ret;
@ -502,10 +500,9 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
}
}
static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
int len)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
int ret;
@ -540,19 +537,18 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
}
}
static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand)
{
uint8_t ret = 0;
sunxi_nfc_read_buf(mtd, &ret, 1);
sunxi_nfc_read_buf(nand, &ret, 1);
return ret;
}
static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
static void sunxi_nfc_cmd_ctrl(struct nand_chip *nand, int dat,
unsigned int ctrl)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
int ret;
@ -761,7 +757,7 @@ static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
{
sunxi_nfc_randomizer_config(mtd, page, ecc);
sunxi_nfc_randomizer_enable(mtd);
sunxi_nfc_write_buf(mtd, buf, len);
sunxi_nfc_write_buf(mtd_to_nand(mtd), buf, len);
sunxi_nfc_randomizer_disable(mtd);
}
@ -770,7 +766,7 @@ static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
{
sunxi_nfc_randomizer_config(mtd, page, ecc);
sunxi_nfc_randomizer_enable(mtd);
sunxi_nfc_read_buf(mtd, buf, len);
sunxi_nfc_read_buf(mtd_to_nand(mtd), buf, len);
sunxi_nfc_randomizer_disable(mtd);
}
@ -995,7 +991,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
false);
if (!randomize)
sunxi_nfc_read_buf(mtd, oob + offset, len);
sunxi_nfc_read_buf(nand, oob + offset, len);
else
sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
false, page);
@ -1189,10 +1185,10 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
*cur_off = mtd->oobsize + mtd->writesize;
}
static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf,
static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
unsigned int max_bitflips = 0;
int ret, i, cur_off = 0;
@ -1227,10 +1223,10 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
return max_bitflips;
}
static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
nand_read_page_op(chip, page, 0, NULL, 0);
@ -1241,14 +1237,14 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd,
return ret;
/* Fallback to PIO mode */
return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page);
return sunxi_nfc_hw_ecc_read_page(chip, buf, oob_required, page);
}
static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
struct nand_chip *chip,
static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip,
u32 data_offs, u32 readlen,
u8 *bufpoi, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int ret, i, cur_off = 0;
unsigned int max_bitflips = 0;
@ -1278,11 +1274,11 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
return max_bitflips;
}
static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd,
struct nand_chip *chip,
static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip,
u32 data_offs, u32 readlen,
u8 *buf, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size);
int ret;
@ -1293,15 +1289,15 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd,
return ret;
/* Fallback to PIO mode */
return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen,
return sunxi_nfc_hw_ecc_read_subpage(chip, data_offs, readlen,
buf, page);
}
static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip,
static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *chip,
const uint8_t *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int ret, i, cur_off = 0;
@ -1331,12 +1327,12 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
return nand_prog_page_end_op(chip);
}
static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
struct nand_chip *chip,
static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *chip,
u32 data_offs, u32 data_len,
const u8 *buf, int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int ret, i, cur_off = 0;
@ -1363,12 +1359,12 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
return nand_prog_page_end_op(chip);
}
static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
struct nand_chip *chip,
static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip,
const u8 *buf,
int oob_required,
int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = &nand->ecc;
@ -1425,28 +1421,25 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
return nand_prog_page_end_op(chip);
pio_fallback:
return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page);
return sunxi_nfc_hw_ecc_write_page(chip, buf, oob_required, page);
}
static int sunxi_nfc_hw_ecc_read_oob(struct mtd_info *mtd,
struct nand_chip *chip,
int page)
static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page)
{
chip->pagebuf = -1;
return chip->ecc.read_page(mtd, chip, chip->data_buf, 1, page);
return chip->ecc.read_page(chip, chip->data_buf, 1, page);
}
static int sunxi_nfc_hw_ecc_write_oob(struct mtd_info *mtd,
struct nand_chip *chip,
int page)
static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
chip->pagebuf = -1;
memset(chip->data_buf, 0xff, mtd->writesize);
ret = chip->ecc.write_page(mtd, chip, chip->data_buf, 1, page);
ret = chip->ecc.write_page(chip, chip->data_buf, 1, page);
if (ret)
return ret;
@ -1475,10 +1468,9 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
#define sunxi_nand_lookup_timing(l, p, c) \
_sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
const struct nand_data_interface *conf)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
const struct nand_sdr_timings *timings;
@ -1920,7 +1912,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
nand = &chip->nand;
/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
nand->chip_delay = 200;
nand->legacy.chip_delay = 200;
nand->controller = &nfc->controller;
nand->controller->ops = &sunxi_nand_controller_ops;
@ -1931,23 +1923,23 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
nand->ecc.mode = NAND_ECC_HW;
nand_set_flash_node(nand, np);
nand->select_chip = sunxi_nfc_select_chip;
nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
nand->read_buf = sunxi_nfc_read_buf;
nand->write_buf = sunxi_nfc_write_buf;
nand->read_byte = sunxi_nfc_read_byte;
nand->legacy.cmd_ctrl = sunxi_nfc_cmd_ctrl;
nand->legacy.read_buf = sunxi_nfc_read_buf;
nand->legacy.write_buf = sunxi_nfc_write_buf;
nand->legacy.read_byte = sunxi_nfc_read_byte;
nand->setup_data_interface = sunxi_nfc_setup_data_interface;
mtd = nand_to_mtd(nand);
mtd->dev.parent = dev;
ret = nand_scan(mtd, nsels);
ret = nand_scan(nand, nsels);
if (ret)
return ret;
ret = mtd_device_register(mtd, NULL, 0);
if (ret) {
dev_err(dev, "failed to register mtd device: %d\n", ret);
nand_release(mtd);
nand_release(nand);
return ret;
}
@ -1986,7 +1978,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
while (!list_empty(&nfc->chips)) {
chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
node);
nand_release(nand_to_mtd(&chip->nand));
nand_release(&chip->nand);
sunxi_nand_ecc_cleanup(&chip->nand.ecc);
list_del(&chip->node);
}

View File

@ -116,9 +116,9 @@ struct tango_chip {
#define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3))
static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
static void tango_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl)
{
struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
struct tango_chip *tchip = to_tango_chip(chip);
if (ctrl & NAND_CLE)
writeb_relaxed(dat, tchip->base + PBUS_CMD);
@ -127,38 +127,36 @@ static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
writeb_relaxed(dat, tchip->base + PBUS_ADDR);
}
static int tango_dev_ready(struct mtd_info *mtd)
static int tango_dev_ready(struct nand_chip *chip)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct tango_nfc *nfc = to_tango_nfc(chip->controller);
return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY;
}
static u8 tango_read_byte(struct mtd_info *mtd)
static u8 tango_read_byte(struct nand_chip *chip)
{
struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
struct tango_chip *tchip = to_tango_chip(chip);
return readb_relaxed(tchip->base + PBUS_DATA);
}
static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len)
static void tango_read_buf(struct nand_chip *chip, u8 *buf, int len)
{
struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
struct tango_chip *tchip = to_tango_chip(chip);
ioread8_rep(tchip->base + PBUS_DATA, buf, len);
}
static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
static void tango_write_buf(struct nand_chip *chip, const u8 *buf, int len)
{
struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
struct tango_chip *tchip = to_tango_chip(chip);
iowrite8_rep(tchip->base + PBUS_DATA, buf, len);
}
static void tango_select_chip(struct mtd_info *mtd, int idx)
static void tango_select_chip(struct nand_chip *chip, int idx)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct tango_nfc *nfc = to_tango_nfc(chip->controller);
struct tango_chip *tchip = to_tango_chip(chip);
@ -277,14 +275,15 @@ dma_unmap:
return err;
}
static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
u8 *buf, int oob_required, int page)
static int tango_read_page(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct tango_nfc *nfc = to_tango_nfc(chip->controller);
int err, res, len = mtd->writesize;
if (oob_required)
chip->ecc.read_oob(mtd, chip, page);
chip->ecc.read_oob(chip, page);
err = do_dma(nfc, DMA_FROM_DEVICE, NFC_READ, buf, len, page);
if (err)
@ -292,16 +291,17 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
res = decode_error_report(chip);
if (res < 0) {
chip->ecc.read_oob_raw(mtd, chip, page);
chip->ecc.read_oob_raw(chip, page);
res = check_erased_page(chip, buf);
}
return res;
}
static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const u8 *buf, int oob_required, int page)
static int tango_write_page(struct nand_chip *chip, const u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct tango_nfc *nfc = to_tango_nfc(chip->controller);
int err, status, len = mtd->writesize;
@ -314,7 +314,7 @@ static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
if (err)
return err;
status = chip->waitfunc(mtd, chip);
status = chip->legacy.waitfunc(chip);
if (status & NAND_STATUS_FAIL)
return -EIO;
@ -323,30 +323,26 @@ static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
{
struct mtd_info *mtd = nand_to_mtd(chip);
*pos += len;
if (!*buf) {
/* skip over "len" bytes */
nand_change_read_column_op(chip, *pos, NULL, 0, false);
} else {
tango_read_buf(mtd, *buf, len);
tango_read_buf(chip, *buf, len);
*buf += len;
}
}
static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
{
struct mtd_info *mtd = nand_to_mtd(chip);
*pos += len;
if (!*buf) {
/* skip over "len" bytes */
nand_change_write_column_op(chip, *pos, NULL, 0, false);
} else {
tango_write_buf(mtd, *buf, len);
tango_write_buf(chip, *buf, len);
*buf += len;
}
}
@ -424,32 +420,30 @@ static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
aux_write(chip, &oob, ecc_size, &pos);
}
static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
u8 *buf, int oob_required, int page)
static int tango_read_page_raw(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
nand_read_page_op(chip, page, 0, NULL, 0);
raw_read(chip, buf, chip->oob_poi);
return 0;
}
static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const u8 *buf, int oob_required, int page)
static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf,
int oob_required, int page)
{
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
raw_write(chip, buf, chip->oob_poi);
return nand_prog_page_end_op(chip);
}
static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int tango_read_oob(struct nand_chip *chip, int page)
{
nand_read_page_op(chip, page, 0, NULL, 0);
raw_read(chip, NULL, chip->oob_poi);
return 0;
}
static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int tango_write_oob(struct nand_chip *chip, int page)
{
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
raw_write(chip, NULL, chip->oob_poi);
@ -485,11 +479,10 @@ static u32 to_ticks(int kHz, int ps)
return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC);
}
static int tango_set_timings(struct mtd_info *mtd, int csline,
static int tango_set_timings(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
struct nand_chip *chip = mtd_to_nand(mtd);
struct tango_nfc *nfc = to_tango_nfc(chip->controller);
struct tango_chip *tchip = to_tango_chip(chip);
u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr;
@ -571,12 +564,12 @@ static int chip_init(struct device *dev, struct device_node *np)
ecc = &chip->ecc;
mtd = nand_to_mtd(chip);
chip->read_byte = tango_read_byte;
chip->write_buf = tango_write_buf;
chip->read_buf = tango_read_buf;
chip->legacy.read_byte = tango_read_byte;
chip->legacy.write_buf = tango_write_buf;
chip->legacy.read_buf = tango_read_buf;
chip->select_chip = tango_select_chip;
chip->cmd_ctrl = tango_cmd_ctrl;
chip->dev_ready = tango_dev_ready;
chip->legacy.cmd_ctrl = tango_cmd_ctrl;
chip->legacy.dev_ready = tango_dev_ready;
chip->setup_data_interface = tango_set_timings;
chip->options = NAND_USE_BOUNCE_BUFFER |
NAND_NO_SUBPAGE_WRITE |
@ -588,7 +581,7 @@ static int chip_init(struct device *dev, struct device_node *np)
mtd_set_ooblayout(mtd, &tango_nand_ooblayout_ops);
mtd->dev.parent = dev;
err = nand_scan(mtd, 1);
err = nand_scan(chip, 1);
if (err)
return err;
@ -617,7 +610,7 @@ static int tango_nand_remove(struct platform_device *pdev)
for (cs = 0; cs < MAX_CS; ++cs) {
if (nfc->chips[cs])
nand_release(nand_to_mtd(&nfc->chips[cs]->nand_chip));
nand_release(&nfc->chips[cs]->nand_chip);
}
return 0;

View File

@ -462,9 +462,8 @@ static int tegra_nand_exec_op(struct nand_chip *chip,
check_only);
}
static void tegra_nand_select_chip(struct mtd_info *mtd, int die_nr)
static void tegra_nand_select_chip(struct nand_chip *chip, int die_nr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct tegra_nand_chip *nand = to_tegra_chip(chip);
struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
@ -615,44 +614,46 @@ err_unmap_dma_page:
return ret;
}
static int tegra_nand_read_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int tegra_nand_read_page_raw(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
void *oob_buf = oob_required ? chip->oob_poi : NULL;
return tegra_nand_page_xfer(mtd, chip, buf, oob_buf,
mtd->oobsize, page, true);
}
static int tegra_nand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const u8 *buf,
static int tegra_nand_write_page_raw(struct nand_chip *chip, const u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
void *oob_buf = oob_required ? chip->oob_poi : NULL;
return tegra_nand_page_xfer(mtd, chip, (void *)buf, oob_buf,
mtd->oobsize, page, false);
}
static int tegra_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int tegra_nand_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi,
mtd->oobsize, page, true);
}
static int tegra_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
static int tegra_nand_write_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi,
mtd->oobsize, page, false);
}
static int tegra_nand_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
static int tegra_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
struct tegra_nand_chip *nand = to_tegra_chip(chip);
void *oob_buf = oob_required ? chip->oob_poi : NULL;
@ -716,7 +717,7 @@ static int tegra_nand_read_page_hwecc(struct mtd_info *mtd,
* erased or if error correction just failed for all sub-
* pages.
*/
ret = tegra_nand_read_oob(mtd, chip, page);
ret = tegra_nand_read_oob(chip, page);
if (ret < 0)
return ret;
@ -759,10 +760,10 @@ static int tegra_nand_read_page_hwecc(struct mtd_info *mtd,
}
}
static int tegra_nand_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const u8 *buf,
static int tegra_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
int oob_required, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
void *oob_buf = oob_required ? chip->oob_poi : NULL;
int ret;
@ -813,10 +814,9 @@ static void tegra_nand_setup_timing(struct tegra_nand_controller *ctrl,
writel_relaxed(reg, ctrl->regs + TIMING_2);
}
static int tegra_nand_setup_data_interface(struct mtd_info *mtd, int csline,
static int tegra_nand_setup_data_interface(struct nand_chip *chip, int csline,
const struct nand_data_interface *conf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
const struct nand_sdr_timings *timings;
@ -1119,7 +1119,7 @@ static int tegra_nand_chips_init(struct device *dev,
chip->select_chip = tegra_nand_select_chip;
chip->setup_data_interface = tegra_nand_setup_data_interface;
ret = nand_scan(mtd, 1);
ret = nand_scan(chip, 1);
if (ret)
return ret;

View File

@ -126,11 +126,10 @@ static inline struct tmio_nand *mtd_to_tmio(struct mtd_info *mtd)
/*--------------------------------------------------------------------------*/
static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void tmio_nand_hwcontrol(struct nand_chip *chip, int cmd,
unsigned int ctrl)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct nand_chip *chip = mtd_to_nand(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
if (ctrl & NAND_CTRL_CHANGE) {
u8 mode;
@ -156,12 +155,12 @@ static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
}
if (cmd != NAND_CMD_NONE)
tmio_iowrite8(cmd, chip->IO_ADDR_W);
tmio_iowrite8(cmd, chip->legacy.IO_ADDR_W);
}
static int tmio_nand_dev_ready(struct mtd_info *mtd)
static int tmio_nand_dev_ready(struct nand_chip *chip)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
return !(tmio_ioread8(tmio->fcr + FCR_STATUS) & FCR_STATUS_BUSY);
}
@ -187,10 +186,9 @@ static irqreturn_t tmio_irq(int irq, void *__tmio)
*erase and write, we enable it to wake us up. The irq handler
*disables the interrupt.
*/
static int
tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
static int tmio_nand_wait(struct nand_chip *nand_chip)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(nand_chip));
long timeout;
u8 status;
@ -199,10 +197,10 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
tmio_iowrite8(0x81, tmio->fcr + FCR_IMR);
timeout = wait_event_timeout(nand_chip->controller->wq,
tmio_nand_dev_ready(mtd),
tmio_nand_dev_ready(nand_chip),
msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20));
if (unlikely(!tmio_nand_dev_ready(mtd))) {
if (unlikely(!tmio_nand_dev_ready(nand_chip))) {
tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n",
nand_chip->state == FL_ERASING ? "erase" : "program",
@ -225,9 +223,9 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
*To prevent stale data from being read, tmio_nand_hwcontrol() clears
*tmio->read_good.
*/
static u_char tmio_nand_read_byte(struct mtd_info *mtd)
static u_char tmio_nand_read_byte(struct nand_chip *chip)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
unsigned int data;
if (tmio->read_good--)
@ -245,33 +243,33 @@ static u_char tmio_nand_read_byte(struct mtd_info *mtd)
*buffer functions.
*/
static void
tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
tmio_nand_write_buf(struct nand_chip *chip, const u_char *buf, int len)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1);
}
static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void tmio_nand_read_buf(struct nand_chip *chip, u_char *buf, int len)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1);
}
static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode)
static void tmio_nand_enable_hwecc(struct nand_chip *chip, int mode)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
tmio_iowrite8(FCR_MODE_HWECC_RESET, tmio->fcr + FCR_MODE);
tmio_ioread8(tmio->fcr + FCR_DATA); /* dummy read */
tmio_iowrite8(FCR_MODE_HWECC_CALC, tmio->fcr + FCR_MODE);
}
static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
static int tmio_nand_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code)
{
struct tmio_nand *tmio = mtd_to_tmio(mtd);
struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip));
unsigned int ecc;
tmio_iowrite8(FCR_MODE_HWECC_RESULT, tmio->fcr + FCR_MODE);
@ -290,16 +288,18 @@ static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
return 0;
}
static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc,
unsigned char *calc_ecc)
{
int r0, r1;
/* assume ecc.size = 512 and ecc.bytes = 6 */
r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256);
r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256, false);
if (r0 < 0)
return r0;
r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256);
r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256,
false);
if (r1 < 0)
return r1;
return r0 + r1;
@ -400,15 +400,15 @@ static int tmio_probe(struct platform_device *dev)
return retval;
/* Set address of NAND IO lines */
nand_chip->IO_ADDR_R = tmio->fcr;
nand_chip->IO_ADDR_W = tmio->fcr;
nand_chip->legacy.IO_ADDR_R = tmio->fcr;
nand_chip->legacy.IO_ADDR_W = tmio->fcr;
/* Set address of hardware control function */
nand_chip->cmd_ctrl = tmio_nand_hwcontrol;
nand_chip->dev_ready = tmio_nand_dev_ready;
nand_chip->read_byte = tmio_nand_read_byte;
nand_chip->write_buf = tmio_nand_write_buf;
nand_chip->read_buf = tmio_nand_read_buf;
nand_chip->legacy.cmd_ctrl = tmio_nand_hwcontrol;
nand_chip->legacy.dev_ready = tmio_nand_dev_ready;
nand_chip->legacy.read_byte = tmio_nand_read_byte;
nand_chip->legacy.write_buf = tmio_nand_write_buf;
nand_chip->legacy.read_buf = tmio_nand_read_buf;
/* set eccmode using hardware ECC */
nand_chip->ecc.mode = NAND_ECC_HW;
@ -423,7 +423,7 @@ static int tmio_probe(struct platform_device *dev)
nand_chip->badblock_pattern = data->badblock_pattern;
/* 15 us command delay time */
nand_chip->chip_delay = 15;
nand_chip->legacy.chip_delay = 15;
retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0,
dev_name(&dev->dev), tmio);
@ -433,10 +433,10 @@ static int tmio_probe(struct platform_device *dev)
}
tmio->irq = irq;
nand_chip->waitfunc = tmio_nand_wait;
nand_chip->legacy.waitfunc = tmio_nand_wait;
/* Scan to find existence of the device */
retval = nand_scan(mtd, 1);
retval = nand_scan(nand_chip, 1);
if (retval)
goto err_irq;
@ -449,7 +449,7 @@ static int tmio_probe(struct platform_device *dev)
if (!retval)
return retval;
nand_release(mtd);
nand_release(nand_chip);
err_irq:
tmio_hw_stop(dev, tmio);
@ -460,7 +460,7 @@ static int tmio_remove(struct platform_device *dev)
{
struct tmio_nand *tmio = platform_get_drvdata(dev);
nand_release(nand_to_mtd(&tmio->chip));
nand_release(&tmio->chip);
tmio_hw_stop(dev, tmio);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More