You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
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:
@@ -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 */
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,8 @@ struct bcm47xxsflash {
|
||||
|
||||
enum bcm47xxsflash_type type;
|
||||
|
||||
u32 window;
|
||||
void __iomem *window;
|
||||
|
||||
u32 blocksize;
|
||||
u16 numblocks;
|
||||
u32 size;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user