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

Pull MTD updates from Brian Norris:
 "First cycle with Boris as NAND maintainer! Many (most) bullets stolen
  from him.

  Generic:
   - Migrated NAND LED trigger to be a generic MTD trigger

  NAND:
   - Introduction of the "ECC algorithm" concept, to avoid overloading
     the ECC mode field too much more
   - Replaced the nand_ecclayout infrastructure with something a little
     more flexible (finally!) and future proof
   - Rework of the OMAP GPMC and NAND drivers; the TI folks pulled some
     of this into their own tree as well
   - Prepare the sunxi NAND driver to receive DMA support
   - Handle bitflips in erased pages on GPMI revisions that do not
     support this in hardware.

  SPI NOR:
   - Start using the spi_flash_read() API for SPI drivers that support
     it (i.e., SPI drivers with special memory-mapped flash modes)

  And other small scattered improvments"

* tag 'for-linus-20160523' of git://git.infradead.org/linux-mtd: (155 commits)
  mtd: spi-nor: support GigaDevice gd25lq64c
  mtd: nand_bch: fix spelling of "probably"
  mtd: brcmnand: respect ECC algorithm set by NAND subsystem
  gpmi-nand: Handle ECC Errors in erased pages
  Documentation: devicetree: deprecate "soft_bch" nand-ecc-mode value
  mtd: nand: add support for "nand-ecc-algo" DT property
  mtd: mtd: drop NAND_ECC_SOFT_BCH enum value
  mtd: drop support for NAND_ECC_SOFT_BCH as "soft_bch" mapping
  mtd: nand: read ECC algorithm from the new field
  mtd: nand: fsmc: validate ECC setup by checking algorithm directly
  mtd: nand: set ECC algorithm to Hamming on fallback
  staging: mt29f_spinand: set ECC algorithm explicitly
  CRIS v32: nand: set ECC algorithm explicitly
  mtd: nand: atmel: set ECC algorithm explicitly
  mtd: nand: davinci: set ECC algorithm explicitly
  mtd: nand: bf5xx: set ECC algorithm explicitly
  mtd: nand: omap2: Fix high memory dma prefetch transfer
  mtd: nand: omap2: Start dma request before enabling prefetch
  mtd: nandsim: add __init attribute
  mtd: nand: move of_get_nand_xxx() helpers into nand_base.c
  ...
This commit is contained in:
Linus Torvalds
2016-05-24 11:00:20 -07:00
89 changed files with 4352 additions and 2922 deletions

View File

@@ -32,6 +32,19 @@ Required properties:
bootloader) are used for the physical address decoding.
As this will change in the future, filling correct
values here is a requirement.
- interrupt-controller: The GPMC driver implements and interrupt controller for
the NAND events "fifoevent" and "termcount" plus the
rising/falling edges on the GPMC_WAIT pins.
The interrupt number mapping is as follows
0 - NAND_fifoevent
1 - NAND_termcount
2 - GPMC_WAIT0 pin edge
3 - GPMC_WAIT1 pin edge, and so on.
- interrupt-cells: Must be set to 2
- gpio-controller: The GPMC driver implements a GPIO controller for the
GPMC WAIT pins that can be used as general purpose inputs.
0 maps to GPMC_WAIT0 pin.
- gpio-cells: Must be set to 2
Timing properties for child nodes. All are optional and default to 0.
@@ -130,6 +143,10 @@ Example for an AM33xx board:
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
/* child nodes go here */
};

View File

@@ -24,6 +24,7 @@ Required properties:
brcm,brcmnand-v5.0
brcm,brcmnand-v6.0
brcm,brcmnand-v6.1
brcm,brcmnand-v6.2
brcm,brcmnand-v7.0
brcm,brcmnand-v7.1
brcm,brcmnand

View File

