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

Pull MTD updates from Brian Norris:
 - A few SPI NOR ID definitions
 - Kill the NAND "max pagesize" restriction
 - Fix some x16 bus-width NAND support
 - Add NAND JEDEC parameter page support
 - DT bindings for NAND ECC
 - GPMI NAND updates (subpage reads)
 - More OMAP NAND refactoring
 - New STMicro SPI NOR driver (now in 40 patches!)
 - A few other random bugfixes

* tag 'for-linus-20140405' of git://git.infradead.org/linux-mtd: (120 commits)
  Fix index regression in nand_read_subpage
  mtd: diskonchip: mem resource name is not optional
  mtd: nand: fix mention to CONFIG_MTD_NAND_ECC_BCH
  mtd: nand: fix GET/SET_FEATURES address on 16-bit devices
  mtd: omap2: Use devm_ioremap_resource()
  mtd: denali_dt: Use devm_ioremap_resource()
  mtd: devices: elm: update DRIVER_NAME as "omap-elm"
  mtd: devices: elm: configure parallel channels based on ecc_steps
  mtd: devices: elm: clean elm_load_syndrome
  mtd: devices: elm: check for hardware engine's design constraints
  mtd: st_spi_fsm: Succinctly reorganise .remove()
  mtd: st_spi_fsm: Allow loop to run at least once before giving up CPU
  mtd: st_spi_fsm: Correct vendor name spelling issue - missing "M"
  mtd: st_spi_fsm: Avoid duplicating MTD core code
  mtd: st_spi_fsm: Remove useless consts from function arguments
  mtd: st_spi_fsm: Convert ST SPI FSM (NOR) Flash driver to new DT partitions
  mtd: st_spi_fsm: Move runtime configurable msg sequences into device's struct
  mtd: st_spi_fsm: Supply the W25Qxxx chip specific configuration call-back
  mtd: st_spi_fsm: Supply the S25FLxxx chip specific configuration call-back
  mtd: st_spi_fsm: Supply the MX25xxx chip specific configuration call-back
  ...
