2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-12 07:14:03 +08:00

MTD merge for 3.13

* Unify some compile-time differences so that we have fewer uses of
    #ifdef CONFIG_OF in atmel_nand
  * Other general cleanups (removing unused functions, options, variables,
    fields; use correct interfaces)
  * Fix BUG() for new odd-sized NAND, which report non-power-of-2 dimensions via
    ONFI
  * Miscellaneous driver fixes (SPI NOR flash; BCM47xx NAND flash; etc.)
  * Improve differentiation between SLC and MLC NAND -- this clarifies an ABI
    issue regarding the MTD "type" (in sysfs and in ioctl(MEMGETINFO)), where
    the MTD_MLCNANDFLASH type was present but inconsistently used
  * Extend GPMI NAND to support multi-chip-select NAND for some platforms
  * Many improvements to the OMAP2/3 NAND driver, including an expanded DT
    binding to bring us closer to mainline support for some OMAP systems
  * Fix a deadlock in the error path of the Atmel NAND driver probe
  * Correct the error codes from MTD mmap() to conform to POSIX and the Linux
    Programmer's Manual. This is an acknowledged change in the MTD ABI, but I
    can't imagine somebody relying on the non-standard -ENOSYS error code
    specifically. Am I just being unimaginative? :)
  * Fix a few important GPMI NAND bugs (one regression from 3.12 and one
    long-standing race condition)
  * More? Read the log!
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.14 (GNU/Linux)
 
 iQIcBAABAgAGBQJSgzYRAAoJEFySrpd9RFgtv8EP/3ZIS1w4fHyWafVSdgVFGR0Y
 urlVDhg7iBauh9admN9xxBz6CYRwhjby8GnN87Q1qzu95Xp63RVx31nNfdBW3DGd
 92vSyskijYJcUtanBxYqGp1i3EbQcpF4mumqxnre3C4KTLNije41t/wNVqnXAstU
 DWho2iymZdkweKJ0DqBA7WF4l/YscdFyNDanO9JWiwII05Rh3Acv7FPMFm3Clblw
 Nvfwzgp4XycYMeIQtkmQgQ3GgeWtxPgQwqMofn97MVH4zeTsmUP317ohIMukLGJD
 db33J2xBdrIbk9P4D3RvjOCYyAyonu9y6/p+B1Vmj+R4CAUvQOIljhklHFoT3UZW
 OzUHPxB6T0+NZyQ/5IRQIYH9As++vdb/bzsUXm/cXceI4o4I0QCPy/8adifakBOF
 IUX9/BCdUOfKXvdOXY5dXMR2sY1IBg/1WfI+qcAoITsS/EVrUTrOcfSLyGqF0ERU
 c7mAzXiyp4D51x66/QnfJ4aJjlioQSoa3mK1j4fXqH08YB5Zclpz938Bo1AO3lWy
 /n+NYSbeXJoi4rVkNawjrRVs+0OTby2XQ5OqBlUMH6f30fqjUefPm66ZBMhbxzYu
 5QFDctUbnHCyAPpOtM/WR3/NOkIqVhQl1331A+dG2TzLK0vTHs+kbt/YmIITpjI+
 yn70XJGhk1F4gy8zhD+V
 =z5qO
 -----END PGP SIGNATURE-----

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

Pull MTD changes from Brian Norris:
 - Unify some compile-time differences so that we have fewer uses of
   #ifdef CONFIG_OF in atmel_nand
 - Other general cleanups (removing unused functions, options,
   variables, fields; use correct interfaces)
 - Fix BUG() for new odd-sized NAND, which report non-power-of-2
   dimensions via ONFI
 - Miscellaneous driver fixes (SPI NOR flash; BCM47xx NAND flash; etc.)
 - Improve differentiation between SLC and MLC NAND -- this clarifies an
   ABI issue regarding the MTD "type" (in sysfs and in the MEMGETINFO
   ioctl), where the MTD_MLCNANDFLASH type was present but
   inconsistently used
 - Extend GPMI NAND to support multi-chip-select NAND for some platforms
 - Many improvements to the OMAP2/3 NAND driver, including an expanded
   DT binding to bring us closer to mainline support for some OMAP
   systems
 - Fix a deadlock in the error path of the Atmel NAND driver probe
 - Correct the error codes from MTD mmap() to conform to POSIX and the
   Linux Programmer's Manual.  This is an acknowledged change in the MTD
   ABI, but I can't imagine somebody relying on the non-standard -ENOSYS
   error code specifically.  Am I just being unimaginative? :)
 - Fix a few important GPMI NAND bugs (one regression from 3.12 and one
   long-standing race condition)
 - More? Read the log!

* tag 'for-linus-20131112' of git://git.infradead.org/linux-mtd: (98 commits)
  mtd: gpmi: fix the NULL pointer
  mtd: gpmi: fix kernel BUG due to racing DMA operations
  mtd: mtdchar: return expected errors on mmap() call
  mtd: gpmi: only scan two chips for imx6
  mtd: gpmi: Use devm_kzalloc()
  mtd: atmel_nand: fix bug driver will in a dead lock if no nand detected
  mtd: nand: use a local variable to simplify the nand_scan_tail
  mtd: nand: remove deprecated IRQF_DISABLED
  mtd: dataflash: Say if we find a device we don't support
  mtd: nand: omap: fix error return code in omap_nand_probe()
  mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES
  mtd: m25p80: fixup device removal failure path
  mtd: mxc_nand: Include linux/of.h header
  mtd: remove duplicated include from mtdcore.c
  mtd: m25p80: add support for Macronix mx25l3255e
  mtd: nand: omap: remove selection of BCH ecc-scheme via KConfig
  mtd: nand: omap: updated devm_xx for all resource allocation and free calls
  mtd: nand: omap: use drivers/mtd/nand/nand_bch.c wrapper for BCH ECC instead of lib/bch.c
  mtd: nand: omap: clean-up ecc layout for BCH ecc schemes
  mtd: nand: omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe
  ...
This commit is contained in:
Linus Torvalds 2013-11-14 12:31:43 +09:00
commit 82cb6acea4
65 changed files with 923 additions and 982 deletions

View File

@ -104,7 +104,7 @@ Description:
One of the following ASCII strings, representing the device
type:
absent, ram, rom, nor, nand, dataflash, ubi, unknown
absent, ram, rom, nor, nand, mlc-nand, dataflash, ubi, unknown
What: /sys/class/mtd/mtdX/writesize
Date: April 2009

View File

@ -1222,8 +1222,6 @@ in this page</entry>
#define NAND_BBT_VERSION 0x00000100
/* Create a bbt if none axists */
#define NAND_BBT_CREATE 0x00000200
/* Search good / bad pattern through all pages of a block */
#define NAND_BBT_SCANALLPAGES 0x00000400
/* Write bbt if neccecary */
#define NAND_BBT_WRITE 0x00001000
/* Read and write back block contents when writing bbt */

View File

@ -22,10 +22,10 @@ Optional properties:
width of 8 is assumed.
- ti,nand-ecc-opt: A string setting the ECC layout to use. One of:
"sw" Software method (default)
"hw" Hardware method
"hw-romcode" gpmc hamming mode method & romcode layout
"sw" <deprecated> use "ham1" instead
"hw" <deprecated> use "ham1" instead
"hw-romcode" <deprecated> use "ham1" instead
"ham1" 1-bit Hamming ecc code
"bch4" 4-bit BCH ecc code
"bch8" 8-bit BCH ecc code
@ -36,8 +36,12 @@ Optional properties:
"prefetch-dma" Prefetch enabled sDMA mode
"prefetch-irq" Prefetch enabled irq mode
- elm_id: Specifies elm device node. This is required to support BCH
error correction using ELM module.
- elm_id: <deprecated> use "ti,elm-id" instead
- ti,elm-id: Specifies phandle of the ELM devicetree node.
ELM is an on-chip hardware engine on TI SoC which is used for
locating ECC errors for BCHx algorithms. SoC devices which have
ELM hardware engines should specify this device node in .dtsi
Using ELM for ECC error correction frees some CPU cycles.
For inline partiton table parsing (optional):

View File

@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
board_nand_data.nr_parts = nr_parts;
board_nand_data.devsize = nand_type;
board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW;
gpmc_nand_init(&board_nand_data, gpmc_t);
}
#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */

View File