@@ -13,7 +13,11 @@ Documentation/devicetree/bindings/mtd/nand.txt
Required properties:
- reg: The CS line the peripheral is connected to
- compatible: "ti,omap2-nand"
- reg: range id (CS number), base offset and length of the
NAND I/O space
- interrupt-parent: must point to gpmc node
- interrupts: Two interrupt specifiers, one for fifoevent, one for termcount.
Optional properties:
@@ -44,6 +48,7 @@ Optional properties:
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.
- rb-gpios: GPIO specifier for the ready/busy# pin.
For inline partition table parsing (optional):
@@ -55,20 +60,26 @@ Example for an AM33xx board:
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
reg = <0x50000000 0x1000000>;
reg = <0x50000000 0x36c>;
interrupts = <100>;
gpmc,num-cs = <8>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x08000000 0x2000>; /* CS0: NAND */
ranges = <0 0 0x08000000 0x1000000>; /* CS0 space, 16MB */
elm_id = <&elm>;
interrupt-controller;
#interrupt-cells = <2>;
nand@0,0 {
reg = <0 0 0>; /* CS0, offset 0 */
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, NAND I/O window 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, <1 IRQ_TYPE NONE>;
nand-bus-width = <16>;
ti,nand-ecc-opt = "bch8";
ti,nand-xfer-type = "polled";
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;

View File

@@ -1,8 +1,31 @@
* MTD generic binding
* NAND chip and NAND controller generic binding
NAND controller/NAND chip representation:
The NAND controller should be represented with its own DT node, and all
NAND chips attached to this controller should be defined as children nodes
of the NAND controller. This representation should be enforced even for
simple controllers supporting only one chip.
Mandatory NAND controller properties:
- #address-cells: depends on your controller. Should at least be 1 to
encode the CS line id.
- #size-cells: depends on your controller. Put zero unless you need a
mapping between CS lines and dedicated memory regions
Optional NAND controller properties
- ranges: only needed if you need to define a mapping between CS lines and
memory regions
Optional NAND chip properties:
- nand-ecc-mode : String, operation mode of the NAND ecc mode.
Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
"soft_bch".
Supported values are: "none", "soft", "hw", "hw_syndrome",
"hw_oob_first".
Deprecated values:
"soft_bch": use "soft" and nand-ecc-algo instead
- nand-ecc-algo: string, algorithm of NAND ECC.
Supported values are: "hamming", "bch".
- nand-bus-width : 8 or 16 bus width if not present 8
- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
@@ -19,3 +42,19 @@ errors per {size} bytes".
The interpretation of these parameters is implementation-defined, so not all
implementations must support all possible combinations. However, implementations
are encouraged to further specify the value(s) they support.
Example:
nand-controller {
#address-cells = <1>;
#size-cells = <0>;
/* controller specific properties */
nand@0 {
reg = <0>;
nand-ecc-mode = "soft_bch";
/* controller specific properties */
};
};

View File

@@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
memset(&s, 0, sizeof(struct gpmc_settings));
if (gpmc_nand_data->of_node)
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
else
gpmc_set_legacy(gpmc_nand_data, &s);
gpmc_set_legacy(gpmc_nand_data, &s);
s.device_nand = true;
@@ -121,8 +118,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
if (err < 0)
goto out_free_cs;
gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
err = -EINVAL;

View File

@@ -763,14 +763,49 @@ static struct nand_bbt_descr spitz_nand_bbt = {
.pattern = scan_ff_pattern
};
static struct nand_ecclayout akita_oobinfo = {
.oobfree = { {0x08, 0x09} },
.eccbytes = 24,
.eccpos = {
0x05, 0x01, 0x02, 0x03, 0x06, 0x07, 0x15, 0x11,
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37,
},
static int akita_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section > 12)
return -ERANGE;
switch (section % 3) {
case 0:
oobregion->offset = 5;
oobregion->length = 1;
break;
case 1:
oobregion->offset = 1;
oobregion->length = 3;
break;
case 2:
oobregion->offset = 6;
oobregion->length = 2;
break;
}
oobregion->offset += (section / 3) * 0x10;
return 0;
}
static int akita_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section)
return -ERANGE;
oobregion->offset = 8;
oobregion->length = 9;
return 0;
}
static const struct mtd_ooblayout_ops akita_ooblayout_ops = {
.ecc = akita_ooblayout_ecc,
.free = akita_ooblayout_free,
};
static struct sharpsl_nand_platform_data spitz_nand_pdata = {
@@ -804,11 +839,11 @@ static void __init spitz_nand_init(void)
} else if (machine_is_akita()) {
spitz_nand_partitions[1].size = 58 * 1024 * 1024;
spitz_nand_bbt.len = 1;
spitz_nand_pdata.ecc_layout = &akita_oobinfo;
spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops;
} else if (machine_is_borzoi()) {
spitz_nand_partitions[1].size = 32 * 1024 * 1024;
spitz_nand_bbt.len = 1;
spitz_nand_pdata.ecc_layout = &akita_oobinfo;
spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops;
}
platform_device_register(&spitz_nand_device);

