Skip to content

Commit

Permalink
Merge tag 'for-linus-20131112' of git://git.infradead.org/linux-mtd
Browse files Browse the repository at this point in the history
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
  ...
  • Loading branch information
Linus Torvalds committed Nov 14, 2013
2 parents 0d522ee + 885d71e commit 82cb6ac
Show file tree
Hide file tree
Showing 65 changed files with 925 additions and 984 deletions.
2 changes: 1 addition & 1 deletion Documentation/ABI/testing/sysfs-class-mtd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions Documentation/DocBook/mtdnand.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
16 changes: 10 additions & 6 deletions Documentation/devicetree/bindings/mtd/gpmc-nand.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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):

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-omap2/board-flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
48 changes: 34 additions & 14 deletions arch/arm/mach-omap2/gpmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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])) {
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/fsl_ifc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
23 changes: 23 additions & 0 deletions drivers/mtd/bcm47xxpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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. */
Expand Down
7 changes: 0 additions & 7 deletions drivers/mtd/devices/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/mtd/devices/block2mtd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/devices/docg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2097,7 +2097,7 @@ static int __init docg3_probe(struct platform_device *pdev)
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]);
Expand Down
82 changes: 33 additions & 49 deletions drivers/mtd/devices/m25p80.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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) },
Expand All @@ -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) },
Expand All @@ -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).
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

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


Expand Down
Loading

0 comments on commit 82cb6ac

Please sign in to comment.