You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
+1
-1
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user