View File

@@ -157,6 +157,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
/* 20 us command delay time */
this->chip_delay = 20;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
/* Enable the following for a flash based bad block table */
/* this->bbt_options = NAND_BBT_USE_FLASH; */

View File

@@ -148,6 +148,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
/* 20 us command delay time */
this->chip_delay = 20;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
/* Enable the following for a flash based bad block table */
/* this->bbt_options = NAND_BBT_USE_FLASH; */

View File

@@ -27,7 +27,7 @@ struct jz_nand_platform_data {
unsigned char banks[JZ_NAND_NUM_BANKS];
void (*ident_callback)(struct platform_device *, struct nand_chip *,
void (*ident_callback)(struct platform_device *, struct mtd_info *,
struct mtd_partition **, int *num_partitions);
};

View File

@@ -48,20 +48,6 @@
#define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26)
/* NAND */
static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
.eccbytes = 36,
.eccpos = {
6, 7, 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
},
.oobfree = {
{ .offset = 2, .length = 4 },
{ .offset = 42, .length = 22 }
},
};
/* Early prototypes of the QI LB60 had only 1GB of NAND.
* In order to support these devices as well the partition and ecc layout is
@@ -84,25 +70,6 @@ static struct mtd_partition qi_lb60_partitions_1gb[] = {
},
};
static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
.eccbytes = 72,
.eccpos = {
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
},
.oobfree = {
{ .offset = 2, .length = 10 },
{ .offset = 84, .length = 44 },
},
};
static struct mtd_partition qi_lb60_partitions_2gb[] = {
{
.name = "NAND BOOT partition",
@@ -121,19 +88,67 @@ static struct mtd_partition qi_lb60_partitions_2gb[] = {
},
};
static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section)
return -ERANGE;
oobregion->length = 36;
oobregion->offset = 6;
if (mtd->oobsize == 128) {
oobregion->length *= 2;
oobregion->offset *= 2;
}
return 0;
}
static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
int eccbytes = 36, eccoff = 6;
if (section > 1)
return -ERANGE;
if (mtd->oobsize == 128) {
eccbytes *= 2;
eccoff *= 2;
}
if (!section) {
oobregion->offset = 2;
oobregion->length = eccoff - 2;
} else {
oobregion->offset = eccoff + eccbytes;
oobregion->length = mtd->oobsize - oobregion->offset;
}
return 0;
}
static const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = {
.ecc = qi_lb60_ooblayout_ecc,
.free = qi_lb60_ooblayout_free,
};
static void qi_lb60_nand_ident(struct platform_device *pdev,
struct nand_chip *chip, struct mtd_partition **partitions,
struct mtd_info *mtd, struct mtd_partition **partitions,
int *num_partitions)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (chip->page_shift == 12) {
chip->ecc.layout = &qi_lb60_ecclayout_2gb;
*partitions = qi_lb60_partitions_2gb;
*num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb);
} else {
chip->ecc.layout = &qi_lb60_ecclayout_1gb;
*partitions = qi_lb60_partitions_1gb;
*num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb);
}
mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
}
static struct jz_nand_platform_data qi_lb60_nand_pdata = {

View File

@@ -146,7 +146,6 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
return -ENOTSUPP;
}
sflash->window = BCMA_SOC_FLASH2;
sflash->blocksize = e->blocksize;
sflash->numblocks = e->numblocks;
sflash->size = sflash->blocksize * sflash->numblocks;

View File

@@ -51,6 +51,7 @@ config TI_EMIF
config OMAP_GPMC
bool
select GPIOLIB
help
This driver is for the General Purpose Memory Controller (GPMC)
present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows

View File

@@ -59,11 +59,11 @@ int fsl_ifc_find(phys_addr_t addr_base)
{
int i = 0;
if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->gregs)
return -ENODEV;
for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) {
u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr);
u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr);
if (cspr & CSPR_V && (cspr & CSPR_BA) ==
convert_ifc_address(addr_base))
return i;
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(fsl_ifc_find);
static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
{
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
struct fsl_ifc_global __iomem *ifc = ctrl->gregs;
/*
* Clear all the common status and event registers
@@ -104,7 +104,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev)
irq_dispose_mapping(ctrl->nand_irq);
irq_dispose_mapping(ctrl->irq);
iounmap(ctrl->regs);
iounmap(ctrl->gregs);
dev_set_drvdata(&dev->dev, NULL);
kfree(ctrl);
@@ -122,7 +122,7 @@ static DEFINE_SPINLOCK(nand_irq_lock);
static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
{
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
unsigned long flags;
u32 stat;
@@ -157,7 +157,7 @@ static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
{
struct fsl_ifc_ctrl *ctrl = data;
struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
struct fsl_ifc_global __iomem *ifc = ctrl->gregs;
u32 err_axiid, err_srcid, status, cs_err, err_addr;
irqreturn_t ret = IRQ_NONE;
@@ -215,6 +215,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
{
int ret = 0;
int version, banks;
void __iomem *addr;
dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
@@ -225,22 +226,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
/* IOMAP the entire IFC region */
fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
if (!fsl_ifc_ctrl_dev->regs) {
fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0);
if (!fsl_ifc_ctrl_dev->gregs) {
dev_err(&dev->dev, "failed to get memory region\n");
ret = -ENODEV;
goto err;
}
version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) &
FSL_IFC_VERSION_MASK;
banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8;
dev_info(&dev->dev, "IFC version %d.%d, %d banks\n",
version >> 24, (version >> 16) & 0xf, banks);
fsl_ifc_ctrl_dev->version = version;
fsl_ifc_ctrl_dev->banks = banks;
if (of_property_read_bool(dev->dev.of_node, "little-endian")) {
fsl_ifc_ctrl_dev->little_endian = true;
dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n");
@@ -249,8 +241,9 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n");
}
version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) &
version = ifc_in32(&fsl_ifc_ctrl_dev->gregs->ifc_rev) &
FSL_IFC_VERSION_MASK;
banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8;
dev_info(&dev->dev, "IFC version %d.%d, %d banks\n",
version >> 24, (version >> 16) & 0xf, banks);
@@ -258,6 +251,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
fsl_ifc_ctrl_dev->version = version;
fsl_ifc_ctrl_dev->banks = banks;
addr = fsl_ifc_ctrl_dev->gregs;
if (version >= FSL_IFC_VERSION_2_0_0)
addr += PGOFFSET_64K;
else
addr += PGOFFSET_4K;
fsl_ifc_ctrl_dev->rregs = addr;
/* get the Controller level irq */
fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
if (fsl_ifc_ctrl_dev->irq == 0) {

File diff suppressed because it is too large Load Diff

View File

@@ -115,6 +115,7 @@ config MTD_MAP_BANK_WIDTH_16
config MTD_MAP_BANK_WIDTH_32
bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
select MTD_COMPLEX_MAPPINGS if HAS_IOMEM
default n
help
If you wish to support CFI devices on a physical bus which is

View File

@@ -2,6 +2,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/mtd/mtd.h>
#include <linux/platform_device.h>
#include <linux/bcma/bcma.h>
@@ -109,8 +110,7 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
if ((from + len) > mtd->size)
return -EINVAL;
memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from),
len);
memcpy_fromio(buf, b47s->window + from, len);
*retlen = len;
return len;
@@ -275,15 +275,33 @@ static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
{
struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev;
struct bcma_sflash *sflash = dev_get_platdata(dev);
struct bcm47xxsflash *b47s;
struct resource *res;
int err;
b47s = devm_kzalloc(&pdev->dev, sizeof(*b47s), GFP_KERNEL);
b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
if (!b47s)
return -ENOMEM;
sflash->priv = b47s;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "invalid resource\n");
return -EINVAL;
}
if (!devm_request_mem_region(dev, res->start, resource_size(res),
res->name)) {
dev_err(dev, "can't request region for resource %pR\n", res);
return -EBUSY;
}
b47s->window = ioremap_cache(res->start, resource_size(res));
if (!b47s->window) {
dev_err(dev, "ioremap failed for resource %pR\n", res);
return -ENOMEM;
}
b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
b47s->cc_read = bcm47xxsflash_bcma_cc_read;
b47s->cc_write = bcm47xxsflash_bcma_cc_write;
@@ -297,7 +315,6 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
break;
}
b47s->window = sflash->window;
b47s->blocksize = sflash->blocksize;
b47s->numblocks = sflash->numblocks;
b47s->size = sflash->size;
@@ -306,6 +323,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
if (err) {
pr_err("Failed to register MTD device: %d\n", err);
iounmap(b47s->window);
return err;
}
@@ -321,6 +339,7 @@ static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
struct bcm47xxsflash *b47s = sflash->priv;
mtd_device_unregister(&b47s->mtd);
iounmap(b47s->window);
return 0;
}