@ -1341,14 +1341,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
#ifdef CONFIG_MTD_NAND
static const char * const nand_ecc_opts[] = {
[OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
[OMAP_ECC_HAMMING_CODE_HW] = "hw",
[OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
[OMAP_ECC_BCH4_CODE_HW] = "bch4",
[OMAP_ECC_BCH8_CODE_HW] = "bch8",
};
static const char * const nand_xfer_types[] = {
[NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
[NAND_OMAP_POLLED] = "polled",
@ -1378,13 +1370,41 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
gpmc_nand_data->cs = val;
gpmc_nand_data->of_node = child;
if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
if (!strcasecmp(s, nand_ecc_opts[val])) {
gpmc_nand_data->ecc_opt = val;
break;
}
/* Detect availability of ELM module */
gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
if (gpmc_nand_data->elm_of_node == NULL)
gpmc_nand_data->elm_of_node =
of_parse_phandle(child, "elm_id", 0);
if (gpmc_nand_data->elm_of_node == NULL)
pr_warn("%s: ti,elm-id property not found\n", __func__);
/* select ecc-scheme for NAND */
if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
return -ENODEV;
}
if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
!strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
gpmc_nand_data->ecc_opt =
OMAP_ECC_HAM1_CODE_HW;
else if (!strcmp(s, "bch4"))
if (gpmc_nand_data->elm_of_node)
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH4_CODE_HW;
else
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
else if (!strcmp(s, "bch8"))
if (gpmc_nand_data->elm_of_node)
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH8_CODE_HW;
else
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
else
pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
/* select data transfer mode for NAND controller */
if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
if (!strcasecmp(s, nand_xfer_types[val])) {

View File

@ -93,6 +93,7 @@
#define CSOR_NAND_PGS_512 0x00000000
#define CSOR_NAND_PGS_2K 0x00080000
#define CSOR_NAND_PGS_4K 0x00100000
#define CSOR_NAND_PGS_8K 0x00180000
/* Spare region Size */
#define CSOR_NAND_SPRZ_MASK 0x0000E000
#define CSOR_NAND_SPRZ_SHIFT 13
@ -102,6 +103,7 @@
#define CSOR_NAND_SPRZ_210 0x00006000
#define CSOR_NAND_SPRZ_218 0x00008000
#define CSOR_NAND_SPRZ_224 0x0000A000
#define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000
/* Pages Per Block */
#define CSOR_NAND_PB_MASK 0x00000700
#define CSOR_NAND_PB_SHIFT 8

View File

@ -27,11 +27,13 @@
/* Magics */
#define BOARD_DATA_MAGIC 0x5246504D /* MPFR */
#define FACTORY_MAGIC 0x59544346 /* FCTY */
#define POT_MAGIC1 0x54544f50 /* POTT */
#define POT_MAGIC2 0x504f /* OP */
#define ML_MAGIC1 0x39685a42
#define ML_MAGIC2 0x26594131
#define TRX_MAGIC 0x30524448
#define SQSH_MAGIC 0x71736873 /* shsq */
struct trx_header {
uint32_t magic;
@ -71,7 +73,14 @@ static int bcm47xxpart_parse(struct mtd_info *master,
/* Alloc */
parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
GFP_KERNEL);
if (!parts)
return -ENOMEM;
buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL);
if (!buf) {
kfree(parts);
return -ENOMEM;
}
/* Parse block by block looking for magics */
for (offset = 0; offset <= master->size - blocksize;
@ -110,6 +119,13 @@ static int bcm47xxpart_parse(struct mtd_info *master,
continue;
}
/* Found on Huawei E970 */
if (buf[0x000 / 4] == FACTORY_MAGIC) {
bcm47xxpart_add_part(&parts[curr_part++], "factory",
offset, MTD_WRITEABLE);
continue;
}
/* POT(TOP) */
if (buf[0x000 / 4] == POT_MAGIC1 &&
(buf[0x004 / 4] & 0xFFFF) == POT_MAGIC2) {
@ -167,6 +183,13 @@ static int bcm47xxpart_parse(struct mtd_info *master,
offset = rounddown(offset + trx->length, blocksize);
continue;
}
/* Squashfs on devices not using TRX */
if (buf[0x000 / 4] == SQSH_MAGIC) {
bcm47xxpart_add_part(&parts[curr_part++], "rootfs",
offset, 0);
continue;
}
}
/* Look for NVRAM at the end of the last block. */

View File

@ -95,13 +95,6 @@ config MTD_M25P80
if you want to specify device partitioning or to use a device which
doesn't support the JEDEC ID instruction.
config M25PXX_USE_FAST_READ
bool "Use FAST_READ OPCode allowing SPI CLK >= 50MHz"
depends on MTD_M25P80
default y
help
This option enables FAST_READ access supported by ST M25Pxx.
config MTD_SPEAR_SMI
tristate "SPEAR MTD NOR Support through SMI controller"
depends on PLAT_SPEAR

View File

@ -20,6 +20,7 @@
#include <linux/mutex.h>
#include <linux/mount.h>
#include <linux/slab.h>
#include <linux/major.h>
/* Info for the block device */
struct block2mtd_dev {

View File

@ -2097,7 +2097,7 @@ notfound:
ret = -ENODEV;
dev_info(dev, "No supported DiskOnChip found\n");
err_probe:
kfree(cascade->bch);
free_bch(cascade->bch);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (cascade->floors[floor])
doc_release_device(cascade->floors[floor]);

View File

@ -78,7 +78,7 @@
/* Define max times to check status register before we give up. */
#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
#define MAX_CMD_SIZE 5
#define MAX_CMD_SIZE 6
#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
@ -367,10 +367,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
spi_message_init(&m);
memset(t, 0, (sizeof t));
/* NOTE:
* OPCODE_FAST_READ (if available) is faster.
* Should add 1 byte DUMMY_BYTE.
*/
t[0].tx_buf = flash->command;
t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
spi_message_add_tail(&t[0], &m);
@ -388,11 +384,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
return 1;
}
/* FIXME switch to OPCODE_FAST_READ. It's required for higher
* clocks; and at this writing, every chip this driver handles
* supports that opcode.
*/
/* Set up the write data buffer. */
opcode = flash->read_opcode;
flash->command[0] = opcode;
@ -749,16 +740,19 @@ static const struct spi_device_id m25p_ids[] = {
{ "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
/* EON -- en25xxx */
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
/* ESMT */
{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
/* Everspin */
{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, M25P_NO_ERASE | M25P_NO_FR) },
{ "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, M25P_NO_ERASE | M25P_NO_FR) },
{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, M25P_NO_ERASE | M25P_NO_FR) },
{ "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, M25P_NO_ERASE | M25P_NO_FR) },
/* GigaDevice */
{ "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
@ -775,6 +769,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
{ "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
{ "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
{ "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
@ -783,15 +778,16 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
/* Micron */
{ "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
{ "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
{ "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
{ "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
{ "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
/* PMC */
{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
{ "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
{ "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
@ -940,12 +936,7 @@ static int m25p_probe(struct spi_device *spi)
struct flash_info *info;
unsigned i;
struct mtd_part_parser_data ppdata;
struct device_node __maybe_unused *np = spi->dev.of_node;
#ifdef CONFIG_MTD_OF_PARTS
if (!of_device_is_available(np))
return -ENODEV;
#endif
struct device_node *np = spi->dev.of_node;
/* Platform data helps sort out which chip type we have, as
* well as how this board partitions it. If we don't have
@ -992,15 +983,13 @@ static int m25p_probe(struct spi_device *spi)
}
}
flash = kzalloc(sizeof *flash, GFP_KERNEL);
flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
if (!flash)
return -ENOMEM;
flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0),
GFP_KERNEL);
if (!flash->command) {
kfree(flash);
flash->command = devm_kzalloc(&spi->dev, MAX_CMD_SIZE, GFP_KERNEL);
if (!flash->command)
return -ENOMEM;
}
flash->spi = spi;
mutex_init(&flash->lock);
@ -1062,13 +1051,14 @@ static int m25p_probe(struct spi_device *spi)
flash->page_size = info->page_size;
flash->mtd.writebufsize = flash->page_size;
flash->fast_read = false;
if (np && of_property_read_bool(np, "m25p,fast-read"))
if (np)
/* If we were instantiated by DT, use it */
flash->fast_read = of_property_read_bool(np, "m25p,fast-read");
else
/* If we weren't instantiated by DT, default to fast-read */
flash->fast_read = true;
#ifdef CONFIG_M25PXX_USE_FAST_READ
flash->fast_read = true;
#endif
/* Some devices cannot do fast-read, no matter what DT tells us */
if (info->flags & M25P_NO_FR)
flash->fast_read = false;
@ -1133,15 +1123,9 @@ static int m25p_probe(struct spi_device *spi)
static int m25p_remove(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
int status;
/* Clean up MTD stuff. */
status = mtd_device_unregister(&flash->mtd);
if (status == 0) {
kfree(flash->command);
kfree(flash);
}
return 0;
return mtd_device_unregister(&flash->mtd);
}

View File

@ -88,8 +88,6 @@ struct dataflash {
uint8_t command[4];
char name[24];
unsigned partitioned:1;
unsigned short page_offset; /* offset in flash address */
unsigned int page_size; /* of bytes per page */
@ -881,7 +879,7 @@ static int dataflash_probe(struct spi_device *spi)
break;
/* obsolete AT45DB1282 not (yet?) supported */
default:
pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
dev_info(&spi->dev, "unsupported device (%x)\n",
status & 0x3c);
status = -ENODEV;
}

View File

@ -94,7 +94,7 @@ static void unregister_devices(void)
}
}
static int register_device(char *name, unsigned long start, unsigned long len)
static int register_device(char *name, phys_addr_t start, size_t len)
{
struct phram_mtd_list *new;
int ret = -ENOMEM;
@ -141,35 +141,35 @@ out0:
return ret;
}
static int ustrtoul(const char *cp, char **endp, unsigned int base)
static int parse_num64(uint64_t *num64, char *token)
{
unsigned long result = simple_strtoul(cp, endp, base);
size_t len;
int shift = 0;
int ret;
switch (**endp) {
case 'G':
result *= 1024;
case 'M':
result *= 1024;
case 'k':
result *= 1024;
len = strlen(token);
/* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
if ((*endp)[1] == 'i')
(*endp) += 2;
if (len > 2) {
if (token[len - 1] == 'i') {
switch (token[len - 2]) {
case 'G':
shift += 10;
case 'M':
shift += 10;
case 'k':
shift += 10;
token[len - 2] = 0;
break;
default:
return -EINVAL;
}
}
}
return result;
}
static int parse_num32(uint32_t *num32, const char *token)
{
char *endp;
unsigned long n;
ret = kstrtou64(token, 0, num64);
*num64 <<= shift;
n = ustrtoul(token, &endp, 0);
if (*endp)
return -EINVAL;
*num32 = n;
return 0;
return ret;
}
static int parse_name(char **pname, const char *token)
@ -209,19 +209,19 @@ static inline void kill_final_newline(char *str)
* This shall contain the module parameter if any. It is of the form:
* - phram=<device>,<address>,<size> for module case
* - phram.phram=<device>,<address>,<size> for built-in case
* We leave 64 bytes for the device name, 12 for the address and 12 for the
* We leave 64 bytes for the device name, 20 for the address and 20 for the
* size.
* Example: phram.phram=rootfs,0xa0000000,512Mi
*/
static __initdata char phram_paramline[64+12+12];
static __initdata char phram_paramline[64 + 20 + 20];
static int __init phram_setup(const char *val)
{
char buf[64+12+12], *str = buf;
char buf[64 + 20 + 20], *str = buf;
char *token[3];
char *name;
uint32_t start;
uint32_t len;
uint64_t start;
uint64_t len;
int i, ret;
if (strnlen(val, sizeof(buf)) >= sizeof(buf))
@ -243,13 +243,13 @@ static int __init phram_setup(const char *val)
if (ret)
return ret;
ret = parse_num32(&start, token[1]);
ret = parse_num64(&start, token[1]);
if (ret) {
kfree(name);
parse_err("illegal start address\n");
}
ret = parse_num32(&len, token[2]);
ret = parse_num64(&len, token[2]);
if (ret) {
kfree(name);
parse_err("illegal device length\n");
@ -257,7 +257,7 @@ static int __init phram_setup(const char *val)
ret = register_device(name, start, len);
if (!ret)
pr_info("%s device: %#x at %#x\n", name, len, start);
pr_info("%s device: %#llx at %#llx\n", name, len, start);
else
kfree(name);

View File

@ -364,7 +364,7 @@ static int sst25l_probe(struct spi_device *spi)
if (!flash_info)
return -ENODEV;
flash = kzalloc(sizeof(struct sst25l_flash), GFP_KERNEL);
flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
if (!flash)
return -ENOMEM;
@ -402,11 +402,8 @@ static int sst25l_probe(struct spi_device *spi)
ret = mtd_device_parse_register(&flash->mtd, NULL, NULL,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
if (ret) {
kfree(flash);
spi_set_drvdata(spi, NULL);
if (ret)
return -ENODEV;
}
return 0;
}
@ -414,12 +411,8 @@ static int sst25l_probe(struct spi_device *spi)
static int sst25l_remove(struct spi_device *spi)
{
struct sst25l_flash *flash = spi_get_drvdata(spi);
int ret;
ret = mtd_device_unregister(&flash->mtd);
if (ret == 0)
kfree(flash);
return ret;
return mtd_device_unregister(&flash->mtd);
}
static struct spi_driver sst25l_driver = {

View File

@ -50,7 +50,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct INFTLrecord *inftl;
unsigned long temp;
if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))

View File

@ -703,7 +703,7 @@ static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
#define DO_XXLOCK_LOCK 1
#define DO_XXLOCK_UNLOCK 2
int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
static int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
{
int ret = 0;
struct map_info *map = mtd->priv;

View File

@ -180,7 +180,6 @@ static void vr_nor_pci_remove(struct pci_dev *dev)
{
struct vr_nor_mtd *p = pci_get_drvdata(dev);
pci_set_drvdata(dev, NULL);
vr_nor_destroy_partitions(p);
vr_nor_destroy_mtd_setup(p);
vr_nor_destroy_maps(p);

View File

@ -316,7 +316,6 @@ static void mtd_pci_remove(struct pci_dev *dev)
map->exit(dev, map);
kfree(map);
pci_set_drvdata(dev, NULL);
pci_release_regions(dev);
}

View File

@ -55,7 +55,7 @@ struct platram_info {
static inline struct platram_info *to_platram_info(struct platform_device *dev)
{
return (struct platram_info *)platform_get_drvdata(dev);
return platform_get_drvdata(dev);
}
/* platram_setrw
@ -257,21 +257,7 @@ static struct platform_driver platram_driver = {
},
};
/* module init/exit */
static int __init platram_init(void)
{
printk("Generic platform RAM MTD, (c) 2004 Simtec Electronics\n");
return platform_driver_register(&platram_driver);
}
static void __exit platram_exit(void)
{
platform_driver_unregister(&platram_driver);
}
module_init(platram_init);
module_exit(platram_exit);
module_platform_driver(platram_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");

View File

@ -212,7 +212,6 @@ static void scb2_flash_remove(struct pci_dev *dev)
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
pci_set_drvdata(dev, NULL);
}
static struct pci_device_id scb2_flash_pci_ids[] = {

View File

@ -32,6 +32,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <linux/mutex.h>
#include <linux/major.h>
struct mtdblk_dev {
@ -373,7 +374,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
.major = 31,
.major = MTD_BLOCK_MAJOR,
.part_bits = 0,
.blksize = 512,
.open = mtdblock_open,

View File

@ -24,6 +24,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <linux/module.h>
#include <linux/major.h>
static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf)
@ -70,7 +71,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
.major = 31,
.major = MTD_BLOCK_MAJOR,
.part_bits = 0,
.blksize = 512,
.readsect = mtdblock_readsect,

View File

@ -32,6 +32,7 @@
#include <linux/mount.h>
#include <linux/blkpg.h>
#include <linux/magic.h>
#include <linux/major.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h>
@ -1099,7 +1100,7 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
return (unsigned long) -EINVAL;
ret = mtd_get_unmapped_area(mtd, len, offset, flags);
return ret == -EOPNOTSUPP ? -ENOSYS : ret;
return ret == -EOPNOTSUPP ? -ENODEV : ret;
}
#endif
@ -1124,9 +1125,9 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
#endif
return vm_iomap_memory(vma, map->phys, map->size);
}
return -ENOSYS;
return -ENODEV;
#else
return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
return vma->vm_flags & VM_SHARED ? 0 : -EACCES;
#endif
}

View File

@ -157,6 +157,9 @@ static ssize_t mtd_type_show(struct device *dev,
case MTD_UBIVOLUME:
type = "ubi";
break;
case MTD_MLCNANDFLASH:
type = "mlc-nand";
break;
default:
type = "unknown";
}

View File

@ -17,6 +17,7 @@
#include <linux/export.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/major.h>
/*
* compare superblocks to see if they're equivalent

View File

@ -96,43 +96,15 @@ config MTD_NAND_OMAP2
config MTD_NAND_OMAP_BCH
depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
tristate "Enable support for hardware BCH error correction"
tristate "Support hardware based BCH error correction"
default n
select BCH
select BCH_CONST_PARAMS
help
Support for hardware BCH error correction.
choice
prompt "BCH error correction capability"
depends on MTD_NAND_OMAP_BCH
config MTD_NAND_OMAP_BCH8
bool "8 bits / 512 bytes (recommended)"
help
Support correcting up to 8 bitflips per 512-byte block.
This will use 13 bytes of spare area per 512 bytes of page data.
This is the recommended mode, as 4-bit mode does not work
on some OMAP3 revisions, due to a hardware bug.
config MTD_NAND_OMAP_BCH4
bool "4 bits / 512 bytes"
help
Support correcting up to 4 bitflips per 512-byte block.
This will use 7 bytes of spare area per 512 bytes of page data.
Note that this mode does not work on some OMAP3 revisions, due to a
hardware bug. Please check your OMAP datasheet before selecting this
mode.
endchoice
if MTD_NAND_OMAP_BCH
config BCH_CONST_M
default 13
config BCH_CONST_T
default 4 if MTD_NAND_OMAP_BCH4
default 8 if MTD_NAND_OMAP_BCH8
endif
This config enables the ELM hardware engine, which can be used to
locate and correct errors when using BCH ECC scheme. This offloads
the cpu from doing ECC error searching and correction. However some
legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine
so they should not enable this config symbol.
config MTD_NAND_IDS
tristate

View File

@ -1062,56 +1062,28 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
}
/*
* Get ECC requirement in ONFI parameters, returns -1 if ONFI
* parameters is not supported.
* return 0 if success to get the ECC requirement.
*/
static int get_onfi_ecc_param(struct nand_chip *chip,
int *ecc_bits, int *sector_size)
{
*ecc_bits = *sector_size = 0;
if (chip->onfi_params.ecc_bits == 0xff)
/* TODO: the sector_size and ecc_bits need to be find in
* extended ecc parameter, currently we don't support it.
*/
return -1;
*ecc_bits = chip->onfi_params.ecc_bits;
/* The default sector size (ecc codeword size) is 512 */
*sector_size = 512;
return 0;
}
/*
* Get ecc requirement from ONFI parameters ecc requirement.
* Get minimum ecc requirements from NAND.
* If pmecc-cap, pmecc-sector-size in DTS are not specified, this function
* will set them according to ONFI ecc requirement. Otherwise, use the
* will set them according to minimum ecc requirement. Otherwise, use the
* value in DTS file.
* return 0 if success. otherwise return error code.
*/
static int pmecc_choose_ecc(struct atmel_nand_host *host,
int *cap, int *sector_size)
{
/* Get ECC requirement from ONFI parameters */
*cap = *sector_size = 0;
if (host->nand_chip.onfi_version) {
if (!get_onfi_ecc_param(&host->nand_chip, cap, sector_size))
dev_info(host->dev, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
/* Get minimum ECC requirements */
if (host->nand_chip.ecc_strength_ds) {
*cap = host->nand_chip.ecc_strength_ds;
*sector_size = host->nand_chip.ecc_step_ds;
dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n",
*cap, *sector_size);
else
dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
} else {
dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
}
if (*cap == 0 && *sector_size == 0) {
*cap = 2;
*sector_size = 512;
dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n");
}
/* If dts file doesn't specify then use the one in ONFI parameters */
/* If device tree doesn't specify, use NAND's minimum ECC parameters */
if (host->pmecc_corr_cap == 0) {
/* use the most fitable ecc bits (the near bigger one ) */
if (*cap <= 2)
@ -1449,7 +1421,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
}
#if defined(CONFIG_OF)
static int atmel_of_init_port(struct atmel_nand_host *host,
struct device_node *np)
{
@ -1457,7 +1428,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
u32 offset[2];
int ecc_mode;
struct atmel_nand_data *board = &host->board;
enum of_gpio_flags flags;
enum of_gpio_flags flags = 0;
if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
if (val >= 32) {
@ -1540,13 +1511,6 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
return 0;
}
#else
static int atmel_of_init_port(struct atmel_nand_host *host,
struct device_node *np)
{
return -EINVAL;
}
#endif
static int atmel_hw_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
@ -2019,7 +1983,8 @@ static int atmel_nand_probe(struct platform_device *pdev)
mtd = &host->mtd;
nand_chip = &host->nand_chip;
host->dev = &pdev->dev;
if (pdev->dev.of_node) {
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
/* Only when CONFIG_OF is enabled of_node can be parsed */
res = atmel_of_init_port(host, pdev->dev.of_node);
if (res)
goto err_nand_ioremap;
@ -2177,7 +2142,6 @@ err_no_card:
if (host->dma_chan)
dma_release_channel(host->dma_chan);
err_nand_ioremap:
platform_driver_unregister(&atmel_nand_nfc_driver);
return res;
}
@ -2207,14 +2171,12 @@ static int atmel_nand_remove(struct platform_device *pdev)
return 0;
}
#if defined(CONFIG_OF)
static const struct of_device_id atmel_nand_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-nand" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
#endif
static int atmel_nand_nfc_probe(struct platform_device *pdev)
{
@ -2253,12 +2215,11 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
return 0;
}
#if defined(CONFIG_OF)
static struct of_device_id atmel_nand_nfc_match[] = {
static const struct of_device_id atmel_nand_nfc_match[] = {
{ .compatible = "atmel,sama5d3-nfc" },
{ /* sentinel */ }
};
#endif
MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
static struct platform_driver atmel_nand_nfc_driver = {
.driver = {

View File

@ -29,11 +29,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
struct bcm47xxnflash *b47n;
int err = 0;
b47n = kzalloc(sizeof(*b47n), GFP_KERNEL);
if (!b47n) {
err = -ENOMEM;
goto out;
}
b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL);
if (!b47n)
return -ENOMEM;
b47n->nand_chip.priv = b47n;
b47n->mtd.owner = THIS_MODULE;
@ -48,22 +46,16 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
}
if (err) {
pr_err("Initialization failed: %d\n", err);
goto err_init;
return err;
}
err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0);
if (err) {
pr_err("Failed to register MTD device: %d\n", err);
goto err_dev_reg;
return err;
}
return 0;
err_dev_reg:
err_init:
kfree(b47n);
out:
return err;
}
static int bcm47xxnflash_remove(struct platform_device *pdev)
@ -85,22 +77,4 @@ static struct platform_driver bcm47xxnflash_driver = {
},
};
static int __init bcm47xxnflash_init(void)
{
int err;
err = platform_driver_register(&bcm47xxnflash_driver);
if (err)
pr_err("Failed to register bcm47xx nand flash driver: %d\n",
err);
return err;
}
static void __exit bcm47xxnflash_exit(void)
{
platform_driver_unregister(&bcm47xxnflash_driver);
}
module_init(bcm47xxnflash_init);
module_exit(bcm47xxnflash_exit);
module_platform_driver(bcm47xxnflash_driver);

View File

@ -1394,7 +1394,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
};
/* initialize driver data structures */
void denali_drv_init(struct denali_nand_info *denali)
static void denali_drv_init(struct denali_nand_info *denali)
{
denali->idx = 0;
@ -1520,7 +1520,7 @@ int denali_init(struct denali_nand_info *denali)
* so just let controller do 15bit ECC for MLC and 8bit ECC for
* SLC if possible.
* */
if (denali->nand.cellinfo & NAND_CI_CELLTYPE_MSK &&
if (!nand_is_slc(&denali->nand) &&
(denali->mtd.oobsize > (denali->bbtskipbytes +
ECC_15BITS * (denali->mtd.writesize /
ECC_SECTOR_SIZE)))) {

View File

@ -119,7 +119,6 @@ static void denali_pci_remove(struct pci_dev *dev)
iounmap(denali->flash_mem);
pci_release_regions(dev);
pci_disable_device(dev);
pci_set_drvdata(dev, NULL);
kfree(denali);
}

View File

@ -38,7 +38,7 @@
#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0
#endif
static unsigned long __initdata doc_locations[] = {
static unsigned long doc_locations[] __initdata = {
#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH
0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,

View File

@ -44,6 +44,7 @@
#include <linux/mtd/nand.h>
#include <linux/bch.h>
#include <linux/bitrev.h>
#include <linux/jiffies.h>
/*
* In "reliable mode" consecutive 2k pages are used in parallel (in some
@ -269,7 +270,7 @@ static int poll_status(struct docg4_priv *doc)
*/
uint16_t flash_status;
unsigned int timeo;
unsigned long timeo;
void __iomem *docptr = doc->virtadr;
dev_dbg(doc->dev, "%s...\n", __func__);
@ -277,22 +278,18 @@ static int poll_status(struct docg4_priv *doc)
/* hardware quirk requires reading twice initially */
flash_status = readw(docptr + DOC_FLASHCONTROL);
timeo = 1000;
timeo = jiffies + msecs_to_jiffies(200); /* generous timeout */
do {
cpu_relax();
flash_status = readb(docptr + DOC_FLASHCONTROL);
} while (!(flash_status & DOC_CTRL_FLASHREADY) && --timeo);
} while (!(flash_status & DOC_CTRL_FLASHREADY) &&
time_before(jiffies, timeo));
if (!timeo) {
if (unlikely(!(flash_status & DOC_CTRL_FLASHREADY))) {
dev_err(doc->dev, "%s: timed out!\n", __func__);
return NAND_STATUS_FAIL;
}
if (unlikely(timeo < 50))
dev_warn(doc->dev, "%s: nearly timed out; %d remaining\n",
__func__, timeo);
return 0;
}
@ -1239,7 +1236,6 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
nand->block_markbad = docg4_block_markbad;
nand->read_buf = docg4_read_buf;
nand->write_buf = docg4_write_buf16;
nand->scan_bbt = nand_default_bbt;
nand->erase_cmd = docg4_erase_block;
nand->ecc.read_page = docg4_read_page;
nand->ecc.write_page = docg4_write_page;

View File

@ -651,8 +651,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
chip->ecclayout);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",

View File

@ -136,6 +136,69 @@ static struct nand_ecclayout oob_4096_ecc8 = {
.oobfree = { {2, 6}, {136, 82} },
};
/* 8192-byte page size with 4-bit ECC */
static struct nand_ecclayout oob_8192_ecc4 = {
.eccbytes = 128,
.eccpos = {
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135,
},
.oobfree = { {2, 6}, {136, 208} },
};
/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
static struct nand_ecclayout oob_8192_ecc8 = {
.eccbytes = 256,
.eccpos = {
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191,
192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223,
224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263,
},
.oobfree = { {2, 6}, {264, 80} },
};
/*
* Generic flash bbt descriptors
@ -442,20 +505,29 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (mtd->writesize > 512) {
nand_fcr0 =
(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
iowrite32be(
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT),
&ifc->ifc_nand.nand_fir0);
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT),
&ifc->ifc_nand.nand_fir0);
iowrite32be(
(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
(IFC_FIR_OP_RDSTAT <<
IFC_NAND_FIR1_OP6_SHIFT) |
(IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT),
&ifc->ifc_nand.nand_fir1);
} else {
nand_fcr0 = ((NAND_CMD_PAGEPROG <<
IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_SEQIN <<
IFC_NAND_FCR0_CMD2_SHIFT));
IFC_NAND_FCR0_CMD2_SHIFT) |
(NAND_CMD_STATUS <<
IFC_NAND_FCR0_CMD3_SHIFT));
iowrite32be(
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@ -464,8 +536,13 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT),
&ifc->ifc_nand.nand_fir0);
iowrite32be(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT,
&ifc->ifc_nand.nand_fir1);
iowrite32be(
(IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
(IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
(IFC_FIR_OP_RDSTAT <<
IFC_NAND_FIR1_OP7_SHIFT) |
(IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT),
&ifc->ifc_nand.nand_fir1);
if (column >= mtd->writesize)
nand_fcr0 |=
@ -719,8 +796,6 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
chip->phys_erase_shift);
dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
chip->ecclayout);
dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
chip->ecc.mode);
dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
@ -873,11 +948,25 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
} else {
layout = &oob_4096_ecc8;
chip->ecc.bytes = 16;
chip->ecc.strength = 8;
}
priv->bufnum_mask = 1;
break;
case CSOR_NAND_PGS_8K:
if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
CSOR_NAND_ECC_MODE_4) {
layout = &oob_8192_ecc4;
} else {
layout = &oob_8192_ecc8;
chip->ecc.bytes = 16;
chip->ecc.strength = 8;
}
priv->bufnum_mask = 0;
break;
default:
dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
return -ENODEV;
@ -908,7 +997,6 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
iounmap(priv->vbase);
ifc_nand_ctrl->chips[priv->bank] = NULL;
dev_set_drvdata(priv->dev, NULL);
return 0;
}
@ -1083,25 +1171,7 @@ static struct platform_driver fsl_ifc_nand_driver = {
.remove = fsl_ifc_nand_remove,
};
static int __init fsl_ifc_nand_init(void)
{
int ret;
ret = platform_driver_register(&fsl_ifc_nand_driver);
if (ret)
printk(KERN_ERR "fsl-ifc: Failed to register platform"
"driver\n");
return ret;
}
static void __exit fsl_ifc_nand_exit(void)
{
platform_driver_unregister(&fsl_ifc_nand_driver);
}
module_init(fsl_ifc_nand_init);
module_exit(fsl_ifc_nand_exit);
module_platform_driver(fsl_ifc_nand_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale");

View File

@ -187,6 +187,12 @@ int gpmi_init(struct gpmi_nand_data *this)
/* Select BCH ECC. */
writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
/*
* Decouple the chip select from dma channel. We use dma0 for all
* the chips.
*/
writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
gpmi_disable_clk(this);
return 0;
err_out:
@ -1073,6 +1079,13 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
} else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) {
/*
* In the imx6, all the ready/busy pins are bound
* together. So we only need to check chip 0.
*/
if (GPMI_IS_MX6Q(this))
chip = 0;
/* MX28 shares the same R/B register as MX6Q. */
mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
reg = readl(r->gpmi_regs + HW_GPMI_STAT);

View File

@ -45,7 +45,10 @@ static struct nand_bbt_descr gpmi_bbt_descr = {
.pattern = scan_ff_pattern
};
/* We will use all the (page + OOB). */
/*
* We may change the layout if we can get the ECC info from the datasheet,
* else we will use all the (page + OOB).
*/
static struct nand_ecclayout gpmi_hw_ecclayout = {
.eccbytes = 0,
.eccpos = { 0, },
@ -354,9 +357,8 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
{
int chipnr = this->current_chip;
return this->dma_chans[chipnr];
/* We use the DMA channel 0 to access all the nand chips. */
return this->dma_chans[0];
}
/* Can we use the upper's buffer directly for DMA? */
@ -392,8 +394,6 @@ static void dma_irq_callback(void *param)
struct gpmi_nand_data *this = param;
struct completion *dma_c = &this->dma_done;
complete(dma_c);
switch (this->dma_type) {
case DMA_FOR_COMMAND:
dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE);
@ -418,6 +418,8 @@ static void dma_irq_callback(void *param)
default:
pr_err("in wrong DMA operation.\n");
}
complete(dma_c);
}
int start_dma_without_bch_irq(struct gpmi_nand_data *this,
@ -1263,14 +1265,22 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
static int
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
{
/*
* The BCH will use all the (page + oob).
* Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob.
* But it can not stop some ioctls such MEMWRITEOOB which uses
* MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit
* these ioctls too.
*/
return -EPERM;
struct nand_oobfree *of = mtd->ecclayout->oobfree;
int status = 0;
/* Do we have available oob area? */
if (!of->length)
return -EPERM;
if (!nand_is_slc(chip))
return -EPERM;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of->offset, page);
chip->write_buf(mtd, chip->oob_poi + of->offset, of->length);
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
status = chip->waitfunc(mtd, chip);
return status & NAND_STATUS_FAIL ? -EIO : 0;
}
static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
@ -1568,8 +1578,6 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this)
{
int ret;
/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
if (GPMI_IS_MX23(this))
this->swap_block_mark = false;
@ -1577,12 +1585,8 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this)
this->swap_block_mark = true;
/* Set up the medium geometry */
ret = gpmi_set_geometry(this);
if (ret)
return ret;
return gpmi_set_geometry(this);
/* NAND boot init, depends on the gpmi_set_geometry(). */
return nand_boot_init(this);
}
static void gpmi_nfc_exit(struct gpmi_nand_data *this)
@ -1664,7 +1668,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
ret = nand_scan_ident(mtd, 1, NULL);
ret = nand_scan_ident(mtd, GPMI_IS_MX6Q(this) ? 2 : 1, NULL);
if (ret)
goto err_out;
@ -1672,10 +1676,16 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
chip->options |= NAND_SKIP_BBTSCAN;
ret = nand_scan_tail(mtd);
if (ret)
goto err_out;
ret = nand_boot_init(this);
if (ret)
goto err_out;
chip->scan_bbt(mtd);
ppdata.of_node = this->pdev->dev.of_node;
ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
if (ret)
@ -1691,19 +1701,19 @@ static const struct platform_device_id gpmi_ids[] = {
{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
{ .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, },
{},
{}
};
static const struct of_device_id gpmi_nand_id_table[] = {
{
.compatible = "fsl,imx23-gpmi-nand",
.data = (void *)&gpmi_ids[IS_MX23]
.data = (void *)&gpmi_ids[IS_MX23],
}, {
.compatible = "fsl,imx28-gpmi-nand",
.data = (void *)&gpmi_ids[IS_MX28]
.data = (void *)&gpmi_ids[IS_MX28],
}, {
.compatible = "fsl,imx6q-gpmi-nand",
.data = (void *)&gpmi_ids[IS_MX6Q]
.data = (void *)&gpmi_ids[IS_MX6Q],
}, {}
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
@ -1722,7 +1732,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
return -ENODEV;
}
this = kzalloc(sizeof(*this), GFP_KERNEL);
this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
if (!this) {
pr_err("Failed to allocate per-device memory\n");
return -ENOMEM;
@ -1752,7 +1762,6 @@ exit_nfc_init:
release_resources(this);
exit_acquire_resources:
dev_err(this->dev, "driver registration failed: %d\n", ret);
kfree(this);
return ret;
}
@ -1763,7 +1772,6 @@ static int gpmi_nand_remove(struct platform_device *pdev)
gpmi_nfc_exit(this);
release_resources(this);
kfree(this);
return 0;
}

View File

@ -108,6 +108,9 @@
#define HW_GPMI_CTRL1_CLR 0x00000068
#define HW_GPMI_CTRL1_TOG 0x0000006c
#define BP_GPMI_CTRL1_DECOUPLE_CS 24
#define BM_GPMI_CTRL1_DECOUPLE_CS (1 << BP_GPMI_CTRL1_DECOUPLE_CS)
#define BP_GPMI_CTRL1_WRN_DLY_SEL 22
#define BM_GPMI_CTRL1_WRN_DLY_SEL (0x3 << BP_GPMI_CTRL1_WRN_DLY_SEL)
#define BF_GPMI_CTRL1_WRN_DLY_SEL(v) \

View File

@ -905,7 +905,7 @@ static struct platform_driver lpc32xx_nand_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(lpc32xx_nand_match),
.of_match_table = lpc32xx_nand_match,
},
};

View File

@ -893,7 +893,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
/* Avoid extra scan if using BBT, setup BBT support */
if (host->ncfg->use_bbt) {
chip->options |= NAND_SKIP_BBTSCAN;
chip->bbt_options |= NAND_BBT_USE_FLASH;
/*
@ -915,13 +914,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
goto err_exit3;
}
/* Standard layout in FLASH for bad block tables */
if (host->ncfg->use_bbt) {
if (nand_default_bbt(mtd) < 0)
dev_err(&pdev->dev,
"Error initializing default bad block tables\n");
}
mtd->name = "nxp_lpc3220_slc";
ppdata.of_node = pdev->dev.of_node;
res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
@ -1023,7 +1015,7 @@ static struct platform_driver lpc32xx_nand_driver = {
.driver = {
.name = LPC32XX_MODNAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(lpc32xx_nand_match),
.of_match_table = lpc32xx_nand_match,
},
};

View File

@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_mtd.h>
@ -1507,7 +1508,7 @@ static int mxcnd_probe(struct platform_device *pdev)
host->devtype_data->irq_control(host, 0);
err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
IRQF_DISABLED, DRIVER_NAME, host);
0, DRIVER_NAME, host);
if (err)
return err;

View File

@ -2912,12 +2912,13 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
/* get the info we want. */
ecc = (struct onfi_ext_ecc_info *)cursor;
if (ecc->codeword_size) {
chip->ecc_strength_ds = ecc->ecc_bits;
chip->ecc_step_ds = 1 << ecc->codeword_size;
if (!ecc->codeword_size) {
pr_debug("Invalid codeword size\n");
goto ext_out;
}
pr_info("ONFI extended param page detected.\n");
chip->ecc_strength_ds = ecc->ecc_bits;
chip->ecc_step_ds = 1 << ecc->codeword_size;
ret = 0;
ext_out:
@ -2935,29 +2936,34 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int i;
int val;
/* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */
if (chip->options & NAND_BUSWIDTH_16) {
pr_err("Trying ONFI probe in 16 bits mode, aborting !\n");
return 0;
}
/* Try ONFI for unknown chip or LP */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
return 0;
/*
* ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not
* with NAND_BUSWIDTH_16
*/
if (chip->options & NAND_BUSWIDTH_16) {
pr_err("ONFI cannot be probed in 16-bit mode; aborting\n");
return 0;
}
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
pr_info("ONFI param page %d valid\n", i);
break;
}
}
if (i == 3)
if (i == 3) {
pr_err("Could not find valid ONFI parameter page; aborting\n");
return 0;
}
/* Check version */
val = le16_to_cpu(p->revision);
@ -2981,11 +2987,23 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
sanitize_string(p->model, sizeof(p->model));
if (!mtd->name)
mtd->name = p->model;
mtd->writesize = le32_to_cpu(p->byte_per_page);
mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
/*
* 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);
chip->chipsize = le32_to_cpu(p->blocks_per_lun);
/* 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;
if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16;
@ -3009,10 +3027,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
/* The Extended Parameter Page is supported since ONFI 2.1. */
if (nand_flash_detect_ext_param_page(mtd, chip, p))
pr_info("Failed to detect the extended param page.\n");
pr_warn("Failed to detect ONFI extended param page\n");
} else {
pr_warn("Could not retrieve ONFI ECC requirements\n");
}
pr_info("ONFI flash detected\n");
return 1;
}
@ -3075,6 +3094,16 @@ static int nand_id_len(u8 *id_data, int arrlen)
return arrlen;
}
/* Extract the bits of per cell from the 3rd byte of the extended ID */
static int nand_get_bits_per_cell(u8 cellinfo)
{
int bits;
bits = cellinfo & NAND_CI_CELLTYPE_MSK;
bits >>= NAND_CI_CELLTYPE_SHIFT;
return bits + 1;
}
/*
* Many new NAND share similar device ID codes, which represent the size of the
* chip. The rest of the parameters must be decoded according to generic or
@ -3085,7 +3114,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
{
int extid, id_len;
/* The 3rd id byte holds MLC / multichip data */
chip->cellinfo = id_data[2];
chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
/* The 4th id byte is the important one */
extid = id_data[3];
@ -3101,8 +3130,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
* ID to decide what to do.
*/
if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
id_data[5] != 0x00) {
!nand_is_slc(chip) && id_data[5] != 0x00) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
@ -3134,7 +3162,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
(((extid >> 1) & 0x04) | (extid & 0x03));
*busw = 0;
} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
!nand_is_slc(chip)) {
unsigned int tmp;
/* Calc pagesize */
@ -3197,7 +3225,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
* - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC
*/
if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
nand_is_slc(chip) &&
(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
!(id_data[4] & 0x80) /* !BENAND */) {
mtd->oobsize = 32 * mtd->writesize >> 9;
@ -3222,6 +3250,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
mtd->oobsize = mtd->writesize / 32;
*busw = type->options & NAND_BUSWIDTH_16;
/* All legacy ID NAND are small-page, SLC */
chip->bits_per_cell = 1;
/*
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
* some Spansion chips have erasesize that conflicts with size
@ -3258,11 +3289,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
* Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
* AMD/Spansion, and Macronix. All others scan only the first page.
*/
if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
if (!nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX))
chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
else if ((nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX ||
maf_id == NAND_MFR_TOSHIBA ||
@ -3286,7 +3317,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
mtd->erasesize = type->erasesize;
mtd->oobsize = type->oobsize;
chip->cellinfo = id_data[2];
chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
chip->chipsize = (uint64_t)type->chipsize << 20;
chip->options |= type->options;
chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
@ -3441,11 +3472,13 @@ ident_done:
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
" %dMiB, page size: %d, OOB size: %d\n",
pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)\n",
*maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
chip->onfi_version ? chip->onfi_params.model : type->name,
(int)(chip->chipsize >> 20), mtd->writesize, mtd->oobsize);
chip->onfi_version ? chip->onfi_params.model : type->name);
pr_info("NAND device: %dMiB, %s, page size: %d, OOB size: %d\n",
(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
mtd->writesize, mtd->oobsize);
return type;
}
@ -3525,6 +3558,7 @@ int nand_scan_tail(struct mtd_info *mtd)
{
int i;
struct nand_chip *chip = mtd->priv;
struct nand_ecc_ctrl *ecc = &chip->ecc;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
@ -3541,19 +3575,19 @@ int nand_scan_tail(struct mtd_info *mtd)
/*
* If no default placement scheme is given, select an appropriate one.
*/
if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) {
switch (mtd->oobsize) {
case 8:
chip->ecc.layout = &nand_oob_8;
ecc->layout = &nand_oob_8;
break;
case 16:
chip->ecc.layout = &nand_oob_16;
ecc->layout = &nand_oob_16;
break;
case 64:
chip->ecc.layout = &nand_oob_64;
ecc->layout = &nand_oob_64;
break;
case 128:
chip->ecc.layout = &nand_oob_128;
ecc->layout = &nand_oob_128;
break;
default:
pr_warn("No oob scheme defined for oobsize %d\n",
@ -3570,64 +3604,62 @@ int nand_scan_tail(struct mtd_info *mtd)
* selected and we have 256 byte pagesize fallback to software ECC
*/
switch (chip->ecc.mode) {
switch (ecc->mode) {
case NAND_ECC_HW_OOB_FIRST:
/* Similar to NAND_ECC_HW, but a separate read_page handle */
if (!chip->ecc.calculate || !chip->ecc.correct ||
!chip->ecc.hwctl) {
if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
if (!chip->ecc.read_page)
chip->ecc.read_page = nand_read_page_hwecc_oob_first;
if (!ecc->read_page)
ecc->read_page = nand_read_page_hwecc_oob_first;
case NAND_ECC_HW:
/* Use standard hwecc read page function? */
if (!chip->ecc.read_page)
chip->ecc.read_page = nand_read_page_hwecc;
if (!chip->ecc.write_page)
chip->ecc.write_page = nand_write_page_hwecc;
if (!chip->ecc.read_page_raw)
chip->ecc.read_page_raw = nand_read_page_raw;
if (!chip->ecc.write_page_raw)
chip->ecc.write_page_raw = nand_write_page_raw;
if (!chip->ecc.read_oob)
chip->ecc.read_oob = nand_read_oob_std;
if (!chip->ecc.write_oob)
chip->ecc.write_oob = nand_write_oob_std;
if (!chip->ecc.read_subpage)
chip->ecc.read_subpage = nand_read_subpage;
if (!chip->ecc.write_subpage)
chip->ecc.write_subpage = nand_write_subpage_hwecc;
if (!ecc->read_page)
ecc->read_page = nand_read_page_hwecc;
if (!ecc->write_page)
ecc->write_page = nand_write_page_hwecc;
if (!ecc->read_page_raw)
ecc->read_page_raw = nand_read_page_raw;
if (!ecc->write_page_raw)
ecc->write_page_raw = nand_write_page_raw;
if (!ecc->read_oob)
ecc->read_oob = nand_read_oob_std;
if (!ecc->write_oob)
ecc->write_oob = nand_write_oob_std;
if (!ecc->read_subpage)
ecc->read_subpage = nand_read_subpage;
if (!ecc->write_subpage)
ecc->write_subpage = nand_write_subpage_hwecc;
case NAND_ECC_HW_SYNDROME:
if ((!chip->ecc.calculate || !chip->ecc.correct ||
!chip->ecc.hwctl) &&
(!chip->ecc.read_page ||
chip->ecc.read_page == nand_read_page_hwecc ||
!chip->ecc.write_page ||
chip->ecc.write_page == nand_write_page_hwecc)) {
if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
(!ecc->read_page ||
ecc->read_page == nand_read_page_hwecc ||
!ecc->write_page ||
ecc->write_page == nand_write_page_hwecc)) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
/* Use standard syndrome read/write page function? */
if (!chip->ecc.read_page)
chip->ecc.read_page = nand_read_page_syndrome;
if (!chip->ecc.write_page)
chip->ecc.write_page = nand_write_page_syndrome;
if (!chip->ecc.read_page_raw)
chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
if (!chip->ecc.write_page_raw)
chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
if (!chip->ecc.read_oob)
chip->ecc.read_oob = nand_read_oob_syndrome;
if (!chip->ecc.write_oob)
chip->ecc.write_oob = nand_write_oob_syndrome;
if (!ecc->read_page)
ecc->read_page = nand_read_page_syndrome;
if (!ecc->write_page)
ecc->write_page = nand_write_page_syndrome;
if (!ecc->read_page_raw)
ecc->read_page_raw = nand_read_page_raw_syndrome;
if (!ecc->write_page_raw)
ecc->write_page_raw = nand_write_page_raw_syndrome;
if (!ecc->read_oob)
ecc->read_oob = nand_read_oob_syndrome;
if (!ecc->write_oob)
ecc->write_oob = nand_write_oob_syndrome;
if (mtd->writesize >= chip->ecc.size) {
if (!chip->ecc.strength) {
if (mtd->writesize >= ecc->size) {
if (!ecc->strength) {
pr_warn("Driver must set ecc.strength when using hardware ECC\n");
BUG();
}
@ -3635,23 +3667,23 @@ int nand_scan_tail(struct mtd_info *mtd)
}
pr_warn("%d byte HW ECC not possible on "
"%d byte page size, fallback to SW ECC\n",
chip->ecc.size, mtd->writesize);
chip->ecc.mode = NAND_ECC_SOFT;
ecc->size, mtd->writesize);
ecc->mode = NAND_ECC_SOFT;
case NAND_ECC_SOFT:
chip->ecc.calculate = nand_calculate_ecc;
chip->ecc.correct = nand_correct_data;
chip->ecc.read_page = nand_read_page_swecc;
chip->ecc.read_subpage = nand_read_subpage;
chip->ecc.write_page = nand_write_page_swecc;
chip->ecc.read_page_raw = nand_read_page_raw;
chip->ecc.write_page_raw = nand_write_page_raw;
chip->ecc.read_oob = nand_read_oob_std;
chip->ecc.write_oob = nand_write_oob_std;
if (!chip->ecc.size)
chip->ecc.size = 256;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
ecc->calculate = nand_calculate_ecc;
ecc->correct = nand_correct_data;
ecc->read_page = nand_read_page_swecc;
ecc->read_subpage = nand_read_subpage;
ecc->write_page = nand_write_page_swecc;
ecc->read_page_raw = nand_read_page_raw;
ecc->write_page_raw = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->write_oob = nand_write_oob_std;
if (!ecc->size)
ecc->size = 256;
ecc->bytes = 3;
ecc->strength = 1;
break;
case NAND_ECC_SOFT_BCH:
@ -3659,88 +3691,83 @@ int nand_scan_tail(struct mtd_info *mtd)
pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
BUG();
}
chip->ecc.calculate = nand_bch_calculate_ecc;
chip->ecc.correct = nand_bch_correct_data;
chip->ecc.read_page = nand_read_page_swecc;
chip->ecc.read_subpage = nand_read_subpage;
chip->ecc.write_page = nand_write_page_swecc;
chip->ecc.read_page_raw = nand_read_page_raw;
chip->ecc.write_page_raw = nand_write_page_raw;
chip->ecc.read_oob = nand_read_oob_std;
chip->ecc.write_oob = nand_write_oob_std;
ecc->calculate = nand_bch_calculate_ecc;
ecc->correct = nand_bch_correct_data;
ecc->read_page = nand_read_page_swecc;
ecc->read_subpage = nand_read_subpage;
ecc->write_page = nand_write_page_swecc;
ecc->read_page_raw = nand_read_page_raw;
ecc->write_page_raw = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->write_oob = nand_write_oob_std;
/*
* Board driver should supply ecc.size and ecc.bytes values to
* select how many bits are correctable; see nand_bch_init()
* for details. Otherwise, default to 4 bits for large page
* devices.
*/
if (!chip->ecc.size && (mtd->oobsize >= 64)) {
chip->ecc.size = 512;
chip->ecc.bytes = 7;
if (!ecc->size && (mtd->oobsize >= 64)) {
ecc->size = 512;
ecc->bytes = 7;
}
chip->ecc.priv = nand_bch_init(mtd,
chip->ecc.size,
chip->ecc.bytes,
&chip->ecc.layout);
if (!chip->ecc.priv) {
ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
&ecc->layout);
if (!ecc->priv) {
pr_warn("BCH ECC initialization failed!\n");
BUG();
}
chip->ecc.strength =
chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size);
break;
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. "
"This is not recommended!\n");
chip->ecc.read_page = nand_read_page_raw;
chip->ecc.write_page = nand_write_page_raw;
chip->ecc.read_oob = nand_read_oob_std;
chip->ecc.read_page_raw = nand_read_page_raw;
chip->ecc.write_page_raw = nand_write_page_raw;
chip->ecc.write_oob = nand_write_oob_std;
chip->ecc.size = mtd->writesize;
chip->ecc.bytes = 0;
chip->ecc.strength = 0;
ecc->read_page = nand_read_page_raw;
ecc->write_page = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->read_page_raw = nand_read_page_raw;
ecc->write_page_raw = nand_write_page_raw;
ecc->write_oob = nand_write_oob_std;
ecc->size = mtd->writesize;
ecc->bytes = 0;
ecc->strength = 0;
break;
default:
pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode);
BUG();
}
/* For many systems, the standard OOB write also works for raw */
if (!chip->ecc.read_oob_raw)
chip->ecc.read_oob_raw = chip->ecc.read_oob;
if (!chip->ecc.write_oob_raw)
chip->ecc.write_oob_raw = chip->ecc.write_oob;
if (!ecc->read_oob_raw)
ecc->read_oob_raw = ecc->read_oob;
if (!ecc->write_oob_raw)
ecc->write_oob_raw = ecc->write_oob;
/*
* The number of bytes available for a client to place data into
* the out of band area.
*/
chip->ecc.layout->oobavail = 0;
for (i = 0; chip->ecc.layout->oobfree[i].length
&& i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
chip->ecc.layout->oobavail +=
chip->ecc.layout->oobfree[i].length;
mtd->oobavail = chip->ecc.layout->oobavail;
ecc->layout->oobavail = 0;
for (i = 0; ecc->layout->oobfree[i].length
&& i < ARRAY_SIZE(ecc->layout->oobfree); i++)
ecc->layout->oobavail += ecc->layout->oobfree[i].length;
mtd->oobavail = ecc->layout->oobavail;
/*
* Set the number of read / write steps for one page depending on ECC
* mode.
*/
chip->ecc.steps = mtd->writesize / chip->ecc.size;
if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
ecc->steps = mtd->writesize / ecc->size;
if (ecc->steps * ecc->size != mtd->writesize) {
pr_warn("Invalid ECC parameters\n");
BUG();
}
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
ecc->total = ecc->steps * ecc->bytes;
/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
switch (chip->ecc.steps) {
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
switch (ecc->steps) {
case 2:
mtd->subpage_sft = 1;
break;
@ -3760,11 +3787,11 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->pagebuf = -1;
/* Large page NAND with SOFT_ECC should support subpage reads */
if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
if ((ecc->mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
chip->options |= NAND_SUBPAGE_READ;
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
MTD_CAP_NANDFLASH;
mtd->_erase = nand_erase;
@ -3785,9 +3812,9 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->writebufsize = mtd->writesize;
/* propagate ecc info to mtd_info */
mtd->ecclayout = chip->ecc.layout;
mtd->ecc_strength = chip->ecc.strength;
mtd->ecc_step_size = chip->ecc.size;
mtd->ecclayout = ecc->layout;
mtd->ecc_strength = ecc->strength;
mtd->ecc_step_size = ecc->size;
/*
* Initialize bitflip_threshold to its default prior scan_bbt() call.
* scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be

View File

@ -412,25 +412,6 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
}
}
/* Scan a given block full */
static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
loff_t offs, uint8_t *buf, size_t readlen,
int scanlen, int numpages)
{
int ret, j;
ret = scan_read_oob(mtd, buf, offs, readlen);
/* Ignore ECC errors when checking for BBM */
if (ret && !mtd_is_bitflip_or_eccerr(ret))
return ret;
for (j = 0; j < numpages; j++, buf += scanlen) {
if (check_pattern(buf, scanlen, mtd->writesize, bd))
return 1;
}
return 0;
}
/* Scan a given block partially */
static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
loff_t offs, uint8_t *buf, int numpages)
@ -477,24 +458,17 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *bd, int chip)
{
struct nand_chip *this = mtd->priv;
int i, numblocks, numpages, scanlen;
int i, numblocks, numpages;
int startblock;
loff_t from;
size_t readlen;
pr_info("Scanning device for bad blocks\n");
if (bd->options & NAND_BBT_SCANALLPAGES)
numpages = 1 << (this->bbt_erase_shift - this->page_shift);
else if (bd->options & NAND_BBT_SCAN2NDPAGE)
if (bd->options & NAND_BBT_SCAN2NDPAGE)
numpages = 2;
else
numpages = 1;
/* We need only read few bytes from the OOB area */
scanlen = 0;
readlen = bd->len;
if (chip == -1) {
numblocks = mtd->size >> this->bbt_erase_shift;
startblock = 0;
@ -519,12 +493,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
BUG_ON(bd->options & NAND_BBT_NO_OOB);
if (bd->options & NAND_BBT_SCANALLPAGES)
ret = scan_block_full(mtd, bd, from, buf, readlen,
scanlen, numpages);
else
ret = scan_block_fast(mtd, bd, from, buf, numpages);
ret = scan_block_fast(mtd, bd, from, buf, numpages);
if (ret < 0)
return ret;
@ -1392,4 +1361,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
}
EXPORT_SYMBOL(nand_scan_bbt);
EXPORT_SYMBOL(nand_default_bbt);

View File

@ -2372,7 +2372,7 @@ static int __init ns_init_module(void)
if ((retval = init_nandsim(nsmtd)) != 0)
goto err_exit;
if ((retval = nand_default_bbt(nsmtd)) != 0)
if ((retval = chip->scan_bbt(nsmtd)) != 0)
goto err_exit;
if ((retval = parse_badblocks(nand, nsmtd)) != 0)

View File

@ -25,10 +25,8 @@
#include <linux/of.h>
#include <linux/of_device.h>
#ifdef CONFIG_MTD_NAND_OMAP_BCH
#include <linux/bch.h>
#include <linux/mtd/nand_bch.h>
#include <linux/platform_data/elm.h>
#endif
#include <linux/platform_data/mtd-nand-omap2.h>
@ -141,6 +139,8 @@
#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */
#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */
#define BADBLOCK_MARKER_LENGTH 2
#ifdef CONFIG_MTD_NAND_OMAP_BCH
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
@ -149,17 +149,6 @@ static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
/* Define some generic bad / good block scan pattern which are used
* while scanning a device for factory marked good / bad blocks
*/
static uint8_t scan_ff_pattern[] = { 0xff };
static struct nand_bbt_descr bb_descrip_flashbased = {
.options = NAND_BBT_SCANALLPAGES,
.offs = 0,
.len = 1,
.pattern = scan_ff_pattern,
};
struct omap_nand_info {
struct nand_hw_control controller;
@ -182,14 +171,10 @@ struct omap_nand_info {
u_char *buf;
int buf_len;
struct gpmc_nand_regs reg;
#ifdef CONFIG_MTD_NAND_OMAP_BCH
struct bch_control *bch;
struct nand_ecclayout ecclayout;
/* fields specific for BCHx_HW ECC scheme */
bool is_elm_used;
struct device *elm_dev;
struct device_node *of_node;
#endif
};
/**
@ -1058,8 +1043,7 @@ static int omap_dev_ready(struct mtd_info *mtd)
}
}
#ifdef CONFIG_MTD_NAND_OMAP_BCH
#if defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH)
/**
* omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
* @mtd: MTD device structure
@ -1140,7 +1124,9 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
/* Clear ecc and enable bits */
writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
#endif
#ifdef CONFIG_MTD_NAND_ECC_BCH
/**
* omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes
* @mtd: MTD device structure
@ -1225,7 +1211,9 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
return 0;
}
#endif /* CONFIG_MTD_NAND_ECC_BCH */
#ifdef CONFIG_MTD_NAND_OMAP_BCH
/**
* omap3_calculate_ecc_bch - Generate bytes of ECC bytes
* @mtd: MTD device structure
@ -1518,38 +1506,6 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
return stat;
}
/**
* omap3_correct_data_bch - Decode received data and correct errors
* @mtd: MTD device structure
* @data: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
*/
static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
{
int i, count;
/* cannot correct more than 8 errors */
unsigned int errloc[8];
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL,
errloc);
if (count > 0) {
/* correct errors */
for (i = 0; i < count; i++) {
/* correct data only, not ecc bytes */
if (errloc[i] < 8*512)
data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
pr_debug("corrected bitflip %u\n", errloc[i]);
}
} else if (count < 0) {
pr_err("ecc unrecoverable error\n");
}
return count;
}
/**
* omap_write_page_bch - BCH ecc based write page function for entire page
* @mtd: mtd info structure
@ -1637,197 +1593,46 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
* omap3_free_bch - Release BCH ecc resources
* @mtd: MTD device structure
* is_elm_present - checks for presence of ELM module by scanning DT nodes
* @omap_nand_info: NAND device structure containing platform data
* @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16
*/
static void omap3_free_bch(struct mtd_info *mtd)
static int is_elm_present(struct omap_nand_info *info,
struct device_node *elm_node, enum bch_ecc bch_type)
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
if (info->bch) {
free_bch(info->bch);
info->bch = NULL;
struct platform_device *pdev;
info->is_elm_used = false;
/* check whether elm-id is passed via DT */
if (!elm_node) {
pr_err("nand: error: ELM DT node not found\n");
return -ENODEV;
}
}
/**
* omap3_init_bch - Initialize BCH ECC
* @mtd: MTD device structure
* @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW)
*/
static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
{
int max_errors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
#ifdef CONFIG_MTD_NAND_OMAP_BCH8
const int hw_errors = BCH8_MAX_ERROR;
#else
const int hw_errors = BCH4_MAX_ERROR;
#endif
enum bch_ecc bch_type;
const __be32 *parp;
int lenp;
struct device_node *elm_node;
info->bch = NULL;
max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ?
BCH8_MAX_ERROR : BCH4_MAX_ERROR;
if (max_errors != hw_errors) {
pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported",
max_errors, hw_errors);
goto fail;
pdev = of_find_device_by_node(elm_node);
/* check whether ELM device is registered */
if (!pdev) {
pr_err("nand: error: ELM device not found\n");
return -ENODEV;
}
info->nand.ecc.size = 512;
info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
info->nand.ecc.mode = NAND_ECC_HW;
info->nand.ecc.strength = max_errors;
if (hw_errors == BCH8_MAX_ERROR)
bch_type = BCH8_ECC;
else
bch_type = BCH4_ECC;
/* Detect availability of ELM module */
parp = of_get_property(info->of_node, "elm_id", &lenp);
if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
pr_err("Missing elm_id property, fall back to Software BCH\n");
info->is_elm_used = false;
} else {
struct platform_device *pdev;
elm_node = of_find_node_by_phandle(be32_to_cpup(parp));
pdev = of_find_device_by_node(elm_node);
info->elm_dev = &pdev->dev;
if (elm_config(info->elm_dev, bch_type) == 0)
info->is_elm_used = true;
}
if (info->is_elm_used && (mtd->writesize <= 4096)) {
if (hw_errors == BCH8_MAX_ERROR)
info->nand.ecc.bytes = BCH8_SIZE;
else
info->nand.ecc.bytes = BCH4_SIZE;
info->nand.ecc.correct = omap_elm_correct_data;
info->nand.ecc.calculate = omap3_calculate_ecc_bch;
info->nand.ecc.read_page = omap_read_page_bch;
info->nand.ecc.write_page = omap_write_page_bch;
} else {
/*
* software bch library is only used to detect and
* locate errors
*/
info->bch = init_bch(13, max_errors,
0x201b /* hw polynomial */);
if (!info->bch)
goto fail;
info->nand.ecc.correct = omap3_correct_data_bch;
/*
* The number of corrected errors in an ecc block that will
* trigger block scrubbing defaults to the ecc strength (4 or 8)
* Set mtd->bitflip_threshold here to define a custom threshold.
*/
if (max_errors == 8) {
info->nand.ecc.bytes = 13;
info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
} else {
info->nand.ecc.bytes = 7;
info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
}
}
pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors);
/* ELM module available, now configure it */
info->elm_dev = &pdev->dev;
if (elm_config(info->elm_dev, bch_type))
return -ENODEV;
info->is_elm_used = true;
return 0;
fail:
omap3_free_bch(mtd);
return -1;
}
/**
* omap3_init_bch_tail - Build an oob layout for BCH ECC correction.
* @mtd: MTD device structure
*/
static int omap3_init_bch_tail(struct mtd_info *mtd)
{
int i, steps, offset;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
struct nand_ecclayout *layout = &info->ecclayout;
/* build oob layout */
steps = mtd->writesize/info->nand.ecc.size;
layout->eccbytes = steps*info->nand.ecc.bytes;
/* do not bother creating special oob layouts for small page devices */
if (mtd->oobsize < 64) {
pr_err("BCH ecc is not supported on small page devices\n");
goto fail;
}
/* reserve 2 bytes for bad block marker */
if (layout->eccbytes+2 > mtd->oobsize) {
pr_err("no oob layout available for oobsize %d eccbytes %u\n",
mtd->oobsize, layout->eccbytes);
goto fail;
}
/* ECC layout compatible with RBL for BCH8 */
if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
offset = 2;
else
offset = mtd->oobsize - layout->eccbytes;
/* put ecc bytes at oob tail */
for (i = 0; i < layout->eccbytes; i++)
layout->eccpos[i] = offset + i;
if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
layout->oobfree[0].offset = 2 + layout->eccbytes * steps;
else
layout->oobfree[0].offset = 2;
layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
info->nand.ecc.layout = layout;
if (!(info->nand.options & NAND_BUSWIDTH_16))
info->nand.badblock_pattern = &bb_descrip_flashbased;
return 0;
fail:
omap3_free_bch(mtd);
return -1;
}
#else
static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
{
pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n");
return -1;
}
static int omap3_init_bch_tail(struct mtd_info *mtd)
{
return -1;
}
static void omap3_free_bch(struct mtd_info *mtd)
{
}
#endif /* CONFIG_MTD_NAND_OMAP_BCH */
#endif /* CONFIG_MTD_NAND_ECC_BCH */
static int omap_nand_probe(struct platform_device *pdev)
{
struct omap_nand_info *info;
struct omap_nand_platform_data *pdata;
struct mtd_info *mtd;
struct nand_chip *nand_chip;
struct nand_ecclayout *ecclayout;
int err;
int i, offset;
dma_cap_mask_t mask;
unsigned sig;
int i;
dma_cap_mask_t mask;
unsigned sig;
struct resource *res;
struct mtd_part_parser_data ppdata = {};
@ -1837,7 +1642,8 @@ static int omap_nand_probe(struct platform_device *pdev)
return -ENODEV;
}
info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -1846,47 +1652,45 @@ static int omap_nand_probe(struct platform_device *pdev)
spin_lock_init(&info->controller.lock);
init_waitqueue_head(&info->controller.wq);
info->pdev = pdev;
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
info->reg = pdata->reg;
info->mtd.priv = &info->nand;
info->mtd.name = dev_name(&pdev->dev);
info->mtd.owner = THIS_MODULE;
info->nand.options = pdata->devsize;
info->nand.options |= NAND_SKIP_BBTSCAN;
#ifdef CONFIG_MTD_NAND_OMAP_BCH
info->of_node = pdata->of_node;
#endif
mtd = &info->mtd;
mtd->priv = &info->nand;
mtd->name = dev_name(&pdev->dev);
mtd->owner = THIS_MODULE;
nand_chip = &info->nand;
nand_chip->ecc.priv = NULL;
nand_chip->options |= NAND_SKIP_BBTSCAN;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
err = -EINVAL;
dev_err(&pdev->dev, "error getting memory resource\n");
goto out_free_info;
goto return_error;
}
info->phys_base = res->start;
info->mem_size = resource_size(res);
if (!request_mem_region(info->phys_base, info->mem_size,
pdev->dev.driver->name)) {
if (!devm_request_mem_region(&pdev->dev, info->phys_base,
info->mem_size, pdev->dev.driver->name)) {
err = -EBUSY;
goto out_free_info;
goto return_error;
}
info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
if (!info->nand.IO_ADDR_R) {
nand_chip->IO_ADDR_R = devm_ioremap(&pdev->dev, info->phys_base,
info->mem_size);
if (!nand_chip->IO_ADDR_R) {
err = -ENOMEM;
goto out_release_mem_region;
goto return_error;
}
info->nand.controller = &info->controller;
nand_chip->controller = &info->controller;
info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
info->nand.cmd_ctrl = omap_hwcontrol;
nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
nand_chip->cmd_ctrl = omap_hwcontrol;
/*
* If RDY/BSY line is connected to OMAP then use the omap ready
@ -1896,26 +1700,42 @@ static int omap_nand_probe(struct platform_device *pdev)
* device and read status register until you get a failure or success
*/
if (pdata->dev_ready) {
info->nand.dev_ready = omap_dev_ready;
info->nand.chip_delay = 0;
nand_chip->dev_ready = omap_dev_ready;
nand_chip->chip_delay = 0;
} else {
info->nand.waitfunc = omap_wait;
info->nand.chip_delay = 50;
nand_chip->waitfunc = omap_wait;
nand_chip->chip_delay = 50;
}
/* scan NAND device connected to chip controller */
nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16;
if (nand_scan_ident(mtd, 1, NULL)) {
pr_err("nand device scan failed, may be bus-width mismatch\n");
err = -ENXIO;
goto return_error;
}
/* check for small page devices */
if ((mtd->oobsize < 64) && (pdata->ecc_opt != OMAP_ECC_HAM1_CODE_HW)) {
pr_err("small page devices are not supported\n");
err = -EINVAL;
goto return_error;
}
/* re-populate low-level callbacks based on xfer modes */
switch (pdata->xfer_type) {
case NAND_OMAP_PREFETCH_POLLED:
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
nand_chip->read_buf = omap_read_buf_pref;
nand_chip->write_buf = omap_write_buf_pref;
break;
case NAND_OMAP_POLLED:
if (info->nand.options & NAND_BUSWIDTH_16) {
info->nand.read_buf = omap_read_buf16;
info->nand.write_buf = omap_write_buf16;
if (nand_chip->options & NAND_BUSWIDTH_16) {
nand_chip->read_buf = omap_read_buf16;
nand_chip->write_buf = omap_write_buf16;
} else {
info->nand.read_buf = omap_read_buf8;
info->nand.write_buf = omap_write_buf8;
nand_chip->read_buf = omap_read_buf8;
nand_chip->write_buf = omap_write_buf8;
}
break;
@ -1927,7 +1747,7 @@ static int omap_nand_probe(struct platform_device *pdev)
if (!info->dma) {
dev_err(&pdev->dev, "DMA engine request failed\n");
err = -ENXIO;
goto out_release_mem_region;
goto return_error;
} else {
struct dma_slave_config cfg;
@ -1942,10 +1762,10 @@ static int omap_nand_probe(struct platform_device *pdev)
if (err) {
dev_err(&pdev->dev, "DMA engine slave config failed: %d\n",
err);
goto out_release_mem_region;
goto return_error;
}
info->nand.read_buf = omap_read_buf_dma_pref;
info->nand.write_buf = omap_write_buf_dma_pref;
nand_chip->read_buf = omap_read_buf_dma_pref;
nand_chip->write_buf = omap_write_buf_dma_pref;
}
break;
@ -1954,34 +1774,36 @@ static int omap_nand_probe(struct platform_device *pdev)
if (info->gpmc_irq_fifo <= 0) {
dev_err(&pdev->dev, "error getting fifo irq\n");
err = -ENODEV;
goto out_release_mem_region;
goto return_error;
}
err = request_irq(info->gpmc_irq_fifo, omap_nand_irq,
IRQF_SHARED, "gpmc-nand-fifo", info);
err = devm_request_irq(&pdev->dev, info->gpmc_irq_fifo,
omap_nand_irq, IRQF_SHARED,
"gpmc-nand-fifo", info);
if (err) {
dev_err(&pdev->dev, "requesting irq(%d) error:%d",
info->gpmc_irq_fifo, err);
info->gpmc_irq_fifo = 0;
goto out_release_mem_region;
goto return_error;
}
info->gpmc_irq_count = platform_get_irq(pdev, 1);
if (info->gpmc_irq_count <= 0) {
dev_err(&pdev->dev, "error getting count irq\n");
err = -ENODEV;
goto out_release_mem_region;
goto return_error;
}
err = request_irq(info->gpmc_irq_count, omap_nand_irq,
IRQF_SHARED, "gpmc-nand-count", info);
err = devm_request_irq(&pdev->dev, info->gpmc_irq_count,
omap_nand_irq, IRQF_SHARED,
"gpmc-nand-count", info);
if (err) {
dev_err(&pdev->dev, "requesting irq(%d) error:%d",
info->gpmc_irq_count, err);
info->gpmc_irq_count = 0;
goto out_release_mem_region;
goto return_error;
}
info->nand.read_buf = omap_read_buf_irq_pref;
info->nand.write_buf = omap_write_buf_irq_pref;
nand_chip->read_buf = omap_read_buf_irq_pref;
nand_chip->write_buf = omap_write_buf_irq_pref;
break;
@ -1989,117 +1811,223 @@ static int omap_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"xfer_type(%d) not supported!\n", pdata->xfer_type);
err = -EINVAL;
goto out_release_mem_region;
goto return_error;
}
/* select the ecc type */
if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
info->nand.ecc.mode = NAND_ECC_SOFT;
else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
(pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
info->nand.ecc.strength = 1;
info->nand.ecc.calculate = omap_calculate_ecc;
info->nand.ecc.hwctl = omap_enable_hwecc;
info->nand.ecc.correct = omap_correct_data;
info->nand.ecc.mode = NAND_ECC_HW;
} else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
(pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
err = omap3_init_bch(&info->mtd, pdata->ecc_opt);
if (err) {
/* populate MTD interface based on ECC scheme */
nand_chip->ecc.layout = &omap_oobinfo;
ecclayout = &omap_oobinfo;
switch (pdata->ecc_opt) {
case OMAP_ECC_HAM1_CODE_HW:
pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.bytes = 3;
nand_chip->ecc.size = 512;
nand_chip->ecc.strength = 1;
nand_chip->ecc.calculate = omap_calculate_ecc;
nand_chip->ecc.hwctl = omap_enable_hwecc;
nand_chip->ecc.correct = omap_correct_data;
/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
nand_chip->ecc.size);
if (nand_chip->options & NAND_BUSWIDTH_16)
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
else
ecclayout->eccpos[0] = 1;
ecclayout->oobfree->offset = ecclayout->eccpos[0] +
ecclayout->eccbytes;
break;
case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
#ifdef CONFIG_MTD_NAND_ECC_BCH
pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
nand_chip->ecc.bytes = 7;
nand_chip->ecc.strength = 4;
nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
nand_chip->ecc.correct = nand_bch_correct_data;
nand_chip->ecc.calculate = omap3_calculate_ecc_bch4;
/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
nand_chip->ecc.size);
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree->offset = ecclayout->eccpos[0] +
ecclayout->eccbytes;
/* software bch library is used for locating errors */
nand_chip->ecc.priv = nand_bch_init(mtd,
nand_chip->ecc.size,
nand_chip->ecc.bytes,
&nand_chip->ecc.layout);
if (!nand_chip->ecc.priv) {
pr_err("nand: error: unable to use s/w BCH library\n");
err = -EINVAL;
goto out_release_mem_region;
}
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif
/* DIP switches on some boards change between 8 and 16 bit
* bus widths for flash. Try the other width if the first try fails.
*/
if (nand_scan_ident(&info->mtd, 1, NULL)) {
info->nand.options ^= NAND_BUSWIDTH_16;
if (nand_scan_ident(&info->mtd, 1, NULL)) {
err = -ENXIO;
goto out_release_mem_region;
case OMAP_ECC_BCH4_CODE_HW:
#ifdef CONFIG_MTD_NAND_OMAP_BCH
pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
/* 14th bit is kept reserved for ROM-code compatibility */
nand_chip->ecc.bytes = 7 + 1;
nand_chip->ecc.strength = 4;
nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
nand_chip->ecc.correct = omap_elm_correct_data;
nand_chip->ecc.calculate = omap3_calculate_ecc_bch;
nand_chip->ecc.read_page = omap_read_page_bch;
nand_chip->ecc.write_page = omap_write_page_bch;
/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
nand_chip->ecc.size);
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree->offset = ecclayout->eccpos[0] +
ecclayout->eccbytes;
/* This ECC scheme requires ELM H/W block */
if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
pr_err("nand: error: could not initialize ELM\n");
err = -ENODEV;
goto return_error;
}
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif
/* rom code layout */
if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
if (info->nand.options & NAND_BUSWIDTH_16)
offset = 2;
else {
offset = 1;
info->nand.badblock_pattern = &bb_descrip_flashbased;
}
omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
for (i = 0; i < omap_oobinfo.eccbytes; i++)
omap_oobinfo.eccpos[i] = i+offset;
omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
omap_oobinfo.oobfree->length = info->mtd.oobsize -
(offset + omap_oobinfo.eccbytes);
info->nand.ecc.layout = &omap_oobinfo;
} else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
(pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
/* build OOB layout for BCH ECC correction */
err = omap3_init_bch_tail(&info->mtd);
if (err) {
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
#ifdef CONFIG_MTD_NAND_ECC_BCH
pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
nand_chip->ecc.bytes = 13;
nand_chip->ecc.strength = 8;
nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
nand_chip->ecc.correct = nand_bch_correct_data;
nand_chip->ecc.calculate = omap3_calculate_ecc_bch8;
/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
nand_chip->ecc.size);
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree->offset = ecclayout->eccpos[0] +
ecclayout->eccbytes;
/* software bch library is used for locating errors */
nand_chip->ecc.priv = nand_bch_init(mtd,
nand_chip->ecc.size,
nand_chip->ecc.bytes,
&nand_chip->ecc.layout);
if (!nand_chip->ecc.priv) {
pr_err("nand: error: unable to use s/w BCH library\n");
err = -EINVAL;
goto out_release_mem_region;
goto return_error;
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif
case OMAP_ECC_BCH8_CODE_HW:
#ifdef CONFIG_MTD_NAND_OMAP_BCH
pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
/* 14th bit is kept reserved for ROM-code compatibility */
nand_chip->ecc.bytes = 13 + 1;
nand_chip->ecc.strength = 8;
nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
nand_chip->ecc.correct = omap_elm_correct_data;
nand_chip->ecc.calculate = omap3_calculate_ecc_bch;
nand_chip->ecc.read_page = omap_read_page_bch;
nand_chip->ecc.write_page = omap_write_page_bch;
/* This ECC scheme requires ELM H/W block */
err = is_elm_present(info, pdata->elm_of_node, BCH8_ECC);
if (err < 0) {
pr_err("nand: error: could not initialize ELM\n");
goto return_error;
}
/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
nand_chip->ecc.size);
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree->offset = ecclayout->eccpos[0] +
ecclayout->eccbytes;
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif
default:
pr_err("nand: error: invalid or unsupported ECC scheme\n");
err = -EINVAL;
goto return_error;
}
/* populate remaining ECC layout data */
ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
ecclayout->eccbytes);
for (i = 1; i < ecclayout->eccbytes; i++)
ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
/* check if NAND device's OOB is enough to store ECC signatures */
if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
pr_err("not enough OOB bytes required = %d, available=%d\n",
ecclayout->eccbytes, mtd->oobsize);
err = -EINVAL;
goto return_error;
}
/* second phase scan */
if (nand_scan_tail(&info->mtd)) {
if (nand_scan_tail(mtd)) {
err = -ENXIO;
goto out_release_mem_region;
goto return_error;
}
ppdata.of_node = pdata->of_node;
mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
pdata->nr_parts);
platform_set_drvdata(pdev, &info->mtd);
platform_set_drvdata(pdev, mtd);
return 0;
out_release_mem_region:
return_error:
if (info->dma)
dma_release_channel(info->dma);
if (info->gpmc_irq_count > 0)
free_irq(info->gpmc_irq_count, info);
if (info->gpmc_irq_fifo > 0)
free_irq(info->gpmc_irq_fifo, info);
release_mem_region(info->phys_base, info->mem_size);
out_free_info:
kfree(info);
if (nand_chip->ecc.priv) {
nand_bch_free(nand_chip->ecc.priv);
nand_chip->ecc.priv = NULL;
}
return err;
}
static int omap_nand_remove(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct nand_chip *nand_chip = mtd->priv;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
omap3_free_bch(&info->mtd);
if (nand_chip->ecc.priv) {
nand_bch_free(nand_chip->ecc.priv);
nand_chip->ecc.priv = NULL;
}
if (info->dma)
dma_release_channel(info->dma);
if (info->gpmc_irq_count > 0)
free_irq(info->gpmc_irq_count, info);
if (info->gpmc_irq_fifo > 0)
free_irq(info->gpmc_irq_fifo, info);
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
iounmap(info->nand.IO_ADDR_R);
release_mem_region(info->phys_base, info->mem_size);
kfree(info);
nand_release(mtd);
return 0;
}

View File

@ -39,6 +39,13 @@
#define NAND_STOP_DELAY (2 * HZ/50)
#define PAGE_CHUNK_SIZE (2048)
/*
* Define a buffer size for the initial command that detects the flash device:
* STATUS, READID and PARAM. The largest of these is the PARAM command,
* needing 256 bytes.
*/
#define INIT_BUFFER_SIZE 256
/* registers and bit definitions */
#define NDCR (0x00) /* Control register */
#define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */
@ -164,6 +171,7 @@ struct pxa3xx_nand_info {
unsigned int buf_start;
unsigned int buf_count;
unsigned int buf_size;
/* DMA information */
int drcmr_dat;
@ -540,7 +548,6 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
info->oob_size = 0;
info->use_ecc = 0;
info->use_spare = 1;
info->use_dma = (use_dma) ? 1 : 0;
info->is_ready = 0;
info->retcode = ERR_NONE;
if (info->cs != 0)
@ -912,26 +919,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
return 0;
}
/* the maximum possible buffer size for large page with OOB data
* is: 2048 + 64 = 2112 bytes, allocate a page here for both the
* data buffer and the DMA descriptor
*/
#define MAX_BUFF_SIZE PAGE_SIZE
#ifdef ARCH_HAS_DMA
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{
struct platform_device *pdev = info->pdev;
int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
if (use_dma == 0) {
info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL)
return -ENOMEM;
return 0;
}
info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
&info->data_buff_phys, GFP_KERNEL);
if (info->data_buff == NULL) {
dev_err(&pdev->dev, "failed to allocate dma buffer\n");
@ -945,11 +946,16 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
pxa3xx_nand_data_dma_irq, info);
if (info->data_dma_ch < 0) {
dev_err(&pdev->dev, "failed to request data dma\n");
dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
dma_free_coherent(&pdev->dev, info->buf_size,
info->data_buff, info->data_buff_phys);
return info->data_dma_ch;
}
/*
* Now that DMA buffers are allocated we turn on
* DMA proper for I/O operations.
*/
info->use_dma = 1;
return 0;
}
@ -958,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
struct platform_device *pdev = info->pdev;
if (use_dma) {
pxa_free_dma(info->data_dma_ch);
dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
dma_free_coherent(&pdev->dev, info->buf_size,
info->data_buff, info->data_buff_phys);
} else {
kfree(info->data_buff);
@ -967,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
#else
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{
info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL)
return -ENOMEM;
return 0;
@ -1081,7 +1087,16 @@ KEEP_CONFIG:
else
host->col_addr_cycles = 1;
/* release the initial buffer */
kfree(info->data_buff);
/* allocate the real data + oob buffer */
info->buf_size = mtd->writesize + mtd->oobsize;
ret = pxa3xx_nand_init_buff(info);
if (ret)
return ret;
info->oob_buff = info->data_buff + mtd->writesize;
if ((mtd->size >> chip->page_shift) > 65536)
host->row_addr_cycles = 3;
else
@ -1187,15 +1202,18 @@ static int alloc_nand_resource(struct platform_device *pdev)
}
info->mmio_phys = r->start;
ret = pxa3xx_nand_init_buff(info);
if (ret)
/* Allocate a buffer to allow flash detection */
info->buf_size = INIT_BUFFER_SIZE;
info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL) {
ret = -ENOMEM;
goto fail_disable_clk;
}
/* initialize all interrupts to be disabled */
disable_int(info, NDSR_MASK);
ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED,
pdev->name, info);
ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ\n");
goto fail_free_buf;
@ -1207,7 +1225,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
fail_free_buf:
free_irq(irq, info);
pxa3xx_nand_free_buff(info);
kfree(info->data_buff);
fail_disable_clk:
clk_disable_unprepare(info->clk);
return ret;
@ -1412,7 +1430,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
static struct platform_driver pxa3xx_nand_driver = {
.driver = {
.name = "pxa3xx-nand",
.of_match_table = of_match_ptr(pxa3xx_nand_dt_ids),
.of_match_table = pxa3xx_nand_dt_ids,
},
.probe = pxa3xx_nand_probe,
.remove = pxa3xx_nand_remove,

View File

@ -150,17 +150,13 @@ static int socrates_nand_probe(struct platform_device *ofdev)
struct mtd_part_parser_data ppdata;
/* Allocate memory for the device structure (and zero it) */
host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
if (!host) {
printk(KERN_ERR
"socrates_nand: failed to allocate device structure.\n");
host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL);
if (!host)
return -ENOMEM;
}
host->io_base = of_iomap(ofdev->dev.of_node, 0);
if (host->io_base == NULL) {
printk(KERN_ERR "socrates_nand: ioremap failed\n");
kfree(host);
dev_err(&ofdev->dev, "ioremap failed\n");
return -EIO;
}
@ -212,9 +208,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
nand_release(mtd);
out:
dev_set_drvdata(&ofdev->dev, NULL);
iounmap(host->io_base);
kfree(host);
return res;
}
@ -228,9 +222,7 @@ static int socrates_nand_remove(struct platform_device *ofdev)
nand_release(mtd);
dev_set_drvdata(&ofdev->dev, NULL);
iounmap(host->io_base);
kfree(host);
return 0;
}

View File

@ -428,8 +428,7 @@ static int tmio_probe(struct platform_device *dev)
/* 15 us command delay time */
nand_chip->chip_delay = 15;
retval = request_irq(irq, &tmio_irq,
IRQF_DISABLED, dev_name(&dev->dev), tmio);
retval = request_irq(irq, &tmio_irq, 0, dev_name(&dev->dev), tmio);
if (retval) {
dev_err(&dev->dev, "request_irq error %d\n", retval);
goto err_irq;

View File

@ -50,7 +50,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct NFTLrecord *nftl;
unsigned long temp;
if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))

View File

@ -573,28 +573,6 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
static struct platform_driver omap2_onenand_driver;
static int __adjust_timing(struct device *dev, void *data)
{
int ret = 0;
struct omap2_onenand *c;
c = dev_get_drvdata(dev);
BUG_ON(c->setup == NULL);
/* DMA is not in use so this is all that is needed */
/* Revisit for OMAP3! */
ret = c->setup(c->onenand.base, &c->freq);
return ret;
}
int omap2_onenand_rephase(void)
{
return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
NULL, __adjust_timing);
}
static void omap2_onenand_shutdown(struct platform_device *pdev)
{
struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);

View File

@ -2556,10 +2556,6 @@ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
int ret;
/* Check for invalid offset */
if (ofs > mtd->size)
return -EINVAL;
onenand_get_device(mtd, FL_READING);
ret = onenand_block_isbad_nolock(mtd, ofs, 0);
onenand_release_device(mtd);
@ -3529,7 +3525,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
unsigned die, bdry;
int ret, syscfg, locked;
int syscfg, locked;
/* Disable ECC */
syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
@ -3540,7 +3536,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->wait(mtd, FL_SYNCING);
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
ret = this->wait(mtd, FL_READING);
this->wait(mtd, FL_READING);
bdry = this->read_word(this->base + ONENAND_DATARAM);
if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
@ -3550,7 +3546,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
this->command(mtd, ONENAND_CMD_RESET, 0, 0);
ret = this->wait(mtd, FL_RESETING);
this->wait(mtd, FL_RESETING);
printk(KERN_INFO "Die %d boundary: %d%s\n", die,
this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@ -3734,7 +3730,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
/* Check is boundary is locked */
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
ret = this->wait(mtd, FL_READING);
this->wait(mtd, FL_READING);
thisboundary = this->read_word(this->base + ONENAND_DATARAM);
if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
@ -3835,7 +3831,7 @@ static int onenand_chip_probe(struct mtd_info *mtd)
static int onenand_probe(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
int maf_id, dev_id, ver_id;
int dev_id, ver_id;
int density;
int ret;
@ -3843,8 +3839,7 @@ static int onenand_probe(struct mtd_info *mtd)
if (ret)
return ret;
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
/* Device and version IDs from Register */
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);

View File

@ -290,7 +290,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
int cis_sector;
/* Check for small page NAND flash */
if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE ||
if (!mtd_type_is_nand(mtd) || mtd->oobsize != OOB_SIZE ||
mtd->size > UINT_MAX)
return;

View File

@ -349,7 +349,7 @@ static int __init mtd_nandbiterrs_init(void)
goto exit_mtddev;
}
if (mtd->type != MTD_NANDFLASH) {
if (!mtd_type_is_nand(mtd)) {
pr_info("this test requires NAND flash\n");
err = -ENODEV;
goto exit_nand;

View File

@ -289,7 +289,7 @@ static int __init mtd_oobtest_init(void)
return err;
}
if (mtd->type != MTD_NANDFLASH) {
if (!mtd_type_is_nand(mtd)) {
pr_info("this test requires NAND flash\n");
goto out;
}

View File

@ -353,7 +353,7 @@ static int __init mtd_pagetest_init(void)
return err;
}
if (mtd->type != MTD_NANDFLASH) {
if (!mtd_type_is_nand(mtd)) {
pr_info("this test requires NAND flash\n");
goto out;
}

View File

@ -299,7 +299,7 @@ static int __init mtd_subpagetest_init(void)
return err;
}
if (mtd->type != MTD_NANDFLASH) {
if (!mtd_type_is_nand(mtd)) {
pr_info("this test requires NAND flash\n");
goto out;
}

View File

@ -41,6 +41,7 @@
#include <linux/kthread.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/major.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */

View File

@ -515,6 +515,10 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
c = JFFS2_SB_INFO(sb);
/* Do not support the MLC nand */
if (c->mtd->type == MTD_MLCNANDFLASH)
return -EINVAL;
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
if (c->mtd->type == MTD_NANDFLASH) {
pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in\n");

View File

@ -91,8 +91,6 @@ struct nand_bbt_descr {
* with NAND_BBT_CREATE.
*/
#define NAND_BBT_CREATE_EMPTY 0x00000400
/* Search good / bad pattern through all pages of a block */
#define NAND_BBT_SCANALLPAGES 0x00000800
/* Write bbt if neccecary */
#define NAND_BBT_WRITE 0x00002000
/* Read and write back block contents when writing bbt */

View File

@ -365,7 +365,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig
bitpos = (map_bankwidth(map)-1-i)*8;
#endif
orig.x[0] &= ~(0xff << bitpos);
orig.x[0] |= buf[i-start] << bitpos;
orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
}
}
return orig;
@ -384,7 +384,7 @@ static inline map_word map_word_ff(struct map_info *map)
if (map_bankwidth(map) < MAP_FF_LIMIT) {
int bw = 8 * map_bankwidth(map);
r.x[0] = (1 << bw) - 1;
r.x[0] = (1UL << bw) - 1;
} else {
for (i=0; i<map_words(map); i++)
r.x[i] = ~0UL;

View File

@ -29,9 +29,6 @@
#include <asm/div64.h>
#define MTD_CHAR_MAJOR 90
#define MTD_BLOCK_MAJOR 31
#define MTD_ERASE_PENDING 0x01
#define MTD_ERASING 0x02
#define MTD_ERASE_SUSPEND 0x04
@ -354,6 +351,11 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
return mtd->_read_oob && mtd->_write_oob;
}
static inline int mtd_type_is_nand(const struct mtd_info *mtd)
{
return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
}
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
{
return !!mtd->_block_isbad;

View File

@ -198,6 +198,7 @@ typedef enum {
/* Cell info constants */
#define NAND_CI_CHIPNR_MSK 0x03
#define NAND_CI_CELLTYPE_MSK 0x0C
#define NAND_CI_CELLTYPE_SHIFT 2
/* Keep gcc happy */
struct nand_chip;
@ -477,7 +478,7 @@ struct nand_buffers {
* @badblockbits: [INTERN] minimum number of set bits in a good block's
* bad block marker position; i.e., BBM == 11110111b is
* not bad when badblockbits == 7
* @cellinfo: [INTERN] MLC/multichip data from chip ident
* @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC.
* @ecc_strength_ds: [INTERN] ECC correctability from the datasheet.
* Minimum amount of bit errors per @ecc_step_ds guaranteed
* to be correctable. If unknown, set to zero.
@ -498,7 +499,6 @@ struct nand_buffers {
* supported, 0 otherwise.
* @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
* @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
* @ecclayout: [REPLACEABLE] the default ECC placement scheme
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
* lookup.
@ -559,7 +559,7 @@ struct nand_chip {
int pagebuf;
unsigned int pagebuf_bitflips;
int subpagesize;
uint8_t cellinfo;
uint8_t bits_per_cell;
uint16_t ecc_strength_ds;
uint16_t ecc_step_ds;
int badblockpos;
@ -572,7 +572,6 @@ struct nand_chip {
uint8_t *oob_poi;
struct nand_hw_control *controller;
struct nand_ecclayout *ecclayout;
struct nand_ecc_ctrl ecc;
struct nand_buffers *buffers;
@ -797,4 +796,13 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
return le16_to_cpu(chip->onfi_params.src_sync_timing_mode);
}
/*
* Check if it is a SLC nand.
* The !nand_is_slc() can be used to check the MLC/TLC nand chips.
* We do not distinguish the MLC and TLC now.
*/
static inline bool nand_is_slc(struct nand_chip *chip)
{
return chip->bits_per_cell == 1;
}
#endif /* __LINUX_MTD_NAND_H */

View File

@ -10,10 +10,29 @@
#define __LINUX_OF_NET_H
#ifdef CONFIG_OF_MTD
#include <linux/of.h>
int of_get_nand_ecc_mode(struct device_node *np);
int of_get_nand_bus_width(struct device_node *np);
bool of_get_nand_on_flash_bbt(struct device_node *np);
#endif
#else /* CONFIG_OF_MTD */
static inline int of_get_nand_ecc_mode(struct device_node *np)
{
return -ENOSYS;
}
static inline int of_get_nand_bus_width(struct device_node *np)
{
return -ENOSYS;
}
static inline bool of_get_nand_on_flash_bbt(struct device_node *np)
{
return false;
}
#endif /* CONFIG_OF_MTD */
#endif /* __LINUX_OF_MTD_H */

View File

@ -23,13 +23,16 @@ enum nand_io {
};
enum omap_ecc {
/* 1-bit ecc: stored at end of spare area */
OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
/* 1-bit ecc: stored at beginning of spare area as romcode */
OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
/* 1-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_HAM1_CODE_HW = 0,
/* 4-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
/* 4-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH4_CODE_HW,
/* 8-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
/* 8-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH8_CODE_HW,
};
struct gpmc_nand_regs {
@ -63,5 +66,6 @@ struct omap_nand_platform_data {
/* for passing the partitions */
struct device_node *of_node;
struct device_node *elm_of_node;
};
#endif

View File

@ -54,6 +54,7 @@
#define ACSI_MAJOR 28
#define AZTECH_CDROM_MAJOR 29
#define FB_MAJOR 29 /* /dev/fb* framebuffers */
#define MTD_BLOCK_MAJOR 31
#define CM206_CDROM_MAJOR 32
#define IDE2_MAJOR 33
#define IDE3_MAJOR 34
@ -105,6 +106,7 @@
#define IDE6_MAJOR 88
#define IDE7_MAJOR 89
#define IDE8_MAJOR 90
#define MTD_CHAR_MAJOR 90
#define IDE9_MAJOR 91
#define DASD_MAJOR 94

View File

@ -94,10 +94,10 @@ struct mtd_write_req {
#define MTD_RAM 1
#define MTD_ROM 2
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4
#define MTD_NANDFLASH 4 /* SLC NAND */
#define MTD_DATAFLASH 6
#define MTD_UBIVOLUME 7
#define MTD_MLCNANDFLASH 8
#define MTD_MLCNANDFLASH 8 /* MLC NAND (including TLC) */
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
@ -275,4 +275,9 @@ enum mtd_file_modes {
MTD_FILE_MODE_RAW,
};
static inline int mtd_type_is_nand_user(const struct mtd_info_user *mtd)
{
return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
}
#endif /* __MTD_ABI_H__ */