This commit is contained in:
Linus Torvalds
2014-04-07 10:17:30 -07:00
83 changed files with 3183 additions and 649 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ config MTD_BCM63XX_PARTS
config MTD_BCM47XX_PARTS
tristate "BCM47XX partitioning support"
depends on BCM47XX
depends on BCM47XX || ARCH_BCM_5301X
help
This provides partitions parser for devices based on BCM47xx
boards.
+8 -3
View File
@@ -14,7 +14,6 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <bcm47xx_nvram.h>
/* 10 parts were found on sflash on Netgear WNDR4500 */
#define BCM47XXPART_MAX_PARTS 12
@@ -30,6 +29,7 @@
#define BOARD_DATA_MAGIC2 0xBD0D0BBD
#define CFE_MAGIC 0x43464531 /* 1EFC */
#define FACTORY_MAGIC 0x59544346 /* FCTY */
#define NVRAM_HEADER 0x48534C46 /* FLSH */
#define POT_MAGIC1 0x54544f50 /* POTT */
#define POT_MAGIC2 0x504f /* OP */
#define ML_MAGIC1 0x39685a42
@@ -91,7 +91,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
if (offset >= 0x2000000)
break;
if (curr_part > BCM47XXPART_MAX_PARTS) {
if (curr_part >= BCM47XXPART_MAX_PARTS) {
pr_warn("Reached maximum number of partitions, scanning stopped!\n");
break;
}
@@ -147,6 +147,11 @@ static int bcm47xxpart_parse(struct mtd_info *master,
/* TRX */
if (buf[0x000 / 4] == TRX_MAGIC) {
if (BCM47XXPART_MAX_PARTS - curr_part < 4) {
pr_warn("Not enough partitions left to register trx, scanning stopped!\n");
break;
}
trx = (struct trx_header *)buf;
trx_part = curr_part;
@@ -212,7 +217,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
/* Look for NVRAM at the end of the last block. */
for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) {
if (curr_part > BCM47XXPART_MAX_PARTS) {
if (curr_part >= BCM47XXPART_MAX_PARTS) {
pr_warn("Reached maximum number of partitions, scanning stopped!\n");
break;
}
+15 -25
View File
@@ -21,7 +21,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -69,10 +68,10 @@ static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, s
static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_intelext_write_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_intelext_lock_user_prot_reg (struct mtd_info *, loff_t, size_t);
static int cfi_intelext_get_fact_prot_info (struct mtd_info *,
struct otp_info *, size_t);
static int cfi_intelext_get_user_prot_info (struct mtd_info *,
struct otp_info *, size_t);
static int cfi_intelext_get_fact_prot_info(struct mtd_info *, size_t,
size_t *, struct otp_info *);
static int cfi_intelext_get_user_prot_info(struct mtd_info *, size_t,
size_t *, struct otp_info *);
#endif
static int cfi_intelext_suspend (struct mtd_info *);
static void cfi_intelext_resume (struct mtd_info *);
@@ -435,10 +434,8 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
int i;
mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
printk(KERN_ERR "Failed to allocate memory for MTD device\n");
if (!mtd)
return NULL;
}
mtd->priv = map;
mtd->type = MTD_NORFLASH;
@@ -564,10 +561,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
* mtd->numeraseregions, GFP_KERNEL);
if (!mtd->eraseregions) {
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
if (!mtd->eraseregions)
goto setup_err;
}
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
unsigned long ernum, ersize;
@@ -2399,24 +2394,19 @@ static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd,
NULL, do_otp_lock, 1);
}
static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd,
struct otp_info *buf, size_t len)
{
size_t retlen;
int ret;
static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, size_t len,
size_t *retlen, struct otp_info *buf)
ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 0);
return ret ? : retlen;
{
return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
NULL, 0);
}
static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd,
struct otp_info *buf, size_t len)
static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd, size_t len,
size_t *retlen, struct otp_info *buf)
{
size_t retlen;
int ret;
ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 1);
return ret ? : retlen;
return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
NULL, 1);
}
#endif
+2 -7
View File
@@ -24,7 +24,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -507,10 +506,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
int i;
mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
if (!mtd)
return NULL;
}
mtd->priv = map;
mtd->type = MTD_NORFLASH;
@@ -661,10 +658,8 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
* mtd->numeraseregions, GFP_KERNEL);
if (!mtd->eraseregions) {
printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
if (!mtd->eraseregions)
goto setup_err;
}
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
unsigned long ernum, ersize;
-3
View File
@@ -22,7 +22,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -176,7 +175,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
if (!mtd) {
printk(KERN_ERR "Failed to allocate memory for MTD device\n");
kfree(cfi->cmdset_priv);
return NULL;
}
@@ -189,7 +187,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
* mtd->numeraseregions, GFP_KERNEL);
if (!mtd->eraseregions) {
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
kfree(cfi->cmdset_priv);
kfree(mtd);
return NULL;
+1 -3
View File
@@ -168,10 +168,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
return 0;
cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
if (!cfi->cfiq) {
printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
if (!cfi->cfiq)
return 0;
}
memset(cfi->cfiq,0,sizeof(struct cfi_ident));
+1 -3
View File
@@ -116,10 +116,8 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);
extp = kmalloc(size, GFP_KERNEL);
if (!extp) {
printk(KERN_ERR "Failed to allocate memory\n");
if (!extp)
goto out;
}
#ifdef CONFIG_MTD_XIP
local_irq_disable();
-2
View File
@@ -114,7 +114,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG);
chip_map = kzalloc(mapsize, GFP_KERNEL);
if (!chip_map) {
printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
kfree(cfi.cfiq);
return NULL;
}
@@ -139,7 +138,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
if (!retcfi) {
printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
kfree(cfi.cfiq);
kfree(chip_map);
return NULL;
+8
View File
@@ -210,6 +210,14 @@ config MTD_DOCG3
M-Systems and now Sandisk. The support is very experimental,
and doesn't give access to any write operations.
config MTD_ST_SPI_FSM
tristate "ST Microelectronics SPI FSM Serial Flash Controller"
depends on ARM || SH
help
This provides an MTD device driver for the ST Microelectronics
SPI Fast Sequence Mode (FSM) Serial Flash Controller and support
for a subset of connected Serial Flash devices.
if MTD_DOCG3
config BCH_CONST_M
default 14
+1
View File
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH) += elm.o
obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o
obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o
obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o
CFLAGS_docg3.o += -I$(src)
+13 -6
View File
@@ -209,7 +209,6 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
}
/* FIXME: ensure that mtd->size % erase_size == 0 */
static struct block2mtd_dev *add_device(char *devname, int erase_size)
{
const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
@@ -240,13 +239,18 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
if (IS_ERR(bdev)) {
pr_err("error: cannot open device %s\n", devname);
goto devinit_err;
goto err_free_block2mtd;
}
dev->blkdev = bdev;
if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
pr_err("attempting to use an MTD device as a block device\n");
goto devinit_err;
goto err_free_block2mtd;
}
if ((long)dev->blkdev->bd_inode->i_size % erase_size) {
pr_err("erasesize must be a divisor of device size\n");
goto err_free_block2mtd;
}
mutex_init(&dev->write_mutex);
@@ -255,7 +259,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
/* make the name contain the block device in */
name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
if (!name)
goto devinit_err;
goto err_destroy_mutex;
dev->mtd.name = name;
@@ -274,7 +278,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
if (mtd_device_register(&dev->mtd, NULL, 0)) {
/* Device didn't get added, so free the entry */
goto devinit_err;
goto err_destroy_mutex;
}
list_add(&dev->list, &blkmtd_device_list);
pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
@@ -283,7 +287,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
dev->mtd.erasesize >> 10, dev->mtd.erasesize);
return dev;
devinit_err:
err_destroy_mutex:
mutex_destroy(&dev->write_mutex);
err_free_block2mtd:
block2mtd_free_device(dev);
return NULL;
}
@@ -448,6 +454,7 @@ static void block2mtd_exit(void)
struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
block2mtd_sync(&dev->mtd);
mtd_device_unregister(&dev->mtd);
mutex_destroy(&dev->write_mutex);
pr_info("mtd%d: [%s] removed\n",
dev->mtd.index,
dev->mtd.name + strlen("block2mtd: "));
+33 -16
View File
@@ -15,6 +15,8 @@
*
*/
#define DRIVER_NAME "omap-elm"
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -84,6 +86,8 @@ struct elm_info {
struct list_head list;
enum bch_ecc bch_type;
struct elm_registers elm_regs;
int ecc_steps;
int ecc_syndrome_size;
};
static LIST_HEAD(elm_devices);
@@ -103,7 +107,8 @@ static u32 elm_read_reg(struct elm_info *info, int offset)
* @dev: ELM device
* @bch_type: Type of BCH ecc
*/
int elm_config(struct device *dev, enum bch_ecc bch_type)
int elm_config(struct device *dev, enum bch_ecc bch_type,
int ecc_steps, int ecc_step_size, int ecc_syndrome_size)
{
u32 reg_val;
struct elm_info *info = dev_get_drvdata(dev);
@@ -112,10 +117,22 @@ int elm_config(struct device *dev, enum bch_ecc bch_type)
dev_err(dev, "Unable to configure elm - device not probed?\n");
return -ENODEV;
}
/* ELM cannot detect ECC errors for chunks > 1KB */
if (ecc_step_size > ((ELM_ECC_SIZE + 1) / 2)) {
dev_err(dev, "unsupported config ecc-size=%d\n", ecc_step_size);
return -EINVAL;
}
/* ELM support 8 error syndrome process */
if (ecc_steps > ERROR_VECTOR_MAX) {
dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps);
return -EINVAL;
}
reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val);
info->bch_type = bch_type;
info->bch_type = bch_type;
info->ecc_steps = ecc_steps;
info->ecc_syndrome_size = ecc_syndrome_size;
return 0;
}
@@ -157,17 +174,15 @@ static void elm_load_syndrome(struct elm_info *info,
int i, offset;
u32 val;
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
for (i = 0; i < info->ecc_steps; i++) {
/* Check error reported */
if (err_vec[i].error_reported) {
elm_configure_page_mode(info, i, true);
offset = ELM_SYNDROME_FRAGMENT_0 +
SYNDROME_FRAGMENT_REG_SIZE * i;
/* BCH8 */
if (info->bch_type) {
switch (info->bch_type) {
case BCH8_ECC:
/* syndrome fragment 0 = ecc[9-12B] */
val = cpu_to_be32(*(u32 *) &ecc[9]);
elm_write_reg(info, offset, val);
@@ -186,7 +201,8 @@ static void elm_load_syndrome(struct elm_info *info,
offset += 4;
val = ecc[0];
elm_write_reg(info, offset, val);
} else {
break;
case BCH4_ECC:
/* syndrome fragment 0 = ecc[20-52b] bits */
val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) |
((ecc[2] & 0xf) << 28);
@@ -196,11 +212,14 @@ static void elm_load_syndrome(struct elm_info *info,
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
elm_write_reg(info, offset, val);
break;
default:
pr_err("invalid config bch_type\n");
}
}
/* Update ecc pointer with ecc byte size */
ecc += info->bch_type ? BCH8_SIZE : BCH4_SIZE;
ecc += info->ecc_syndrome_size;
}
}
@@ -223,7 +242,7 @@ static void elm_start_processing(struct elm_info *info,
* Set syndrome vector valid, so that ELM module
* will process it for vectors error is reported
*/
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
for (i = 0; i < info->ecc_steps; i++) {
if (err_vec[i].error_reported) {
offset = ELM_SYNDROME_FRAGMENT_6 +
SYNDROME_FRAGMENT_REG_SIZE * i;
@@ -252,7 +271,7 @@ static void elm_error_correction(struct elm_info *info,
int offset;
u32 reg_val;
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
for (i = 0; i < info->ecc_steps; i++) {
/* Check error reported */
if (err_vec[i].error_reported) {
@@ -354,10 +373,8 @@ static int elm_probe(struct platform_device *pdev)
struct elm_info *info;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) {
dev_err(&pdev->dev, "failed to allocate memory\n");
if (!info)
return -ENOMEM;
}
info->dev = &pdev->dev;
@@ -380,7 +397,7 @@ static int elm_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
if (pm_runtime_get_sync(&pdev->dev)) {
if (pm_runtime_get_sync(&pdev->dev) < 0) {
ret = -EINVAL;
pm_runtime_disable(&pdev->dev);
dev_err(&pdev->dev, "can't enable clock\n");
@@ -505,7 +522,7 @@ MODULE_DEVICE_TABLE(of, elm_of_match);
static struct platform_driver elm_driver = {
.driver = {
.name = "elm",
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(elm_of_match),
.pm = &elm_pm_ops,
+25 -10
View File
@@ -15,7 +15,6 @@
*
*/
#include <linux/init.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -41,7 +40,8 @@
#define OPCODE_WRSR 0x01 /* Write status register 1 byte */
#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
#define OPCODE_QUAD_READ 0x6b /* Read data bytes */
#define OPCODE_DUAL_READ 0x3b /* Read data bytes (Dual SPI) */
#define OPCODE_QUAD_READ 0x6b /* Read data bytes (Quad SPI) */
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
@@ -54,7 +54,8 @@
/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
#define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */
#define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes */
#define OPCODE_DUAL_READ_4B 0x3c /* Read data bytes (Dual SPI) */
#define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes (Quad SPI) */
#define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */
@@ -95,6 +96,7 @@
enum read_type {
M25P80_NORMAL = 0,
M25P80_FAST,
M25P80_DUAL,
M25P80_QUAD,
};
@@ -479,6 +481,7 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash)
{
switch (flash->flash_read) {
case M25P80_FAST:
case M25P80_DUAL:
case M25P80_QUAD:
return 1;
case M25P80_NORMAL:
@@ -492,6 +495,8 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash)
static inline unsigned int m25p80_rx_nbits(const struct m25p *flash)
{
switch (flash->flash_read) {
case M25P80_DUAL:
return 2;
case M25P80_QUAD:
return 4;
default:
@@ -855,7 +860,8 @@ struct flash_info {
#define SST_WRITE 0x04 /* use SST byte programming */
#define M25P_NO_FR 0x08 /* Can't do fastread */
#define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */
#define M25P80_QUAD_READ 0x20 /* Flash supports Quad Read */
#define M25P80_DUAL_READ 0x20 /* Flash supports Dual Read */
#define M25P80_QUAD_READ 0x40 /* Flash supports Quad Read */
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -934,6 +940,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) },
{ "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, M25P80_QUAD_READ) },
/* Micron */
{ "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
@@ -953,8 +960,8 @@ static const struct spi_device_id m25p_ids[] = {
{ "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) },
{ "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_QUAD_READ) },
{ "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_QUAD_READ) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_DUAL_READ | M25P80_QUAD_READ) },
{ "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_DUAL_READ | M25P80_QUAD_READ) },
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
@@ -965,6 +972,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
{ "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
{ "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
{ "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) },
{ "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
@@ -1072,9 +1080,8 @@ static const struct spi_device_id *jedec_probe(struct spi_device *spi)
for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
info = (void *)m25p_ids[tmp].driver_data;
if (info->jedec_id == jedec) {
if (info->ext_id != 0 && info->ext_id != ext_jedec)
continue;
return &m25p_ids[tmp];
if (info->ext_id == 0 || info->ext_id == ext_jedec)
return &m25p_ids[tmp];
}
}
dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
@@ -1226,7 +1233,7 @@ static int m25p_probe(struct spi_device *spi)
if (info->flags & M25P_NO_FR)
flash->flash_read = M25P80_NORMAL;
/* Quad-read mode takes precedence over fast/normal */
/* Quad/Dual-read mode takes precedence over fast/normal */
if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) {
ret = set_quad_mode(flash, info->jedec_id);
if (ret) {
@@ -1234,6 +1241,8 @@ static int m25p_probe(struct spi_device *spi)
return ret;
}
flash->flash_read = M25P80_QUAD;
} else if (spi->mode & SPI_RX_DUAL && info->flags & M25P80_DUAL_READ) {
flash->flash_read = M25P80_DUAL;
}
/* Default commands */
@@ -1241,6 +1250,9 @@ static int m25p_probe(struct spi_device *spi)
case M25P80_QUAD:
flash->read_opcode = OPCODE_QUAD_READ;
break;
case M25P80_DUAL:
flash->read_opcode = OPCODE_DUAL_READ;
break;
case M25P80_FAST:
flash->read_opcode = OPCODE_FAST_READ;
break;
@@ -1265,6 +1277,9 @@ static int m25p_probe(struct spi_device *spi)
case M25P80_QUAD:
flash->read_opcode = OPCODE_QUAD_READ_4B;
break;
case M25P80_DUAL:
flash->read_opcode = OPCODE_DUAL_READ_4B;
break;
case M25P80_FAST:
flash->read_opcode = OPCODE_FAST_READ_4B;
break;
+14 -10
View File
@@ -10,7 +10,6 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -440,8 +439,8 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
#ifdef CONFIG_MTD_DATAFLASH_OTP
static int dataflash_get_otp_info(struct mtd_info *mtd,
struct otp_info *info, size_t len)
static int dataflash_get_otp_info(struct mtd_info *mtd, size_t len,
size_t *retlen, struct otp_info *info)
{
/* Report both blocks as identical: bytes 0..64, locked.
* Unless the user block changed from all-ones, we can't
@@ -450,7 +449,8 @@ static int dataflash_get_otp_info(struct mtd_info *mtd,
info->start = 0;
info->length = 64;
info->locked = 1;
return sizeof(*info);
*retlen = sizeof(*info);
return 0;
}
static ssize_t otp_read(struct spi_device *spi, unsigned base,
@@ -542,14 +542,18 @@ static int dataflash_write_user_otp(struct mtd_info *mtd,
struct dataflash *priv = mtd->priv;
int status;
if (len > 64)
return -EINVAL;
if (from >= 64) {
/*
* Attempting to write beyond the end of OTP memory,
* no data can be written.
*/
*retlen = 0;
return 0;
}
/* Strictly speaking, we *could* truncate the write ... but
* let's not do that for the only write that's ever possible.
*/
/* Truncate the write to fit into OTP memory. */
if ((from + len) > 64)
return -EINVAL;
len = 64 - from;
/* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes
* IN: ignore all
+35 -8
View File
@@ -205,6 +205,8 @@ static inline void kill_final_newline(char *str)
return 1; \
} while (0)
#ifndef MODULE
static int phram_init_called;
/*
* This shall contain the module parameter if any. It is of the form:
* - phram=<device>,<address>,<size> for module case
@@ -213,9 +215,10 @@ static inline void kill_final_newline(char *str)
* size.
* Example: phram.phram=rootfs,0xa0000000,512Mi
*/
static __initdata char phram_paramline[64 + 20 + 20];
static char phram_paramline[64 + 20 + 20];
#endif
static int __init phram_setup(const char *val)
static int phram_setup(const char *val)
{
char buf[64 + 20 + 20], *str = buf;
char *token[3];
@@ -264,17 +267,36 @@ static int __init phram_setup(const char *val)
return ret;
}
static int __init phram_param_call(const char *val, struct kernel_param *kp)
static int phram_param_call(const char *val, struct kernel_param *kp)
{
#ifdef MODULE
return phram_setup(val);
#else
/*
* This function is always called before 'init_phram()', whether
* built-in or module.
* If more parameters are later passed in via
* /sys/module/phram/parameters/phram
* and init_phram() has already been called,
* we can parse the argument now.
*/
if (phram_init_called)
return phram_setup(val);
/*
* During early boot stage, we only save the parameters
* here. We must parse them later: if the param passed
* from kernel boot command line, phram_param_call() is
* called so early that it is not possible to resolve
* the device (even kmalloc() fails). Defer that work to
* phram_setup().
*/
if (strlen(val) >= sizeof(phram_paramline))
return -ENOSPC;
strcpy(phram_paramline, val);
return 0;
#endif
}
module_param_call(phram, phram_param_call, NULL, NULL, 000);
@@ -283,10 +305,15 @@ MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"
static int __init init_phram(void)
{
if (phram_paramline[0])
return phram_setup(phram_paramline);
int ret = 0;
return 0;
#ifndef MODULE
if (phram_paramline[0])
ret = phram_setup(phram_paramline);
phram_init_called = 1;
#endif
return ret;
}
static void __exit cleanup_phram(void)
+1 -6
View File
@@ -725,16 +725,11 @@ static int __init init_pmc551(void)
}
mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
if (!mtd) {
printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
"device.\n");
if (!mtd)
break;
}
priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
if (!priv) {
printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
"device.\n");
kfree(mtd);
break;
}
+81
View File
@@ -0,0 +1,81 @@
/*
* Generic/SFDP Flash Commands and Device Capabilities
*
* Copyright (C) 2013 Lee Jones <lee.jones@lianro.org>
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef _MTD_SERIAL_FLASH_CMDS_H
#define _MTD_SERIAL_FLASH_CMDS_H
/* Generic Flash Commands/OPCODEs */
#define FLASH_CMD_WREN 0x06
#define FLASH_CMD_WRDI 0x04
#define FLASH_CMD_RDID 0x9f
#define FLASH_CMD_RDSR 0x05
#define FLASH_CMD_RDSR2 0x35
#define FLASH_CMD_WRSR 0x01
#define FLASH_CMD_SE_4K 0x20
#define FLASH_CMD_SE_32K 0x52
#define FLASH_CMD_SE 0xd8
#define FLASH_CMD_CHIPERASE 0xc7
#define FLASH_CMD_WRVCR 0x81
#define FLASH_CMD_RDVCR 0x85
/* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
#define FLASH_CMD_READ 0x03 /* READ */
#define FLASH_CMD_READ_FAST 0x0b /* FAST READ */
#define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */
#define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */
#define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */
#define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */
#define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */
#define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
#define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
#define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */
#define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */
/* READ commands with 32-bit addressing */
#define FLASH_CMD_READ4 0x13
#define FLASH_CMD_READ4_FAST 0x0c
#define FLASH_CMD_READ4_1_1_2 0x3c
#define FLASH_CMD_READ4_1_2_2 0xbc
#define FLASH_CMD_READ4_1_1_4 0x6c
#define FLASH_CMD_READ4_1_4_4 0xec
/* Configuration flags */
#define FLASH_FLAG_SINGLE 0x000000ff
#define FLASH_FLAG_READ_WRITE 0x00000001
#define FLASH_FLAG_READ_FAST 0x00000002
#define FLASH_FLAG_SE_4K 0x00000004
#define FLASH_FLAG_SE_32K 0x00000008
#define FLASH_FLAG_CE 0x00000010
#define FLASH_FLAG_32BIT_ADDR 0x00000020
#define FLASH_FLAG_RESET 0x00000040
#define FLASH_FLAG_DYB_LOCKING 0x00000080
#define FLASH_FLAG_DUAL 0x0000ff00
#define FLASH_FLAG_READ_1_1_2 0x00000100
#define FLASH_FLAG_READ_1_2_2 0x00000200
#define FLASH_FLAG_READ_2_2_2 0x00000400
#define FLASH_FLAG_WRITE_1_1_2 0x00001000
#define FLASH_FLAG_WRITE_1_2_2 0x00002000
#define FLASH_FLAG_WRITE_2_2_2 0x00004000
#define FLASH_FLAG_QUAD 0x00ff0000
#define FLASH_FLAG_READ_1_1_4 0x00010000
#define FLASH_FLAG_READ_1_4_4 0x00020000
#define FLASH_FLAG_READ_4_4_4 0x00040000
#define FLASH_FLAG_WRITE_1_1_4 0x00100000
#define FLASH_FLAG_WRITE_1_4_4 0x00200000
#define FLASH_FLAG_WRITE_4_4_4 0x00400000
#endif /* _MTD_SERIAL_FLASH_CMDS_H */
-2
View File
@@ -913,7 +913,6 @@ static int spear_smi_probe(struct platform_device *pdev)
if (np) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
pr_err("%s: ERROR: no memory", __func__);
ret = -ENOMEM;
goto err;
}
@@ -943,7 +942,6 @@ static int spear_smi_probe(struct platform_device *pdev)
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_ATOMIC);
if (!dev) {
ret = -ENOMEM;
dev_err(&pdev->dev, "mem alloc fail\n");
goto err;
}
-1
View File
@@ -15,7 +15,6 @@
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mutex.h>
File diff suppressed because it is too large Load Diff

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