View File

@@ -65,7 +65,8 @@ struct bcm47xxsflash {
enum bcm47xxsflash_type type;
u32 window;
void __iomem *window;
u32 blocksize;
u16 numblocks;
u32 size;

View File

@@ -67,16 +67,40 @@ module_param(reliable_mode, uint, 0);
MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, "
"2=reliable) : MLC normal operations are in normal mode");
/**
* struct docg3_oobinfo - DiskOnChip G3 OOB layout
* @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC)
* @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC)
* @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15
*/
static struct nand_ecclayout docg3_oobinfo = {
.eccbytes = 8,
.eccpos = {7, 8, 9, 10, 11, 12, 13, 14},
.oobfree = {{0, 7}, {15, 1} },
static int docg3_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section)
return -ERANGE;
/* byte 7 is Hamming ECC, byte 8-14 are BCH ECC */
oobregion->offset = 7;
oobregion->length = 8;
return 0;
}
static int docg3_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section > 1)
return -ERANGE;
/* free bytes: byte 0 until byte 6, byte 15 */
if (!section) {
oobregion->offset = 0;
oobregion->length = 7;
} else {
oobregion->offset = 15;
oobregion->length = 1;
}
return 0;
}
static const struct mtd_ooblayout_ops nand_ooblayout_docg3_ops = {
.ecc = docg3_ooblayout_ecc,
.free = docg3_ooblayout_free,
};
static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
@@ -1857,7 +1881,7 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
mtd->_read_oob = doc_read_oob;
mtd->_write_oob = doc_write_oob;
mtd->_block_isbad = doc_block_isbad;
mtd->ecclayout = &docg3_oobinfo;
mtd_set_ooblayout(mtd, &nand_ooblayout_docg3_ops);
mtd->oobavail = 8;
mtd->ecc_strength = DOC_ECC_BCH_T;

View File

@@ -131,6 +131,28 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
/* convert the dummy cycles to the number of bytes */
dummy /= 8;
if (spi_flash_read_supported(spi)) {
struct spi_flash_read_message msg;
int ret;
memset(&msg, 0, sizeof(msg));
msg.buf = buf;
msg.from = from;
msg.len = len;
msg.read_opcode = nor->read_opcode;
msg.addr_width = nor->addr_width;
msg.dummy_bytes = dummy;
/* TODO: Support other combinations */
msg.opcode_nbits = SPI_NBITS_SINGLE;
msg.addr_nbits = SPI_NBITS_SINGLE;
msg.data_nbits = m25p80_rx_nbits(nor);
ret = spi_flash_read(spi, &msg);
*retlen = msg.retlen;
return ret;
}
spi_message_init(&m);
memset(t, 0, (sizeof t));

View File

@@ -353,7 +353,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
* mechanism
* returns the size of the memory region found.
*/
static int fixup_pmc551(struct pci_dev *dev)
static int __init fixup_pmc551(struct pci_dev *dev)
{
#ifdef CONFIG_MTD_PMC551_BUGFIX
u32 dram_data;

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