diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-24 14:00:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-24 14:00:20 -0400 |
| commit | 8bc4d5f394a3facbad6af2f18940f1db3b1a0844 (patch) | |
| tree | 14838a236e87126d4b84d22b9049b9a6f0be878f | |
| parent | 29567292c0b5b2fb484125c280a2175141fe2205 (diff) | |
| parent | e5366a266a8cd4cd6b0fe66876462cca2e1c6a89 (diff) | |
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
...
89 files changed, 4338 insertions, 2908 deletions
diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt index 01683707060b..21055e210234 100644 --- a/Documentation/devicetree/bindings/bus/ti-gpmc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt | |||
| @@ -32,6 +32,19 @@ Required properties: | |||
| 32 | bootloader) are used for the physical address decoding. | 32 | bootloader) are used for the physical address decoding. |
| 33 | As this will change in the future, filling correct | 33 | As this will change in the future, filling correct |
| 34 | values here is a requirement. | 34 | values here is a requirement. |
| 35 | - interrupt-controller: The GPMC driver implements and interrupt controller for | ||
| 36 | the NAND events "fifoevent" and "termcount" plus the | ||
| 37 | rising/falling edges on the GPMC_WAIT pins. | ||
| 38 | The interrupt number mapping is as follows | ||
| 39 | 0 - NAND_fifoevent | ||
| 40 | 1 - NAND_termcount | ||
| 41 | 2 - GPMC_WAIT0 pin edge | ||
| 42 | 3 - GPMC_WAIT1 pin edge, and so on. | ||
| 43 | - interrupt-cells: Must be set to 2 | ||
| 44 | - gpio-controller: The GPMC driver implements a GPIO controller for the | ||
| 45 | GPMC WAIT pins that can be used as general purpose inputs. | ||
| 46 | 0 maps to GPMC_WAIT0 pin. | ||
| 47 | - gpio-cells: Must be set to 2 | ||
| 35 | 48 | ||
| 36 | Timing properties for child nodes. All are optional and default to 0. | 49 | Timing properties for child nodes. All are optional and default to 0. |
| 37 | 50 | ||
| @@ -130,6 +143,10 @@ Example for an AM33xx board: | |||
| 130 | #address-cells = <2>; | 143 | #address-cells = <2>; |
| 131 | #size-cells = <1>; | 144 | #size-cells = <1>; |
| 132 | ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */ | 145 | ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */ |
| 146 | interrupt-controller; | ||
| 147 | #interrupt-cells = <2>; | ||
| 148 | gpio-controller; | ||
| 149 | #gpio-cells = <2>; | ||
| 133 | 150 | ||
| 134 | /* child nodes go here */ | 151 | /* child nodes go here */ |
| 135 | }; | 152 | }; |
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt index 0f6985b5de49..7066597c9a81 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt | |||
| @@ -24,6 +24,7 @@ Required properties: | |||
| 24 | brcm,brcmnand-v5.0 | 24 | brcm,brcmnand-v5.0 |
| 25 | brcm,brcmnand-v6.0 | 25 | brcm,brcmnand-v6.0 |
| 26 | brcm,brcmnand-v6.1 | 26 | brcm,brcmnand-v6.1 |
| 27 | brcm,brcmnand-v6.2 | ||
| 27 | brcm,brcmnand-v7.0 | 28 | brcm,brcmnand-v7.0 |
| 28 | brcm,brcmnand-v7.1 | 29 | brcm,brcmnand-v7.1 |
| 29 | brcm,brcmnand | 30 | brcm,brcmnand |
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index fb733c4e1c11..3ee7e202657c 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt | |||
| @@ -13,7 +13,11 @@ Documentation/devicetree/bindings/mtd/nand.txt | |||
| 13 | 13 | ||
| 14 | Required properties: | 14 | Required properties: |
| 15 | 15 | ||
| 16 | - reg: The CS line the peripheral is connected to | 16 | - compatible: "ti,omap2-nand" |
| 17 | - reg: range id (CS number), base offset and length of the | ||
| 18 | NAND I/O space | ||
| 19 | - interrupt-parent: must point to gpmc node | ||
| 20 | - interrupts: Two interrupt specifiers, one for fifoevent, one for termcount. | ||
| 17 | 21 | ||
| 18 | Optional properties: | 22 | Optional properties: |
| 19 | 23 | ||
| @@ -44,6 +48,7 @@ Optional properties: | |||
| 44 | locating ECC errors for BCHx algorithms. SoC devices which have | 48 | locating ECC errors for BCHx algorithms. SoC devices which have |
| 45 | ELM hardware engines should specify this device node in .dtsi | 49 | ELM hardware engines should specify this device node in .dtsi |
| 46 | Using ELM for ECC error correction frees some CPU cycles. | 50 | Using ELM for ECC error correction frees some CPU cycles. |
| 51 | - rb-gpios: GPIO specifier for the ready/busy# pin. | ||
| 47 | 52 | ||
| 48 | For inline partition table parsing (optional): | 53 | For inline partition table parsing (optional): |
| 49 | 54 | ||
| @@ -55,20 +60,26 @@ Example for an AM33xx board: | |||
| 55 | gpmc: gpmc@50000000 { | 60 | gpmc: gpmc@50000000 { |
| 56 | compatible = "ti,am3352-gpmc"; | 61 | compatible = "ti,am3352-gpmc"; |
| 57 | ti,hwmods = "gpmc"; | 62 | ti,hwmods = "gpmc"; |
| 58 | reg = <0x50000000 0x1000000>; | 63 | reg = <0x50000000 0x36c>; |
| 59 | interrupts = <100>; | 64 | interrupts = <100>; |
| 60 | gpmc,num-cs = <8>; | 65 | gpmc,num-cs = <8>; |
| 61 | gpmc,num-waitpins = <2>; | 66 | gpmc,num-waitpins = <2>; |
| 62 | #address-cells = <2>; | 67 | #address-cells = <2>; |
| 63 | #size-cells = <1>; | 68 | #size-cells = <1>; |
| 64 | ranges = <0 0 0x08000000 0x2000>; /* CS0: NAND */ | 69 | ranges = <0 0 0x08000000 0x1000000>; /* CS0 space, 16MB */ |
| 65 | elm_id = <&elm>; | 70 | elm_id = <&elm>; |
| 71 | interrupt-controller; | ||
| 72 | #interrupt-cells = <2>; | ||
| 66 | 73 | ||
| 67 | nand@0,0 { | 74 | nand@0,0 { |
| 68 | reg = <0 0 0>; /* CS0, offset 0 */ | 75 | compatible = "ti,omap2-nand"; |
| 76 | reg = <0 0 4>; /* CS0, offset 0, NAND I/O window 4 */ | ||
| 77 | interrupt-parent = <&gpmc>; | ||
| 78 | interrupts = <0 IRQ_TYPE_NONE>, <1 IRQ_TYPE NONE>; | ||
| 69 | nand-bus-width = <16>; | 79 | nand-bus-width = <16>; |
| 70 | ti,nand-ecc-opt = "bch8"; | 80 | ti,nand-ecc-opt = "bch8"; |
| 71 | ti,nand-xfer-type = "polled"; | 81 | ti,nand-xfer-type = "polled"; |
| 82 | rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ | ||
| 72 | 83 | ||
| 73 | gpmc,sync-clk-ps = <0>; | 84 | gpmc,sync-clk-ps = <0>; |
| 74 | gpmc,cs-on-ns = <0>; | 85 | gpmc,cs-on-ns = <0>; |
diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt index b53f92e252d4..68342eac2383 100644 --- a/Documentation/devicetree/bindings/mtd/nand.txt +++ b/Documentation/devicetree/bindings/mtd/nand.txt | |||
| @@ -1,8 +1,31 @@ | |||
| 1 | * MTD generic binding | 1 | * NAND chip and NAND controller generic binding |
| 2 | |||
| 3 | NAND controller/NAND chip representation: | ||
| 4 | |||
| 5 | The NAND controller should be represented with its own DT node, and all | ||
| 6 | NAND chips attached to this controller should be defined as children nodes | ||
| 7 | of the NAND controller. This representation should be enforced even for | ||
| 8 | simple controllers supporting only one chip. | ||
| 9 | |||
| 10 | Mandatory NAND controller properties: | ||
| 11 | - #address-cells: depends on your controller. Should at least be 1 to | ||
| 12 | encode the CS line id. | ||
| 13 | - #size-cells: depends on your controller. Put zero unless you need a | ||
| 14 | mapping between CS lines and dedicated memory regions | ||
| 15 | |||
| 16 | Optional NAND controller properties | ||
| 17 | - ranges: only needed if you need to define a mapping between CS lines and | ||
| 18 | memory regions | ||
| 19 | |||
| 20 | Optional NAND chip properties: | ||
| 2 | 21 | ||
| 3 | - nand-ecc-mode : String, operation mode of the NAND ecc mode. | 22 | - nand-ecc-mode : String, operation mode of the NAND ecc mode. |
| 4 | Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", | 23 | Supported values are: "none", "soft", "hw", "hw_syndrome", |
| 5 | "soft_bch". | 24 | "hw_oob_first". |
| 25 | Deprecated values: | ||
| 26 | "soft_bch": use "soft" and nand-ecc-algo instead | ||
| 27 | - nand-ecc-algo: string, algorithm of NAND ECC. | ||
| 28 | Supported values are: "hamming", "bch". | ||
| 6 | - nand-bus-width : 8 or 16 bus width if not present 8 | 29 | - nand-bus-width : 8 or 16 bus width if not present 8 |
| 7 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false | 30 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false |
| 8 | 31 | ||
| @@ -19,3 +42,19 @@ errors per {size} bytes". | |||
| 19 | The interpretation of these parameters is implementation-defined, so not all | 42 | The interpretation of these parameters is implementation-defined, so not all |
| 20 | implementations must support all possible combinations. However, implementations | 43 | implementations must support all possible combinations. However, implementations |
| 21 | are encouraged to further specify the value(s) they support. | 44 | are encouraged to further specify the value(s) they support. |
| 45 | |||
| 46 | Example: | ||
| 47 | |||
| 48 | nand-controller { | ||
| 49 | #address-cells = <1>; | ||
| 50 | #size-cells = <0>; | ||
| 51 | |||
| 52 | /* controller specific properties */ | ||
| 53 | |||
| 54 | nand@0 { | ||
| 55 | reg = <0>; | ||
| 56 | nand-ecc-mode = "soft_bch"; | ||
| 57 | |||
| 58 | /* controller specific properties */ | ||
| 59 | }; | ||
| 60 | }; | ||
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 72918c4973ea..f6ac027f3c3b 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c | |||
| @@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | |||
| 97 | gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); | 97 | gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); |
| 98 | 98 | ||
| 99 | memset(&s, 0, sizeof(struct gpmc_settings)); | 99 | memset(&s, 0, sizeof(struct gpmc_settings)); |
| 100 | if (gpmc_nand_data->of_node) | 100 | gpmc_set_legacy(gpmc_nand_data, &s); |
| 101 | gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); | ||
| 102 | else | ||
| 103 | gpmc_set_legacy(gpmc_nand_data, &s); | ||
| 104 | 101 | ||
| 105 | s.device_nand = true; | 102 | s.device_nand = true; |
| 106 | 103 | ||
| @@ -121,8 +118,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | |||
| 121 | if (err < 0) | 118 | if (err < 0) |
| 122 | goto out_free_cs; | 119 | goto out_free_cs; |
| 123 | 120 | ||
| 124 | gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); | ||
| 125 | |||
| 126 | if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { | 121 | if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { |
| 127 | pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n"); | 122 | pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n"); |
| 128 | err = -EINVAL; | 123 | err = -EINVAL; |
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index d9578bc49fdc..bd7cd8b6a286 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c | |||
| @@ -763,14 +763,49 @@ static struct nand_bbt_descr spitz_nand_bbt = { | |||
| 763 | .pattern = scan_ff_pattern | 763 | .pattern = scan_ff_pattern |
| 764 | }; | 764 | }; |
| 765 | 765 | ||
| 766 | static struct nand_ecclayout akita_oobinfo = { | 766 | static int akita_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 767 | .oobfree = { {0x08, 0x09} }, | 767 | struct mtd_oob_region *oobregion) |
| 768 | .eccbytes = 24, | 768 | { |
| 769 | .eccpos = { | 769 | if (section > 12) |
| 770 | 0x05, 0x01, 0x02, 0x03, 0x06, 0x07, 0x15, 0x11, | 770 | return -ERANGE; |
| 771 | 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, | 771 | |
| 772 | 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37, | 772 | switch (section % 3) { |
| 773 | }, | 773 | case 0: |
| 774 | oobregion->offset = 5; | ||
| 775 | oobregion->length = 1; | ||
| 776 | break; | ||
| 777 | |||
| 778 | case 1: | ||
| 779 | oobregion->offset = 1; | ||
| 780 | oobregion->length = 3; | ||
| 781 | break; | ||
| 782 | |||
| 783 | case 2: | ||
| 784 | oobregion->offset = 6; | ||
| 785 | oobregion->length = 2; | ||
| 786 | break; | ||
| 787 | } | ||
| 788 | |||
| 789 | oobregion->offset += (section / 3) * 0x10; | ||
| 790 | |||
| 791 | return 0; | ||
| 792 | } | ||
| 793 | |||
| 794 | static int akita_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 795 | struct mtd_oob_region *oobregion) | ||
| 796 | { | ||
| 797 | if (section) | ||
| 798 | return -ERANGE; | ||
| 799 | |||
| 800 | oobregion->offset = 8; | ||
| 801 | oobregion->length = 9; | ||
| 802 | |||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | |||
| 806 | static const struct mtd_ooblayout_ops akita_ooblayout_ops = { | ||
| 807 | .ecc = akita_ooblayout_ecc, | ||
| 808 | .free = akita_ooblayout_free, | ||
| 774 | }; | 809 | }; |
| 775 | 810 | ||
| 776 | static struct sharpsl_nand_platform_data spitz_nand_pdata = { | 811 | static struct sharpsl_nand_platform_data spitz_nand_pdata = { |
| @@ -804,11 +839,11 @@ static void __init spitz_nand_init(void) | |||
| 804 | } else if (machine_is_akita()) { | 839 | } else if (machine_is_akita()) { |
| 805 | spitz_nand_partitions[1].size = 58 * 1024 * 1024; | 840 | spitz_nand_partitions[1].size = 58 * 1024 * 1024; |
| 806 | spitz_nand_bbt.len = 1; | 841 | spitz_nand_bbt.len = 1; |
| 807 | spitz_nand_pdata.ecc_layout = &akita_oobinfo; | 842 | spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops; |
| 808 | } else if (machine_is_borzoi()) { | 843 | } else if (machine_is_borzoi()) { |
| 809 | spitz_nand_partitions[1].size = 32 * 1024 * 1024; | 844 | spitz_nand_partitions[1].size = 32 * 1024 * 1024; |
| 810 | spitz_nand_bbt.len = 1; | 845 | spitz_nand_bbt.len = 1; |
| 811 | spitz_nand_pdata.ecc_layout = &akita_oobinfo; | 846 | spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops; |
| 812 | } | 847 | } |
| 813 | 848 | ||
| 814 | platform_device_register(&spitz_nand_device); | 849 | platform_device_register(&spitz_nand_device); |
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c index 5aa3f5162310..3f646c787e58 100644 --- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c +++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c | |||
| @@ -157,6 +157,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void) | |||
| 157 | /* 20 us command delay time */ | 157 | /* 20 us command delay time */ |
| 158 | this->chip_delay = 20; | 158 | this->chip_delay = 20; |
| 159 | this->ecc.mode = NAND_ECC_SOFT; | 159 | this->ecc.mode = NAND_ECC_SOFT; |
| 160 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 160 | 161 | ||
| 161 | /* Enable the following for a flash based bad block table */ | 162 | /* Enable the following for a flash based bad block table */ |
| 162 | /* this->bbt_options = NAND_BBT_USE_FLASH; */ | 163 | /* this->bbt_options = NAND_BBT_USE_FLASH; */ |
diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c index a7c17b0f172a..a74540514bdb 100644 --- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c +++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c | |||
| @@ -148,6 +148,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void) | |||
| 148 | /* 20 us command delay time */ | 148 | /* 20 us command delay time */ |
| 149 | this->chip_delay = 20; | 149 | this->chip_delay = 20; |
| 150 | this->ecc.mode = NAND_ECC_SOFT; | 150 | this->ecc.mode = NAND_ECC_SOFT; |
| 151 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 151 | 152 | ||
| 152 | /* Enable the following for a flash based bad block table */ | 153 | /* Enable the following for a flash based bad block table */ |
| 153 | /* this->bbt_options = NAND_BBT_USE_FLASH; */ | 154 | /* this->bbt_options = NAND_BBT_USE_FLASH; */ |
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h index 398733e3e2cf..7f7b0fc554da 100644 --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h | |||
| @@ -27,7 +27,7 @@ struct jz_nand_platform_data { | |||
| 27 | 27 | ||
| 28 | unsigned char banks[JZ_NAND_NUM_BANKS]; | 28 | unsigned char banks[JZ_NAND_NUM_BANKS]; |
| 29 | 29 | ||
| 30 | void (*ident_callback)(struct platform_device *, struct nand_chip *, | 30 | void (*ident_callback)(struct platform_device *, struct mtd_info *, |
| 31 | struct mtd_partition **, int *num_partitions); | 31 | struct mtd_partition **, int *num_partitions); |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 4e3f9b7a02e4..258fd03c9ef5 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
| @@ -48,20 +48,6 @@ | |||
| 48 | #define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) | 48 | #define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) |
| 49 | 49 | ||
| 50 | /* NAND */ | 50 | /* NAND */ |
| 51 | static struct nand_ecclayout qi_lb60_ecclayout_1gb = { | ||
| 52 | .eccbytes = 36, | ||
| 53 | .eccpos = { | ||
| 54 | 6, 7, 8, 9, 10, 11, 12, 13, | ||
| 55 | 14, 15, 16, 17, 18, 19, 20, 21, | ||
| 56 | 22, 23, 24, 25, 26, 27, 28, 29, | ||
| 57 | 30, 31, 32, 33, 34, 35, 36, 37, | ||
| 58 | 38, 39, 40, 41 | ||
| 59 | }, | ||
| 60 | .oobfree = { | ||
| 61 | { .offset = 2, .length = 4 }, | ||
| 62 | { .offset = 42, .length = 22 } | ||
| 63 | }, | ||
| 64 | }; | ||
| 65 | 51 | ||
| 66 | /* Early prototypes of the QI LB60 had only 1GB of NAND. | 52 | /* Early prototypes of the QI LB60 had only 1GB of NAND. |
| 67 | * In order to support these devices as well the partition and ecc layout is | 53 | * 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[] = { | |||
| 84 | }, | 70 | }, |
| 85 | }; | 71 | }; |
| 86 | 72 | ||
| 87 | static struct nand_ecclayout qi_lb60_ecclayout_2gb = { | ||
| 88 | .eccbytes = 72, | ||
| 89 | .eccpos = { | ||
| 90 | 12, 13, 14, 15, 16, 17, 18, 19, | ||
| 91 | 20, 21, 22, 23, 24, 25, 26, 27, | ||
| 92 | 28, 29, 30, 31, 32, 33, 34, 35, | ||
| 93 | 36, 37, 38, 39, 40, 41, 42, 43, | ||
| 94 | 44, 45, 46, 47, 48, 49, 50, 51, | ||
| 95 | 52, 53, 54, 55, 56, 57, 58, 59, | ||
| 96 | 60, 61, 62, 63, 64, 65, 66, 67, | ||
| 97 | 68, 69, 70, 71, 72, 73, 74, 75, | ||
| 98 | 76, 77, 78, 79, 80, 81, 82, 83 | ||
| 99 | }, | ||
| 100 | .oobfree = { | ||
| 101 | { .offset = 2, .length = 10 }, | ||
| 102 | { .offset = 84, .length = 44 }, | ||
| 103 | }, | ||
| 104 | }; | ||
| 105 | |||
| 106 | static struct mtd_partition qi_lb60_partitions_2gb[] = { | 73 | static struct mtd_partition qi_lb60_partitions_2gb[] = { |
| 107 | { | 74 | { |
| 108 | .name = "NAND BOOT partition", | 75 | .name = "NAND BOOT partition", |
| @@ -121,19 +88,67 @@ static struct mtd_partition qi_lb60_partitions_2gb[] = { | |||
| 121 | }, | 88 | }, |
| 122 | }; | 89 | }; |
| 123 | 90 | ||
| 91 | static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 92 | struct mtd_oob_region *oobregion) | ||
| 93 | { | ||
| 94 | if (section) | ||
| 95 | return -ERANGE; | ||
| 96 | |||
| 97 | oobregion->length = 36; | ||
| 98 | oobregion->offset = 6; | ||
| 99 | |||
| 100 | if (mtd->oobsize == 128) { | ||
| 101 | oobregion->length *= 2; | ||
| 102 | oobregion->offset *= 2; | ||
| 103 | } | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 109 | struct mtd_oob_region *oobregion) | ||
| 110 | { | ||
| 111 | int eccbytes = 36, eccoff = 6; | ||
| 112 | |||
| 113 | if (section > 1) | ||
| 114 | return -ERANGE; | ||
| 115 | |||
| 116 | if (mtd->oobsize == 128) { | ||
| 117 | eccbytes *= 2; | ||
| 118 | eccoff *= 2; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (!section) { | ||
| 122 | oobregion->offset = 2; | ||
| 123 | oobregion->length = eccoff - 2; | ||
| 124 | } else { | ||
| 125 | oobregion->offset = eccoff + eccbytes; | ||
| 126 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 127 | } | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = { | ||
| 133 | .ecc = qi_lb60_ooblayout_ecc, | ||
| 134 | .free = qi_lb60_ooblayout_free, | ||
| 135 | }; | ||
| 136 | |||
| 124 | static void qi_lb60_nand_ident(struct platform_device *pdev, | 137 | static void qi_lb60_nand_ident(struct platform_device *pdev, |
| 125 | struct nand_chip *chip, struct mtd_partition **partitions, | 138 | struct mtd_info *mtd, struct mtd_partition **partitions, |
| 126 | int *num_partitions) | 139 | int *num_partitions) |
| 127 | { | 140 | { |
| 141 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 142 | |||
| 128 | if (chip->page_shift == 12) { | 143 | if (chip->page_shift == 12) { |
| 129 | chip->ecc.layout = &qi_lb60_ecclayout_2gb; | ||
| 130 | *partitions = qi_lb60_partitions_2gb; | 144 | *partitions = qi_lb60_partitions_2gb; |
| 131 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); | 145 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); |
| 132 | } else { | 146 | } else { |
| 133 | chip->ecc.layout = &qi_lb60_ecclayout_1gb; | ||
| 134 | *partitions = qi_lb60_partitions_1gb; | 147 | *partitions = qi_lb60_partitions_1gb; |
| 135 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); | 148 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); |
| 136 | } | 149 | } |
| 150 | |||
| 151 | mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops); | ||
| 137 | } | 152 | } |
| 138 | 153 | ||
| 139 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { | 154 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { |
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 04d706ca5f43..35b13a08ca3e 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c | |||
| @@ -146,7 +146,6 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) | |||
| 146 | return -ENOTSUPP; | 146 | return -ENOTSUPP; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | sflash->window = BCMA_SOC_FLASH2; | ||
| 150 | sflash->blocksize = e->blocksize; | 149 | sflash->blocksize = e->blocksize; |
| 151 | sflash->numblocks = e->numblocks; | 150 | sflash->numblocks = e->numblocks; |
| 152 | sflash->size = sflash->blocksize * sflash->numblocks; | 151 | sflash->size = sflash->blocksize * sflash->numblocks; |
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index c61a284133e0..81ddb17575a9 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
| @@ -51,6 +51,7 @@ config TI_EMIF | |||
| 51 | 51 | ||
| 52 | config OMAP_GPMC | 52 | config OMAP_GPMC |
| 53 | bool | 53 | bool |
| 54 | select GPIOLIB | ||
| 54 | help | 55 | help |
| 55 | This driver is for the General Purpose Memory Controller (GPMC) | 56 | This driver is for the General Purpose Memory Controller (GPMC) |
| 56 | present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows | 57 | present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows |
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index 2a691da8c1c7..904b4af5f142 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c | |||
| @@ -59,11 +59,11 @@ int fsl_ifc_find(phys_addr_t addr_base) | |||
| 59 | { | 59 | { |
| 60 | int i = 0; | 60 | int i = 0; |
| 61 | 61 | ||
| 62 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) | 62 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->gregs) |
| 63 | return -ENODEV; | 63 | return -ENODEV; |
| 64 | 64 | ||
| 65 | for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { | 65 | for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { |
| 66 | u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); | 66 | u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr); |
| 67 | if (cspr & CSPR_V && (cspr & CSPR_BA) == | 67 | if (cspr & CSPR_V && (cspr & CSPR_BA) == |
| 68 | convert_ifc_address(addr_base)) | 68 | convert_ifc_address(addr_base)) |
| 69 | return i; | 69 | return i; |
| @@ -75,7 +75,7 @@ EXPORT_SYMBOL(fsl_ifc_find); | |||
| 75 | 75 | ||
| 76 | static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) | 76 | static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) |
| 77 | { | 77 | { |
| 78 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 78 | struct fsl_ifc_global __iomem *ifc = ctrl->gregs; |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| 81 | * Clear all the common status and event registers | 81 | * Clear all the common status and event registers |
| @@ -104,7 +104,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev) | |||
| 104 | irq_dispose_mapping(ctrl->nand_irq); | 104 | irq_dispose_mapping(ctrl->nand_irq); |
| 105 | irq_dispose_mapping(ctrl->irq); | 105 | irq_dispose_mapping(ctrl->irq); |
| 106 | 106 | ||
| 107 | iounmap(ctrl->regs); | 107 | iounmap(ctrl->gregs); |
| 108 | 108 | ||
| 109 | dev_set_drvdata(&dev->dev, NULL); | 109 | dev_set_drvdata(&dev->dev, NULL); |
| 110 | kfree(ctrl); | 110 | kfree(ctrl); |
| @@ -122,7 +122,7 @@ static DEFINE_SPINLOCK(nand_irq_lock); | |||
| 122 | 122 | ||
| 123 | static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) | 123 | static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) |
| 124 | { | 124 | { |
| 125 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 125 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 126 | unsigned long flags; | 126 | unsigned long flags; |
| 127 | u32 stat; | 127 | u32 stat; |
| 128 | 128 | ||
| @@ -157,7 +157,7 @@ static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data) | |||
| 157 | static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) | 157 | static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) |
| 158 | { | 158 | { |
| 159 | struct fsl_ifc_ctrl *ctrl = data; | 159 | struct fsl_ifc_ctrl *ctrl = data; |
| 160 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 160 | struct fsl_ifc_global __iomem *ifc = ctrl->gregs; |
| 161 | u32 err_axiid, err_srcid, status, cs_err, err_addr; | 161 | u32 err_axiid, err_srcid, status, cs_err, err_addr; |
| 162 | irqreturn_t ret = IRQ_NONE; | 162 | irqreturn_t ret = IRQ_NONE; |
| 163 | 163 | ||
| @@ -215,6 +215,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) | |||
| 215 | { | 215 | { |
| 216 | int ret = 0; | 216 | int ret = 0; |
| 217 | int version, banks; | 217 | int version, banks; |
| 218 | void __iomem *addr; | ||
| 218 | 219 | ||
| 219 | dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); | 220 | dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); |
| 220 | 221 | ||
| @@ -225,22 +226,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) | |||
| 225 | dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev); | 226 | dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev); |
| 226 | 227 | ||
| 227 | /* IOMAP the entire IFC region */ | 228 | /* IOMAP the entire IFC region */ |
| 228 | fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); | 229 | fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0); |
| 229 | if (!fsl_ifc_ctrl_dev->regs) { | 230 | if (!fsl_ifc_ctrl_dev->gregs) { |
| 230 | dev_err(&dev->dev, "failed to get memory region\n"); | 231 | dev_err(&dev->dev, "failed to get memory region\n"); |
| 231 | ret = -ENODEV; | 232 | ret = -ENODEV; |
| 232 | goto err; | 233 | goto err; |
| 233 | } | 234 | } |
| 234 | 235 | ||
| 235 | version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) & | ||
| 236 | FSL_IFC_VERSION_MASK; | ||
| 237 | banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; | ||
| 238 | dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", | ||
| 239 | version >> 24, (version >> 16) & 0xf, banks); | ||
| 240 | |||
| 241 | fsl_ifc_ctrl_dev->version = version; | ||
| 242 | fsl_ifc_ctrl_dev->banks = banks; | ||
| 243 | |||
| 244 | if (of_property_read_bool(dev->dev.of_node, "little-endian")) { | 236 | if (of_property_read_bool(dev->dev.of_node, "little-endian")) { |
| 245 | fsl_ifc_ctrl_dev->little_endian = true; | 237 | fsl_ifc_ctrl_dev->little_endian = true; |
| 246 | dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); | 238 | dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); |
| @@ -249,8 +241,9 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) | |||
| 249 | dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); | 241 | dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); |
| 250 | } | 242 | } |
| 251 | 243 | ||
| 252 | version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & | 244 | version = ifc_in32(&fsl_ifc_ctrl_dev->gregs->ifc_rev) & |
| 253 | FSL_IFC_VERSION_MASK; | 245 | FSL_IFC_VERSION_MASK; |
| 246 | |||
| 254 | banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; | 247 | banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; |
| 255 | dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", | 248 | dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", |
| 256 | version >> 24, (version >> 16) & 0xf, banks); | 249 | version >> 24, (version >> 16) & 0xf, banks); |
| @@ -258,6 +251,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) | |||
| 258 | fsl_ifc_ctrl_dev->version = version; | 251 | fsl_ifc_ctrl_dev->version = version; |
| 259 | fsl_ifc_ctrl_dev->banks = banks; | 252 | fsl_ifc_ctrl_dev->banks = banks; |
| 260 | 253 | ||
| 254 | addr = fsl_ifc_ctrl_dev->gregs; | ||
| 255 | if (version >= FSL_IFC_VERSION_2_0_0) | ||
| 256 | addr += PGOFFSET_64K; | ||
| 257 | else | ||
| 258 | addr += PGOFFSET_4K; | ||
| 259 | fsl_ifc_ctrl_dev->rregs = addr; | ||
| 260 | |||
| 261 | /* get the Controller level irq */ | 261 | /* get the Controller level irq */ |
| 262 | fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | 262 | fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); |
| 263 | if (fsl_ifc_ctrl_dev->irq == 0) { | 263 | if (fsl_ifc_ctrl_dev->irq == 0) { |
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 21825ddce4a3..af4884ba6b7c 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c | |||
| @@ -21,15 +21,15 @@ | |||
| 21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| 22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/gpio/driver.h> | ||
| 24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/irqdomain.h> | ||
| 25 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 26 | #include <linux/of.h> | 28 | #include <linux/of.h> |
| 27 | #include <linux/of_address.h> | 29 | #include <linux/of_address.h> |
| 28 | #include <linux/of_mtd.h> | ||
| 29 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
| 30 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
| 31 | #include <linux/omap-gpmc.h> | 32 | #include <linux/omap-gpmc.h> |
| 32 | #include <linux/mtd/nand.h> | ||
| 33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
| 34 | 34 | ||
| 35 | #include <linux/platform_data/mtd-nand-omap2.h> | 35 | #include <linux/platform_data/mtd-nand-omap2.h> |
| @@ -81,6 +81,8 @@ | |||
| 81 | 81 | ||
| 82 | #define GPMC_CONFIG_LIMITEDADDRESS BIT(1) | 82 | #define GPMC_CONFIG_LIMITEDADDRESS BIT(1) |
| 83 | 83 | ||
| 84 | #define GPMC_STATUS_EMPTYWRITEBUFFERSTATUS BIT(0) | ||
| 85 | |||
| 84 | #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) | 86 | #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) |
| 85 | #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) | 87 | #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) |
| 86 | #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) | 88 | #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) |
| @@ -92,6 +94,14 @@ | |||
| 92 | #define GPMC_CS_SIZE 0x30 | 94 | #define GPMC_CS_SIZE 0x30 |
| 93 | #define GPMC_BCH_SIZE 0x10 | 95 | #define GPMC_BCH_SIZE 0x10 |
| 94 | 96 | ||
| 97 | /* | ||
| 98 | * The first 1MB of GPMC address space is typically mapped to | ||
| 99 | * the internal ROM. Never allocate the first page, to | ||
| 100 | * facilitate bug detection; even if we didn't boot from ROM. | ||
| 101 | * As GPMC minimum partition size is 16MB we can only start from | ||
| 102 | * there. | ||
| 103 | */ | ||
| 104 | #define GPMC_MEM_START 0x1000000 | ||
| 95 | #define GPMC_MEM_END 0x3FFFFFFF | 105 | #define GPMC_MEM_END 0x3FFFFFFF |
| 96 | 106 | ||
| 97 | #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ | 107 | #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ |
| @@ -125,7 +135,6 @@ | |||
| 125 | #define GPMC_CONFIG_RDY_BSY 0x00000001 | 135 | #define GPMC_CONFIG_RDY_BSY 0x00000001 |
| 126 | #define GPMC_CONFIG_DEV_SIZE 0x00000002 | 136 | #define GPMC_CONFIG_DEV_SIZE 0x00000002 |
| 127 | #define GPMC_CONFIG_DEV_TYPE 0x00000003 | 137 | #define GPMC_CONFIG_DEV_TYPE 0x00000003 |
| 128 | #define GPMC_SET_IRQ_STATUS 0x00000004 | ||
| 129 | 138 | ||
| 130 | #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) | 139 | #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) |
| 131 | #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) | 140 | #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) |
| @@ -174,16 +183,12 @@ | |||
| 174 | #define GPMC_CONFIG_WRITEPROTECT 0x00000010 | 183 | #define GPMC_CONFIG_WRITEPROTECT 0x00000010 |
| 175 | #define WR_RD_PIN_MONITORING 0x00600000 | 184 | #define WR_RD_PIN_MONITORING 0x00600000 |
| 176 | 185 | ||
| 177 | #define GPMC_ENABLE_IRQ 0x0000000d | ||
| 178 | |||
| 179 | /* ECC commands */ | 186 | /* ECC commands */ |
| 180 | #define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ | 187 | #define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ |
| 181 | #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ | 188 | #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ |
| 182 | #define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ | 189 | #define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ |
| 183 | 190 | ||
| 184 | /* XXX: Only NAND irq has been considered,currently these are the only ones used | 191 | #define GPMC_NR_NAND_IRQS 2 /* number of NAND specific IRQs */ |
| 185 | */ | ||
| 186 | #define GPMC_NR_IRQ 2 | ||
| 187 | 192 | ||
| 188 | enum gpmc_clk_domain { | 193 | enum gpmc_clk_domain { |
| 189 | GPMC_CD_FCLK, | 194 | GPMC_CD_FCLK, |
| @@ -199,11 +204,6 @@ struct gpmc_cs_data { | |||
| 199 | struct resource mem; | 204 | struct resource mem; |
| 200 | }; | 205 | }; |
| 201 | 206 | ||
| 202 | struct gpmc_client_irq { | ||
| 203 | unsigned irq; | ||
| 204 | u32 bitmask; | ||
| 205 | }; | ||
| 206 | |||
| 207 | /* Structure to save gpmc cs context */ | 207 | /* Structure to save gpmc cs context */ |
| 208 | struct gpmc_cs_config { | 208 | struct gpmc_cs_config { |
| 209 | u32 config1; | 209 | u32 config1; |
| @@ -231,9 +231,15 @@ struct omap3_gpmc_regs { | |||
| 231 | struct gpmc_cs_config cs_context[GPMC_CS_NUM]; | 231 | struct gpmc_cs_config cs_context[GPMC_CS_NUM]; |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; | 234 | struct gpmc_device { |
| 235 | static struct irq_chip gpmc_irq_chip; | 235 | struct device *dev; |
| 236 | static int gpmc_irq_start; | 236 | int irq; |
| 237 | struct irq_chip irq_chip; | ||
| 238 | struct gpio_chip gpio_chip; | ||
| 239 | int nirqs; | ||
| 240 | }; | ||
| 241 | |||
| 242 | static struct irq_domain *gpmc_irq_domain; | ||
| 237 | 243 | ||
| 238 | static struct resource gpmc_mem_root; | 244 | static struct resource gpmc_mem_root; |
| 239 | static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; | 245 | static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; |
| @@ -241,8 +247,6 @@ static DEFINE_SPINLOCK(gpmc_mem_lock); | |||
| 241 | /* Define chip-selects as reserved by default until probe completes */ | 247 | /* Define chip-selects as reserved by default until probe completes */ |
| 242 | static unsigned int gpmc_cs_num = GPMC_CS_NUM; | 248 | static unsigned int gpmc_cs_num = GPMC_CS_NUM; |
| 243 | static unsigned int gpmc_nr_waitpins; | 249 | static unsigned int gpmc_nr_waitpins; |
| 244 | static struct device *gpmc_dev; | ||
| 245 | static int gpmc_irq; | ||
| 246 | static resource_size_t phys_base, mem_size; | 250 | static resource_size_t phys_base, mem_size; |
| 247 | static unsigned gpmc_capability; | 251 | static unsigned gpmc_capability; |
| 248 | static void __iomem *gpmc_base; | 252 | static void __iomem *gpmc_base; |
| @@ -1054,14 +1058,6 @@ int gpmc_configure(int cmd, int wval) | |||
| 1054 | u32 regval; | 1058 | u32 regval; |
| 1055 | 1059 | ||
| 1056 | switch (cmd) { | 1060 | switch (cmd) { |
| 1057 | case GPMC_ENABLE_IRQ: | ||
| 1058 | gpmc_write_reg(GPMC_IRQENABLE, wval); | ||
| 1059 | break; | ||
| 1060 | |||
| 1061 | case GPMC_SET_IRQ_STATUS: | ||
| 1062 | gpmc_write_reg(GPMC_IRQSTATUS, wval); | ||
| 1063 | break; | ||
| 1064 | |||
| 1065 | case GPMC_CONFIG_WP: | 1061 | case GPMC_CONFIG_WP: |
| 1066 | regval = gpmc_read_reg(GPMC_CONFIG); | 1062 | regval = gpmc_read_reg(GPMC_CONFIG); |
| 1067 | if (wval) | 1063 | if (wval) |
| @@ -1084,7 +1080,7 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) | |||
| 1084 | { | 1080 | { |
| 1085 | int i; | 1081 | int i; |
| 1086 | 1082 | ||
| 1087 | reg->gpmc_status = gpmc_base + GPMC_STATUS; | 1083 | reg->gpmc_status = NULL; /* deprecated */ |
| 1088 | reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + | 1084 | reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + |
| 1089 | GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; | 1085 | GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; |
| 1090 | reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET + | 1086 | reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET + |
| @@ -1118,87 +1114,201 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) | |||
| 1118 | } | 1114 | } |
| 1119 | } | 1115 | } |
| 1120 | 1116 | ||
| 1121 | int gpmc_get_client_irq(unsigned irq_config) | 1117 | static bool gpmc_nand_writebuffer_empty(void) |
| 1122 | { | 1118 | { |
| 1123 | int i; | 1119 | if (gpmc_read_reg(GPMC_STATUS) & GPMC_STATUS_EMPTYWRITEBUFFERSTATUS) |
| 1120 | return true; | ||
| 1124 | 1121 | ||
| 1125 | if (hweight32(irq_config) > 1) | 1122 | return false; |
| 1123 | } | ||
| 1124 | |||
| 1125 | static struct gpmc_nand_ops nand_ops = { | ||
| 1126 | .nand_writebuffer_empty = gpmc_nand_writebuffer_empty, | ||
| 1127 | }; | ||
| 1128 | |||
| 1129 | /** | ||
| 1130 | * gpmc_omap_get_nand_ops - Get the GPMC NAND interface | ||
| 1131 | * @regs: the GPMC NAND register map exclusive for NAND use. | ||
| 1132 | * @cs: GPMC chip select number on which the NAND sits. The | ||
| 1133 | * register map returned will be specific to this chip select. | ||
| 1134 | * | ||
| 1135 | * Returns NULL on error e.g. invalid cs. | ||
| 1136 | */ | ||
| 1137 | struct gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *reg, int cs) | ||
| 1138 | { | ||
| 1139 | if (cs >= gpmc_cs_num) | ||
| 1140 | return NULL; | ||
| 1141 | |||
| 1142 | gpmc_update_nand_reg(reg, cs); | ||
| 1143 | |||
| 1144 | return &nand_ops; | ||
| 1145 | } | ||
| 1146 | EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops); | ||
| 1147 | |||
| 1148 | int gpmc_get_client_irq(unsigned irq_config) | ||
| 1149 | { | ||
| 1150 | if (!gpmc_irq_domain) { | ||
| 1151 | pr_warn("%s called before GPMC IRQ domain available\n", | ||
| 1152 | __func__); | ||
| 1126 | return 0; | 1153 | return 0; |
| 1154 | } | ||
| 1127 | 1155 | ||
| 1128 | for (i = 0; i < GPMC_NR_IRQ; i++) | 1156 | /* we restrict this to NAND IRQs only */ |
| 1129 | if (gpmc_client_irq[i].bitmask & irq_config) | 1157 | if (irq_config >= GPMC_NR_NAND_IRQS) |
| 1130 | return gpmc_client_irq[i].irq; | 1158 | return 0; |
| 1131 | 1159 | ||
| 1132 | return 0; | 1160 | return irq_create_mapping(gpmc_irq_domain, irq_config); |
| 1133 | } | 1161 | } |
| 1134 | 1162 | ||
| 1135 | static int gpmc_irq_endis(unsigned irq, bool endis) | 1163 | static int gpmc_irq_endis(unsigned long hwirq, bool endis) |
| 1136 | { | 1164 | { |
| 1137 | int i; | ||
| 1138 | u32 regval; | 1165 | u32 regval; |
| 1139 | 1166 | ||
| 1140 | for (i = 0; i < GPMC_NR_IRQ; i++) | 1167 | /* bits GPMC_NR_NAND_IRQS to 8 are reserved */ |
| 1141 | if (irq == gpmc_client_irq[i].irq) { | 1168 | if (hwirq >= GPMC_NR_NAND_IRQS) |
| 1142 | regval = gpmc_read_reg(GPMC_IRQENABLE); | 1169 | hwirq += 8 - GPMC_NR_NAND_IRQS; |
| 1143 | if (endis) | 1170 | |
| 1144 | regval |= gpmc_client_irq[i].bitmask; | 1171 | regval = gpmc_read_reg(GPMC_IRQENABLE); |
| 1145 | else | 1172 | if (endis) |
| 1146 | regval &= ~gpmc_client_irq[i].bitmask; | 1173 | regval |= BIT(hwirq); |
| 1147 | gpmc_write_reg(GPMC_IRQENABLE, regval); | 1174 | else |
| 1148 | break; | 1175 | regval &= ~BIT(hwirq); |
| 1149 | } | 1176 | gpmc_write_reg(GPMC_IRQENABLE, regval); |
| 1150 | 1177 | ||
| 1151 | return 0; | 1178 | return 0; |
| 1152 | } | 1179 | } |
| 1153 | 1180 | ||
| 1154 | static void gpmc_irq_disable(struct irq_data *p) | 1181 | static void gpmc_irq_disable(struct irq_data *p) |
| 1155 | { | 1182 | { |
| 1156 | gpmc_irq_endis(p->irq, false); | 1183 | gpmc_irq_endis(p->hwirq, false); |
| 1157 | } | 1184 | } |
| 1158 | 1185 | ||
| 1159 | static void gpmc_irq_enable(struct irq_data *p) | 1186 | static void gpmc_irq_enable(struct irq_data *p) |
| 1160 | { | 1187 | { |
| 1161 | gpmc_irq_endis(p->irq, true); | 1188 | gpmc_irq_endis(p->hwirq, true); |
| 1162 | } | 1189 | } |
| 1163 | 1190 | ||
| 1164 | static void gpmc_irq_noop(struct irq_data *data) { } | 1191 | static void gpmc_irq_mask(struct irq_data *d) |
| 1192 | { | ||
| 1193 | gpmc_irq_endis(d->hwirq, false); | ||
| 1194 | } | ||
| 1165 | 1195 | ||
| 1166 | static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } | 1196 | static void gpmc_irq_unmask(struct irq_data *d) |
| 1197 | { | ||
| 1198 | gpmc_irq_endis(d->hwirq, true); | ||
| 1199 | } | ||
| 1167 | 1200 | ||
| 1168 | static int gpmc_setup_irq(void) | 1201 | static void gpmc_irq_edge_config(unsigned long hwirq, bool rising_edge) |
| 1169 | { | 1202 | { |
| 1170 | int i; | ||
| 1171 | u32 regval; | 1203 | u32 regval; |
| 1172 | 1204 | ||
| 1173 | if (!gpmc_irq) | 1205 | /* NAND IRQs polarity is not configurable */ |
| 1206 | if (hwirq < GPMC_NR_NAND_IRQS) | ||
| 1207 | return; | ||
| 1208 | |||
| 1209 | /* WAITPIN starts at BIT 8 */ | ||
| 1210 | hwirq += 8 - GPMC_NR_NAND_IRQS; | ||
| 1211 | |||
| 1212 | regval = gpmc_read_reg(GPMC_CONFIG); | ||
| 1213 | if (rising_edge) | ||
| 1214 | regval &= ~BIT(hwirq); | ||
| 1215 | else | ||
| 1216 | regval |= BIT(hwirq); | ||
| 1217 | |||
| 1218 | gpmc_write_reg(GPMC_CONFIG, regval); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | static void gpmc_irq_ack(struct irq_data *d) | ||
| 1222 | { | ||
| 1223 | unsigned int hwirq = d->hwirq; | ||
| 1224 | |||
| 1225 | /* skip reserved bits */ | ||
| 1226 | if (hwirq >= GPMC_NR_NAND_IRQS) | ||
| 1227 | hwirq += 8 - GPMC_NR_NAND_IRQS; | ||
| 1228 | |||
| 1229 | /* Setting bit to 1 clears (or Acks) the interrupt */ | ||
| 1230 | gpmc_write_reg(GPMC_IRQSTATUS, BIT(hwirq)); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | static int gpmc_irq_set_type(struct irq_data *d, unsigned int trigger) | ||
| 1234 | { | ||
| 1235 | /* can't set type for NAND IRQs */ | ||
| 1236 | if (d->hwirq < GPMC_NR_NAND_IRQS) | ||
| 1174 | return -EINVAL; | 1237 | return -EINVAL; |
| 1175 | 1238 | ||
| 1176 | gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); | 1239 | /* We can support either rising or falling edge at a time */ |
| 1177 | if (gpmc_irq_start < 0) { | 1240 | if (trigger == IRQ_TYPE_EDGE_FALLING) |
| 1178 | pr_err("irq_alloc_descs failed\n"); | 1241 | gpmc_irq_edge_config(d->hwirq, false); |
| 1179 | return gpmc_irq_start; | 1242 | else if (trigger == IRQ_TYPE_EDGE_RISING) |
| 1243 | gpmc_irq_edge_config(d->hwirq, true); | ||
| 1244 | else | ||
| 1245 | return -EINVAL; | ||
| 1246 | |||
| 1247 | return 0; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | static int gpmc_irq_map(struct irq_domain *d, unsigned int virq, | ||
| 1251 | irq_hw_number_t hw) | ||
| 1252 | { | ||
| 1253 | struct gpmc_device *gpmc = d->host_data; | ||
| 1254 | |||
| 1255 | irq_set_chip_data(virq, gpmc); | ||
| 1256 | if (hw < GPMC_NR_NAND_IRQS) { | ||
| 1257 | irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOAUTOEN); | ||
| 1258 | irq_set_chip_and_handler(virq, &gpmc->irq_chip, | ||
| 1259 | handle_simple_irq); | ||
| 1260 | } else { | ||
| 1261 | irq_set_chip_and_handler(virq, &gpmc->irq_chip, | ||
| 1262 | handle_edge_irq); | ||
| 1180 | } | 1263 | } |
| 1181 | 1264 | ||
| 1182 | gpmc_irq_chip.name = "gpmc"; | 1265 | return 0; |
| 1183 | gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; | 1266 | } |
| 1184 | gpmc_irq_chip.irq_enable = gpmc_irq_enable; | 1267 | |
| 1185 | gpmc_irq_chip.irq_disable = gpmc_irq_disable; | 1268 | static const struct irq_domain_ops gpmc_irq_domain_ops = { |
| 1186 | gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; | 1269 | .map = gpmc_irq_map, |
| 1187 | gpmc_irq_chip.irq_ack = gpmc_irq_noop; | 1270 | .xlate = irq_domain_xlate_twocell, |
| 1188 | gpmc_irq_chip.irq_mask = gpmc_irq_noop; | 1271 | }; |
| 1189 | gpmc_irq_chip.irq_unmask = gpmc_irq_noop; | 1272 | |
| 1190 | 1273 | static irqreturn_t gpmc_handle_irq(int irq, void *data) | |
| 1191 | gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; | 1274 | { |
| 1192 | gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; | 1275 | int hwirq, virq; |
| 1193 | 1276 | u32 regval, regvalx; | |
| 1194 | for (i = 0; i < GPMC_NR_IRQ; i++) { | 1277 | struct gpmc_device *gpmc = data; |
| 1195 | gpmc_client_irq[i].irq = gpmc_irq_start + i; | 1278 | |
| 1196 | irq_set_chip_and_handler(gpmc_client_irq[i].irq, | 1279 | regval = gpmc_read_reg(GPMC_IRQSTATUS); |
| 1197 | &gpmc_irq_chip, handle_simple_irq); | 1280 | regvalx = regval; |
| 1198 | irq_modify_status(gpmc_client_irq[i].irq, IRQ_NOREQUEST, | 1281 | |
| 1199 | IRQ_NOAUTOEN); | 1282 | if (!regval) |
| 1283 | return IRQ_NONE; | ||
| 1284 | |||
| 1285 | for (hwirq = 0; hwirq < gpmc->nirqs; hwirq++) { | ||
| 1286 | /* skip reserved status bits */ | ||
| 1287 | if (hwirq == GPMC_NR_NAND_IRQS) | ||
| 1288 | regvalx >>= 8 - GPMC_NR_NAND_IRQS; | ||
| 1289 | |||
| 1290 | if (regvalx & BIT(hwirq)) { | ||
| 1291 | virq = irq_find_mapping(gpmc_irq_domain, hwirq); | ||
| 1292 | if (!virq) { | ||
| 1293 | dev_warn(gpmc->dev, | ||
| 1294 | "spurious irq detected hwirq %d, virq %d\n", | ||
| 1295 | hwirq, virq); | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | generic_handle_irq(virq); | ||
| 1299 | } | ||
| 1200 | } | 1300 | } |
| 1201 | 1301 | ||
| 1302 | gpmc_write_reg(GPMC_IRQSTATUS, regval); | ||
| 1303 | |||
| 1304 | return IRQ_HANDLED; | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | static int gpmc_setup_irq(struct gpmc_device *gpmc) | ||
| 1308 | { | ||
| 1309 | u32 regval; | ||
| 1310 | int rc; | ||
| 1311 | |||
| 1202 | /* Disable interrupts */ | 1312 | /* Disable interrupts */ |
| 1203 | gpmc_write_reg(GPMC_IRQENABLE, 0); | 1313 | gpmc_write_reg(GPMC_IRQENABLE, 0); |
| 1204 | 1314 | ||
| @@ -1206,22 +1316,45 @@ static int gpmc_setup_irq(void) | |||
| 1206 | regval = gpmc_read_reg(GPMC_IRQSTATUS); | 1316 | regval = gpmc_read_reg(GPMC_IRQSTATUS); |
| 1207 | gpmc_write_reg(GPMC_IRQSTATUS, regval); | 1317 | gpmc_write_reg(GPMC_IRQSTATUS, regval); |
| 1208 | 1318 | ||
| 1209 | return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL); | 1319 | gpmc->irq_chip.name = "gpmc"; |
| 1320 | gpmc->irq_chip.irq_enable = gpmc_irq_enable; | ||
| 1321 | gpmc->irq_chip.irq_disable = gpmc_irq_disable; | ||
| 1322 | gpmc->irq_chip.irq_ack = gpmc_irq_ack; | ||
| 1323 | gpmc->irq_chip.irq_mask = gpmc_irq_mask; | ||
| 1324 | gpmc->irq_chip.irq_unmask = gpmc_irq_unmask; | ||
| 1325 | gpmc->irq_chip.irq_set_type = gpmc_irq_set_type; | ||
| 1326 | |||
| 1327 | gpmc_irq_domain = irq_domain_add_linear(gpmc->dev->of_node, | ||
| 1328 | gpmc->nirqs, | ||
| 1329 | &gpmc_irq_domain_ops, | ||
| 1330 | gpmc); | ||
| 1331 | if (!gpmc_irq_domain) { | ||
| 1332 | dev_err(gpmc->dev, "IRQ domain add failed\n"); | ||
| 1333 | return -ENODEV; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | rc = request_irq(gpmc->irq, gpmc_handle_irq, 0, "gpmc", gpmc); | ||
| 1337 | if (rc) { | ||
| 1338 | dev_err(gpmc->dev, "failed to request irq %d: %d\n", | ||
| 1339 | gpmc->irq, rc); | ||
| 1340 | irq_domain_remove(gpmc_irq_domain); | ||
| 1341 | gpmc_irq_domain = NULL; | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | return rc; | ||
| 1210 | } | 1345 | } |
| 1211 | 1346 | ||
| 1212 | static int gpmc_free_irq(void) | 1347 | static int gpmc_free_irq(struct gpmc_device *gpmc) |
| 1213 | { | 1348 | { |
| 1214 | int i; | 1349 | int hwirq; |
| 1215 | 1350 | ||
| 1216 | if (gpmc_irq) | 1351 | free_irq(gpmc->irq, gpmc); |
| 1217 | free_irq(gpmc_irq, NULL); | ||
| 1218 | 1352 | ||
| 1219 | for (i = 0; i < GPMC_NR_IRQ; i++) { | 1353 | for (hwirq = 0; hwirq < gpmc->nirqs; hwirq++) |
| 1220 | irq_set_handler(gpmc_client_irq[i].irq, NULL); | 1354 | irq_dispose_mapping(irq_find_mapping(gpmc_irq_domain, hwirq)); |
| 1221 | irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip); | ||
| 1222 | } | ||
| 1223 | 1355 | ||
| 1224 | irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ); | 1356 | irq_domain_remove(gpmc_irq_domain); |
| 1357 | gpmc_irq_domain = NULL; | ||
| 1225 | 1358 | ||
| 1226 | return 0; | 1359 | return 0; |
| 1227 | } | 1360 | } |
| @@ -1242,12 +1375,7 @@ static void gpmc_mem_init(void) | |||
| 1242 | { | 1375 | { |
| 1243 | int cs; | 1376 | int cs; |
| 1244 | 1377 | ||
| 1245 | /* | 1378 | gpmc_mem_root.start = GPMC_MEM_START; |
| 1246 | * The first 1MB of GPMC address space is typically mapped to | ||
| 1247 | * the internal ROM. Never allocate the first page, to | ||
| 1248 | * facilitate bug detection; even if we didn't boot from ROM. | ||
| 1249 | */ | ||
| 1250 | gpmc_mem_root.start = SZ_1M; | ||
| 1251 | gpmc_mem_root.end = GPMC_MEM_END; | 1379 | gpmc_mem_root.end = GPMC_MEM_END; |
| 1252 | 1380 | ||
| 1253 | /* Reserve all regions that has been set up by bootloader */ | 1381 | /* Reserve all regions that has been set up by bootloader */ |
| @@ -1796,105 +1924,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, | |||
| 1796 | of_property_read_bool(np, "gpmc,time-para-granularity"); | 1924 | of_property_read_bool(np, "gpmc,time-para-granularity"); |
| 1797 | } | 1925 | } |
| 1798 | 1926 | ||
| 1799 | #if IS_ENABLED(CONFIG_MTD_NAND) | ||
| 1800 | |||
| 1801 | static const char * const nand_xfer_types[] = { | ||
| 1802 | [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", | ||
| 1803 | [NAND_OMAP_POLLED] = "polled", | ||
| 1804 | [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", | ||
| 1805 | [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", | ||
| 1806 | }; | ||
| 1807 | |||
| 1808 | static int gpmc_probe_nand_child(struct platform_device *pdev, | ||
| 1809 | struct device_node *child) | ||
| 1810 | { | ||
| 1811 | u32 val; | ||
| 1812 | const char *s; | ||
| 1813 | struct gpmc_timings gpmc_t; | ||
| 1814 | struct omap_nand_platform_data *gpmc_nand_data; | ||
| 1815 | |||
| 1816 | if (of_property_read_u32(child, "reg", &val) < 0) { | ||
| 1817 | dev_err(&pdev->dev, "%s has no 'reg' property\n", | ||
| 1818 | child->full_name); | ||
| 1819 | return -ENODEV; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data), | ||
| 1823 | GFP_KERNEL); | ||
| 1824 | if (!gpmc_nand_data) | ||
| 1825 | return -ENOMEM; | ||
| 1826 | |||
| 1827 | gpmc_nand_data->cs = val; | ||
| 1828 | gpmc_nand_data->of_node = child; | ||
| 1829 | |||
| 1830 | /* Detect availability of ELM module */ | ||
| 1831 | gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); | ||
| 1832 | if (gpmc_nand_data->elm_of_node == NULL) | ||
| 1833 | gpmc_nand_data->elm_of_node = | ||
| 1834 | of_parse_phandle(child, "elm_id", 0); | ||
| 1835 | |||
| 1836 | /* select ecc-scheme for NAND */ | ||
| 1837 | if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { | ||
| 1838 | pr_err("%s: ti,nand-ecc-opt not found\n", __func__); | ||
| 1839 | return -ENODEV; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | if (!strcmp(s, "sw")) | ||
| 1843 | gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW; | ||
| 1844 | else if (!strcmp(s, "ham1") || | ||
| 1845 | !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) | ||
| 1846 | gpmc_nand_data->ecc_opt = | ||
| 1847 | OMAP_ECC_HAM1_CODE_HW; | ||
| 1848 | else if (!strcmp(s, "bch4")) | ||
| 1849 | if (gpmc_nand_data->elm_of_node) | ||
| 1850 | gpmc_nand_data->ecc_opt = | ||
| 1851 | OMAP_ECC_BCH4_CODE_HW; | ||
| 1852 | else | ||
| 1853 | gpmc_nand_data->ecc_opt = | ||
| 1854 | OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; | ||
| 1855 | else if (!strcmp(s, "bch8")) | ||
| 1856 | if (gpmc_nand_data->elm_of_node) | ||
| 1857 | gpmc_nand_data->ecc_opt = | ||
| 1858 | OMAP_ECC_BCH8_CODE_HW; | ||
| 1859 | else | ||
| 1860 | gpmc_nand_data->ecc_opt = | ||
| 1861 | OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; | ||
| 1862 | else if (!strcmp(s, "bch16")) | ||
| 1863 | if (gpmc_nand_data->elm_of_node) | ||
| 1864 | gpmc_nand_data->ecc_opt = | ||
| 1865 | OMAP_ECC_BCH16_CODE_HW; | ||
| 1866 | else | ||
| 1867 | pr_err("%s: BCH16 requires ELM support\n", __func__); | ||
| 1868 | else | ||
| 1869 | pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__); | ||
| 1870 | |||
| 1871 | /* select data transfer mode for NAND controller */ | ||
| 1872 | if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) | ||
| 1873 | for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) | ||
| 1874 | if (!strcasecmp(s, nand_xfer_types[val])) { | ||
| 1875 | gpmc_nand_data->xfer_type = val; | ||
| 1876 | break; | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child); | ||
| 1880 | |||
| 1881 | val = of_get_nand_bus_width(child); | ||
| 1882 | if (val == 16) | ||
| 1883 | gpmc_nand_data->devsize = NAND_BUSWIDTH_16; | ||
| 1884 | |||
| 1885 | gpmc_read_timings_dt(child, &gpmc_t); | ||
| 1886 | gpmc_nand_init(gpmc_nand_data, &gpmc_t); | ||
| 1887 | |||
| 1888 | return 0; | ||
| 1889 | } | ||
| 1890 | #else | ||
| 1891 | static int gpmc_probe_nand_child(struct platform_device *pdev, | ||
| 1892 | struct device_node *child) | ||
| 1893 | { | ||
| 1894 | return 0; | ||
| 1895 | } | ||
| 1896 | #endif | ||
| 1897 | |||
| 1898 | #if IS_ENABLED(CONFIG_MTD_ONENAND) | 1927 | #if IS_ENABLED(CONFIG_MTD_ONENAND) |
| 1899 | static int gpmc_probe_onenand_child(struct platform_device *pdev, | 1928 | static int gpmc_probe_onenand_child(struct platform_device *pdev, |
| 1900 | struct device_node *child) | 1929 | struct device_node *child) |
| @@ -1950,6 +1979,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
| 1950 | const char *name; | 1979 | const char *name; |
| 1951 | int ret, cs; | 1980 | int ret, cs; |
| 1952 | u32 val; | 1981 | u32 val; |
| 1982 | struct gpio_desc *waitpin_desc = NULL; | ||
| 1983 | struct gpmc_device *gpmc = platform_get_drvdata(pdev); | ||
| 1953 | 1984 | ||
| 1954 | if (of_property_read_u32(child, "reg", &cs) < 0) { | 1985 | if (of_property_read_u32(child, "reg", &cs) < 0) { |
| 1955 | dev_err(&pdev->dev, "%s has no 'reg' property\n", | 1986 | dev_err(&pdev->dev, "%s has no 'reg' property\n", |
| @@ -2010,23 +2041,80 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
| 2010 | if (ret < 0) { | 2041 | if (ret < 0) { |
| 2011 | dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n", | 2042 | dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n", |
| 2012 | cs, &res.start); | 2043 | cs, &res.start); |
| 2044 | if (res.start < GPMC_MEM_START) { | ||
| 2045 | dev_info(&pdev->dev, | ||
| 2046 | "GPMC CS %d start cannot be lesser than 0x%x\n", | ||
| 2047 | cs, GPMC_MEM_START); | ||
| 2048 | } else if (res.end > GPMC_MEM_END) { | ||
| 2049 | dev_info(&pdev->dev, | ||
| 2050 | "GPMC CS %d end cannot be greater than 0x%x\n", | ||
| 2051 | cs, GPMC_MEM_END); | ||
| 2052 | } | ||
| 2013 | goto err; | 2053 | goto err; |
| 2014 | } | 2054 | } |
| 2015 | 2055 | ||
| 2016 | ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); | 2056 | if (of_node_cmp(child->name, "nand") == 0) { |
| 2017 | if (ret < 0) | 2057 | /* Warn about older DT blobs with no compatible property */ |
| 2018 | goto err; | 2058 | if (!of_property_read_bool(child, "compatible")) { |
| 2059 | dev_warn(&pdev->dev, | ||
| 2060 | "Incompatible NAND node: missing compatible"); | ||
| 2061 | ret = -EINVAL; | ||
| 2062 | goto err; | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | if (of_device_is_compatible(child, "ti,omap2-nand")) { | ||
| 2067 | /* NAND specific setup */ | ||
| 2068 | val = 8; | ||
| 2069 | of_property_read_u32(child, "nand-bus-width", &val); | ||
| 2070 | switch (val) { | ||
| 2071 | case 8: | ||
| 2072 | gpmc_s.device_width = GPMC_DEVWIDTH_8BIT; | ||
| 2073 | break; | ||
| 2074 | case 16: | ||
| 2075 | gpmc_s.device_width = GPMC_DEVWIDTH_16BIT; | ||
| 2076 | break; | ||
| 2077 | default: | ||
| 2078 | dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n", | ||
| 2079 | child->name); | ||
| 2080 | ret = -EINVAL; | ||
| 2081 | goto err; | ||
| 2082 | } | ||
| 2083 | |||
| 2084 | /* disable write protect */ | ||
| 2085 | gpmc_configure(GPMC_CONFIG_WP, 0); | ||
| 2086 | gpmc_s.device_nand = true; | ||
| 2087 | } else { | ||
| 2088 | ret = of_property_read_u32(child, "bank-width", | ||
| 2089 | &gpmc_s.device_width); | ||
| 2090 | if (ret < 0) | ||
| 2091 | goto err; | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | /* Reserve wait pin if it is required and valid */ | ||
| 2095 | if (gpmc_s.wait_on_read || gpmc_s.wait_on_write) { | ||
| 2096 | unsigned int wait_pin = gpmc_s.wait_pin; | ||
| 2097 | |||
| 2098 | waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip, | ||
| 2099 | wait_pin, "WAITPIN"); | ||
| 2100 | if (IS_ERR(waitpin_desc)) { | ||
| 2101 | dev_err(&pdev->dev, "invalid wait-pin: %d\n", wait_pin); | ||
| 2102 | ret = PTR_ERR(waitpin_desc); | ||
| 2103 | goto err; | ||
| 2104 | } | ||
| 2105 | } | ||
| 2019 | 2106 | ||
| 2020 | gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings"); | 2107 | gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings"); |
| 2108 | |||
| 2021 | ret = gpmc_cs_program_settings(cs, &gpmc_s); | 2109 | ret = gpmc_cs_program_settings(cs, &gpmc_s); |
| 2022 | if (ret < 0) | 2110 | if (ret < 0) |
| 2023 | goto err; | 2111 | goto err_cs; |
| 2024 | 2112 | ||
| 2025 | ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s); | 2113 | ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s); |
| 2026 | if (ret) { | 2114 | if (ret) { |
| 2027 | dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n", | 2115 | dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n", |
| 2028 | child->name); | 2116 | child->name); |
| 2029 | goto err; | 2117 | goto err_cs; |
| 2030 | } | 2118 | } |
| 2031 | 2119 | ||
| 2032 | /* Clear limited address i.e. enable A26-A11 */ | 2120 | /* Clear limited address i.e. enable A26-A11 */ |
| @@ -2057,16 +2145,81 @@ err_child_fail: | |||
| 2057 | dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name); | 2145 | dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name); |
| 2058 | ret = -ENODEV; | 2146 | ret = -ENODEV; |
| 2059 | 2147 | ||
| 2148 | err_cs: | ||
| 2149 | if (waitpin_desc) | ||
| 2150 | gpiochip_free_own_desc(waitpin_desc); | ||
| 2151 | |||
| 2060 | err: | 2152 | err: |
| 2061 | gpmc_cs_free(cs); | 2153 | gpmc_cs_free(cs); |
| 2062 | 2154 | ||
| 2063 | return ret; | 2155 | return ret; |
| 2064 | } | 2156 | } |
| 2065 | 2157 | ||
| 2158 | static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) | ||
| 2159 | { | ||
| 2160 | return 1; /* we're input only */ | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | static int gpmc_gpio_direction_input(struct gpio_chip *chip, | ||
| 2164 | unsigned int offset) | ||
| 2165 | { | ||
| 2166 | return 0; /* we're input only */ | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | static int gpmc_gpio_direction_output(struct gpio_chip *chip, | ||
| 2170 | unsigned int offset, int value) | ||
| 2171 | { | ||
| 2172 | return -EINVAL; /* we're input only */ | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
| 2176 | int value) | ||
| 2177 | { | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
| 2181 | { | ||
| 2182 | u32 reg; | ||
| 2183 | |||
| 2184 | offset += 8; | ||
| 2185 | |||
| 2186 | reg = gpmc_read_reg(GPMC_STATUS) & BIT(offset); | ||
| 2187 | |||
| 2188 | return !!reg; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | static int gpmc_gpio_init(struct gpmc_device *gpmc) | ||
| 2192 | { | ||
| 2193 | int ret; | ||
| 2194 | |||
| 2195 | gpmc->gpio_chip.parent = gpmc->dev; | ||
| 2196 | gpmc->gpio_chip.owner = THIS_MODULE; | ||
| 2197 | gpmc->gpio_chip.label = DEVICE_NAME; | ||
| 2198 | gpmc->gpio_chip.ngpio = gpmc_nr_waitpins; | ||
| 2199 | gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction; | ||
| 2200 | gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input; | ||
| 2201 | gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output; | ||
| 2202 | gpmc->gpio_chip.set = gpmc_gpio_set; | ||
| 2203 | gpmc->gpio_chip.get = gpmc_gpio_get; | ||
| 2204 | gpmc->gpio_chip.base = -1; | ||
| 2205 | |||
| 2206 | ret = gpiochip_add(&gpmc->gpio_chip); | ||
| 2207 | if (ret < 0) { | ||
| 2208 | dev_err(gpmc->dev, "could not register gpio chip: %d\n", ret); | ||
| 2209 | return ret; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | return 0; | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | static void gpmc_gpio_exit(struct gpmc_device *gpmc) | ||
| 2216 | { | ||
| 2217 | gpiochip_remove(&gpmc->gpio_chip); | ||
| 2218 | } | ||
| 2219 | |||
| 2066 | static int gpmc_probe_dt(struct platform_device *pdev) | 2220 | static int gpmc_probe_dt(struct platform_device *pdev) |
| 2067 | { | 2221 | { |
| 2068 | int ret; | 2222 | int ret; |
| 2069 | struct device_node *child; | ||
| 2070 | const struct of_device_id *of_id = | 2223 | const struct of_device_id *of_id = |
| 2071 | of_match_device(gpmc_dt_ids, &pdev->dev); | 2224 | of_match_device(gpmc_dt_ids, &pdev->dev); |
| 2072 | 2225 | ||
| @@ -2094,17 +2247,26 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
| 2094 | return ret; | 2247 | return ret; |
| 2095 | } | 2248 | } |
| 2096 | 2249 | ||
| 2250 | return 0; | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | static int gpmc_probe_dt_children(struct platform_device *pdev) | ||
| 2254 | { | ||
| 2255 | int ret; | ||
| 2256 | struct device_node *child; | ||
| 2257 | |||
| 2097 | for_each_available_child_of_node(pdev->dev.of_node, child) { | 2258 | for_each_available_child_of_node(pdev->dev.of_node, child) { |
| 2098 | 2259 | ||
| 2099 | if (!child->name) | 2260 | if (!child->name) |
| 2100 | continue; | 2261 | continue; |
| 2101 | 2262 | ||
| 2102 | if (of_node_cmp(child->name, "nand") == 0) | 2263 | if (of_node_cmp(child->name, "onenand") == 0) |
| 2103 | ret = gpmc_probe_nand_child(pdev, child); | ||
| 2104 | else if (of_node_cmp(child->name, "onenand") == 0) | ||
| 2105 | ret = gpmc_probe_onenand_child(pdev, child); | 2264 | ret = gpmc_probe_onenand_child(pdev, child); |
| 2106 | else | 2265 | else |
| 2107 | ret = gpmc_probe_generic_child(pdev, child); | 2266 | ret = gpmc_probe_generic_child(pdev, child); |
| 2267 | |||
| 2268 | if (ret) | ||
| 2269 | return ret; | ||
| 2108 | } | 2270 | } |
| 2109 | 2271 | ||
| 2110 | return 0; | 2272 | return 0; |
| @@ -2114,6 +2276,11 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
| 2114 | { | 2276 | { |
| 2115 | return 0; | 2277 | return 0; |
| 2116 | } | 2278 | } |
| 2279 | |||
| 2280 | static int gpmc_probe_dt_children(struct platform_device *pdev) | ||
| 2281 | { | ||
| 2282 | return 0; | ||
| 2283 | } | ||
| 2117 | #endif | 2284 | #endif |
| 2118 | 2285 | ||
| 2119 | static int gpmc_probe(struct platform_device *pdev) | 2286 | static int gpmc_probe(struct platform_device *pdev) |
| @@ -2121,6 +2288,14 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2121 | int rc; | 2288 | int rc; |
| 2122 | u32 l; | 2289 | u32 l; |
| 2123 | struct resource *res; | 2290 | struct resource *res; |
| 2291 | struct gpmc_device *gpmc; | ||
| 2292 | |||
| 2293 | gpmc = devm_kzalloc(&pdev->dev, sizeof(*gpmc), GFP_KERNEL); | ||
| 2294 | if (!gpmc) | ||
| 2295 | return -ENOMEM; | ||
| 2296 | |||
| 2297 | gpmc->dev = &pdev->dev; | ||
| 2298 | platform_set_drvdata(pdev, gpmc); | ||
| 2124 | 2299 | ||
| 2125 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2300 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2126 | if (res == NULL) | 2301 | if (res == NULL) |
| @@ -2134,15 +2309,16 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2134 | return PTR_ERR(gpmc_base); | 2309 | return PTR_ERR(gpmc_base); |
| 2135 | 2310 | ||
| 2136 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 2311 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 2137 | if (res == NULL) | 2312 | if (!res) { |
| 2138 | dev_warn(&pdev->dev, "Failed to get resource: irq\n"); | 2313 | dev_err(&pdev->dev, "Failed to get resource: irq\n"); |
| 2139 | else | 2314 | return -ENOENT; |
| 2140 | gpmc_irq = res->start; | 2315 | } |
| 2316 | |||
| 2317 | gpmc->irq = res->start; | ||
| 2141 | 2318 | ||
| 2142 | gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); | 2319 | gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); |
| 2143 | if (IS_ERR(gpmc_l3_clk)) { | 2320 | if (IS_ERR(gpmc_l3_clk)) { |
| 2144 | dev_err(&pdev->dev, "Failed to get GPMC fck\n"); | 2321 | dev_err(&pdev->dev, "Failed to get GPMC fck\n"); |
| 2145 | gpmc_irq = 0; | ||
| 2146 | return PTR_ERR(gpmc_l3_clk); | 2322 | return PTR_ERR(gpmc_l3_clk); |
| 2147 | } | 2323 | } |
| 2148 | 2324 | ||
| @@ -2151,11 +2327,18 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2151 | return -EINVAL; | 2327 | return -EINVAL; |
| 2152 | } | 2328 | } |
| 2153 | 2329 | ||
| 2330 | if (pdev->dev.of_node) { | ||
| 2331 | rc = gpmc_probe_dt(pdev); | ||
| 2332 | if (rc) | ||
| 2333 | return rc; | ||
| 2334 | } else { | ||
| 2335 | gpmc_cs_num = GPMC_CS_NUM; | ||
| 2336 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | ||
| 2337 | } | ||
| 2338 | |||
| 2154 | pm_runtime_enable(&pdev->dev); | 2339 | pm_runtime_enable(&pdev->dev); |
| 2155 | pm_runtime_get_sync(&pdev->dev); | 2340 | pm_runtime_get_sync(&pdev->dev); |
| 2156 | 2341 | ||
| 2157 | gpmc_dev = &pdev->dev; | ||
| 2158 | |||
| 2159 | l = gpmc_read_reg(GPMC_REVISION); | 2342 | l = gpmc_read_reg(GPMC_REVISION); |
| 2160 | 2343 | ||
| 2161 | /* | 2344 | /* |
| @@ -2174,36 +2357,51 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2174 | gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; | 2357 | gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; |
| 2175 | if (GPMC_REVISION_MAJOR(l) > 0x5) | 2358 | if (GPMC_REVISION_MAJOR(l) > 0x5) |
| 2176 | gpmc_capability |= GPMC_HAS_MUX_AAD; | 2359 | gpmc_capability |= GPMC_HAS_MUX_AAD; |
| 2177 | dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), | 2360 | dev_info(gpmc->dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), |
| 2178 | GPMC_REVISION_MINOR(l)); | 2361 | GPMC_REVISION_MINOR(l)); |
| 2179 | 2362 | ||
| 2180 | gpmc_mem_init(); | 2363 | gpmc_mem_init(); |
| 2181 | 2364 | rc = gpmc_gpio_init(gpmc); | |
| 2182 | if (gpmc_setup_irq() < 0) | 2365 | if (rc) |
| 2183 | dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); | 2366 | goto gpio_init_failed; |
| 2184 | 2367 | ||
| 2185 | if (!pdev->dev.of_node) { | 2368 | gpmc->nirqs = GPMC_NR_NAND_IRQS + gpmc_nr_waitpins; |
| 2186 | gpmc_cs_num = GPMC_CS_NUM; | 2369 | rc = gpmc_setup_irq(gpmc); |
| 2187 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | 2370 | if (rc) { |
| 2371 | dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); | ||
| 2372 | goto setup_irq_failed; | ||
| 2188 | } | 2373 | } |
| 2189 | 2374 | ||
| 2190 | rc = gpmc_probe_dt(pdev); | 2375 | rc = gpmc_probe_dt_children(pdev); |
| 2191 | if (rc < 0) { | 2376 | if (rc < 0) { |
| 2192 | pm_runtime_put_sync(&pdev->dev); | 2377 | dev_err(gpmc->dev, "failed to probe DT children\n"); |
| 2193 | dev_err(gpmc_dev, "failed to probe DT parameters\n"); | 2378 | goto dt_children_failed; |
| 2194 | return rc; | ||
| 2195 | } | 2379 | } |
| 2196 | 2380 | ||
| 2197 | return 0; | 2381 | return 0; |
| 2382 | |||
| 2383 | dt_children_failed: | ||
| 2384 | gpmc_free_irq(gpmc); | ||
| 2385 | setup_irq_failed: | ||
| 2386 | gpmc_gpio_exit(gpmc); | ||
| 2387 | gpio_init_failed: | ||
| 2388 | gpmc_mem_exit(); | ||
| 2389 | pm_runtime_put_sync(&pdev->dev); | ||
| 2390 | pm_runtime_disable(&pdev->dev); | ||
| 2391 | |||
| 2392 | return rc; | ||
| 2198 | } | 2393 | } |
| 2199 | 2394 | ||
| 2200 | static int gpmc_remove(struct platform_device *pdev) | 2395 | static int gpmc_remove(struct platform_device *pdev) |
| 2201 | { | 2396 | { |
| 2202 | gpmc_free_irq(); | 2397 | struct gpmc_device *gpmc = platform_get_drvdata(pdev); |
| 2398 | |||
| 2399 | gpmc_free_irq(gpmc); | ||
| 2400 | gpmc_gpio_exit(gpmc); | ||
| 2203 | gpmc_mem_exit(); | 2401 | gpmc_mem_exit(); |
| 2204 | pm_runtime_put_sync(&pdev->dev); | 2402 | pm_runtime_put_sync(&pdev->dev); |
| 2205 | pm_runtime_disable(&pdev->dev); | 2403 | pm_runtime_disable(&pdev->dev); |
| 2206 | gpmc_dev = NULL; | 2404 | |
| 2207 | return 0; | 2405 | return 0; |
| 2208 | } | 2406 | } |
| 2209 | 2407 | ||
| @@ -2249,25 +2447,6 @@ static __exit void gpmc_exit(void) | |||
| 2249 | postcore_initcall(gpmc_init); | 2447 | postcore_initcall(gpmc_init); |
| 2250 | module_exit(gpmc_exit); | 2448 | module_exit(gpmc_exit); |
| 2251 | 2449 | ||
| 2252 | static irqreturn_t gpmc_handle_irq(int irq, void *dev) | ||
| 2253 | { | ||
| 2254 | int i; | ||
| 2255 | u32 regval; | ||
| 2256 | |||
| 2257 | regval = gpmc_read_reg(GPMC_IRQSTATUS); | ||
| 2258 | |||
| 2259 | if (!regval) | ||
| 2260 | return IRQ_NONE; | ||
| 2261 | |||
| 2262 | for (i = 0; i < GPMC_NR_IRQ; i++) | ||
| 2263 | if (regval & gpmc_client_irq[i].bitmask) | ||
| 2264 | generic_handle_irq(gpmc_client_irq[i].irq); | ||
| 2265 | |||
| 2266 | gpmc_write_reg(GPMC_IRQSTATUS, regval); | ||
| 2267 | |||
| 2268 | return IRQ_HANDLED; | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | static struct omap3_gpmc_regs gpmc_context; | 2450 | static struct omap3_gpmc_regs gpmc_context; |
| 2272 | 2451 | ||
| 2273 | void omap3_gpmc_save_context(void) | 2452 | void omap3_gpmc_save_context(void) |
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 3b3dabce58de..bbfa1f129266 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
| @@ -115,6 +115,7 @@ config MTD_MAP_BANK_WIDTH_16 | |||
| 115 | 115 | ||
| 116 | config MTD_MAP_BANK_WIDTH_32 | 116 | config MTD_MAP_BANK_WIDTH_32 |
| 117 | bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY | 117 | bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY |
| 118 | select MTD_COMPLEX_MAPPINGS if HAS_IOMEM | ||
| 118 | default n | 119 | default n |
| 119 | help | 120 | help |
| 120 | If you wish to support CFI devices on a physical bus which is | 121 | If you wish to support CFI devices on a physical bus which is |
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 347bb83db864..1c65c15b31a1 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
| 4 | #include <linux/delay.h> | 4 | #include <linux/delay.h> |
| 5 | #include <linux/ioport.h> | ||
| 5 | #include <linux/mtd/mtd.h> | 6 | #include <linux/mtd/mtd.h> |
| 6 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 7 | #include <linux/bcma/bcma.h> | 8 | #include <linux/bcma/bcma.h> |
| @@ -109,8 +110,7 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 109 | if ((from + len) > mtd->size) | 110 | if ((from + len) > mtd->size) |
| 110 | return -EINVAL; | 111 | return -EINVAL; |
| 111 | 112 | ||
| 112 | memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from), | 113 | memcpy_fromio(buf, b47s->window + from, len); |
| 113 | len); | ||
| 114 | *retlen = len; | 114 | *retlen = len; |
| 115 | 115 | ||
| 116 | return len; | 116 | return len; |
| @@ -275,15 +275,33 @@ static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset, | |||
| 275 | 275 | ||
| 276 | static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) | 276 | static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) |
| 277 | { | 277 | { |
| 278 | struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); | 278 | struct device *dev = &pdev->dev; |
| 279 | struct bcma_sflash *sflash = dev_get_platdata(dev); | ||
| 279 | struct bcm47xxsflash *b47s; | 280 | struct bcm47xxsflash *b47s; |
| 281 | struct resource *res; | ||
| 280 | int err; | 282 | int err; |
| 281 | 283 | ||
| 282 | b47s = devm_kzalloc(&pdev->dev, sizeof(*b47s), GFP_KERNEL); | 284 | b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL); |
| 283 | if (!b47s) | 285 | if (!b47s) |
| 284 | return -ENOMEM; | 286 | return -ENOMEM; |
| 285 | sflash->priv = b47s; | 287 | sflash->priv = b47s; |
| 286 | 288 | ||
| 289 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 290 | if (!res) { | ||
| 291 | dev_err(dev, "invalid resource\n"); | ||
| 292 | return -EINVAL; | ||
| 293 | } | ||
| 294 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | ||
| 295 | res->name)) { | ||
| 296 | dev_err(dev, "can't request region for resource %pR\n", res); | ||
| 297 | return -EBUSY; | ||
| 298 | } | ||
| 299 | b47s->window = ioremap_cache(res->start, resource_size(res)); | ||
| 300 | if (!b47s->window) { | ||
| 301 | dev_err(dev, "ioremap failed for resource %pR\n", res); | ||
| 302 | return -ENOMEM; | ||
| 303 | } | ||
| 304 | |||
| 287 | b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash); | 305 | b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash); |
| 288 | b47s->cc_read = bcm47xxsflash_bcma_cc_read; | 306 | b47s->cc_read = bcm47xxsflash_bcma_cc_read; |
| 289 | b47s->cc_write = bcm47xxsflash_bcma_cc_write; | 307 | b47s->cc_write = bcm47xxsflash_bcma_cc_write; |
| @@ -297,7 +315,6 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) | |||
| 297 | break; | 315 | break; |
| 298 | } | 316 | } |
| 299 | 317 | ||
| 300 | b47s->window = sflash->window; | ||
| 301 | b47s->blocksize = sflash->blocksize; | 318 | b47s->blocksize = sflash->blocksize; |
| 302 | b47s->numblocks = sflash->numblocks; | 319 | b47s->numblocks = sflash->numblocks; |
| 303 | b47s->size = sflash->size; | 320 | b47s->size = sflash->size; |
| @@ -306,6 +323,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) | |||
| 306 | err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); | 323 | err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); |
| 307 | if (err) { | 324 | if (err) { |
| 308 | pr_err("Failed to register MTD device: %d\n", err); | 325 | pr_err("Failed to register MTD device: %d\n", err); |
| 326 | iounmap(b47s->window); | ||
| 309 | return err; | 327 | return err; |
| 310 | } | 328 | } |
| 311 | 329 | ||
| @@ -321,6 +339,7 @@ static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) | |||
| 321 | struct bcm47xxsflash *b47s = sflash->priv; | 339 | struct bcm47xxsflash *b47s = sflash->priv; |
| 322 | 340 | ||
| 323 | mtd_device_unregister(&b47s->mtd); | 341 | mtd_device_unregister(&b47s->mtd); |
| 342 | iounmap(b47s->window); | ||
| 324 | 343 | ||
| 325 | return 0; | 344 | return 0; |
| 326 | } | 345 | } |
diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h index fe93daf4f489..1564b62b412e 100644 --- a/drivers/mtd/devices/bcm47xxsflash.h +++ b/drivers/mtd/devices/bcm47xxsflash.h | |||
| @@ -65,7 +65,8 @@ struct bcm47xxsflash { | |||
| 65 | 65 | ||
| 66 | enum bcm47xxsflash_type type; | 66 | enum bcm47xxsflash_type type; |
| 67 | 67 | ||
| 68 | u32 window; | 68 | void __iomem *window; |
| 69 | |||
| 69 | u32 blocksize; | 70 | u32 blocksize; |
| 70 | u16 numblocks; | 71 | u16 numblocks; |
| 71 | u32 size; | 72 | u32 size; |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index e7b2e439696c..b833e6cc684c 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
| @@ -67,16 +67,40 @@ module_param(reliable_mode, uint, 0); | |||
| 67 | MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, " | 67 | MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, " |
| 68 | "2=reliable) : MLC normal operations are in normal mode"); | 68 | "2=reliable) : MLC normal operations are in normal mode"); |
| 69 | 69 | ||
| 70 | /** | 70 | static int docg3_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 71 | * struct docg3_oobinfo - DiskOnChip G3 OOB layout | 71 | struct mtd_oob_region *oobregion) |
| 72 | * @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC) | 72 | { |
| 73 | * @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC) | 73 | if (section) |
| 74 | * @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15 | 74 | return -ERANGE; |
| 75 | */ | 75 | |
| 76 | static struct nand_ecclayout docg3_oobinfo = { | 76 | /* byte 7 is Hamming ECC, byte 8-14 are BCH ECC */ |
| 77 | .eccbytes = 8, | 77 | oobregion->offset = 7; |
| 78 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14}, | 78 | oobregion->length = 8; |
| 79 | .oobfree = {{0, 7}, {15, 1} }, | 79 | |
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int docg3_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 84 | struct mtd_oob_region *oobregion) | ||
| 85 | { | ||
| 86 | if (section > 1) | ||
| 87 | return -ERANGE; | ||
| 88 | |||
| 89 | /* free bytes: byte 0 until byte 6, byte 15 */ | ||
| 90 | if (!section) { | ||
| 91 | oobregion->offset = 0; | ||
| 92 | oobregion->length = 7; | ||
| 93 | } else { | ||
| 94 | oobregion->offset = 15; | ||
| 95 | oobregion->length = 1; | ||
| 96 | } | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static const struct mtd_ooblayout_ops nand_ooblayout_docg3_ops = { | ||
| 102 | .ecc = docg3_ooblayout_ecc, | ||
| 103 | .free = docg3_ooblayout_free, | ||
| 80 | }; | 104 | }; |
| 81 | 105 | ||
| 82 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | 106 | 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) | |||
| 1857 | mtd->_read_oob = doc_read_oob; | 1881 | mtd->_read_oob = doc_read_oob; |
| 1858 | mtd->_write_oob = doc_write_oob; | 1882 | mtd->_write_oob = doc_write_oob; |
| 1859 | mtd->_block_isbad = doc_block_isbad; | 1883 | mtd->_block_isbad = doc_block_isbad; |
| 1860 | mtd->ecclayout = &docg3_oobinfo; | 1884 | mtd_set_ooblayout(mtd, &nand_ooblayout_docg3_ops); |
| 1861 | mtd->oobavail = 8; | 1885 | mtd->oobavail = 8; |
| 1862 | mtd->ecc_strength = DOC_ECC_BCH_T; | 1886 | mtd->ecc_strength = DOC_ECC_BCH_T; |
| 1863 | 1887 | ||
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index c9c3b7fa3051..9d6854467651 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
| @@ -131,6 +131,28 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, | |||
| 131 | /* convert the dummy cycles to the number of bytes */ | 131 | /* convert the dummy cycles to the number of bytes */ |
| 132 | dummy /= 8; | 132 | dummy /= 8; |
| 133 | 133 | ||
| 134 | if (spi_flash_read_supported(spi)) { | ||
| 135 | struct spi_flash_read_message msg; | ||
| 136 | int ret; | ||
| 137 | |||
| 138 | memset(&msg, 0, sizeof(msg)); | ||
| 139 | |||
| 140 | msg.buf = buf; | ||
| 141 | msg.from = from; | ||
| 142 | msg.len = len; | ||
| 143 | msg.read_opcode = nor->read_opcode; | ||
| 144 | msg.addr_width = nor->addr_width; | ||
| 145 | msg.dummy_bytes = dummy; | ||
| 146 | /* TODO: Support other combinations */ | ||
| 147 | msg.opcode_nbits = SPI_NBITS_SINGLE; | ||
| 148 | msg.addr_nbits = SPI_NBITS_SINGLE; | ||
| 149 | msg.data_nbits = m25p80_rx_nbits(nor); | ||
| 150 | |||
| 151 | ret = spi_flash_read(spi, &msg); | ||
| 152 | *retlen = msg.retlen; | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 134 | spi_message_init(&m); | 156 | spi_message_init(&m); |
| 135 | memset(t, 0, (sizeof t)); | 157 | memset(t, 0, (sizeof t)); |
| 136 | 158 | ||
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 708b7e8c8b18..220f9200fa52 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
| @@ -353,7 +353,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 353 | * mechanism | 353 | * mechanism |
| 354 | * returns the size of the memory region found. | 354 | * returns the size of the memory region found. |
| 355 | */ | 355 | */ |
| 356 | static int fixup_pmc551(struct pci_dev *dev) | 356 | static int __init fixup_pmc551(struct pci_dev *dev) |
| 357 | { | 357 | { |
| 358 | #ifdef CONFIG_MTD_PMC551_BUGFIX | 358 | #ifdef CONFIG_MTD_PMC551_BUGFIX |
| 359 | u32 dram_data; | 359 | u32 dram_data; |
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 0455166f05fa..4f206a99164c 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c | |||
| @@ -112,8 +112,8 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | 114 | ||
| 115 | static int ck804xrom_init_one(struct pci_dev *pdev, | 115 | static int __init ck804xrom_init_one(struct pci_dev *pdev, |
| 116 | const struct pci_device_id *ent) | 116 | const struct pci_device_id *ent) |
| 117 | { | 117 | { |
| 118 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 118 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
| 119 | u8 byte; | 119 | u8 byte; |
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 76ed651b515b..9646b0766ce0 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c | |||
| @@ -144,8 +144,8 @@ static void esb2rom_cleanup(struct esb2rom_window *window) | |||
| 144 | pci_dev_put(window->pdev); | 144 | pci_dev_put(window->pdev); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | static int esb2rom_init_one(struct pci_dev *pdev, | 147 | static int __init esb2rom_init_one(struct pci_dev *pdev, |
| 148 | const struct pci_device_id *ent) | 148 | const struct pci_device_id *ent) |
| 149 | { | 149 | { |
| 150 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 150 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
| 151 | struct esb2rom_window *window = &esb2rom_window; | 151 | struct esb2rom_window *window = &esb2rom_window; |
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 8636bba42200..e17d02ae03f0 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c | |||
| @@ -84,8 +84,8 @@ static void ichxrom_cleanup(struct ichxrom_window *window) | |||
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | 86 | ||
| 87 | static int ichxrom_init_one(struct pci_dev *pdev, | 87 | static int __init ichxrom_init_one(struct pci_dev *pdev, |
| 88 | const struct pci_device_id *ent) | 88 | const struct pci_device_id *ent) |
| 89 | { | 89 | { |
| 90 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 90 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
| 91 | struct ichxrom_window *window = &ichxrom_window; | 91 | struct ichxrom_window *window = &ichxrom_window; |
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index c1af83db5202..00a8190797ec 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c | |||
| @@ -4,11 +4,13 @@ | |||
| 4 | * uclinux.c -- generic memory mapped MTD driver for uclinux | 4 | * uclinux.c -- generic memory mapped MTD driver for uclinux |
| 5 | * | 5 | * |
| 6 | * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) | 6 | * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) |
| 7 | * | ||
| 8 | * License: GPL | ||
| 7 | */ | 9 | */ |
| 8 | 10 | ||
| 9 | /****************************************************************************/ | 11 | /****************************************************************************/ |
| 10 | 12 | ||
| 11 | #include <linux/module.h> | 13 | #include <linux/moduleparam.h> |
| 12 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| @@ -117,27 +119,6 @@ static int __init uclinux_mtd_init(void) | |||
| 117 | 119 | ||
| 118 | return(0); | 120 | return(0); |
| 119 | } | 121 | } |
| 120 | 122 | device_initcall(uclinux_mtd_init); | |
| 121 | /****************************************************************************/ | ||
| 122 | |||
| 123 | static void __exit uclinux_mtd_cleanup(void) | ||
| 124 | { | ||
| 125 | if (uclinux_ram_mtdinfo) { | ||
| 126 | mtd_device_unregister(uclinux_ram_mtdinfo); | ||
| 127 | map_destroy(uclinux_ram_mtdinfo); | ||
| 128 | uclinux_ram_mtdinfo = NULL; | ||
| 129 | } | ||
| 130 | if (uclinux_ram_map.virt) | ||
| 131 | uclinux_ram_map.virt = 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | /****************************************************************************/ | ||
| 135 | |||
| 136 | module_init(uclinux_mtd_init); | ||
| 137 | module_exit(uclinux_mtd_cleanup); | ||
| 138 | |||
| 139 | MODULE_LICENSE("GPL"); | ||
| 140 | MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); | ||
| 141 | MODULE_DESCRIPTION("Generic MTD for uClinux"); | ||
| 142 | 123 | ||
| 143 | /****************************************************************************/ | 124 | /****************************************************************************/ |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 6d19835b80a9..2a47a3f0e730 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
| @@ -465,35 +465,108 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd, | |||
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | /* | 467 | /* |
| 468 | * Copies (and truncates, if necessary) data from the larger struct, | 468 | * Copies (and truncates, if necessary) OOB layout information to the |
| 469 | * nand_ecclayout, to the smaller, deprecated layout struct, | 469 | * deprecated layout struct, nand_ecclayout_user. This is necessary only to |
| 470 | * nand_ecclayout_user. This is necessary only to support the deprecated | 470 | * support the deprecated API ioctl ECCGETLAYOUT while allowing all new |
| 471 | * API ioctl ECCGETLAYOUT while allowing all new functionality to use | 471 | * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops |
| 472 | * nand_ecclayout flexibly (i.e. the struct may change size in new | 472 | * can describe any kind of OOB layout with almost zero overhead from a |
| 473 | * releases without requiring major rewrites). | 473 | * memory usage point of view). |
| 474 | */ | 474 | */ |
| 475 | static int shrink_ecclayout(const struct nand_ecclayout *from, | 475 | static int shrink_ecclayout(struct mtd_info *mtd, |
| 476 | struct nand_ecclayout_user *to) | 476 | struct nand_ecclayout_user *to) |
| 477 | { | 477 | { |
| 478 | int i; | 478 | struct mtd_oob_region oobregion; |
| 479 | int i, section = 0, ret; | ||
| 479 | 480 | ||
| 480 | if (!from || !to) | 481 | if (!mtd || !to) |
| 481 | return -EINVAL; | 482 | return -EINVAL; |
| 482 | 483 | ||
| 483 | memset(to, 0, sizeof(*to)); | 484 | memset(to, 0, sizeof(*to)); |
| 484 | 485 | ||
| 485 | to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES); | 486 | to->eccbytes = 0; |
| 486 | for (i = 0; i < to->eccbytes; i++) | 487 | for (i = 0; i < MTD_MAX_ECCPOS_ENTRIES;) { |
| 487 | to->eccpos[i] = from->eccpos[i]; | 488 | u32 eccpos; |
| 489 | |||
| 490 | ret = mtd_ooblayout_ecc(mtd, section, &oobregion); | ||
| 491 | if (ret < 0) { | ||
| 492 | if (ret != -ERANGE) | ||
| 493 | return ret; | ||
| 494 | |||
| 495 | break; | ||
| 496 | } | ||
| 497 | |||
| 498 | eccpos = oobregion.offset; | ||
| 499 | for (; i < MTD_MAX_ECCPOS_ENTRIES && | ||
| 500 | eccpos < oobregion.offset + oobregion.length; i++) { | ||
| 501 | to->eccpos[i] = eccpos++; | ||
| 502 | to->eccbytes++; | ||
| 503 | } | ||
| 504 | } | ||
| 488 | 505 | ||
| 489 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { | 506 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { |
| 490 | if (from->oobfree[i].length == 0 && | 507 | ret = mtd_ooblayout_free(mtd, i, &oobregion); |
| 491 | from->oobfree[i].offset == 0) | 508 | if (ret < 0) { |
| 509 | if (ret != -ERANGE) | ||
| 510 | return ret; | ||
| 511 | |||
| 512 | break; | ||
| 513 | } | ||
| 514 | |||
| 515 | to->oobfree[i].offset = oobregion.offset; | ||
| 516 | to->oobfree[i].length = oobregion.length; | ||
| 517 | to->oobavail += to->oobfree[i].length; | ||
| 518 | } | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to) | ||
| 524 | { | ||
| 525 | struct mtd_oob_region oobregion; | ||
| 526 | int i, section = 0, ret; | ||
| 527 | |||
| 528 | if (!mtd || !to) | ||
| 529 | return -EINVAL; | ||
| 530 | |||
| 531 | memset(to, 0, sizeof(*to)); | ||
| 532 | |||
| 533 | to->eccbytes = 0; | ||
| 534 | for (i = 0; i < ARRAY_SIZE(to->eccpos);) { | ||
| 535 | u32 eccpos; | ||
| 536 | |||
| 537 | ret = mtd_ooblayout_ecc(mtd, section, &oobregion); | ||
| 538 | if (ret < 0) { | ||
| 539 | if (ret != -ERANGE) | ||
| 540 | return ret; | ||
| 541 | |||
| 492 | break; | 542 | break; |
| 493 | to->oobavail += from->oobfree[i].length; | 543 | } |
| 494 | to->oobfree[i] = from->oobfree[i]; | 544 | |
| 545 | if (oobregion.length + i > ARRAY_SIZE(to->eccpos)) | ||
| 546 | return -EINVAL; | ||
| 547 | |||
| 548 | eccpos = oobregion.offset; | ||
| 549 | for (; eccpos < oobregion.offset + oobregion.length; i++) { | ||
| 550 | to->eccpos[i] = eccpos++; | ||
| 551 | to->eccbytes++; | ||
| 552 | } | ||
| 495 | } | 553 | } |
| 496 | 554 | ||
| 555 | for (i = 0; i < 8; i++) { | ||
| 556 | ret = mtd_ooblayout_free(mtd, i, &oobregion); | ||
| 557 | if (ret < 0) { | ||
| 558 | if (ret != -ERANGE) | ||
| 559 | return ret; | ||
| 560 | |||
| 561 | break; | ||
| 562 | } | ||
| 563 | |||
| 564 | to->oobfree[i][0] = oobregion.offset; | ||
| 565 | to->oobfree[i][1] = oobregion.length; | ||
| 566 | } | ||
| 567 | |||
| 568 | to->useecc = MTD_NANDECC_AUTOPLACE; | ||
| 569 | |||
| 497 | return 0; | 570 | return 0; |
| 498 | } | 571 | } |
| 499 | 572 | ||
| @@ -815,16 +888,12 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) | |||
| 815 | { | 888 | { |
| 816 | struct nand_oobinfo oi; | 889 | struct nand_oobinfo oi; |
| 817 | 890 | ||
| 818 | if (!mtd->ecclayout) | 891 | if (!mtd->ooblayout) |
| 819 | return -EOPNOTSUPP; | 892 | return -EOPNOTSUPP; |
| 820 | if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos)) | ||
| 821 | return -EINVAL; | ||
| 822 | 893 | ||
| 823 | oi.useecc = MTD_NANDECC_AUTOPLACE; | 894 | ret = get_oobinfo(mtd, &oi); |
| 824 | memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); | 895 | if (ret) |
| 825 | memcpy(&oi.oobfree, mtd->ecclayout->oobfree, | 896 | return ret; |
| 826 | sizeof(oi.oobfree)); | ||
| 827 | oi.eccbytes = mtd->ecclayout->eccbytes; | ||
| 828 | 897 | ||
| 829 | if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) | 898 | if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) |
| 830 | return -EFAULT; | 899 | return -EFAULT; |
| @@ -913,14 +982,14 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) | |||
| 913 | { | 982 | { |
| 914 | struct nand_ecclayout_user *usrlay; | 983 | struct nand_ecclayout_user *usrlay; |
| 915 | 984 | ||
| 916 | if (!mtd->ecclayout) | 985 | if (!mtd->ooblayout) |
| 917 | return -EOPNOTSUPP; | 986 | return -EOPNOTSUPP; |
| 918 | 987 | ||
| 919 | usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); | 988 | usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); |
| 920 | if (!usrlay) | 989 | if (!usrlay) |
| 921 | return -ENOMEM; | 990 | return -ENOMEM; |
| 922 | 991 | ||
| 923 | shrink_ecclayout(mtd->ecclayout, usrlay); | 992 | shrink_ecclayout(mtd, usrlay); |
| 924 | 993 | ||
| 925 | if (copy_to_user(argp, usrlay, sizeof(*usrlay))) | 994 | if (copy_to_user(argp, usrlay, sizeof(*usrlay))) |
| 926 | ret = -EFAULT; | 995 | ret = -EFAULT; |
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 239a8c806b67..d573606b91c2 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
| @@ -777,7 +777,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
| 777 | 777 | ||
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | concat->mtd.ecclayout = subdev[0]->ecclayout; | 780 | mtd_set_ooblayout(&concat->mtd, subdev[0]->ooblayout); |
| 781 | 781 | ||
| 782 | concat->num_subdev = num_devs; | 782 | concat->num_subdev = num_devs; |
| 783 | concat->mtd.name = name; | 783 | concat->mtd.name = name; |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index bee180bd11e7..e3936b847c6b 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
| @@ -1016,6 +1016,366 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to, | |||
| 1016 | } | 1016 | } |
| 1017 | EXPORT_SYMBOL_GPL(mtd_write_oob); | 1017 | EXPORT_SYMBOL_GPL(mtd_write_oob); |
| 1018 | 1018 | ||
| 1019 | /** | ||
| 1020 | * mtd_ooblayout_ecc - Get the OOB region definition of a specific ECC section | ||
| 1021 | * @mtd: MTD device structure | ||
| 1022 | * @section: ECC section. Depending on the layout you may have all the ECC | ||
| 1023 | * bytes stored in a single contiguous section, or one section | ||
| 1024 | * per ECC chunk (and sometime several sections for a single ECC | ||
| 1025 | * ECC chunk) | ||
| 1026 | * @oobecc: OOB region struct filled with the appropriate ECC position | ||
| 1027 | * information | ||
| 1028 | * | ||
| 1029 | * This functions return ECC section information in the OOB area. I you want | ||
| 1030 | * to get all the ECC bytes information, then you should call | ||
| 1031 | * mtd_ooblayout_ecc(mtd, section++, oobecc) until it returns -ERANGE. | ||
| 1032 | * | ||
| 1033 | * Returns zero on success, a negative error code otherwise. | ||
| 1034 | */ | ||
| 1035 | int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 1036 | struct mtd_oob_region *oobecc) | ||
| 1037 | { | ||
| 1038 | memset(oobecc, 0, sizeof(*oobecc)); | ||
| 1039 | |||
| 1040 | if (!mtd || section < 0) | ||
| 1041 | return -EINVAL; | ||
| 1042 | |||
| 1043 | if (!mtd->ooblayout || !mtd->ooblayout->ecc) | ||
| 1044 | return -ENOTSUPP; | ||
| 1045 | |||
| 1046 | return mtd->ooblayout->ecc(mtd, section, oobecc); | ||
| 1047 | } | ||
| 1048 | EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc); | ||
| 1049 | |||
| 1050 | /** | ||
| 1051 | * mtd_ooblayout_free - Get the OOB region definition of a specific free | ||
| 1052 | * section | ||
| 1053 | * @mtd: MTD device structure | ||
| 1054 | * @section: Free section you are interested in. Depending on the layout | ||
| 1055 | * you may have all the free bytes stored in a single contiguous | ||
| 1056 | * section, or one section per ECC chunk plus an extra section | ||
| 1057 | * for the remaining bytes (or other funky layout). | ||
| 1058 | * @oobfree: OOB region struct filled with the appropriate free position | ||
| 1059 | * information | ||
| 1060 | * | ||
| 1061 | * This functions return free bytes position in the OOB area. I you want | ||
| 1062 | * to get all the free bytes information, then you should call | ||
| 1063 | * mtd_ooblayout_free(mtd, section++, oobfree) until it returns -ERANGE. | ||
| 1064 | * | ||
| 1065 | * Returns zero on success, a negative error code otherwise. | ||
| 1066 | */ | ||
| 1067 | int mtd_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 1068 | struct mtd_oob_region *oobfree) | ||
| 1069 | { | ||
| 1070 | memset(oobfree, 0, sizeof(*oobfree)); | ||
| 1071 | |||
| 1072 | if (!mtd || section < 0) | ||
| 1073 | return -EINVAL; | ||
| 1074 | |||
| 1075 | if (!mtd->ooblayout || !mtd->ooblayout->free) | ||
| 1076 | return -ENOTSUPP; | ||
| 1077 | |||
| 1078 | return mtd->ooblayout->free(mtd, section, oobfree); | ||
| 1079 | } | ||
| 1080 | EXPORT_SYMBOL_GPL(mtd_ooblayout_free); | ||
| 1081 | |||
| 1082 | /** | ||
| 1083 | * mtd_ooblayout_find_region - Find the region attached to a specific byte | ||
| 1084 | * @mtd: mtd info structure | ||
| 1085 | * @byte: the byte we are searching for | ||
| 1086 | * @sectionp: pointer where the section id will be stored | ||
| 1087 | * @oobregion: used to retrieve the ECC position | ||
| 1088 | * @iter: iterator function. Should be either mtd_ooblayout_free or | ||
| 1089 | * mtd_ooblayout_ecc depending on the region type you're searching for | ||
| 1090 | * | ||
| 1091 | * This functions returns the section id and oobregion information of a | ||
| 1092 | * specific byte. For example, say you want to know where the 4th ECC byte is | ||
| 1093 | * stored, you'll use: | ||
| 1094 | * | ||
| 1095 | * mtd_ooblayout_find_region(mtd, 3, §ion, &oobregion, mtd_ooblayout_ecc); | ||
| 1096 | * | ||
| 1097 | * Returns zero on success, a negative error code otherwise. | ||
| 1098 | */ | ||
| 1099 | static int mtd_ooblayout_find_region(struct mtd_info *mtd, int byte, | ||
| 1100 | int *sectionp, struct mtd_oob_region *oobregion, | ||
| 1101 | int (*iter)(struct mtd_info *, | ||
| 1102 | int section, | ||
| 1103 | struct mtd_oob_region *oobregion)) | ||
| 1104 | { | ||
| 1105 | int pos = 0, ret, section = 0; | ||
| 1106 | |||
| 1107 | memset(oobregion, 0, sizeof(*oobregion)); | ||
| 1108 | |||
| 1109 | while (1) { | ||
| 1110 | ret = iter(mtd, section, oobregion); | ||
| 1111 | if (ret) | ||
| 1112 | return ret; | ||
| 1113 | |||
| 1114 | if (pos + oobregion->length > byte) | ||
| 1115 | break; | ||
| 1116 | |||
| 1117 | pos += oobregion->length; | ||
| 1118 | section++; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | /* | ||
| 1122 | * Adjust region info to make it start at the beginning at the | ||
| 1123 | * 'start' ECC byte. | ||
| 1124 | */ | ||
| 1125 | oobregion->offset += byte - pos; | ||
| 1126 | oobregion->length -= byte - pos; | ||
| 1127 | *sectionp = section; | ||
| 1128 | |||
| 1129 | return 0; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | /** | ||
| 1133 | * mtd_ooblayout_find_eccregion - Find the ECC region attached to a specific | ||
| 1134 | * ECC byte | ||
| 1135 | * @mtd: mtd info structure | ||
| 1136 | * @eccbyte: the byte we are searching for | ||
| 1137 | * @sectionp: pointer where the section id will be stored | ||
| 1138 | * @oobregion: OOB region information | ||
| 1139 | * | ||
| 1140 | * Works like mtd_ooblayout_find_region() except it searches for a specific ECC | ||
| 1141 | * byte. | ||
| 1142 | * | ||
| 1143 | * Returns zero on success, a negative error code otherwise. | ||
| 1144 | */ | ||
| 1145 | int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, | ||
| 1146 | int *section, | ||
| 1147 | struct mtd_oob_region *oobregion) | ||
| 1148 | { | ||
| 1149 | return mtd_ooblayout_find_region(mtd, eccbyte, section, oobregion, | ||
| 1150 | mtd_ooblayout_ecc); | ||
| 1151 | } | ||
| 1152 | EXPORT_SYMBOL_GPL(mtd_ooblayout_find_eccregion); | ||
| 1153 | |||
| 1154 | /** | ||
| 1155 | * mtd_ooblayout_get_bytes - Extract OOB bytes from the oob buffer | ||
| 1156 | * @mtd: mtd info structure | ||
| 1157 | * @buf: destination buffer to store OOB bytes | ||
| 1158 | * @oobbuf: OOB buffer | ||
| 1159 | * @start: first byte to retrieve | ||
| 1160 | * @nbytes: number of bytes to retrieve | ||
| 1161 | * @iter: section iterator | ||
| 1162 | * | ||
| 1163 | * Extract bytes attached to a specific category (ECC or free) | ||
| 1164 | * from the OOB buffer and copy them into buf. | ||
| 1165 | * | ||
| 1166 | * Returns zero on success, a negative error code otherwise. | ||
| 1167 | */ | ||
| 1168 | static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf, | ||
| 1169 | const u8 *oobbuf, int start, int nbytes, | ||
| 1170 | int (*iter)(struct mtd_info *, | ||
| 1171 | int section, | ||
| 1172 | struct mtd_oob_region *oobregion)) | ||
| 1173 | { | ||
| 1174 | struct mtd_oob_region oobregion = { }; | ||
| 1175 | int section = 0, ret; | ||
| 1176 | |||
| 1177 | ret = mtd_ooblayout_find_region(mtd, start, §ion, | ||
| 1178 | &oobregion, iter); | ||
| 1179 | |||
| 1180 | while (!ret) { | ||
| 1181 | int cnt; | ||
| 1182 | |||
| 1183 | cnt = oobregion.length > nbytes ? nbytes : oobregion.length; | ||
| 1184 | memcpy(buf, oobbuf + oobregion.offset, cnt); | ||
| 1185 | buf += cnt; | ||
| 1186 | nbytes -= cnt; | ||
| 1187 | |||
| 1188 | if (!nbytes) | ||
| 1189 | break; | ||
| 1190 | |||
| 1191 | ret = iter(mtd, ++section, &oobregion); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | return ret; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | /** | ||
| 1198 | * mtd_ooblayout_set_bytes - put OOB bytes into the oob buffer | ||
| 1199 | * @mtd: mtd info structure | ||
| 1200 | * @buf: source buffer to get OOB bytes from | ||
| 1201 | * @oobbuf: OOB buffer | ||
| 1202 | * @start: first OOB byte to set | ||
| 1203 | * @nbytes: number of OOB bytes to set | ||
| 1204 | * @iter: section iterator | ||
| 1205 | * | ||
| 1206 | * Fill the OOB buffer with data provided in buf. The category (ECC or free) | ||
| 1207 | * is selected by passing the appropriate iterator. | ||
| 1208 | * | ||
| 1209 | * Returns zero on success, a negative error code otherwise. | ||
| 1210 | */ | ||
| 1211 | static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf, | ||
| 1212 | u8 *oobbuf, int start, int nbytes, | ||
| 1213 | int (*iter)(struct mtd_info *, | ||
| 1214 | int section, | ||
| 1215 | struct mtd_oob_region *oobregion)) | ||
| 1216 | { | ||
| 1217 | struct mtd_oob_region oobregion = { }; | ||
| 1218 | int section = 0, ret; | ||
| 1219 | |||
| 1220 | ret = mtd_ooblayout_find_region(mtd, start, §ion, | ||
| 1221 | &oobregion, iter); | ||
| 1222 | |||
| 1223 | while (!ret) { | ||
| 1224 | int cnt; | ||
| 1225 | |||
| 1226 | cnt = oobregion.length > nbytes ? nbytes : oobregion.length; | ||
| 1227 | memcpy(oobbuf + oobregion.offset, buf, cnt); | ||
| 1228 | buf += cnt; | ||
| 1229 | nbytes -= cnt; | ||
| 1230 | |||
| 1231 | if (!nbytes) | ||
| 1232 | break; | ||
| 1233 | |||
| 1234 | ret = iter(mtd, ++section, &oobregion); | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | return ret; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | /** | ||
| 1241 | * mtd_ooblayout_count_bytes - count the number of bytes in a OOB category | ||
| 1242 | * @mtd: mtd info structure | ||
| 1243 | * @iter: category iterator | ||
| 1244 | * | ||
| 1245 | * Count the number of bytes in a given category. | ||
| 1246 | * | ||
| 1247 | * Returns a positive value on success, a negative error code otherwise. | ||
| 1248 | */ | ||
| 1249 | static int mtd_ooblayout_count_bytes(struct mtd_info *mtd, | ||
| 1250 | int (*iter)(struct mtd_info *, | ||
| 1251 | int section, | ||
| 1252 | struct mtd_oob_region *oobregion)) | ||
| 1253 | { | ||
| 1254 | struct mtd_oob_region oobregion = { }; | ||
| 1255 | int section = 0, ret, nbytes = 0; | ||
| 1256 | |||
| 1257 | while (1) { | ||
| 1258 | ret = iter(mtd, section++, &oobregion); | ||
| 1259 | if (ret) { | ||
| 1260 | if (ret == -ERANGE) | ||
| 1261 | ret = nbytes; | ||
| 1262 | break; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | nbytes += oobregion.length; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | return ret; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | /** | ||
| 1272 | * mtd_ooblayout_get_eccbytes - extract ECC bytes from the oob buffer | ||
| 1273 | * @mtd: mtd info structure | ||
| 1274 | * @eccbuf: destination buffer to store ECC bytes | ||
| 1275 | * @oobbuf: OOB buffer | ||
| 1276 | * @start: first ECC byte to retrieve | ||
| 1277 | * @nbytes: number of ECC bytes to retrieve | ||
| 1278 | * | ||
| 1279 | * Works like mtd_ooblayout_get_bytes(), except it acts on ECC bytes. | ||
| 1280 | * | ||
| 1281 | * Returns zero on success, a negative error code otherwise. | ||
| 1282 | */ | ||
| 1283 | int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, | ||
| 1284 | const u8 *oobbuf, int start, int nbytes) | ||
| 1285 | { | ||
| 1286 | return mtd_ooblayout_get_bytes(mtd, eccbuf, oobbuf, start, nbytes, | ||
| 1287 | mtd_ooblayout_ecc); | ||
| 1288 | } | ||
| 1289 | EXPORT_SYMBOL_GPL(mtd_ooblayout_get_eccbytes); | ||
| 1290 | |||
| 1291 | /** | ||
| 1292 | * mtd_ooblayout_set_eccbytes - set ECC bytes into the oob buffer | ||
| 1293 | * @mtd: mtd info structure | ||
| 1294 | * @eccbuf: source buffer to get ECC bytes from | ||
| 1295 | * @oobbuf: OOB buffer | ||
| 1296 | * @start: first ECC byte to set | ||
| 1297 | * @nbytes: number of ECC bytes to set | ||
| 1298 | * | ||
| 1299 | * Works like mtd_ooblayout_set_bytes(), except it acts on ECC bytes. | ||
| 1300 | * | ||
| 1301 | * Returns zero on success, a negative error code otherwise. | ||
| 1302 | */ | ||
| 1303 | int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, | ||
| 1304 | u8 *oobbuf, int start, int nbytes) | ||
| 1305 | { | ||
| 1306 | return mtd_ooblayout_set_bytes(mtd, eccbuf, oobbuf, start, nbytes, | ||
| 1307 | mtd_ooblayout_ecc); | ||
| 1308 | } | ||
| 1309 | EXPORT_SYMBOL_GPL(mtd_ooblayout_set_eccbytes); | ||
| 1310 | |||
| 1311 | /** | ||
| 1312 | * mtd_ooblayout_get_databytes - extract data bytes from the oob buffer | ||
| 1313 | * @mtd: mtd info structure | ||
| 1314 | * @databuf: destination buffer to store ECC bytes | ||
| 1315 | * @oobbuf: OOB buffer | ||
| 1316 | * @start: first ECC byte to retrieve | ||
| 1317 | * @nbytes: number of ECC bytes to retrieve | ||
| 1318 | * | ||
| 1319 | * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes. | ||
| 1320 | * | ||
| 1321 | * Returns zero on success, a negative error code otherwise. | ||
| 1322 | */ | ||
| 1323 | int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, | ||
| 1324 | const u8 *oobbuf, int start, int nbytes) | ||
| 1325 | { | ||
| 1326 | return mtd_ooblayout_get_bytes(mtd, databuf, oobbuf, start, nbytes, | ||
| 1327 | mtd_ooblayout_free); | ||
| 1328 | } | ||
| 1329 | EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes); | ||
| 1330 | |||
| 1331 | /** | ||
| 1332 | * mtd_ooblayout_get_eccbytes - set data bytes into the oob buffer | ||
| 1333 | * @mtd: mtd info structure | ||
| 1334 | * @eccbuf: source buffer to get data bytes from | ||
| 1335 | * @oobbuf: OOB buffer | ||
| 1336 | * @start: first ECC byte to set | ||
| 1337 | * @nbytes: number of ECC bytes to set | ||
| 1338 | * | ||
| 1339 | * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes. | ||
| 1340 | * | ||
| 1341 | * Returns zero on success, a negative error code otherwise. | ||
| 1342 | */ | ||
| 1343 | int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, | ||
| 1344 | u8 *oobbuf, int start, int nbytes) | ||
| 1345 | { | ||
| 1346 | return mtd_ooblayout_set_bytes(mtd, databuf, oobbuf, start, nbytes, | ||
| 1347 | mtd_ooblayout_free); | ||
| 1348 | } | ||
| 1349 | EXPORT_SYMBOL_GPL(mtd_ooblayout_set_databytes); | ||
| 1350 | |||
| 1351 | /** | ||
| 1352 | * mtd_ooblayout_count_freebytes - count the number of free bytes in OOB | ||
| 1353 | * @mtd: mtd info structure | ||
| 1354 | * | ||
| 1355 | * Works like mtd_ooblayout_count_bytes(), except it count free bytes. | ||
| 1356 | * | ||
| 1357 | * Returns zero on success, a negative error code otherwise. | ||
| 1358 | */ | ||
| 1359 | int mtd_ooblayout_count_freebytes(struct mtd_info *mtd) | ||
| 1360 | { | ||
| 1361 | return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_free); | ||
| 1362 | } | ||
| 1363 | EXPORT_SYMBOL_GPL(mtd_ooblayout_count_freebytes); | ||
| 1364 | |||
| 1365 | /** | ||
| 1366 | * mtd_ooblayout_count_freebytes - count the number of ECC bytes in OOB | ||
| 1367 | * @mtd: mtd info structure | ||
| 1368 | * | ||
| 1369 | * Works like mtd_ooblayout_count_bytes(), except it count ECC bytes. | ||
| 1370 | * | ||
| 1371 | * Returns zero on success, a negative error code otherwise. | ||
| 1372 | */ | ||
| 1373 | int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd) | ||
| 1374 | { | ||
| 1375 | return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_ecc); | ||
| 1376 | } | ||
| 1377 | EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes); | ||
| 1378 | |||
| 1019 | /* | 1379 | /* |
| 1020 | * Method to access the protection register area, present in some flash | 1380 | * Method to access the protection register area, present in some flash |
| 1021 | * devices. The user data is one time programmable but the factory data is read | 1381 | * devices. The user data is one time programmable but the factory data is read |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 08de4b2cf0f5..1f13e32556f8 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
| @@ -317,6 +317,27 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
| 317 | return res; | 317 | return res; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int part_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 321 | struct mtd_oob_region *oobregion) | ||
| 322 | { | ||
| 323 | struct mtd_part *part = mtd_to_part(mtd); | ||
| 324 | |||
| 325 | return mtd_ooblayout_ecc(part->master, section, oobregion); | ||
| 326 | } | ||
| 327 | |||
| 328 | static int part_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 329 | struct mtd_oob_region *oobregion) | ||
| 330 | { | ||
| 331 | struct mtd_part *part = mtd_to_part(mtd); | ||
| 332 | |||
| 333 | return mtd_ooblayout_free(part->master, section, oobregion); | ||
| 334 | } | ||
| 335 | |||
| 336 | static const struct mtd_ooblayout_ops part_ooblayout_ops = { | ||
| 337 | .ecc = part_ooblayout_ecc, | ||
| 338 | .free = part_ooblayout_free, | ||
| 339 | }; | ||
| 340 | |||
| 320 | static inline void free_partition(struct mtd_part *p) | 341 | static inline void free_partition(struct mtd_part *p) |
| 321 | { | 342 | { |
| 322 | kfree(p->mtd.name); | 343 | kfree(p->mtd.name); |
| @@ -533,7 +554,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
| 533 | part->name); | 554 | part->name); |
| 534 | } | 555 | } |
| 535 | 556 | ||
| 536 | slave->mtd.ecclayout = master->ecclayout; | 557 | mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); |
| 537 | slave->mtd.ecc_step_size = master->ecc_step_size; | 558 | slave->mtd.ecc_step_size = master->ecc_step_size; |
| 538 | slave->mtd.ecc_strength = master->ecc_strength; | 559 | slave->mtd.ecc_strength = master->ecc_strength; |
| 539 | slave->mtd.bitflip_threshold = master->bitflip_threshold; | 560 | slave->mtd.bitflip_threshold = master->bitflip_threshold; |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 68b58c85789c..78e12cc8bac2 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
| @@ -224,6 +224,7 @@ static int ams_delta_init(struct platform_device *pdev) | |||
| 224 | /* 25 us command delay time */ | 224 | /* 25 us command delay time */ |
| 225 | this->chip_delay = 30; | 225 | this->chip_delay = 30; |
| 226 | this->ecc.mode = NAND_ECC_SOFT; | 226 | this->ecc.mode = NAND_ECC_SOFT; |
| 227 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 227 | 228 | ||
| 228 | platform_set_drvdata(pdev, io_base); | 229 | platform_set_drvdata(pdev, io_base); |
| 229 | 230 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 20cbaabb2959..efc8ea250c1d 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
| 37 | #include <linux/of_device.h> | 37 | #include <linux/of_device.h> |
| 38 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
| 39 | #include <linux/of_mtd.h> | ||
| 40 | #include <linux/mtd/mtd.h> | 39 | #include <linux/mtd/mtd.h> |
| 41 | #include <linux/mtd/nand.h> | 40 | #include <linux/mtd/nand.h> |
| 42 | #include <linux/mtd/partitions.h> | 41 | #include <linux/mtd/partitions.h> |
| @@ -72,30 +71,44 @@ struct atmel_nand_nfc_caps { | |||
| 72 | uint32_t rb_mask; | 71 | uint32_t rb_mask; |
| 73 | }; | 72 | }; |
| 74 | 73 | ||
| 75 | /* oob layout for large page size | 74 | /* |
| 75 | * oob layout for large page size | ||
| 76 | * bad block info is on bytes 0 and 1 | 76 | * bad block info is on bytes 0 and 1 |
| 77 | * the bytes have to be consecutives to avoid | 77 | * the bytes have to be consecutives to avoid |
| 78 | * several NAND_CMD_RNDOUT during read | 78 | * several NAND_CMD_RNDOUT during read |
| 79 | */ | 79 | * |
| 80 | static struct nand_ecclayout atmel_oobinfo_large = { | 80 | * oob layout for small page size |
| 81 | .eccbytes = 4, | ||
| 82 | .eccpos = {60, 61, 62, 63}, | ||
| 83 | .oobfree = { | ||
| 84 | {2, 58} | ||
| 85 | }, | ||
| 86 | }; | ||
| 87 | |||
| 88 | /* oob layout for small page size | ||
| 89 | * bad block info is on bytes 4 and 5 | 81 | * bad block info is on bytes 4 and 5 |
| 90 | * the bytes have to be consecutives to avoid | 82 | * the bytes have to be consecutives to avoid |
| 91 | * several NAND_CMD_RNDOUT during read | 83 | * several NAND_CMD_RNDOUT during read |
| 92 | */ | 84 | */ |
| 93 | static struct nand_ecclayout atmel_oobinfo_small = { | 85 | static int atmel_ooblayout_ecc_sp(struct mtd_info *mtd, int section, |
| 94 | .eccbytes = 4, | 86 | struct mtd_oob_region *oobregion) |
| 95 | .eccpos = {0, 1, 2, 3}, | 87 | { |
| 96 | .oobfree = { | 88 | if (section) |
| 97 | {6, 10} | 89 | return -ERANGE; |
| 98 | }, | 90 | |
| 91 | oobregion->length = 4; | ||
| 92 | oobregion->offset = 0; | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int atmel_ooblayout_free_sp(struct mtd_info *mtd, int section, | ||
| 98 | struct mtd_oob_region *oobregion) | ||
| 99 | { | ||
| 100 | if (section) | ||
| 101 | return -ERANGE; | ||
| 102 | |||
| 103 | oobregion->offset = 6; | ||
| 104 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static const struct mtd_ooblayout_ops atmel_ooblayout_sp_ops = { | ||
| 110 | .ecc = atmel_ooblayout_ecc_sp, | ||
| 111 | .free = atmel_ooblayout_free_sp, | ||
| 99 | }; | 112 | }; |
| 100 | 113 | ||
| 101 | struct atmel_nfc { | 114 | struct atmel_nfc { |
| @@ -163,8 +176,6 @@ struct atmel_nand_host { | |||
| 163 | int *pmecc_delta; | 176 | int *pmecc_delta; |
| 164 | }; | 177 | }; |
| 165 | 178 | ||
| 166 | static struct nand_ecclayout atmel_pmecc_oobinfo; | ||
| 167 | |||
| 168 | /* | 179 | /* |
| 169 | * Enable NAND. | 180 | * Enable NAND. |
| 170 | */ | 181 | */ |
| @@ -434,14 +445,13 @@ err_buf: | |||
| 434 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | 445 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) |
| 435 | { | 446 | { |
| 436 | struct nand_chip *chip = mtd_to_nand(mtd); | 447 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 437 | struct atmel_nand_host *host = nand_get_controller_data(chip); | ||
| 438 | 448 | ||
| 439 | if (use_dma && len > mtd->oobsize) | 449 | if (use_dma && len > mtd->oobsize) |
| 440 | /* only use DMA for bigger than oob size: better performances */ | 450 | /* only use DMA for bigger than oob size: better performances */ |
| 441 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) | 451 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) |
| 442 | return; | 452 | return; |
| 443 | 453 | ||
| 444 | if (host->board.bus_width_16) | 454 | if (chip->options & NAND_BUSWIDTH_16) |
| 445 | atmel_read_buf16(mtd, buf, len); | 455 | atmel_read_buf16(mtd, buf, len); |
| 446 | else | 456 | else |
| 447 | atmel_read_buf8(mtd, buf, len); | 457 | atmel_read_buf8(mtd, buf, len); |
| @@ -450,14 +460,13 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
| 450 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | 460 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) |
| 451 | { | 461 | { |
| 452 | struct nand_chip *chip = mtd_to_nand(mtd); | 462 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 453 | struct atmel_nand_host *host = nand_get_controller_data(chip); | ||
| 454 | 463 | ||
| 455 | if (use_dma && len > mtd->oobsize) | 464 | if (use_dma && len > mtd->oobsize) |
| 456 | /* only use DMA for bigger than oob size: better performances */ | 465 | /* only use DMA for bigger than oob size: better performances */ |
| 457 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) | 466 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) |
| 458 | return; | 467 | return; |
| 459 | 468 | ||
| 460 | if (host->board.bus_width_16) | 469 | if (chip->options & NAND_BUSWIDTH_16) |
| 461 | atmel_write_buf16(mtd, buf, len); | 470 | atmel_write_buf16(mtd, buf, len); |
| 462 | else | 471 | else |
| 463 | atmel_write_buf8(mtd, buf, len); | 472 | atmel_write_buf8(mtd, buf, len); |
| @@ -483,22 +492,6 @@ static int pmecc_get_ecc_bytes(int cap, int sector_size) | |||
| 483 | return (m * cap + 7) / 8; | 492 | return (m * cap + 7) / 8; |
| 484 | } | 493 | } |
| 485 | 494 | ||
| 486 | static void pmecc_config_ecc_layout(struct nand_ecclayout *layout, | ||
| 487 | int oobsize, int ecc_len) | ||
| 488 | { | ||
| 489 | int i; | ||
| 490 | |||
| 491 | layout->eccbytes = ecc_len; | ||
| 492 | |||
| 493 | /* ECC will occupy the last ecc_len bytes continuously */ | ||
| 494 | for (i = 0; i < ecc_len; i++) | ||
| 495 | layout->eccpos[i] = oobsize - ecc_len + i; | ||
| 496 | |||
| 497 | layout->oobfree[0].offset = PMECC_OOB_RESERVED_BYTES; | ||
| 498 | layout->oobfree[0].length = | ||
| 499 | oobsize - ecc_len - layout->oobfree[0].offset; | ||
| 500 | } | ||
| 501 | |||
| 502 | static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) | 495 | static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) |
| 503 | { | 496 | { |
| 504 | int table_size; | 497 | int table_size; |
| @@ -836,13 +829,16 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, | |||
| 836 | dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | 829 | dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", |
| 837 | pos, bit_pos, err_byte, *(buf + byte_pos)); | 830 | pos, bit_pos, err_byte, *(buf + byte_pos)); |
| 838 | } else { | 831 | } else { |
| 832 | struct mtd_oob_region oobregion; | ||
| 833 | |||
| 839 | /* Bit flip in OOB area */ | 834 | /* Bit flip in OOB area */ |
| 840 | tmp = sector_num * nand_chip->ecc.bytes | 835 | tmp = sector_num * nand_chip->ecc.bytes |
| 841 | + (byte_pos - sector_size); | 836 | + (byte_pos - sector_size); |
| 842 | err_byte = ecc[tmp]; | 837 | err_byte = ecc[tmp]; |
| 843 | ecc[tmp] ^= (1 << bit_pos); | 838 | ecc[tmp] ^= (1 << bit_pos); |
| 844 | 839 | ||
| 845 | pos = tmp + nand_chip->ecc.layout->eccpos[0]; | 840 | mtd_ooblayout_ecc(mtd, 0, &oobregion); |
| 841 | pos = tmp + oobregion.offset; | ||
| 846 | dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | 842 | dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", |
| 847 | pos, bit_pos, err_byte, ecc[tmp]); | 843 | pos, bit_pos, err_byte, ecc[tmp]); |
| 848 | } | 844 | } |
| @@ -863,17 +859,6 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
| 863 | uint8_t *buf_pos; | 859 | uint8_t *buf_pos; |
| 864 | int max_bitflips = 0; | 860 | int max_bitflips = 0; |
| 865 | 861 | ||
| 866 | /* If can correct bitfilps from erased page, do the normal check */ | ||
| 867 | if (host->caps->pmecc_correct_erase_page) | ||
| 868 | goto normal_check; | ||
| 869 | |||
| 870 | for (i = 0; i < nand_chip->ecc.total; i++) | ||
| 871 | if (ecc[i] != 0xff) | ||
| 872 | goto normal_check; | ||
| 873 | /* Erased page, return OK */ | ||
| 874 | return 0; | ||
| 875 | |||
| 876 | normal_check: | ||
| 877 | for (i = 0; i < nand_chip->ecc.steps; i++) { | 862 | for (i = 0; i < nand_chip->ecc.steps; i++) { |
| 878 | err_nbr = 0; | 863 | err_nbr = 0; |
| 879 | if (pmecc_stat & 0x1) { | 864 | if (pmecc_stat & 0x1) { |
| @@ -884,16 +869,30 @@ normal_check: | |||
| 884 | pmecc_get_sigma(mtd); | 869 | pmecc_get_sigma(mtd); |
| 885 | 870 | ||
| 886 | err_nbr = pmecc_err_location(mtd); | 871 | err_nbr = pmecc_err_location(mtd); |
| 887 | if (err_nbr == -1) { | 872 | if (err_nbr >= 0) { |
| 873 | pmecc_correct_data(mtd, buf_pos, ecc, i, | ||
| 874 | nand_chip->ecc.bytes, | ||
| 875 | err_nbr); | ||
| 876 | } else if (!host->caps->pmecc_correct_erase_page) { | ||
| 877 | u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes); | ||
| 878 | |||
| 879 | /* Try to detect erased pages */ | ||
| 880 | err_nbr = nand_check_erased_ecc_chunk(buf_pos, | ||
| 881 | host->pmecc_sector_size, | ||
| 882 | ecc_pos, | ||
| 883 | nand_chip->ecc.bytes, | ||
| 884 | NULL, 0, | ||
| 885 | nand_chip->ecc.strength); | ||
| 886 | } | ||
| 887 | |||
| 888 | if (err_nbr < 0) { | ||
| 888 | dev_err(host->dev, "PMECC: Too many errors\n"); | 889 | dev_err(host->dev, "PMECC: Too many errors\n"); |
| 889 | mtd->ecc_stats.failed++; | 890 | mtd->ecc_stats.failed++; |
| 890 | return -EIO; | 891 | return -EIO; |
| 891 | } else { | ||
| 892 | pmecc_correct_data(mtd, buf_pos, ecc, i, | ||
| 893 | nand_chip->ecc.bytes, err_nbr); | ||
| 894 | mtd->ecc_stats.corrected += err_nbr; | ||
| 895 | max_bitflips = max_t(int, max_bitflips, err_nbr); | ||
| 896 | } | 892 | } |
| 893 | |||
| 894 | mtd->ecc_stats.corrected += err_nbr; | ||
| 895 | max_bitflips = max_t(int, max_bitflips, err_nbr); | ||
| 897 | } | 896 | } |
| 898 | pmecc_stat >>= 1; | 897 | pmecc_stat >>= 1; |
| 899 | } | 898 | } |
| @@ -931,7 +930,6 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
| 931 | struct atmel_nand_host *host = nand_get_controller_data(chip); | 930 | struct atmel_nand_host *host = nand_get_controller_data(chip); |
| 932 | int eccsize = chip->ecc.size * chip->ecc.steps; | 931 | int eccsize = chip->ecc.size * chip->ecc.steps; |
| 933 | uint8_t *oob = chip->oob_poi; | 932 | uint8_t *oob = chip->oob_poi; |
| 934 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 935 | uint32_t stat; | 933 | uint32_t stat; |
| 936 | unsigned long end_time; | 934 | unsigned long end_time; |
| 937 | int bitflips = 0; | 935 | int bitflips = 0; |
| @@ -953,7 +951,11 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
| 953 | 951 | ||
| 954 | stat = pmecc_readl_relaxed(host->ecc, ISR); | 952 | stat = pmecc_readl_relaxed(host->ecc, ISR); |
| 955 | if (stat != 0) { | 953 | if (stat != 0) { |
| 956 | bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); | 954 | struct mtd_oob_region oobregion; |
| 955 | |||
| 956 | mtd_ooblayout_ecc(mtd, 0, &oobregion); | ||
| 957 | bitflips = pmecc_correction(mtd, stat, buf, | ||
| 958 | &oob[oobregion.offset]); | ||
| 957 | if (bitflips < 0) | 959 | if (bitflips < 0) |
| 958 | /* uncorrectable errors */ | 960 | /* uncorrectable errors */ |
| 959 | return 0; | 961 | return 0; |
| @@ -967,8 +969,8 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | |||
| 967 | int page) | 969 | int page) |
| 968 | { | 970 | { |
| 969 | struct atmel_nand_host *host = nand_get_controller_data(chip); | 971 | struct atmel_nand_host *host = nand_get_controller_data(chip); |
| 970 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 972 | struct mtd_oob_region oobregion = { }; |
| 971 | int i, j; | 973 | int i, j, section = 0; |
| 972 | unsigned long end_time; | 974 | unsigned long end_time; |
| 973 | 975 | ||
| 974 | if (!host->nfc || !host->nfc->write_by_sram) { | 976 | if (!host->nfc || !host->nfc->write_by_sram) { |
| @@ -987,11 +989,14 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | |||
| 987 | 989 | ||
| 988 | for (i = 0; i < chip->ecc.steps; i++) { | 990 | for (i = 0; i < chip->ecc.steps; i++) { |
| 989 | for (j = 0; j < chip->ecc.bytes; j++) { | 991 | for (j = 0; j < chip->ecc.bytes; j++) { |
| 990 | int pos; | 992 | if (!oobregion.length) |
| 993 | mtd_ooblayout_ecc(mtd, section, &oobregion); | ||
| 991 | 994 | ||
| 992 | pos = i * chip->ecc.bytes + j; | 995 | chip->oob_poi[oobregion.offset] = |
| 993 | chip->oob_poi[eccpos[pos]] = | ||
| 994 | pmecc_readb_ecc_relaxed(host->ecc, i, j); | 996 | pmecc_readb_ecc_relaxed(host->ecc, i, j); |
| 997 | oobregion.length--; | ||
| 998 | oobregion.offset++; | ||
| 999 | section++; | ||
| 995 | } | 1000 | } |
| 996 | } | 1001 | } |
| 997 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 1002 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
| @@ -1003,8 +1008,9 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) | |||
| 1003 | { | 1008 | { |
| 1004 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | 1009 | struct nand_chip *nand_chip = mtd_to_nand(mtd); |
| 1005 | struct atmel_nand_host *host = nand_get_controller_data(nand_chip); | 1010 | struct atmel_nand_host *host = nand_get_controller_data(nand_chip); |
| 1011 | int eccbytes = mtd_ooblayout_count_eccbytes(mtd); | ||
| 1006 | uint32_t val = 0; | 1012 | uint32_t val = 0; |
| 1007 | struct nand_ecclayout *ecc_layout; | 1013 | struct mtd_oob_region oobregion; |
| 1008 | 1014 | ||
| 1009 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | 1015 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); |
| 1010 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 1016 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); |
| @@ -1054,11 +1060,11 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) | |||
| 1054 | | PMECC_CFG_AUTO_DISABLE); | 1060 | | PMECC_CFG_AUTO_DISABLE); |
| 1055 | pmecc_writel(host->ecc, CFG, val); | 1061 | pmecc_writel(host->ecc, CFG, val); |
| 1056 | 1062 | ||
| 1057 | ecc_layout = nand_chip->ecc.layout; | ||
| 1058 | pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); | 1063 | pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); |
| 1059 | pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]); | 1064 | mtd_ooblayout_ecc(mtd, 0, &oobregion); |
| 1065 | pmecc_writel(host->ecc, SADDR, oobregion.offset); | ||
| 1060 | pmecc_writel(host->ecc, EADDR, | 1066 | pmecc_writel(host->ecc, EADDR, |
| 1061 | ecc_layout->eccpos[ecc_layout->eccbytes - 1]); | 1067 | oobregion.offset + eccbytes - 1); |
| 1062 | /* See datasheet about PMECC Clock Control Register */ | 1068 | /* See datasheet about PMECC Clock Control Register */ |
| 1063 | pmecc_writel(host->ecc, CLK, 2); | 1069 | pmecc_writel(host->ecc, CLK, 2); |
| 1064 | pmecc_writel(host->ecc, IDR, 0xff); | 1070 | pmecc_writel(host->ecc, IDR, 0xff); |
| @@ -1206,6 +1212,7 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
| 1206 | dev_warn(host->dev, | 1212 | dev_warn(host->dev, |
| 1207 | "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n"); | 1213 | "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n"); |
| 1208 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1214 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
| 1215 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1209 | return 0; | 1216 | return 0; |
| 1210 | } | 1217 | } |
| 1211 | 1218 | ||
| @@ -1280,11 +1287,8 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
| 1280 | err_no = -EINVAL; | 1287 | err_no = -EINVAL; |
| 1281 | goto err; | 1288 | goto err; |
| 1282 | } | 1289 | } |
| 1283 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, | ||
| 1284 | mtd->oobsize, | ||
| 1285 | nand_chip->ecc.total); | ||
| 1286 | 1290 | ||
| 1287 | nand_chip->ecc.layout = &atmel_pmecc_oobinfo; | 1291 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 1288 | break; | 1292 | break; |
| 1289 | default: | 1293 | default: |
| 1290 | dev_warn(host->dev, | 1294 | dev_warn(host->dev, |
| @@ -1292,6 +1296,7 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
| 1292 | /* page size not handled by HW ECC */ | 1296 | /* page size not handled by HW ECC */ |
| 1293 | /* switching back to soft ECC */ | 1297 | /* switching back to soft ECC */ |
| 1294 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1298 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
| 1299 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1295 | return 0; | 1300 | return 0; |
| 1296 | } | 1301 | } |
| 1297 | 1302 | ||
| @@ -1359,12 +1364,12 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1359 | { | 1364 | { |
| 1360 | int eccsize = chip->ecc.size; | 1365 | int eccsize = chip->ecc.size; |
| 1361 | int eccbytes = chip->ecc.bytes; | 1366 | int eccbytes = chip->ecc.bytes; |
| 1362 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1363 | uint8_t *p = buf; | 1367 | uint8_t *p = buf; |
| 1364 | uint8_t *oob = chip->oob_poi; | 1368 | uint8_t *oob = chip->oob_poi; |
| 1365 | uint8_t *ecc_pos; | 1369 | uint8_t *ecc_pos; |
| 1366 | int stat; | 1370 | int stat; |
| 1367 | unsigned int max_bitflips = 0; | 1371 | unsigned int max_bitflips = 0; |
| 1372 | struct mtd_oob_region oobregion = {}; | ||
| 1368 | 1373 | ||
| 1369 | /* | 1374 | /* |
| 1370 | * Errata: ALE is incorrectly wired up to the ECC controller | 1375 | * Errata: ALE is incorrectly wired up to the ECC controller |
| @@ -1382,19 +1387,20 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1382 | chip->read_buf(mtd, p, eccsize); | 1387 | chip->read_buf(mtd, p, eccsize); |
| 1383 | 1388 | ||
| 1384 | /* move to ECC position if needed */ | 1389 | /* move to ECC position if needed */ |
| 1385 | if (eccpos[0] != 0) { | 1390 | mtd_ooblayout_ecc(mtd, 0, &oobregion); |
| 1386 | /* This only works on large pages | 1391 | if (oobregion.offset != 0) { |
| 1387 | * because the ECC controller waits for | 1392 | /* |
| 1388 | * NAND_CMD_RNDOUTSTART after the | 1393 | * This only works on large pages because the ECC controller |
| 1389 | * NAND_CMD_RNDOUT. | 1394 | * waits for NAND_CMD_RNDOUTSTART after the NAND_CMD_RNDOUT. |
| 1390 | * anyway, for small pages, the eccpos[0] == 0 | 1395 | * Anyway, for small pages, the first ECC byte is at offset |
| 1396 | * 0 in the OOB area. | ||
| 1391 | */ | 1397 | */ |
| 1392 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | 1398 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
| 1393 | mtd->writesize + eccpos[0], -1); | 1399 | mtd->writesize + oobregion.offset, -1); |
| 1394 | } | 1400 | } |
| 1395 | 1401 | ||
| 1396 | /* the ECC controller needs to read the ECC just after the data */ | 1402 | /* the ECC controller needs to read the ECC just after the data */ |
| 1397 | ecc_pos = oob + eccpos[0]; | 1403 | ecc_pos = oob + oobregion.offset; |
| 1398 | chip->read_buf(mtd, ecc_pos, eccbytes); | 1404 | chip->read_buf(mtd, ecc_pos, eccbytes); |
| 1399 | 1405 | ||
| 1400 | /* check if there's an error */ | 1406 | /* check if there's an error */ |
| @@ -1504,58 +1510,17 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
| 1504 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1510 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
| 1505 | } | 1511 | } |
| 1506 | 1512 | ||
| 1507 | static int atmel_of_init_port(struct atmel_nand_host *host, | 1513 | static int atmel_of_init_ecc(struct atmel_nand_host *host, |
| 1508 | struct device_node *np) | 1514 | struct device_node *np) |
| 1509 | { | 1515 | { |
| 1510 | u32 val; | ||
| 1511 | u32 offset[2]; | 1516 | u32 offset[2]; |
| 1512 | int ecc_mode; | 1517 | u32 val; |
| 1513 | struct atmel_nand_data *board = &host->board; | ||
| 1514 | enum of_gpio_flags flags = 0; | ||
| 1515 | |||
| 1516 | host->caps = (struct atmel_nand_caps *) | ||
| 1517 | of_device_get_match_data(host->dev); | ||
| 1518 | |||
| 1519 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | ||
| 1520 | if (val >= 32) { | ||
| 1521 | dev_err(host->dev, "invalid addr-offset %u\n", val); | ||
| 1522 | return -EINVAL; | ||
| 1523 | } | ||
| 1524 | board->ale = val; | ||
| 1525 | } | ||
| 1526 | |||
| 1527 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { | ||
| 1528 | if (val >= 32) { | ||
| 1529 | dev_err(host->dev, "invalid cmd-offset %u\n", val); | ||
| 1530 | return -EINVAL; | ||
| 1531 | } | ||
| 1532 | board->cle = val; | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | ecc_mode = of_get_nand_ecc_mode(np); | ||
| 1536 | |||
| 1537 | board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; | ||
| 1538 | |||
| 1539 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); | ||
| 1540 | |||
| 1541 | board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma"); | ||
| 1542 | |||
| 1543 | if (of_get_nand_bus_width(np) == 16) | ||
| 1544 | board->bus_width_16 = 1; | ||
| 1545 | |||
| 1546 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); | ||
| 1547 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); | ||
| 1548 | |||
| 1549 | board->enable_pin = of_get_gpio(np, 1); | ||
| 1550 | board->det_pin = of_get_gpio(np, 2); | ||
| 1551 | 1518 | ||
| 1552 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); | 1519 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); |
| 1553 | 1520 | ||
| 1554 | /* load the nfc driver if there is */ | 1521 | /* Not using PMECC */ |
| 1555 | of_platform_populate(np, NULL, NULL, host->dev); | 1522 | if (!(host->nand_chip.ecc.mode == NAND_ECC_HW) || !host->has_pmecc) |
| 1556 | 1523 | return 0; | |
| 1557 | if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) | ||
| 1558 | return 0; /* Not using PMECC */ | ||
| 1559 | 1524 | ||
| 1560 | /* use PMECC, get correction capability, sector size and lookup | 1525 | /* use PMECC, get correction capability, sector size and lookup |
| 1561 | * table offset. | 1526 | * table offset. |
| @@ -1596,16 +1561,65 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
| 1596 | /* Will build a lookup table and initialize the offset later */ | 1561 | /* Will build a lookup table and initialize the offset later */ |
| 1597 | return 0; | 1562 | return 0; |
| 1598 | } | 1563 | } |
| 1564 | |||
| 1599 | if (!offset[0] && !offset[1]) { | 1565 | if (!offset[0] && !offset[1]) { |
| 1600 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); | 1566 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); |
| 1601 | return -EINVAL; | 1567 | return -EINVAL; |
| 1602 | } | 1568 | } |
| 1569 | |||
| 1603 | host->pmecc_lookup_table_offset_512 = offset[0]; | 1570 | host->pmecc_lookup_table_offset_512 = offset[0]; |
| 1604 | host->pmecc_lookup_table_offset_1024 = offset[1]; | 1571 | host->pmecc_lookup_table_offset_1024 = offset[1]; |
| 1605 | 1572 | ||
| 1606 | return 0; | 1573 | return 0; |
| 1607 | } | 1574 | } |
| 1608 | 1575 | ||
| 1576 | static int atmel_of_init_port(struct atmel_nand_host *host, | ||
| 1577 | struct device_node *np) | ||
| 1578 | { | ||
| 1579 | u32 val; | ||
| 1580 | struct atmel_nand_data *board = &host->board; | ||
| 1581 | enum of_gpio_flags flags = 0; | ||
| 1582 | |||
| 1583 | host->caps = (struct atmel_nand_caps *) | ||
| 1584 | of_device_get_match_data(host->dev); | ||
| 1585 | |||
| 1586 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | ||
| 1587 | if (val >= 32) { | ||
| 1588 | dev_err(host->dev, "invalid addr-offset %u\n", val); | ||
| 1589 | return -EINVAL; | ||
| 1590 | } | ||
| 1591 | board->ale = val; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { | ||
| 1595 | if (val >= 32) { | ||
| 1596 | dev_err(host->dev, "invalid cmd-offset %u\n", val); | ||
| 1597 | return -EINVAL; | ||
| 1598 | } | ||
| 1599 | board->cle = val; | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma"); | ||
| 1603 | |||
| 1604 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); | ||
| 1605 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); | ||
| 1606 | |||
| 1607 | board->enable_pin = of_get_gpio(np, 1); | ||
| 1608 | board->det_pin = of_get_gpio(np, 2); | ||
| 1609 | |||
| 1610 | /* load the nfc driver if there is */ | ||
| 1611 | of_platform_populate(np, NULL, NULL, host->dev); | ||
| 1612 | |||
| 1613 | /* | ||
| 1614 | * Initialize ECC mode to NAND_ECC_SOFT so that we have a correct value | ||
| 1615 | * even if the nand-ecc-mode property is not defined. | ||
| 1616 | */ | ||
| 1617 | host->nand_chip.ecc.mode = NAND_ECC_SOFT; | ||
| 1618 | host->nand_chip.ecc.algo = NAND_ECC_HAMMING; | ||
| 1619 | |||
| 1620 | return 0; | ||
| 1621 | } | ||
| 1622 | |||
| 1609 | static int atmel_hw_nand_init_params(struct platform_device *pdev, | 1623 | static int atmel_hw_nand_init_params(struct platform_device *pdev, |
| 1610 | struct atmel_nand_host *host) | 1624 | struct atmel_nand_host *host) |
| 1611 | { | 1625 | { |
| @@ -1618,6 +1632,7 @@ static int atmel_hw_nand_init_params(struct platform_device *pdev, | |||
| 1618 | dev_err(host->dev, | 1632 | dev_err(host->dev, |
| 1619 | "Can't get I/O resource regs, use software ECC\n"); | 1633 | "Can't get I/O resource regs, use software ECC\n"); |
| 1620 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1634 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
| 1635 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1621 | return 0; | 1636 | return 0; |
| 1622 | } | 1637 | } |
| 1623 | 1638 | ||
| @@ -1631,25 +1646,26 @@ static int atmel_hw_nand_init_params(struct platform_device *pdev, | |||
| 1631 | /* set ECC page size and oob layout */ | 1646 | /* set ECC page size and oob layout */ |
| 1632 | switch (mtd->writesize) { | 1647 | switch (mtd->writesize) { |
| 1633 | case 512: | 1648 | case 512: |
| 1634 | nand_chip->ecc.layout = &atmel_oobinfo_small; | 1649 | mtd_set_ooblayout(mtd, &atmel_ooblayout_sp_ops); |
| 1635 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); | 1650 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); |
| 1636 | break; | 1651 | break; |
| 1637 | case 1024: | 1652 | case 1024: |
| 1638 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1653 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 1639 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); | 1654 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); |
| 1640 | break; | 1655 | break; |
| 1641 | case 2048: | 1656 | case 2048: |
| 1642 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1657 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 1643 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); | 1658 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); |
| 1644 | break; | 1659 | break; |
| 1645 | case 4096: | 1660 | case 4096: |
| 1646 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1661 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 1647 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); | 1662 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); |
| 1648 | break; | 1663 | break; |
| 1649 | default: | 1664 | default: |
| 1650 | /* page size not handled by HW ECC */ | 1665 | /* page size not handled by HW ECC */ |
| 1651 | /* switching back to soft ECC */ | 1666 | /* switching back to soft ECC */ |
| 1652 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1667 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
| 1668 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1653 | return 0; | 1669 | return 0; |
| 1654 | } | 1670 | } |
| 1655 | 1671 | ||
| @@ -2147,6 +2163,19 @@ static int atmel_nand_probe(struct platform_device *pdev) | |||
| 2147 | } else { | 2163 | } else { |
| 2148 | memcpy(&host->board, dev_get_platdata(&pdev->dev), | 2164 | memcpy(&host->board, dev_get_platdata(&pdev->dev), |
| 2149 | sizeof(struct atmel_nand_data)); | 2165 | sizeof(struct atmel_nand_data)); |
| 2166 | nand_chip->ecc.mode = host->board.ecc_mode; | ||
| 2167 | |||
| 2168 | /* | ||
| 2169 | * When using software ECC every supported avr32 board means | ||
| 2170 | * Hamming algorithm. If that ever changes we'll need to add | ||
| 2171 | * ecc_algo field to the struct atmel_nand_data. | ||
| 2172 | */ | ||
| 2173 | if (nand_chip->ecc.mode == NAND_ECC_SOFT) | ||
| 2174 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 2175 | |||
| 2176 | /* 16-bit bus width */ | ||
| 2177 | if (host->board.bus_width_16) | ||
| 2178 | nand_chip->options |= NAND_BUSWIDTH_16; | ||
| 2150 | } | 2179 | } |
| 2151 | 2180 | ||
| 2152 | /* link the private data structures */ | 2181 | /* link the private data structures */ |
| @@ -2188,11 +2217,8 @@ static int atmel_nand_probe(struct platform_device *pdev) | |||
| 2188 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; | 2217 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; |
| 2189 | } | 2218 | } |
| 2190 | 2219 | ||
| 2191 | nand_chip->ecc.mode = host->board.ecc_mode; | ||
| 2192 | nand_chip->chip_delay = 40; /* 40us command delay time */ | 2220 | nand_chip->chip_delay = 40; /* 40us command delay time */ |
| 2193 | 2221 | ||
| 2194 | if (host->board.bus_width_16) /* 16-bit bus width */ | ||
| 2195 | nand_chip->options |= NAND_BUSWIDTH_16; | ||
| 2196 | 2222 | ||
| 2197 | nand_chip->read_buf = atmel_read_buf; | 2223 | nand_chip->read_buf = atmel_read_buf; |
| 2198 | nand_chip->write_buf = atmel_write_buf; | 2224 | nand_chip->write_buf = atmel_write_buf; |
| @@ -2225,11 +2251,6 @@ static int atmel_nand_probe(struct platform_device *pdev) | |||
| 2225 | } | 2251 | } |
| 2226 | } | 2252 | } |
| 2227 | 2253 | ||
| 2228 | if (host->board.on_flash_bbt || on_flash_bbt) { | ||
| 2229 | dev_info(&pdev->dev, "Use On Flash BBT\n"); | ||
| 2230 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | if (!host->board.has_dma) | 2254 | if (!host->board.has_dma) |
| 2234 | use_dma = 0; | 2255 | use_dma = 0; |
| 2235 | 2256 | ||
| @@ -2256,6 +2277,18 @@ static int atmel_nand_probe(struct platform_device *pdev) | |||
| 2256 | goto err_scan_ident; | 2277 | goto err_scan_ident; |
| 2257 | } | 2278 | } |
| 2258 | 2279 | ||
| 2280 | if (host->board.on_flash_bbt || on_flash_bbt) | ||
| 2281 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | ||
| 2282 | |||
| 2283 | if (nand_chip->bbt_options & NAND_BBT_USE_FLASH) | ||
| 2284 | dev_info(&pdev->dev, "Use On Flash BBT\n"); | ||
| 2285 | |||
| 2286 | if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { | ||
| 2287 | res = atmel_of_init_ecc(host, pdev->dev.of_node); | ||
| 2288 | if (res) | ||
| 2289 | goto err_hw_ecc; | ||
| 2290 | } | ||
| 2291 | |||
| 2259 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 2292 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
| 2260 | if (host->has_pmecc) | 2293 | if (host->has_pmecc) |
| 2261 | res = atmel_pmecc_nand_init_params(pdev, host); | 2294 | res = atmel_pmecc_nand_init_params(pdev, host); |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 341ea4904164..9bf6d9915694 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
| @@ -459,6 +459,7 @@ static int au1550nd_probe(struct platform_device *pdev) | |||
| 459 | /* 30 us command delay time */ | 459 | /* 30 us command delay time */ |
| 460 | this->chip_delay = 30; | 460 | this->chip_delay = 30; |
| 461 | this->ecc.mode = NAND_ECC_SOFT; | 461 | this->ecc.mode = NAND_ECC_SOFT; |
| 462 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 462 | 463 | ||
| 463 | if (pd->devwidth) | 464 | if (pd->devwidth) |
| 464 | this->options |= NAND_BUSWIDTH_16; | 465 | this->options |= NAND_BUSWIDTH_16; |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 7f6b30e615b7..37da4236ab90 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
| @@ -109,28 +109,33 @@ static const unsigned short bfin_nfc_pin_req[] = | |||
| 109 | 0}; | 109 | 0}; |
| 110 | 110 | ||
| 111 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 111 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
| 112 | static struct nand_ecclayout bootrom_ecclayout = { | 112 | static int bootrom_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 113 | .eccbytes = 24, | 113 | struct mtd_oob_region *oobregion) |
| 114 | .eccpos = { | 114 | { |
| 115 | 0x8 * 0, 0x8 * 0 + 1, 0x8 * 0 + 2, | 115 | if (section > 7) |
| 116 | 0x8 * 1, 0x8 * 1 + 1, 0x8 * 1 + 2, | 116 | return -ERANGE; |
| 117 | 0x8 * 2, 0x8 * 2 + 1, 0x8 * 2 + 2, | 117 | |
| 118 | 0x8 * 3, 0x8 * 3 + 1, 0x8 * 3 + 2, | 118 | oobregion->offset = section * 8; |
| 119 | 0x8 * 4, 0x8 * 4 + 1, 0x8 * 4 + 2, | 119 | oobregion->length = 3; |
| 120 | 0x8 * 5, 0x8 * 5 + 1, 0x8 * 5 + 2, | 120 | |
| 121 | 0x8 * 6, 0x8 * 6 + 1, 0x8 * 6 + 2, | 121 | return 0; |
| 122 | 0x8 * 7, 0x8 * 7 + 1, 0x8 * 7 + 2 | 122 | } |
| 123 | }, | 123 | |
| 124 | .oobfree = { | 124 | static int bootrom_ooblayout_free(struct mtd_info *mtd, int section, |
| 125 | { 0x8 * 0 + 3, 5 }, | 125 | struct mtd_oob_region *oobregion) |
| 126 | { 0x8 * 1 + 3, 5 }, | 126 | { |
| 127 | { 0x8 * 2 + 3, 5 }, | 127 | if (section > 7) |
| 128 | { 0x8 * 3 + 3, 5 }, | 128 | return -ERANGE; |
| 129 | { 0x8 * 4 + 3, 5 }, | 129 | |
| 130 | { 0x8 * 5 + 3, 5 }, | 130 | oobregion->offset = (section * 8) + 3; |
| 131 | { 0x8 * 6 + 3, 5 }, | 131 | oobregion->length = 5; |
| 132 | { 0x8 * 7 + 3, 5 }, | 132 | |
| 133 | } | 133 | return 0; |
| 134 | } | ||
| 135 | |||
| 136 | static const struct mtd_ooblayout_ops bootrom_ooblayout_ops = { | ||
| 137 | .ecc = bootrom_ooblayout_ecc, | ||
| 138 | .free = bootrom_ooblayout_free, | ||
| 134 | }; | 139 | }; |
| 135 | #endif | 140 | #endif |
| 136 | 141 | ||
| @@ -800,7 +805,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) | |||
| 800 | /* setup hardware ECC data struct */ | 805 | /* setup hardware ECC data struct */ |
| 801 | if (hardware_ecc) { | 806 | if (hardware_ecc) { |
| 802 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 807 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
| 803 | chip->ecc.layout = &bootrom_ecclayout; | 808 | mtd_set_ooblayout(mtd, &bootrom_ooblayout_ops); |
| 804 | #endif | 809 | #endif |
| 805 | chip->read_buf = bf5xx_nand_dma_read_buf; | 810 | chip->read_buf = bf5xx_nand_dma_read_buf; |
| 806 | chip->write_buf = bf5xx_nand_dma_write_buf; | 811 | chip->write_buf = bf5xx_nand_dma_write_buf; |
| @@ -812,6 +817,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) | |||
| 812 | chip->ecc.write_page_raw = bf5xx_nand_write_page_raw; | 817 | chip->ecc.write_page_raw = bf5xx_nand_write_page_raw; |
| 813 | } else { | 818 | } else { |
| 814 | chip->ecc.mode = NAND_ECC_SOFT; | 819 | chip->ecc.mode = NAND_ECC_SOFT; |
| 820 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 815 | } | 821 | } |
| 816 | 822 | ||
| 817 | /* scan hardware nand chip and setup mtd info data struct */ | 823 | /* scan hardware nand chip and setup mtd info data struct */ |
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index e0528397306a..b76ad7c0144f 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <linux/mtd/nand.h> | 32 | #include <linux/mtd/nand.h> |
| 33 | #include <linux/mtd/partitions.h> | 33 | #include <linux/mtd/partitions.h> |
| 34 | #include <linux/of.h> | 34 | #include <linux/of.h> |
| 35 | #include <linux/of_mtd.h> | ||
| 36 | #include <linux/of_platform.h> | 35 | #include <linux/of_platform.h> |
| 37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 38 | #include <linux/list.h> | 37 | #include <linux/list.h> |
| @@ -601,7 +600,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) | |||
| 601 | 600 | ||
| 602 | static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) | 601 | static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) |
| 603 | { | 602 | { |
| 604 | if (ctrl->nand_version < 0x0700) | 603 | if (ctrl->nand_version < 0x0602) |
| 605 | return 24; | 604 | return 24; |
| 606 | return 0; | 605 | return 0; |
| 607 | } | 606 | } |
| @@ -781,127 +780,183 @@ static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg) | |||
| 781 | } | 780 | } |
| 782 | 781 | ||
| 783 | /* | 782 | /* |
| 784 | * Returns a nand_ecclayout strucutre for the given layout/configuration. | 783 | * Set mtd->ooblayout to the appropriate mtd_ooblayout_ops given |
| 785 | * Returns NULL on failure. | 784 | * the layout/configuration. |
| 785 | * Returns -ERRCODE on failure. | ||
| 786 | */ | 786 | */ |
| 787 | static struct nand_ecclayout *brcmnand_create_layout(int ecc_level, | 787 | static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 788 | struct brcmnand_host *host) | 788 | struct mtd_oob_region *oobregion) |
| 789 | { | 789 | { |
| 790 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 791 | struct brcmnand_host *host = nand_get_controller_data(chip); | ||
| 790 | struct brcmnand_cfg *cfg = &host->hwcfg; | 792 | struct brcmnand_cfg *cfg = &host->hwcfg; |
| 791 | int i, j; | 793 | int sas = cfg->spare_area_size << cfg->sector_size_1k; |
| 792 | struct nand_ecclayout *layout; | 794 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); |
| 793 | int req; | ||
| 794 | int sectors; | ||
| 795 | int sas; | ||
| 796 | int idx1, idx2; | ||
| 797 | |||
| 798 | layout = devm_kzalloc(&host->pdev->dev, sizeof(*layout), GFP_KERNEL); | ||
| 799 | if (!layout) | ||
| 800 | return NULL; | ||
| 801 | |||
| 802 | sectors = cfg->page_size / (512 << cfg->sector_size_1k); | ||
| 803 | sas = cfg->spare_area_size << cfg->sector_size_1k; | ||
| 804 | |||
| 805 | /* Hamming */ | ||
| 806 | if (is_hamming_ecc(cfg)) { | ||
| 807 | for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { | ||
| 808 | /* First sector of each page may have BBI */ | ||
| 809 | if (i == 0) { | ||
| 810 | layout->oobfree[idx2].offset = i * sas + 1; | ||
| 811 | /* Small-page NAND use byte 6 for BBI */ | ||
| 812 | if (cfg->page_size == 512) | ||
| 813 | layout->oobfree[idx2].offset--; | ||
| 814 | layout->oobfree[idx2].length = 5; | ||
| 815 | } else { | ||
| 816 | layout->oobfree[idx2].offset = i * sas; | ||
| 817 | layout->oobfree[idx2].length = 6; | ||
| 818 | } | ||
| 819 | idx2++; | ||
| 820 | layout->eccpos[idx1++] = i * sas + 6; | ||
| 821 | layout->eccpos[idx1++] = i * sas + 7; | ||
| 822 | layout->eccpos[idx1++] = i * sas + 8; | ||
| 823 | layout->oobfree[idx2].offset = i * sas + 9; | ||
| 824 | layout->oobfree[idx2].length = 7; | ||
| 825 | idx2++; | ||
| 826 | /* Leave zero-terminated entry for OOBFREE */ | ||
| 827 | if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || | ||
| 828 | idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) | ||
| 829 | break; | ||
| 830 | } | ||
| 831 | 795 | ||
| 832 | return layout; | 796 | if (section >= sectors) |
| 833 | } | 797 | return -ERANGE; |
| 834 | 798 | ||
| 835 | /* | 799 | oobregion->offset = (section * sas) + 6; |
| 836 | * CONTROLLER_VERSION: | 800 | oobregion->length = 3; |
| 837 | * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) | 801 | |
| 838 | * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) | 802 | return 0; |
| 839 | * But we will just be conservative. | 803 | } |
| 840 | */ | 804 | |
| 841 | req = DIV_ROUND_UP(ecc_level * 14, 8); | 805 | static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section, |
| 842 | if (req >= sas) { | 806 | struct mtd_oob_region *oobregion) |
| 843 | dev_err(&host->pdev->dev, | 807 | { |
| 844 | "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", | 808 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 845 | req, sas); | 809 | struct brcmnand_host *host = nand_get_controller_data(chip); |
| 846 | return NULL; | 810 | struct brcmnand_cfg *cfg = &host->hwcfg; |
| 847 | } | 811 | int sas = cfg->spare_area_size << cfg->sector_size_1k; |
| 812 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | ||
| 848 | 813 | ||
| 849 | layout->eccbytes = req * sectors; | 814 | if (section >= sectors * 2) |
| 850 | for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { | 815 | return -ERANGE; |
| 851 | for (j = sas - req; j < sas && idx1 < | 816 | |
| 852 | MTD_MAX_ECCPOS_ENTRIES_LARGE; j++, idx1++) | 817 | oobregion->offset = (section / 2) * sas; |
| 853 | layout->eccpos[idx1] = i * sas + j; | 818 | |
| 819 | if (section & 1) { | ||
| 820 | oobregion->offset += 9; | ||
| 821 | oobregion->length = 7; | ||
| 822 | } else { | ||
| 823 | oobregion->length = 6; | ||
| 854 | 824 | ||
| 855 | /* First sector of each page may have BBI */ | 825 | /* First sector of each page may have BBI */ |
| 856 | if (i == 0) { | 826 | if (!section) { |
| 857 | if (cfg->page_size == 512 && (sas - req >= 6)) { | 827 | /* |
| 858 | /* Small-page NAND use byte 6 for BBI */ | 828 | * Small-page NAND use byte 6 for BBI while large-page |
| 859 | layout->oobfree[idx2].offset = 0; | 829 | * NAND use byte 0. |
| 860 | layout->oobfree[idx2].length = 5; | 830 | */ |
| 861 | idx2++; | 831 | if (cfg->page_size > 512) |
| 862 | if (sas - req > 6) { | 832 | oobregion->offset++; |
| 863 | layout->oobfree[idx2].offset = 6; | 833 | oobregion->length--; |
| 864 | layout->oobfree[idx2].length = | ||
| 865 | sas - req - 6; | ||
| 866 | idx2++; | ||
| 867 | } | ||
| 868 | } else if (sas > req + 1) { | ||
| 869 | layout->oobfree[idx2].offset = i * sas + 1; | ||
| 870 | layout->oobfree[idx2].length = sas - req - 1; | ||
| 871 | idx2++; | ||
| 872 | } | ||
| 873 | } else if (sas > req) { | ||
| 874 | layout->oobfree[idx2].offset = i * sas; | ||
| 875 | layout->oobfree[idx2].length = sas - req; | ||
| 876 | idx2++; | ||
| 877 | } | 834 | } |
| 878 | /* Leave zero-terminated entry for OOBFREE */ | ||
| 879 | if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || | ||
| 880 | idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) | ||
| 881 | break; | ||
| 882 | } | 835 | } |
| 883 | 836 | ||
| 884 | return layout; | 837 | return 0; |
| 838 | } | ||
| 839 | |||
| 840 | static const struct mtd_ooblayout_ops brcmnand_hamming_ooblayout_ops = { | ||
| 841 | .ecc = brcmnand_hamming_ooblayout_ecc, | ||
| 842 | .free = brcmnand_hamming_ooblayout_free, | ||
| 843 | }; | ||
| 844 | |||
| 845 | static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 846 | struct mtd_oob_region *oobregion) | ||
| 847 | { | ||
| 848 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 849 | struct brcmnand_host *host = nand_get_controller_data(chip); | ||
| 850 | struct brcmnand_cfg *cfg = &host->hwcfg; | ||
| 851 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | ||
| 852 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | ||
| 853 | |||
| 854 | if (section >= sectors) | ||
| 855 | return -ERANGE; | ||
| 856 | |||
| 857 | oobregion->offset = (section * (sas + 1)) - chip->ecc.bytes; | ||
| 858 | oobregion->length = chip->ecc.bytes; | ||
| 859 | |||
| 860 | return 0; | ||
| 861 | } | ||
| 862 | |||
| 863 | static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section, | ||
| 864 | struct mtd_oob_region *oobregion) | ||
| 865 | { | ||
| 866 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 867 | struct brcmnand_host *host = nand_get_controller_data(chip); | ||
| 868 | struct brcmnand_cfg *cfg = &host->hwcfg; | ||
| 869 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | ||
| 870 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | ||
| 871 | |||
| 872 | if (section >= sectors) | ||
| 873 | return -ERANGE; | ||
| 874 | |||
| 875 | if (sas <= chip->ecc.bytes) | ||
| 876 | return 0; | ||
| 877 | |||
| 878 | oobregion->offset = section * sas; | ||
| 879 | oobregion->length = sas - chip->ecc.bytes; | ||
| 880 | |||
| 881 | if (!section) { | ||
| 882 | oobregion->offset++; | ||
| 883 | oobregion->length--; | ||
| 884 | } | ||
| 885 | |||
| 886 | return 0; | ||
| 885 | } | 887 | } |
| 886 | 888 | ||
| 887 | static struct nand_ecclayout *brcmstb_choose_ecc_layout( | 889 | static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section, |
| 888 | struct brcmnand_host *host) | 890 | struct mtd_oob_region *oobregion) |
| 891 | { | ||
| 892 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 893 | struct brcmnand_host *host = nand_get_controller_data(chip); | ||
| 894 | struct brcmnand_cfg *cfg = &host->hwcfg; | ||
| 895 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | ||
| 896 | |||
| 897 | if (section > 1 || sas - chip->ecc.bytes < 6 || | ||
| 898 | (section && sas - chip->ecc.bytes == 6)) | ||
| 899 | return -ERANGE; | ||
| 900 | |||
| 901 | if (!section) { | ||
| 902 | oobregion->offset = 0; | ||
| 903 | oobregion->length = 5; | ||
| 904 | } else { | ||
| 905 | oobregion->offset = 6; | ||
| 906 | oobregion->length = sas - chip->ecc.bytes - 6; | ||
| 907 | } | ||
| 908 | |||
| 909 | return 0; | ||
| 910 | } | ||
| 911 | |||
| 912 | static const struct mtd_ooblayout_ops brcmnand_bch_lp_ooblayout_ops = { | ||
| 913 | .ecc = brcmnand_bch_ooblayout_ecc, | ||
| 914 | .free = brcmnand_bch_ooblayout_free_lp, | ||
| 915 | }; | ||
| 916 | |||
| 917 | static const struct mtd_ooblayout_ops brcmnand_bch_sp_ooblayout_ops = { | ||
| 918 | .ecc = brcmnand_bch_ooblayout_ecc, | ||
| 919 | .free = brcmnand_bch_ooblayout_free_sp, | ||
| 920 | }; | ||
| 921 | |||
| 922 | static int brcmstb_choose_ecc_layout(struct brcmnand_host *host) | ||
| 889 | { | 923 | { |
| 890 | struct nand_ecclayout *layout; | ||
| 891 | struct brcmnand_cfg *p = &host->hwcfg; | 924 | struct brcmnand_cfg *p = &host->hwcfg; |
| 925 | struct mtd_info *mtd = nand_to_mtd(&host->chip); | ||
| 926 | struct nand_ecc_ctrl *ecc = &host->chip.ecc; | ||
| 892 | unsigned int ecc_level = p->ecc_level; | 927 | unsigned int ecc_level = p->ecc_level; |
| 928 | int sas = p->spare_area_size << p->sector_size_1k; | ||
| 929 | int sectors = p->page_size / (512 << p->sector_size_1k); | ||
| 893 | 930 | ||
| 894 | if (p->sector_size_1k) | 931 | if (p->sector_size_1k) |
| 895 | ecc_level <<= 1; | 932 | ecc_level <<= 1; |
| 896 | 933 | ||
| 897 | layout = brcmnand_create_layout(ecc_level, host); | 934 | if (is_hamming_ecc(p)) { |
| 898 | if (!layout) { | 935 | ecc->bytes = 3 * sectors; |
| 936 | mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops); | ||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | /* | ||
| 941 | * CONTROLLER_VERSION: | ||
| 942 | * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) | ||
| 943 | * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) | ||
| 944 | * But we will just be conservative. | ||
| 945 | */ | ||
| 946 | ecc->bytes = DIV_ROUND_UP(ecc_level * 14, 8); | ||
| 947 | if (p->page_size == 512) | ||
| 948 | mtd_set_ooblayout(mtd, &brcmnand_bch_sp_ooblayout_ops); | ||
| 949 | else | ||
| 950 | mtd_set_ooblayout(mtd, &brcmnand_bch_lp_ooblayout_ops); | ||
| 951 | |||
| 952 | if (ecc->bytes >= sas) { | ||
| 899 | dev_err(&host->pdev->dev, | 953 | dev_err(&host->pdev->dev, |
| 900 | "no proper ecc_layout for this NAND cfg\n"); | 954 | "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", |
| 901 | return NULL; | 955 | ecc->bytes, sas); |
| 956 | return -EINVAL; | ||
| 902 | } | 957 | } |
| 903 | 958 | ||
| 904 | return layout; | 959 | return 0; |
| 905 | } | 960 | } |
| 906 | 961 | ||
| 907 | static void brcmnand_wp(struct mtd_info *mtd, int wp) | 962 | static void brcmnand_wp(struct mtd_info *mtd, int wp) |
| @@ -1870,9 +1925,31 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) | |||
| 1870 | cfg->col_adr_bytes = 2; | 1925 | cfg->col_adr_bytes = 2; |
| 1871 | cfg->blk_adr_bytes = get_blk_adr_bytes(mtd->size, mtd->writesize); | 1926 | cfg->blk_adr_bytes = get_blk_adr_bytes(mtd->size, mtd->writesize); |
| 1872 | 1927 | ||
| 1928 | if (chip->ecc.mode != NAND_ECC_HW) { | ||
| 1929 | dev_err(ctrl->dev, "only HW ECC supported; selected: %d\n", | ||
| 1930 | chip->ecc.mode); | ||
| 1931 | return -EINVAL; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | if (chip->ecc.algo == NAND_ECC_UNKNOWN) { | ||
| 1935 | if (chip->ecc.strength == 1 && chip->ecc.size == 512) | ||
| 1936 | /* Default to Hamming for 1-bit ECC, if unspecified */ | ||
| 1937 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1938 | else | ||
| 1939 | /* Otherwise, BCH */ | ||
| 1940 | chip->ecc.algo = NAND_ECC_BCH; | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | if (chip->ecc.algo == NAND_ECC_HAMMING && (chip->ecc.strength != 1 || | ||
| 1944 | chip->ecc.size != 512)) { | ||
| 1945 | dev_err(ctrl->dev, "invalid Hamming params: %d bits per %d bytes\n", | ||
| 1946 | chip->ecc.strength, chip->ecc.size); | ||
| 1947 | return -EINVAL; | ||
| 1948 | } | ||
| 1949 | |||
| 1873 | switch (chip->ecc.size) { | 1950 | switch (chip->ecc.size) { |
| 1874 | case 512: | 1951 | case 512: |
| 1875 | if (chip->ecc.strength == 1) /* Hamming */ | 1952 | if (chip->ecc.algo == NAND_ECC_HAMMING) |
| 1876 | cfg->ecc_level = 15; | 1953 | cfg->ecc_level = 15; |
| 1877 | else | 1954 | else |
| 1878 | cfg->ecc_level = chip->ecc.strength; | 1955 | cfg->ecc_level = chip->ecc.strength; |
| @@ -2001,8 +2078,8 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) | |||
| 2001 | */ | 2078 | */ |
| 2002 | chip->options |= NAND_USE_BOUNCE_BUFFER; | 2079 | chip->options |= NAND_USE_BOUNCE_BUFFER; |
| 2003 | 2080 | ||
| 2004 | if (of_get_nand_on_flash_bbt(dn)) | 2081 | if (chip->bbt_options & NAND_BBT_USE_FLASH) |
| 2005 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | 2082 | chip->bbt_options |= NAND_BBT_NO_OOB; |
| 2006 | 2083 | ||
| 2007 | if (brcmnand_setup_dev(host)) | 2084 | if (brcmnand_setup_dev(host)) |
| 2008 | return -ENXIO; | 2085 | return -ENXIO; |
| @@ -2011,9 +2088,9 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) | |||
| 2011 | /* only use our internal HW threshold */ | 2088 | /* only use our internal HW threshold */ |
| 2012 | mtd->bitflip_threshold = 1; | 2089 | mtd->bitflip_threshold = 1; |
| 2013 | 2090 | ||
| 2014 | chip->ecc.layout = brcmstb_choose_ecc_layout(host); | 2091 | ret = brcmstb_choose_ecc_layout(host); |
| 2015 | if (!chip->ecc.layout) | 2092 | if (ret) |
| 2016 | return -ENXIO; | 2093 | return ret; |
| 2017 | 2094 | ||
| 2018 | if (nand_scan_tail(mtd)) | 2095 | if (nand_scan_tail(mtd)) |
| 2019 | return -ENXIO; | 2096 | return -ENXIO; |
| @@ -2115,6 +2192,7 @@ static const struct of_device_id brcmnand_of_match[] = { | |||
| 2115 | { .compatible = "brcm,brcmnand-v5.0" }, | 2192 | { .compatible = "brcm,brcmnand-v5.0" }, |
| 2116 | { .compatible = "brcm,brcmnand-v6.0" }, | 2193 | { .compatible = "brcm,brcmnand-v6.0" }, |
| 2117 | { .compatible = "brcm,brcmnand-v6.1" }, | 2194 | { .compatible = "brcm,brcmnand-v6.1" }, |
| 2195 | { .compatible = "brcm,brcmnand-v6.2" }, | ||
| 2118 | { .compatible = "brcm,brcmnand-v7.0" }, | 2196 | { .compatible = "brcm,brcmnand-v7.0" }, |
| 2119 | { .compatible = "brcm,brcmnand-v7.1" }, | 2197 | { .compatible = "brcm,brcmnand-v7.1" }, |
| 2120 | {}, | 2198 | {}, |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index e553aff68987..0b0c93702abb 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
| @@ -459,10 +459,37 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 459 | return max_bitflips; | 459 | return max_bitflips; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static struct nand_ecclayout cafe_oobinfo_2048 = { | 462 | static int cafe_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 463 | .eccbytes = 14, | 463 | struct mtd_oob_region *oobregion) |
| 464 | .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, | 464 | { |
| 465 | .oobfree = {{14, 50}} | 465 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 466 | |||
| 467 | if (section) | ||
| 468 | return -ERANGE; | ||
| 469 | |||
| 470 | oobregion->offset = 0; | ||
| 471 | oobregion->length = chip->ecc.total; | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int cafe_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 477 | struct mtd_oob_region *oobregion) | ||
| 478 | { | ||
| 479 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 480 | |||
| 481 | if (section) | ||
| 482 | return -ERANGE; | ||
| 483 | |||
| 484 | oobregion->offset = chip->ecc.total; | ||
| 485 | oobregion->length = mtd->oobsize - chip->ecc.total; | ||
| 486 | |||
| 487 | return 0; | ||
| 488 | } | ||
| 489 | |||
| 490 | static const struct mtd_ooblayout_ops cafe_ooblayout_ops = { | ||
| 491 | .ecc = cafe_ooblayout_ecc, | ||
| 492 | .free = cafe_ooblayout_free, | ||
| 466 | }; | 493 | }; |
| 467 | 494 | ||
| 468 | /* Ick. The BBT code really ought to be able to work this bit out | 495 | /* Ick. The BBT code really ought to be able to work this bit out |
| @@ -494,12 +521,6 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { | |||
| 494 | .pattern = cafe_mirror_pattern_2048 | 521 | .pattern = cafe_mirror_pattern_2048 |
| 495 | }; | 522 | }; |
| 496 | 523 | ||
| 497 | static struct nand_ecclayout cafe_oobinfo_512 = { | ||
| 498 | .eccbytes = 14, | ||
| 499 | .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, | ||
| 500 | .oobfree = {{14, 2}} | ||
| 501 | }; | ||
| 502 | |||
| 503 | static struct nand_bbt_descr cafe_bbt_main_descr_512 = { | 524 | static struct nand_bbt_descr cafe_bbt_main_descr_512 = { |
| 504 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 525 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
| 505 | | NAND_BBT_2BIT | NAND_BBT_VERSION, | 526 | | NAND_BBT_2BIT | NAND_BBT_VERSION, |
| @@ -743,12 +764,11 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
| 743 | cafe->ctl2 |= 1<<29; /* 2KiB page size */ | 764 | cafe->ctl2 |= 1<<29; /* 2KiB page size */ |
| 744 | 765 | ||
| 745 | /* Set up ECC according to the type of chip we found */ | 766 | /* Set up ECC according to the type of chip we found */ |
| 767 | mtd_set_ooblayout(mtd, &cafe_ooblayout_ops); | ||
| 746 | if (mtd->writesize == 2048) { | 768 | if (mtd->writesize == 2048) { |
| 747 | cafe->nand.ecc.layout = &cafe_oobinfo_2048; | ||
| 748 | cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; | 769 | cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; |
| 749 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; | 770 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; |
| 750 | } else if (mtd->writesize == 512) { | 771 | } else if (mtd->writesize == 512) { |
| 751 | cafe->nand.ecc.layout = &cafe_oobinfo_512; | ||
| 752 | cafe->nand.bbt_td = &cafe_bbt_main_descr_512; | 772 | cafe->nand.bbt_td = &cafe_bbt_main_descr_512; |
| 753 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512; | 773 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512; |
| 754 | } else { | 774 | } else { |
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 6f97ebba52c4..49133783ca53 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c | |||
| @@ -187,6 +187,7 @@ static int __init cmx270_init(void) | |||
| 187 | /* 15 us command delay time */ | 187 | /* 15 us command delay time */ |
| 188 | this->chip_delay = 20; | 188 | this->chip_delay = 20; |
| 189 | this->ecc.mode = NAND_ECC_SOFT; | 189 | this->ecc.mode = NAND_ECC_SOFT; |
| 190 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 190 | 191 | ||
| 191 | /* read/write functions */ | 192 | /* read/write functions */ |
| 192 | this->read_byte = cmx270_read_byte; | 193 | this->read_byte = cmx270_read_byte; |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8cb821b6686e..cc07ba0f044d 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/of_device.h> | 35 | #include <linux/of_device.h> |
| 36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
| 37 | #include <linux/of_mtd.h> | ||
| 38 | 37 | ||
| 39 | #include <linux/platform_data/mtd-davinci.h> | 38 | #include <linux/platform_data/mtd-davinci.h> |
| 40 | #include <linux/platform_data/mtd-davinci-aemif.h> | 39 | #include <linux/platform_data/mtd-davinci-aemif.h> |
| @@ -54,7 +53,6 @@ | |||
| 54 | */ | 53 | */ |
| 55 | struct davinci_nand_info { | 54 | struct davinci_nand_info { |
| 56 | struct nand_chip chip; | 55 | struct nand_chip chip; |
| 57 | struct nand_ecclayout ecclayout; | ||
| 58 | 56 | ||
| 59 | struct device *dev; | 57 | struct device *dev; |
| 60 | struct clk *clk; | 58 | struct clk *clk; |
| @@ -480,63 +478,46 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) | |||
| 480 | * ten ECC bytes plus the manufacturer's bad block marker byte, and | 478 | * ten ECC bytes plus the manufacturer's bad block marker byte, and |
| 481 | * and not overlapping the default BBT markers. | 479 | * and not overlapping the default BBT markers. |
| 482 | */ | 480 | */ |
| 483 | static struct nand_ecclayout hwecc4_small = { | 481 | static int hwecc4_ooblayout_small_ecc(struct mtd_info *mtd, int section, |
| 484 | .eccbytes = 10, | 482 | struct mtd_oob_region *oobregion) |
| 485 | .eccpos = { 0, 1, 2, 3, 4, | 483 | { |
| 486 | /* offset 5 holds the badblock marker */ | 484 | if (section > 2) |
| 487 | 6, 7, | 485 | return -ERANGE; |
| 488 | 13, 14, 15, }, | 486 | |
| 489 | .oobfree = { | 487 | if (!section) { |
| 490 | {.offset = 8, .length = 5, }, | 488 | oobregion->offset = 0; |
| 491 | {.offset = 16, }, | 489 | oobregion->length = 5; |
| 492 | }, | 490 | } else if (section == 1) { |
| 493 | }; | 491 | oobregion->offset = 6; |
| 492 | oobregion->length = 2; | ||
| 493 | } else { | ||
| 494 | oobregion->offset = 13; | ||
| 495 | oobregion->length = 3; | ||
| 496 | } | ||
| 494 | 497 | ||
| 495 | /* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash, | 498 | return 0; |
| 496 | * storing ten ECC bytes plus the manufacturer's bad block marker byte, | 499 | } |
| 497 | * and not overlapping the default BBT markers. | ||
| 498 | */ | ||
| 499 | static struct nand_ecclayout hwecc4_2048 = { | ||
| 500 | .eccbytes = 40, | ||
| 501 | .eccpos = { | ||
| 502 | /* at the end of spare sector */ | ||
| 503 | 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, | ||
| 504 | 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, | ||
| 505 | 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, | ||
| 506 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 507 | }, | ||
| 508 | .oobfree = { | ||
| 509 | /* 2 bytes at offset 0 hold manufacturer badblock markers */ | ||
| 510 | {.offset = 2, .length = 22, }, | ||
| 511 | /* 5 bytes at offset 8 hold BBT markers */ | ||
| 512 | /* 8 bytes at offset 16 hold JFFS2 clean markers */ | ||
| 513 | }, | ||
| 514 | }; | ||
| 515 | 500 | ||
| 516 | /* | 501 | static int hwecc4_ooblayout_small_free(struct mtd_info *mtd, int section, |
| 517 | * An ECC layout for using 4-bit ECC with large-page (4096bytes) flash, | 502 | struct mtd_oob_region *oobregion) |
| 518 | * storing ten ECC bytes plus the manufacturer's bad block marker byte, | 503 | { |
| 519 | * and not overlapping the default BBT markers. | 504 | if (section > 1) |
| 520 | */ | 505 | return -ERANGE; |
| 521 | static struct nand_ecclayout hwecc4_4096 = { | 506 | |
| 522 | .eccbytes = 80, | 507 | if (!section) { |
| 523 | .eccpos = { | 508 | oobregion->offset = 8; |
| 524 | /* at the end of spare sector */ | 509 | oobregion->length = 5; |
| 525 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, | 510 | } else { |
| 526 | 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, | 511 | oobregion->offset = 16; |
| 527 | 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, | 512 | oobregion->length = mtd->oobsize - 16; |
| 528 | 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, | 513 | } |
| 529 | 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, | 514 | |
| 530 | 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, | 515 | return 0; |
| 531 | 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, | 516 | } |
| 532 | 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, | 517 | |
| 533 | }, | 518 | static const struct mtd_ooblayout_ops hwecc4_small_ooblayout_ops = { |
| 534 | .oobfree = { | 519 | .ecc = hwecc4_ooblayout_small_ecc, |
| 535 | /* 2 bytes at offset 0 hold manufacturer badblock markers */ | 520 | .free = hwecc4_ooblayout_small_free, |
| 536 | {.offset = 2, .length = 46, }, | ||
| 537 | /* 5 bytes at offset 8 hold BBT markers */ | ||
| 538 | /* 8 bytes at offset 16 hold JFFS2 clean markers */ | ||
| 539 | }, | ||
| 540 | }; | 521 | }; |
| 541 | 522 | ||
| 542 | #if defined(CONFIG_OF) | 523 | #if defined(CONFIG_OF) |
| @@ -577,8 +558,6 @@ static struct davinci_nand_pdata | |||
| 577 | "ti,davinci-mask-chipsel", &prop)) | 558 | "ti,davinci-mask-chipsel", &prop)) |
| 578 | pdata->mask_chipsel = prop; | 559 | pdata->mask_chipsel = prop; |
| 579 | if (!of_property_read_string(pdev->dev.of_node, | 560 | if (!of_property_read_string(pdev->dev.of_node, |
| 580 | "nand-ecc-mode", &mode) || | ||
| 581 | !of_property_read_string(pdev->dev.of_node, | ||
| 582 | "ti,davinci-ecc-mode", &mode)) { | 561 | "ti,davinci-ecc-mode", &mode)) { |
| 583 | if (!strncmp("none", mode, 4)) | 562 | if (!strncmp("none", mode, 4)) |
| 584 | pdata->ecc_mode = NAND_ECC_NONE; | 563 | pdata->ecc_mode = NAND_ECC_NONE; |
| @@ -591,14 +570,11 @@ static struct davinci_nand_pdata | |||
| 591 | "ti,davinci-ecc-bits", &prop)) | 570 | "ti,davinci-ecc-bits", &prop)) |
| 592 | pdata->ecc_bits = prop; | 571 | pdata->ecc_bits = prop; |
| 593 | 572 | ||
| 594 | prop = of_get_nand_bus_width(pdev->dev.of_node); | 573 | if (!of_property_read_u32(pdev->dev.of_node, |
| 595 | if (0 < prop || !of_property_read_u32(pdev->dev.of_node, | 574 | "ti,davinci-nand-buswidth", &prop) && prop == 16) |
| 596 | "ti,davinci-nand-buswidth", &prop)) | 575 | pdata->options |= NAND_BUSWIDTH_16; |
| 597 | if (prop == 16) | 576 | |
| 598 | pdata->options |= NAND_BUSWIDTH_16; | ||
| 599 | if (of_property_read_bool(pdev->dev.of_node, | 577 | if (of_property_read_bool(pdev->dev.of_node, |
| 600 | "nand-on-flash-bbt") || | ||
| 601 | of_property_read_bool(pdev->dev.of_node, | ||
| 602 | "ti,davinci-nand-use-bbt")) | 578 | "ti,davinci-nand-use-bbt")) |
| 603 | pdata->bbt_options = NAND_BBT_USE_FLASH; | 579 | pdata->bbt_options = NAND_BBT_USE_FLASH; |
| 604 | 580 | ||
| @@ -628,7 +604,6 @@ static int nand_davinci_probe(struct platform_device *pdev) | |||
| 628 | void __iomem *base; | 604 | void __iomem *base; |
| 629 | int ret; | 605 | int ret; |
| 630 | uint32_t val; | 606 | uint32_t val; |
| 631 | nand_ecc_modes_t ecc_mode; | ||
| 632 | struct mtd_info *mtd; | 607 | struct mtd_info *mtd; |
| 633 | 608 | ||
| 634 | pdata = nand_davinci_get_pdata(pdev); | 609 | pdata = nand_davinci_get_pdata(pdev); |
| @@ -712,13 +687,53 @@ static int nand_davinci_probe(struct platform_device *pdev) | |||
| 712 | info->chip.write_buf = nand_davinci_write_buf; | 687 | info->chip.write_buf = nand_davinci_write_buf; |
| 713 | 688 | ||
| 714 | /* Use board-specific ECC config */ | 689 | /* Use board-specific ECC config */ |
| 715 | ecc_mode = pdata->ecc_mode; | 690 | info->chip.ecc.mode = pdata->ecc_mode; |
| 716 | 691 | ||
| 717 | ret = -EINVAL; | 692 | ret = -EINVAL; |
| 718 | switch (ecc_mode) { | 693 | |
| 694 | info->clk = devm_clk_get(&pdev->dev, "aemif"); | ||
| 695 | if (IS_ERR(info->clk)) { | ||
| 696 | ret = PTR_ERR(info->clk); | ||
| 697 | dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); | ||
| 698 | return ret; | ||
| 699 | } | ||
| 700 | |||
| 701 | ret = clk_prepare_enable(info->clk); | ||
| 702 | if (ret < 0) { | ||
| 703 | dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n", | ||
| 704 | ret); | ||
| 705 | goto err_clk_enable; | ||
| 706 | } | ||
| 707 | |||
| 708 | spin_lock_irq(&davinci_nand_lock); | ||
| 709 | |||
| 710 | /* put CSxNAND into NAND mode */ | ||
| 711 | val = davinci_nand_readl(info, NANDFCR_OFFSET); | ||
| 712 | val |= BIT(info->core_chipsel); | ||
| 713 | davinci_nand_writel(info, NANDFCR_OFFSET, val); | ||
| 714 | |||
| 715 | spin_unlock_irq(&davinci_nand_lock); | ||
| 716 | |||
| 717 | /* Scan to find existence of the device(s) */ | ||
| 718 | ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL); | ||
| 719 | if (ret < 0) { | ||
| 720 | dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); | ||
| 721 | goto err; | ||
| 722 | } | ||
| 723 | |||
| 724 | switch (info->chip.ecc.mode) { | ||
| 719 | case NAND_ECC_NONE: | 725 | case NAND_ECC_NONE: |
| 726 | pdata->ecc_bits = 0; | ||
| 727 | break; | ||
| 720 | case NAND_ECC_SOFT: | 728 | case NAND_ECC_SOFT: |
| 721 | pdata->ecc_bits = 0; | 729 | pdata->ecc_bits = 0; |
| 730 | /* | ||
| 731 | * This driver expects Hamming based ECC when ecc_mode is set | ||
| 732 | * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to | ||
| 733 | * avoid adding an extra ->ecc_algo field to | ||
| 734 | * davinci_nand_pdata. | ||
| 735 | */ | ||
| 736 | info->chip.ecc.algo = NAND_ECC_HAMMING; | ||
| 722 | break; | 737 | break; |
| 723 | case NAND_ECC_HW: | 738 | case NAND_ECC_HW: |
| 724 | if (pdata->ecc_bits == 4) { | 739 | if (pdata->ecc_bits == 4) { |
| @@ -754,37 +769,6 @@ static int nand_davinci_probe(struct platform_device *pdev) | |||
| 754 | default: | 769 | default: |
| 755 | return -EINVAL; | 770 | return -EINVAL; |
| 756 | } | 771 | } |
| 757 | info->chip.ecc.mode = ecc_mode; | ||
| 758 | |||
| 759 | info->clk = devm_clk_get(&pdev->dev, "aemif"); | ||
| 760 | if (IS_ERR(info->clk)) { | ||
| 761 | ret = PTR_ERR(info->clk); | ||
| 762 | dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); | ||
| 763 | return ret; | ||
| 764 | } | ||
| 765 | |||
| 766 | ret = clk_prepare_enable(info->clk); | ||
| 767 | if (ret < 0) { | ||
| 768 | dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n", | ||
| 769 | ret); | ||
| 770 | goto err_clk_enable; | ||
| 771 | } | ||
| 772 | |||
| 773 | spin_lock_irq(&davinci_nand_lock); | ||
| 774 | |||
| 775 | /* put CSxNAND into NAND mode */ | ||
| 776 | val = davinci_nand_readl(info, NANDFCR_OFFSET); | ||
| 777 | val |= BIT(info->core_chipsel); | ||
| 778 | davinci_nand_writel(info, NANDFCR_OFFSET, val); | ||
| 779 | |||
| 780 | spin_unlock_irq(&davinci_nand_lock); | ||
| 781 | |||
| 782 | /* Scan to find existence of the device(s) */ | ||
| 783 | ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL); | ||
| 784 | if (ret < 0) { | ||
| 785 | dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); | ||
| 786 | goto err; | ||
| 787 | } | ||
| 788 | 772 | ||
| 789 | /* Update ECC layout if needed ... for 1-bit HW ECC, the default | 773 | /* Update ECC layout if needed ... for 1-bit HW ECC, the default |
| 790 | * is OK, but it allocates 6 bytes when only 3 are needed (for | 774 | * is OK, but it allocates 6 bytes when only 3 are needed (for |
| @@ -805,26 +789,14 @@ static int nand_davinci_probe(struct platform_device *pdev) | |||
| 805 | * table marker fits in the free bytes. | 789 | * table marker fits in the free bytes. |
| 806 | */ | 790 | */ |
| 807 | if (chunks == 1) { | 791 | if (chunks == 1) { |
| 808 | info->ecclayout = hwecc4_small; | 792 | mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops); |
| 809 | info->ecclayout.oobfree[1].length = mtd->oobsize - 16; | 793 | } else if (chunks == 4 || chunks == 8) { |
| 810 | goto syndrome_done; | 794 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 811 | } | ||
| 812 | if (chunks == 4) { | ||
| 813 | info->ecclayout = hwecc4_2048; | ||
| 814 | info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; | ||
| 815 | goto syndrome_done; | ||
| 816 | } | ||
| 817 | if (chunks == 8) { | ||
| 818 | info->ecclayout = hwecc4_4096; | ||
| 819 | info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; | 795 | info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; |
| 820 | goto syndrome_done; | 796 | } else { |
| 797 | ret = -EIO; | ||
| 798 | goto err; | ||
| 821 | } | 799 | } |
| 822 | |||
| 823 | ret = -EIO; | ||
| 824 | goto err; | ||
| 825 | |||
| 826 | syndrome_done: | ||
| 827 | info->chip.ecc.layout = &info->ecclayout; | ||
| 828 | } | 800 | } |
| 829 | 801 | ||
| 830 | ret = nand_scan_tail(mtd); | 802 | ret = nand_scan_tail(mtd); |
| @@ -850,7 +822,7 @@ err: | |||
| 850 | 822 | ||
| 851 | err_clk_enable: | 823 | err_clk_enable: |
| 852 | spin_lock_irq(&davinci_nand_lock); | 824 | spin_lock_irq(&davinci_nand_lock); |
| 853 | if (ecc_mode == NAND_ECC_HW_SYNDROME) | 825 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) |
| 854 | ecc4_busy = false; | 826 | ecc4_busy = false; |
| 855 | spin_unlock_irq(&davinci_nand_lock); | 827 | spin_unlock_irq(&davinci_nand_lock); |
| 856 | return ret; | 828 | return ret; |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 30bf5f690f78..0476ae8776d9 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
| @@ -1374,13 +1374,41 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
| 1374 | * correction | 1374 | * correction |
| 1375 | */ | 1375 | */ |
| 1376 | #define ECC_8BITS 14 | 1376 | #define ECC_8BITS 14 |
| 1377 | static struct nand_ecclayout nand_8bit_oob = { | ||
| 1378 | .eccbytes = 14, | ||
| 1379 | }; | ||
| 1380 | |||
| 1381 | #define ECC_15BITS 26 | 1377 | #define ECC_15BITS 26 |
| 1382 | static struct nand_ecclayout nand_15bit_oob = { | 1378 | |
| 1383 | .eccbytes = 26, | 1379 | static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 1380 | struct mtd_oob_region *oobregion) | ||
| 1381 | { | ||
| 1382 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1383 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1384 | |||
| 1385 | if (section) | ||
| 1386 | return -ERANGE; | ||
| 1387 | |||
| 1388 | oobregion->offset = denali->bbtskipbytes; | ||
| 1389 | oobregion->length = chip->ecc.total; | ||
| 1390 | |||
| 1391 | return 0; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | static int denali_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 1395 | struct mtd_oob_region *oobregion) | ||
| 1396 | { | ||
| 1397 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1398 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1399 | |||
| 1400 | if (section) | ||
| 1401 | return -ERANGE; | ||
| 1402 | |||
| 1403 | oobregion->offset = chip->ecc.total + denali->bbtskipbytes; | ||
| 1404 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 1405 | |||
| 1406 | return 0; | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | static const struct mtd_ooblayout_ops denali_ooblayout_ops = { | ||
| 1410 | .ecc = denali_ooblayout_ecc, | ||
| 1411 | .free = denali_ooblayout_free, | ||
| 1384 | }; | 1412 | }; |
| 1385 | 1413 | ||
| 1386 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | 1414 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; |
| @@ -1561,7 +1589,6 @@ int denali_init(struct denali_nand_info *denali) | |||
| 1561 | ECC_SECTOR_SIZE)))) { | 1589 | ECC_SECTOR_SIZE)))) { |
| 1562 | /* if MLC OOB size is large enough, use 15bit ECC*/ | 1590 | /* if MLC OOB size is large enough, use 15bit ECC*/ |
| 1563 | denali->nand.ecc.strength = 15; | 1591 | denali->nand.ecc.strength = 15; |
| 1564 | denali->nand.ecc.layout = &nand_15bit_oob; | ||
| 1565 | denali->nand.ecc.bytes = ECC_15BITS; | 1592 | denali->nand.ecc.bytes = ECC_15BITS; |
| 1566 | iowrite32(15, denali->flash_reg + ECC_CORRECTION); | 1593 | iowrite32(15, denali->flash_reg + ECC_CORRECTION); |
| 1567 | } else if (mtd->oobsize < (denali->bbtskipbytes + | 1594 | } else if (mtd->oobsize < (denali->bbtskipbytes + |
| @@ -1571,20 +1598,13 @@ int denali_init(struct denali_nand_info *denali) | |||
| 1571 | goto failed_req_irq; | 1598 | goto failed_req_irq; |
| 1572 | } else { | 1599 | } else { |
| 1573 | denali->nand.ecc.strength = 8; | 1600 | denali->nand.ecc.strength = 8; |
| 1574 | denali->nand.ecc.layout = &nand_8bit_oob; | ||
| 1575 | denali->nand.ecc.bytes = ECC_8BITS; | 1601 | denali->nand.ecc.bytes = ECC_8BITS; |
| 1576 | iowrite32(8, denali->flash_reg + ECC_CORRECTION); | 1602 | iowrite32(8, denali->flash_reg + ECC_CORRECTION); |
| 1577 | } | 1603 | } |
| 1578 | 1604 | ||
| 1605 | mtd_set_ooblayout(mtd, &denali_ooblayout_ops); | ||
| 1579 | denali->nand.ecc.bytes *= denali->devnum; | 1606 | denali->nand.ecc.bytes *= denali->devnum; |
| 1580 | denali->nand.ecc.strength *= denali->devnum; | 1607 | denali->nand.ecc.strength *= denali->devnum; |
| 1581 | denali->nand.ecc.layout->eccbytes *= | ||
| 1582 | mtd->writesize / ECC_SECTOR_SIZE; | ||
| 1583 | denali->nand.ecc.layout->oobfree[0].offset = | ||
| 1584 | denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes; | ||
| 1585 | denali->nand.ecc.layout->oobfree[0].length = | ||
| 1586 | mtd->oobsize - denali->nand.ecc.layout->eccbytes - | ||
| 1587 | denali->bbtskipbytes; | ||
| 1588 | 1608 | ||
| 1589 | /* | 1609 | /* |
| 1590 | * Let driver know the total blocks number and how many blocks | 1610 | * Let driver know the total blocks number and how many blocks |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 547c1002941d..a023ab9e9cbf 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
| @@ -950,20 +950,50 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, | |||
| 950 | 950 | ||
| 951 | //u_char mydatabuf[528]; | 951 | //u_char mydatabuf[528]; |
| 952 | 952 | ||
| 953 | /* The strange out-of-order .oobfree list below is a (possibly unneeded) | 953 | static int doc200x_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 954 | * attempt to retain compatibility. It used to read: | 954 | struct mtd_oob_region *oobregion) |
| 955 | * .oobfree = { {8, 8} } | 955 | { |
| 956 | * Since that leaves two bytes unusable, it was changed. But the following | 956 | if (section) |
| 957 | * scheme might affect existing jffs2 installs by moving the cleanmarker: | 957 | return -ERANGE; |
| 958 | * .oobfree = { {6, 10} } | 958 | |
| 959 | * jffs2 seems to handle the above gracefully, but the current scheme seems | 959 | oobregion->offset = 0; |
| 960 | * safer. The only problem with it is that any code that parses oobfree must | 960 | oobregion->length = 6; |
| 961 | * be able to handle out-of-order segments. | 961 | |
| 962 | */ | 962 | return 0; |
| 963 | static struct nand_ecclayout doc200x_oobinfo = { | 963 | } |
| 964 | .eccbytes = 6, | 964 | |
| 965 | .eccpos = {0, 1, 2, 3, 4, 5}, | 965 | static int doc200x_ooblayout_free(struct mtd_info *mtd, int section, |
| 966 | .oobfree = {{8, 8}, {6, 2}} | 966 | struct mtd_oob_region *oobregion) |
| 967 | { | ||
| 968 | if (section > 1) | ||
| 969 | return -ERANGE; | ||
| 970 | |||
| 971 | /* | ||
| 972 | * The strange out-of-order free bytes definition is a (possibly | ||
| 973 | * unneeded) attempt to retain compatibility. It used to read: | ||
| 974 | * .oobfree = { {8, 8} } | ||
| 975 | * Since that leaves two bytes unusable, it was changed. But the | ||
| 976 | * following scheme might affect existing jffs2 installs by moving the | ||
| 977 | * cleanmarker: | ||
| 978 | * .oobfree = { {6, 10} } | ||
| 979 | * jffs2 seems to handle the above gracefully, but the current scheme | ||
| 980 | * seems safer. The only problem with it is that any code retrieving | ||
| 981 | * free bytes position must be able to handle out-of-order segments. | ||
| 982 | */ | ||
| 983 | if (!section) { | ||
| 984 | oobregion->offset = 8; | ||
| 985 | oobregion->length = 8; | ||
| 986 | } else { | ||
| 987 | oobregion->offset = 6; | ||
| 988 | oobregion->length = 2; | ||
| 989 | } | ||
| 990 | |||
| 991 | return 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | static const struct mtd_ooblayout_ops doc200x_ooblayout_ops = { | ||
| 995 | .ecc = doc200x_ooblayout_ecc, | ||
| 996 | .free = doc200x_ooblayout_free, | ||
| 967 | }; | 997 | }; |
| 968 | 998 | ||
| 969 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. | 999 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. |
| @@ -1537,6 +1567,7 @@ static int __init doc_probe(unsigned long physadr) | |||
| 1537 | nand->bbt_md = nand->bbt_td + 1; | 1567 | nand->bbt_md = nand->bbt_td + 1; |
| 1538 | 1568 | ||
| 1539 | mtd->owner = THIS_MODULE; | 1569 | mtd->owner = THIS_MODULE; |
| 1570 | mtd_set_ooblayout(mtd, &doc200x_ooblayout_ops); | ||
| 1540 | 1571 | ||
| 1541 | nand_set_controller_data(nand, doc); | 1572 | nand_set_controller_data(nand, doc); |
| 1542 | nand->select_chip = doc200x_select_chip; | 1573 | nand->select_chip = doc200x_select_chip; |
| @@ -1548,7 +1579,6 @@ static int __init doc_probe(unsigned long physadr) | |||
| 1548 | nand->ecc.calculate = doc200x_calculate_ecc; | 1579 | nand->ecc.calculate = doc200x_calculate_ecc; |
| 1549 | nand->ecc.correct = doc200x_correct_data; | 1580 | nand->ecc.correct = doc200x_correct_data; |
| 1550 | 1581 | ||
| 1551 | nand->ecc.layout = &doc200x_oobinfo; | ||
| 1552 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; | 1582 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
| 1553 | nand->ecc.size = 512; | 1583 | nand->ecc.size = 512; |
| 1554 | nand->ecc.bytes = 6; | 1584 | nand->ecc.bytes = 6; |
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index d86a60e1bbcb..47316998017f 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c | |||
| @@ -222,10 +222,33 @@ struct docg4_priv { | |||
| 222 | * Bytes 8 - 14 are hw-generated ecc covering entire page + oob bytes 0 - 14. | 222 | * Bytes 8 - 14 are hw-generated ecc covering entire page + oob bytes 0 - 14. |
| 223 | * Byte 15 (the last) is used by the driver as a "page written" flag. | 223 | * Byte 15 (the last) is used by the driver as a "page written" flag. |
| 224 | */ | 224 | */ |
| 225 | static struct nand_ecclayout docg4_oobinfo = { | 225 | static int docg4_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 226 | .eccbytes = 9, | 226 | struct mtd_oob_region *oobregion) |
| 227 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, | 227 | { |
| 228 | .oobfree = { {.offset = 2, .length = 5} } | 228 | if (section) |
| 229 | return -ERANGE; | ||
| 230 | |||
| 231 | oobregion->offset = 7; | ||
| 232 | oobregion->length = 9; | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int docg4_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 238 | struct mtd_oob_region *oobregion) | ||
| 239 | { | ||
| 240 | if (section) | ||
| 241 | return -ERANGE; | ||
| 242 | |||
| 243 | oobregion->offset = 2; | ||
| 244 | oobregion->length = 5; | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static const struct mtd_ooblayout_ops docg4_ooblayout_ops = { | ||
| 250 | .ecc = docg4_ooblayout_ecc, | ||
| 251 | .free = docg4_ooblayout_free, | ||
| 229 | }; | 252 | }; |
| 230 | 253 | ||
| 231 | /* | 254 | /* |
| @@ -1209,6 +1232,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) | |||
| 1209 | mtd->writesize = DOCG4_PAGE_SIZE; | 1232 | mtd->writesize = DOCG4_PAGE_SIZE; |
| 1210 | mtd->erasesize = DOCG4_BLOCK_SIZE; | 1233 | mtd->erasesize = DOCG4_BLOCK_SIZE; |
| 1211 | mtd->oobsize = DOCG4_OOB_SIZE; | 1234 | mtd->oobsize = DOCG4_OOB_SIZE; |
| 1235 | mtd_set_ooblayout(mtd, &docg4_ooblayout_ops); | ||
| 1212 | nand->chipsize = DOCG4_CHIP_SIZE; | 1236 | nand->chipsize = DOCG4_CHIP_SIZE; |
| 1213 | nand->chip_shift = DOCG4_CHIP_SHIFT; | 1237 | nand->chip_shift = DOCG4_CHIP_SHIFT; |
| 1214 | nand->bbt_erase_shift = nand->phys_erase_shift = DOCG4_ERASE_SHIFT; | 1238 | nand->bbt_erase_shift = nand->phys_erase_shift = DOCG4_ERASE_SHIFT; |
| @@ -1217,7 +1241,6 @@ static void __init init_mtd_structs(struct mtd_info *mtd) | |||
| 1217 | nand->pagemask = 0x3ffff; | 1241 | nand->pagemask = 0x3ffff; |
| 1218 | nand->badblockpos = NAND_LARGE_BADBLOCK_POS; | 1242 | nand->badblockpos = NAND_LARGE_BADBLOCK_POS; |
| 1219 | nand->badblockbits = 8; | 1243 | nand->badblockbits = 8; |
| 1220 | nand->ecc.layout = &docg4_oobinfo; | ||
| 1221 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; | 1244 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
| 1222 | nand->ecc.size = DOCG4_PAGE_SIZE; | 1245 | nand->ecc.size = DOCG4_PAGE_SIZE; |
| 1223 | nand->ecc.prepad = 8; | 1246 | nand->ecc.prepad = 8; |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 059d5f7ec124..60a88f24c6b3 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
| @@ -79,32 +79,53 @@ struct fsl_elbc_fcm_ctrl { | |||
| 79 | 79 | ||
| 80 | /* These map to the positions used by the FCM hardware ECC generator */ | 80 | /* These map to the positions used by the FCM hardware ECC generator */ |
| 81 | 81 | ||
| 82 | /* Small Page FLASH with FMR[ECCM] = 0 */ | 82 | static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 83 | static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = { | 83 | struct mtd_oob_region *oobregion) |
| 84 | .eccbytes = 3, | 84 | { |
| 85 | .eccpos = {6, 7, 8}, | 85 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 86 | .oobfree = { {0, 5}, {9, 7} }, | 86 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
| 87 | }; | ||
| 88 | 87 | ||
| 89 | /* Small Page FLASH with FMR[ECCM] = 1 */ | 88 | if (section >= chip->ecc.steps) |
| 90 | static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = { | 89 | return -ERANGE; |
| 91 | .eccbytes = 3, | ||
| 92 | .eccpos = {8, 9, 10}, | ||
| 93 | .oobfree = { {0, 5}, {6, 2}, {11, 5} }, | ||
| 94 | }; | ||
| 95 | 90 | ||
| 96 | /* Large Page FLASH with FMR[ECCM] = 0 */ | 91 | oobregion->offset = (16 * section) + 6; |
| 97 | static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = { | 92 | if (priv->fmr & FMR_ECCM) |
| 98 | .eccbytes = 12, | 93 | oobregion->offset += 2; |
| 99 | .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56}, | ||
| 100 | .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} }, | ||
| 101 | }; | ||
| 102 | 94 | ||
| 103 | /* Large Page FLASH with FMR[ECCM] = 1 */ | 95 | oobregion->length = chip->ecc.bytes; |
| 104 | static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = { | 96 | |
| 105 | .eccbytes = 12, | 97 | return 0; |
| 106 | .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, | 98 | } |
| 107 | .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} }, | 99 | |
| 100 | static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 101 | struct mtd_oob_region *oobregion) | ||
| 102 | { | ||
| 103 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 104 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); | ||
| 105 | |||
| 106 | if (section > chip->ecc.steps) | ||
| 107 | return -ERANGE; | ||
| 108 | |||
| 109 | if (!section) { | ||
| 110 | oobregion->offset = 0; | ||
| 111 | if (mtd->writesize > 512) | ||
| 112 | oobregion->offset++; | ||
| 113 | oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5; | ||
| 114 | } else { | ||
| 115 | oobregion->offset = (16 * section) - | ||
| 116 | ((priv->fmr & FMR_ECCM) ? 5 : 7); | ||
| 117 | if (section < chip->ecc.steps) | ||
| 118 | oobregion->length = 13; | ||
| 119 | else | ||
| 120 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 121 | } | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = { | ||
| 127 | .ecc = fsl_elbc_ooblayout_ecc, | ||
| 128 | .free = fsl_elbc_ooblayout_free, | ||
| 108 | }; | 129 | }; |
| 109 | 130 | ||
| 110 | /* | 131 | /* |
| @@ -657,8 +678,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
| 657 | chip->ecc.bytes); | 678 | chip->ecc.bytes); |
| 658 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | 679 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", |
| 659 | chip->ecc.total); | 680 | chip->ecc.total); |
| 660 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", | 681 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n", |
| 661 | chip->ecc.layout); | 682 | mtd->ooblayout); |
| 662 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | 683 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); |
| 663 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | 684 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); |
| 664 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | 685 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", |
| @@ -675,14 +696,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
| 675 | } else if (mtd->writesize == 2048) { | 696 | } else if (mtd->writesize == 2048) { |
| 676 | priv->page_size = 1; | 697 | priv->page_size = 1; |
| 677 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | 698 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); |
| 678 | /* adjust ecc setup if needed */ | ||
| 679 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == | ||
| 680 | BR_DECC_CHK_GEN) { | ||
| 681 | chip->ecc.size = 512; | ||
| 682 | chip->ecc.layout = (priv->fmr & FMR_ECCM) ? | ||
| 683 | &fsl_elbc_oob_lp_eccm1 : | ||
| 684 | &fsl_elbc_oob_lp_eccm0; | ||
| 685 | } | ||
| 686 | } else { | 699 | } else { |
| 687 | dev_err(priv->dev, | 700 | dev_err(priv->dev, |
| 688 | "fsl_elbc_init: page size %d is not supported\n", | 701 | "fsl_elbc_init: page size %d is not supported\n", |
| @@ -780,15 +793,14 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
| 780 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == | 793 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == |
| 781 | BR_DECC_CHK_GEN) { | 794 | BR_DECC_CHK_GEN) { |
| 782 | chip->ecc.mode = NAND_ECC_HW; | 795 | chip->ecc.mode = NAND_ECC_HW; |
| 783 | /* put in small page settings and adjust later if needed */ | 796 | mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); |
| 784 | chip->ecc.layout = (priv->fmr & FMR_ECCM) ? | ||
| 785 | &fsl_elbc_oob_sp_eccm1 : &fsl_elbc_oob_sp_eccm0; | ||
| 786 | chip->ecc.size = 512; | 797 | chip->ecc.size = 512; |
| 787 | chip->ecc.bytes = 3; | 798 | chip->ecc.bytes = 3; |
| 788 | chip->ecc.strength = 1; | 799 | chip->ecc.strength = 1; |
| 789 | } else { | 800 | } else { |
| 790 | /* otherwise fall back to default software ECC */ | 801 | /* otherwise fall back to default software ECC */ |
| 791 | chip->ecc.mode = NAND_ECC_SOFT; | 802 | chip->ecc.mode = NAND_ECC_SOFT; |
| 803 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 792 | } | 804 | } |
| 793 | 805 | ||
| 794 | return 0; | 806 | return 0; |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 43f5a3a4873f..4e9e5fd8faf3 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
| @@ -67,136 +67,6 @@ struct fsl_ifc_nand_ctrl { | |||
| 67 | 67 | ||
| 68 | static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; | 68 | static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; |
| 69 | 69 | ||
| 70 | /* 512-byte page with 4-bit ECC, 8-bit */ | ||
| 71 | static struct nand_ecclayout oob_512_8bit_ecc4 = { | ||
| 72 | .eccbytes = 8, | ||
| 73 | .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, | ||
| 74 | .oobfree = { {0, 5}, {6, 2} }, | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* 512-byte page with 4-bit ECC, 16-bit */ | ||
| 78 | static struct nand_ecclayout oob_512_16bit_ecc4 = { | ||
| 79 | .eccbytes = 8, | ||
| 80 | .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, | ||
| 81 | .oobfree = { {2, 6}, }, | ||
| 82 | }; | ||
| 83 | |||
| 84 | /* 2048-byte page size with 4-bit ECC */ | ||
| 85 | static struct nand_ecclayout oob_2048_ecc4 = { | ||
| 86 | .eccbytes = 32, | ||
| 87 | .eccpos = { | ||
| 88 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 89 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
| 90 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 91 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 92 | }, | ||
| 93 | .oobfree = { {2, 6}, {40, 24} }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* 4096-byte page size with 4-bit ECC */ | ||
| 97 | static struct nand_ecclayout oob_4096_ecc4 = { | ||
| 98 | .eccbytes = 64, | ||
| 99 | .eccpos = { | ||
| 100 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 101 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
| 102 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 103 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 104 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 105 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 106 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 107 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
| 108 | }, | ||
| 109 | .oobfree = { {2, 6}, {72, 56} }, | ||
| 110 | }; | ||
| 111 | |||
| 112 | /* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */ | ||
| 113 | static struct nand_ecclayout oob_4096_ecc8 = { | ||
| 114 | .eccbytes = 128, | ||
| 115 | .eccpos = { | ||
| 116 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 117 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
| 118 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 119 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 120 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 121 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 122 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 123 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
| 124 | 72, 73, 74, 75, 76, 77, 78, 79, | ||
| 125 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
| 126 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
| 127 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
| 128 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 129 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
| 130 | 120, 121, 122, 123, 124, 125, 126, 127, | ||
| 131 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
| 132 | }, | ||
| 133 | .oobfree = { {2, 6}, {136, 82} }, | ||
| 134 | }; | ||
| 135 | |||
| 136 | /* 8192-byte page size with 4-bit ECC */ | ||
| 137 | static struct nand_ecclayout oob_8192_ecc4 = { | ||
| 138 | .eccbytes = 128, | ||
| 139 | .eccpos = { | ||
| 140 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 141 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
| 142 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 143 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 144 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 145 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 146 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 147 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
| 148 | 72, 73, 74, 75, 76, 77, 78, 79, | ||
| 149 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
| 150 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
| 151 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
| 152 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 153 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
| 154 | 120, 121, 122, 123, 124, 125, 126, 127, | ||
| 155 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
| 156 | }, | ||
| 157 | .oobfree = { {2, 6}, {136, 208} }, | ||
| 158 | }; | ||
| 159 | |||
| 160 | /* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */ | ||
| 161 | static struct nand_ecclayout oob_8192_ecc8 = { | ||
| 162 | .eccbytes = 256, | ||
| 163 | .eccpos = { | ||
| 164 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 165 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
| 166 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 167 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 168 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 169 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 170 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 171 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
| 172 | 72, 73, 74, 75, 76, 77, 78, 79, | ||
| 173 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
| 174 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
| 175 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
| 176 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 177 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
| 178 | 120, 121, 122, 123, 124, 125, 126, 127, | ||
| 179 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
| 180 | 136, 137, 138, 139, 140, 141, 142, 143, | ||
| 181 | 144, 145, 146, 147, 148, 149, 150, 151, | ||
| 182 | 152, 153, 154, 155, 156, 157, 158, 159, | ||
| 183 | 160, 161, 162, 163, 164, 165, 166, 167, | ||
| 184 | 168, 169, 170, 171, 172, 173, 174, 175, | ||
| 185 | 176, 177, 178, 179, 180, 181, 182, 183, | ||
| 186 | 184, 185, 186, 187, 188, 189, 190, 191, | ||
| 187 | 192, 193, 194, 195, 196, 197, 198, 199, | ||
| 188 | 200, 201, 202, 203, 204, 205, 206, 207, | ||
| 189 | 208, 209, 210, 211, 212, 213, 214, 215, | ||
| 190 | 216, 217, 218, 219, 220, 221, 222, 223, | ||
| 191 | 224, 225, 226, 227, 228, 229, 230, 231, | ||
| 192 | 232, 233, 234, 235, 236, 237, 238, 239, | ||
| 193 | 240, 241, 242, 243, 244, 245, 246, 247, | ||
| 194 | 248, 249, 250, 251, 252, 253, 254, 255, | ||
| 195 | 256, 257, 258, 259, 260, 261, 262, 263, | ||
| 196 | }, | ||
| 197 | .oobfree = { {2, 6}, {264, 80} }, | ||
| 198 | }; | ||
| 199 | |||
| 200 | /* | 70 | /* |
| 201 | * Generic flash bbt descriptors | 71 | * Generic flash bbt descriptors |
| 202 | */ | 72 | */ |
| @@ -223,6 +93,57 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
| 223 | .pattern = mirror_pattern, | 93 | .pattern = mirror_pattern, |
| 224 | }; | 94 | }; |
| 225 | 95 | ||
| 96 | static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 97 | struct mtd_oob_region *oobregion) | ||
| 98 | { | ||
| 99 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 100 | |||
| 101 | if (section) | ||
| 102 | return -ERANGE; | ||
| 103 | |||
| 104 | oobregion->offset = 8; | ||
| 105 | oobregion->length = chip->ecc.total; | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 111 | struct mtd_oob_region *oobregion) | ||
| 112 | { | ||
| 113 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 114 | |||
| 115 | if (section > 1) | ||
| 116 | return -ERANGE; | ||
| 117 | |||
| 118 | if (mtd->writesize == 512 && | ||
| 119 | !(chip->options & NAND_BUSWIDTH_16)) { | ||
| 120 | if (!section) { | ||
| 121 | oobregion->offset = 0; | ||
| 122 | oobregion->length = 5; | ||
| 123 | } else { | ||
| 124 | oobregion->offset = 6; | ||
| 125 | oobregion->length = 2; | ||
| 126 | } | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (!section) { | ||
| 132 | oobregion->offset = 2; | ||
| 133 | oobregion->length = 6; | ||
| 134 | } else { | ||
| 135 | oobregion->offset = chip->ecc.total + 8; | ||
| 136 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 137 | } | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | static const struct mtd_ooblayout_ops fsl_ifc_ooblayout_ops = { | ||
| 143 | .ecc = fsl_ifc_ooblayout_ecc, | ||
| 144 | .free = fsl_ifc_ooblayout_free, | ||
| 145 | }; | ||
| 146 | |||
| 226 | /* | 147 | /* |
| 227 | * Set up the IFC hardware block and page address fields, and the ifc nand | 148 | * Set up the IFC hardware block and page address fields, and the ifc nand |
| 228 | * structure addr field to point to the correct IFC buffer in memory | 149 | * structure addr field to point to the correct IFC buffer in memory |
| @@ -232,7 +153,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
| 232 | struct nand_chip *chip = mtd_to_nand(mtd); | 153 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 233 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 154 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 234 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 155 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 235 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 156 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 236 | int buf_num; | 157 | int buf_num; |
| 237 | 158 | ||
| 238 | ifc_nand_ctrl->page = page_addr; | 159 | ifc_nand_ctrl->page = page_addr; |
| @@ -257,18 +178,22 @@ static int is_blank(struct mtd_info *mtd, unsigned int bufnum) | |||
| 257 | u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); | 178 | u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); |
| 258 | u32 __iomem *mainarea = (u32 __iomem *)addr; | 179 | u32 __iomem *mainarea = (u32 __iomem *)addr; |
| 259 | u8 __iomem *oob = addr + mtd->writesize; | 180 | u8 __iomem *oob = addr + mtd->writesize; |
| 260 | int i; | 181 | struct mtd_oob_region oobregion = { }; |
| 182 | int i, section = 0; | ||
| 261 | 183 | ||
| 262 | for (i = 0; i < mtd->writesize / 4; i++) { | 184 | for (i = 0; i < mtd->writesize / 4; i++) { |
| 263 | if (__raw_readl(&mainarea[i]) != 0xffffffff) | 185 | if (__raw_readl(&mainarea[i]) != 0xffffffff) |
| 264 | return 0; | 186 | return 0; |
| 265 | } | 187 | } |
| 266 | 188 | ||
| 267 | for (i = 0; i < chip->ecc.layout->eccbytes; i++) { | 189 | mtd_ooblayout_ecc(mtd, section++, &oobregion); |
| 268 | int pos = chip->ecc.layout->eccpos[i]; | 190 | while (oobregion.length) { |
| 191 | for (i = 0; i < oobregion.length; i++) { | ||
| 192 | if (__raw_readb(&oob[oobregion.offset + i]) != 0xff) | ||
| 193 | return 0; | ||
| 194 | } | ||
| 269 | 195 | ||
| 270 | if (__raw_readb(&oob[pos]) != 0xff) | 196 | mtd_ooblayout_ecc(mtd, section++, &oobregion); |
| 271 | return 0; | ||
| 272 | } | 197 | } |
| 273 | 198 | ||
| 274 | return 1; | 199 | return 1; |
| @@ -295,7 +220,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) | |||
| 295 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 220 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 296 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 221 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 297 | struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; | 222 | struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; |
| 298 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 223 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 299 | u32 eccstat[4]; | 224 | u32 eccstat[4]; |
| 300 | int i; | 225 | int i; |
| 301 | 226 | ||
| @@ -371,7 +296,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, | |||
| 371 | { | 296 | { |
| 372 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 297 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 373 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 298 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 374 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 299 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 375 | 300 | ||
| 376 | /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ | 301 | /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ |
| 377 | if (mtd->writesize > 512) { | 302 | if (mtd->writesize > 512) { |
| @@ -411,7 +336,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
| 411 | struct nand_chip *chip = mtd_to_nand(mtd); | 336 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 412 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 337 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 413 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 338 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 414 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 339 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 415 | 340 | ||
| 416 | /* clear the read buffer */ | 341 | /* clear the read buffer */ |
| 417 | ifc_nand_ctrl->read_bytes = 0; | 342 | ifc_nand_ctrl->read_bytes = 0; |
| @@ -723,7 +648,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
| 723 | { | 648 | { |
| 724 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 649 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 725 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 650 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 726 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 651 | struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; |
| 727 | u32 nand_fsr; | 652 | u32 nand_fsr; |
| 728 | 653 | ||
| 729 | /* Use READ_STATUS command, but wait for the device to be ready */ | 654 | /* Use READ_STATUS command, but wait for the device to be ready */ |
| @@ -808,8 +733,8 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) | |||
| 808 | chip->ecc.bytes); | 733 | chip->ecc.bytes); |
| 809 | dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__, | 734 | dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__, |
| 810 | chip->ecc.total); | 735 | chip->ecc.total); |
| 811 | dev_dbg(priv->dev, "%s: nand->ecc.layout = %p\n", __func__, | 736 | dev_dbg(priv->dev, "%s: mtd->ooblayout = %p\n", __func__, |
| 812 | chip->ecc.layout); | 737 | mtd->ooblayout); |
| 813 | dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags); | 738 | dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags); |
| 814 | dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size); | 739 | dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size); |
| 815 | dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__, | 740 | dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__, |
| @@ -825,39 +750,42 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) | |||
| 825 | static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) | 750 | static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) |
| 826 | { | 751 | { |
| 827 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 752 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 828 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 753 | struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; |
| 754 | struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs; | ||
| 829 | uint32_t csor = 0, csor_8k = 0, csor_ext = 0; | 755 | uint32_t csor = 0, csor_8k = 0, csor_ext = 0; |
| 830 | uint32_t cs = priv->bank; | 756 | uint32_t cs = priv->bank; |
| 831 | 757 | ||
| 832 | /* Save CSOR and CSOR_ext */ | 758 | /* Save CSOR and CSOR_ext */ |
| 833 | csor = ifc_in32(&ifc->csor_cs[cs].csor); | 759 | csor = ifc_in32(&ifc_global->csor_cs[cs].csor); |
| 834 | csor_ext = ifc_in32(&ifc->csor_cs[cs].csor_ext); | 760 | csor_ext = ifc_in32(&ifc_global->csor_cs[cs].csor_ext); |
| 835 | 761 | ||
| 836 | /* chage PageSize 8K and SpareSize 1K*/ | 762 | /* chage PageSize 8K and SpareSize 1K*/ |
| 837 | csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; | 763 | csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; |
| 838 | ifc_out32(csor_8k, &ifc->csor_cs[cs].csor); | 764 | ifc_out32(csor_8k, &ifc_global->csor_cs[cs].csor); |
| 839 | ifc_out32(0x0000400, &ifc->csor_cs[cs].csor_ext); | 765 | ifc_out32(0x0000400, &ifc_global->csor_cs[cs].csor_ext); |
| 840 | 766 | ||
| 841 | /* READID */ | 767 | /* READID */ |
| 842 | ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | 768 | ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | |
| 843 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | | 769 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | |
| 844 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), | 770 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), |
| 845 | &ifc->ifc_nand.nand_fir0); | 771 | &ifc_runtime->ifc_nand.nand_fir0); |
| 846 | ifc_out32(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, | 772 | ifc_out32(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, |
| 847 | &ifc->ifc_nand.nand_fcr0); | 773 | &ifc_runtime->ifc_nand.nand_fcr0); |
| 848 | ifc_out32(0x0, &ifc->ifc_nand.row3); | 774 | ifc_out32(0x0, &ifc_runtime->ifc_nand.row3); |
| 849 | 775 | ||
| 850 | ifc_out32(0x0, &ifc->ifc_nand.nand_fbcr); | 776 | ifc_out32(0x0, &ifc_runtime->ifc_nand.nand_fbcr); |
| 851 | 777 | ||
| 852 | /* Program ROW0/COL0 */ | 778 | /* Program ROW0/COL0 */ |
| 853 | ifc_out32(0x0, &ifc->ifc_nand.row0); | 779 | ifc_out32(0x0, &ifc_runtime->ifc_nand.row0); |
| 854 | ifc_out32(0x0, &ifc->ifc_nand.col0); | 780 | ifc_out32(0x0, &ifc_runtime->ifc_nand.col0); |
| 855 | 781 | ||
| 856 | /* set the chip select for NAND Transaction */ | 782 | /* set the chip select for NAND Transaction */ |
| 857 | ifc_out32(cs << IFC_NAND_CSEL_SHIFT, &ifc->ifc_nand.nand_csel); | 783 | ifc_out32(cs << IFC_NAND_CSEL_SHIFT, |
| 784 | &ifc_runtime->ifc_nand.nand_csel); | ||
| 858 | 785 | ||
| 859 | /* start read seq */ | 786 | /* start read seq */ |
| 860 | ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); | 787 | ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, |
| 788 | &ifc_runtime->ifc_nand.nandseq_strt); | ||
| 861 | 789 | ||
| 862 | /* wait for command complete flag or timeout */ | 790 | /* wait for command complete flag or timeout */ |
| 863 | wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, | 791 | wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, |
| @@ -867,17 +795,17 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) | |||
| 867 | printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); | 795 | printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); |
| 868 | 796 | ||
| 869 | /* Restore CSOR and CSOR_ext */ | 797 | /* Restore CSOR and CSOR_ext */ |
| 870 | ifc_out32(csor, &ifc->csor_cs[cs].csor); | 798 | ifc_out32(csor, &ifc_global->csor_cs[cs].csor); |
| 871 | ifc_out32(csor_ext, &ifc->csor_cs[cs].csor_ext); | 799 | ifc_out32(csor_ext, &ifc_global->csor_cs[cs].csor_ext); |
| 872 | } | 800 | } |
| 873 | 801 | ||
| 874 | static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | 802 | static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) |
| 875 | { | 803 | { |
| 876 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 804 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
| 877 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 805 | struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs; |
| 806 | struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; | ||
| 878 | struct nand_chip *chip = &priv->chip; | 807 | struct nand_chip *chip = &priv->chip; |
| 879 | struct mtd_info *mtd = nand_to_mtd(&priv->chip); | 808 | struct mtd_info *mtd = nand_to_mtd(&priv->chip); |
| 880 | struct nand_ecclayout *layout; | ||
| 881 | u32 csor; | 809 | u32 csor; |
| 882 | 810 | ||
| 883 | /* Fill in fsl_ifc_mtd structure */ | 811 | /* Fill in fsl_ifc_mtd structure */ |
| @@ -886,7 +814,8 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
| 886 | 814 | ||
| 887 | /* fill in nand_chip structure */ | 815 | /* fill in nand_chip structure */ |
| 888 | /* set up function call table */ | 816 | /* set up function call table */ |
| 889 | if ((ifc_in32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) | 817 | if ((ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr)) |
| 818 | & CSPR_PORT_SIZE_16) | ||
| 890 | chip->read_byte = fsl_ifc_read_byte16; | 819 | chip->read_byte = fsl_ifc_read_byte16; |
| 891 | else | 820 | else |
| 892 | chip->read_byte = fsl_ifc_read_byte; | 821 | chip->read_byte = fsl_ifc_read_byte; |
| @@ -900,13 +829,14 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
| 900 | chip->bbt_td = &bbt_main_descr; | 829 | chip->bbt_td = &bbt_main_descr; |
| 901 | chip->bbt_md = &bbt_mirror_descr; | 830 | chip->bbt_md = &bbt_mirror_descr; |
| 902 | 831 | ||
| 903 | ifc_out32(0x0, &ifc->ifc_nand.ncfgr); | 832 | ifc_out32(0x0, &ifc_runtime->ifc_nand.ncfgr); |
| 904 | 833 | ||
| 905 | /* set up nand options */ | 834 | /* set up nand options */ |
| 906 | chip->bbt_options = NAND_BBT_USE_FLASH; | 835 | chip->bbt_options = NAND_BBT_USE_FLASH; |
| 907 | chip->options = NAND_NO_SUBPAGE_WRITE; | 836 | chip->options = NAND_NO_SUBPAGE_WRITE; |
| 908 | 837 | ||
| 909 | if (ifc_in32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { | 838 | if (ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr) |
| 839 | & CSPR_PORT_SIZE_16) { | ||
| 910 | chip->read_byte = fsl_ifc_read_byte16; | 840 | chip->read_byte = fsl_ifc_read_byte16; |
| 911 | chip->options |= NAND_BUSWIDTH_16; | 841 | chip->options |= NAND_BUSWIDTH_16; |
| 912 | } else { | 842 | } else { |
| @@ -919,20 +849,11 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
| 919 | chip->ecc.read_page = fsl_ifc_read_page; | 849 | chip->ecc.read_page = fsl_ifc_read_page; |
| 920 | chip->ecc.write_page = fsl_ifc_write_page; | 850 | chip->ecc.write_page = fsl_ifc_write_page; |
| 921 | 851 | ||
| 922 | csor = ifc_in32(&ifc->csor_cs[priv->bank].csor); | 852 | csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor); |
| 923 | |||
| 924 | /* Hardware generates ECC per 512 Bytes */ | ||
| 925 | chip->ecc.size = 512; | ||
| 926 | chip->ecc.bytes = 8; | ||
| 927 | chip->ecc.strength = 4; | ||
| 928 | 853 | ||
| 929 | switch (csor & CSOR_NAND_PGS_MASK) { | 854 | switch (csor & CSOR_NAND_PGS_MASK) { |
| 930 | case CSOR_NAND_PGS_512: | 855 | case CSOR_NAND_PGS_512: |
| 931 | if (chip->options & NAND_BUSWIDTH_16) { | 856 | if (!(chip->options & NAND_BUSWIDTH_16)) { |
| 932 | layout = &oob_512_16bit_ecc4; | ||
| 933 | } else { | ||
| 934 | layout = &oob_512_8bit_ecc4; | ||
| 935 | |||
| 936 | /* Avoid conflict with bad block marker */ | 857 | /* Avoid conflict with bad block marker */ |
| 937 | bbt_main_descr.offs = 0; | 858 | bbt_main_descr.offs = 0; |
| 938 | bbt_mirror_descr.offs = 0; | 859 | bbt_mirror_descr.offs = 0; |
| @@ -942,35 +863,16 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
| 942 | break; | 863 | break; |
| 943 | 864 | ||
| 944 | case CSOR_NAND_PGS_2K: | 865 | case CSOR_NAND_PGS_2K: |
| 945 | layout = &oob_2048_ecc4; | ||
| 946 | priv->bufnum_mask = 3; | 866 | priv->bufnum_mask = 3; |
| 947 | break; | 867 | break; |
| 948 | 868 | ||
| 949 | case CSOR_NAND_PGS_4K: | 869 | case CSOR_NAND_PGS_4K: |
| 950 | if ((csor & CSOR_NAND_ECC_MODE_MASK) == | ||
| 951 | CSOR_NAND_ECC_MODE_4) { | ||
| 952 | layout = &oob_4096_ecc4; | ||
| 953 | } else { | ||
| 954 | layout = &oob_4096_ecc8; | ||
| 955 | chip->ecc.bytes = 16; | ||
| 956 | chip->ecc.strength = 8; | ||
| 957 | } | ||
| 958 | |||
| 959 | priv->bufnum_mask = 1; | 870 | priv->bufnum_mask = 1; |
| 960 | break; | 871 | break; |
| 961 | 872 | ||
| 962 | case CSOR_NAND_PGS_8K: | 873 | case CSOR_NAND_PGS_8K: |
| 963 | if ((csor & CSOR_NAND_ECC_MODE_MASK) == | ||
| 964 | CSOR_NAND_ECC_MODE_4) { | ||
| 965 | layout = &oob_8192_ecc4; | ||
| 966 | } else { | ||
| 967 | layout = &oob_8192_ecc8; | ||
| 968 | chip->ecc.bytes = 16; | ||
| 969 | chip->ecc.strength = 8; | ||
| 970 | } | ||
| 971 | |||
| 972 | priv->bufnum_mask = 0; | 874 | priv->bufnum_mask = 0; |
| 973 | break; | 875 | break; |
| 974 | 876 | ||
| 975 | default: | 877 | default: |
| 976 | dev_err(priv->dev, "bad csor %#x: bad page size\n", csor); | 878 | dev_err(priv->dev, "bad csor %#x: bad page size\n", csor); |
| @@ -980,9 +882,20 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
| 980 | /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */ | 882 | /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */ |
| 981 | if (csor & CSOR_NAND_ECC_DEC_EN) { | 883 | if (csor & CSOR_NAND_ECC_DEC_EN) { |
| 982 | chip->ecc.mode = NAND_ECC_HW; | 884 | chip->ecc.mode = NAND_ECC_HW; |
| 983 | chip->ecc.layout = layout; | 885 | mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops); |
| 886 | |||
| 887 | /* Hardware generates ECC per 512 Bytes */ | ||
| 888 | chip->ecc.size = 512; | ||
| 889 | if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) { | ||
| 890 | chip->ecc.bytes = 8; | ||
| 891 | chip->ecc.strength = 4; | ||
| 892 | } else { | ||
| 893 | chip->ecc.bytes = 16; | ||
| 894 | chip->ecc.strength = 8; | ||
| 895 | } | ||
| 984 | } else { | 896 | } else { |
| 985 | chip->ecc.mode = NAND_ECC_SOFT; | 897 | chip->ecc.mode = NAND_ECC_SOFT; |
| 898 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 986 | } | 899 | } |
| 987 | 900 | ||
| 988 | if (ctrl->version == FSL_IFC_VERSION_1_1_0) | 901 | if (ctrl->version == FSL_IFC_VERSION_1_1_0) |
| @@ -1007,10 +920,10 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) | |||
| 1007 | return 0; | 920 | return 0; |
| 1008 | } | 921 | } |
| 1009 | 922 | ||
| 1010 | static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, | 923 | static int match_bank(struct fsl_ifc_global __iomem *ifc_global, int bank, |
| 1011 | phys_addr_t addr) | 924 | phys_addr_t addr) |
| 1012 | { | 925 | { |
| 1013 | u32 cspr = ifc_in32(&ifc->cspr_cs[bank].cspr); | 926 | u32 cspr = ifc_in32(&ifc_global->cspr_cs[bank].cspr); |
| 1014 | 927 | ||
| 1015 | if (!(cspr & CSPR_V)) | 928 | if (!(cspr & CSPR_V)) |
| 1016 | return 0; | 929 | return 0; |
| @@ -1024,7 +937,7 @@ static DEFINE_MUTEX(fsl_ifc_nand_mutex); | |||
| 1024 | 937 | ||
| 1025 | static int fsl_ifc_nand_probe(struct platform_device *dev) | 938 | static int fsl_ifc_nand_probe(struct platform_device *dev) |
| 1026 | { | 939 | { |
| 1027 | struct fsl_ifc_regs __iomem *ifc; | 940 | struct fsl_ifc_runtime __iomem *ifc; |
| 1028 | struct fsl_ifc_mtd *priv; | 941 | struct fsl_ifc_mtd *priv; |
| 1029 | struct resource res; | 942 | struct resource res; |
| 1030 | static const char *part_probe_types[] | 943 | static const char *part_probe_types[] |
| @@ -1034,9 +947,9 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) | |||
| 1034 | struct device_node *node = dev->dev.of_node; | 947 | struct device_node *node = dev->dev.of_node; |
| 1035 | struct mtd_info *mtd; | 948 | struct mtd_info *mtd; |
| 1036 | 949 | ||
| 1037 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) | 950 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->rregs) |
| 1038 | return -ENODEV; | 951 | return -ENODEV; |
| 1039 | ifc = fsl_ifc_ctrl_dev->regs; | 952 | ifc = fsl_ifc_ctrl_dev->rregs; |
| 1040 | 953 | ||
| 1041 | /* get, allocate and map the memory resource */ | 954 | /* get, allocate and map the memory resource */ |
| 1042 | ret = of_address_to_resource(node, 0, &res); | 955 | ret = of_address_to_resource(node, 0, &res); |
| @@ -1047,7 +960,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) | |||
| 1047 | 960 | ||
| 1048 | /* find which chip select it is connected to */ | 961 | /* find which chip select it is connected to */ |
| 1049 | for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) { | 962 | for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) { |
| 1050 | if (match_bank(ifc, bank, res.start)) | 963 | if (match_bank(fsl_ifc_ctrl_dev->gregs, bank, res.start)) |
| 1051 | break; | 964 | break; |
| 1052 | } | 965 | } |
| 1053 | 966 | ||
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index cafd12de7276..d85fa2555b68 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
| @@ -170,6 +170,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, | |||
| 170 | fun->chip.read_buf = fun_read_buf; | 170 | fun->chip.read_buf = fun_read_buf; |
| 171 | fun->chip.write_buf = fun_write_buf; | 171 | fun->chip.write_buf = fun_write_buf; |
| 172 | fun->chip.ecc.mode = NAND_ECC_SOFT; | 172 | fun->chip.ecc.mode = NAND_ECC_SOFT; |
| 173 | fun->chip.ecc.algo = NAND_ECC_HAMMING; | ||
| 173 | if (fun->mchip_count > 1) | 174 | if (fun->mchip_count > 1) |
| 174 | fun->chip.select_chip = fun_select_chip; | 175 | fun->chip.select_chip = fun_select_chip; |
| 175 | 176 | ||
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 1bdcd4fa26d4..d4f454a4b35e 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
| @@ -39,210 +39,41 @@ | |||
| 39 | #include <linux/amba/bus.h> | 39 | #include <linux/amba/bus.h> |
| 40 | #include <mtd/mtd-abi.h> | 40 | #include <mtd/mtd-abi.h> |
| 41 | 41 | ||
| 42 | static struct nand_ecclayout fsmc_ecc1_128_layout = { | 42 | static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 43 | .eccbytes = 24, | 43 | struct mtd_oob_region *oobregion) |
| 44 | .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52, | 44 | { |
| 45 | 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116}, | 45 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 46 | .oobfree = { | ||
| 47 | {.offset = 8, .length = 8}, | ||
| 48 | {.offset = 24, .length = 8}, | ||
| 49 | {.offset = 40, .length = 8}, | ||
| 50 | {.offset = 56, .length = 8}, | ||
| 51 | {.offset = 72, .length = 8}, | ||
| 52 | {.offset = 88, .length = 8}, | ||
| 53 | {.offset = 104, .length = 8}, | ||
| 54 | {.offset = 120, .length = 8} | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | 46 | ||
| 58 | static struct nand_ecclayout fsmc_ecc1_64_layout = { | 47 | if (section >= chip->ecc.steps) |
| 59 | .eccbytes = 12, | 48 | return -ERANGE; |
| 60 | .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52}, | ||
| 61 | .oobfree = { | ||
| 62 | {.offset = 8, .length = 8}, | ||
| 63 | {.offset = 24, .length = 8}, | ||
| 64 | {.offset = 40, .length = 8}, | ||
| 65 | {.offset = 56, .length = 8}, | ||
| 66 | } | ||
| 67 | }; | ||
| 68 | 49 | ||
| 69 | static struct nand_ecclayout fsmc_ecc1_16_layout = { | 50 | oobregion->offset = (section * 16) + 2; |
| 70 | .eccbytes = 3, | 51 | oobregion->length = 3; |
| 71 | .eccpos = {2, 3, 4}, | ||
| 72 | .oobfree = { | ||
| 73 | {.offset = 8, .length = 8}, | ||
| 74 | } | ||
| 75 | }; | ||
| 76 | 52 | ||
| 77 | /* | 53 | return 0; |
| 78 | * ECC4 layout for NAND of pagesize 8192 bytes & OOBsize 256 bytes. 13*16 bytes | 54 | } |
| 79 | * of OB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block and 46 | ||
| 80 | * bytes are free for use. | ||
| 81 | */ | ||
| 82 | static struct nand_ecclayout fsmc_ecc4_256_layout = { | ||
| 83 | .eccbytes = 208, | ||
| 84 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
| 85 | 9, 10, 11, 12, 13, 14, | ||
| 86 | 18, 19, 20, 21, 22, 23, 24, | ||
| 87 | 25, 26, 27, 28, 29, 30, | ||
| 88 | 34, 35, 36, 37, 38, 39, 40, | ||
| 89 | 41, 42, 43, 44, 45, 46, | ||
| 90 | 50, 51, 52, 53, 54, 55, 56, | ||
| 91 | 57, 58, 59, 60, 61, 62, | ||
| 92 | 66, 67, 68, 69, 70, 71, 72, | ||
| 93 | 73, 74, 75, 76, 77, 78, | ||
| 94 | 82, 83, 84, 85, 86, 87, 88, | ||
| 95 | 89, 90, 91, 92, 93, 94, | ||
| 96 | 98, 99, 100, 101, 102, 103, 104, | ||
| 97 | 105, 106, 107, 108, 109, 110, | ||
| 98 | 114, 115, 116, 117, 118, 119, 120, | ||
| 99 | 121, 122, 123, 124, 125, 126, | ||
| 100 | 130, 131, 132, 133, 134, 135, 136, | ||
| 101 | 137, 138, 139, 140, 141, 142, | ||
| 102 | 146, 147, 148, 149, 150, 151, 152, | ||
| 103 | 153, 154, 155, 156, 157, 158, | ||
| 104 | 162, 163, 164, 165, 166, 167, 168, | ||
| 105 | 169, 170, 171, 172, 173, 174, | ||
| 106 | 178, 179, 180, 181, 182, 183, 184, | ||
| 107 | 185, 186, 187, 188, 189, 190, | ||
| 108 | 194, 195, 196, 197, 198, 199, 200, | ||
| 109 | 201, 202, 203, 204, 205, 206, | ||
| 110 | 210, 211, 212, 213, 214, 215, 216, | ||
| 111 | 217, 218, 219, 220, 221, 222, | ||
| 112 | 226, 227, 228, 229, 230, 231, 232, | ||
| 113 | 233, 234, 235, 236, 237, 238, | ||
| 114 | 242, 243, 244, 245, 246, 247, 248, | ||
| 115 | 249, 250, 251, 252, 253, 254 | ||
| 116 | }, | ||
| 117 | .oobfree = { | ||
| 118 | {.offset = 15, .length = 3}, | ||
| 119 | {.offset = 31, .length = 3}, | ||
| 120 | {.offset = 47, .length = 3}, | ||
| 121 | {.offset = 63, .length = 3}, | ||
| 122 | {.offset = 79, .length = 3}, | ||
| 123 | {.offset = 95, .length = 3}, | ||
| 124 | {.offset = 111, .length = 3}, | ||
| 125 | {.offset = 127, .length = 3}, | ||
| 126 | {.offset = 143, .length = 3}, | ||
| 127 | {.offset = 159, .length = 3}, | ||
| 128 | {.offset = 175, .length = 3}, | ||
| 129 | {.offset = 191, .length = 3}, | ||
| 130 | {.offset = 207, .length = 3}, | ||
| 131 | {.offset = 223, .length = 3}, | ||
| 132 | {.offset = 239, .length = 3}, | ||
| 133 | {.offset = 255, .length = 1} | ||
| 134 | } | ||
| 135 | }; | ||
| 136 | 55 | ||
| 137 | /* | 56 | static int fsmc_ecc1_ooblayout_free(struct mtd_info *mtd, int section, |
| 138 | * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes | 57 | struct mtd_oob_region *oobregion) |
| 139 | * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118 | 58 | { |
| 140 | * bytes are free for use. | 59 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 141 | */ | ||
| 142 | static struct nand_ecclayout fsmc_ecc4_224_layout = { | ||
| 143 | .eccbytes = 104, | ||
| 144 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
| 145 | 9, 10, 11, 12, 13, 14, | ||
| 146 | 18, 19, 20, 21, 22, 23, 24, | ||
| 147 | 25, 26, 27, 28, 29, 30, | ||
| 148 | 34, 35, 36, 37, 38, 39, 40, | ||
| 149 | 41, 42, 43, 44, 45, 46, | ||
| 150 | 50, 51, 52, 53, 54, 55, 56, | ||
| 151 | 57, 58, 59, 60, 61, 62, | ||
| 152 | 66, 67, 68, 69, 70, 71, 72, | ||
| 153 | 73, 74, 75, 76, 77, 78, | ||
| 154 | 82, 83, 84, 85, 86, 87, 88, | ||
| 155 | 89, 90, 91, 92, 93, 94, | ||
| 156 | 98, 99, 100, 101, 102, 103, 104, | ||
| 157 | 105, 106, 107, 108, 109, 110, | ||
| 158 | 114, 115, 116, 117, 118, 119, 120, | ||
| 159 | 121, 122, 123, 124, 125, 126 | ||
| 160 | }, | ||
| 161 | .oobfree = { | ||
| 162 | {.offset = 15, .length = 3}, | ||
| 163 | {.offset = 31, .length = 3}, | ||
| 164 | {.offset = 47, .length = 3}, | ||
| 165 | {.offset = 63, .length = 3}, | ||
| 166 | {.offset = 79, .length = 3}, | ||
| 167 | {.offset = 95, .length = 3}, | ||
| 168 | {.offset = 111, .length = 3}, | ||
| 169 | {.offset = 127, .length = 97} | ||
| 170 | } | ||
| 171 | }; | ||
| 172 | 60 | ||
| 173 | /* | 61 | if (section >= chip->ecc.steps) |
| 174 | * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 128 bytes. 13*8 bytes | 62 | return -ERANGE; |
| 175 | * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 22 | ||
| 176 | * bytes are free for use. | ||
| 177 | */ | ||
| 178 | static struct nand_ecclayout fsmc_ecc4_128_layout = { | ||
| 179 | .eccbytes = 104, | ||
| 180 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
| 181 | 9, 10, 11, 12, 13, 14, | ||
| 182 | 18, 19, 20, 21, 22, 23, 24, | ||
| 183 | 25, 26, 27, 28, 29, 30, | ||
| 184 | 34, 35, 36, 37, 38, 39, 40, | ||
| 185 | 41, 42, 43, 44, 45, 46, | ||
| 186 | 50, 51, 52, 53, 54, 55, 56, | ||
| 187 | 57, 58, 59, 60, 61, 62, | ||
| 188 | 66, 67, 68, 69, 70, 71, 72, | ||
| 189 | 73, 74, 75, 76, 77, 78, | ||
| 190 | 82, 83, 84, 85, 86, 87, 88, | ||
| 191 | 89, 90, 91, 92, 93, 94, | ||
| 192 | 98, 99, 100, 101, 102, 103, 104, | ||
| 193 | 105, 106, 107, 108, 109, 110, | ||
| 194 | 114, 115, 116, 117, 118, 119, 120, | ||
| 195 | 121, 122, 123, 124, 125, 126 | ||
| 196 | }, | ||
| 197 | .oobfree = { | ||
| 198 | {.offset = 15, .length = 3}, | ||
| 199 | {.offset = 31, .length = 3}, | ||
| 200 | {.offset = 47, .length = 3}, | ||
| 201 | {.offset = 63, .length = 3}, | ||
| 202 | {.offset = 79, .length = 3}, | ||
| 203 | {.offset = 95, .length = 3}, | ||
| 204 | {.offset = 111, .length = 3}, | ||
| 205 | {.offset = 127, .length = 1} | ||
| 206 | } | ||
| 207 | }; | ||
| 208 | 63 | ||
| 209 | /* | 64 | oobregion->offset = (section * 16) + 8; |
| 210 | * ECC4 layout for NAND of pagesize 2048 bytes & OOBsize 64 bytes. 13*4 bytes of | ||
| 211 | * OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block and 10 | ||
| 212 | * bytes are free for use. | ||
| 213 | */ | ||
| 214 | static struct nand_ecclayout fsmc_ecc4_64_layout = { | ||
| 215 | .eccbytes = 52, | ||
| 216 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
| 217 | 9, 10, 11, 12, 13, 14, | ||
| 218 | 18, 19, 20, 21, 22, 23, 24, | ||
| 219 | 25, 26, 27, 28, 29, 30, | ||
| 220 | 34, 35, 36, 37, 38, 39, 40, | ||
| 221 | 41, 42, 43, 44, 45, 46, | ||
| 222 | 50, 51, 52, 53, 54, 55, 56, | ||
| 223 | 57, 58, 59, 60, 61, 62, | ||
| 224 | }, | ||
| 225 | .oobfree = { | ||
| 226 | {.offset = 15, .length = 3}, | ||
| 227 | {.offset = 31, .length = 3}, | ||
| 228 | {.offset = 47, .length = 3}, | ||
| 229 | {.offset = 63, .length = 1}, | ||
| 230 | } | ||
| 231 | }; | ||
| 232 | 65 | ||
| 233 | /* | 66 | if (section < chip->ecc.steps - 1) |
| 234 | * ECC4 layout for NAND of pagesize 512 bytes & OOBsize 16 bytes. 13 bytes of | 67 | oobregion->length = 8; |
| 235 | * OOB size is reserved for ECC, Byte no. 4 & 5 reserved for bad block and One | 68 | else |
| 236 | * byte is free for use. | 69 | oobregion->length = mtd->oobsize - oobregion->offset; |
| 237 | */ | 70 | |
| 238 | static struct nand_ecclayout fsmc_ecc4_16_layout = { | 71 | return 0; |
| 239 | .eccbytes = 13, | 72 | } |
| 240 | .eccpos = { 0, 1, 2, 3, 6, 7, 8, | 73 | |
| 241 | 9, 10, 11, 12, 13, 14 | 74 | static const struct mtd_ooblayout_ops fsmc_ecc1_ooblayout_ops = { |
| 242 | }, | 75 | .ecc = fsmc_ecc1_ooblayout_ecc, |
| 243 | .oobfree = { | 76 | .free = fsmc_ecc1_ooblayout_free, |
| 244 | {.offset = 15, .length = 1}, | ||
| 245 | } | ||
| 246 | }; | 77 | }; |
| 247 | 78 | ||
| 248 | /* | 79 | /* |
| @@ -250,28 +81,46 @@ static struct nand_ecclayout fsmc_ecc4_16_layout = { | |||
| 250 | * There are 13 bytes of ecc for every 512 byte block and it has to be read | 81 | * There are 13 bytes of ecc for every 512 byte block and it has to be read |
| 251 | * consecutively and immediately after the 512 byte data block for hardware to | 82 | * consecutively and immediately after the 512 byte data block for hardware to |
| 252 | * generate the error bit offsets in 512 byte data. | 83 | * generate the error bit offsets in 512 byte data. |
| 253 | * Managing the ecc bytes in the following way makes it easier for software to | ||
| 254 | * read ecc bytes consecutive to data bytes. This way is similar to | ||
| 255 | * oobfree structure maintained already in generic nand driver | ||
| 256 | */ | 84 | */ |
| 257 | static struct fsmc_eccplace fsmc_ecc4_lp_place = { | 85 | static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 258 | .eccplace = { | 86 | struct mtd_oob_region *oobregion) |
| 259 | {.offset = 2, .length = 13}, | 87 | { |
| 260 | {.offset = 18, .length = 13}, | 88 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 261 | {.offset = 34, .length = 13}, | ||
| 262 | {.offset = 50, .length = 13}, | ||
| 263 | {.offset = 66, .length = 13}, | ||
| 264 | {.offset = 82, .length = 13}, | ||
| 265 | {.offset = 98, .length = 13}, | ||
| 266 | {.offset = 114, .length = 13} | ||
| 267 | } | ||
| 268 | }; | ||
| 269 | 89 | ||
| 270 | static struct fsmc_eccplace fsmc_ecc4_sp_place = { | 90 | if (section >= chip->ecc.steps) |
| 271 | .eccplace = { | 91 | return -ERANGE; |
| 272 | {.offset = 0, .length = 4}, | 92 | |
| 273 | {.offset = 6, .length = 9} | 93 | oobregion->length = chip->ecc.bytes; |
| 274 | } | 94 | |
| 95 | if (!section && mtd->writesize <= 512) | ||
| 96 | oobregion->offset = 0; | ||
| 97 | else | ||
| 98 | oobregion->offset = (section * 16) + 2; | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int fsmc_ecc4_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 104 | struct mtd_oob_region *oobregion) | ||
| 105 | { | ||
| 106 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 107 | |||
| 108 | if (section >= chip->ecc.steps) | ||
| 109 | return -ERANGE; | ||
| 110 | |||
| 111 | oobregion->offset = (section * 16) + 15; | ||
| 112 | |||
| 113 | if (section < chip->ecc.steps - 1) | ||
| 114 | oobregion->length = 3; | ||
| 115 | else | ||
| 116 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static const struct mtd_ooblayout_ops fsmc_ecc4_ooblayout_ops = { | ||
| 122 | .ecc = fsmc_ecc4_ooblayout_ecc, | ||
| 123 | .free = fsmc_ecc4_ooblayout_free, | ||
| 275 | }; | 124 | }; |
| 276 | 125 | ||
| 277 | /** | 126 | /** |
| @@ -283,7 +132,6 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = { | |||
| 283 | * @partitions: Partition info for a NAND Flash. | 132 | * @partitions: Partition info for a NAND Flash. |
| 284 | * @nr_partitions: Total number of partition of a NAND flash. | 133 | * @nr_partitions: Total number of partition of a NAND flash. |
| 285 | * | 134 | * |
| 286 | * @ecc_place: ECC placing locations in oobfree type format. | ||
| 287 | * @bank: Bank number for probed device. | 135 | * @bank: Bank number for probed device. |
| 288 | * @clk: Clock structure for FSMC. | 136 | * @clk: Clock structure for FSMC. |
| 289 | * | 137 | * |
| @@ -303,7 +151,6 @@ struct fsmc_nand_data { | |||
| 303 | struct mtd_partition *partitions; | 151 | struct mtd_partition *partitions; |
| 304 | unsigned int nr_partitions; | 152 | unsigned int nr_partitions; |
| 305 | 153 | ||
| 306 | struct fsmc_eccplace *ecc_place; | ||
| 307 | unsigned int bank; | 154 | unsigned int bank; |
| 308 | struct device *dev; | 155 | struct device *dev; |
| 309 | enum access_mode mode; | 156 | enum access_mode mode; |
| @@ -710,8 +557,6 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, | |||
| 710 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 557 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
| 711 | uint8_t *buf, int oob_required, int page) | 558 | uint8_t *buf, int oob_required, int page) |
| 712 | { | 559 | { |
| 713 | struct fsmc_nand_data *host = mtd_to_fsmc(mtd); | ||
| 714 | struct fsmc_eccplace *ecc_place = host->ecc_place; | ||
| 715 | int i, j, s, stat, eccsize = chip->ecc.size; | 560 | int i, j, s, stat, eccsize = chip->ecc.size; |
| 716 | int eccbytes = chip->ecc.bytes; | 561 | int eccbytes = chip->ecc.bytes; |
| 717 | int eccsteps = chip->ecc.steps; | 562 | int eccsteps = chip->ecc.steps; |
| @@ -734,9 +579,15 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 734 | chip->read_buf(mtd, p, eccsize); | 579 | chip->read_buf(mtd, p, eccsize); |
| 735 | 580 | ||
| 736 | for (j = 0; j < eccbytes;) { | 581 | for (j = 0; j < eccbytes;) { |
| 737 | off = ecc_place->eccplace[group].offset; | 582 | struct mtd_oob_region oobregion; |
| 738 | len = ecc_place->eccplace[group].length; | 583 | int ret; |
| 739 | group++; | 584 | |
| 585 | ret = mtd_ooblayout_ecc(mtd, group++, &oobregion); | ||
| 586 | if (ret) | ||
| 587 | return ret; | ||
| 588 | |||
| 589 | off = oobregion.offset; | ||
| 590 | len = oobregion.length; | ||
| 740 | 591 | ||
| 741 | /* | 592 | /* |
| 742 | * length is intentionally kept a higher multiple of 2 | 593 | * length is intentionally kept a higher multiple of 2 |
| @@ -1084,24 +935,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
| 1084 | if (AMBA_REV_BITS(host->pid) >= 8) { | 935 | if (AMBA_REV_BITS(host->pid) >= 8) { |
| 1085 | switch (mtd->oobsize) { | 936 | switch (mtd->oobsize) { |
| 1086 | case 16: | 937 | case 16: |
| 1087 | nand->ecc.layout = &fsmc_ecc4_16_layout; | ||
| 1088 | host->ecc_place = &fsmc_ecc4_sp_place; | ||
| 1089 | break; | ||
| 1090 | case 64: | 938 | case 64: |
| 1091 | nand->ecc.layout = &fsmc_ecc4_64_layout; | ||
| 1092 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
| 1093 | break; | ||
| 1094 | case 128: | 939 | case 128: |
| 1095 | nand->ecc.layout = &fsmc_ecc4_128_layout; | ||
| 1096 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
| 1097 | break; | ||
| 1098 | case 224: | 940 | case 224: |
| 1099 | nand->ecc.layout = &fsmc_ecc4_224_layout; | ||
| 1100 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
| 1101 | break; | ||
| 1102 | case 256: | 941 | case 256: |
| 1103 | nand->ecc.layout = &fsmc_ecc4_256_layout; | ||
| 1104 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
| 1105 | break; | 942 | break; |
| 1106 | default: | 943 | default: |
| 1107 | dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n", | 944 | dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n", |
| @@ -1109,6 +946,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
| 1109 | ret = -EINVAL; | 946 | ret = -EINVAL; |
| 1110 | goto err_probe; | 947 | goto err_probe; |
| 1111 | } | 948 | } |
| 949 | |||
| 950 | mtd_set_ooblayout(mtd, &fsmc_ecc4_ooblayout_ops); | ||
| 1112 | } else { | 951 | } else { |
| 1113 | switch (nand->ecc.mode) { | 952 | switch (nand->ecc.mode) { |
| 1114 | case NAND_ECC_HW: | 953 | case NAND_ECC_HW: |
| @@ -1119,9 +958,11 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
| 1119 | nand->ecc.strength = 1; | 958 | nand->ecc.strength = 1; |
| 1120 | break; | 959 | break; |
| 1121 | 960 | ||
| 1122 | case NAND_ECC_SOFT_BCH: | 961 | case NAND_ECC_SOFT: |
| 1123 | dev_info(&pdev->dev, "Using 4-bit SW BCH ECC scheme\n"); | 962 | if (nand->ecc.algo == NAND_ECC_BCH) { |
| 1124 | break; | 963 | dev_info(&pdev->dev, "Using 4-bit SW BCH ECC scheme\n"); |
| 964 | break; | ||
| 965 | } | ||
| 1125 | 966 | ||
| 1126 | default: | 967 | default: |
| 1127 | dev_err(&pdev->dev, "Unsupported ECC mode!\n"); | 968 | dev_err(&pdev->dev, "Unsupported ECC mode!\n"); |
| @@ -1132,16 +973,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
| 1132 | * Don't set layout for BCH4 SW ECC. This will be | 973 | * Don't set layout for BCH4 SW ECC. This will be |
| 1133 | * generated later in nand_bch_init() later. | 974 | * generated later in nand_bch_init() later. |
| 1134 | */ | 975 | */ |
| 1135 | if (nand->ecc.mode != NAND_ECC_SOFT_BCH) { | 976 | if (nand->ecc.mode == NAND_ECC_HW) { |
| 1136 | switch (mtd->oobsize) { | 977 | switch (mtd->oobsize) { |
| 1137 | case 16: | 978 | case 16: |
| 1138 | nand->ecc.layout = &fsmc_ecc1_16_layout; | ||
| 1139 | break; | ||
| 1140 | case 64: | 979 | case 64: |
| 1141 | nand->ecc.layout = &fsmc_ecc1_64_layout; | ||
| 1142 | break; | ||
| 1143 | case 128: | 980 | case 128: |
| 1144 | nand->ecc.layout = &fsmc_ecc1_128_layout; | 981 | mtd_set_ooblayout(mtd, |
| 982 | &fsmc_ecc1_ooblayout_ops); | ||
| 1145 | break; | 983 | break; |
| 1146 | default: | 984 | default: |
| 1147 | dev_warn(&pdev->dev, | 985 | dev_warn(&pdev->dev, |
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index ded658fc7d73..6317f6836022 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
| @@ -273,6 +273,7 @@ static int gpio_nand_probe(struct platform_device *pdev) | |||
| 273 | nand_set_flash_node(chip, pdev->dev.of_node); | 273 | nand_set_flash_node(chip, pdev->dev.of_node); |
| 274 | chip->IO_ADDR_W = chip->IO_ADDR_R; | 274 | chip->IO_ADDR_W = chip->IO_ADDR_R; |
| 275 | chip->ecc.mode = NAND_ECC_SOFT; | 275 | chip->ecc.mode = NAND_ECC_SOFT; |
| 276 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 276 | chip->options = gpiomtd->plat.options; | 277 | chip->options = gpiomtd->plat.options; |
| 277 | chip->chip_delay = gpiomtd->plat.chip_delay; | 278 | chip->chip_delay = gpiomtd->plat.chip_delay; |
| 278 | chip->cmd_ctrl = gpio_nand_cmd_ctrl; | 279 | chip->cmd_ctrl = gpio_nand_cmd_ctrl; |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 8122c699ccf2..6e461560c6a8 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/mtd/partitions.h> | 25 | #include <linux/mtd/partitions.h> |
| 26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
| 27 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
| 28 | #include <linux/of_mtd.h> | ||
| 29 | #include "gpmi-nand.h" | 28 | #include "gpmi-nand.h" |
| 30 | #include "bch-regs.h" | 29 | #include "bch-regs.h" |
| 31 | 30 | ||
| @@ -47,10 +46,44 @@ static struct nand_bbt_descr gpmi_bbt_descr = { | |||
| 47 | * We may change the layout if we can get the ECC info from the datasheet, | 46 | * We may change the layout if we can get the ECC info from the datasheet, |
| 48 | * else we will use all the (page + OOB). | 47 | * else we will use all the (page + OOB). |
| 49 | */ | 48 | */ |
| 50 | static struct nand_ecclayout gpmi_hw_ecclayout = { | 49 | static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 51 | .eccbytes = 0, | 50 | struct mtd_oob_region *oobregion) |
| 52 | .eccpos = { 0, }, | 51 | { |
| 53 | .oobfree = { {.offset = 0, .length = 0} } | 52 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 53 | struct gpmi_nand_data *this = nand_get_controller_data(chip); | ||
| 54 | struct bch_geometry *geo = &this->bch_geometry; | ||
| 55 | |||
| 56 | if (section) | ||
| 57 | return -ERANGE; | ||
| 58 | |||
| 59 | oobregion->offset = 0; | ||
| 60 | oobregion->length = geo->page_size - mtd->writesize; | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int gpmi_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 66 | struct mtd_oob_region *oobregion) | ||
| 67 | { | ||
| 68 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 69 | struct gpmi_nand_data *this = nand_get_controller_data(chip); | ||
| 70 | struct bch_geometry *geo = &this->bch_geometry; | ||
| 71 | |||
| 72 | if (section) | ||
| 73 | return -ERANGE; | ||
| 74 | |||
| 75 | /* The available oob size we have. */ | ||
| 76 | if (geo->page_size < mtd->writesize + mtd->oobsize) { | ||
| 77 | oobregion->offset = geo->page_size - mtd->writesize; | ||
| 78 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 79 | } | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static const struct mtd_ooblayout_ops gpmi_ooblayout_ops = { | ||
| 85 | .ecc = gpmi_ooblayout_ecc, | ||
| 86 | .free = gpmi_ooblayout_free, | ||
| 54 | }; | 87 | }; |
| 55 | 88 | ||
| 56 | static const struct gpmi_devdata gpmi_devdata_imx23 = { | 89 | static const struct gpmi_devdata gpmi_devdata_imx23 = { |
| @@ -141,7 +174,6 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this) | |||
| 141 | struct bch_geometry *geo = &this->bch_geometry; | 174 | struct bch_geometry *geo = &this->bch_geometry; |
| 142 | struct nand_chip *chip = &this->nand; | 175 | struct nand_chip *chip = &this->nand; |
| 143 | struct mtd_info *mtd = nand_to_mtd(chip); | 176 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 144 | struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree; | ||
| 145 | unsigned int block_mark_bit_offset; | 177 | unsigned int block_mark_bit_offset; |
| 146 | 178 | ||
| 147 | if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) | 179 | if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) |
| @@ -229,12 +261,6 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this) | |||
| 229 | geo->page_size = mtd->writesize + geo->metadata_size + | 261 | geo->page_size = mtd->writesize + geo->metadata_size + |
| 230 | (geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8; | 262 | (geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8; |
| 231 | 263 | ||
| 232 | /* The available oob size we have. */ | ||
| 233 | if (geo->page_size < mtd->writesize + mtd->oobsize) { | ||
| 234 | of->offset = geo->page_size - mtd->writesize; | ||
| 235 | of->length = mtd->oobsize - of->offset; | ||
| 236 | } | ||
| 237 | |||
| 238 | geo->payload_size = mtd->writesize; | 264 | geo->payload_size = mtd->writesize; |
| 239 | 265 | ||
| 240 | geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4); | 266 | geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4); |
| @@ -797,6 +823,7 @@ static void gpmi_free_dma_buffer(struct gpmi_nand_data *this) | |||
| 797 | 823 | ||
| 798 | this->cmd_buffer = NULL; | 824 | this->cmd_buffer = NULL; |
| 799 | this->data_buffer_dma = NULL; | 825 | this->data_buffer_dma = NULL; |
| 826 | this->raw_buffer = NULL; | ||
| 800 | this->page_buffer_virt = NULL; | 827 | this->page_buffer_virt = NULL; |
| 801 | this->page_buffer_size = 0; | 828 | this->page_buffer_size = 0; |
| 802 | } | 829 | } |
| @@ -1037,14 +1064,87 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1037 | /* Loop over status bytes, accumulating ECC status. */ | 1064 | /* Loop over status bytes, accumulating ECC status. */ |
| 1038 | status = auxiliary_virt + nfc_geo->auxiliary_status_offset; | 1065 | status = auxiliary_virt + nfc_geo->auxiliary_status_offset; |
| 1039 | 1066 | ||
| 1067 | read_page_swap_end(this, buf, nfc_geo->payload_size, | ||
| 1068 | this->payload_virt, this->payload_phys, | ||
| 1069 | nfc_geo->payload_size, | ||
| 1070 | payload_virt, payload_phys); | ||
| 1071 | |||
| 1040 | for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) { | 1072 | for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) { |
| 1041 | if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED)) | 1073 | if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED)) |
| 1042 | continue; | 1074 | continue; |
| 1043 | 1075 | ||
| 1044 | if (*status == STATUS_UNCORRECTABLE) { | 1076 | if (*status == STATUS_UNCORRECTABLE) { |
| 1077 | int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len; | ||
| 1078 | u8 *eccbuf = this->raw_buffer; | ||
| 1079 | int offset, bitoffset; | ||
| 1080 | int eccbytes; | ||
| 1081 | int flips; | ||
| 1082 | |||
| 1083 | /* Read ECC bytes into our internal raw_buffer */ | ||
| 1084 | offset = nfc_geo->metadata_size * 8; | ||
| 1085 | offset += ((8 * nfc_geo->ecc_chunk_size) + eccbits) * (i + 1); | ||
| 1086 | offset -= eccbits; | ||
| 1087 | bitoffset = offset % 8; | ||
| 1088 | eccbytes = DIV_ROUND_UP(offset + eccbits, 8); | ||
| 1089 | offset /= 8; | ||
| 1090 | eccbytes -= offset; | ||
| 1091 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
| 1092 | chip->read_buf(mtd, eccbuf, eccbytes); | ||
| 1093 | |||
| 1094 | /* | ||
| 1095 | * ECC data are not byte aligned and we may have | ||
| 1096 | * in-band data in the first and last byte of | ||
| 1097 | * eccbuf. Set non-eccbits to one so that | ||
| 1098 | * nand_check_erased_ecc_chunk() does not count them | ||
| 1099 | * as bitflips. | ||
| 1100 | */ | ||
| 1101 | if (bitoffset) | ||
| 1102 | eccbuf[0] |= GENMASK(bitoffset - 1, 0); | ||
| 1103 | |||
| 1104 | bitoffset = (bitoffset + eccbits) % 8; | ||
| 1105 | if (bitoffset) | ||
| 1106 | eccbuf[eccbytes - 1] |= GENMASK(7, bitoffset); | ||
| 1107 | |||
| 1108 | /* | ||
| 1109 | * The ECC hardware has an uncorrectable ECC status | ||
| 1110 | * code in case we have bitflips in an erased page. As | ||
| 1111 | * nothing was written into this subpage the ECC is | ||
| 1112 | * obviously wrong and we can not trust it. We assume | ||
| 1113 | * at this point that we are reading an erased page and | ||
| 1114 | * try to correct the bitflips in buffer up to | ||
| 1115 | * ecc_strength bitflips. If this is a page with random | ||
| 1116 | * data, we exceed this number of bitflips and have a | ||
| 1117 | * ECC failure. Otherwise we use the corrected buffer. | ||
| 1118 | */ | ||
| 1119 | if (i == 0) { | ||
| 1120 | /* The first block includes metadata */ | ||
| 1121 | flips = nand_check_erased_ecc_chunk( | ||
| 1122 | buf + i * nfc_geo->ecc_chunk_size, | ||
| 1123 | nfc_geo->ecc_chunk_size, | ||
| 1124 | eccbuf, eccbytes, | ||
| 1125 | auxiliary_virt, | ||
| 1126 | nfc_geo->metadata_size, | ||
| 1127 | nfc_geo->ecc_strength); | ||
| 1128 | } else { | ||
| 1129 | flips = nand_check_erased_ecc_chunk( | ||
| 1130 | buf + i * nfc_geo->ecc_chunk_size, | ||
| 1131 | nfc_geo->ecc_chunk_size, | ||
| 1132 | eccbuf, eccbytes, | ||
| 1133 | NULL, 0, | ||
| 1134 | nfc_geo->ecc_strength); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | if (flips > 0) { | ||
| 1138 | max_bitflips = max_t(unsigned int, max_bitflips, | ||
| 1139 | flips); | ||
| 1140 | mtd->ecc_stats.corrected += flips; | ||
| 1141 | continue; | ||
| 1142 | } | ||
| 1143 | |||
| 1045 | mtd->ecc_stats.failed++; | 1144 | mtd->ecc_stats.failed++; |
| 1046 | continue; | 1145 | continue; |
| 1047 | } | 1146 | } |
| 1147 | |||
| 1048 | mtd->ecc_stats.corrected += *status; | 1148 | mtd->ecc_stats.corrected += *status; |
| 1049 | max_bitflips = max_t(unsigned int, max_bitflips, *status); | 1149 | max_bitflips = max_t(unsigned int, max_bitflips, *status); |
| 1050 | } | 1150 | } |
| @@ -1064,11 +1164,6 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1064 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; | 1164 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; |
| 1065 | } | 1165 | } |
| 1066 | 1166 | ||
| 1067 | read_page_swap_end(this, buf, nfc_geo->payload_size, | ||
| 1068 | this->payload_virt, this->payload_phys, | ||
| 1069 | nfc_geo->payload_size, | ||
| 1070 | payload_virt, payload_phys); | ||
| 1071 | |||
| 1072 | return max_bitflips; | 1167 | return max_bitflips; |
| 1073 | } | 1168 | } |
| 1074 | 1169 | ||
| @@ -1327,18 +1422,19 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1327 | static int | 1422 | static int |
| 1328 | gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) | 1423 | gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) |
| 1329 | { | 1424 | { |
| 1330 | struct nand_oobfree *of = mtd->ecclayout->oobfree; | 1425 | struct mtd_oob_region of = { }; |
| 1331 | int status = 0; | 1426 | int status = 0; |
| 1332 | 1427 | ||
| 1333 | /* Do we have available oob area? */ | 1428 | /* Do we have available oob area? */ |
| 1334 | if (!of->length) | 1429 | mtd_ooblayout_free(mtd, 0, &of); |
| 1430 | if (!of.length) | ||
| 1335 | return -EPERM; | 1431 | return -EPERM; |
| 1336 | 1432 | ||
| 1337 | if (!nand_is_slc(chip)) | 1433 | if (!nand_is_slc(chip)) |
| 1338 | return -EPERM; | 1434 | return -EPERM; |
| 1339 | 1435 | ||
| 1340 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of->offset, page); | 1436 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of.offset, page); |
| 1341 | chip->write_buf(mtd, chip->oob_poi + of->offset, of->length); | 1437 | chip->write_buf(mtd, chip->oob_poi + of.offset, of.length); |
| 1342 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | 1438 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); |
| 1343 | 1439 | ||
| 1344 | status = chip->waitfunc(mtd, chip); | 1440 | status = chip->waitfunc(mtd, chip); |
| @@ -1840,6 +1936,7 @@ static void gpmi_nand_exit(struct gpmi_nand_data *this) | |||
| 1840 | static int gpmi_init_last(struct gpmi_nand_data *this) | 1936 | static int gpmi_init_last(struct gpmi_nand_data *this) |
| 1841 | { | 1937 | { |
| 1842 | struct nand_chip *chip = &this->nand; | 1938 | struct nand_chip *chip = &this->nand; |
| 1939 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 1843 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 1940 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 1844 | struct bch_geometry *bch_geo = &this->bch_geometry; | 1941 | struct bch_geometry *bch_geo = &this->bch_geometry; |
| 1845 | int ret; | 1942 | int ret; |
| @@ -1861,7 +1958,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this) | |||
| 1861 | ecc->mode = NAND_ECC_HW; | 1958 | ecc->mode = NAND_ECC_HW; |
| 1862 | ecc->size = bch_geo->ecc_chunk_size; | 1959 | ecc->size = bch_geo->ecc_chunk_size; |
| 1863 | ecc->strength = bch_geo->ecc_strength; | 1960 | ecc->strength = bch_geo->ecc_strength; |
| 1864 | ecc->layout = &gpmi_hw_ecclayout; | 1961 | mtd_set_ooblayout(mtd, &gpmi_ooblayout_ops); |
| 1865 | 1962 | ||
| 1866 | /* | 1963 | /* |
| 1867 | * We only enable the subpage read when: | 1964 | * We only enable the subpage read when: |
| @@ -1914,16 +2011,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) | |||
| 1914 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | 2011 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ |
| 1915 | this->swap_block_mark = !GPMI_IS_MX23(this); | 2012 | this->swap_block_mark = !GPMI_IS_MX23(this); |
| 1916 | 2013 | ||
| 1917 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) { | ||
| 1918 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | ||
| 1919 | |||
| 1920 | if (of_property_read_bool(this->dev->of_node, | ||
| 1921 | "fsl,no-blockmark-swap")) | ||
| 1922 | this->swap_block_mark = false; | ||
| 1923 | } | ||
| 1924 | dev_dbg(this->dev, "Blockmark swapping %sabled\n", | ||
| 1925 | this->swap_block_mark ? "en" : "dis"); | ||
| 1926 | |||
| 1927 | /* | 2014 | /* |
| 1928 | * Allocate a temporary DMA buffer for reading ID in the | 2015 | * Allocate a temporary DMA buffer for reading ID in the |
| 1929 | * nand_scan_ident(). | 2016 | * nand_scan_ident(). |
| @@ -1938,6 +2025,16 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) | |||
| 1938 | if (ret) | 2025 | if (ret) |
| 1939 | goto err_out; | 2026 | goto err_out; |
| 1940 | 2027 | ||
| 2028 | if (chip->bbt_options & NAND_BBT_USE_FLASH) { | ||
| 2029 | chip->bbt_options |= NAND_BBT_NO_OOB; | ||
| 2030 | |||
| 2031 | if (of_property_read_bool(this->dev->of_node, | ||
| 2032 | "fsl,no-blockmark-swap")) | ||
| 2033 | this->swap_block_mark = false; | ||
| 2034 | } | ||
| 2035 | dev_dbg(this->dev, "Blockmark swapping %sabled\n", | ||
| 2036 | this->swap_block_mark ? "en" : "dis"); | ||
| 2037 | |||
| 1941 | ret = gpmi_init_last(this); | 2038 | ret = gpmi_init_last(this); |
| 1942 | if (ret) | 2039 | if (ret) |
| 1943 | goto err_out; | 2040 | goto err_out; |
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 96502b624cfb..9432546f4cd4 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * GNU General Public License for more details. | 19 | * GNU General Public License for more details. |
| 20 | */ | 20 | */ |
| 21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 22 | #include <linux/of_mtd.h> | ||
| 23 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
| 24 | #include <linux/sizes.h> | 23 | #include <linux/sizes.h> |
| 25 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
| @@ -631,8 +630,28 @@ static void hisi_nfc_host_init(struct hinfc_host *host) | |||
| 631 | hinfc_write(host, HINFC504_INTEN_DMA, HINFC504_INTEN); | 630 | hinfc_write(host, HINFC504_INTEN_DMA, HINFC504_INTEN); |
| 632 | } | 631 | } |
| 633 | 632 | ||
| 634 | static struct nand_ecclayout nand_ecc_2K_16bits = { | 633 | static int hisi_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 635 | .oobfree = { {2, 6} }, | 634 | struct mtd_oob_region *oobregion) |
| 635 | { | ||
| 636 | /* FIXME: add ECC bytes position */ | ||
| 637 | return -ENOTSUPP; | ||
| 638 | } | ||
| 639 | |||
| 640 | static int hisi_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 641 | struct mtd_oob_region *oobregion) | ||
| 642 | { | ||
| 643 | if (section) | ||
| 644 | return -ERANGE; | ||
| 645 | |||
| 646 | oobregion->offset = 2; | ||
| 647 | oobregion->length = 6; | ||
| 648 | |||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | static const struct mtd_ooblayout_ops hisi_ooblayout_ops = { | ||
| 653 | .ecc = hisi_ooblayout_ecc, | ||
| 654 | .free = hisi_ooblayout_free, | ||
| 636 | }; | 655 | }; |
| 637 | 656 | ||
| 638 | static int hisi_nfc_ecc_probe(struct hinfc_host *host) | 657 | static int hisi_nfc_ecc_probe(struct hinfc_host *host) |
| @@ -642,10 +661,9 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host) | |||
| 642 | struct device *dev = host->dev; | 661 | struct device *dev = host->dev; |
| 643 | struct nand_chip *chip = &host->chip; | 662 | struct nand_chip *chip = &host->chip; |
| 644 | struct mtd_info *mtd = nand_to_mtd(chip); | 663 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 645 | struct device_node *np = host->dev->of_node; | ||
| 646 | 664 | ||
| 647 | size = of_get_nand_ecc_step_size(np); | 665 | size = chip->ecc.size; |
| 648 | strength = of_get_nand_ecc_strength(np); | 666 | strength = chip->ecc.strength; |
| 649 | if (size != 1024) { | 667 | if (size != 1024) { |
| 650 | dev_err(dev, "error ecc size: %d\n", size); | 668 | dev_err(dev, "error ecc size: %d\n", size); |
| 651 | return -EINVAL; | 669 | return -EINVAL; |
| @@ -668,7 +686,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host) | |||
| 668 | case 16: | 686 | case 16: |
| 669 | ecc_bits = 6; | 687 | ecc_bits = 6; |
| 670 | if (mtd->writesize == 2048) | 688 | if (mtd->writesize == 2048) |
| 671 | chip->ecc.layout = &nand_ecc_2K_16bits; | 689 | mtd_set_ooblayout(mtd, &hisi_ooblayout_ops); |
| 672 | 690 | ||
| 673 | /* TODO: add more page size support */ | 691 | /* TODO: add more page size support */ |
| 674 | break; | 692 | break; |
| @@ -695,7 +713,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host) | |||
| 695 | 713 | ||
| 696 | static int hisi_nfc_probe(struct platform_device *pdev) | 714 | static int hisi_nfc_probe(struct platform_device *pdev) |
| 697 | { | 715 | { |
| 698 | int ret = 0, irq, buswidth, flag, max_chips = HINFC504_MAX_CHIP; | 716 | int ret = 0, irq, flag, max_chips = HINFC504_MAX_CHIP; |
| 699 | struct device *dev = &pdev->dev; | 717 | struct device *dev = &pdev->dev; |
| 700 | struct hinfc_host *host; | 718 | struct hinfc_host *host; |
| 701 | struct nand_chip *chip; | 719 | struct nand_chip *chip; |
| @@ -747,12 +765,6 @@ static int hisi_nfc_probe(struct platform_device *pdev) | |||
| 747 | chip->read_buf = hisi_nfc_read_buf; | 765 | chip->read_buf = hisi_nfc_read_buf; |
| 748 | chip->chip_delay = HINFC504_CHIP_DELAY; | 766 | chip->chip_delay = HINFC504_CHIP_DELAY; |
| 749 | 767 | ||
| 750 | chip->ecc.mode = of_get_nand_ecc_mode(np); | ||
| 751 | |||
| 752 | buswidth = of_get_nand_bus_width(np); | ||
| 753 | if (buswidth == 16) | ||
| 754 | chip->options |= NAND_BUSWIDTH_16; | ||
| 755 | |||
| 756 | hisi_nfc_host_init(host); | 768 | hisi_nfc_host_init(host); |
| 757 | 769 | ||
| 758 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, 0x0, "nandc", host); | 770 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, 0x0, "nandc", host); |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 673ceb2a0b44..5551c36adbdf 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
| @@ -221,7 +221,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, | |||
| 221 | struct jz_nand *nand = mtd_to_jz_nand(mtd); | 221 | struct jz_nand *nand = mtd_to_jz_nand(mtd); |
| 222 | int i, error_count, index; | 222 | int i, error_count, index; |
| 223 | uint32_t reg, status, error; | 223 | uint32_t reg, status, error; |
| 224 | uint32_t t; | ||
| 225 | unsigned int timeout = 1000; | 224 | unsigned int timeout = 1000; |
| 226 | 225 | ||
| 227 | for (i = 0; i < 9; ++i) | 226 | for (i = 0; i < 9; ++i) |
| @@ -476,7 +475,7 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 476 | } | 475 | } |
| 477 | 476 | ||
| 478 | if (pdata && pdata->ident_callback) { | 477 | if (pdata && pdata->ident_callback) { |
| 479 | pdata->ident_callback(pdev, chip, &pdata->partitions, | 478 | pdata->ident_callback(pdev, mtd, &pdata->partitions, |
| 480 | &pdata->num_partitions); | 479 | &pdata->num_partitions); |
| 481 | } | 480 | } |
| 482 | 481 | ||
diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/jz4780_bch.c index 755499c6650e..d74f4ba4a6f4 100644 --- a/drivers/mtd/nand/jz4780_bch.c +++ b/drivers/mtd/nand/jz4780_bch.c | |||
| @@ -287,7 +287,6 @@ static struct jz4780_bch *jz4780_bch_get(struct device_node *np) | |||
| 287 | bch = platform_get_drvdata(pdev); | 287 | bch = platform_get_drvdata(pdev); |
| 288 | clk_prepare_enable(bch->clk); | 288 | clk_prepare_enable(bch->clk); |
| 289 | 289 | ||
| 290 | bch->dev = &pdev->dev; | ||
| 291 | return bch; | 290 | return bch; |
| 292 | } | 291 | } |
| 293 | 292 | ||
diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c index e1c016c9d32d..daf3c4217f4d 100644 --- a/drivers/mtd/nand/jz4780_nand.c +++ b/drivers/mtd/nand/jz4780_nand.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 19 | #include <linux/gpio/consumer.h> | 19 | #include <linux/gpio/consumer.h> |
| 20 | #include <linux/of_mtd.h> | ||
| 21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 23 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
| @@ -56,8 +55,6 @@ struct jz4780_nand_chip { | |||
| 56 | struct nand_chip chip; | 55 | struct nand_chip chip; |
| 57 | struct list_head chip_list; | 56 | struct list_head chip_list; |
| 58 | 57 | ||
| 59 | struct nand_ecclayout ecclayout; | ||
| 60 | |||
| 61 | struct gpio_desc *busy_gpio; | 58 | struct gpio_desc *busy_gpio; |
| 62 | struct gpio_desc *wp_gpio; | 59 | struct gpio_desc *wp_gpio; |
| 63 | unsigned int reading: 1; | 60 | unsigned int reading: 1; |
| @@ -165,8 +162,7 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de | |||
| 165 | struct nand_chip *chip = &nand->chip; | 162 | struct nand_chip *chip = &nand->chip; |
| 166 | struct mtd_info *mtd = nand_to_mtd(chip); | 163 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 167 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller); | 164 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller); |
| 168 | struct nand_ecclayout *layout = &nand->ecclayout; | 165 | int eccbytes; |
| 169 | u32 start, i; | ||
| 170 | 166 | ||
| 171 | chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * | 167 | chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * |
| 172 | (chip->ecc.strength / 8); | 168 | (chip->ecc.strength / 8); |
| @@ -183,7 +179,6 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de | |||
| 183 | chip->ecc.correct = jz4780_nand_ecc_correct; | 179 | chip->ecc.correct = jz4780_nand_ecc_correct; |
| 184 | /* fall through */ | 180 | /* fall through */ |
| 185 | case NAND_ECC_SOFT: | 181 | case NAND_ECC_SOFT: |
| 186 | case NAND_ECC_SOFT_BCH: | ||
| 187 | dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n", | 182 | dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n", |
| 188 | (nfc->bch) ? "hardware BCH" : "software ECC", | 183 | (nfc->bch) ? "hardware BCH" : "software ECC", |
| 189 | chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); | 184 | chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); |
| @@ -201,23 +196,17 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de | |||
| 201 | return 0; | 196 | return 0; |
| 202 | 197 | ||
| 203 | /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ | 198 | /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ |
| 204 | layout->eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; | 199 | eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; |
| 205 | 200 | ||
| 206 | if (layout->eccbytes > mtd->oobsize - 2) { | 201 | if (eccbytes > mtd->oobsize - 2) { |
| 207 | dev_err(dev, | 202 | dev_err(dev, |
| 208 | "invalid ECC config: required %d ECC bytes, but only %d are available", | 203 | "invalid ECC config: required %d ECC bytes, but only %d are available", |
| 209 | layout->eccbytes, mtd->oobsize - 2); | 204 | eccbytes, mtd->oobsize - 2); |
| 210 | return -EINVAL; | 205 | return -EINVAL; |
| 211 | } | 206 | } |
| 212 | 207 | ||
| 213 | start = mtd->oobsize - layout->eccbytes; | 208 | mtd->ooblayout = &nand_ooblayout_lp_ops; |
| 214 | for (i = 0; i < layout->eccbytes; i++) | ||
| 215 | layout->eccpos[i] = start + i; | ||
| 216 | |||
| 217 | layout->oobfree[0].offset = 2; | ||
| 218 | layout->oobfree[0].length = mtd->oobsize - layout->eccbytes - 2; | ||
| 219 | 209 | ||
| 220 | chip->ecc.layout = layout; | ||
| 221 | return 0; | 210 | return 0; |
| 222 | } | 211 | } |
| 223 | 212 | ||
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index d8c3e7afcc0b..852388171f20 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <linux/completion.h> | 35 | #include <linux/completion.h> |
| 36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
| 37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
| 38 | #include <linux/of_mtd.h> | ||
| 39 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
| 40 | #include <linux/mtd/lpc32xx_mlc.h> | 39 | #include <linux/mtd/lpc32xx_mlc.h> |
| 41 | #include <linux/io.h> | 40 | #include <linux/io.h> |
| @@ -139,22 +138,37 @@ struct lpc32xx_nand_cfg_mlc { | |||
| 139 | unsigned num_parts; | 138 | unsigned num_parts; |
| 140 | }; | 139 | }; |
| 141 | 140 | ||
| 142 | static struct nand_ecclayout lpc32xx_nand_oob = { | 141 | static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 143 | .eccbytes = 40, | 142 | struct mtd_oob_region *oobregion) |
| 144 | .eccpos = { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | 143 | { |
| 145 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, | 144 | struct nand_chip *nand_chip = mtd_to_nand(mtd); |
| 146 | 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, | 145 | |
| 147 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, | 146 | if (section >= nand_chip->ecc.steps) |
| 148 | .oobfree = { | 147 | return -ERANGE; |
| 149 | { .offset = 0, | 148 | |
| 150 | .length = 6, }, | 149 | oobregion->offset = ((section + 1) * 16) - nand_chip->ecc.bytes; |
| 151 | { .offset = 16, | 150 | oobregion->length = nand_chip->ecc.bytes; |
| 152 | .length = 6, }, | 151 | |
| 153 | { .offset = 32, | 152 | return 0; |
| 154 | .length = 6, }, | 153 | } |
| 155 | { .offset = 48, | 154 | |
| 156 | .length = 6, }, | 155 | static int lpc32xx_ooblayout_free(struct mtd_info *mtd, int section, |
| 157 | }, | 156 | struct mtd_oob_region *oobregion) |
| 157 | { | ||
| 158 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | ||
| 159 | |||
| 160 | if (section >= nand_chip->ecc.steps) | ||
| 161 | return -ERANGE; | ||
| 162 | |||
| 163 | oobregion->offset = 16 * section; | ||
| 164 | oobregion->length = 16 - nand_chip->ecc.bytes; | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static const struct mtd_ooblayout_ops lpc32xx_ooblayout_ops = { | ||
| 170 | .ecc = lpc32xx_ooblayout_ecc, | ||
| 171 | .free = lpc32xx_ooblayout_free, | ||
| 158 | }; | 172 | }; |
| 159 | 173 | ||
| 160 | static struct nand_bbt_descr lpc32xx_nand_bbt = { | 174 | static struct nand_bbt_descr lpc32xx_nand_bbt = { |
| @@ -713,6 +727,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
| 713 | nand_chip->ecc.write_oob = lpc32xx_write_oob; | 727 | nand_chip->ecc.write_oob = lpc32xx_write_oob; |
| 714 | nand_chip->ecc.read_oob = lpc32xx_read_oob; | 728 | nand_chip->ecc.read_oob = lpc32xx_read_oob; |
| 715 | nand_chip->ecc.strength = 4; | 729 | nand_chip->ecc.strength = 4; |
| 730 | nand_chip->ecc.bytes = 10; | ||
| 716 | nand_chip->waitfunc = lpc32xx_waitfunc; | 731 | nand_chip->waitfunc = lpc32xx_waitfunc; |
| 717 | 732 | ||
| 718 | nand_chip->options = NAND_NO_SUBPAGE_WRITE; | 733 | nand_chip->options = NAND_NO_SUBPAGE_WRITE; |
| @@ -751,7 +766,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
| 751 | 766 | ||
| 752 | nand_chip->ecc.mode = NAND_ECC_HW; | 767 | nand_chip->ecc.mode = NAND_ECC_HW; |
| 753 | nand_chip->ecc.size = 512; | 768 | nand_chip->ecc.size = 512; |
| 754 | nand_chip->ecc.layout = &lpc32xx_nand_oob; | 769 | mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops); |
| 755 | host->mlcsubpages = mtd->writesize / 512; | 770 | host->mlcsubpages = mtd->writesize / 512; |
| 756 | 771 | ||
| 757 | /* initially clear interrupt status */ | 772 | /* initially clear interrupt status */ |
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 3b8f3735f3e8..8d3edc34958e 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <linux/mtd/nand_ecc.h> | 35 | #include <linux/mtd/nand_ecc.h> |
| 36 | #include <linux/gpio.h> | 36 | #include <linux/gpio.h> |
| 37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
| 38 | #include <linux/of_mtd.h> | ||
| 39 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
| 40 | #include <linux/mtd/lpc32xx_slc.h> | 39 | #include <linux/mtd/lpc32xx_slc.h> |
| 41 | 40 | ||
| @@ -146,13 +145,38 @@ | |||
| 146 | * NAND ECC Layout for small page NAND devices | 145 | * NAND ECC Layout for small page NAND devices |
| 147 | * Note: For large and huge page devices, the default layouts are used | 146 | * Note: For large and huge page devices, the default layouts are used |
| 148 | */ | 147 | */ |
| 149 | static struct nand_ecclayout lpc32xx_nand_oob_16 = { | 148 | static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 150 | .eccbytes = 6, | 149 | struct mtd_oob_region *oobregion) |
| 151 | .eccpos = {10, 11, 12, 13, 14, 15}, | 150 | { |
| 152 | .oobfree = { | 151 | if (section) |
| 153 | { .offset = 0, .length = 4 }, | 152 | return -ERANGE; |
| 154 | { .offset = 6, .length = 4 }, | 153 | |
| 155 | }, | 154 | oobregion->length = 6; |
| 155 | oobregion->offset = 10; | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int lpc32xx_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 161 | struct mtd_oob_region *oobregion) | ||
| 162 | { | ||
| 163 | if (section > 1) | ||
| 164 | return -ERANGE; | ||
| 165 | |||
| 166 | if (!section) { | ||
| 167 | oobregion->offset = 0; | ||
| 168 | oobregion->length = 4; | ||
| 169 | } else { | ||
| 170 | oobregion->offset = 6; | ||
| 171 | oobregion->length = 4; | ||
| 172 | } | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static const struct mtd_ooblayout_ops lpc32xx_ooblayout_ops = { | ||
| 178 | .ecc = lpc32xx_ooblayout_ecc, | ||
| 179 | .free = lpc32xx_ooblayout_free, | ||
| 156 | }; | 180 | }; |
| 157 | 181 | ||
| 158 | static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; | 182 | static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; |
| @@ -194,7 +218,6 @@ struct lpc32xx_nand_cfg_slc { | |||
| 194 | uint32_t rwidth; | 218 | uint32_t rwidth; |
| 195 | uint32_t rhold; | 219 | uint32_t rhold; |
| 196 | uint32_t rsetup; | 220 | uint32_t rsetup; |
| 197 | bool use_bbt; | ||
| 198 | int wp_gpio; | 221 | int wp_gpio; |
| 199 | struct mtd_partition *parts; | 222 | struct mtd_partition *parts; |
| 200 | unsigned num_parts; | 223 | unsigned num_parts; |
| @@ -604,7 +627,8 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, | |||
| 604 | int oob_required, int page) | 627 | int oob_required, int page) |
| 605 | { | 628 | { |
| 606 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); | 629 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); |
| 607 | int stat, i, status; | 630 | struct mtd_oob_region oobregion = { }; |
| 631 | int stat, i, status, error; | ||
| 608 | uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE]; | 632 | uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE]; |
| 609 | 633 | ||
| 610 | /* Issue read command */ | 634 | /* Issue read command */ |
| @@ -620,7 +644,11 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, | |||
| 620 | lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps); | 644 | lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps); |
| 621 | 645 | ||
| 622 | /* Pointer to ECC data retrieved from NAND spare area */ | 646 | /* Pointer to ECC data retrieved from NAND spare area */ |
| 623 | oobecc = chip->oob_poi + chip->ecc.layout->eccpos[0]; | 647 | error = mtd_ooblayout_ecc(mtd, 0, &oobregion); |
| 648 | if (error) | ||
| 649 | return error; | ||
| 650 | |||
| 651 | oobecc = chip->oob_poi + oobregion.offset; | ||
| 624 | 652 | ||
| 625 | for (i = 0; i < chip->ecc.steps; i++) { | 653 | for (i = 0; i < chip->ecc.steps; i++) { |
| 626 | stat = chip->ecc.correct(mtd, buf, oobecc, | 654 | stat = chip->ecc.correct(mtd, buf, oobecc, |
| @@ -666,7 +694,8 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, | |||
| 666 | int oob_required, int page) | 694 | int oob_required, int page) |
| 667 | { | 695 | { |
| 668 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); | 696 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); |
| 669 | uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0]; | 697 | struct mtd_oob_region oobregion = { }; |
| 698 | uint8_t *pb; | ||
| 670 | int error; | 699 | int error; |
| 671 | 700 | ||
| 672 | /* Write data, calculate ECC on outbound data */ | 701 | /* Write data, calculate ECC on outbound data */ |
| @@ -678,6 +707,11 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, | |||
| 678 | * The calculated ECC needs some manual work done to it before | 707 | * The calculated ECC needs some manual work done to it before |
| 679 | * committing it to NAND. Process the calculated ECC and place | 708 | * committing it to NAND. Process the calculated ECC and place |
| 680 | * the resultant values directly into the OOB buffer. */ | 709 | * the resultant values directly into the OOB buffer. */ |
| 710 | error = mtd_ooblayout_ecc(mtd, 0, &oobregion); | ||
| 711 | if (error) | ||
| 712 | return error; | ||
| 713 | |||
| 714 | pb = chip->oob_poi + oobregion.offset; | ||
| 681 | lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps); | 715 | lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps); |
| 682 | 716 | ||
| 683 | /* Write ECC data to device */ | 717 | /* Write ECC data to device */ |
| @@ -747,7 +781,6 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev) | |||
| 747 | return NULL; | 781 | return NULL; |
| 748 | } | 782 | } |
| 749 | 783 | ||
| 750 | ncfg->use_bbt = of_get_nand_on_flash_bbt(np); | ||
| 751 | ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0); | 784 | ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0); |
| 752 | 785 | ||
| 753 | return ncfg; | 786 | return ncfg; |
| @@ -875,26 +908,22 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
| 875 | * custom BBT marker layout. | 908 | * custom BBT marker layout. |
| 876 | */ | 909 | */ |
| 877 | if (mtd->writesize <= 512) | 910 | if (mtd->writesize <= 512) |
| 878 | chip->ecc.layout = &lpc32xx_nand_oob_16; | 911 | mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops); |
| 879 | 912 | ||
| 880 | /* These sizes remain the same regardless of page size */ | 913 | /* These sizes remain the same regardless of page size */ |
| 881 | chip->ecc.size = 256; | 914 | chip->ecc.size = 256; |
| 882 | chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES; | 915 | chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES; |
| 883 | chip->ecc.prepad = chip->ecc.postpad = 0; | 916 | chip->ecc.prepad = chip->ecc.postpad = 0; |
| 884 | 917 | ||
| 885 | /* Avoid extra scan if using BBT, setup BBT support */ | 918 | /* |
| 886 | if (host->ncfg->use_bbt) { | 919 | * Use a custom BBT marker setup for small page FLASH that |
| 887 | chip->bbt_options |= NAND_BBT_USE_FLASH; | 920 | * won't interfere with the ECC layout. Large and huge page |
| 888 | 921 | * FLASH use the standard layout. | |
| 889 | /* | 922 | */ |
| 890 | * Use a custom BBT marker setup for small page FLASH that | 923 | if ((chip->bbt_options & NAND_BBT_USE_FLASH) && |
| 891 | * won't interfere with the ECC layout. Large and huge page | 924 | mtd->writesize <= 512) { |
| 892 | * FLASH use the standard layout. | 925 | chip->bbt_td = &bbt_smallpage_main_descr; |
| 893 | */ | 926 | chip->bbt_md = &bbt_smallpage_mirror_descr; |
| 894 | if (mtd->writesize <= 512) { | ||
| 895 | chip->bbt_td = &bbt_smallpage_main_descr; | ||
| 896 | chip->bbt_md = &bbt_smallpage_mirror_descr; | ||
| 897 | } | ||
| 898 | } | 927 | } |
| 899 | 928 | ||
| 900 | /* | 929 | /* |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 5d7843ffff6a..7eacb2f545f5 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
| @@ -710,6 +710,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) | |||
| 710 | chip->select_chip = mpc5121_nfc_select_chip; | 710 | chip->select_chip = mpc5121_nfc_select_chip; |
| 711 | chip->bbt_options = NAND_BBT_USE_FLASH; | 711 | chip->bbt_options = NAND_BBT_USE_FLASH; |
| 712 | chip->ecc.mode = NAND_ECC_SOFT; | 712 | chip->ecc.mode = NAND_ECC_SOFT; |
| 713 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 713 | 714 | ||
| 714 | /* Support external chip-select logic on ADS5121 board */ | 715 | /* Support external chip-select logic on ADS5121 board */ |
| 715 | if (of_machine_is_compatible("fsl,mpc5121ads")) { | 716 | if (of_machine_is_compatible("fsl,mpc5121ads")) { |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 854c832597aa..5173fadc9a4e 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/completion.h> | 34 | #include <linux/completion.h> |
| 35 | #include <linux/of.h> | 35 | #include <linux/of.h> |
| 36 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
| 37 | #include <linux/of_mtd.h> | ||
| 38 | 37 | ||
| 39 | #include <asm/mach/flash.h> | 38 | #include <asm/mach/flash.h> |
| 40 | #include <linux/platform_data/mtd-mxc_nand.h> | 39 | #include <linux/platform_data/mtd-mxc_nand.h> |
| @@ -149,7 +148,7 @@ struct mxc_nand_devtype_data { | |||
| 149 | int (*check_int)(struct mxc_nand_host *); | 148 | int (*check_int)(struct mxc_nand_host *); |
| 150 | void (*irq_control)(struct mxc_nand_host *, int); | 149 | void (*irq_control)(struct mxc_nand_host *, int); |
| 151 | u32 (*get_ecc_status)(struct mxc_nand_host *); | 150 | u32 (*get_ecc_status)(struct mxc_nand_host *); |
| 152 | struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k; | 151 | const struct mtd_ooblayout_ops *ooblayout; |
| 153 | void (*select_chip)(struct mtd_info *mtd, int chip); | 152 | void (*select_chip)(struct mtd_info *mtd, int chip); |
| 154 | int (*correct_data)(struct mtd_info *mtd, u_char *dat, | 153 | int (*correct_data)(struct mtd_info *mtd, u_char *dat, |
| 155 | u_char *read_ecc, u_char *calc_ecc); | 154 | u_char *read_ecc, u_char *calc_ecc); |
| @@ -200,73 +199,6 @@ struct mxc_nand_host { | |||
| 200 | struct mxc_nand_platform_data pdata; | 199 | struct mxc_nand_platform_data pdata; |
| 201 | }; | 200 | }; |
| 202 | 201 | ||
| 203 | /* OOB placement block for use with hardware ecc generation */ | ||
| 204 | static struct nand_ecclayout nandv1_hw_eccoob_smallpage = { | ||
| 205 | .eccbytes = 5, | ||
| 206 | .eccpos = {6, 7, 8, 9, 10}, | ||
| 207 | .oobfree = {{0, 5}, {12, 4}, } | ||
| 208 | }; | ||
| 209 | |||
| 210 | static struct nand_ecclayout nandv1_hw_eccoob_largepage = { | ||
| 211 | .eccbytes = 20, | ||
| 212 | .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, | ||
| 213 | 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, | ||
| 214 | .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, } | ||
| 215 | }; | ||
| 216 | |||
| 217 | /* OOB description for 512 byte pages with 16 byte OOB */ | ||
| 218 | static struct nand_ecclayout nandv2_hw_eccoob_smallpage = { | ||
| 219 | .eccbytes = 1 * 9, | ||
| 220 | .eccpos = { | ||
| 221 | 7, 8, 9, 10, 11, 12, 13, 14, 15 | ||
| 222 | }, | ||
| 223 | .oobfree = { | ||
| 224 | {.offset = 0, .length = 5} | ||
| 225 | } | ||
| 226 | }; | ||
| 227 | |||
| 228 | /* OOB description for 2048 byte pages with 64 byte OOB */ | ||
| 229 | static struct nand_ecclayout nandv2_hw_eccoob_largepage = { | ||
| 230 | .eccbytes = 4 * 9, | ||
| 231 | .eccpos = { | ||
| 232 | 7, 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 233 | 23, 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 234 | 39, 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 235 | 55, 56, 57, 58, 59, 60, 61, 62, 63 | ||
| 236 | }, | ||
| 237 | .oobfree = { | ||
| 238 | {.offset = 2, .length = 4}, | ||
| 239 | {.offset = 16, .length = 7}, | ||
| 240 | {.offset = 32, .length = 7}, | ||
| 241 | {.offset = 48, .length = 7} | ||
| 242 | } | ||
| 243 | }; | ||
| 244 | |||
| 245 | /* OOB description for 4096 byte pages with 128 byte OOB */ | ||
| 246 | static struct nand_ecclayout nandv2_hw_eccoob_4k = { | ||
| 247 | .eccbytes = 8 * 9, | ||
| 248 | .eccpos = { | ||
| 249 | 7, 8, 9, 10, 11, 12, 13, 14, 15, | ||
| 250 | 23, 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 251 | 39, 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 252 | 55, 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 253 | 71, 72, 73, 74, 75, 76, 77, 78, 79, | ||
| 254 | 87, 88, 89, 90, 91, 92, 93, 94, 95, | ||
| 255 | 103, 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 256 | 119, 120, 121, 122, 123, 124, 125, 126, 127, | ||
| 257 | }, | ||
| 258 | .oobfree = { | ||
| 259 | {.offset = 2, .length = 4}, | ||
| 260 | {.offset = 16, .length = 7}, | ||
| 261 | {.offset = 32, .length = 7}, | ||
| 262 | {.offset = 48, .length = 7}, | ||
| 263 | {.offset = 64, .length = 7}, | ||
| 264 | {.offset = 80, .length = 7}, | ||
| 265 | {.offset = 96, .length = 7}, | ||
| 266 | {.offset = 112, .length = 7}, | ||
| 267 | } | ||
| 268 | }; | ||
| 269 | |||
| 270 | static const char * const part_probes[] = { | 202 | static const char * const part_probes[] = { |
| 271 | "cmdlinepart", "RedBoot", "ofpart", NULL }; | 203 | "cmdlinepart", "RedBoot", "ofpart", NULL }; |
| 272 | 204 | ||
| @@ -942,6 +874,99 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
| 942 | } | 874 | } |
| 943 | } | 875 | } |
| 944 | 876 | ||
| 877 | static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 878 | struct mtd_oob_region *oobregion) | ||
| 879 | { | ||
| 880 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | ||
| 881 | |||
| 882 | if (section >= nand_chip->ecc.steps) | ||
| 883 | return -ERANGE; | ||
| 884 | |||
| 885 | oobregion->offset = (section * 16) + 6; | ||
| 886 | oobregion->length = nand_chip->ecc.bytes; | ||
| 887 | |||
| 888 | return 0; | ||
| 889 | } | ||
| 890 | |||
| 891 | static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 892 | struct mtd_oob_region *oobregion) | ||
| 893 | { | ||
| 894 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | ||
| 895 | |||
| 896 | if (section > nand_chip->ecc.steps) | ||
| 897 | return -ERANGE; | ||
| 898 | |||
| 899 | if (!section) { | ||
| 900 | if (mtd->writesize <= 512) { | ||
| 901 | oobregion->offset = 0; | ||
| 902 | oobregion->length = 5; | ||
| 903 | } else { | ||
| 904 | oobregion->offset = 2; | ||
| 905 | oobregion->length = 4; | ||
| 906 | } | ||
| 907 | } else { | ||
| 908 | oobregion->offset = ((section - 1) * 16) + | ||
| 909 | nand_chip->ecc.bytes + 6; | ||
| 910 | if (section < nand_chip->ecc.steps) | ||
| 911 | oobregion->length = (section * 16) + 6 - | ||
| 912 | oobregion->offset; | ||
| 913 | else | ||
| 914 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
| 915 | } | ||
| 916 | |||
| 917 | return 0; | ||
| 918 | } | ||
| 919 | |||
| 920 | static const struct mtd_ooblayout_ops mxc_v1_ooblayout_ops = { | ||
| 921 | .ecc = mxc_v1_ooblayout_ecc, | ||
| 922 | .free = mxc_v1_ooblayout_free, | ||
| 923 | }; | ||
| 924 | |||
| 925 | static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 926 | struct mtd_oob_region *oobregion) | ||
| 927 | { | ||
| 928 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | ||
| 929 | int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26; | ||
| 930 | |||
| 931 | if (section >= nand_chip->ecc.steps) | ||
| 932 | return -ERANGE; | ||
| 933 | |||
| 934 | oobregion->offset = (section * stepsize) + 7; | ||
| 935 | oobregion->length = nand_chip->ecc.bytes; | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 941 | struct mtd_oob_region *oobregion) | ||
| 942 | { | ||
| 943 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | ||
| 944 | int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26; | ||
| 945 | |||
| 946 | if (section > nand_chip->ecc.steps) | ||
| 947 | return -ERANGE; | ||
| 948 | |||
| 949 | if (!section) { | ||
| 950 | if (mtd->writesize <= 512) { | ||
| 951 | oobregion->offset = 0; | ||
| 952 | oobregion->length = 5; | ||
| 953 | } else { | ||
| 954 | oobregion->offset = 2; | ||
| 955 | oobregion->length = 4; | ||
| 956 | } | ||
| 957 | } else { | ||
| 958 | oobregion->offset = section * stepsize; | ||
| 959 | oobregion->length = 7; | ||
| 960 | } | ||
| 961 | |||
| 962 | return 0; | ||
| 963 | } | ||
| 964 | |||
| 965 | static const struct mtd_ooblayout_ops mxc_v2_ooblayout_ops = { | ||
| 966 | .ecc = mxc_v2_ooblayout_ecc, | ||
| 967 | .free = mxc_v2_ooblayout_free, | ||
| 968 | }; | ||
| 969 | |||
| 945 | /* | 970 | /* |
| 946 | * v2 and v3 type controllers can do 4bit or 8bit ecc depending | 971 | * v2 and v3 type controllers can do 4bit or 8bit ecc depending |
| 947 | * on how much oob the nand chip has. For 8bit ecc we need at least | 972 | * on how much oob the nand chip has. For 8bit ecc we need at least |
| @@ -959,23 +984,6 @@ static int get_eccsize(struct mtd_info *mtd) | |||
| 959 | return 8; | 984 | return 8; |
| 960 | } | 985 | } |
| 961 | 986 | ||
| 962 | static void ecc_8bit_layout_4k(struct nand_ecclayout *layout) | ||
| 963 | { | ||
| 964 | int i, j; | ||
| 965 | |||
| 966 | layout->eccbytes = 8*18; | ||
| 967 | for (i = 0; i < 8; i++) | ||
| 968 | for (j = 0; j < 18; j++) | ||
| 969 | layout->eccpos[i*18 + j] = i*26 + j + 7; | ||
| 970 | |||
| 971 | layout->oobfree[0].offset = 2; | ||
| 972 | layout->oobfree[0].length = 4; | ||
| 973 | for (i = 1; i < 8; i++) { | ||
| 974 | layout->oobfree[i].offset = i*26; | ||
| 975 | layout->oobfree[i].length = 7; | ||
| 976 | } | ||
| 977 | } | ||
| 978 | |||
| 979 | static void preset_v1(struct mtd_info *mtd) | 987 | static void preset_v1(struct mtd_info *mtd) |
| 980 | { | 988 | { |
| 981 | struct nand_chip *nand_chip = mtd_to_nand(mtd); | 989 | struct nand_chip *nand_chip = mtd_to_nand(mtd); |
| @@ -1269,9 +1277,7 @@ static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { | |||
| 1269 | .check_int = check_int_v1_v2, | 1277 | .check_int = check_int_v1_v2, |
| 1270 | .irq_control = irq_control_v1_v2, | 1278 | .irq_control = irq_control_v1_v2, |
| 1271 | .get_ecc_status = get_ecc_status_v1, | 1279 | .get_ecc_status = get_ecc_status_v1, |
| 1272 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | 1280 | .ooblayout = &mxc_v1_ooblayout_ops, |
| 1273 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
| 1274 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
| 1275 | .select_chip = mxc_nand_select_chip_v1_v3, | 1281 | .select_chip = mxc_nand_select_chip_v1_v3, |
| 1276 | .correct_data = mxc_nand_correct_data_v1, | 1282 | .correct_data = mxc_nand_correct_data_v1, |
| 1277 | .irqpending_quirk = 1, | 1283 | .irqpending_quirk = 1, |
| @@ -1294,9 +1300,7 @@ static const struct mxc_nand_devtype_data imx27_nand_devtype_data = { | |||
| 1294 | .check_int = check_int_v1_v2, | 1300 | .check_int = check_int_v1_v2, |
| 1295 | .irq_control = irq_control_v1_v2, | 1301 | .irq_control = irq_control_v1_v2, |
| 1296 | .get_ecc_status = get_ecc_status_v1, | 1302 | .get_ecc_status = get_ecc_status_v1, |
| 1297 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | 1303 | .ooblayout = &mxc_v1_ooblayout_ops, |
| 1298 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
| 1299 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
| 1300 | .select_chip = mxc_nand_select_chip_v1_v3, | 1304 | .select_chip = mxc_nand_select_chip_v1_v3, |
| 1301 | .correct_data = mxc_nand_correct_data_v1, | 1305 | .correct_data = mxc_nand_correct_data_v1, |
| 1302 | .irqpending_quirk = 0, | 1306 | .irqpending_quirk = 0, |
| @@ -1320,9 +1324,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { | |||
| 1320 | .check_int = check_int_v1_v2, | 1324 | .check_int = check_int_v1_v2, |
| 1321 | .irq_control = irq_control_v1_v2, | 1325 | .irq_control = irq_control_v1_v2, |
| 1322 | .get_ecc_status = get_ecc_status_v2, | 1326 | .get_ecc_status = get_ecc_status_v2, |
| 1323 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | 1327 | .ooblayout = &mxc_v2_ooblayout_ops, |
| 1324 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
| 1325 | .ecclayout_4k = &nandv2_hw_eccoob_4k, | ||
| 1326 | .select_chip = mxc_nand_select_chip_v2, | 1328 | .select_chip = mxc_nand_select_chip_v2, |
| 1327 | .correct_data = mxc_nand_correct_data_v2_v3, | 1329 | .correct_data = mxc_nand_correct_data_v2_v3, |
| 1328 | .irqpending_quirk = 0, | 1330 | .irqpending_quirk = 0, |
| @@ -1346,9 +1348,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { | |||
| 1346 | .check_int = check_int_v3, | 1348 | .check_int = check_int_v3, |
| 1347 | .irq_control = irq_control_v3, | 1349 | .irq_control = irq_control_v3, |
| 1348 | .get_ecc_status = get_ecc_status_v3, | 1350 | .get_ecc_status = get_ecc_status_v3, |
| 1349 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | 1351 | .ooblayout = &mxc_v2_ooblayout_ops, |
| 1350 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
| 1351 | .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
| 1352 | .select_chip = mxc_nand_select_chip_v1_v3, | 1352 | .select_chip = mxc_nand_select_chip_v1_v3, |
| 1353 | .correct_data = mxc_nand_correct_data_v2_v3, | 1353 | .correct_data = mxc_nand_correct_data_v2_v3, |
| 1354 | .irqpending_quirk = 0, | 1354 | .irqpending_quirk = 0, |
| @@ -1373,9 +1373,7 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = { | |||
| 1373 | .check_int = check_int_v3, | 1373 | .check_int = check_int_v3, |
| 1374 | .irq_control = irq_control_v3, | 1374 | .irq_control = irq_control_v3, |
| 1375 | .get_ecc_status = get_ecc_status_v3, | 1375 | .get_ecc_status = get_ecc_status_v3, |
| 1376 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | 1376 | .ooblayout = &mxc_v2_ooblayout_ops, |
| 1377 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
| 1378 | .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
| 1379 | .select_chip = mxc_nand_select_chip_v1_v3, | 1377 | .select_chip = mxc_nand_select_chip_v1_v3, |
| 1380 | .correct_data = mxc_nand_correct_data_v2_v3, | 1378 | .correct_data = mxc_nand_correct_data_v2_v3, |
| 1381 | .irqpending_quirk = 0, | 1379 | .irqpending_quirk = 0, |
| @@ -1461,25 +1459,12 @@ MODULE_DEVICE_TABLE(of, mxcnd_dt_ids); | |||
| 1461 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | 1459 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) |
| 1462 | { | 1460 | { |
| 1463 | struct device_node *np = host->dev->of_node; | 1461 | struct device_node *np = host->dev->of_node; |
| 1464 | struct mxc_nand_platform_data *pdata = &host->pdata; | ||
| 1465 | const struct of_device_id *of_id = | 1462 | const struct of_device_id *of_id = |
| 1466 | of_match_device(mxcnd_dt_ids, host->dev); | 1463 | of_match_device(mxcnd_dt_ids, host->dev); |
| 1467 | int buswidth; | ||
| 1468 | 1464 | ||
| 1469 | if (!np) | 1465 | if (!np) |
| 1470 | return 1; | 1466 | return 1; |
| 1471 | 1467 | ||
| 1472 | if (of_get_nand_ecc_mode(np) >= 0) | ||
| 1473 | pdata->hw_ecc = 1; | ||
| 1474 | |||
| 1475 | pdata->flash_bbt = of_get_nand_on_flash_bbt(np); | ||
| 1476 | |||
| 1477 | buswidth = of_get_nand_bus_width(np); | ||
| 1478 | if (buswidth < 0) | ||
| 1479 | return buswidth; | ||
| 1480 | |||
| 1481 | pdata->width = buswidth / 8; | ||
| 1482 | |||
| 1483 | host->devtype_data = of_id->data; | 1468 | host->devtype_data = of_id->data; |
| 1484 | 1469 | ||
| 1485 | return 0; | 1470 | return 0; |
| @@ -1576,27 +1561,22 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
| 1576 | 1561 | ||
| 1577 | this->select_chip = host->devtype_data->select_chip; | 1562 | this->select_chip = host->devtype_data->select_chip; |
| 1578 | this->ecc.size = 512; | 1563 | this->ecc.size = 512; |
| 1579 | this->ecc.layout = host->devtype_data->ecclayout_512; | 1564 | mtd_set_ooblayout(mtd, host->devtype_data->ooblayout); |
| 1580 | 1565 | ||
| 1581 | if (host->pdata.hw_ecc) { | 1566 | if (host->pdata.hw_ecc) { |
| 1582 | this->ecc.calculate = mxc_nand_calculate_ecc; | ||
| 1583 | this->ecc.hwctl = mxc_nand_enable_hwecc; | ||
| 1584 | this->ecc.correct = host->devtype_data->correct_data; | ||
| 1585 | this->ecc.mode = NAND_ECC_HW; | 1567 | this->ecc.mode = NAND_ECC_HW; |
| 1586 | } else { | 1568 | } else { |
| 1587 | this->ecc.mode = NAND_ECC_SOFT; | 1569 | this->ecc.mode = NAND_ECC_SOFT; |
| 1570 | this->ecc.algo = NAND_ECC_HAMMING; | ||
| 1588 | } | 1571 | } |
| 1589 | 1572 | ||
| 1590 | /* NAND bus width determines access functions used by upper layer */ | 1573 | /* NAND bus width determines access functions used by upper layer */ |
| 1591 | if (host->pdata.width == 2) | 1574 | if (host->pdata.width == 2) |
| 1592 | this->options |= NAND_BUSWIDTH_16; | 1575 | this->options |= NAND_BUSWIDTH_16; |
| 1593 | 1576 | ||
| 1594 | if (host->pdata.flash_bbt) { | 1577 | /* update flash based bbt */ |
| 1595 | this->bbt_td = &bbt_main_descr; | 1578 | if (host->pdata.flash_bbt) |
| 1596 | this->bbt_md = &bbt_mirror_descr; | ||
| 1597 | /* update flash based bbt */ | ||
| 1598 | this->bbt_options |= NAND_BBT_USE_FLASH; | 1579 | this->bbt_options |= NAND_BBT_USE_FLASH; |
| 1599 | } | ||
| 1600 | 1580 | ||
| 1601 | init_completion(&host->op_completion); | 1581 | init_completion(&host->op_completion); |
| 1602 | 1582 | ||
| @@ -1637,6 +1617,26 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
| 1637 | goto escan; | 1617 | goto escan; |
| 1638 | } | 1618 | } |
| 1639 | 1619 | ||
| 1620 | switch (this->ecc.mode) { | ||
| 1621 | case NAND_ECC_HW: | ||
| 1622 | this->ecc.calculate = mxc_nand_calculate_ecc; | ||
| 1623 | this->ecc.hwctl = mxc_nand_enable_hwecc; | ||
| 1624 | this->ecc.correct = host->devtype_data->correct_data; | ||
| 1625 | break; | ||
| 1626 | |||
| 1627 | case NAND_ECC_SOFT: | ||
| 1628 | break; | ||
| 1629 | |||
| 1630 | default: | ||
| 1631 | err = -EINVAL; | ||
| 1632 | goto escan; | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | if (this->bbt_options & NAND_BBT_USE_FLASH) { | ||
| 1636 | this->bbt_td = &bbt_main_descr; | ||
| 1637 | this->bbt_md = &bbt_mirror_descr; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | /* allocate the right size buffer now */ | 1640 | /* allocate the right size buffer now */ |
| 1641 | devm_kfree(&pdev->dev, (void *)host->data_buf); | 1641 | devm_kfree(&pdev->dev, (void *)host->data_buf); |
| 1642 | host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize, | 1642 | host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize, |
| @@ -1649,12 +1649,11 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
| 1649 | /* Call preset again, with correct writesize this time */ | 1649 | /* Call preset again, with correct writesize this time */ |
| 1650 | host->devtype_data->preset(mtd); | 1650 | host->devtype_data->preset(mtd); |
| 1651 | 1651 | ||
| 1652 | if (mtd->writesize == 2048) | 1652 | if (!this->ecc.bytes) { |
| 1653 | this->ecc.layout = host->devtype_data->ecclayout_2k; | 1653 | if (host->eccsize == 8) |
| 1654 | else if (mtd->writesize == 4096) { | 1654 | this->ecc.bytes = 18; |
| 1655 | this->ecc.layout = host->devtype_data->ecclayout_4k; | 1655 | else if (host->eccsize == 4) |
| 1656 | if (get_eccsize(mtd) == 8) | 1656 | this->ecc.bytes = 9; |
| 1657 | ecc_8bit_layout_4k(this->ecc.layout); | ||
| 1658 | } | 1657 | } |
| 1659 | 1658 | ||
| 1660 | /* | 1659 | /* |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ba4f603e0537..0b0dc29d2af7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -45,56 +45,98 @@ | |||
| 45 | #include <linux/bitops.h> | 45 | #include <linux/bitops.h> |
| 46 | #include <linux/io.h> | 46 | #include <linux/io.h> |
| 47 | #include <linux/mtd/partitions.h> | 47 | #include <linux/mtd/partitions.h> |
| 48 | #include <linux/of_mtd.h> | 48 | #include <linux/of.h> |
| 49 | |||
| 50 | static int nand_get_device(struct mtd_info *mtd, int new_state); | ||
| 51 | |||
| 52 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | ||
| 53 | struct mtd_oob_ops *ops); | ||
| 49 | 54 | ||
| 50 | /* Define default oob placement schemes for large and small page devices */ | 55 | /* Define default oob placement schemes for large and small page devices */ |
| 51 | static struct nand_ecclayout nand_oob_8 = { | 56 | static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, |
| 52 | .eccbytes = 3, | 57 | struct mtd_oob_region *oobregion) |
| 53 | .eccpos = {0, 1, 2}, | 58 | { |
| 54 | .oobfree = { | 59 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 55 | {.offset = 3, | 60 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 56 | .length = 2}, | ||
| 57 | {.offset = 6, | ||
| 58 | .length = 2} } | ||
| 59 | }; | ||
| 60 | 61 | ||
| 61 | static struct nand_ecclayout nand_oob_16 = { | 62 | if (section > 1) |
| 62 | .eccbytes = 6, | 63 | return -ERANGE; |
| 63 | .eccpos = {0, 1, 2, 3, 6, 7}, | ||
| 64 | .oobfree = { | ||
| 65 | {.offset = 8, | ||
| 66 | . length = 8} } | ||
| 67 | }; | ||
| 68 | 64 | ||
| 69 | static struct nand_ecclayout nand_oob_64 = { | 65 | if (!section) { |
| 70 | .eccbytes = 24, | 66 | oobregion->offset = 0; |
| 71 | .eccpos = { | 67 | oobregion->length = 4; |
| 72 | 40, 41, 42, 43, 44, 45, 46, 47, | 68 | } else { |
| 73 | 48, 49, 50, 51, 52, 53, 54, 55, | 69 | oobregion->offset = 6; |
| 74 | 56, 57, 58, 59, 60, 61, 62, 63}, | 70 | oobregion->length = ecc->total - 4; |
| 75 | .oobfree = { | 71 | } |
| 76 | {.offset = 2, | 72 | |
| 77 | .length = 38} } | 73 | return 0; |
| 78 | }; | 74 | } |
| 75 | |||
| 76 | static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section, | ||
| 77 | struct mtd_oob_region *oobregion) | ||
| 78 | { | ||
| 79 | if (section > 1) | ||
| 80 | return -ERANGE; | ||
| 81 | |||
| 82 | if (mtd->oobsize == 16) { | ||
| 83 | if (section) | ||
| 84 | return -ERANGE; | ||
| 85 | |||
| 86 | oobregion->length = 8; | ||
| 87 | oobregion->offset = 8; | ||
| 88 | } else { | ||
| 89 | oobregion->length = 2; | ||
| 90 | if (!section) | ||
| 91 | oobregion->offset = 3; | ||
| 92 | else | ||
| 93 | oobregion->offset = 6; | ||
| 94 | } | ||
| 95 | |||
| 96 | return 0; | ||
| 97 | } | ||
| 79 | 98 | ||
| 80 | static struct nand_ecclayout nand_oob_128 = { | 99 | const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = { |
| 81 | .eccbytes = 48, | 100 | .ecc = nand_ooblayout_ecc_sp, |
| 82 | .eccpos = { | 101 | .free = nand_ooblayout_free_sp, |
| 83 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
| 84 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
| 85 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
| 86 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 87 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
| 88 | 120, 121, 122, 123, 124, 125, 126, 127}, | ||
| 89 | .oobfree = { | ||
| 90 | {.offset = 2, | ||
| 91 | .length = 78} } | ||
| 92 | }; | 102 | }; |
| 103 | EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops); | ||
| 93 | 104 | ||
| 94 | static int nand_get_device(struct mtd_info *mtd, int new_state); | 105 | static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section, |
| 106 | struct mtd_oob_region *oobregion) | ||
| 107 | { | ||
| 108 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 109 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 95 | 110 | ||
| 96 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | 111 | if (section) |
| 97 | struct mtd_oob_ops *ops); | 112 | return -ERANGE; |
| 113 | |||
| 114 | oobregion->length = ecc->total; | ||
| 115 | oobregion->offset = mtd->oobsize - oobregion->length; | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section, | ||
| 121 | struct mtd_oob_region *oobregion) | ||
| 122 | { | ||
| 123 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 124 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 125 | |||
| 126 | if (section) | ||
| 127 | return -ERANGE; | ||
| 128 | |||
| 129 | oobregion->length = mtd->oobsize - ecc->total - 2; | ||
| 130 | oobregion->offset = 2; | ||
| 131 | |||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { | ||
| 136 | .ecc = nand_ooblayout_ecc_lp, | ||
| 137 | .free = nand_ooblayout_free_lp, | ||
| 138 | }; | ||
| 139 | EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); | ||
| 98 | 140 | ||
| 99 | static int check_offs_len(struct mtd_info *mtd, | 141 | static int check_offs_len(struct mtd_info *mtd, |
| 100 | loff_t ofs, uint64_t len) | 142 | loff_t ofs, uint64_t len) |
| @@ -1279,13 +1321,12 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, | |||
| 1279 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | 1321 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
| 1280 | uint8_t *buf, int oob_required, int page) | 1322 | uint8_t *buf, int oob_required, int page) |
| 1281 | { | 1323 | { |
| 1282 | int i, eccsize = chip->ecc.size; | 1324 | int i, eccsize = chip->ecc.size, ret; |
| 1283 | int eccbytes = chip->ecc.bytes; | 1325 | int eccbytes = chip->ecc.bytes; |
| 1284 | int eccsteps = chip->ecc.steps; | 1326 | int eccsteps = chip->ecc.steps; |
| 1285 | uint8_t *p = buf; | 1327 | uint8_t *p = buf; |
| 1286 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1328 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 1287 | uint8_t *ecc_code = chip->buffers->ecccode; | 1329 | uint8_t *ecc_code = chip->buffers->ecccode; |
| 1288 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1289 | unsigned int max_bitflips = 0; | 1330 | unsigned int max_bitflips = 0; |
| 1290 | 1331 | ||
| 1291 | chip->ecc.read_page_raw(mtd, chip, buf, 1, page); | 1332 | chip->ecc.read_page_raw(mtd, chip, buf, 1, page); |
| @@ -1293,8 +1334,10 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1293 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 1334 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
| 1294 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 1335 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
| 1295 | 1336 | ||
| 1296 | for (i = 0; i < chip->ecc.total; i++) | 1337 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
| 1297 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1338 | chip->ecc.total); |
| 1339 | if (ret) | ||
| 1340 | return ret; | ||
| 1298 | 1341 | ||
| 1299 | eccsteps = chip->ecc.steps; | 1342 | eccsteps = chip->ecc.steps; |
| 1300 | p = buf; | 1343 | p = buf; |
| @@ -1326,14 +1369,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1326 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, | 1369 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, |
| 1327 | int page) | 1370 | int page) |
| 1328 | { | 1371 | { |
| 1329 | int start_step, end_step, num_steps; | 1372 | int start_step, end_step, num_steps, ret; |
| 1330 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1331 | uint8_t *p; | 1373 | uint8_t *p; |
| 1332 | int data_col_addr, i, gaps = 0; | 1374 | int data_col_addr, i, gaps = 0; |
| 1333 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1375 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
| 1334 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1376 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
| 1335 | int index; | 1377 | int index, section = 0; |
| 1336 | unsigned int max_bitflips = 0; | 1378 | unsigned int max_bitflips = 0; |
| 1379 | struct mtd_oob_region oobregion = { }; | ||
| 1337 | 1380 | ||
| 1338 | /* Column address within the page aligned to ECC size (256bytes) */ | 1381 | /* Column address within the page aligned to ECC size (256bytes) */ |
| 1339 | start_step = data_offs / chip->ecc.size; | 1382 | start_step = data_offs / chip->ecc.size; |
| @@ -1361,12 +1404,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1361 | * The performance is faster if we position offsets according to | 1404 | * The performance is faster if we position offsets according to |
| 1362 | * ecc.pos. Let's make sure that there are no gaps in ECC positions. | 1405 | * ecc.pos. Let's make sure that there are no gaps in ECC positions. |
| 1363 | */ | 1406 | */ |
| 1364 | for (i = 0; i < eccfrag_len - 1; i++) { | 1407 | ret = mtd_ooblayout_find_eccregion(mtd, index, §ion, &oobregion); |
| 1365 | if (eccpos[i + index] + 1 != eccpos[i + index + 1]) { | 1408 | if (ret) |
| 1366 | gaps = 1; | 1409 | return ret; |
| 1367 | break; | 1410 | |
| 1368 | } | 1411 | if (oobregion.length < eccfrag_len) |
| 1369 | } | 1412 | gaps = 1; |
| 1413 | |||
| 1370 | if (gaps) { | 1414 | if (gaps) { |
| 1371 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | 1415 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); |
| 1372 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1416 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
| @@ -1375,20 +1419,23 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1375 | * Send the command to read the particular ECC bytes take care | 1419 | * Send the command to read the particular ECC bytes take care |
| 1376 | * about buswidth alignment in read_buf. | 1420 | * about buswidth alignment in read_buf. |
| 1377 | */ | 1421 | */ |
| 1378 | aligned_pos = eccpos[index] & ~(busw - 1); | 1422 | aligned_pos = oobregion.offset & ~(busw - 1); |
| 1379 | aligned_len = eccfrag_len; | 1423 | aligned_len = eccfrag_len; |
| 1380 | if (eccpos[index] & (busw - 1)) | 1424 | if (oobregion.offset & (busw - 1)) |
| 1381 | aligned_len++; | 1425 | aligned_len++; |
| 1382 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) | 1426 | if ((oobregion.offset + (num_steps * chip->ecc.bytes)) & |
| 1427 | (busw - 1)) | ||
| 1383 | aligned_len++; | 1428 | aligned_len++; |
| 1384 | 1429 | ||
| 1385 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | 1430 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
| 1386 | mtd->writesize + aligned_pos, -1); | 1431 | mtd->writesize + aligned_pos, -1); |
| 1387 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | 1432 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); |
| 1388 | } | 1433 | } |
| 1389 | 1434 | ||
| 1390 | for (i = 0; i < eccfrag_len; i++) | 1435 | ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode, |
| 1391 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; | 1436 | chip->oob_poi, index, eccfrag_len); |
| 1437 | if (ret) | ||
| 1438 | return ret; | ||
| 1392 | 1439 | ||
| 1393 | p = bufpoi + data_col_addr; | 1440 | p = bufpoi + data_col_addr; |
| 1394 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { | 1441 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { |
| @@ -1429,13 +1476,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1429 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 1476 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
| 1430 | uint8_t *buf, int oob_required, int page) | 1477 | uint8_t *buf, int oob_required, int page) |
| 1431 | { | 1478 | { |
| 1432 | int i, eccsize = chip->ecc.size; | 1479 | int i, eccsize = chip->ecc.size, ret; |
| 1433 | int eccbytes = chip->ecc.bytes; | 1480 | int eccbytes = chip->ecc.bytes; |
| 1434 | int eccsteps = chip->ecc.steps; | 1481 | int eccsteps = chip->ecc.steps; |
| 1435 | uint8_t *p = buf; | 1482 | uint8_t *p = buf; |
| 1436 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1483 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 1437 | uint8_t *ecc_code = chip->buffers->ecccode; | 1484 | uint8_t *ecc_code = chip->buffers->ecccode; |
| 1438 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1439 | unsigned int max_bitflips = 0; | 1485 | unsigned int max_bitflips = 0; |
| 1440 | 1486 | ||
| 1441 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1487 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
| @@ -1445,8 +1491,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1445 | } | 1491 | } |
| 1446 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1492 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
| 1447 | 1493 | ||
| 1448 | for (i = 0; i < chip->ecc.total; i++) | 1494 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
| 1449 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1495 | chip->ecc.total); |
| 1496 | if (ret) | ||
| 1497 | return ret; | ||
| 1450 | 1498 | ||
| 1451 | eccsteps = chip->ecc.steps; | 1499 | eccsteps = chip->ecc.steps; |
| 1452 | p = buf; | 1500 | p = buf; |
| @@ -1491,12 +1539,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1491 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | 1539 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, |
| 1492 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | 1540 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) |
| 1493 | { | 1541 | { |
| 1494 | int i, eccsize = chip->ecc.size; | 1542 | int i, eccsize = chip->ecc.size, ret; |
| 1495 | int eccbytes = chip->ecc.bytes; | 1543 | int eccbytes = chip->ecc.bytes; |
| 1496 | int eccsteps = chip->ecc.steps; | 1544 | int eccsteps = chip->ecc.steps; |
| 1497 | uint8_t *p = buf; | 1545 | uint8_t *p = buf; |
| 1498 | uint8_t *ecc_code = chip->buffers->ecccode; | 1546 | uint8_t *ecc_code = chip->buffers->ecccode; |
| 1499 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1500 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1547 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 1501 | unsigned int max_bitflips = 0; | 1548 | unsigned int max_bitflips = 0; |
| 1502 | 1549 | ||
| @@ -1505,8 +1552,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
| 1505 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1552 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
| 1506 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | 1553 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |
| 1507 | 1554 | ||
| 1508 | for (i = 0; i < chip->ecc.total; i++) | 1555 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
| 1509 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1556 | chip->ecc.total); |
| 1557 | if (ret) | ||
| 1558 | return ret; | ||
| 1510 | 1559 | ||
| 1511 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1560 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
| 1512 | int stat; | 1561 | int stat; |
| @@ -1607,14 +1656,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1607 | 1656 | ||
| 1608 | /** | 1657 | /** |
| 1609 | * nand_transfer_oob - [INTERN] Transfer oob to client buffer | 1658 | * nand_transfer_oob - [INTERN] Transfer oob to client buffer |
| 1610 | * @chip: nand chip structure | 1659 | * @mtd: mtd info structure |
| 1611 | * @oob: oob destination address | 1660 | * @oob: oob destination address |
| 1612 | * @ops: oob ops structure | 1661 | * @ops: oob ops structure |
| 1613 | * @len: size of oob to transfer | 1662 | * @len: size of oob to transfer |
| 1614 | */ | 1663 | */ |
| 1615 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | 1664 | static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob, |
| 1616 | struct mtd_oob_ops *ops, size_t len) | 1665 | struct mtd_oob_ops *ops, size_t len) |
| 1617 | { | 1666 | { |
| 1667 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1668 | int ret; | ||
| 1669 | |||
| 1618 | switch (ops->mode) { | 1670 | switch (ops->mode) { |
| 1619 | 1671 | ||
| 1620 | case MTD_OPS_PLACE_OOB: | 1672 | case MTD_OPS_PLACE_OOB: |
| @@ -1622,31 +1674,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
| 1622 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); | 1674 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); |
| 1623 | return oob + len; | 1675 | return oob + len; |
| 1624 | 1676 | ||
| 1625 | case MTD_OPS_AUTO_OOB: { | 1677 | case MTD_OPS_AUTO_OOB: |
| 1626 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 1678 | ret = mtd_ooblayout_get_databytes(mtd, oob, chip->oob_poi, |
| 1627 | uint32_t boffs = 0, roffs = ops->ooboffs; | 1679 | ops->ooboffs, len); |
| 1628 | size_t bytes = 0; | 1680 | BUG_ON(ret); |
| 1629 | 1681 | return oob + len; | |
| 1630 | for (; free->length && len; free++, len -= bytes) { | 1682 | |
| 1631 | /* Read request not from offset 0? */ | ||
| 1632 | if (unlikely(roffs)) { | ||
| 1633 | if (roffs >= free->length) { | ||
| 1634 | roffs -= free->length; | ||
| 1635 | continue; | ||
| 1636 | } | ||
| 1637 | boffs = free->offset + roffs; | ||
| 1638 | bytes = min_t(size_t, len, | ||
| 1639 | (free->length - roffs)); | ||
| 1640 | roffs = 0; | ||
| 1641 | } else { | ||
| 1642 | bytes = min_t(size_t, len, free->length); | ||
| 1643 | boffs = free->offset; | ||
| 1644 | } | ||
| 1645 | memcpy(oob, chip->oob_poi + boffs, bytes); | ||
| 1646 | oob += bytes; | ||
| 1647 | } | ||
| 1648 | return oob; | ||
| 1649 | } | ||
| 1650 | default: | 1683 | default: |
| 1651 | BUG(); | 1684 | BUG(); |
| 1652 | } | 1685 | } |
| @@ -1780,7 +1813,7 @@ read_retry: | |||
| 1780 | int toread = min(oobreadlen, max_oobsize); | 1813 | int toread = min(oobreadlen, max_oobsize); |
| 1781 | 1814 | ||
| 1782 | if (toread) { | 1815 | if (toread) { |
| 1783 | oob = nand_transfer_oob(chip, | 1816 | oob = nand_transfer_oob(mtd, |
| 1784 | oob, ops, toread); | 1817 | oob, ops, toread); |
| 1785 | oobreadlen -= toread; | 1818 | oobreadlen -= toread; |
| 1786 | } | 1819 | } |
| @@ -1893,13 +1926,13 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1893 | * @chip: nand chip info structure | 1926 | * @chip: nand chip info structure |
| 1894 | * @page: page number to read | 1927 | * @page: page number to read |
| 1895 | */ | 1928 | */ |
| 1896 | static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1929 | int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) |
| 1897 | int page) | ||
| 1898 | { | 1930 | { |
| 1899 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | 1931 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
| 1900 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1932 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
| 1901 | return 0; | 1933 | return 0; |
| 1902 | } | 1934 | } |
| 1935 | EXPORT_SYMBOL(nand_read_oob_std); | ||
| 1903 | 1936 | ||
| 1904 | /** | 1937 | /** |
| 1905 | * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC | 1938 | * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC |
| @@ -1908,8 +1941,8 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1908 | * @chip: nand chip info structure | 1941 | * @chip: nand chip info structure |
| 1909 | * @page: page number to read | 1942 | * @page: page number to read |
| 1910 | */ | 1943 | */ |
| 1911 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1944 | int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
| 1912 | int page) | 1945 | int page) |
| 1913 | { | 1946 | { |
| 1914 | int length = mtd->oobsize; | 1947 | int length = mtd->oobsize; |
| 1915 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 1948 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
| @@ -1937,6 +1970,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1937 | 1970 | ||
| 1938 | return 0; | 1971 | return 0; |
| 1939 | } | 1972 | } |
| 1973 | EXPORT_SYMBOL(nand_read_oob_syndrome); | ||
| 1940 | 1974 | ||
| 1941 | /** | 1975 | /** |
| 1942 | * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function | 1976 | * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function |
| @@ -1944,8 +1978,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1944 | * @chip: nand chip info structure | 1978 | * @chip: nand chip info structure |
| 1945 | * @page: page number to write | 1979 | * @page: page number to write |
| 1946 | */ | 1980 | */ |
| 1947 | static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1981 | int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) |
| 1948 | int page) | ||
| 1949 | { | 1982 | { |
| 1950 | int status = 0; | 1983 | int status = 0; |
| 1951 | const uint8_t *buf = chip->oob_poi; | 1984 | const uint8_t *buf = chip->oob_poi; |
| @@ -1960,6 +1993,7 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1960 | 1993 | ||
| 1961 | return status & NAND_STATUS_FAIL ? -EIO : 0; | 1994 | return status & NAND_STATUS_FAIL ? -EIO : 0; |
| 1962 | } | 1995 | } |
| 1996 | EXPORT_SYMBOL(nand_write_oob_std); | ||
| 1963 | 1997 | ||
| 1964 | /** | 1998 | /** |
| 1965 | * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC | 1999 | * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC |
| @@ -1968,8 +2002,8 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1968 | * @chip: nand chip info structure | 2002 | * @chip: nand chip info structure |
| 1969 | * @page: page number to write | 2003 | * @page: page number to write |
| 1970 | */ | 2004 | */ |
| 1971 | static int nand_write_oob_syndrome(struct mtd_info *mtd, | 2005 | int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
| 1972 | struct nand_chip *chip, int page) | 2006 | int page) |
| 1973 | { | 2007 | { |
| 1974 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 2008 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
| 1975 | int eccsize = chip->ecc.size, length = mtd->oobsize; | 2009 | int eccsize = chip->ecc.size, length = mtd->oobsize; |
| @@ -2019,6 +2053,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
| 2019 | 2053 | ||
| 2020 | return status & NAND_STATUS_FAIL ? -EIO : 0; | 2054 | return status & NAND_STATUS_FAIL ? -EIO : 0; |
| 2021 | } | 2055 | } |
| 2056 | EXPORT_SYMBOL(nand_write_oob_syndrome); | ||
| 2022 | 2057 | ||
| 2023 | /** | 2058 | /** |
| 2024 | * nand_do_read_oob - [INTERN] NAND read out-of-band | 2059 | * nand_do_read_oob - [INTERN] NAND read out-of-band |
| @@ -2078,7 +2113,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
| 2078 | break; | 2113 | break; |
| 2079 | 2114 | ||
| 2080 | len = min(len, readlen); | 2115 | len = min(len, readlen); |
| 2081 | buf = nand_transfer_oob(chip, buf, ops, len); | 2116 | buf = nand_transfer_oob(mtd, buf, ops, len); |
| 2082 | 2117 | ||
| 2083 | if (chip->options & NAND_NEED_READRDY) { | 2118 | if (chip->options & NAND_NEED_READRDY) { |
| 2084 | /* Apply delay or wait for ready/busy pin */ | 2119 | /* Apply delay or wait for ready/busy pin */ |
| @@ -2237,19 +2272,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 2237 | const uint8_t *buf, int oob_required, | 2272 | const uint8_t *buf, int oob_required, |
| 2238 | int page) | 2273 | int page) |
| 2239 | { | 2274 | { |
| 2240 | int i, eccsize = chip->ecc.size; | 2275 | int i, eccsize = chip->ecc.size, ret; |
| 2241 | int eccbytes = chip->ecc.bytes; | 2276 | int eccbytes = chip->ecc.bytes; |
| 2242 | int eccsteps = chip->ecc.steps; | 2277 | int eccsteps = chip->ecc.steps; |
| 2243 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 2278 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 2244 | const uint8_t *p = buf; | 2279 | const uint8_t *p = buf; |
| 2245 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 2246 | 2280 | ||
| 2247 | /* Software ECC calculation */ | 2281 | /* Software ECC calculation */ |
| 2248 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 2282 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
| 2249 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 2283 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
| 2250 | 2284 | ||
| 2251 | for (i = 0; i < chip->ecc.total; i++) | 2285 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
| 2252 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2286 | chip->ecc.total); |
| 2287 | if (ret) | ||
| 2288 | return ret; | ||
| 2253 | 2289 | ||
| 2254 | return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); | 2290 | return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); |
| 2255 | } | 2291 | } |
| @@ -2266,12 +2302,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 2266 | const uint8_t *buf, int oob_required, | 2302 | const uint8_t *buf, int oob_required, |
| 2267 | int page) | 2303 | int page) |
| 2268 | { | 2304 | { |
| 2269 | int i, eccsize = chip->ecc.size; | 2305 | int i, eccsize = chip->ecc.size, ret; |
| 2270 | int eccbytes = chip->ecc.bytes; | 2306 | int eccbytes = chip->ecc.bytes; |
| 2271 | int eccsteps = chip->ecc.steps; | 2307 | int eccsteps = chip->ecc.steps; |
| 2272 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 2308 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 2273 | const uint8_t *p = buf; | 2309 | const uint8_t *p = buf; |
| 2274 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 2275 | 2310 | ||
| 2276 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 2311 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
| 2277 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | 2312 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
| @@ -2279,8 +2314,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 2279 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 2314 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
| 2280 | } | 2315 | } |
| 2281 | 2316 | ||
| 2282 | for (i = 0; i < chip->ecc.total; i++) | 2317 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
| 2283 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2318 | chip->ecc.total); |
| 2319 | if (ret) | ||
| 2320 | return ret; | ||
| 2284 | 2321 | ||
| 2285 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 2322 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
| 2286 | 2323 | ||
| @@ -2308,11 +2345,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, | |||
| 2308 | int ecc_size = chip->ecc.size; | 2345 | int ecc_size = chip->ecc.size; |
| 2309 | int ecc_bytes = chip->ecc.bytes; | 2346 | int ecc_bytes = chip->ecc.bytes; |
| 2310 | int ecc_steps = chip->ecc.steps; | 2347 | int ecc_steps = chip->ecc.steps; |
| 2311 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 2312 | uint32_t start_step = offset / ecc_size; | 2348 | uint32_t start_step = offset / ecc_size; |
| 2313 | uint32_t end_step = (offset + data_len - 1) / ecc_size; | 2349 | uint32_t end_step = (offset + data_len - 1) / ecc_size; |
| 2314 | int oob_bytes = mtd->oobsize / ecc_steps; | 2350 | int oob_bytes = mtd->oobsize / ecc_steps; |
| 2315 | int step, i; | 2351 | int step, ret; |
| 2316 | 2352 | ||
| 2317 | for (step = 0; step < ecc_steps; step++) { | 2353 | for (step = 0; step < ecc_steps; step++) { |
| 2318 | /* configure controller for WRITE access */ | 2354 | /* configure controller for WRITE access */ |
| @@ -2340,8 +2376,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, | |||
| 2340 | /* copy calculated ECC for whole page to chip->buffer->oob */ | 2376 | /* copy calculated ECC for whole page to chip->buffer->oob */ |
| 2341 | /* this include masked-value(0xFF) for unwritten subpages */ | 2377 | /* this include masked-value(0xFF) for unwritten subpages */ |
| 2342 | ecc_calc = chip->buffers->ecccalc; | 2378 | ecc_calc = chip->buffers->ecccalc; |
| 2343 | for (i = 0; i < chip->ecc.total; i++) | 2379 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
| 2344 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2380 | chip->ecc.total); |
| 2381 | if (ret) | ||
| 2382 | return ret; | ||
| 2345 | 2383 | ||
| 2346 | /* write OOB buffer to NAND device */ | 2384 | /* write OOB buffer to NAND device */ |
| 2347 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 2385 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
| @@ -2478,6 +2516,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, | |||
| 2478 | struct mtd_oob_ops *ops) | 2516 | struct mtd_oob_ops *ops) |
| 2479 | { | 2517 | { |
| 2480 | struct nand_chip *chip = mtd_to_nand(mtd); | 2518 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 2519 | int ret; | ||
| 2481 | 2520 | ||
| 2482 | /* | 2521 | /* |
| 2483 | * Initialise to all 0xFF, to avoid the possibility of left over OOB | 2522 | * Initialise to all 0xFF, to avoid the possibility of left over OOB |
| @@ -2492,31 +2531,12 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, | |||
| 2492 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); | 2531 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); |
| 2493 | return oob + len; | 2532 | return oob + len; |
| 2494 | 2533 | ||
| 2495 | case MTD_OPS_AUTO_OOB: { | 2534 | case MTD_OPS_AUTO_OOB: |
| 2496 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 2535 | ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi, |
| 2497 | uint32_t boffs = 0, woffs = ops->ooboffs; | 2536 | ops->ooboffs, len); |
| 2498 | size_t bytes = 0; | 2537 | BUG_ON(ret); |
| 2499 | 2538 | return oob + len; | |
| 2500 | for (; free->length && len; free++, len -= bytes) { | 2539 | |
| 2501 | /* Write request not from offset 0? */ | ||
| 2502 | if (unlikely(woffs)) { | ||
| 2503 | if (woffs >= free->length) { | ||
| 2504 | woffs -= free->length; | ||
| 2505 | continue; | ||
| 2506 | } | ||
| 2507 | boffs = free->offset + woffs; | ||
| 2508 | bytes = min_t(size_t, len, | ||
| 2509 | (free->length - woffs)); | ||
| 2510 | woffs = 0; | ||
| 2511 | } else { | ||
| 2512 | bytes = min_t(size_t, len, free->length); | ||
| 2513 | boffs = free->offset; | ||
| 2514 | } | ||
| 2515 | memcpy(chip->oob_poi + boffs, oob, bytes); | ||
| 2516 | oob += bytes; | ||
| 2517 | } | ||
| 2518 | return oob; | ||
| 2519 | } | ||
| 2520 | default: | 2540 | default: |
| 2521 | BUG(); | 2541 | BUG(); |
| 2522 | } | 2542 | } |
| @@ -3951,10 +3971,115 @@ ident_done: | |||
| 3951 | return type; | 3971 | return type; |
| 3952 | } | 3972 | } |
| 3953 | 3973 | ||
| 3974 | static const char * const nand_ecc_modes[] = { | ||
| 3975 | [NAND_ECC_NONE] = "none", | ||
| 3976 | [NAND_ECC_SOFT] = "soft", | ||
| 3977 | [NAND_ECC_HW] = "hw", | ||
| 3978 | [NAND_ECC_HW_SYNDROME] = "hw_syndrome", | ||
| 3979 | [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first", | ||
| 3980 | }; | ||
| 3981 | |||
| 3982 | static int of_get_nand_ecc_mode(struct device_node *np) | ||
| 3983 | { | ||
| 3984 | const char *pm; | ||
| 3985 | int err, i; | ||
| 3986 | |||
| 3987 | err = of_property_read_string(np, "nand-ecc-mode", &pm); | ||
| 3988 | if (err < 0) | ||
| 3989 | return err; | ||
| 3990 | |||
| 3991 | for (i = 0; i < ARRAY_SIZE(nand_ecc_modes); i++) | ||
| 3992 | if (!strcasecmp(pm, nand_ecc_modes[i])) | ||
| 3993 | return i; | ||
| 3994 | |||
| 3995 | /* | ||
| 3996 | * For backward compatibility we support few obsoleted values that don't | ||
| 3997 | * have their mappings into nand_ecc_modes_t anymore (they were merged | ||
| 3998 | * with other enums). | ||
| 3999 | */ | ||
| 4000 | if (!strcasecmp(pm, "soft_bch")) | ||
| 4001 | return NAND_ECC_SOFT; | ||
| 4002 | |||
| 4003 | return -ENODEV; | ||
| 4004 | } | ||
| 4005 | |||
| 4006 | static const char * const nand_ecc_algos[] = { | ||
| 4007 | [NAND_ECC_HAMMING] = "hamming", | ||
| 4008 | [NAND_ECC_BCH] = "bch", | ||
| 4009 | }; | ||
| 4010 | |||
| 4011 | static int of_get_nand_ecc_algo(struct device_node *np) | ||
| 4012 | { | ||
| 4013 | const char *pm; | ||
| 4014 | int err, i; | ||
| 4015 | |||
| 4016 | err = of_property_read_string(np, "nand-ecc-algo", &pm); | ||
| 4017 | if (!err) { | ||
| 4018 | for (i = NAND_ECC_HAMMING; i < ARRAY_SIZE(nand_ecc_algos); i++) | ||
| 4019 | if (!strcasecmp(pm, nand_ecc_algos[i])) | ||
| 4020 | return i; | ||
| 4021 | return -ENODEV; | ||
| 4022 | } | ||
| 4023 | |||
| 4024 | /* | ||
| 4025 | * For backward compatibility we also read "nand-ecc-mode" checking | ||
| 4026 | * for some obsoleted values that were specifying ECC algorithm. | ||
| 4027 | */ | ||
| 4028 | err = of_property_read_string(np, "nand-ecc-mode", &pm); | ||
| 4029 | if (err < 0) | ||
| 4030 | return err; | ||
| 4031 | |||
| 4032 | if (!strcasecmp(pm, "soft")) | ||
| 4033 | return NAND_ECC_HAMMING; | ||
| 4034 | else if (!strcasecmp(pm, "soft_bch")) | ||
| 4035 | return NAND_ECC_BCH; | ||
| 4036 | |||
| 4037 | return -ENODEV; | ||
| 4038 | } | ||
| 4039 | |||
| 4040 | static int of_get_nand_ecc_step_size(struct device_node *np) | ||
| 4041 | { | ||
| 4042 | int ret; | ||
| 4043 | u32 val; | ||
| 4044 | |||
| 4045 | ret = of_property_read_u32(np, "nand-ecc-step-size", &val); | ||
| 4046 | return ret ? ret : val; | ||
| 4047 | } | ||
| 4048 | |||
| 4049 | static int of_get_nand_ecc_strength(struct device_node *np) | ||
| 4050 | { | ||
| 4051 | int ret; | ||
| 4052 | u32 val; | ||
| 4053 | |||
| 4054 | ret = of_property_read_u32(np, "nand-ecc-strength", &val); | ||
| 4055 | return ret ? ret : val; | ||
| 4056 | } | ||
| 4057 | |||
| 4058 | static int of_get_nand_bus_width(struct device_node *np) | ||
| 4059 | { | ||
| 4060 | u32 val; | ||
| 4061 | |||
| 4062 | if (of_property_read_u32(np, "nand-bus-width", &val)) | ||
| 4063 | return 8; | ||
| 4064 | |||
| 4065 | switch (val) { | ||
| 4066 | case 8: | ||
| 4067 | case 16: | ||
| 4068 | return val; | ||
| 4069 | default: | ||
| 4070 | return -EIO; | ||
| 4071 | } | ||
| 4072 | } | ||
| 4073 | |||
| 4074 | static bool of_get_nand_on_flash_bbt(struct device_node *np) | ||
| 4075 | { | ||
| 4076 | return of_property_read_bool(np, "nand-on-flash-bbt"); | ||
| 4077 | } | ||
| 4078 | |||
| 3954 | static int nand_dt_init(struct nand_chip *chip) | 4079 | static int nand_dt_init(struct nand_chip *chip) |
| 3955 | { | 4080 | { |
| 3956 | struct device_node *dn = nand_get_flash_node(chip); | 4081 | struct device_node *dn = nand_get_flash_node(chip); |
| 3957 | int ecc_mode, ecc_strength, ecc_step; | 4082 | int ecc_mode, ecc_algo, ecc_strength, ecc_step; |
| 3958 | 4083 | ||
| 3959 | if (!dn) | 4084 | if (!dn) |
| 3960 | return 0; | 4085 | return 0; |
| @@ -3966,6 +4091,7 @@ static int nand_dt_init(struct nand_chip *chip) | |||
| 3966 | chip->bbt_options |= NAND_BBT_USE_FLASH; | 4091 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
| 3967 | 4092 | ||
| 3968 | ecc_mode = of_get_nand_ecc_mode(dn); | 4093 | ecc_mode = of_get_nand_ecc_mode(dn); |
| 4094 | ecc_algo = of_get_nand_ecc_algo(dn); | ||
| 3969 | ecc_strength = of_get_nand_ecc_strength(dn); | 4095 | ecc_strength = of_get_nand_ecc_strength(dn); |
| 3970 | ecc_step = of_get_nand_ecc_step_size(dn); | 4096 | ecc_step = of_get_nand_ecc_step_size(dn); |
| 3971 | 4097 | ||
| @@ -3978,6 +4104,9 @@ static int nand_dt_init(struct nand_chip *chip) | |||
| 3978 | if (ecc_mode >= 0) | 4104 | if (ecc_mode >= 0) |
| 3979 | chip->ecc.mode = ecc_mode; | 4105 | chip->ecc.mode = ecc_mode; |
| 3980 | 4106 | ||
| 4107 | if (ecc_algo >= 0) | ||
| 4108 | chip->ecc.algo = ecc_algo; | ||
| 4109 | |||
| 3981 | if (ecc_strength >= 0) | 4110 | if (ecc_strength >= 0) |
| 3982 | chip->ecc.strength = ecc_strength; | 4111 | chip->ecc.strength = ecc_strength; |
| 3983 | 4112 | ||
| @@ -4054,6 +4183,82 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
| 4054 | } | 4183 | } |
| 4055 | EXPORT_SYMBOL(nand_scan_ident); | 4184 | EXPORT_SYMBOL(nand_scan_ident); |
| 4056 | 4185 | ||
| 4186 | static int nand_set_ecc_soft_ops(struct mtd_info *mtd) | ||
| 4187 | { | ||
| 4188 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 4189 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 4190 | |||
| 4191 | if (WARN_ON(ecc->mode != NAND_ECC_SOFT)) | ||
| 4192 | return -EINVAL; | ||
| 4193 | |||
| 4194 | switch (ecc->algo) { | ||
| 4195 | case NAND_ECC_HAMMING: | ||
| 4196 | ecc->calculate = nand_calculate_ecc; | ||
| 4197 | ecc->correct = nand_correct_data; | ||
| 4198 | ecc->read_page = nand_read_page_swecc; | ||
| 4199 | ecc->read_subpage = nand_read_subpage; | ||
| 4200 | ecc->write_page = nand_write_page_swecc; | ||
| 4201 | ecc->read_page_raw = nand_read_page_raw; | ||
| 4202 | ecc->write_page_raw = nand_write_page_raw; | ||
| 4203 | ecc->read_oob = nand_read_oob_std; | ||
| 4204 | ecc->write_oob = nand_write_oob_std; | ||
| 4205 | if (!ecc->size) | ||
| 4206 | ecc->size = 256; | ||
| 4207 | ecc->bytes = 3; | ||
| 4208 | ecc->strength = 1; | ||
| 4209 | return 0; | ||
| 4210 | case NAND_ECC_BCH: | ||
| 4211 | if (!mtd_nand_has_bch()) { | ||
| 4212 | WARN(1, "CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | ||
| 4213 | return -EINVAL; | ||
| 4214 | } | ||
| 4215 | ecc->calculate = nand_bch_calculate_ecc; | ||
| 4216 | ecc->correct = nand_bch_correct_data; | ||
| 4217 | ecc->read_page = nand_read_page_swecc; | ||
| 4218 | ecc->read_subpage = nand_read_subpage; | ||
| 4219 | ecc->write_page = nand_write_page_swecc; | ||
| 4220 | ecc->read_page_raw = nand_read_page_raw; | ||
| 4221 | ecc->write_page_raw = nand_write_page_raw; | ||
| 4222 | ecc->read_oob = nand_read_oob_std; | ||
| 4223 | ecc->write_oob = nand_write_oob_std; | ||
| 4224 | /* | ||
| 4225 | * Board driver should supply ecc.size and ecc.strength | ||
| 4226 | * values to select how many bits are correctable. | ||
| 4227 | * Otherwise, default to 4 bits for large page devices. | ||
| 4228 | */ | ||
| 4229 | if (!ecc->size && (mtd->oobsize >= 64)) { | ||
| 4230 | ecc->size = 512; | ||
| 4231 | ecc->strength = 4; | ||
| 4232 | } | ||
| 4233 | |||
| 4234 | /* | ||
| 4235 | * if no ecc placement scheme was provided pickup the default | ||
| 4236 | * large page one. | ||
| 4237 | */ | ||
| 4238 | if (!mtd->ooblayout) { | ||
| 4239 | /* handle large page devices only */ | ||
| 4240 | if (mtd->oobsize < 64) { | ||
| 4241 | WARN(1, "OOB layout is required when using software BCH on small pages\n"); | ||
| 4242 | return -EINVAL; | ||
| 4243 | } | ||
| 4244 | |||
| 4245 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); | ||
| 4246 | } | ||
| 4247 | |||
| 4248 | /* See nand_bch_init() for details. */ | ||
| 4249 | ecc->bytes = 0; | ||
| 4250 | ecc->priv = nand_bch_init(mtd); | ||
| 4251 | if (!ecc->priv) { | ||
| 4252 | WARN(1, "BCH ECC initialization failed!\n"); | ||
| 4253 | return -EINVAL; | ||
| 4254 | } | ||
| 4255 | return 0; | ||
| 4256 | default: | ||
| 4257 | WARN(1, "Unsupported ECC algorithm!\n"); | ||
| 4258 | return -EINVAL; | ||
| 4259 | } | ||
| 4260 | } | ||
| 4261 | |||
| 4057 | /* | 4262 | /* |
| 4058 | * Check if the chip configuration meet the datasheet requirements. | 4263 | * Check if the chip configuration meet the datasheet requirements. |
| 4059 | 4264 | ||
| @@ -4098,14 +4303,15 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) | |||
| 4098 | */ | 4303 | */ |
| 4099 | int nand_scan_tail(struct mtd_info *mtd) | 4304 | int nand_scan_tail(struct mtd_info *mtd) |
| 4100 | { | 4305 | { |
| 4101 | int i; | ||
| 4102 | struct nand_chip *chip = mtd_to_nand(mtd); | 4306 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4103 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 4307 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 4104 | struct nand_buffers *nbuf; | 4308 | struct nand_buffers *nbuf; |
| 4309 | int ret; | ||
| 4105 | 4310 | ||
| 4106 | /* New bad blocks should be marked in OOB, flash-based BBT, or both */ | 4311 | /* New bad blocks should be marked in OOB, flash-based BBT, or both */ |
| 4107 | BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && | 4312 | if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && |
| 4108 | !(chip->bbt_options & NAND_BBT_USE_FLASH)); | 4313 | !(chip->bbt_options & NAND_BBT_USE_FLASH))) |
| 4314 | return -EINVAL; | ||
| 4109 | 4315 | ||
| 4110 | if (!(chip->options & NAND_OWN_BUFFERS)) { | 4316 | if (!(chip->options & NAND_OWN_BUFFERS)) { |
| 4111 | nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize | 4317 | nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize |
| @@ -4128,24 +4334,22 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4128 | /* | 4334 | /* |
| 4129 | * If no default placement scheme is given, select an appropriate one. | 4335 | * If no default placement scheme is given, select an appropriate one. |
| 4130 | */ | 4336 | */ |
| 4131 | if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) { | 4337 | if (!mtd->ooblayout && |
| 4338 | !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH)) { | ||
| 4132 | switch (mtd->oobsize) { | 4339 | switch (mtd->oobsize) { |
| 4133 | case 8: | 4340 | case 8: |
| 4134 | ecc->layout = &nand_oob_8; | ||
| 4135 | break; | ||
| 4136 | case 16: | 4341 | case 16: |
| 4137 | ecc->layout = &nand_oob_16; | 4342 | mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops); |
| 4138 | break; | 4343 | break; |
| 4139 | case 64: | 4344 | case 64: |
| 4140 | ecc->layout = &nand_oob_64; | ||
| 4141 | break; | ||
| 4142 | case 128: | 4345 | case 128: |
| 4143 | ecc->layout = &nand_oob_128; | 4346 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
| 4144 | break; | 4347 | break; |
| 4145 | default: | 4348 | default: |
| 4146 | pr_warn("No oob scheme defined for oobsize %d\n", | 4349 | WARN(1, "No oob scheme defined for oobsize %d\n", |
| 4147 | mtd->oobsize); | 4350 | mtd->oobsize); |
| 4148 | BUG(); | 4351 | ret = -EINVAL; |
| 4352 | goto err_free; | ||
| 4149 | } | 4353 | } |
| 4150 | } | 4354 | } |
| 4151 | 4355 | ||
| @@ -4161,8 +4365,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4161 | case NAND_ECC_HW_OOB_FIRST: | 4365 | case NAND_ECC_HW_OOB_FIRST: |
| 4162 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ | 4366 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ |
| 4163 | if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { | 4367 | if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { |
| 4164 | pr_warn("No ECC functions supplied; hardware ECC not possible\n"); | 4368 | WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); |
| 4165 | BUG(); | 4369 | ret = -EINVAL; |
| 4370 | goto err_free; | ||
| 4166 | } | 4371 | } |
| 4167 | if (!ecc->read_page) | 4372 | if (!ecc->read_page) |
| 4168 | ecc->read_page = nand_read_page_hwecc_oob_first; | 4373 | ecc->read_page = nand_read_page_hwecc_oob_first; |
| @@ -4192,8 +4397,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4192 | ecc->read_page == nand_read_page_hwecc || | 4397 | ecc->read_page == nand_read_page_hwecc || |
| 4193 | !ecc->write_page || | 4398 | !ecc->write_page || |
| 4194 | ecc->write_page == nand_write_page_hwecc)) { | 4399 | ecc->write_page == nand_write_page_hwecc)) { |
| 4195 | pr_warn("No ECC functions supplied; hardware ECC not possible\n"); | 4400 | WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); |
| 4196 | BUG(); | 4401 | ret = -EINVAL; |
| 4402 | goto err_free; | ||
| 4197 | } | 4403 | } |
| 4198 | /* Use standard syndrome read/write page function? */ | 4404 | /* Use standard syndrome read/write page function? */ |
| 4199 | if (!ecc->read_page) | 4405 | if (!ecc->read_page) |
| @@ -4211,61 +4417,22 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4211 | 4417 | ||
| 4212 | if (mtd->writesize >= ecc->size) { | 4418 | if (mtd->writesize >= ecc->size) { |
| 4213 | if (!ecc->strength) { | 4419 | if (!ecc->strength) { |
| 4214 | pr_warn("Driver must set ecc.strength when using hardware ECC\n"); | 4420 | WARN(1, "Driver must set ecc.strength when using hardware ECC\n"); |
| 4215 | BUG(); | 4421 | ret = -EINVAL; |
| 4422 | goto err_free; | ||
| 4216 | } | 4423 | } |
| 4217 | break; | 4424 | break; |
| 4218 | } | 4425 | } |
| 4219 | pr_warn("%d byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", | 4426 | pr_warn("%d byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", |
| 4220 | ecc->size, mtd->writesize); | 4427 | ecc->size, mtd->writesize); |
| 4221 | ecc->mode = NAND_ECC_SOFT; | 4428 | ecc->mode = NAND_ECC_SOFT; |
| 4429 | ecc->algo = NAND_ECC_HAMMING; | ||
| 4222 | 4430 | ||
| 4223 | case NAND_ECC_SOFT: | 4431 | case NAND_ECC_SOFT: |
| 4224 | ecc->calculate = nand_calculate_ecc; | 4432 | ret = nand_set_ecc_soft_ops(mtd); |
| 4225 | ecc->correct = nand_correct_data; | 4433 | if (ret) { |
| 4226 | ecc->read_page = nand_read_page_swecc; | 4434 | ret = -EINVAL; |
| 4227 | ecc->read_subpage = nand_read_subpage; | 4435 | goto err_free; |
| 4228 | ecc->write_page = nand_write_page_swecc; | ||
| 4229 | ecc->read_page_raw = nand_read_page_raw; | ||
| 4230 | ecc->write_page_raw = nand_write_page_raw; | ||
| 4231 | ecc->read_oob = nand_read_oob_std; | ||
| 4232 | ecc->write_oob = nand_write_oob_std; | ||
| 4233 | if (!ecc->size) | ||
| 4234 | ecc->size = 256; | ||
| 4235 | ecc->bytes = 3; | ||
| 4236 | ecc->strength = 1; | ||
| 4237 | break; | ||
| 4238 | |||
| 4239 | case NAND_ECC_SOFT_BCH: | ||
| 4240 | if (!mtd_nand_has_bch()) { | ||
| 4241 | pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | ||
| 4242 | BUG(); | ||
| 4243 | } | ||
| 4244 | ecc->calculate = nand_bch_calculate_ecc; | ||
| 4245 | ecc->correct = nand_bch_correct_data; | ||
| 4246 | ecc->read_page = nand_read_page_swecc; | ||
| 4247 | ecc->read_subpage = nand_read_subpage; | ||
| 4248 | ecc->write_page = nand_write_page_swecc; | ||
| 4249 | ecc->read_page_raw = nand_read_page_raw; | ||
| 4250 | ecc->write_page_raw = nand_write_page_raw; | ||
| 4251 | ecc->read_oob = nand_read_oob_std; | ||
| 4252 | ecc->write_oob = nand_write_oob_std; | ||
| 4253 | /* | ||
| 4254 | * Board driver should supply ecc.size and ecc.strength values | ||
| 4255 | * to select how many bits are correctable. Otherwise, default | ||
| 4256 | * to 4 bits for large page devices. | ||
| 4257 | */ | ||
| 4258 | if (!ecc->size && (mtd->oobsize >= 64)) { | ||
| 4259 | ecc->size = 512; | ||
| 4260 | ecc->strength = 4; | ||
| 4261 | } | ||
| 4262 | |||
| 4263 | /* See nand_bch_init() for details. */ | ||
| 4264 | ecc->bytes = 0; | ||
| 4265 | ecc->priv = nand_bch_init(mtd); | ||
| 4266 | if (!ecc->priv) { | ||
| 4267 | pr_warn("BCH ECC initialization failed!\n"); | ||
| 4268 | BUG(); | ||
| 4269 | } | 4436 | } |
| 4270 | break; | 4437 | break; |
| 4271 | 4438 | ||
| @@ -4283,8 +4450,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4283 | break; | 4450 | break; |
| 4284 | 4451 | ||
| 4285 | default: | 4452 | default: |
| 4286 | pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode); | 4453 | WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode); |
| 4287 | BUG(); | 4454 | ret = -EINVAL; |
| 4455 | goto err_free; | ||
| 4288 | } | 4456 | } |
| 4289 | 4457 | ||
| 4290 | /* For many systems, the standard OOB write also works for raw */ | 4458 | /* For many systems, the standard OOB write also works for raw */ |
| @@ -4293,20 +4461,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4293 | if (!ecc->write_oob_raw) | 4461 | if (!ecc->write_oob_raw) |
| 4294 | ecc->write_oob_raw = ecc->write_oob; | 4462 | ecc->write_oob_raw = ecc->write_oob; |
| 4295 | 4463 | ||
| 4296 | /* | 4464 | /* propagate ecc info to mtd_info */ |
| 4297 | * The number of bytes available for a client to place data into | 4465 | mtd->ecc_strength = ecc->strength; |
| 4298 | * the out of band area. | 4466 | mtd->ecc_step_size = ecc->size; |
| 4299 | */ | ||
| 4300 | mtd->oobavail = 0; | ||
| 4301 | if (ecc->layout) { | ||
| 4302 | for (i = 0; ecc->layout->oobfree[i].length; i++) | ||
| 4303 | mtd->oobavail += ecc->layout->oobfree[i].length; | ||
| 4304 | } | ||
| 4305 | |||
| 4306 | /* ECC sanity check: warn if it's too weak */ | ||
| 4307 | if (!nand_ecc_strength_good(mtd)) | ||
| 4308 | pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", | ||
| 4309 | mtd->name); | ||
| 4310 | 4467 | ||
| 4311 | /* | 4468 | /* |
| 4312 | * Set the number of read / write steps for one page depending on ECC | 4469 | * Set the number of read / write steps for one page depending on ECC |
| @@ -4314,11 +4471,27 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4314 | */ | 4471 | */ |
| 4315 | ecc->steps = mtd->writesize / ecc->size; | 4472 | ecc->steps = mtd->writesize / ecc->size; |
| 4316 | if (ecc->steps * ecc->size != mtd->writesize) { | 4473 | if (ecc->steps * ecc->size != mtd->writesize) { |
| 4317 | pr_warn("Invalid ECC parameters\n"); | 4474 | WARN(1, "Invalid ECC parameters\n"); |
| 4318 | BUG(); | 4475 | ret = -EINVAL; |
| 4476 | goto err_free; | ||
| 4319 | } | 4477 | } |
| 4320 | ecc->total = ecc->steps * ecc->bytes; | 4478 | ecc->total = ecc->steps * ecc->bytes; |
| 4321 | 4479 | ||
| 4480 | /* | ||
| 4481 | * The number of bytes available for a client to place data into | ||
| 4482 | * the out of band area. | ||
| 4483 | */ | ||
| 4484 | ret = mtd_ooblayout_count_freebytes(mtd); | ||
| 4485 | if (ret < 0) | ||
| 4486 | ret = 0; | ||
| 4487 | |||
| 4488 | mtd->oobavail = ret; | ||
| 4489 | |||
| 4490 | /* ECC sanity check: warn if it's too weak */ | ||
| 4491 | if (!nand_ecc_strength_good(mtd)) | ||
| 4492 | pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", | ||
| 4493 | mtd->name); | ||
| 4494 | |||
| 4322 | /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ | 4495 | /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ |
| 4323 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { | 4496 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { |
| 4324 | switch (ecc->steps) { | 4497 | switch (ecc->steps) { |
| @@ -4343,7 +4516,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4343 | /* Large page NAND with SOFT_ECC should support subpage reads */ | 4516 | /* Large page NAND with SOFT_ECC should support subpage reads */ |
| 4344 | switch (ecc->mode) { | 4517 | switch (ecc->mode) { |
| 4345 | case NAND_ECC_SOFT: | 4518 | case NAND_ECC_SOFT: |
| 4346 | case NAND_ECC_SOFT_BCH: | ||
| 4347 | if (chip->page_shift > 9) | 4519 | if (chip->page_shift > 9) |
| 4348 | chip->options |= NAND_SUBPAGE_READ; | 4520 | chip->options |= NAND_SUBPAGE_READ; |
| 4349 | break; | 4521 | break; |
| @@ -4375,10 +4547,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4375 | mtd->_block_markbad = nand_block_markbad; | 4547 | mtd->_block_markbad = nand_block_markbad; |
| 4376 | mtd->writebufsize = mtd->writesize; | 4548 | mtd->writebufsize = mtd->writesize; |
| 4377 | 4549 | ||
| 4378 | /* propagate ecc info to mtd_info */ | ||
| 4379 | mtd->ecclayout = ecc->layout; | ||
| 4380 | mtd->ecc_strength = ecc->strength; | ||
| 4381 | mtd->ecc_step_size = ecc->size; | ||
| 4382 | /* | 4550 | /* |
| 4383 | * Initialize bitflip_threshold to its default prior scan_bbt() call. | 4551 | * Initialize bitflip_threshold to its default prior scan_bbt() call. |
| 4384 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be | 4552 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be |
| @@ -4393,6 +4561,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4393 | 4561 | ||
| 4394 | /* Build bad block table */ | 4562 | /* Build bad block table */ |
| 4395 | return chip->scan_bbt(mtd); | 4563 | return chip->scan_bbt(mtd); |
| 4564 | err_free: | ||
| 4565 | if (!(chip->options & NAND_OWN_BUFFERS)) | ||
| 4566 | kfree(chip->buffers); | ||
| 4567 | return ret; | ||
| 4396 | } | 4568 | } |
| 4397 | EXPORT_SYMBOL(nand_scan_tail); | 4569 | EXPORT_SYMBOL(nand_scan_tail); |
| 4398 | 4570 | ||
| @@ -4436,7 +4608,8 @@ void nand_release(struct mtd_info *mtd) | |||
| 4436 | { | 4608 | { |
| 4437 | struct nand_chip *chip = mtd_to_nand(mtd); | 4609 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4438 | 4610 | ||
| 4439 | if (chip->ecc.mode == NAND_ECC_SOFT_BCH) | 4611 | if (chip->ecc.mode == NAND_ECC_SOFT && |
| 4612 | chip->ecc.algo == NAND_ECC_BCH) | ||
| 4440 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); | 4613 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); |
| 4441 | 4614 | ||
| 4442 | mtd_device_unregister(mtd); | 4615 | mtd_device_unregister(mtd); |
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index b585bae37929..44763f87eae4 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c | |||
| @@ -32,13 +32,11 @@ | |||
| 32 | /** | 32 | /** |
| 33 | * struct nand_bch_control - private NAND BCH control structure | 33 | * struct nand_bch_control - private NAND BCH control structure |
| 34 | * @bch: BCH control structure | 34 | * @bch: BCH control structure |
| 35 | * @ecclayout: private ecc layout for this BCH configuration | ||
| 36 | * @errloc: error location array | 35 | * @errloc: error location array |
| 37 | * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid | 36 | * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid |
| 38 | */ | 37 | */ |
| 39 | struct nand_bch_control { | 38 | struct nand_bch_control { |
| 40 | struct bch_control *bch; | 39 | struct bch_control *bch; |
| 41 | struct nand_ecclayout ecclayout; | ||
| 42 | unsigned int *errloc; | 40 | unsigned int *errloc; |
| 43 | unsigned char *eccmask; | 41 | unsigned char *eccmask; |
| 44 | }; | 42 | }; |
| @@ -124,7 +122,6 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) | |||
| 124 | { | 122 | { |
| 125 | struct nand_chip *nand = mtd_to_nand(mtd); | 123 | struct nand_chip *nand = mtd_to_nand(mtd); |
| 126 | unsigned int m, t, eccsteps, i; | 124 | unsigned int m, t, eccsteps, i; |
| 127 | struct nand_ecclayout *layout = nand->ecc.layout; | ||
| 128 | struct nand_bch_control *nbc = NULL; | 125 | struct nand_bch_control *nbc = NULL; |
| 129 | unsigned char *erased_page; | 126 | unsigned char *erased_page; |
| 130 | unsigned int eccsize = nand->ecc.size; | 127 | unsigned int eccsize = nand->ecc.size; |
| @@ -161,34 +158,10 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) | |||
| 161 | 158 | ||
| 162 | eccsteps = mtd->writesize/eccsize; | 159 | eccsteps = mtd->writesize/eccsize; |
| 163 | 160 | ||
| 164 | /* if no ecc placement scheme was provided, build one */ | 161 | /* Check that we have an oob layout description. */ |
| 165 | if (!layout) { | 162 | if (!mtd->ooblayout) { |
| 166 | 163 | pr_warn("missing oob scheme"); | |
| 167 | /* handle large page devices only */ | 164 | goto fail; |
| 168 | if (mtd->oobsize < 64) { | ||
| 169 | printk(KERN_WARNING "must provide an oob scheme for " | ||
| 170 | "oobsize %d\n", mtd->oobsize); | ||
| 171 | goto fail; | ||
| 172 | } | ||
| 173 | |||
| 174 | layout = &nbc->ecclayout; | ||
| 175 | layout->eccbytes = eccsteps*eccbytes; | ||
| 176 | |||
| 177 | /* reserve 2 bytes for bad block marker */ | ||
| 178 | if (layout->eccbytes+2 > mtd->oobsize) { | ||
| 179 | printk(KERN_WARNING "no suitable oob scheme available " | ||
| 180 | "for oobsize %d eccbytes %u\n", mtd->oobsize, | ||
| 181 | eccbytes); | ||
| 182 | goto fail; | ||
| 183 | } | ||
| 184 | /* put ecc bytes at oob tail */ | ||
| 185 | for (i = 0; i < layout->eccbytes; i++) | ||
| 186 | layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; | ||
| 187 | |||
| 188 | layout->oobfree[0].offset = 2; | ||
| 189 | layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; | ||
| 190 | |||
| 191 | nand->ecc.layout = layout; | ||
| 192 | } | 165 | } |
| 193 | 166 | ||
| 194 | /* sanity checks */ | 167 | /* sanity checks */ |
| @@ -196,7 +169,18 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) | |||
| 196 | printk(KERN_WARNING "eccsize %u is too large\n", eccsize); | 169 | printk(KERN_WARNING "eccsize %u is too large\n", eccsize); |
| 197 | goto fail; | 170 | goto fail; |
| 198 | } | 171 | } |
| 199 | if (layout->eccbytes != (eccsteps*eccbytes)) { | 172 | |
| 173 | /* | ||
| 174 | * ecc->steps and ecc->total might be used by mtd->ooblayout->ecc(), | ||
| 175 | * which is called by mtd_ooblayout_count_eccbytes(). | ||
| 176 | * Make sure they are properly initialized before calling | ||
| 177 | * mtd_ooblayout_count_eccbytes(). | ||
| 178 | * FIXME: we should probably rework the sequencing in nand_scan_tail() | ||
| 179 | * to avoid setting those fields twice. | ||
| 180 | */ | ||
| 181 | nand->ecc.steps = eccsteps; | ||
| 182 | nand->ecc.total = eccsteps * eccbytes; | ||
| 183 | if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) { | ||
| 200 | printk(KERN_WARNING "invalid ecc layout\n"); | 184 | printk(KERN_WARNING "invalid ecc layout\n"); |
| 201 | goto fail; | 185 | goto fail; |
| 202 | } | 186 | } |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a58169a28741..1eb934414eb5 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
| @@ -569,7 +569,7 @@ static void nandsim_debugfs_remove(struct nandsim *ns) | |||
| 569 | * | 569 | * |
| 570 | * RETURNS: 0 if success, -ENOMEM if memory alloc fails. | 570 | * RETURNS: 0 if success, -ENOMEM if memory alloc fails. |
| 571 | */ | 571 | */ |
| 572 | static int alloc_device(struct nandsim *ns) | 572 | static int __init alloc_device(struct nandsim *ns) |
| 573 | { | 573 | { |
| 574 | struct file *cfile; | 574 | struct file *cfile; |
| 575 | int i, err; | 575 | int i, err; |
| @@ -654,7 +654,7 @@ static void free_device(struct nandsim *ns) | |||
| 654 | } | 654 | } |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | static char *get_partition_name(int i) | 657 | static char __init *get_partition_name(int i) |
| 658 | { | 658 | { |
| 659 | return kasprintf(GFP_KERNEL, "NAND simulator partition %d", i); | 659 | return kasprintf(GFP_KERNEL, "NAND simulator partition %d", i); |
| 660 | } | 660 | } |
| @@ -664,7 +664,7 @@ static char *get_partition_name(int i) | |||
| 664 | * | 664 | * |
| 665 | * RETURNS: 0 if success, -ERRNO if failure. | 665 | * RETURNS: 0 if success, -ERRNO if failure. |
| 666 | */ | 666 | */ |
| 667 | static int init_nandsim(struct mtd_info *mtd) | 667 | static int __init init_nandsim(struct mtd_info *mtd) |
| 668 | { | 668 | { |
| 669 | struct nand_chip *chip = mtd_to_nand(mtd); | 669 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 670 | struct nandsim *ns = nand_get_controller_data(chip); | 670 | struct nandsim *ns = nand_get_controller_data(chip); |
| @@ -2261,6 +2261,7 @@ static int __init ns_init_module(void) | |||
| 2261 | chip->read_buf = ns_nand_read_buf; | 2261 | chip->read_buf = ns_nand_read_buf; |
| 2262 | chip->read_word = ns_nand_read_word; | 2262 | chip->read_word = ns_nand_read_word; |
| 2263 | chip->ecc.mode = NAND_ECC_SOFT; | 2263 | chip->ecc.mode = NAND_ECC_SOFT; |
| 2264 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 2264 | /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ | 2265 | /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ |
| 2265 | /* and 'badblocks' parameters to work */ | 2266 | /* and 'badblocks' parameters to work */ |
| 2266 | chip->options |= NAND_SKIP_BBTSCAN; | 2267 | chip->options |= NAND_SKIP_BBTSCAN; |
| @@ -2338,7 +2339,8 @@ static int __init ns_init_module(void) | |||
| 2338 | retval = -EINVAL; | 2339 | retval = -EINVAL; |
| 2339 | goto error; | 2340 | goto error; |
| 2340 | } | 2341 | } |
| 2341 | chip->ecc.mode = NAND_ECC_SOFT_BCH; | 2342 | chip->ecc.mode = NAND_ECC_SOFT; |
| 2343 | chip->ecc.algo = NAND_ECC_BCH; | ||
| 2342 | chip->ecc.size = 512; | 2344 | chip->ecc.size = 512; |
| 2343 | chip->ecc.strength = bch; | 2345 | chip->ecc.strength = bch; |
| 2344 | chip->ecc.bytes = eccbytes; | 2346 | chip->ecc.bytes = eccbytes; |
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index dbc5b571c2bb..8f64011d32ef 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
| @@ -261,6 +261,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) | |||
| 261 | chip->chip_delay = 50; | 261 | chip->chip_delay = 50; |
| 262 | chip->options = 0; | 262 | chip->options = 0; |
| 263 | chip->ecc.mode = NAND_ECC_SOFT; | 263 | chip->ecc.mode = NAND_ECC_SOFT; |
| 264 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 264 | 265 | ||
| 265 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 266 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 266 | nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res); | 267 | nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res); |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0749ca1a1456..08e158895635 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/dmaengine.h> | 12 | #include <linux/dmaengine.h> |
| 13 | #include <linux/dma-mapping.h> | 13 | #include <linux/dma-mapping.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/gpio/consumer.h> | ||
| 15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 17 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/mtd/nand_bch.h> | 29 | #include <linux/mtd/nand_bch.h> |
| 29 | #include <linux/platform_data/elm.h> | 30 | #include <linux/platform_data/elm.h> |
| 30 | 31 | ||
| 32 | #include <linux/omap-gpmc.h> | ||
| 31 | #include <linux/platform_data/mtd-nand-omap2.h> | 33 | #include <linux/platform_data/mtd-nand-omap2.h> |
| 32 | 34 | ||
| 33 | #define DRIVER_NAME "omap2-nand" | 35 | #define DRIVER_NAME "omap2-nand" |
| @@ -151,13 +153,17 @@ static struct nand_hw_control omap_gpmc_controller = { | |||
| 151 | }; | 153 | }; |
| 152 | 154 | ||
| 153 | struct omap_nand_info { | 155 | struct omap_nand_info { |
| 154 | struct omap_nand_platform_data *pdata; | ||
| 155 | struct nand_chip nand; | 156 | struct nand_chip nand; |
| 156 | struct platform_device *pdev; | 157 | struct platform_device *pdev; |
| 157 | 158 | ||
| 158 | int gpmc_cs; | 159 | int gpmc_cs; |
| 159 | unsigned long phys_base; | 160 | bool dev_ready; |
| 161 | enum nand_io xfer_type; | ||
| 162 | int devsize; | ||
| 160 | enum omap_ecc ecc_opt; | 163 | enum omap_ecc ecc_opt; |
| 164 | struct device_node *elm_of_node; | ||
| 165 | |||
| 166 | unsigned long phys_base; | ||
| 161 | struct completion comp; | 167 | struct completion comp; |
| 162 | struct dma_chan *dma; | 168 | struct dma_chan *dma; |
| 163 | int gpmc_irq_fifo; | 169 | int gpmc_irq_fifo; |
| @@ -168,12 +174,14 @@ struct omap_nand_info { | |||
| 168 | } iomode; | 174 | } iomode; |
| 169 | u_char *buf; | 175 | u_char *buf; |
| 170 | int buf_len; | 176 | int buf_len; |
| 177 | /* Interface to GPMC */ | ||
| 171 | struct gpmc_nand_regs reg; | 178 | struct gpmc_nand_regs reg; |
| 172 | /* generated at runtime depending on ECC algorithm and layout selected */ | 179 | struct gpmc_nand_ops *ops; |
| 173 | struct nand_ecclayout oobinfo; | 180 | bool flash_bbt; |
| 174 | /* fields specific for BCHx_HW ECC scheme */ | 181 | /* fields specific for BCHx_HW ECC scheme */ |
| 175 | struct device *elm_dev; | 182 | struct device *elm_dev; |
| 176 | struct device_node *of_node; | 183 | /* NAND ready gpio */ |
| 184 | struct gpio_desc *ready_gpiod; | ||
| 177 | }; | 185 | }; |
| 178 | 186 | ||
| 179 | static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) | 187 | static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) |
| @@ -208,7 +216,7 @@ static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode, | |||
| 208 | */ | 216 | */ |
| 209 | val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) | | 217 | val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) | |
| 210 | PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH | | 218 | PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH | |
| 211 | (dma_mode << DMA_MPU_MODE_SHIFT) | (0x1 & is_write)); | 219 | (dma_mode << DMA_MPU_MODE_SHIFT) | (is_write & 0x1)); |
| 212 | writel(val, info->reg.gpmc_prefetch_config1); | 220 | writel(val, info->reg.gpmc_prefetch_config1); |
| 213 | 221 | ||
| 214 | /* Start the prefetch engine */ | 222 | /* Start the prefetch engine */ |
| @@ -288,14 +296,13 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) | |||
| 288 | { | 296 | { |
| 289 | struct omap_nand_info *info = mtd_to_omap(mtd); | 297 | struct omap_nand_info *info = mtd_to_omap(mtd); |
| 290 | u_char *p = (u_char *)buf; | 298 | u_char *p = (u_char *)buf; |
| 291 | u32 status = 0; | 299 | bool status; |
| 292 | 300 | ||
| 293 | while (len--) { | 301 | while (len--) { |
| 294 | iowrite8(*p++, info->nand.IO_ADDR_W); | 302 | iowrite8(*p++, info->nand.IO_ADDR_W); |
| 295 | /* wait until buffer is available for write */ | 303 | /* wait until buffer is available for write */ |
| 296 | do { | 304 | do { |
| 297 | status = readl(info->reg.gpmc_status) & | 305 | status = info->ops->nand_writebuffer_empty(); |
| 298 | STATUS_BUFF_EMPTY; | ||
| 299 | } while (!status); | 306 | } while (!status); |
| 300 | } | 307 | } |
| 301 | } | 308 | } |
| @@ -323,7 +330,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) | |||
| 323 | { | 330 | { |
| 324 | struct omap_nand_info *info = mtd_to_omap(mtd); | 331 | struct omap_nand_info *info = mtd_to_omap(mtd); |
| 325 | u16 *p = (u16 *) buf; | 332 | u16 *p = (u16 *) buf; |
| 326 | u32 status = 0; | 333 | bool status; |
| 327 | /* FIXME try bursts of writesw() or DMA ... */ | 334 | /* FIXME try bursts of writesw() or DMA ... */ |
| 328 | len >>= 1; | 335 | len >>= 1; |
| 329 | 336 | ||
| @@ -331,8 +338,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) | |||
| 331 | iowrite16(*p++, info->nand.IO_ADDR_W); | 338 | iowrite16(*p++, info->nand.IO_ADDR_W); |
| 332 | /* wait until buffer is available for write */ | 339 | /* wait until buffer is available for write */ |
| 333 | do { | 340 | do { |
| 334 | status = readl(info->reg.gpmc_status) & | 341 | status = info->ops->nand_writebuffer_empty(); |
| 335 | STATUS_BUFF_EMPTY; | ||
| 336 | } while (!status); | 342 | } while (!status); |
| 337 | } | 343 | } |
| 338 | } | 344 | } |
| @@ -467,17 +473,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, | |||
| 467 | int ret; | 473 | int ret; |
| 468 | u32 val; | 474 | u32 val; |
| 469 | 475 | ||
| 470 | if (addr >= high_memory) { | 476 | if (!virt_addr_valid(addr)) |
| 471 | struct page *p1; | 477 | goto out_copy; |
| 472 | |||
| 473 | if (((size_t)addr & PAGE_MASK) != | ||
| 474 | ((size_t)(addr + len - 1) & PAGE_MASK)) | ||
| 475 | goto out_copy; | ||
| 476 | p1 = vmalloc_to_page(addr); | ||
| 477 | if (!p1) | ||
| 478 | goto out_copy; | ||
| 479 | addr = page_address(p1) + ((size_t)addr & ~PAGE_MASK); | ||
| 480 | } | ||
| 481 | 478 | ||
| 482 | sg_init_one(&sg, addr, len); | 479 | sg_init_one(&sg, addr, len); |
| 483 | n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); | 480 | n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); |
| @@ -497,6 +494,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, | |||
| 497 | tx->callback_param = &info->comp; | 494 | tx->callback_param = &info->comp; |
| 498 | dmaengine_submit(tx); | 495 | dmaengine_submit(tx); |
| 499 | 496 | ||
| 497 | init_completion(&info->comp); | ||
| 498 | |||
| 499 | /* setup and start DMA using dma_addr */ | ||
| 500 | dma_async_issue_pending(info->dma); | ||
| 501 | |||
| 500 | /* configure and start prefetch transfer */ | 502 | /* configure and start prefetch transfer */ |
| 501 | ret = omap_prefetch_enable(info->gpmc_cs, | 503 | ret = omap_prefetch_enable(info->gpmc_cs, |
| 502 | PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info); | 504 | PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info); |
| @@ -504,10 +506,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, | |||
| 504 | /* PFPW engine is busy, use cpu copy method */ | 506 | /* PFPW engine is busy, use cpu copy method */ |
| 505 | goto out_copy_unmap; | 507 | goto out_copy_unmap; |
| 506 | 508 | ||
| 507 | init_completion(&info->comp); | ||
| 508 | dma_async_issue_pending(info->dma); | ||
| 509 | |||
| 510 | /* setup and start DMA using dma_addr */ | ||
| 511 | wait_for_completion(&info->comp); | 509 | wait_for_completion(&info->comp); |
| 512 | tim = 0; | 510 | tim = 0; |
| 513 | limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); | 511 | limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); |
| @@ -1017,21 +1015,16 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
| 1017 | } | 1015 | } |
| 1018 | 1016 | ||
| 1019 | /** | 1017 | /** |
| 1020 | * omap_dev_ready - calls the platform specific dev_ready function | 1018 | * omap_dev_ready - checks the NAND Ready GPIO line |
| 1021 | * @mtd: MTD device structure | 1019 | * @mtd: MTD device structure |
| 1020 | * | ||
| 1021 | * Returns true if ready and false if busy. | ||
| 1022 | */ | 1022 | */ |
| 1023 | static int omap_dev_ready(struct mtd_info *mtd) | 1023 | static int omap_dev_ready(struct mtd_info *mtd) |
| 1024 | { | 1024 | { |
| 1025 | unsigned int val = 0; | ||
| 1026 | struct omap_nand_info *info = mtd_to_omap(mtd); | 1025 | struct omap_nand_info *info = mtd_to_omap(mtd); |
| 1027 | 1026 | ||
| 1028 | val = readl(info->reg.gpmc_status); | 1027 | return gpiod_get_value(info->ready_gpiod); |
| 1029 | |||
| 1030 | if ((val & 0x100) == 0x100) { | ||
| 1031 | return 1; | ||
| 1032 | } else { | ||
| 1033 | return 0; | ||
| 1034 | } | ||
| 1035 | } | 1028 | } |
| 1036 | 1029 | ||
| 1037 | /** | 1030 | /** |
| @@ -1495,9 +1488,8 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
| 1495 | static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, | 1488 | static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, |
| 1496 | const uint8_t *buf, int oob_required, int page) | 1489 | const uint8_t *buf, int oob_required, int page) |
| 1497 | { | 1490 | { |
| 1498 | int i; | 1491 | int ret; |
| 1499 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1492 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 1500 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 1501 | 1493 | ||
| 1502 | /* Enable GPMC ecc engine */ | 1494 | /* Enable GPMC ecc engine */ |
| 1503 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | 1495 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
| @@ -1508,8 +1500,10 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1508 | /* Update ecc vector from GPMC result registers */ | 1500 | /* Update ecc vector from GPMC result registers */ |
| 1509 | chip->ecc.calculate(mtd, buf, &ecc_calc[0]); | 1501 | chip->ecc.calculate(mtd, buf, &ecc_calc[0]); |
| 1510 | 1502 | ||
| 1511 | for (i = 0; i < chip->ecc.total; i++) | 1503 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
| 1512 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 1504 | chip->ecc.total); |
| 1505 | if (ret) | ||
| 1506 | return ret; | ||
| 1513 | 1507 | ||
| 1514 | /* Write ecc vector to OOB area */ | 1508 | /* Write ecc vector to OOB area */ |
| 1515 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 1509 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
| @@ -1536,10 +1530,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1536 | { | 1530 | { |
| 1537 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1531 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
| 1538 | uint8_t *ecc_code = chip->buffers->ecccode; | 1532 | uint8_t *ecc_code = chip->buffers->ecccode; |
| 1539 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1533 | int stat, ret; |
| 1540 | uint8_t *oob = &chip->oob_poi[eccpos[0]]; | ||
| 1541 | uint32_t oob_pos = mtd->writesize + chip->ecc.layout->eccpos[0]; | ||
| 1542 | int stat; | ||
| 1543 | unsigned int max_bitflips = 0; | 1534 | unsigned int max_bitflips = 0; |
| 1544 | 1535 | ||
| 1545 | /* Enable GPMC ecc engine */ | 1536 | /* Enable GPMC ecc engine */ |
| @@ -1549,13 +1540,18 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1549 | chip->read_buf(mtd, buf, mtd->writesize); | 1540 | chip->read_buf(mtd, buf, mtd->writesize); |
| 1550 | 1541 | ||
| 1551 | /* Read oob bytes */ | 1542 | /* Read oob bytes */ |
| 1552 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1); | 1543 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
| 1553 | chip->read_buf(mtd, oob, chip->ecc.total); | 1544 | mtd->writesize + BADBLOCK_MARKER_LENGTH, -1); |
| 1545 | chip->read_buf(mtd, chip->oob_poi + BADBLOCK_MARKER_LENGTH, | ||
| 1546 | chip->ecc.total); | ||
| 1554 | 1547 | ||
| 1555 | /* Calculate ecc bytes */ | 1548 | /* Calculate ecc bytes */ |
| 1556 | chip->ecc.calculate(mtd, buf, ecc_calc); | 1549 | chip->ecc.calculate(mtd, buf, ecc_calc); |
| 1557 | 1550 | ||
| 1558 | memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total); | 1551 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
| 1552 | chip->ecc.total); | ||
| 1553 | if (ret) | ||
| 1554 | return ret; | ||
| 1559 | 1555 | ||
| 1560 | stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc); | 1556 | stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc); |
| 1561 | 1557 | ||
| @@ -1630,7 +1626,7 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info, | |||
| 1630 | "CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); | 1626 | "CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); |
| 1631 | return false; | 1627 | return false; |
| 1632 | } | 1628 | } |
| 1633 | if (ecc_needs_elm && !is_elm_present(info, pdata->elm_of_node)) { | 1629 | if (ecc_needs_elm && !is_elm_present(info, info->elm_of_node)) { |
| 1634 | dev_err(&info->pdev->dev, "ELM not available\n"); | 1630 | dev_err(&info->pdev->dev, "ELM not available\n"); |
| 1635 | return false; | 1631 | return false; |
| 1636 | } | 1632 | } |
| @@ -1638,43 +1634,227 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info, | |||
| 1638 | return true; | 1634 | return true; |
| 1639 | } | 1635 | } |
| 1640 | 1636 | ||
| 1637 | static const char * const nand_xfer_types[] = { | ||
| 1638 | [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", | ||
| 1639 | [NAND_OMAP_POLLED] = "polled", | ||
| 1640 | [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", | ||
| 1641 | [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", | ||
| 1642 | }; | ||
| 1643 | |||
| 1644 | static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info) | ||
| 1645 | { | ||
| 1646 | struct device_node *child = dev->of_node; | ||
| 1647 | int i; | ||
| 1648 | const char *s; | ||
| 1649 | u32 cs; | ||
| 1650 | |||
| 1651 | if (of_property_read_u32(child, "reg", &cs) < 0) { | ||
| 1652 | dev_err(dev, "reg not found in DT\n"); | ||
| 1653 | return -EINVAL; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | info->gpmc_cs = cs; | ||
| 1657 | |||
| 1658 | /* detect availability of ELM module. Won't be present pre-OMAP4 */ | ||
| 1659 | info->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); | ||
| 1660 | if (!info->elm_of_node) | ||
| 1661 | dev_dbg(dev, "ti,elm-id not in DT\n"); | ||
| 1662 | |||
| 1663 | /* select ecc-scheme for NAND */ | ||
| 1664 | if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { | ||
| 1665 | dev_err(dev, "ti,nand-ecc-opt not found\n"); | ||
| 1666 | return -EINVAL; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | if (!strcmp(s, "sw")) { | ||
| 1670 | info->ecc_opt = OMAP_ECC_HAM1_CODE_SW; | ||
| 1671 | } else if (!strcmp(s, "ham1") || | ||
| 1672 | !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) { | ||
| 1673 | info->ecc_opt = OMAP_ECC_HAM1_CODE_HW; | ||
| 1674 | } else if (!strcmp(s, "bch4")) { | ||
| 1675 | if (info->elm_of_node) | ||
| 1676 | info->ecc_opt = OMAP_ECC_BCH4_CODE_HW; | ||
| 1677 | else | ||
| 1678 | info->ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; | ||
| 1679 | } else if (!strcmp(s, "bch8")) { | ||
| 1680 | if (info->elm_of_node) | ||
| 1681 | info->ecc_opt = OMAP_ECC_BCH8_CODE_HW; | ||
| 1682 | else | ||
| 1683 | info->ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; | ||
| 1684 | } else if (!strcmp(s, "bch16")) { | ||
| 1685 | info->ecc_opt = OMAP_ECC_BCH16_CODE_HW; | ||
| 1686 | } else { | ||
| 1687 | dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n"); | ||
| 1688 | return -EINVAL; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | /* select data transfer mode */ | ||
| 1692 | if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) { | ||
| 1693 | for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) { | ||
| 1694 | if (!strcasecmp(s, nand_xfer_types[i])) { | ||
| 1695 | info->xfer_type = i; | ||
| 1696 | return 0; | ||
| 1697 | } | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | dev_err(dev, "unrecognized value for ti,nand-xfer-type\n"); | ||
| 1701 | return -EINVAL; | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | return 0; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | static int omap_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 1708 | struct mtd_oob_region *oobregion) | ||
| 1709 | { | ||
| 1710 | struct omap_nand_info *info = mtd_to_omap(mtd); | ||
| 1711 | struct nand_chip *chip = &info->nand; | ||
| 1712 | int off = BADBLOCK_MARKER_LENGTH; | ||
| 1713 | |||
| 1714 | if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && | ||
| 1715 | !(chip->options & NAND_BUSWIDTH_16)) | ||
| 1716 | off = 1; | ||
| 1717 | |||
| 1718 | if (section) | ||
| 1719 | return -ERANGE; | ||
| 1720 | |||
| 1721 | oobregion->offset = off; | ||
| 1722 | oobregion->length = chip->ecc.total; | ||
| 1723 | |||
| 1724 | return 0; | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | static int omap_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 1728 | struct mtd_oob_region *oobregion) | ||
| 1729 | { | ||
| 1730 | struct omap_nand_info *info = mtd_to_omap(mtd); | ||
| 1731 | struct nand_chip *chip = &info->nand; | ||
| 1732 | int off = BADBLOCK_MARKER_LENGTH; | ||
| 1733 | |||
| 1734 | if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && | ||
| 1735 | !(chip->options & NAND_BUSWIDTH_16)) | ||
| 1736 | off = 1; | ||
| 1737 | |||
| 1738 | if (section) | ||
| 1739 | return -ERANGE; | ||
| 1740 | |||
| 1741 | off += chip->ecc.total; | ||
| 1742 | if (off >= mtd->oobsize) | ||
| 1743 | return -ERANGE; | ||
| 1744 | |||
| 1745 | oobregion->offset = off; | ||
| 1746 | oobregion->length = mtd->oobsize - off; | ||
| 1747 | |||
| 1748 | return 0; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | static const struct mtd_ooblayout_ops omap_ooblayout_ops = { | ||
| 1752 | .ecc = omap_ooblayout_ecc, | ||
| 1753 | .free = omap_ooblayout_free, | ||
| 1754 | }; | ||
| 1755 | |||
| 1756 | static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 1757 | struct mtd_oob_region *oobregion) | ||
| 1758 | { | ||
| 1759 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1760 | int off = BADBLOCK_MARKER_LENGTH; | ||
| 1761 | |||
| 1762 | if (section >= chip->ecc.steps) | ||
| 1763 | return -ERANGE; | ||
| 1764 | |||
| 1765 | /* | ||
| 1766 | * When SW correction is employed, one OMAP specific marker byte is | ||
| 1767 | * reserved after each ECC step. | ||
| 1768 | */ | ||
| 1769 | oobregion->offset = off + (section * (chip->ecc.bytes + 1)); | ||
| 1770 | oobregion->length = chip->ecc.bytes; | ||
| 1771 | |||
| 1772 | return 0; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 1776 | struct mtd_oob_region *oobregion) | ||
| 1777 | { | ||
| 1778 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1779 | int off = BADBLOCK_MARKER_LENGTH; | ||
| 1780 | |||
| 1781 | if (section) | ||
| 1782 | return -ERANGE; | ||
| 1783 | |||
| 1784 | /* | ||
| 1785 | * When SW correction is employed, one OMAP specific marker byte is | ||
| 1786 | * reserved after each ECC step. | ||
| 1787 | */ | ||
| 1788 | off += ((chip->ecc.bytes + 1) * chip->ecc.steps); | ||
| 1789 | if (off >= mtd->oobsize) | ||
| 1790 | return -ERANGE; | ||
| 1791 | |||
| 1792 | oobregion->offset = off; | ||
| 1793 | oobregion->length = mtd->oobsize - off; | ||
| 1794 | |||
| 1795 | return 0; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | static const struct mtd_ooblayout_ops omap_sw_ooblayout_ops = { | ||
| 1799 | .ecc = omap_sw_ooblayout_ecc, | ||
| 1800 | .free = omap_sw_ooblayout_free, | ||
| 1801 | }; | ||
| 1802 | |||
| 1641 | static int omap_nand_probe(struct platform_device *pdev) | 1803 | static int omap_nand_probe(struct platform_device *pdev) |
| 1642 | { | 1804 | { |
| 1643 | struct omap_nand_info *info; | 1805 | struct omap_nand_info *info; |
| 1644 | struct omap_nand_platform_data *pdata; | 1806 | struct omap_nand_platform_data *pdata = NULL; |
| 1645 | struct mtd_info *mtd; | 1807 | struct mtd_info *mtd; |
| 1646 | struct nand_chip *nand_chip; | 1808 | struct nand_chip *nand_chip; |
| 1647 | struct nand_ecclayout *ecclayout; | ||
| 1648 | int err; | 1809 | int err; |
| 1649 | int i; | ||
| 1650 | dma_cap_mask_t mask; | 1810 | dma_cap_mask_t mask; |
| 1651 | unsigned sig; | 1811 | unsigned sig; |
| 1652 | unsigned oob_index; | ||
| 1653 | struct resource *res; | 1812 | struct resource *res; |
| 1654 | 1813 | struct device *dev = &pdev->dev; | |
| 1655 | pdata = dev_get_platdata(&pdev->dev); | 1814 | int min_oobbytes = BADBLOCK_MARKER_LENGTH; |
| 1656 | if (pdata == NULL) { | 1815 | int oobbytes_per_step; |
| 1657 | dev_err(&pdev->dev, "platform data missing\n"); | ||
| 1658 | return -ENODEV; | ||
| 1659 | } | ||
| 1660 | 1816 | ||
| 1661 | info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), | 1817 | info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), |
| 1662 | GFP_KERNEL); | 1818 | GFP_KERNEL); |
| 1663 | if (!info) | 1819 | if (!info) |
| 1664 | return -ENOMEM; | 1820 | return -ENOMEM; |
| 1665 | 1821 | ||
| 1822 | info->pdev = pdev; | ||
| 1823 | |||
| 1824 | if (dev->of_node) { | ||
| 1825 | if (omap_get_dt_info(dev, info)) | ||
| 1826 | return -EINVAL; | ||
| 1827 | } else { | ||
| 1828 | pdata = dev_get_platdata(&pdev->dev); | ||
| 1829 | if (!pdata) { | ||
| 1830 | dev_err(&pdev->dev, "platform data missing\n"); | ||
| 1831 | return -EINVAL; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | info->gpmc_cs = pdata->cs; | ||
| 1835 | info->reg = pdata->reg; | ||
| 1836 | info->ecc_opt = pdata->ecc_opt; | ||
| 1837 | if (pdata->dev_ready) | ||
| 1838 | dev_info(&pdev->dev, "pdata->dev_ready is deprecated\n"); | ||
| 1839 | |||
| 1840 | info->xfer_type = pdata->xfer_type; | ||
| 1841 | info->devsize = pdata->devsize; | ||
| 1842 | info->elm_of_node = pdata->elm_of_node; | ||
| 1843 | info->flash_bbt = pdata->flash_bbt; | ||
| 1844 | } | ||
| 1845 | |||
| 1666 | platform_set_drvdata(pdev, info); | 1846 | platform_set_drvdata(pdev, info); |
| 1847 | info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); | ||
| 1848 | if (!info->ops) { | ||
| 1849 | dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); | ||
| 1850 | return -ENODEV; | ||
| 1851 | } | ||
| 1667 | 1852 | ||
| 1668 | info->pdev = pdev; | ||
| 1669 | info->gpmc_cs = pdata->cs; | ||
| 1670 | info->reg = pdata->reg; | ||
| 1671 | info->of_node = pdata->of_node; | ||
| 1672 | info->ecc_opt = pdata->ecc_opt; | ||
| 1673 | nand_chip = &info->nand; | 1853 | nand_chip = &info->nand; |
| 1674 | mtd = nand_to_mtd(nand_chip); | 1854 | mtd = nand_to_mtd(nand_chip); |
| 1675 | mtd->dev.parent = &pdev->dev; | 1855 | mtd->dev.parent = &pdev->dev; |
| 1676 | nand_chip->ecc.priv = NULL; | 1856 | nand_chip->ecc.priv = NULL; |
| 1677 | nand_set_flash_node(nand_chip, pdata->of_node); | 1857 | nand_set_flash_node(nand_chip, dev->of_node); |
| 1678 | 1858 | ||
| 1679 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1859 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1680 | nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); | 1860 | nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); |
| @@ -1688,6 +1868,13 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1688 | nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; | 1868 | nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; |
| 1689 | nand_chip->cmd_ctrl = omap_hwcontrol; | 1869 | nand_chip->cmd_ctrl = omap_hwcontrol; |
| 1690 | 1870 | ||
| 1871 | info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", | ||
| 1872 | GPIOD_IN); | ||
| 1873 | if (IS_ERR(info->ready_gpiod)) { | ||
| 1874 | dev_err(dev, "failed to get ready gpio\n"); | ||
| 1875 | return PTR_ERR(info->ready_gpiod); | ||
| 1876 | } | ||
| 1877 | |||
| 1691 | /* | 1878 | /* |
| 1692 | * If RDY/BSY line is connected to OMAP then use the omap ready | 1879 | * If RDY/BSY line is connected to OMAP then use the omap ready |
| 1693 | * function and the generic nand_wait function which reads the status | 1880 | * function and the generic nand_wait function which reads the status |
| @@ -1695,7 +1882,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1695 | * chip delay which is slightly more than tR (AC Timing) of the NAND | 1882 | * chip delay which is slightly more than tR (AC Timing) of the NAND |
| 1696 | * device and read status register until you get a failure or success | 1883 | * device and read status register until you get a failure or success |
| 1697 | */ | 1884 | */ |
| 1698 | if (pdata->dev_ready) { | 1885 | if (info->ready_gpiod) { |
| 1699 | nand_chip->dev_ready = omap_dev_ready; | 1886 | nand_chip->dev_ready = omap_dev_ready; |
| 1700 | nand_chip->chip_delay = 0; | 1887 | nand_chip->chip_delay = 0; |
| 1701 | } else { | 1888 | } else { |
| @@ -1703,21 +1890,25 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1703 | nand_chip->chip_delay = 50; | 1890 | nand_chip->chip_delay = 50; |
| 1704 | } | 1891 | } |
| 1705 | 1892 | ||
| 1706 | if (pdata->flash_bbt) | 1893 | if (info->flash_bbt) |
| 1707 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | 1894 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
| 1708 | else | ||
| 1709 | nand_chip->options |= NAND_SKIP_BBTSCAN; | ||
| 1710 | 1895 | ||
| 1711 | /* scan NAND device connected to chip controller */ | 1896 | /* scan NAND device connected to chip controller */ |
| 1712 | nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16; | 1897 | nand_chip->options |= info->devsize & NAND_BUSWIDTH_16; |
| 1713 | if (nand_scan_ident(mtd, 1, NULL)) { | 1898 | if (nand_scan_ident(mtd, 1, NULL)) { |
| 1714 | dev_err(&info->pdev->dev, "scan failed, may be bus-width mismatch\n"); | 1899 | dev_err(&info->pdev->dev, |
| 1900 | "scan failed, may be bus-width mismatch\n"); | ||
| 1715 | err = -ENXIO; | 1901 | err = -ENXIO; |
| 1716 | goto return_error; | 1902 | goto return_error; |
| 1717 | } | 1903 | } |
| 1718 | 1904 | ||
| 1905 | if (nand_chip->bbt_options & NAND_BBT_USE_FLASH) | ||
| 1906 | nand_chip->bbt_options |= NAND_BBT_NO_OOB; | ||
| 1907 | else | ||
| 1908 | nand_chip->options |= NAND_SKIP_BBTSCAN; | ||
| 1909 | |||
| 1719 | /* re-populate low-level callbacks based on xfer modes */ | 1910 | /* re-populate low-level callbacks based on xfer modes */ |
| 1720 | switch (pdata->xfer_type) { | 1911 | switch (info->xfer_type) { |
| 1721 | case NAND_OMAP_PREFETCH_POLLED: | 1912 | case NAND_OMAP_PREFETCH_POLLED: |
| 1722 | nand_chip->read_buf = omap_read_buf_pref; | 1913 | nand_chip->read_buf = omap_read_buf_pref; |
| 1723 | nand_chip->write_buf = omap_write_buf_pref; | 1914 | nand_chip->write_buf = omap_write_buf_pref; |
| @@ -1797,7 +1988,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1797 | 1988 | ||
| 1798 | default: | 1989 | default: |
| 1799 | dev_err(&pdev->dev, | 1990 | dev_err(&pdev->dev, |
| 1800 | "xfer_type(%d) not supported!\n", pdata->xfer_type); | 1991 | "xfer_type(%d) not supported!\n", info->xfer_type); |
| 1801 | err = -EINVAL; | 1992 | err = -EINVAL; |
| 1802 | goto return_error; | 1993 | goto return_error; |
| 1803 | } | 1994 | } |
| @@ -1809,16 +2000,15 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1809 | 2000 | ||
| 1810 | /* | 2001 | /* |
| 1811 | * Bail out earlier to let NAND_ECC_SOFT code create its own | 2002 | * Bail out earlier to let NAND_ECC_SOFT code create its own |
| 1812 | * ecclayout instead of using ours. | 2003 | * ooblayout instead of using ours. |
| 1813 | */ | 2004 | */ |
| 1814 | if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { | 2005 | if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { |
| 1815 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 2006 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
| 2007 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1816 | goto scan_tail; | 2008 | goto scan_tail; |
| 1817 | } | 2009 | } |
| 1818 | 2010 | ||
| 1819 | /* populate MTD interface based on ECC scheme */ | 2011 | /* populate MTD interface based on ECC scheme */ |
| 1820 | ecclayout = &info->oobinfo; | ||
| 1821 | nand_chip->ecc.layout = ecclayout; | ||
| 1822 | switch (info->ecc_opt) { | 2012 | switch (info->ecc_opt) { |
| 1823 | case OMAP_ECC_HAM1_CODE_HW: | 2013 | case OMAP_ECC_HAM1_CODE_HW: |
| 1824 | pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); | 2014 | pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); |
| @@ -1829,19 +2019,12 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1829 | nand_chip->ecc.calculate = omap_calculate_ecc; | 2019 | nand_chip->ecc.calculate = omap_calculate_ecc; |
| 1830 | nand_chip->ecc.hwctl = omap_enable_hwecc; | 2020 | nand_chip->ecc.hwctl = omap_enable_hwecc; |
| 1831 | nand_chip->ecc.correct = omap_correct_data; | 2021 | nand_chip->ecc.correct = omap_correct_data; |
| 1832 | /* define ECC layout */ | 2022 | mtd_set_ooblayout(mtd, &omap_ooblayout_ops); |
| 1833 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 2023 | oobbytes_per_step = nand_chip->ecc.bytes; |
| 1834 | (mtd->writesize / | 2024 | |
| 1835 | nand_chip->ecc.size); | 2025 | if (!(nand_chip->options & NAND_BUSWIDTH_16)) |
| 1836 | if (nand_chip->options & NAND_BUSWIDTH_16) | 2026 | min_oobbytes = 1; |
| 1837 | oob_index = BADBLOCK_MARKER_LENGTH; | 2027 | |
| 1838 | else | ||
| 1839 | oob_index = 1; | ||
| 1840 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1841 | ecclayout->eccpos[i] = oob_index; | ||
| 1842 | /* no reserved-marker in ecclayout for this ecc-scheme */ | ||
| 1843 | ecclayout->oobfree->offset = | ||
| 1844 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1845 | break; | 2028 | break; |
| 1846 | 2029 | ||
| 1847 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | 2030 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
| @@ -1853,19 +2036,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1853 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; | 2036 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
| 1854 | nand_chip->ecc.correct = nand_bch_correct_data; | 2037 | nand_chip->ecc.correct = nand_bch_correct_data; |
| 1855 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; | 2038 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
| 1856 | /* define ECC layout */ | 2039 | mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops); |
| 1857 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 2040 | /* Reserve one byte for the OMAP marker */ |
| 1858 | (mtd->writesize / | 2041 | oobbytes_per_step = nand_chip->ecc.bytes + 1; |
| 1859 | nand_chip->ecc.size); | ||
| 1860 | oob_index = BADBLOCK_MARKER_LENGTH; | ||
| 1861 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { | ||
| 1862 | ecclayout->eccpos[i] = oob_index; | ||
| 1863 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | ||
| 1864 | oob_index++; | ||
| 1865 | } | ||
| 1866 | /* include reserved-marker in ecclayout->oobfree calculation */ | ||
| 1867 | ecclayout->oobfree->offset = 1 + | ||
| 1868 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1869 | /* software bch library is used for locating errors */ | 2042 | /* software bch library is used for locating errors */ |
| 1870 | nand_chip->ecc.priv = nand_bch_init(mtd); | 2043 | nand_chip->ecc.priv = nand_bch_init(mtd); |
| 1871 | if (!nand_chip->ecc.priv) { | 2044 | if (!nand_chip->ecc.priv) { |
| @@ -1887,16 +2060,8 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1887 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; | 2060 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
| 1888 | nand_chip->ecc.read_page = omap_read_page_bch; | 2061 | nand_chip->ecc.read_page = omap_read_page_bch; |
| 1889 | nand_chip->ecc.write_page = omap_write_page_bch; | 2062 | nand_chip->ecc.write_page = omap_write_page_bch; |
| 1890 | /* define ECC layout */ | 2063 | mtd_set_ooblayout(mtd, &omap_ooblayout_ops); |
| 1891 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 2064 | oobbytes_per_step = nand_chip->ecc.bytes; |
| 1892 | (mtd->writesize / | ||
| 1893 | nand_chip->ecc.size); | ||
| 1894 | oob_index = BADBLOCK_MARKER_LENGTH; | ||
| 1895 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1896 | ecclayout->eccpos[i] = oob_index; | ||
| 1897 | /* reserved marker already included in ecclayout->eccbytes */ | ||
| 1898 | ecclayout->oobfree->offset = | ||
| 1899 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1900 | 2065 | ||
| 1901 | err = elm_config(info->elm_dev, BCH4_ECC, | 2066 | err = elm_config(info->elm_dev, BCH4_ECC, |
| 1902 | mtd->writesize / nand_chip->ecc.size, | 2067 | mtd->writesize / nand_chip->ecc.size, |
| @@ -1914,19 +2079,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1914 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; | 2079 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
| 1915 | nand_chip->ecc.correct = nand_bch_correct_data; | 2080 | nand_chip->ecc.correct = nand_bch_correct_data; |
| 1916 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; | 2081 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
| 1917 | /* define ECC layout */ | 2082 | mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops); |
| 1918 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 2083 | /* Reserve one byte for the OMAP marker */ |
| 1919 | (mtd->writesize / | 2084 | oobbytes_per_step = nand_chip->ecc.bytes + 1; |
| 1920 | nand_chip->ecc.size); | ||
| 1921 | oob_index = BADBLOCK_MARKER_LENGTH; | ||
| 1922 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { | ||
| 1923 | ecclayout->eccpos[i] = oob_index; | ||
| 1924 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | ||
| 1925 | oob_index++; | ||
| 1926 | } | ||
| 1927 | /* include reserved-marker in ecclayout->oobfree calculation */ | ||
| 1928 | ecclayout->oobfree->offset = 1 + | ||
| 1929 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1930 | /* software bch library is used for locating errors */ | 2085 | /* software bch library is used for locating errors */ |
| 1931 | nand_chip->ecc.priv = nand_bch_init(mtd); | 2086 | nand_chip->ecc.priv = nand_bch_init(mtd); |
| 1932 | if (!nand_chip->ecc.priv) { | 2087 | if (!nand_chip->ecc.priv) { |
| @@ -1948,6 +2103,8 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1948 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; | 2103 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
| 1949 | nand_chip->ecc.read_page = omap_read_page_bch; | 2104 | nand_chip->ecc.read_page = omap_read_page_bch; |
| 1950 | nand_chip->ecc.write_page = omap_write_page_bch; | 2105 | nand_chip->ecc.write_page = omap_write_page_bch; |
| 2106 | mtd_set_ooblayout(mtd, &omap_ooblayout_ops); | ||
| 2107 | oobbytes_per_step = nand_chip->ecc.bytes; | ||
| 1951 | 2108 | ||
| 1952 | err = elm_config(info->elm_dev, BCH8_ECC, | 2109 | err = elm_config(info->elm_dev, BCH8_ECC, |
| 1953 | mtd->writesize / nand_chip->ecc.size, | 2110 | mtd->writesize / nand_chip->ecc.size, |
| @@ -1955,16 +2112,6 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1955 | if (err < 0) | 2112 | if (err < 0) |
| 1956 | goto return_error; | 2113 | goto return_error; |
| 1957 | 2114 | ||
| 1958 | /* define ECC layout */ | ||
| 1959 | ecclayout->eccbytes = nand_chip->ecc.bytes * | ||
| 1960 | (mtd->writesize / | ||
| 1961 | nand_chip->ecc.size); | ||
| 1962 | oob_index = BADBLOCK_MARKER_LENGTH; | ||
| 1963 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1964 | ecclayout->eccpos[i] = oob_index; | ||
| 1965 | /* reserved marker already included in ecclayout->eccbytes */ | ||
| 1966 | ecclayout->oobfree->offset = | ||
| 1967 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1968 | break; | 2115 | break; |
| 1969 | 2116 | ||
| 1970 | case OMAP_ECC_BCH16_CODE_HW: | 2117 | case OMAP_ECC_BCH16_CODE_HW: |
| @@ -1978,6 +2125,8 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1978 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; | 2125 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
| 1979 | nand_chip->ecc.read_page = omap_read_page_bch; | 2126 | nand_chip->ecc.read_page = omap_read_page_bch; |
| 1980 | nand_chip->ecc.write_page = omap_write_page_bch; | 2127 | nand_chip->ecc.write_page = omap_write_page_bch; |
| 2128 | mtd_set_ooblayout(mtd, &omap_ooblayout_ops); | ||
| 2129 | oobbytes_per_step = nand_chip->ecc.bytes; | ||
| 1981 | 2130 | ||
| 1982 | err = elm_config(info->elm_dev, BCH16_ECC, | 2131 | err = elm_config(info->elm_dev, BCH16_ECC, |
| 1983 | mtd->writesize / nand_chip->ecc.size, | 2132 | mtd->writesize / nand_chip->ecc.size, |
| @@ -1985,16 +2134,6 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1985 | if (err < 0) | 2134 | if (err < 0) |
| 1986 | goto return_error; | 2135 | goto return_error; |
| 1987 | 2136 | ||
| 1988 | /* define ECC layout */ | ||
| 1989 | ecclayout->eccbytes = nand_chip->ecc.bytes * | ||
| 1990 | (mtd->writesize / | ||
| 1991 | nand_chip->ecc.size); | ||
| 1992 | oob_index = BADBLOCK_MARKER_LENGTH; | ||
| 1993 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1994 | ecclayout->eccpos[i] = oob_index; | ||
| 1995 | /* reserved marker already included in ecclayout->eccbytes */ | ||
| 1996 | ecclayout->oobfree->offset = | ||
| 1997 | ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; | ||
| 1998 | break; | 2137 | break; |
| 1999 | default: | 2138 | default: |
| 2000 | dev_err(&info->pdev->dev, "invalid or unsupported ECC scheme\n"); | 2139 | dev_err(&info->pdev->dev, "invalid or unsupported ECC scheme\n"); |
| @@ -2002,13 +2141,13 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 2002 | goto return_error; | 2141 | goto return_error; |
| 2003 | } | 2142 | } |
| 2004 | 2143 | ||
| 2005 | /* all OOB bytes from oobfree->offset till end off OOB are free */ | ||
| 2006 | ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; | ||
| 2007 | /* check if NAND device's OOB is enough to store ECC signatures */ | 2144 | /* check if NAND device's OOB is enough to store ECC signatures */ |
| 2008 | if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { | 2145 | min_oobbytes += (oobbytes_per_step * |
| 2146 | (mtd->writesize / nand_chip->ecc.size)); | ||
| 2147 | if (mtd->oobsize < min_oobbytes) { | ||
| 2009 | dev_err(&info->pdev->dev, | 2148 | dev_err(&info->pdev->dev, |
| 2010 | "not enough OOB bytes required = %d, available=%d\n", | 2149 | "not enough OOB bytes required = %d, available=%d\n", |
| 2011 | ecclayout->eccbytes, mtd->oobsize); | 2150 | min_oobbytes, mtd->oobsize); |
| 2012 | err = -EINVAL; | 2151 | err = -EINVAL; |
| 2013 | goto return_error; | 2152 | goto return_error; |
| 2014 | } | 2153 | } |
| @@ -2020,7 +2159,10 @@ scan_tail: | |||
| 2020 | goto return_error; | 2159 | goto return_error; |
| 2021 | } | 2160 | } |
| 2022 | 2161 | ||
| 2023 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); | 2162 | if (dev->of_node) |
| 2163 | mtd_device_register(mtd, NULL, 0); | ||
| 2164 | else | ||
| 2165 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); | ||
| 2024 | 2166 | ||
| 2025 | platform_set_drvdata(pdev, mtd); | 2167 | platform_set_drvdata(pdev, mtd); |
| 2026 | 2168 | ||
| @@ -2051,11 +2193,17 @@ static int omap_nand_remove(struct platform_device *pdev) | |||
| 2051 | return 0; | 2193 | return 0; |
| 2052 | } | 2194 | } |
| 2053 | 2195 | ||
| 2196 | static const struct of_device_id omap_nand_ids[] = { | ||
| 2197 | { .compatible = "ti,omap2-nand", }, | ||
| 2198 | {}, | ||
| 2199 | }; | ||
| 2200 | |||
| 2054 | static struct platform_driver omap_nand_driver = { | 2201 | static struct platform_driver omap_nand_driver = { |
| 2055 | .probe = omap_nand_probe, | 2202 | .probe = omap_nand_probe, |
| 2056 | .remove = omap_nand_remove, | 2203 | .remove = omap_nand_remove, |
| 2057 | .driver = { | 2204 | .driver = { |
| 2058 | .name = DRIVER_NAME, | 2205 | .name = DRIVER_NAME, |
| 2206 | .of_match_table = of_match_ptr(omap_nand_ids), | ||
| 2059 | }, | 2207 | }, |
| 2060 | }; | 2208 | }; |
| 2061 | 2209 | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index d4614bfbfed6..40a7c4a2cf0d 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
| @@ -130,6 +130,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
| 130 | nc->cmd_ctrl = orion_nand_cmd_ctrl; | 130 | nc->cmd_ctrl = orion_nand_cmd_ctrl; |
| 131 | nc->read_buf = orion_nand_read_buf; | 131 | nc->read_buf = orion_nand_read_buf; |
| 132 | nc->ecc.mode = NAND_ECC_SOFT; | 132 | nc->ecc.mode = NAND_ECC_SOFT; |
| 133 | nc->ecc.algo = NAND_ECC_HAMMING; | ||
| 133 | 134 | ||
| 134 | if (board->chip_delay) | 135 | if (board->chip_delay) |
| 135 | nc->chip_delay = board->chip_delay; | 136 | nc->chip_delay = board->chip_delay; |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 3ab53ca53cca..5de7591b0510 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
| @@ -92,8 +92,9 @@ int pasemi_device_ready(struct mtd_info *mtd) | |||
| 92 | 92 | ||
| 93 | static int pasemi_nand_probe(struct platform_device *ofdev) | 93 | static int pasemi_nand_probe(struct platform_device *ofdev) |
| 94 | { | 94 | { |
| 95 | struct device *dev = &ofdev->dev; | ||
| 95 | struct pci_dev *pdev; | 96 | struct pci_dev *pdev; |
| 96 | struct device_node *np = ofdev->dev.of_node; | 97 | struct device_node *np = dev->of_node; |
| 97 | struct resource res; | 98 | struct resource res; |
| 98 | struct nand_chip *chip; | 99 | struct nand_chip *chip; |
| 99 | int err = 0; | 100 | int err = 0; |
| @@ -107,13 +108,11 @@ static int pasemi_nand_probe(struct platform_device *ofdev) | |||
| 107 | if (pasemi_nand_mtd) | 108 | if (pasemi_nand_mtd) |
| 108 | return -ENODEV; | 109 | return -ENODEV; |
| 109 | 110 | ||
| 110 | pr_debug("pasemi_nand at %pR\n", &res); | 111 | dev_dbg(dev, "pasemi_nand at %pR\n", &res); |
| 111 | 112 | ||
| 112 | /* Allocate memory for MTD device structure and private data */ | 113 | /* Allocate memory for MTD device structure and private data */ |
| 113 | chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); | 114 | chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); |
| 114 | if (!chip) { | 115 | if (!chip) { |
| 115 | printk(KERN_WARNING | ||
| 116 | "Unable to allocate PASEMI NAND MTD device structure\n"); | ||
| 117 | err = -ENOMEM; | 116 | err = -ENOMEM; |
| 118 | goto out; | 117 | goto out; |
| 119 | } | 118 | } |
| @@ -121,7 +120,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) | |||
| 121 | pasemi_nand_mtd = nand_to_mtd(chip); | 120 | pasemi_nand_mtd = nand_to_mtd(chip); |
| 122 | 121 | ||
| 123 | /* Link the private data with the MTD structure */ | 122 | /* Link the private data with the MTD structure */ |
| 124 | pasemi_nand_mtd->dev.parent = &ofdev->dev; | 123 | pasemi_nand_mtd->dev.parent = dev; |
| 125 | 124 | ||
| 126 | chip->IO_ADDR_R = of_iomap(np, 0); | 125 | chip->IO_ADDR_R = of_iomap(np, 0); |
| 127 | chip->IO_ADDR_W = chip->IO_ADDR_R; | 126 | chip->IO_ADDR_W = chip->IO_ADDR_R; |
| @@ -151,6 +150,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) | |||
| 151 | chip->write_buf = pasemi_write_buf; | 150 | chip->write_buf = pasemi_write_buf; |
| 152 | chip->chip_delay = 0; | 151 | chip->chip_delay = 0; |
| 153 | chip->ecc.mode = NAND_ECC_SOFT; | 152 | chip->ecc.mode = NAND_ECC_SOFT; |
| 153 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 154 | 154 | ||
| 155 | /* Enable the following for a flash based bad block table */ | 155 | /* Enable the following for a flash based bad block table */ |
| 156 | chip->bbt_options = NAND_BBT_USE_FLASH; | 156 | chip->bbt_options = NAND_BBT_USE_FLASH; |
| @@ -162,13 +162,13 @@ static int pasemi_nand_probe(struct platform_device *ofdev) | |||
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { | 164 | if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { |
| 165 | printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n"); | 165 | dev_err(dev, "Unable to register MTD device\n"); |
| 166 | err = -ENODEV; | 166 | err = -ENODEV; |
| 167 | goto out_lpc; | 167 | goto out_lpc; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n", | 170 | dev_info(dev, "PA Semi NAND flash at %pR, control at I/O %x\n", &res, |
| 171 | res.start, lpcctl); | 171 | lpcctl); |
| 172 | 172 | ||
| 173 | return 0; | 173 | return 0; |
| 174 | 174 | ||
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index e4e50da30444..415a53a0deeb 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
| @@ -74,6 +74,7 @@ static int plat_nand_probe(struct platform_device *pdev) | |||
| 74 | 74 | ||
| 75 | data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; | 75 | data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; |
| 76 | data->chip.ecc.mode = NAND_ECC_SOFT; | 76 | data->chip.ecc.mode = NAND_ECC_SOFT; |
| 77 | data->chip.ecc.algo = NAND_ECC_HAMMING; | ||
| 77 | 78 | ||
| 78 | platform_set_drvdata(pdev, data); | 79 | platform_set_drvdata(pdev, data); |
| 79 | 80 | ||
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index d6508856da99..436dd6dc11f4 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
| 31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
| 32 | #include <linux/of_mtd.h> | ||
| 33 | #include <linux/platform_data/mtd-nand-pxa3xx.h> | 32 | #include <linux/platform_data/mtd-nand-pxa3xx.h> |
| 34 | 33 | ||
| 35 | #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) | 34 | #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) |
| @@ -324,6 +323,62 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { | |||
| 324 | { 0xba20, 16, 16, &timing[3] }, | 323 | { 0xba20, 16, 16, &timing[3] }, |
| 325 | }; | 324 | }; |
| 326 | 325 | ||
| 326 | static int pxa3xx_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 327 | struct mtd_oob_region *oobregion) | ||
| 328 | { | ||
| 329 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 330 | struct pxa3xx_nand_host *host = nand_get_controller_data(chip); | ||
| 331 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 332 | int nchunks = mtd->writesize / info->chunk_size; | ||
| 333 | |||
| 334 | if (section >= nchunks) | ||
| 335 | return -ERANGE; | ||
| 336 | |||
| 337 | oobregion->offset = ((info->ecc_size + info->spare_size) * section) + | ||
| 338 | info->spare_size; | ||
| 339 | oobregion->length = info->ecc_size; | ||
| 340 | |||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int pxa3xx_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 345 | struct mtd_oob_region *oobregion) | ||
| 346 | { | ||
| 347 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 348 | struct pxa3xx_nand_host *host = nand_get_controller_data(chip); | ||
| 349 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 350 | int nchunks = mtd->writesize / info->chunk_size; | ||
| 351 | |||
| 352 | if (section >= nchunks) | ||
| 353 | return -ERANGE; | ||
| 354 | |||
| 355 | if (!info->spare_size) | ||
| 356 | return 0; | ||
| 357 | |||
| 358 | oobregion->offset = section * (info->ecc_size + info->spare_size); | ||
| 359 | oobregion->length = info->spare_size; | ||
| 360 | if (!section) { | ||
| 361 | /* | ||
| 362 | * Bootrom looks in bytes 0 & 5 for bad blocks for the | ||
| 363 | * 4KB page / 4bit BCH combination. | ||
| 364 | */ | ||
| 365 | if (mtd->writesize == 4096 && info->chunk_size == 2048) { | ||
| 366 | oobregion->offset += 6; | ||
| 367 | oobregion->length -= 6; | ||
| 368 | } else { | ||
| 369 | oobregion->offset += 2; | ||
| 370 | oobregion->length -= 2; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | static const struct mtd_ooblayout_ops pxa3xx_ooblayout_ops = { | ||
| 378 | .ecc = pxa3xx_ooblayout_ecc, | ||
| 379 | .free = pxa3xx_ooblayout_free, | ||
| 380 | }; | ||
| 381 | |||
| 327 | static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' }; | 382 | static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' }; |
| 328 | static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' }; | 383 | static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' }; |
| 329 | 384 | ||
| @@ -347,41 +402,6 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
| 347 | .pattern = bbt_mirror_pattern | 402 | .pattern = bbt_mirror_pattern |
| 348 | }; | 403 | }; |
| 349 | 404 | ||
| 350 | static struct nand_ecclayout ecc_layout_2KB_bch4bit = { | ||
| 351 | .eccbytes = 32, | ||
| 352 | .eccpos = { | ||
| 353 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 354 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 355 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 356 | 56, 57, 58, 59, 60, 61, 62, 63}, | ||
| 357 | .oobfree = { {2, 30} } | ||
| 358 | }; | ||
| 359 | |||
| 360 | static struct nand_ecclayout ecc_layout_4KB_bch4bit = { | ||
| 361 | .eccbytes = 64, | ||
| 362 | .eccpos = { | ||
| 363 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 364 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 365 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 366 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 367 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
| 368 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
| 369 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
| 370 | 120, 121, 122, 123, 124, 125, 126, 127}, | ||
| 371 | /* Bootrom looks in bytes 0 & 5 for bad blocks */ | ||
| 372 | .oobfree = { {6, 26}, { 64, 32} } | ||
| 373 | }; | ||
| 374 | |||
| 375 | static struct nand_ecclayout ecc_layout_4KB_bch8bit = { | ||
| 376 | .eccbytes = 128, | ||
| 377 | .eccpos = { | ||
| 378 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 379 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 380 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 381 | 56, 57, 58, 59, 60, 61, 62, 63}, | ||
| 382 | .oobfree = { } | ||
| 383 | }; | ||
| 384 | |||
| 385 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 405 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
| 386 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 406 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
| 387 | #define NDTR0_tWH(c) (min((c), 7) << 11) | 407 | #define NDTR0_tWH(c) (min((c), 7) << 11) |
| @@ -1546,9 +1566,12 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) | |||
| 1546 | } | 1566 | } |
| 1547 | 1567 | ||
| 1548 | static int pxa_ecc_init(struct pxa3xx_nand_info *info, | 1568 | static int pxa_ecc_init(struct pxa3xx_nand_info *info, |
| 1549 | struct nand_ecc_ctrl *ecc, | 1569 | struct mtd_info *mtd, |
| 1550 | int strength, int ecc_stepsize, int page_size) | 1570 | int strength, int ecc_stepsize, int page_size) |
| 1551 | { | 1571 | { |
| 1572 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1573 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 1574 | |||
| 1552 | if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { | 1575 | if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { |
| 1553 | info->nfullchunks = 1; | 1576 | info->nfullchunks = 1; |
| 1554 | info->ntotalchunks = 1; | 1577 | info->ntotalchunks = 1; |
| @@ -1582,7 +1605,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, | |||
| 1582 | info->ecc_size = 32; | 1605 | info->ecc_size = 32; |
| 1583 | ecc->mode = NAND_ECC_HW; | 1606 | ecc->mode = NAND_ECC_HW; |
| 1584 | ecc->size = info->chunk_size; | 1607 | ecc->size = info->chunk_size; |
| 1585 | ecc->layout = &ecc_layout_2KB_bch4bit; | 1608 | mtd_set_ooblayout(mtd, &pxa3xx_ooblayout_ops); |
| 1586 | ecc->strength = 16; | 1609 | ecc->strength = 16; |
| 1587 | 1610 | ||
| 1588 | } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { | 1611 | } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { |
| @@ -1594,7 +1617,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, | |||
| 1594 | info->ecc_size = 32; | 1617 | info->ecc_size = 32; |
| 1595 | ecc->mode = NAND_ECC_HW; | 1618 | ecc->mode = NAND_ECC_HW; |
| 1596 | ecc->size = info->chunk_size; | 1619 | ecc->size = info->chunk_size; |
| 1597 | ecc->layout = &ecc_layout_4KB_bch4bit; | 1620 | mtd_set_ooblayout(mtd, &pxa3xx_ooblayout_ops); |
| 1598 | ecc->strength = 16; | 1621 | ecc->strength = 16; |
| 1599 | 1622 | ||
| 1600 | /* | 1623 | /* |
| @@ -1612,7 +1635,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, | |||
| 1612 | info->ecc_size = 32; | 1635 | info->ecc_size = 32; |
| 1613 | ecc->mode = NAND_ECC_HW; | 1636 | ecc->mode = NAND_ECC_HW; |
| 1614 | ecc->size = info->chunk_size; | 1637 | ecc->size = info->chunk_size; |
| 1615 | ecc->layout = &ecc_layout_4KB_bch8bit; | 1638 | mtd_set_ooblayout(mtd, &pxa3xx_ooblayout_ops); |
| 1616 | ecc->strength = 16; | 1639 | ecc->strength = 16; |
| 1617 | } else { | 1640 | } else { |
| 1618 | dev_err(&info->pdev->dev, | 1641 | dev_err(&info->pdev->dev, |
| @@ -1651,6 +1674,12 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 1651 | if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) | 1674 | if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) |
| 1652 | nand_writel(info, NDECCCTRL, 0x0); | 1675 | nand_writel(info, NDECCCTRL, 0x0); |
| 1653 | 1676 | ||
| 1677 | if (pdata->flash_bbt) | ||
| 1678 | chip->bbt_options |= NAND_BBT_USE_FLASH; | ||
| 1679 | |||
| 1680 | chip->ecc.strength = pdata->ecc_strength; | ||
| 1681 | chip->ecc.size = pdata->ecc_step_size; | ||
| 1682 | |||
| 1654 | if (nand_scan_ident(mtd, 1, NULL)) | 1683 | if (nand_scan_ident(mtd, 1, NULL)) |
| 1655 | return -ENODEV; | 1684 | return -ENODEV; |
| 1656 | 1685 | ||
| @@ -1663,13 +1692,12 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 1663 | } | 1692 | } |
| 1664 | } | 1693 | } |
| 1665 | 1694 | ||
| 1666 | if (pdata->flash_bbt) { | 1695 | if (chip->bbt_options & NAND_BBT_USE_FLASH) { |
| 1667 | /* | 1696 | /* |
| 1668 | * We'll use a bad block table stored in-flash and don't | 1697 | * We'll use a bad block table stored in-flash and don't |
| 1669 | * allow writing the bad block marker to the flash. | 1698 | * allow writing the bad block marker to the flash. |
| 1670 | */ | 1699 | */ |
| 1671 | chip->bbt_options |= NAND_BBT_USE_FLASH | | 1700 | chip->bbt_options |= NAND_BBT_NO_OOB_BBM; |
| 1672 | NAND_BBT_NO_OOB_BBM; | ||
| 1673 | chip->bbt_td = &bbt_main_descr; | 1701 | chip->bbt_td = &bbt_main_descr; |
| 1674 | chip->bbt_md = &bbt_mirror_descr; | 1702 | chip->bbt_md = &bbt_mirror_descr; |
| 1675 | } | 1703 | } |
| @@ -1689,10 +1717,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 1689 | } | 1717 | } |
| 1690 | } | 1718 | } |
| 1691 | 1719 | ||
| 1692 | if (pdata->ecc_strength && pdata->ecc_step_size) { | 1720 | ecc_strength = chip->ecc.strength; |
| 1693 | ecc_strength = pdata->ecc_strength; | 1721 | ecc_step = chip->ecc.size; |
| 1694 | ecc_step = pdata->ecc_step_size; | 1722 | if (!ecc_strength || !ecc_step) { |
| 1695 | } else { | ||
| 1696 | ecc_strength = chip->ecc_strength_ds; | 1723 | ecc_strength = chip->ecc_strength_ds; |
| 1697 | ecc_step = chip->ecc_step_ds; | 1724 | ecc_step = chip->ecc_step_ds; |
| 1698 | } | 1725 | } |
| @@ -1703,7 +1730,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 1703 | ecc_step = 512; | 1730 | ecc_step = 512; |
| 1704 | } | 1731 | } |
| 1705 | 1732 | ||
| 1706 | ret = pxa_ecc_init(info, &chip->ecc, ecc_strength, | 1733 | ret = pxa_ecc_init(info, mtd, ecc_strength, |
| 1707 | ecc_step, mtd->writesize); | 1734 | ecc_step, mtd->writesize); |
| 1708 | if (ret) | 1735 | if (ret) |
| 1709 | return ret; | 1736 | return ret; |
| @@ -1903,15 +1930,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) | |||
| 1903 | if (of_get_property(np, "marvell,nand-keep-config", NULL)) | 1930 | if (of_get_property(np, "marvell,nand-keep-config", NULL)) |
| 1904 | pdata->keep_config = 1; | 1931 | pdata->keep_config = 1; |
| 1905 | of_property_read_u32(np, "num-cs", &pdata->num_cs); | 1932 | of_property_read_u32(np, "num-cs", &pdata->num_cs); |
| 1906 | pdata->flash_bbt = of_get_nand_on_flash_bbt(np); | ||
| 1907 | |||
| 1908 | pdata->ecc_strength = of_get_nand_ecc_strength(np); | ||
| 1909 | if (pdata->ecc_strength < 0) | ||
| 1910 | pdata->ecc_strength = 0; | ||
| 1911 | |||
| 1912 | pdata->ecc_step_size = of_get_nand_ecc_step_size(np); | ||
| 1913 | if (pdata->ecc_step_size < 0) | ||
| 1914 | pdata->ecc_step_size = 0; | ||
| 1915 | 1933 | ||
| 1916 | pdev->dev.platform_data = pdata; | 1934 | pdev->dev.platform_data = pdata; |
| 1917 | 1935 | ||
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index f550a57e6eea..de7d28e62d4e 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/mtd/partitions.h> | 21 | #include <linux/mtd/partitions.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
| 24 | #include <linux/of_mtd.h> | ||
| 25 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 26 | 25 | ||
| 27 | /* NANDc reg offsets */ | 26 | /* NANDc reg offsets */ |
| @@ -1437,7 +1436,6 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1437 | struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); | 1436 | struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); |
| 1438 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 1437 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 1439 | u8 *oob = chip->oob_poi; | 1438 | u8 *oob = chip->oob_poi; |
| 1440 | int free_boff; | ||
| 1441 | int data_size, oob_size; | 1439 | int data_size, oob_size; |
| 1442 | int ret, status = 0; | 1440 | int ret, status = 0; |
| 1443 | 1441 | ||
| @@ -1451,12 +1449,11 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1451 | 1449 | ||
| 1452 | /* calculate the data and oob size for the last codeword/step */ | 1450 | /* calculate the data and oob size for the last codeword/step */ |
| 1453 | data_size = ecc->size - ((ecc->steps - 1) << 2); | 1451 | data_size = ecc->size - ((ecc->steps - 1) << 2); |
| 1454 | oob_size = ecc->steps << 2; | 1452 | oob_size = mtd->oobavail; |
| 1455 | |||
| 1456 | free_boff = ecc->layout->oobfree[0].offset; | ||
| 1457 | 1453 | ||
| 1458 | /* override new oob content to last codeword */ | 1454 | /* override new oob content to last codeword */ |
| 1459 | memcpy(nandc->data_buffer + data_size, oob + free_boff, oob_size); | 1455 | mtd_ooblayout_get_databytes(mtd, nandc->data_buffer + data_size, oob, |
| 1456 | 0, mtd->oobavail); | ||
| 1460 | 1457 | ||
| 1461 | set_address(host, host->cw_size * (ecc->steps - 1), page); | 1458 | set_address(host, host->cw_size * (ecc->steps - 1), page); |
| 1462 | update_rw_regs(host, 1, false); | 1459 | update_rw_regs(host, 1, false); |
| @@ -1710,61 +1707,52 @@ static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr) | |||
| 1710 | * This layout is read as is when ECC is disabled. When ECC is enabled, the | 1707 | * This layout is read as is when ECC is disabled. When ECC is enabled, the |
| 1711 | * inaccessible Bad Block byte(s) are ignored when we write to a page/oob, | 1708 | * inaccessible Bad Block byte(s) are ignored when we write to a page/oob, |
| 1712 | * and assumed as 0xffs when we read a page/oob. The ECC, unused and | 1709 | * and assumed as 0xffs when we read a page/oob. The ECC, unused and |
| 1713 | * dummy/real bad block bytes are grouped as ecc bytes in nand_ecclayout (i.e, | 1710 | * dummy/real bad block bytes are grouped as ecc bytes (i.e, ecc->bytes is |
| 1714 | * ecc->bytes is the sum of the three). | 1711 | * the sum of the three). |
| 1715 | */ | 1712 | */ |
| 1716 | 1713 | static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section, | |
| 1717 | static struct nand_ecclayout * | 1714 | struct mtd_oob_region *oobregion) |
| 1718 | qcom_nand_create_layout(struct qcom_nand_host *host) | ||
| 1719 | { | 1715 | { |
| 1720 | struct nand_chip *chip = &host->chip; | 1716 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 1721 | struct mtd_info *mtd = nand_to_mtd(chip); | 1717 | struct qcom_nand_host *host = to_qcom_nand_host(chip); |
| 1722 | struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); | ||
| 1723 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 1718 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 1724 | struct nand_ecclayout *layout; | ||
| 1725 | int i, j, steps, pos = 0, shift = 0; | ||
| 1726 | 1719 | ||
| 1727 | layout = devm_kzalloc(nandc->dev, sizeof(*layout), GFP_KERNEL); | 1720 | if (section > 1) |
| 1728 | if (!layout) | 1721 | return -ERANGE; |
| 1729 | return NULL; | ||
| 1730 | |||
| 1731 | steps = mtd->writesize / ecc->size; | ||
| 1732 | layout->eccbytes = steps * ecc->bytes; | ||
| 1733 | 1722 | ||
| 1734 | layout->oobfree[0].offset = (steps - 1) * ecc->bytes + host->bbm_size; | 1723 | if (!section) { |
| 1735 | layout->oobfree[0].length = steps << 2; | 1724 | oobregion->length = (ecc->bytes * (ecc->steps - 1)) + |
| 1736 | 1725 | host->bbm_size; | |
| 1737 | /* | 1726 | oobregion->offset = 0; |
| 1738 | * the oob bytes in the first n - 1 codewords are all grouped together | 1727 | } else { |
| 1739 | * in the format: | 1728 | oobregion->length = host->ecc_bytes_hw + host->spare_bytes; |
| 1740 | * DUMMY_BBM + UNUSED + ECC | 1729 | oobregion->offset = mtd->oobsize - oobregion->length; |
| 1741 | */ | ||
| 1742 | for (i = 0; i < steps - 1; i++) { | ||
| 1743 | for (j = 0; j < ecc->bytes; j++) | ||
| 1744 | layout->eccpos[pos++] = i * ecc->bytes + j; | ||
| 1745 | } | 1730 | } |
| 1746 | 1731 | ||
| 1747 | /* | 1732 | return 0; |
| 1748 | * the oob bytes in the last codeword are grouped in the format: | 1733 | } |
| 1749 | * BBM + FREE OOB + UNUSED + ECC | ||
| 1750 | */ | ||
| 1751 | 1734 | ||
| 1752 | /* fill up the bbm positions */ | 1735 | static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section, |
| 1753 | for (j = 0; j < host->bbm_size; j++) | 1736 | struct mtd_oob_region *oobregion) |
| 1754 | layout->eccpos[pos++] = i * ecc->bytes + j; | 1737 | { |
| 1738 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 1739 | struct qcom_nand_host *host = to_qcom_nand_host(chip); | ||
| 1740 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 1755 | 1741 | ||
| 1756 | /* | 1742 | if (section) |
| 1757 | * fill up the ecc and reserved positions, their indices are offseted | 1743 | return -ERANGE; |
| 1758 | * by the free oob region | ||
| 1759 | */ | ||
| 1760 | shift = layout->oobfree[0].length + host->bbm_size; | ||
| 1761 | 1744 | ||
| 1762 | for (j = 0; j < (host->ecc_bytes_hw + host->spare_bytes); j++) | 1745 | oobregion->length = ecc->steps * 4; |
| 1763 | layout->eccpos[pos++] = i * ecc->bytes + shift + j; | 1746 | oobregion->offset = ((ecc->steps - 1) * ecc->bytes) + host->bbm_size; |
| 1764 | 1747 | ||
| 1765 | return layout; | 1748 | return 0; |
| 1766 | } | 1749 | } |
| 1767 | 1750 | ||
| 1751 | static const struct mtd_ooblayout_ops qcom_nand_ooblayout_ops = { | ||
| 1752 | .ecc = qcom_nand_ooblayout_ecc, | ||
| 1753 | .free = qcom_nand_ooblayout_free, | ||
| 1754 | }; | ||
| 1755 | |||
| 1768 | static int qcom_nand_host_setup(struct qcom_nand_host *host) | 1756 | static int qcom_nand_host_setup(struct qcom_nand_host *host) |
| 1769 | { | 1757 | { |
| 1770 | struct nand_chip *chip = &host->chip; | 1758 | struct nand_chip *chip = &host->chip; |
| @@ -1851,9 +1839,7 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host) | |||
| 1851 | 1839 | ||
| 1852 | ecc->mode = NAND_ECC_HW; | 1840 | ecc->mode = NAND_ECC_HW; |
| 1853 | 1841 | ||
| 1854 | ecc->layout = qcom_nand_create_layout(host); | 1842 | mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops); |
| 1855 | if (!ecc->layout) | ||
| 1856 | return -ENOMEM; | ||
| 1857 | 1843 | ||
| 1858 | cwperpage = mtd->writesize / ecc->size; | 1844 | cwperpage = mtd->writesize / ecc->size; |
| 1859 | 1845 | ||
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 9c9397b54b2c..d9309cf0ce2e 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
| @@ -84,11 +84,33 @@ | |||
| 84 | 84 | ||
| 85 | /* new oob placement block for use with hardware ecc generation | 85 | /* new oob placement block for use with hardware ecc generation |
| 86 | */ | 86 | */ |
| 87 | static int s3c2410_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 88 | struct mtd_oob_region *oobregion) | ||
| 89 | { | ||
| 90 | if (section) | ||
| 91 | return -ERANGE; | ||
| 92 | |||
| 93 | oobregion->offset = 0; | ||
| 94 | oobregion->length = 3; | ||
| 95 | |||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int s3c2410_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 100 | struct mtd_oob_region *oobregion) | ||
| 101 | { | ||
| 102 | if (section) | ||
| 103 | return -ERANGE; | ||
| 104 | |||
| 105 | oobregion->offset = 8; | ||
| 106 | oobregion->length = 8; | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 87 | 110 | ||
| 88 | static struct nand_ecclayout nand_hw_eccoob = { | 111 | static const struct mtd_ooblayout_ops s3c2410_ooblayout_ops = { |
| 89 | .eccbytes = 3, | 112 | .ecc = s3c2410_ooblayout_ecc, |
| 90 | .eccpos = {0, 1, 2}, | 113 | .free = s3c2410_ooblayout_free, |
| 91 | .oobfree = {{8, 8}} | ||
| 92 | }; | 114 | }; |
| 93 | 115 | ||
| 94 | /* controller and mtd information */ | 116 | /* controller and mtd information */ |
| @@ -542,7 +564,8 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
| 542 | diff0 |= (diff1 << 8); | 564 | diff0 |= (diff1 << 8); |
| 543 | diff0 |= (diff2 << 16); | 565 | diff0 |= (diff2 << 16); |
| 544 | 566 | ||
| 545 | if ((diff0 & ~(1<<fls(diff0))) == 0) | 567 | /* equal to "(diff0 & ~(1 << __ffs(diff0)))" */ |
| 568 | if ((diff0 & (diff0 - 1)) == 0) | ||
| 546 | return 1; | 569 | return 1; |
| 547 | 570 | ||
| 548 | return -1; | 571 | return -1; |
| @@ -859,6 +882,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
| 859 | } | 882 | } |
| 860 | #else | 883 | #else |
| 861 | chip->ecc.mode = NAND_ECC_SOFT; | 884 | chip->ecc.mode = NAND_ECC_SOFT; |
| 885 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 862 | #endif | 886 | #endif |
| 863 | 887 | ||
| 864 | if (set->disable_ecc) | 888 | if (set->disable_ecc) |
| @@ -919,7 +943,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, | |||
| 919 | } else { | 943 | } else { |
| 920 | chip->ecc.size = 512; | 944 | chip->ecc.size = 512; |
| 921 | chip->ecc.bytes = 3; | 945 | chip->ecc.bytes = 3; |
| 922 | chip->ecc.layout = &nand_hw_eccoob; | 946 | mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops); |
| 923 | } | 947 | } |
| 924 | } | 948 | } |
| 925 | 949 | ||
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 4814402902f9..6fa3bcd59769 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | #include <linux/of.h> | 32 | #include <linux/of.h> |
| 33 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
| 34 | #include <linux/of_mtd.h> | ||
| 35 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 36 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
| 37 | #include <linux/sh_dma.h> | 36 | #include <linux/sh_dma.h> |
| @@ -43,26 +42,73 @@ | |||
| 43 | #include <linux/mtd/partitions.h> | 42 | #include <linux/mtd/partitions.h> |
| 44 | #include <linux/mtd/sh_flctl.h> | 43 | #include <linux/mtd/sh_flctl.h> |
| 45 | 44 | ||
| 46 | static struct nand_ecclayout flctl_4secc_oob_16 = { | 45 | static int flctl_4secc_ooblayout_sp_ecc(struct mtd_info *mtd, int section, |
| 47 | .eccbytes = 10, | 46 | struct mtd_oob_region *oobregion) |
| 48 | .eccpos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, | 47 | { |
| 49 | .oobfree = { | 48 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 50 | {.offset = 12, | 49 | |
| 51 | . length = 4} }, | 50 | if (section) |
| 51 | return -ERANGE; | ||
| 52 | |||
| 53 | oobregion->offset = 0; | ||
| 54 | oobregion->length = chip->ecc.bytes; | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int flctl_4secc_ooblayout_sp_free(struct mtd_info *mtd, int section, | ||
| 60 | struct mtd_oob_region *oobregion) | ||
| 61 | { | ||
| 62 | if (section) | ||
| 63 | return -ERANGE; | ||
| 64 | |||
| 65 | oobregion->offset = 12; | ||
| 66 | oobregion->length = 4; | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | static const struct mtd_ooblayout_ops flctl_4secc_oob_smallpage_ops = { | ||
| 72 | .ecc = flctl_4secc_ooblayout_sp_ecc, | ||
| 73 | .free = flctl_4secc_ooblayout_sp_free, | ||
| 52 | }; | 74 | }; |
| 53 | 75 | ||
| 54 | static struct nand_ecclayout flctl_4secc_oob_64 = { | 76 | static int flctl_4secc_ooblayout_lp_ecc(struct mtd_info *mtd, int section, |
| 55 | .eccbytes = 4 * 10, | 77 | struct mtd_oob_region *oobregion) |
| 56 | .eccpos = { | 78 | { |
| 57 | 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | 79 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 58 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, | 80 | |
| 59 | 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, | 81 | if (section >= chip->ecc.steps) |
| 60 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, | 82 | return -ERANGE; |
| 61 | .oobfree = { | 83 | |
| 62 | {.offset = 2, .length = 4}, | 84 | oobregion->offset = (section * 16) + 6; |
| 63 | {.offset = 16, .length = 6}, | 85 | oobregion->length = chip->ecc.bytes; |
| 64 | {.offset = 32, .length = 6}, | 86 | |
| 65 | {.offset = 48, .length = 6} }, | 87 | return 0; |
| 88 | } | ||
| 89 | |||
| 90 | static int flctl_4secc_ooblayout_lp_free(struct mtd_info *mtd, int section, | ||
| 91 | struct mtd_oob_region *oobregion) | ||
| 92 | { | ||
| 93 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 94 | |||
| 95 | if (section >= chip->ecc.steps) | ||
| 96 | return -ERANGE; | ||
| 97 | |||
| 98 | oobregion->offset = section * 16; | ||
| 99 | oobregion->length = 6; | ||
| 100 | |||
| 101 | if (!section) { | ||
| 102 | oobregion->offset += 2; | ||
| 103 | oobregion->length -= 2; | ||
| 104 | } | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static const struct mtd_ooblayout_ops flctl_4secc_oob_largepage_ops = { | ||
| 110 | .ecc = flctl_4secc_ooblayout_lp_ecc, | ||
| 111 | .free = flctl_4secc_ooblayout_lp_free, | ||
| 66 | }; | 112 | }; |
| 67 | 113 | ||
| 68 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 114 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
| @@ -987,10 +1033,10 @@ static int flctl_chip_init_tail(struct mtd_info *mtd) | |||
| 987 | 1033 | ||
| 988 | if (flctl->hwecc) { | 1034 | if (flctl->hwecc) { |
| 989 | if (mtd->writesize == 512) { | 1035 | if (mtd->writesize == 512) { |
| 990 | chip->ecc.layout = &flctl_4secc_oob_16; | 1036 | mtd_set_ooblayout(mtd, &flctl_4secc_oob_smallpage_ops); |
| 991 | chip->badblock_pattern = &flctl_4secc_smallpage; | 1037 | chip->badblock_pattern = &flctl_4secc_smallpage; |
| 992 | } else { | 1038 | } else { |
| 993 | chip->ecc.layout = &flctl_4secc_oob_64; | 1039 | mtd_set_ooblayout(mtd, &flctl_4secc_oob_largepage_ops); |
| 994 | chip->badblock_pattern = &flctl_4secc_largepage; | 1040 | chip->badblock_pattern = &flctl_4secc_largepage; |
| 995 | } | 1041 | } |
| 996 | 1042 | ||
| @@ -1005,6 +1051,7 @@ static int flctl_chip_init_tail(struct mtd_info *mtd) | |||
| 1005 | flctl->flcmncr_base |= _4ECCEN; | 1051 | flctl->flcmncr_base |= _4ECCEN; |
| 1006 | } else { | 1052 | } else { |
| 1007 | chip->ecc.mode = NAND_ECC_SOFT; | 1053 | chip->ecc.mode = NAND_ECC_SOFT; |
| 1054 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 1008 | } | 1055 | } |
| 1009 | 1056 | ||
| 1010 | return 0; | 1057 | return 0; |
| @@ -1044,8 +1091,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) | |||
| 1044 | const struct of_device_id *match; | 1091 | const struct of_device_id *match; |
| 1045 | struct flctl_soc_config *config; | 1092 | struct flctl_soc_config *config; |
| 1046 | struct sh_flctl_platform_data *pdata; | 1093 | struct sh_flctl_platform_data *pdata; |
| 1047 | struct device_node *dn = dev->of_node; | ||
| 1048 | int ret; | ||
| 1049 | 1094 | ||
| 1050 | match = of_match_device(of_flctl_match, dev); | 1095 | match = of_match_device(of_flctl_match, dev); |
| 1051 | if (match) | 1096 | if (match) |
| @@ -1065,15 +1110,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) | |||
| 1065 | pdata->has_hwecc = config->has_hwecc; | 1110 | pdata->has_hwecc = config->has_hwecc; |
| 1066 | pdata->use_holden = config->use_holden; | 1111 | pdata->use_holden = config->use_holden; |
| 1067 | 1112 | ||
| 1068 | /* parse user defined options */ | ||
| 1069 | ret = of_get_nand_bus_width(dn); | ||
| 1070 | if (ret == 16) | ||
| 1071 | pdata->flcmncr_val |= SEL_16BIT; | ||
| 1072 | else if (ret != 8) { | ||
| 1073 | dev_err(dev, "%s: invalid bus width\n", __func__); | ||
| 1074 | return NULL; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | return pdata; | 1113 | return pdata; |
| 1078 | } | 1114 | } |
| 1079 | 1115 | ||
| @@ -1136,15 +1172,14 @@ static int flctl_probe(struct platform_device *pdev) | |||
| 1136 | nand->chip_delay = 20; | 1172 | nand->chip_delay = 20; |
| 1137 | 1173 | ||
| 1138 | nand->read_byte = flctl_read_byte; | 1174 | nand->read_byte = flctl_read_byte; |
| 1175 | nand->read_word = flctl_read_word; | ||
| 1139 | nand->write_buf = flctl_write_buf; | 1176 | nand->write_buf = flctl_write_buf; |
| 1140 | nand->read_buf = flctl_read_buf; | 1177 | nand->read_buf = flctl_read_buf; |
| 1141 | nand->select_chip = flctl_select_chip; | 1178 | nand->select_chip = flctl_select_chip; |
| 1142 | nand->cmdfunc = flctl_cmdfunc; | 1179 | nand->cmdfunc = flctl_cmdfunc; |
| 1143 | 1180 | ||
| 1144 | if (pdata->flcmncr_val & SEL_16BIT) { | 1181 | if (pdata->flcmncr_val & SEL_16BIT) |
| 1145 | nand->options |= NAND_BUSWIDTH_16; | 1182 | nand->options |= NAND_BUSWIDTH_16; |
| 1146 | nand->read_word = flctl_read_word; | ||
| 1147 | } | ||
| 1148 | 1183 | ||
| 1149 | pm_runtime_enable(&pdev->dev); | 1184 | pm_runtime_enable(&pdev->dev); |
| 1150 | pm_runtime_resume(&pdev->dev); | 1185 | pm_runtime_resume(&pdev->dev); |
| @@ -1155,6 +1190,16 @@ static int flctl_probe(struct platform_device *pdev) | |||
| 1155 | if (ret) | 1190 | if (ret) |
| 1156 | goto err_chip; | 1191 | goto err_chip; |
| 1157 | 1192 | ||
| 1193 | if (nand->options & NAND_BUSWIDTH_16) { | ||
| 1194 | /* | ||
| 1195 | * NAND_BUSWIDTH_16 may have been set by nand_scan_ident(). | ||
| 1196 | * Add the SEL_16BIT flag in pdata->flcmncr_val and re-assign | ||
| 1197 | * flctl->flcmncr_base to pdata->flcmncr_val. | ||
| 1198 | */ | ||
| 1199 | pdata->flcmncr_val |= SEL_16BIT; | ||
| 1200 | flctl->flcmncr_base = pdata->flcmncr_val; | ||
| 1201 | } | ||
| 1202 | |||
| 1158 | ret = flctl_chip_init_tail(flctl_mtd); | 1203 | ret = flctl_chip_init_tail(flctl_mtd); |
| 1159 | if (ret) | 1204 | if (ret) |
| 1160 | goto err_chip; | 1205 | goto err_chip; |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index b7d1b55a160b..064ca1757589 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
| @@ -148,6 +148,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) | |||
| 148 | /* Link the private data with the MTD structure */ | 148 | /* Link the private data with the MTD structure */ |
| 149 | mtd = nand_to_mtd(this); | 149 | mtd = nand_to_mtd(this); |
| 150 | mtd->dev.parent = &pdev->dev; | 150 | mtd->dev.parent = &pdev->dev; |
| 151 | mtd_set_ooblayout(mtd, data->ecc_layout); | ||
| 151 | 152 | ||
| 152 | platform_set_drvdata(pdev, sharpsl); | 153 | platform_set_drvdata(pdev, sharpsl); |
| 153 | 154 | ||
| @@ -170,7 +171,6 @@ static int sharpsl_nand_probe(struct platform_device *pdev) | |||
| 170 | this->ecc.bytes = 3; | 171 | this->ecc.bytes = 3; |
| 171 | this->ecc.strength = 1; | 172 | this->ecc.strength = 1; |
| 172 | this->badblock_pattern = data->badblock_pattern; | 173 | this->badblock_pattern = data->badblock_pattern; |
| 173 | this->ecc.layout = data->ecc_layout; | ||
| 174 | this->ecc.hwctl = sharpsl_nand_enable_hwecc; | 174 | this->ecc.hwctl = sharpsl_nand_enable_hwecc; |
| 175 | this->ecc.calculate = sharpsl_nand_calculate_ecc; | 175 | this->ecc.calculate = sharpsl_nand_calculate_ecc; |
| 176 | this->ecc.correct = nand_correct_data; | 176 | this->ecc.correct = nand_correct_data; |
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index c514740f9a83..5939dff253c2 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
| @@ -12,14 +12,47 @@ | |||
| 12 | #include <linux/sizes.h> | 12 | #include <linux/sizes.h> |
| 13 | #include "sm_common.h" | 13 | #include "sm_common.h" |
| 14 | 14 | ||
| 15 | static struct nand_ecclayout nand_oob_sm = { | 15 | static int oob_sm_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 16 | .eccbytes = 6, | 16 | struct mtd_oob_region *oobregion) |
| 17 | .eccpos = {8, 9, 10, 13, 14, 15}, | 17 | { |
| 18 | .oobfree = { | 18 | if (section > 1) |
| 19 | {.offset = 0 , .length = 4}, /* reserved */ | 19 | return -ERANGE; |
| 20 | {.offset = 6 , .length = 2}, /* LBA1 */ | 20 | |
| 21 | {.offset = 11, .length = 2} /* LBA2 */ | 21 | oobregion->length = 3; |
| 22 | oobregion->offset = ((section + 1) * 8) - 3; | ||
| 23 | |||
| 24 | return 0; | ||
| 25 | } | ||
| 26 | |||
| 27 | static int oob_sm_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 28 | struct mtd_oob_region *oobregion) | ||
| 29 | { | ||
| 30 | switch (section) { | ||
| 31 | case 0: | ||
| 32 | /* reserved */ | ||
| 33 | oobregion->offset = 0; | ||
| 34 | oobregion->length = 4; | ||
| 35 | break; | ||
| 36 | case 1: | ||
| 37 | /* LBA1 */ | ||
| 38 | oobregion->offset = 6; | ||
| 39 | oobregion->length = 2; | ||
| 40 | break; | ||
| 41 | case 2: | ||
| 42 | /* LBA2 */ | ||
| 43 | oobregion->offset = 11; | ||
| 44 | oobregion->length = 2; | ||
| 45 | break; | ||
| 46 | default: | ||
| 47 | return -ERANGE; | ||
| 22 | } | 48 | } |
| 49 | |||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static const struct mtd_ooblayout_ops oob_sm_ops = { | ||
| 54 | .ecc = oob_sm_ooblayout_ecc, | ||
| 55 | .free = oob_sm_ooblayout_free, | ||
| 23 | }; | 56 | }; |
| 24 | 57 | ||
| 25 | /* NOTE: This layout is is not compatabable with SmartMedia, */ | 58 | /* NOTE: This layout is is not compatabable with SmartMedia, */ |
| @@ -28,15 +61,43 @@ static struct nand_ecclayout nand_oob_sm = { | |||
| 28 | /* If you use smftl, it will bypass this and work correctly */ | 61 | /* If you use smftl, it will bypass this and work correctly */ |
| 29 | /* If you not, then you break SmartMedia compliance anyway */ | 62 | /* If you not, then you break SmartMedia compliance anyway */ |
| 30 | 63 | ||
| 31 | static struct nand_ecclayout nand_oob_sm_small = { | 64 | static int oob_sm_small_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 32 | .eccbytes = 3, | 65 | struct mtd_oob_region *oobregion) |
| 33 | .eccpos = {0, 1, 2}, | 66 | { |
| 34 | .oobfree = { | 67 | if (section) |
| 35 | {.offset = 3 , .length = 2}, /* reserved */ | 68 | return -ERANGE; |
| 36 | {.offset = 6 , .length = 2}, /* LBA1 */ | 69 | |
| 70 | oobregion->length = 3; | ||
| 71 | oobregion->offset = 0; | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static int oob_sm_small_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 77 | struct mtd_oob_region *oobregion) | ||
| 78 | { | ||
| 79 | switch (section) { | ||
| 80 | case 0: | ||
| 81 | /* reserved */ | ||
| 82 | oobregion->offset = 3; | ||
| 83 | oobregion->length = 2; | ||
| 84 | break; | ||
| 85 | case 1: | ||
| 86 | /* LBA1 */ | ||
| 87 | oobregion->offset = 6; | ||
| 88 | oobregion->length = 2; | ||
| 89 | break; | ||
| 90 | default: | ||
| 91 | return -ERANGE; | ||
| 37 | } | 92 | } |
| 38 | }; | ||
| 39 | 93 | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static const struct mtd_ooblayout_ops oob_sm_small_ops = { | ||
| 98 | .ecc = oob_sm_small_ooblayout_ecc, | ||
| 99 | .free = oob_sm_small_ooblayout_free, | ||
| 100 | }; | ||
| 40 | 101 | ||
| 41 | static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) | 102 | static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) |
| 42 | { | 103 | { |
| @@ -121,9 +182,9 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia) | |||
| 121 | 182 | ||
| 122 | /* ECC layout */ | 183 | /* ECC layout */ |
| 123 | if (mtd->writesize == SM_SECTOR_SIZE) | 184 | if (mtd->writesize == SM_SECTOR_SIZE) |
| 124 | chip->ecc.layout = &nand_oob_sm; | 185 | mtd_set_ooblayout(mtd, &oob_sm_ops); |
| 125 | else if (mtd->writesize == SM_SMALL_PAGE) | 186 | else if (mtd->writesize == SM_SMALL_PAGE) |
| 126 | chip->ecc.layout = &nand_oob_sm_small; | 187 | mtd_set_ooblayout(mtd, &oob_sm_small_ops); |
| 127 | else | 188 | else |
| 128 | return -ENODEV; | 189 | return -ENODEV; |
| 129 | 190 | ||
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index e3305f9dd6fb..888fd314c62a 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
| @@ -180,6 +180,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) | |||
| 180 | nand_chip->dev_ready = socrates_nand_device_ready; | 180 | nand_chip->dev_ready = socrates_nand_device_ready; |
| 181 | 181 | ||
| 182 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ | 182 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ |
| 183 | nand_chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 183 | 184 | ||
| 184 | /* TODO: I have no idea what real delay is. */ | 185 | /* TODO: I have no idea what real delay is. */ |
| 185 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 186 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 1c03eee44f3d..a83a690688b4 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
| 31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
| 32 | #include <linux/of_gpio.h> | 32 | #include <linux/of_gpio.h> |
| 33 | #include <linux/of_mtd.h> | ||
| 34 | #include <linux/mtd/mtd.h> | 33 | #include <linux/mtd/mtd.h> |
| 35 | #include <linux/mtd/nand.h> | 34 | #include <linux/mtd/nand.h> |
| 36 | #include <linux/mtd/partitions.h> | 35 | #include <linux/mtd/partitions.h> |
| @@ -39,7 +38,7 @@ | |||
| 39 | #include <linux/dmaengine.h> | 38 | #include <linux/dmaengine.h> |
| 40 | #include <linux/gpio.h> | 39 | #include <linux/gpio.h> |
| 41 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
| 42 | #include <linux/io.h> | 41 | #include <linux/iopoll.h> |
| 43 | 42 | ||
| 44 | #define NFC_REG_CTL 0x0000 | 43 | #define NFC_REG_CTL 0x0000 |
| 45 | #define NFC_REG_ST 0x0004 | 44 | #define NFC_REG_ST 0x0004 |
| @@ -155,7 +154,7 @@ | |||
| 155 | /* define bit use in NFC_ECC_ST */ | 154 | /* define bit use in NFC_ECC_ST */ |
| 156 | #define NFC_ECC_ERR(x) BIT(x) | 155 | #define NFC_ECC_ERR(x) BIT(x) |
| 157 | #define NFC_ECC_PAT_FOUND(x) BIT(x + 16) | 156 | #define NFC_ECC_PAT_FOUND(x) BIT(x + 16) |
| 158 | #define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff) | 157 | #define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff) |
| 159 | 158 | ||
| 160 | #define NFC_DEFAULT_TIMEOUT_MS 1000 | 159 | #define NFC_DEFAULT_TIMEOUT_MS 1000 |
| 161 | 160 | ||
| @@ -212,12 +211,9 @@ struct sunxi_nand_chip_sel { | |||
| 212 | * sunxi HW ECC infos: stores information related to HW ECC support | 211 | * sunxi HW ECC infos: stores information related to HW ECC support |
| 213 | * | 212 | * |
| 214 | * @mode: the sunxi ECC mode field deduced from ECC requirements | 213 | * @mode: the sunxi ECC mode field deduced from ECC requirements |
| 215 | * @layout: the OOB layout depending on the ECC requirements and the | ||
| 216 | * selected ECC mode | ||
| 217 | */ | 214 | */ |
| 218 | struct sunxi_nand_hw_ecc { | 215 | struct sunxi_nand_hw_ecc { |
| 219 | int mode; | 216 | int mode; |
| 220 | struct nand_ecclayout layout; | ||
| 221 | }; | 217 | }; |
| 222 | 218 | ||
| 223 | /* | 219 | /* |
| @@ -239,6 +235,10 @@ struct sunxi_nand_chip { | |||
| 239 | u32 timing_cfg; | 235 | u32 timing_cfg; |
| 240 | u32 timing_ctl; | 236 | u32 timing_ctl; |
| 241 | int selected; | 237 | int selected; |
| 238 | int addr_cycles; | ||
| 239 | u32 addr[2]; | ||
| 240 | int cmd_cycles; | ||
| 241 | u8 cmd[2]; | ||
| 242 | int nsels; | 242 | int nsels; |
| 243 | struct sunxi_nand_chip_sel sels[0]; | 243 | struct sunxi_nand_chip_sel sels[0]; |
| 244 | }; | 244 | }; |
| @@ -298,54 +298,71 @@ static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id) | |||
| 298 | return IRQ_HANDLED; | 298 | return IRQ_HANDLED; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags, | 301 | static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, |
| 302 | unsigned int timeout_ms) | 302 | bool use_polling, unsigned int timeout_ms) |
| 303 | { | 303 | { |
| 304 | init_completion(&nfc->complete); | 304 | int ret; |
| 305 | 305 | ||
| 306 | writel(flags, nfc->regs + NFC_REG_INT); | 306 | if (events & ~NFC_INT_MASK) |
| 307 | return -EINVAL; | ||
| 307 | 308 | ||
| 308 | if (!timeout_ms) | 309 | if (!timeout_ms) |
| 309 | timeout_ms = NFC_DEFAULT_TIMEOUT_MS; | 310 | timeout_ms = NFC_DEFAULT_TIMEOUT_MS; |
| 310 | 311 | ||
| 311 | if (!wait_for_completion_timeout(&nfc->complete, | 312 | if (!use_polling) { |
| 312 | msecs_to_jiffies(timeout_ms))) { | 313 | init_completion(&nfc->complete); |
| 313 | dev_err(nfc->dev, "wait interrupt timedout\n"); | 314 | |
| 314 | return -ETIMEDOUT; | 315 | writel(events, nfc->regs + NFC_REG_INT); |
| 316 | |||
| 317 | ret = wait_for_completion_timeout(&nfc->complete, | ||
| 318 | msecs_to_jiffies(timeout_ms)); | ||
| 319 | |||
| 320 | writel(0, nfc->regs + NFC_REG_INT); | ||
| 321 | } else { | ||
| 322 | u32 status; | ||
| 323 | |||
| 324 | ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, | ||
| 325 | (status & events) == events, 1, | ||
| 326 | timeout_ms * 1000); | ||
| 315 | } | 327 | } |
| 316 | 328 | ||
| 317 | return 0; | 329 | writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); |
| 330 | |||
| 331 | if (ret) | ||
| 332 | dev_err(nfc->dev, "wait interrupt timedout\n"); | ||
| 333 | |||
| 334 | return ret; | ||
| 318 | } | 335 | } |
| 319 | 336 | ||
| 320 | static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) | 337 | static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) |
| 321 | { | 338 | { |
| 322 | unsigned long timeout = jiffies + | 339 | u32 status; |
| 323 | msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); | 340 | int ret; |
| 324 | 341 | ||
| 325 | do { | 342 | ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, |
| 326 | if (!(readl(nfc->regs + NFC_REG_ST) & NFC_CMD_FIFO_STATUS)) | 343 | !(status & NFC_CMD_FIFO_STATUS), 1, |
| 327 | return 0; | 344 | NFC_DEFAULT_TIMEOUT_MS * 1000); |
| 328 | } while (time_before(jiffies, timeout)); | 345 | if (ret) |
| 346 | dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); | ||
| 329 | 347 | ||
| 330 | dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); | 348 | return ret; |
| 331 | return -ETIMEDOUT; | ||
| 332 | } | 349 | } |
| 333 | 350 | ||
| 334 | static int sunxi_nfc_rst(struct sunxi_nfc *nfc) | 351 | static int sunxi_nfc_rst(struct sunxi_nfc *nfc) |
| 335 | { | 352 | { |
| 336 | unsigned long timeout = jiffies + | 353 | u32 ctl; |
| 337 | msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); | 354 | int ret; |
| 338 | 355 | ||
| 339 | writel(0, nfc->regs + NFC_REG_ECC_CTL); | 356 | writel(0, nfc->regs + NFC_REG_ECC_CTL); |
| 340 | writel(NFC_RESET, nfc->regs + NFC_REG_CTL); | 357 | writel(NFC_RESET, nfc->regs + NFC_REG_CTL); |
| 341 | 358 | ||
| 342 | do { | 359 | ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl, |
| 343 | if (!(readl(nfc->regs + NFC_REG_CTL) & NFC_RESET)) | 360 | !(ctl & NFC_RESET), 1, |
| 344 | return 0; | 361 | NFC_DEFAULT_TIMEOUT_MS * 1000); |
| 345 | } while (time_before(jiffies, timeout)); | 362 | if (ret) |
| 363 | dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); | ||
| 346 | 364 | ||
| 347 | dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); | 365 | return ret; |
| 348 | return -ETIMEDOUT; | ||
| 349 | } | 366 | } |
| 350 | 367 | ||
| 351 | static int sunxi_nfc_dev_ready(struct mtd_info *mtd) | 368 | static int sunxi_nfc_dev_ready(struct mtd_info *mtd) |
| @@ -354,7 +371,6 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) | |||
| 354 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | 371 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); |
| 355 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | 372 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); |
| 356 | struct sunxi_nand_rb *rb; | 373 | struct sunxi_nand_rb *rb; |
| 357 | unsigned long timeo = (sunxi_nand->nand.state == FL_ERASING ? 400 : 20); | ||
| 358 | int ret; | 374 | int ret; |
| 359 | 375 | ||
| 360 | if (sunxi_nand->selected < 0) | 376 | if (sunxi_nand->selected < 0) |
| @@ -366,12 +382,6 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) | |||
| 366 | case RB_NATIVE: | 382 | case RB_NATIVE: |
| 367 | ret = !!(readl(nfc->regs + NFC_REG_ST) & | 383 | ret = !!(readl(nfc->regs + NFC_REG_ST) & |
| 368 | NFC_RB_STATE(rb->info.nativeid)); | 384 | NFC_RB_STATE(rb->info.nativeid)); |
| 369 | if (ret) | ||
| 370 | break; | ||
| 371 | |||
| 372 | sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo); | ||
| 373 | ret = !!(readl(nfc->regs + NFC_REG_ST) & | ||
| 374 | NFC_RB_STATE(rb->info.nativeid)); | ||
| 375 | break; | 385 | break; |
| 376 | case RB_GPIO: | 386 | case RB_GPIO: |
| 377 | ret = gpio_get_value(rb->info.gpio); | 387 | ret = gpio_get_value(rb->info.gpio); |
| @@ -407,7 +417,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) | |||
| 407 | sel = &sunxi_nand->sels[chip]; | 417 | sel = &sunxi_nand->sels[chip]; |
| 408 | 418 | ||
| 409 | ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | | 419 | ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | |
| 410 | NFC_PAGE_SHIFT(nand->page_shift - 10); | 420 | NFC_PAGE_SHIFT(nand->page_shift); |
| 411 | if (sel->rb.type == RB_NONE) { | 421 | if (sel->rb.type == RB_NONE) { |
| 412 | nand->dev_ready = NULL; | 422 | nand->dev_ready = NULL; |
| 413 | } else { | 423 | } else { |
| @@ -452,7 +462,7 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
| 452 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; | 462 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; |
| 453 | writel(tmp, nfc->regs + NFC_REG_CMD); | 463 | writel(tmp, nfc->regs + NFC_REG_CMD); |
| 454 | 464 | ||
| 455 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | 465 | ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); |
| 456 | if (ret) | 466 | if (ret) |
| 457 | break; | 467 | break; |
| 458 | 468 | ||
| @@ -487,7 +497,7 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, | |||
| 487 | NFC_ACCESS_DIR; | 497 | NFC_ACCESS_DIR; |
| 488 | writel(tmp, nfc->regs + NFC_REG_CMD); | 498 | writel(tmp, nfc->regs + NFC_REG_CMD); |
| 489 | 499 | ||
| 490 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | 500 | ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); |
| 491 | if (ret) | 501 | if (ret) |
| 492 | break; | 502 | break; |
| 493 | 503 | ||
| @@ -511,32 +521,54 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, | |||
| 511 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | 521 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); |
| 512 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | 522 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); |
| 513 | int ret; | 523 | int ret; |
| 514 | u32 tmp; | ||
| 515 | 524 | ||
| 516 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | 525 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); |
| 517 | if (ret) | 526 | if (ret) |
| 518 | return; | 527 | return; |
| 519 | 528 | ||
| 520 | if (ctrl & NAND_CTRL_CHANGE) { | 529 | if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) && |
| 521 | tmp = readl(nfc->regs + NFC_REG_CTL); | 530 | !(ctrl & (NAND_CLE | NAND_ALE))) { |
| 522 | if (ctrl & NAND_NCE) | 531 | u32 cmd = 0; |
| 523 | tmp |= NFC_CE_CTL; | ||
| 524 | else | ||
| 525 | tmp &= ~NFC_CE_CTL; | ||
| 526 | writel(tmp, nfc->regs + NFC_REG_CTL); | ||
| 527 | } | ||
| 528 | 532 | ||
| 529 | if (dat == NAND_CMD_NONE) | 533 | if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles) |
| 530 | return; | 534 | return; |
| 531 | 535 | ||
| 532 | if (ctrl & NAND_CLE) { | 536 | if (sunxi_nand->cmd_cycles--) |
| 533 | writel(NFC_SEND_CMD1 | dat, nfc->regs + NFC_REG_CMD); | 537 | cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0]; |
| 534 | } else { | 538 | |
| 535 | writel(dat, nfc->regs + NFC_REG_ADDR_LOW); | 539 | if (sunxi_nand->cmd_cycles--) { |
| 536 | writel(NFC_SEND_ADR, nfc->regs + NFC_REG_CMD); | 540 | cmd |= NFC_SEND_CMD2; |
| 541 | writel(sunxi_nand->cmd[1], | ||
| 542 | nfc->regs + NFC_REG_RCMD_SET); | ||
| 543 | } | ||
| 544 | |||
| 545 | sunxi_nand->cmd_cycles = 0; | ||
| 546 | |||
| 547 | if (sunxi_nand->addr_cycles) { | ||
| 548 | cmd |= NFC_SEND_ADR | | ||
| 549 | NFC_ADR_NUM(sunxi_nand->addr_cycles); | ||
| 550 | writel(sunxi_nand->addr[0], | ||
| 551 | nfc->regs + NFC_REG_ADDR_LOW); | ||
| 552 | } | ||
| 553 | |||
| 554 | if (sunxi_nand->addr_cycles > 4) | ||
| 555 | writel(sunxi_nand->addr[1], | ||
| 556 | nfc->regs + NFC_REG_ADDR_HIGH); | ||
| 557 | |||
| 558 | writel(cmd, nfc->regs + NFC_REG_CMD); | ||
| 559 | sunxi_nand->addr[0] = 0; | ||
| 560 | sunxi_nand->addr[1] = 0; | ||
| 561 | sunxi_nand->addr_cycles = 0; | ||
| 562 | sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); | ||
| 537 | } | 563 | } |
| 538 | 564 | ||
| 539 | sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | 565 | if (ctrl & NAND_CLE) { |
| 566 | sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat; | ||
| 567 | } else if (ctrl & NAND_ALE) { | ||
| 568 | sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |= | ||
| 569 | dat << ((sunxi_nand->addr_cycles % 4) * 8); | ||
| 570 | sunxi_nand->addr_cycles++; | ||
| 571 | } | ||
| 540 | } | 572 | } |
| 541 | 573 | ||
| 542 | /* These seed values have been extracted from Allwinner's BSP */ | 574 | /* These seed values have been extracted from Allwinner's BSP */ |
| @@ -717,7 +749,8 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) | |||
| 717 | ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); | 749 | ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); |
| 718 | ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE | | 750 | ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE | |
| 719 | NFC_ECC_BLOCK_SIZE_MSK); | 751 | NFC_ECC_BLOCK_SIZE_MSK); |
| 720 | ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION; | 752 | ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION | |
| 753 | NFC_ECC_PIPELINE; | ||
| 721 | 754 | ||
| 722 | writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); | 755 | writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); |
| 723 | } | 756 | } |
| @@ -739,18 +772,106 @@ static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf) | |||
| 739 | buf[3] = user_data >> 24; | 772 | buf[3] = user_data >> 24; |
| 740 | } | 773 | } |
| 741 | 774 | ||
| 775 | static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) | ||
| 776 | { | ||
| 777 | return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); | ||
| 778 | } | ||
| 779 | |||
| 780 | static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob, | ||
| 781 | int step, bool bbm, int page) | ||
| 782 | { | ||
| 783 | struct nand_chip *nand = mtd_to_nand(mtd); | ||
| 784 | struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); | ||
| 785 | |||
| 786 | sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)), | ||
| 787 | oob); | ||
| 788 | |||
| 789 | /* De-randomize the Bad Block Marker. */ | ||
| 790 | if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) | ||
| 791 | sunxi_nfc_randomize_bbm(mtd, page, oob); | ||
| 792 | } | ||
| 793 | |||
| 794 | static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd, | ||
| 795 | const u8 *oob, int step, | ||
| 796 | bool bbm, int page) | ||
| 797 | { | ||
| 798 | struct nand_chip *nand = mtd_to_nand(mtd); | ||
| 799 | struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); | ||
| 800 | u8 user_data[4]; | ||
| 801 | |||
| 802 | /* Randomize the Bad Block Marker. */ | ||
| 803 | if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { | ||
| 804 | memcpy(user_data, oob, sizeof(user_data)); | ||
| 805 | sunxi_nfc_randomize_bbm(mtd, page, user_data); | ||
| 806 | oob = user_data; | ||
| 807 | } | ||
| 808 | |||
| 809 | writel(sunxi_nfc_buf_to_user_data(oob), | ||
| 810 | nfc->regs + NFC_REG_USER_DATA(step)); | ||
| 811 | } | ||
| 812 | |||
| 813 | static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd, | ||
| 814 | unsigned int *max_bitflips, int ret) | ||
| 815 | { | ||
| 816 | if (ret < 0) { | ||
| 817 | mtd->ecc_stats.failed++; | ||
| 818 | } else { | ||
| 819 | mtd->ecc_stats.corrected += ret; | ||
| 820 | *max_bitflips = max_t(unsigned int, *max_bitflips, ret); | ||
| 821 | } | ||
| 822 | } | ||
| 823 | |||
| 824 | static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob, | ||
| 825 | int step, bool *erased) | ||
| 826 | { | ||
| 827 | struct nand_chip *nand = mtd_to_nand(mtd); | ||
| 828 | struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); | ||
| 829 | struct nand_ecc_ctrl *ecc = &nand->ecc; | ||
| 830 | u32 status, tmp; | ||
| 831 | |||
| 832 | *erased = false; | ||
| 833 | |||
| 834 | status = readl(nfc->regs + NFC_REG_ECC_ST); | ||
| 835 | |||
| 836 | if (status & NFC_ECC_ERR(step)) | ||
| 837 | return -EBADMSG; | ||
| 838 | |||
| 839 | if (status & NFC_ECC_PAT_FOUND(step)) { | ||
| 840 | u8 pattern; | ||
| 841 | |||
| 842 | if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) { | ||
| 843 | pattern = 0x0; | ||
| 844 | } else { | ||
| 845 | pattern = 0xff; | ||
| 846 | *erased = true; | ||
| 847 | } | ||
| 848 | |||
| 849 | if (data) | ||
| 850 | memset(data, pattern, ecc->size); | ||
| 851 | |||
| 852 | if (oob) | ||
| 853 | memset(oob, pattern, ecc->bytes + 4); | ||
| 854 | |||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step)); | ||
| 859 | |||
| 860 | return NFC_ECC_ERR_CNT(step, tmp); | ||
| 861 | } | ||
| 862 | |||
| 742 | static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, | 863 | static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, |
| 743 | u8 *data, int data_off, | 864 | u8 *data, int data_off, |
| 744 | u8 *oob, int oob_off, | 865 | u8 *oob, int oob_off, |
| 745 | int *cur_off, | 866 | int *cur_off, |
| 746 | unsigned int *max_bitflips, | 867 | unsigned int *max_bitflips, |
| 747 | bool bbm, int page) | 868 | bool bbm, bool oob_required, int page) |
| 748 | { | 869 | { |
| 749 | struct nand_chip *nand = mtd_to_nand(mtd); | 870 | struct nand_chip *nand = mtd_to_nand(mtd); |
| 750 | struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); | 871 | struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); |
| 751 | struct nand_ecc_ctrl *ecc = &nand->ecc; | 872 | struct nand_ecc_ctrl *ecc = &nand->ecc; |
| 752 | int raw_mode = 0; | 873 | int raw_mode = 0; |
| 753 | u32 status; | 874 | bool erased; |
| 754 | int ret; | 875 | int ret; |
| 755 | 876 | ||
| 756 | if (*cur_off != data_off) | 877 | if (*cur_off != data_off) |
| @@ -769,34 +890,19 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, | |||
| 769 | writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, | 890 | writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, |
| 770 | nfc->regs + NFC_REG_CMD); | 891 | nfc->regs + NFC_REG_CMD); |
| 771 | 892 | ||
| 772 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | 893 | ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); |
| 773 | sunxi_nfc_randomizer_disable(mtd); | 894 | sunxi_nfc_randomizer_disable(mtd); |
| 774 | if (ret) | 895 | if (ret) |
| 775 | return ret; | 896 | return ret; |
| 776 | 897 | ||
| 777 | *cur_off = oob_off + ecc->bytes + 4; | 898 | *cur_off = oob_off + ecc->bytes + 4; |
| 778 | 899 | ||
| 779 | status = readl(nfc->regs + NFC_REG_ECC_ST); | 900 | ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0, |
| 780 | if (status & NFC_ECC_PAT_FOUND(0)) { | 901 | &erased); |
| 781 | u8 pattern = 0xff; | 902 | if (erased) |
| 782 | |||
| 783 | if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) | ||
| 784 | pattern = 0x0; | ||
| 785 | |||
| 786 | memset(data, pattern, ecc->size); | ||
| 787 | memset(oob, pattern, ecc->bytes + 4); | ||
| 788 | |||
| 789 | return 1; | 903 | return 1; |
| 790 | } | ||
| 791 | |||
| 792 | ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0))); | ||
| 793 | |||
| 794 | memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); | ||
| 795 | |||
| 796 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); | ||
| 797 | sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page); | ||
| 798 | 904 | ||
| 799 | if (status & NFC_ECC_ERR(0)) { | 905 | if (ret < 0) { |
| 800 | /* | 906 | /* |
| 801 | * Re-read the data with the randomizer disabled to identify | 907 | * Re-read the data with the randomizer disabled to identify |
| 802 | * bitflips in erased pages. | 908 | * bitflips in erased pages. |
| @@ -804,35 +910,34 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, | |||
| 804 | if (nand->options & NAND_NEED_SCRAMBLING) { | 910 | if (nand->options & NAND_NEED_SCRAMBLING) { |
| 805 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); | 911 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); |
| 806 | nand->read_buf(mtd, data, ecc->size); | 912 | nand->read_buf(mtd, data, ecc->size); |
| 807 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); | 913 | } else { |
| 808 | nand->read_buf(mtd, oob, ecc->bytes + 4); | 914 | memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, |
| 915 | ecc->size); | ||
| 809 | } | 916 | } |
| 810 | 917 | ||
| 918 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); | ||
| 919 | nand->read_buf(mtd, oob, ecc->bytes + 4); | ||
| 920 | |||
| 811 | ret = nand_check_erased_ecc_chunk(data, ecc->size, | 921 | ret = nand_check_erased_ecc_chunk(data, ecc->size, |
| 812 | oob, ecc->bytes + 4, | 922 | oob, ecc->bytes + 4, |
| 813 | NULL, 0, ecc->strength); | 923 | NULL, 0, ecc->strength); |
| 814 | if (ret >= 0) | 924 | if (ret >= 0) |
| 815 | raw_mode = 1; | 925 | raw_mode = 1; |
| 816 | } else { | 926 | } else { |
| 817 | /* | 927 | memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); |
| 818 | * The engine protects 4 bytes of OOB data per chunk. | ||
| 819 | * Retrieve the corrected OOB bytes. | ||
| 820 | */ | ||
| 821 | sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)), | ||
| 822 | oob); | ||
| 823 | 928 | ||
| 824 | /* De-randomize the Bad Block Marker. */ | 929 | if (oob_required) { |
| 825 | if (bbm && nand->options & NAND_NEED_SCRAMBLING) | 930 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); |
| 826 | sunxi_nfc_randomize_bbm(mtd, page, oob); | 931 | sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, |
| 827 | } | 932 | true, page); |
| 828 | 933 | ||
| 829 | if (ret < 0) { | 934 | sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0, |
| 830 | mtd->ecc_stats.failed++; | 935 | bbm, page); |
| 831 | } else { | 936 | } |
| 832 | mtd->ecc_stats.corrected += ret; | ||
| 833 | *max_bitflips = max_t(unsigned int, *max_bitflips, ret); | ||
| 834 | } | 937 | } |
| 835 | 938 | ||
| 939 | sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret); | ||
| 940 | |||
| 836 | return raw_mode; | 941 | return raw_mode; |
| 837 | } | 942 | } |
| 838 | 943 | ||
| @@ -848,7 +953,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, | |||
| 848 | if (len <= 0) | 953 | if (len <= 0) |
| 849 | return; | 954 | return; |
| 850 | 955 | ||
| 851 | if (*cur_off != offset) | 956 | if (!cur_off || *cur_off != offset) |
| 852 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, | 957 | nand->cmdfunc(mtd, NAND_CMD_RNDOUT, |
| 853 | offset + mtd->writesize, -1); | 958 | offset + mtd->writesize, -1); |
| 854 | 959 | ||
| @@ -858,12 +963,8 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, | |||
| 858 | sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, | 963 | sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, |
| 859 | false, page); | 964 | false, page); |
| 860 | 965 | ||
| 861 | *cur_off = mtd->oobsize + mtd->writesize; | 966 | if (cur_off) |
| 862 | } | 967 | *cur_off = mtd->oobsize + mtd->writesize; |
| 863 | |||
| 864 | static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) | ||
| 865 | { | ||
| 866 | return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); | ||
| 867 | } | 968 | } |
| 868 | 969 | ||
| 869 | static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, | 970 | static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, |
| @@ -882,19 +983,6 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, | |||
| 882 | 983 | ||
| 883 | sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); | 984 | sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); |
| 884 | 985 | ||
| 885 | /* Fill OOB data in */ | ||
| 886 | if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) { | ||
| 887 | u8 user_data[4]; | ||
| 888 | |||
| 889 | memcpy(user_data, oob, 4); | ||
| 890 | sunxi_nfc_randomize_bbm(mtd, page, user_data); | ||
| 891 | writel(sunxi_nfc_buf_to_user_data(user_data), | ||
| 892 | nfc->regs + NFC_REG_USER_DATA(0)); | ||
| 893 | } else { | ||
| 894 | writel(sunxi_nfc_buf_to_user_data(oob), | ||
| 895 | nfc->regs + NFC_REG_USER_DATA(0)); | ||
| 896 | } | ||
| 897 | |||
| 898 | if (data_off + ecc->size != oob_off) | 986 | if (data_off + ecc->size != oob_off) |
| 899 | nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1); | 987 | nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1); |
| 900 | 988 | ||
| @@ -903,11 +991,13 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, | |||
| 903 | return ret; | 991 | return ret; |
| 904 | 992 | ||
| 905 | sunxi_nfc_randomizer_enable(mtd); | 993 | sunxi_nfc_randomizer_enable(mtd); |
| 994 | sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page); | ||
| 995 | |||
| 906 | writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | | 996 | writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | |
| 907 | NFC_ACCESS_DIR | NFC_ECC_OP, | 997 | NFC_ACCESS_DIR | NFC_ECC_OP, |
| 908 | nfc->regs + NFC_REG_CMD); | 998 | nfc->regs + NFC_REG_CMD); |
| 909 | 999 | ||
| 910 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | 1000 | ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); |
| 911 | sunxi_nfc_randomizer_disable(mtd); | 1001 | sunxi_nfc_randomizer_disable(mtd); |
| 912 | if (ret) | 1002 | if (ret) |
| 913 | return ret; | 1003 | return ret; |
| @@ -929,13 +1019,14 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, | |||
| 929 | if (len <= 0) | 1019 | if (len <= 0) |
| 930 | return; | 1020 | return; |
| 931 | 1021 | ||
| 932 | if (*cur_off != offset) | 1022 | if (!cur_off || *cur_off != offset) |
| 933 | nand->cmdfunc(mtd, NAND_CMD_RNDIN, | 1023 | nand->cmdfunc(mtd, NAND_CMD_RNDIN, |
| 934 | offset + mtd->writesize, -1); | 1024 | offset + mtd->writesize, -1); |
| 935 | 1025 | ||
| 936 | sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); | 1026 | sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); |
| 937 | 1027 | ||
| 938 | *cur_off = mtd->oobsize + mtd->writesize; | 1028 | if (cur_off) |
| 1029 | *cur_off = mtd->oobsize + mtd->writesize; | ||
| 939 | } | 1030 | } |
| 940 | 1031 | ||
| 941 | static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, | 1032 | static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, |
| @@ -958,7 +1049,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, | |||
| 958 | ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, | 1049 | ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, |
| 959 | oob_off + mtd->writesize, | 1050 | oob_off + mtd->writesize, |
| 960 | &cur_off, &max_bitflips, | 1051 | &cur_off, &max_bitflips, |
| 961 | !i, page); | 1052 | !i, oob_required, page); |
| 962 | if (ret < 0) | 1053 | if (ret < 0) |
| 963 | return ret; | 1054 | return ret; |
| 964 | else if (ret) | 1055 | else if (ret) |
| @@ -974,6 +1065,39 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, | |||
| 974 | return max_bitflips; | 1065 | return max_bitflips; |
| 975 | } | 1066 | } |
| 976 | 1067 | ||
| 1068 | static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, | ||
| 1069 | struct nand_chip *chip, | ||
| 1070 | u32 data_offs, u32 readlen, | ||
| 1071 | u8 *bufpoi, int page) | ||
| 1072 | { | ||
| 1073 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 1074 | int ret, i, cur_off = 0; | ||
| 1075 | unsigned int max_bitflips = 0; | ||
| 1076 | |||
| 1077 | sunxi_nfc_hw_ecc_enable(mtd); | ||
| 1078 | |||
| 1079 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
| 1080 | for (i = data_offs / ecc->size; | ||
| 1081 | i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { | ||
| 1082 | int data_off = i * ecc->size; | ||
| 1083 | int oob_off = i * (ecc->bytes + 4); | ||
| 1084 | u8 *data = bufpoi + data_off; | ||
| 1085 | u8 *oob = chip->oob_poi + oob_off; | ||
| 1086 | |||
| 1087 | ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, | ||
| 1088 | oob, | ||
| 1089 | oob_off + mtd->writesize, | ||
| 1090 | &cur_off, &max_bitflips, !i, | ||
| 1091 | false, page); | ||
| 1092 | if (ret < 0) | ||
| 1093 | return ret; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | sunxi_nfc_hw_ecc_disable(mtd); | ||
| 1097 | |||
| 1098 | return max_bitflips; | ||
| 1099 | } | ||
| 1100 | |||
| 977 | static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, | 1101 | static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, |
| 978 | struct nand_chip *chip, | 1102 | struct nand_chip *chip, |
| 979 | const uint8_t *buf, int oob_required, | 1103 | const uint8_t *buf, int oob_required, |
| @@ -1026,7 +1150,9 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, | |||
| 1026 | 1150 | ||
| 1027 | ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, | 1151 | ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, |
| 1028 | oob_off, &cur_off, | 1152 | oob_off, &cur_off, |
| 1029 | &max_bitflips, !i, page); | 1153 | &max_bitflips, !i, |
| 1154 | oob_required, | ||
| 1155 | page); | ||
| 1030 | if (ret < 0) | 1156 | if (ret < 0) |
| 1031 | return ret; | 1157 | return ret; |
| 1032 | else if (ret) | 1158 | else if (ret) |
| @@ -1074,6 +1200,40 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, | |||
| 1074 | return 0; | 1200 | return 0; |
| 1075 | } | 1201 | } |
| 1076 | 1202 | ||
| 1203 | static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd, | ||
| 1204 | struct nand_chip *chip, | ||
| 1205 | int page) | ||
| 1206 | { | ||
| 1207 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
| 1208 | |||
| 1209 | chip->pagebuf = -1; | ||
| 1210 | |||
| 1211 | return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page); | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd, | ||
| 1215 | struct nand_chip *chip, | ||
| 1216 | int page) | ||
| 1217 | { | ||
| 1218 | int ret, status; | ||
| 1219 | |||
| 1220 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page); | ||
| 1221 | |||
| 1222 | chip->pagebuf = -1; | ||
| 1223 | |||
| 1224 | memset(chip->buffers->databuf, 0xff, mtd->writesize); | ||
| 1225 | ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page); | ||
| 1226 | if (ret) | ||
| 1227 | return ret; | ||
| 1228 | |||
| 1229 | /* Send command to program the OOB data */ | ||
| 1230 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
| 1231 | |||
| 1232 | status = chip->waitfunc(mtd, chip); | ||
| 1233 | |||
| 1234 | return status & NAND_STATUS_FAIL ? -EIO : 0; | ||
| 1235 | } | ||
| 1236 | |||
| 1077 | static const s32 tWB_lut[] = {6, 12, 16, 20}; | 1237 | static const s32 tWB_lut[] = {6, 12, 16, 20}; |
| 1078 | static const s32 tRHW_lut[] = {4, 8, 12, 20}; | 1238 | static const s32 tRHW_lut[] = {4, 8, 12, 20}; |
| 1079 | 1239 | ||
| @@ -1101,6 +1261,7 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, | |||
| 1101 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); | 1261 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); |
| 1102 | u32 min_clk_period = 0; | 1262 | u32 min_clk_period = 0; |
| 1103 | s32 tWB, tADL, tWHR, tRHW, tCAD; | 1263 | s32 tWB, tADL, tWHR, tRHW, tCAD; |
| 1264 | long real_clk_rate; | ||
| 1104 | 1265 | ||
| 1105 | /* T1 <=> tCLS */ | 1266 | /* T1 <=> tCLS */ |
| 1106 | if (timings->tCLS_min > min_clk_period) | 1267 | if (timings->tCLS_min > min_clk_period) |
| @@ -1163,6 +1324,18 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, | |||
| 1163 | min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); | 1324 | min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); |
| 1164 | 1325 | ||
| 1165 | /* T16 - T19 + tCAD */ | 1326 | /* T16 - T19 + tCAD */ |
| 1327 | if (timings->tWB_max > (min_clk_period * 20)) | ||
| 1328 | min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20); | ||
| 1329 | |||
| 1330 | if (timings->tADL_min > (min_clk_period * 32)) | ||
| 1331 | min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32); | ||
| 1332 | |||
| 1333 | if (timings->tWHR_min > (min_clk_period * 32)) | ||
| 1334 | min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32); | ||
| 1335 | |||
| 1336 | if (timings->tRHW_min > (min_clk_period * 20)) | ||
| 1337 | min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20); | ||
| 1338 | |||
| 1166 | tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, | 1339 | tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, |
| 1167 | min_clk_period); | 1340 | min_clk_period); |
| 1168 | if (tWB < 0) { | 1341 | if (tWB < 0) { |
| @@ -1198,23 +1371,26 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, | |||
| 1198 | /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ | 1371 | /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ |
| 1199 | chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); | 1372 | chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); |
| 1200 | 1373 | ||
| 1201 | /* | ||
| 1202 | * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data | ||
| 1203 | * output cycle timings shall be used if the host drives tRC less than | ||
| 1204 | * 30 ns. | ||
| 1205 | */ | ||
| 1206 | chip->timing_ctl = (timings->tRC_min < 30000) ? NFC_TIMING_CTL_EDO : 0; | ||
| 1207 | |||
| 1208 | /* Convert min_clk_period from picoseconds to nanoseconds */ | 1374 | /* Convert min_clk_period from picoseconds to nanoseconds */ |
| 1209 | min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); | 1375 | min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); |
| 1210 | 1376 | ||
| 1211 | /* | 1377 | /* |
| 1212 | * Convert min_clk_period into a clk frequency, then get the | 1378 | * Unlike what is stated in Allwinner datasheet, the clk_rate should |
| 1213 | * appropriate rate for the NAND controller IP given this formula | 1379 | * be set to (1 / min_clk_period), and not (2 / min_clk_period). |
| 1214 | * (specified in the datasheet): | 1380 | * This new formula was verified with a scope and validated by |
| 1215 | * nand clk_rate = 2 * min_clk_rate | 1381 | * Allwinner engineers. |
| 1216 | */ | 1382 | */ |
| 1217 | chip->clk_rate = (2 * NSEC_PER_SEC) / min_clk_period; | 1383 | chip->clk_rate = NSEC_PER_SEC / min_clk_period; |
| 1384 | real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate); | ||
| 1385 | |||
| 1386 | /* | ||
| 1387 | * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data | ||
| 1388 | * output cycle timings shall be used if the host drives tRC less than | ||
| 1389 | * 30 ns. | ||
| 1390 | */ | ||
| 1391 | min_clk_period = NSEC_PER_SEC / real_clk_rate; | ||
| 1392 | chip->timing_ctl = ((min_clk_period * 2) < 30) ? | ||
| 1393 | NFC_TIMING_CTL_EDO : 0; | ||
| 1218 | 1394 | ||
| 1219 | return 0; | 1395 | return 0; |
| 1220 | } | 1396 | } |
| @@ -1257,6 +1433,57 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip, | |||
| 1257 | return sunxi_nand_chip_set_timings(chip, timings); | 1433 | return sunxi_nand_chip_set_timings(chip, timings); |
| 1258 | } | 1434 | } |
| 1259 | 1435 | ||
| 1436 | static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 1437 | struct mtd_oob_region *oobregion) | ||
| 1438 | { | ||
| 1439 | struct nand_chip *nand = mtd_to_nand(mtd); | ||
| 1440 | struct nand_ecc_ctrl *ecc = &nand->ecc; | ||
| 1441 | |||
| 1442 | if (section >= ecc->steps) | ||
| 1443 | return -ERANGE; | ||
| 1444 | |||
| 1445 | oobregion->offset = section * (ecc->bytes + 4) + 4; | ||
| 1446 | oobregion->length = ecc->bytes; | ||
| 1447 | |||
| 1448 | return 0; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 1452 | struct mtd_oob_region *oobregion) | ||
| 1453 | { | ||
| 1454 | struct nand_chip *nand = mtd_to_nand(mtd); | ||
| 1455 | struct nand_ecc_ctrl *ecc = &nand->ecc; | ||
| 1456 | |||
| 1457 | if (section > ecc->steps) | ||
| 1458 | return -ERANGE; | ||
| 1459 | |||
| 1460 | /* | ||
| 1461 | * The first 2 bytes are used for BB markers, hence we | ||
| 1462 | * only have 2 bytes available in the first user data | ||
| 1463 | * section. | ||
| 1464 | */ | ||
| 1465 | if (!section && ecc->mode == NAND_ECC_HW) { | ||
| 1466 | oobregion->offset = 2; | ||
| 1467 | oobregion->length = 2; | ||
| 1468 | |||
| 1469 | return 0; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | oobregion->offset = section * (ecc->bytes + 4); | ||
| 1473 | |||
| 1474 | if (section < ecc->steps) | ||
| 1475 | oobregion->length = 4; | ||
| 1476 | else | ||
| 1477 | oobregion->offset = mtd->oobsize - oobregion->offset; | ||
| 1478 | |||
| 1479 | return 0; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops = { | ||
| 1483 | .ecc = sunxi_nand_ooblayout_ecc, | ||
| 1484 | .free = sunxi_nand_ooblayout_free, | ||
| 1485 | }; | ||
| 1486 | |||
| 1260 | static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, | 1487 | static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, |
| 1261 | struct nand_ecc_ctrl *ecc, | 1488 | struct nand_ecc_ctrl *ecc, |
| 1262 | struct device_node *np) | 1489 | struct device_node *np) |
| @@ -1266,7 +1493,6 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1266 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | 1493 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); |
| 1267 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | 1494 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); |
| 1268 | struct sunxi_nand_hw_ecc *data; | 1495 | struct sunxi_nand_hw_ecc *data; |
| 1269 | struct nand_ecclayout *layout; | ||
| 1270 | int nsectors; | 1496 | int nsectors; |
| 1271 | int ret; | 1497 | int ret; |
| 1272 | int i; | 1498 | int i; |
| @@ -1295,7 +1521,6 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1295 | /* HW ECC always work with even numbers of ECC bytes */ | 1521 | /* HW ECC always work with even numbers of ECC bytes */ |
| 1296 | ecc->bytes = ALIGN(ecc->bytes, 2); | 1522 | ecc->bytes = ALIGN(ecc->bytes, 2); |
| 1297 | 1523 | ||
| 1298 | layout = &data->layout; | ||
| 1299 | nsectors = mtd->writesize / ecc->size; | 1524 | nsectors = mtd->writesize / ecc->size; |
| 1300 | 1525 | ||
| 1301 | if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) { | 1526 | if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) { |
| @@ -1303,9 +1528,9 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1303 | goto err; | 1528 | goto err; |
| 1304 | } | 1529 | } |
| 1305 | 1530 | ||
| 1306 | layout->eccbytes = (ecc->bytes * nsectors); | 1531 | ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob; |
| 1307 | 1532 | ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob; | |
| 1308 | ecc->layout = layout; | 1533 | mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops); |
| 1309 | ecc->priv = data; | 1534 | ecc->priv = data; |
| 1310 | 1535 | ||
| 1311 | return 0; | 1536 | return 0; |
| @@ -1325,9 +1550,6 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1325 | struct nand_ecc_ctrl *ecc, | 1550 | struct nand_ecc_ctrl *ecc, |
| 1326 | struct device_node *np) | 1551 | struct device_node *np) |
| 1327 | { | 1552 | { |
| 1328 | struct nand_ecclayout *layout; | ||
| 1329 | int nsectors; | ||
| 1330 | int i, j; | ||
| 1331 | int ret; | 1553 | int ret; |
| 1332 | 1554 | ||
| 1333 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); | 1555 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); |
| @@ -1336,40 +1558,9 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1336 | 1558 | ||
| 1337 | ecc->read_page = sunxi_nfc_hw_ecc_read_page; | 1559 | ecc->read_page = sunxi_nfc_hw_ecc_read_page; |
| 1338 | ecc->write_page = sunxi_nfc_hw_ecc_write_page; | 1560 | ecc->write_page = sunxi_nfc_hw_ecc_write_page; |
| 1339 | layout = ecc->layout; | 1561 | ecc->read_oob_raw = nand_read_oob_std; |
| 1340 | nsectors = mtd->writesize / ecc->size; | 1562 | ecc->write_oob_raw = nand_write_oob_std; |
| 1341 | 1563 | ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage; | |
| 1342 | for (i = 0; i < nsectors; i++) { | ||
| 1343 | if (i) { | ||
| 1344 | layout->oobfree[i].offset = | ||
| 1345 | layout->oobfree[i - 1].offset + | ||
| 1346 | layout->oobfree[i - 1].length + | ||
| 1347 | ecc->bytes; | ||
| 1348 | layout->oobfree[i].length = 4; | ||
| 1349 | } else { | ||
| 1350 | /* | ||
| 1351 | * The first 2 bytes are used for BB markers, hence we | ||
| 1352 | * only have 2 bytes available in the first user data | ||
| 1353 | * section. | ||
| 1354 | */ | ||
| 1355 | layout->oobfree[i].length = 2; | ||
| 1356 | layout->oobfree[i].offset = 2; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | for (j = 0; j < ecc->bytes; j++) | ||
| 1360 | layout->eccpos[(ecc->bytes * i) + j] = | ||
| 1361 | layout->oobfree[i].offset + | ||
| 1362 | layout->oobfree[i].length + j; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | if (mtd->oobsize > (ecc->bytes + 4) * nsectors) { | ||
| 1366 | layout->oobfree[nsectors].offset = | ||
| 1367 | layout->oobfree[nsectors - 1].offset + | ||
| 1368 | layout->oobfree[nsectors - 1].length + | ||
| 1369 | ecc->bytes; | ||
| 1370 | layout->oobfree[nsectors].length = mtd->oobsize - | ||
| 1371 | ((ecc->bytes + 4) * nsectors); | ||
| 1372 | } | ||
| 1373 | 1564 | ||
| 1374 | return 0; | 1565 | return 0; |
| 1375 | } | 1566 | } |
| @@ -1378,9 +1569,6 @@ static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1378 | struct nand_ecc_ctrl *ecc, | 1569 | struct nand_ecc_ctrl *ecc, |
| 1379 | struct device_node *np) | 1570 | struct device_node *np) |
| 1380 | { | 1571 | { |
| 1381 | struct nand_ecclayout *layout; | ||
| 1382 | int nsectors; | ||
| 1383 | int i; | ||
| 1384 | int ret; | 1572 | int ret; |
| 1385 | 1573 | ||
| 1386 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); | 1574 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); |
| @@ -1390,15 +1578,8 @@ static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, | |||
| 1390 | ecc->prepad = 4; | 1578 | ecc->prepad = 4; |
| 1391 | ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page; | 1579 | ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page; |
| 1392 | ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page; | 1580 | ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page; |
| 1393 | 1581 | ecc->read_oob_raw = nand_read_oob_syndrome; | |
| 1394 | layout = ecc->layout; | 1582 | ecc->write_oob_raw = nand_write_oob_syndrome; |
| 1395 | nsectors = mtd->writesize / ecc->size; | ||
| 1396 | |||
| 1397 | for (i = 0; i < (ecc->bytes * nsectors); i++) | ||
| 1398 | layout->eccpos[i] = i; | ||
| 1399 | |||
| 1400 | layout->oobfree[0].length = mtd->oobsize - i; | ||
| 1401 | layout->oobfree[0].offset = i; | ||
| 1402 | 1583 | ||
| 1403 | return 0; | 1584 | return 0; |
| 1404 | } | 1585 | } |
| @@ -1411,7 +1592,6 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) | |||
| 1411 | sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc); | 1592 | sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc); |
| 1412 | break; | 1593 | break; |
| 1413 | case NAND_ECC_NONE: | 1594 | case NAND_ECC_NONE: |
| 1414 | kfree(ecc->layout); | ||
| 1415 | default: | 1595 | default: |
| 1416 | break; | 1596 | break; |
| 1417 | } | 1597 | } |
| @@ -1432,8 +1612,6 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, | |||
| 1432 | return -EINVAL; | 1612 | return -EINVAL; |
| 1433 | 1613 | ||
| 1434 | switch (ecc->mode) { | 1614 | switch (ecc->mode) { |
| 1435 | case NAND_ECC_SOFT_BCH: | ||
| 1436 | break; | ||
| 1437 | case NAND_ECC_HW: | 1615 | case NAND_ECC_HW: |
| 1438 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); | 1616 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); |
| 1439 | if (ret) | 1617 | if (ret) |
| @@ -1445,10 +1623,6 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, | |||
| 1445 | return ret; | 1623 | return ret; |
| 1446 | break; | 1624 | break; |
| 1447 | case NAND_ECC_NONE: | 1625 | case NAND_ECC_NONE: |
| 1448 | ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL); | ||
| 1449 | if (!ecc->layout) | ||
| 1450 | return -ENOMEM; | ||
| 1451 | ecc->layout->oobfree[0].length = mtd->oobsize; | ||
| 1452 | case NAND_ECC_SOFT: | 1626 | case NAND_ECC_SOFT: |
| 1453 | break; | 1627 | break; |
| 1454 | default: | 1628 | default: |
| @@ -1536,21 +1710,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, | |||
| 1536 | } | 1710 | } |
| 1537 | } | 1711 | } |
| 1538 | 1712 | ||
| 1539 | timings = onfi_async_timing_mode_to_sdr_timings(0); | ||
| 1540 | if (IS_ERR(timings)) { | ||
| 1541 | ret = PTR_ERR(timings); | ||
| 1542 | dev_err(dev, | ||
| 1543 | "could not retrieve timings for ONFI mode 0: %d\n", | ||
| 1544 | ret); | ||
| 1545 | return ret; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | ret = sunxi_nand_chip_set_timings(chip, timings); | ||
| 1549 | if (ret) { | ||
| 1550 | dev_err(dev, "could not configure chip timings: %d\n", ret); | ||
| 1551 | return ret; | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | nand = &chip->nand; | 1713 | nand = &chip->nand; |
| 1555 | /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ | 1714 | /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ |
| 1556 | nand->chip_delay = 200; | 1715 | nand->chip_delay = 200; |
| @@ -1570,6 +1729,21 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, | |||
| 1570 | mtd = nand_to_mtd(nand); | 1729 | mtd = nand_to_mtd(nand); |
| 1571 | mtd->dev.parent = dev; | 1730 | mtd->dev.parent = dev; |
| 1572 | 1731 | ||
| 1732 | timings = onfi_async_timing_mode_to_sdr_timings(0); | ||
| 1733 | if (IS_ERR(timings)) { | ||
| 1734 | ret = PTR_ERR(timings); | ||
| 1735 | dev_err(dev, | ||
| 1736 | "could not retrieve timings for ONFI mode 0: %d\n", | ||
| 1737 | ret); | ||
| 1738 | return ret; | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | ret = sunxi_nand_chip_set_timings(chip, timings); | ||
| 1742 | if (ret) { | ||
| 1743 | dev_err(dev, "could not configure chip timings: %d\n", ret); | ||
| 1744 | return ret; | ||
| 1745 | } | ||
| 1746 | |||
| 1573 | ret = nand_scan_ident(mtd, nsels, NULL); | 1747 | ret = nand_scan_ident(mtd, nsels, NULL); |
| 1574 | if (ret) | 1748 | if (ret) |
| 1575 | return ret; | 1749 | return ret; |
| @@ -1580,6 +1754,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, | |||
| 1580 | if (nand->options & NAND_NEED_SCRAMBLING) | 1754 | if (nand->options & NAND_NEED_SCRAMBLING) |
| 1581 | nand->options |= NAND_NO_SUBPAGE_WRITE; | 1755 | nand->options |= NAND_NO_SUBPAGE_WRITE; |
| 1582 | 1756 | ||
| 1757 | nand->options |= NAND_SUBPAGE_READ; | ||
| 1758 | |||
| 1583 | ret = sunxi_nand_chip_init_timings(chip, np); | 1759 | ret = sunxi_nand_chip_init_timings(chip, np); |
| 1584 | if (ret) { | 1760 | if (ret) { |
| 1585 | dev_err(dev, "could not configure chip timings: %d\n", ret); | 1761 | dev_err(dev, "could not configure chip timings: %d\n", ret); |
| @@ -1728,6 +1904,8 @@ static int sunxi_nfc_remove(struct platform_device *pdev) | |||
| 1728 | struct sunxi_nfc *nfc = platform_get_drvdata(pdev); | 1904 | struct sunxi_nfc *nfc = platform_get_drvdata(pdev); |
| 1729 | 1905 | ||
| 1730 | sunxi_nand_chips_cleanup(nfc); | 1906 | sunxi_nand_chips_cleanup(nfc); |
| 1907 | clk_disable_unprepare(nfc->mod_clk); | ||
| 1908 | clk_disable_unprepare(nfc->ahb_clk); | ||
| 1731 | 1909 | ||
| 1732 | return 0; | 1910 | return 0; |
| 1733 | } | 1911 | } |
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 293feb19b0b1..3ad514c44dcb 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/mtd/mtd.h> | 33 | #include <linux/mtd/mtd.h> |
| 34 | #include <linux/mtd/nand.h> | 34 | #include <linux/mtd/nand.h> |
| 35 | #include <linux/mtd/partitions.h> | 35 | #include <linux/mtd/partitions.h> |
| 36 | #include <linux/of_mtd.h> | ||
| 37 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
| 38 | #include <linux/pinctrl/consumer.h> | 37 | #include <linux/pinctrl/consumer.h> |
| 39 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
| @@ -175,34 +174,6 @@ static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd) | |||
| 175 | return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip); | 174 | return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip); |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | static struct nand_ecclayout vf610_nfc_ecc45 = { | ||
| 179 | .eccbytes = 45, | ||
| 180 | .eccpos = {19, 20, 21, 22, 23, | ||
| 181 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 182 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 183 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 184 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 185 | 56, 57, 58, 59, 60, 61, 62, 63}, | ||
| 186 | .oobfree = { | ||
| 187 | {.offset = 2, | ||
| 188 | .length = 17} } | ||
| 189 | }; | ||
| 190 | |||
| 191 | static struct nand_ecclayout vf610_nfc_ecc60 = { | ||
| 192 | .eccbytes = 60, | ||
| 193 | .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11, | ||
| 194 | 12, 13, 14, 15, 16, 17, 18, 19, | ||
| 195 | 20, 21, 22, 23, 24, 25, 26, 27, | ||
| 196 | 28, 29, 30, 31, 32, 33, 34, 35, | ||
| 197 | 36, 37, 38, 39, 40, 41, 42, 43, | ||
| 198 | 44, 45, 46, 47, 48, 49, 50, 51, | ||
| 199 | 52, 53, 54, 55, 56, 57, 58, 59, | ||
| 200 | 60, 61, 62, 63 }, | ||
| 201 | .oobfree = { | ||
| 202 | {.offset = 2, | ||
| 203 | .length = 2} } | ||
| 204 | }; | ||
| 205 | |||
| 206 | static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg) | 177 | static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg) |
| 207 | { | 178 | { |
| 208 | return readl(nfc->regs + reg); | 179 | return readl(nfc->regs + reg); |
| @@ -781,14 +752,16 @@ static int vf610_nfc_probe(struct platform_device *pdev) | |||
| 781 | if (mtd->oobsize > 64) | 752 | if (mtd->oobsize > 64) |
| 782 | mtd->oobsize = 64; | 753 | mtd->oobsize = 64; |
| 783 | 754 | ||
| 755 | /* | ||
| 756 | * mtd->ecclayout is not specified here because we're using the | ||
| 757 | * default large page ECC layout defined in NAND core. | ||
| 758 | */ | ||
| 784 | if (chip->ecc.strength == 32) { | 759 | if (chip->ecc.strength == 32) { |
| 785 | nfc->ecc_mode = ECC_60_BYTE; | 760 | nfc->ecc_mode = ECC_60_BYTE; |
| 786 | chip->ecc.bytes = 60; | 761 | chip->ecc.bytes = 60; |
| 787 | chip->ecc.layout = &vf610_nfc_ecc60; | ||
| 788 | } else if (chip->ecc.strength == 24) { | 762 | } else if (chip->ecc.strength == 24) { |
| 789 | nfc->ecc_mode = ECC_45_BYTE; | 763 | nfc->ecc_mode = ECC_45_BYTE; |
| 790 | chip->ecc.bytes = 45; | 764 | chip->ecc.bytes = 45; |
| 791 | chip->ecc.layout = &vf610_nfc_ecc45; | ||
| 792 | } else { | 765 | } else { |
| 793 | dev_err(nfc->dev, "Unsupported ECC strength\n"); | 766 | dev_err(nfc->dev, "Unsupported ECC strength\n"); |
| 794 | err = -ENXIO; | 767 | err = -ENXIO; |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index af28bb3ae7cf..a4b029a417f0 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
| @@ -68,21 +68,33 @@ MODULE_PARM_DESC(otp, "Corresponding behaviour of OneNAND in OTP" | |||
| 68 | * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page | 68 | * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page |
| 69 | * For now, we expose only 64 out of 80 ecc bytes | 69 | * For now, we expose only 64 out of 80 ecc bytes |
| 70 | */ | 70 | */ |
| 71 | static struct nand_ecclayout flexonenand_oob_128 = { | 71 | static int flexonenand_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 72 | .eccbytes = 64, | 72 | struct mtd_oob_region *oobregion) |
| 73 | .eccpos = { | 73 | { |
| 74 | 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | 74 | if (section > 7) |
| 75 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, | 75 | return -ERANGE; |
| 76 | 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, | 76 | |
| 77 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, | 77 | oobregion->offset = (section * 16) + 6; |
| 78 | 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, | 78 | oobregion->length = 10; |
| 79 | 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, | 79 | |
| 80 | 102, 103, 104, 105 | 80 | return 0; |
| 81 | }, | 81 | } |
| 82 | .oobfree = { | 82 | |
| 83 | {2, 4}, {18, 4}, {34, 4}, {50, 4}, | 83 | static int flexonenand_ooblayout_free(struct mtd_info *mtd, int section, |
| 84 | {66, 4}, {82, 4}, {98, 4}, {114, 4} | 84 | struct mtd_oob_region *oobregion) |
| 85 | } | 85 | { |
| 86 | if (section > 7) | ||
| 87 | return -ERANGE; | ||
| 88 | |||
| 89 | oobregion->offset = (section * 16) + 2; | ||
| 90 | oobregion->length = 4; | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static const struct mtd_ooblayout_ops flexonenand_ooblayout_ops = { | ||
| 96 | .ecc = flexonenand_ooblayout_ecc, | ||
| 97 | .free = flexonenand_ooblayout_free, | ||
| 86 | }; | 98 | }; |
| 87 | 99 | ||
| 88 | /* | 100 | /* |
| @@ -91,56 +103,77 @@ static struct nand_ecclayout flexonenand_oob_128 = { | |||
| 91 | * Based on specification: | 103 | * Based on specification: |
| 92 | * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010 | 104 | * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010 |
| 93 | * | 105 | * |
| 94 | * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout) | ||
| 95 | * | ||
| 96 | * oobfree uses the spare area fields marked as | ||
| 97 | * "Managed by internal ECC logic for Logical Sector Number area" | ||
| 98 | */ | 106 | */ |
| 99 | static struct nand_ecclayout onenand_oob_128 = { | 107 | static int onenand_ooblayout_128_ecc(struct mtd_info *mtd, int section, |
| 100 | .eccbytes = 64, | 108 | struct mtd_oob_region *oobregion) |
| 101 | .eccpos = { | 109 | { |
| 102 | 7, 8, 9, 10, 11, 12, 13, 14, 15, | 110 | if (section > 7) |
| 103 | 23, 24, 25, 26, 27, 28, 29, 30, 31, | 111 | return -ERANGE; |
| 104 | 39, 40, 41, 42, 43, 44, 45, 46, 47, | 112 | |
| 105 | 55, 56, 57, 58, 59, 60, 61, 62, 63, | 113 | oobregion->offset = (section * 16) + 7; |
| 106 | 71, 72, 73, 74, 75, 76, 77, 78, 79, | 114 | oobregion->length = 9; |
| 107 | 87, 88, 89, 90, 91, 92, 93, 94, 95, | 115 | |
| 108 | 103, 104, 105, 106, 107, 108, 109, 110, 111, | 116 | return 0; |
| 109 | 119 | 117 | } |
| 110 | }, | 118 | |
| 111 | .oobfree = { | 119 | static int onenand_ooblayout_128_free(struct mtd_info *mtd, int section, |
| 112 | {2, 3}, {18, 3}, {34, 3}, {50, 3}, | 120 | struct mtd_oob_region *oobregion) |
| 113 | {66, 3}, {82, 3}, {98, 3}, {114, 3} | 121 | { |
| 114 | } | 122 | if (section >= 8) |
| 123 | return -ERANGE; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * free bytes are using the spare area fields marked as | ||
| 127 | * "Managed by internal ECC logic for Logical Sector Number area" | ||
| 128 | */ | ||
| 129 | oobregion->offset = (section * 16) + 2; | ||
| 130 | oobregion->length = 3; | ||
| 131 | |||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static const struct mtd_ooblayout_ops onenand_oob_128_ooblayout_ops = { | ||
| 136 | .ecc = onenand_ooblayout_128_ecc, | ||
| 137 | .free = onenand_ooblayout_128_free, | ||
| 115 | }; | 138 | }; |
| 116 | 139 | ||
| 117 | /** | 140 | /** |
| 118 | * onenand_oob_64 - oob info for large (2KB) page | 141 | * onenand_oob_32_64 - oob info for large (2KB) page |
| 119 | */ | 142 | */ |
| 120 | static struct nand_ecclayout onenand_oob_64 = { | 143 | static int onenand_ooblayout_32_64_ecc(struct mtd_info *mtd, int section, |
| 121 | .eccbytes = 20, | 144 | struct mtd_oob_region *oobregion) |
| 122 | .eccpos = { | 145 | { |
| 123 | 8, 9, 10, 11, 12, | 146 | if (section > 3) |
| 124 | 24, 25, 26, 27, 28, | 147 | return -ERANGE; |
| 125 | 40, 41, 42, 43, 44, | 148 | |
| 126 | 56, 57, 58, 59, 60, | 149 | oobregion->offset = (section * 16) + 8; |
| 127 | }, | 150 | oobregion->length = 5; |
| 128 | .oobfree = { | 151 | |
| 129 | {2, 3}, {14, 2}, {18, 3}, {30, 2}, | 152 | return 0; |
| 130 | {34, 3}, {46, 2}, {50, 3}, {62, 2} | 153 | } |
| 154 | |||
| 155 | static int onenand_ooblayout_32_64_free(struct mtd_info *mtd, int section, | ||
| 156 | struct mtd_oob_region *oobregion) | ||
| 157 | { | ||
| 158 | int sections = (mtd->oobsize / 32) * 2; | ||
| 159 | |||
| 160 | if (section >= sections) | ||
| 161 | return -ERANGE; | ||
| 162 | |||
| 163 | if (section & 1) { | ||
| 164 | oobregion->offset = ((section - 1) * 16) + 14; | ||
| 165 | oobregion->length = 2; | ||
| 166 | } else { | ||
| 167 | oobregion->offset = (section * 16) + 2; | ||
| 168 | oobregion->length = 3; | ||
| 131 | } | 169 | } |
| 132 | }; | ||
| 133 | 170 | ||
| 134 | /** | 171 | return 0; |
| 135 | * onenand_oob_32 - oob info for middle (1KB) page | 172 | } |
| 136 | */ | 173 | |
| 137 | static struct nand_ecclayout onenand_oob_32 = { | 174 | static const struct mtd_ooblayout_ops onenand_oob_32_64_ooblayout_ops = { |
| 138 | .eccbytes = 10, | 175 | .ecc = onenand_ooblayout_32_64_ecc, |
| 139 | .eccpos = { | 176 | .free = onenand_ooblayout_32_64_free, |
| 140 | 8, 9, 10, 11, 12, | ||
| 141 | 24, 25, 26, 27, 28, | ||
| 142 | }, | ||
| 143 | .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } | ||
| 144 | }; | 177 | }; |
| 145 | 178 | ||
| 146 | static const unsigned char ffchars[] = { | 179 | static const unsigned char ffchars[] = { |
| @@ -1024,34 +1057,15 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col | |||
| 1024 | int thislen) | 1057 | int thislen) |
| 1025 | { | 1058 | { |
| 1026 | struct onenand_chip *this = mtd->priv; | 1059 | struct onenand_chip *this = mtd->priv; |
| 1027 | struct nand_oobfree *free; | 1060 | int ret; |
| 1028 | int readcol = column; | 1061 | |
| 1029 | int readend = column + thislen; | 1062 | this->read_bufferram(mtd, ONENAND_SPARERAM, this->oob_buf, 0, |
| 1030 | int lastgap = 0; | 1063 | mtd->oobsize); |
| 1031 | unsigned int i; | 1064 | ret = mtd_ooblayout_get_databytes(mtd, buf, this->oob_buf, |
| 1032 | uint8_t *oob_buf = this->oob_buf; | 1065 | column, thislen); |
| 1033 | 1066 | if (ret) | |
| 1034 | free = this->ecclayout->oobfree; | 1067 | return ret; |
| 1035 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | 1068 | |
| 1036 | if (readcol >= lastgap) | ||
| 1037 | readcol += free->offset - lastgap; | ||
| 1038 | if (readend >= lastgap) | ||
| 1039 | readend += free->offset - lastgap; | ||
| 1040 | lastgap = free->offset + free->length; | ||
| 1041 | } | ||
| 1042 | this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); | ||
| 1043 | free = this->ecclayout->oobfree; | ||
| 1044 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | ||
| 1045 | int free_end = free->offset + free->length; | ||
| 1046 | if (free->offset < readend && free_end > readcol) { | ||
| 1047 | int st = max_t(int,free->offset,readcol); | ||
| 1048 | int ed = min_t(int,free_end,readend); | ||
| 1049 | int n = ed - st; | ||
| 1050 | memcpy(buf, oob_buf + st, n); | ||
| 1051 | buf += n; | ||
| 1052 | } else if (column == 0) | ||
| 1053 | break; | ||
| 1054 | } | ||
| 1055 | return 0; | 1069 | return 0; |
| 1056 | } | 1070 | } |
| 1057 | 1071 | ||
| @@ -1808,34 +1822,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1808 | static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, | 1822 | static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, |
| 1809 | const u_char *buf, int column, int thislen) | 1823 | const u_char *buf, int column, int thislen) |
| 1810 | { | 1824 | { |
| 1811 | struct onenand_chip *this = mtd->priv; | 1825 | return mtd_ooblayout_set_databytes(mtd, buf, oob_buf, column, thislen); |
| 1812 | struct nand_oobfree *free; | ||
| 1813 | int writecol = column; | ||
| 1814 | int writeend = column + thislen; | ||
| 1815 | int lastgap = 0; | ||
| 1816 | unsigned int i; | ||
| 1817 | |||
| 1818 | free = this->ecclayout->oobfree; | ||
| 1819 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | ||
| 1820 | if (writecol >= lastgap) | ||
| 1821 | writecol += free->offset - lastgap; | ||
| 1822 | if (writeend >= lastgap) | ||
| 1823 | writeend += free->offset - lastgap; | ||
| 1824 | lastgap = free->offset + free->length; | ||
| 1825 | } | ||
| 1826 | free = this->ecclayout->oobfree; | ||
| 1827 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | ||
| 1828 | int free_end = free->offset + free->length; | ||
| 1829 | if (free->offset < writeend && free_end > writecol) { | ||
| 1830 | int st = max_t(int,free->offset,writecol); | ||
| 1831 | int ed = min_t(int,free_end,writeend); | ||
| 1832 | int n = ed - st; | ||
| 1833 | memcpy(oob_buf + st, buf, n); | ||
| 1834 | buf += n; | ||
| 1835 | } else if (column == 0) | ||
| 1836 | break; | ||
| 1837 | } | ||
| 1838 | return 0; | ||
| 1839 | } | 1826 | } |
| 1840 | 1827 | ||
| 1841 | /** | 1828 | /** |
| @@ -4003,22 +3990,22 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
| 4003 | switch (mtd->oobsize) { | 3990 | switch (mtd->oobsize) { |
| 4004 | case 128: | 3991 | case 128: |
| 4005 | if (FLEXONENAND(this)) { | 3992 | if (FLEXONENAND(this)) { |
| 4006 | this->ecclayout = &flexonenand_oob_128; | 3993 | mtd_set_ooblayout(mtd, &flexonenand_ooblayout_ops); |
| 4007 | mtd->subpage_sft = 0; | 3994 | mtd->subpage_sft = 0; |
| 4008 | } else { | 3995 | } else { |
| 4009 | this->ecclayout = &onenand_oob_128; | 3996 | mtd_set_ooblayout(mtd, &onenand_oob_128_ooblayout_ops); |
| 4010 | mtd->subpage_sft = 2; | 3997 | mtd->subpage_sft = 2; |
| 4011 | } | 3998 | } |
| 4012 | if (ONENAND_IS_NOP_1(this)) | 3999 | if (ONENAND_IS_NOP_1(this)) |
| 4013 | mtd->subpage_sft = 0; | 4000 | mtd->subpage_sft = 0; |
| 4014 | break; | 4001 | break; |
| 4015 | case 64: | 4002 | case 64: |
| 4016 | this->ecclayout = &onenand_oob_64; | 4003 | mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); |
| 4017 | mtd->subpage_sft = 2; | 4004 | mtd->subpage_sft = 2; |
| 4018 | break; | 4005 | break; |
| 4019 | 4006 | ||
| 4020 | case 32: | 4007 | case 32: |
| 4021 | this->ecclayout = &onenand_oob_32; | 4008 | mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); |
| 4022 | mtd->subpage_sft = 1; | 4009 | mtd->subpage_sft = 1; |
| 4023 | break; | 4010 | break; |
| 4024 | 4011 | ||
| @@ -4027,7 +4014,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
| 4027 | __func__, mtd->oobsize); | 4014 | __func__, mtd->oobsize); |
| 4028 | mtd->subpage_sft = 0; | 4015 | mtd->subpage_sft = 0; |
| 4029 | /* To prevent kernel oops */ | 4016 | /* To prevent kernel oops */ |
| 4030 | this->ecclayout = &onenand_oob_32; | 4017 | mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); |
| 4031 | break; | 4018 | break; |
| 4032 | } | 4019 | } |
| 4033 | 4020 | ||
| @@ -4037,12 +4024,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
| 4037 | * The number of bytes available for a client to place data into | 4024 | * The number of bytes available for a client to place data into |
| 4038 | * the out of band area | 4025 | * the out of band area |
| 4039 | */ | 4026 | */ |
| 4040 | mtd->oobavail = 0; | 4027 | ret = mtd_ooblayout_count_freebytes(mtd); |
| 4041 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && | 4028 | if (ret < 0) |
| 4042 | this->ecclayout->oobfree[i].length; i++) | 4029 | ret = 0; |
| 4043 | mtd->oobavail += this->ecclayout->oobfree[i].length; | 4030 | |
| 4031 | mtd->oobavail = ret; | ||
| 4044 | 4032 | ||
| 4045 | mtd->ecclayout = this->ecclayout; | ||
| 4046 | mtd->ecc_strength = 1; | 4033 | mtd->ecc_strength = 1; |
| 4047 | 4034 | ||
| 4048 | /* Fill in remaining MTD driver data */ | 4035 | /* Fill in remaining MTD driver data */ |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 157841dc3e99..c52e45594bfd 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
| @@ -832,6 +832,7 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 832 | /* GigaDevice */ | 832 | /* GigaDevice */ |
| 833 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, | 833 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, |
| 834 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, | 834 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, |
| 835 | { "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 835 | { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, | 836 | { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, |
| 836 | 837 | ||
| 837 | /* Intel/Numonyx -- xxxs33b */ | 838 | /* Intel/Numonyx -- xxxs33b */ |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index bee3fa96b981..d7efd9d458aa 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
| @@ -10,7 +10,6 @@ obj-$(CONFIG_OF_UNITTEST) += unittest.o | |||
| 10 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 10 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
| 11 | obj-$(CONFIG_OF_PCI) += of_pci.o | 11 | obj-$(CONFIG_OF_PCI) += of_pci.o |
| 12 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 12 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
| 13 | obj-$(CONFIG_OF_MTD) += of_mtd.o | ||
| 14 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o | 13 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o |
| 15 | obj-$(CONFIG_OF_RESOLVE) += resolver.o | 14 | obj-$(CONFIG_OF_RESOLVE) += resolver.o |
| 16 | obj-$(CONFIG_OF_OVERLAY) += overlay.o | 15 | obj-$(CONFIG_OF_OVERLAY) += overlay.o |
diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c deleted file mode 100644 index b7361ed70537..000000000000 --- a/drivers/of/of_mtd.c +++ /dev/null | |||
| @@ -1,119 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | ||
| 3 | * | ||
| 4 | * OF helpers for mtd. | ||
| 5 | * | ||
| 6 | * This file is released under the GPLv2 | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/of_mtd.h> | ||
| 11 | #include <linux/mtd/nand.h> | ||
| 12 | #include <linux/export.h> | ||
| 13 | |||
| 14 | /** | ||
| 15 | * It maps 'enum nand_ecc_modes_t' found in include/linux/mtd/nand.h | ||
| 16 | * into the device tree binding of 'nand-ecc', so that MTD | ||
| 17 | * device driver can get nand ecc from device tree. | ||
| 18 | */ | ||
| 19 | static const char *nand_ecc_modes[] = { | ||
| 20 | [NAND_ECC_NONE] = "none", | ||
| 21 | [NAND_ECC_SOFT] = "soft", | ||
| 22 | [NAND_ECC_HW] = "hw", | ||
| 23 | [NAND_ECC_HW_SYNDROME] = "hw_syndrome", | ||
| 24 | [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first", | ||
| 25 | [NAND_ECC_SOFT_BCH] = "soft_bch", | ||
| 26 | }; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * of_get_nand_ecc_mode - Get nand ecc mode for given device_node | ||
| 30 | * @np: Pointer to the given device_node | ||
| 31 | * | ||
| 32 | * The function gets ecc mode string from property 'nand-ecc-mode', | ||
| 33 | * and return its index in nand_ecc_modes table, or errno in error case. | ||
| 34 | */ | ||
| 35 | int of_get_nand_ecc_mode(struct device_node *np) | ||
| 36 | { | ||
| 37 | const char *pm; | ||
| 38 | int err, i; | ||
| 39 | |||
| 40 | err = of_property_read_string(np, "nand-ecc-mode", &pm); | ||
| 41 | if (err < 0) | ||
| 42 | return err; | ||
| 43 | |||
| 44 | for (i = 0; i < ARRAY_SIZE(nand_ecc_modes); i++) | ||
| 45 | if (!strcasecmp(pm, nand_ecc_modes[i])) | ||
| 46 | return i; | ||
| 47 | |||
| 48 | return -ENODEV; | ||
| 49 | } | ||
| 50 | EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode); | ||
| 51 | |||
| 52 | /** | ||
| 53 | * of_get_nand_ecc_step_size - Get ECC step size associated to | ||
| 54 | * the required ECC strength (see below). | ||
| 55 | * @np: Pointer to the given device_node | ||
| 56 | * | ||
| 57 | * return the ECC step size, or errno in error case. | ||
| 58 | */ | ||
| 59 | int of_get_nand_ecc_step_size(struct device_node *np) | ||
| 60 | { | ||
| 61 | int ret; | ||
| 62 | u32 val; | ||
| 63 | |||
| 64 | ret = of_property_read_u32(np, "nand-ecc-step-size", &val); | ||
| 65 | return ret ? ret : val; | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL_GPL(of_get_nand_ecc_step_size); | ||
| 68 | |||
| 69 | /** | ||
| 70 | * of_get_nand_ecc_strength - Get required ECC strength over the | ||
| 71 | * correspnding step size as defined by 'nand-ecc-size' | ||
| 72 | * @np: Pointer to the given device_node | ||
| 73 | * | ||
| 74 | * return the ECC strength, or errno in error case. | ||
| 75 | */ | ||
| 76 | int of_get_nand_ecc_strength(struct device_node *np) | ||
| 77 | { | ||
| 78 | int ret; | ||
| 79 | u32 val; | ||
| 80 | |||
| 81 | ret = of_property_read_u32(np, "nand-ecc-strength", &val); | ||
| 82 | return ret ? ret : val; | ||
| 83 | } | ||
| 84 | EXPORT_SYMBOL_GPL(of_get_nand_ecc_strength); | ||
| 85 | |||
| 86 | /** | ||
| 87 | * of_get_nand_bus_width - Get nand bus witdh for given device_node | ||
| 88 | * @np: Pointer to the given device_node | ||
| 89 | * | ||
| 90 | * return bus width option, or errno in error case. | ||
| 91 | */ | ||
| 92 | int of_get_nand_bus_width(struct device_node *np) | ||
| 93 | { | ||
| 94 | u32 val; | ||
| 95 | |||
| 96 | if (of_property_read_u32(np, "nand-bus-width", &val)) | ||
| 97 | return 8; | ||
| 98 | |||
| 99 | switch(val) { | ||
| 100 | case 8: | ||
| 101 | case 16: | ||
| 102 | return val; | ||
| 103 | default: | ||
| 104 | return -EIO; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | EXPORT_SYMBOL_GPL(of_get_nand_bus_width); | ||
| 108 | |||
| 109 | /** | ||
| 110 | * of_get_nand_on_flash_bbt - Get nand on flash bbt for given device_node | ||
| 111 | * @np: Pointer to the given device_node | ||
| 112 | * | ||
| 113 | * return true if present false other wise | ||
| 114 | */ | ||
| 115 | bool of_get_nand_on_flash_bbt(struct device_node *np) | ||
| 116 | { | ||
| 117 | return of_property_read_bool(np, "nand-on-flash-bbt"); | ||
| 118 | } | ||
| 119 | EXPORT_SYMBOL_GPL(of_get_nand_on_flash_bbt); | ||
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 163f21a1298d..e389009fca42 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c | |||
| @@ -42,23 +42,33 @@ static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd) | |||
| 42 | static int enable_hw_ecc; | 42 | static int enable_hw_ecc; |
| 43 | static int enable_read_hw_ecc; | 43 | static int enable_read_hw_ecc; |
| 44 | 44 | ||
| 45 | static struct nand_ecclayout spinand_oob_64 = { | 45 | static int spinand_ooblayout_64_ecc(struct mtd_info *mtd, int section, |
| 46 | .eccbytes = 24, | 46 | struct mtd_oob_region *oobregion) |
| 47 | .eccpos = { | 47 | { |
| 48 | 1, 2, 3, 4, 5, 6, | 48 | if (section > 3) |
| 49 | 17, 18, 19, 20, 21, 22, | 49 | return -ERANGE; |
| 50 | 33, 34, 35, 36, 37, 38, | 50 | |
| 51 | 49, 50, 51, 52, 53, 54, }, | 51 | oobregion->offset = (section * 16) + 1; |
| 52 | .oobfree = { | 52 | oobregion->length = 6; |
| 53 | {.offset = 8, | 53 | |
| 54 | .length = 8}, | 54 | return 0; |
| 55 | {.offset = 24, | 55 | } |
| 56 | .length = 8}, | 56 | |
| 57 | {.offset = 40, | 57 | static int spinand_ooblayout_64_free(struct mtd_info *mtd, int section, |
| 58 | .length = 8}, | 58 | struct mtd_oob_region *oobregion) |
| 59 | {.offset = 56, | 59 | { |
| 60 | .length = 8}, | 60 | if (section > 3) |
| 61 | } | 61 | return -ERANGE; |
| 62 | |||
| 63 | oobregion->offset = (section * 16) + 8; | ||
| 64 | oobregion->length = 8; | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static const struct mtd_ooblayout_ops spinand_oob_64_ops = { | ||
| 70 | .ecc = spinand_ooblayout_64_ecc, | ||
| 71 | .free = spinand_ooblayout_64_free, | ||
| 62 | }; | 72 | }; |
| 63 | #endif | 73 | #endif |
| 64 | 74 | ||
| @@ -886,11 +896,11 @@ static int spinand_probe(struct spi_device *spi_nand) | |||
| 886 | 896 | ||
| 887 | chip->ecc.strength = 1; | 897 | chip->ecc.strength = 1; |
| 888 | chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; | 898 | chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; |
| 889 | chip->ecc.layout = &spinand_oob_64; | ||
| 890 | chip->ecc.read_page = spinand_read_page_hwecc; | 899 | chip->ecc.read_page = spinand_read_page_hwecc; |
| 891 | chip->ecc.write_page = spinand_write_page_hwecc; | 900 | chip->ecc.write_page = spinand_write_page_hwecc; |
| 892 | #else | 901 | #else |
| 893 | chip->ecc.mode = NAND_ECC_SOFT; | 902 | chip->ecc.mode = NAND_ECC_SOFT; |
| 903 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 894 | if (spinand_disable_ecc(spi_nand) < 0) | 904 | if (spinand_disable_ecc(spi_nand) < 0) |
| 895 | dev_info(&spi_nand->dev, "%s: disable ecc failed!\n", | 905 | dev_info(&spi_nand->dev, "%s: disable ecc failed!\n", |
| 896 | __func__); | 906 | __func__); |
| @@ -912,6 +922,9 @@ static int spinand_probe(struct spi_device *spi_nand) | |||
| 912 | 922 | ||
| 913 | mtd->dev.parent = &spi_nand->dev; | 923 | mtd->dev.parent = &spi_nand->dev; |
| 914 | mtd->oobsize = 64; | 924 | mtd->oobsize = 64; |
| 925 | #ifdef CONFIG_MTD_SPINAND_ONDIEECC | ||
| 926 | mtd_set_ooblayout(mtd, &spinand_oob_64_ops); | ||
| 927 | #endif | ||
| 915 | 928 | ||
| 916 | if (nand_scan(mtd, 1)) | 929 | if (nand_scan(mtd, 1)) |
| 917 | return -ENXIO; | 930 | return -ENXIO; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 846513c73606..a5ac2cad5cb7 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
| @@ -587,7 +587,6 @@ struct mtd_info; | |||
| 587 | 587 | ||
| 588 | struct bcma_sflash { | 588 | struct bcma_sflash { |
| 589 | bool present; | 589 | bool present; |
| 590 | u32 window; | ||
| 591 | u32 blocksize; | 590 | u32 blocksize; |
| 592 | u16 numblocks; | 591 | u16 numblocks; |
| 593 | u32 size; | 592 | u32 size; |
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h index 0023088b253b..3f9778cbc79d 100644 --- a/include/linux/fsl_ifc.h +++ b/include/linux/fsl_ifc.h | |||
| @@ -39,6 +39,10 @@ | |||
| 39 | #define FSL_IFC_VERSION_MASK 0x0F0F0000 | 39 | #define FSL_IFC_VERSION_MASK 0x0F0F0000 |
| 40 | #define FSL_IFC_VERSION_1_0_0 0x01000000 | 40 | #define FSL_IFC_VERSION_1_0_0 0x01000000 |
| 41 | #define FSL_IFC_VERSION_1_1_0 0x01010000 | 41 | #define FSL_IFC_VERSION_1_1_0 0x01010000 |
| 42 | #define FSL_IFC_VERSION_2_0_0 0x02000000 | ||
| 43 | |||
| 44 | #define PGOFFSET_64K (64*1024) | ||
| 45 | #define PGOFFSET_4K (4*1024) | ||
| 42 | 46 | ||
| 43 | /* | 47 | /* |
| 44 | * CSPR - Chip Select Property Register | 48 | * CSPR - Chip Select Property Register |
| @@ -723,20 +727,26 @@ struct fsl_ifc_nand { | |||
| 723 | __be32 nand_evter_en; | 727 | __be32 nand_evter_en; |
| 724 | u32 res17[0x2]; | 728 | u32 res17[0x2]; |
| 725 | __be32 nand_evter_intr_en; | 729 | __be32 nand_evter_intr_en; |
| 726 | u32 res18[0x2]; | 730 | __be32 nand_vol_addr_stat; |
| 731 | u32 res18; | ||
| 727 | __be32 nand_erattr0; | 732 | __be32 nand_erattr0; |
| 728 | __be32 nand_erattr1; | 733 | __be32 nand_erattr1; |
| 729 | u32 res19[0x10]; | 734 | u32 res19[0x10]; |
| 730 | __be32 nand_fsr; | 735 | __be32 nand_fsr; |
| 731 | u32 res20; | 736 | u32 res20[0x3]; |
| 732 | __be32 nand_eccstat[4]; | 737 | __be32 nand_eccstat[6]; |
| 733 | u32 res21[0x20]; | 738 | u32 res21[0x1c]; |
| 734 | __be32 nanndcr; | 739 | __be32 nanndcr; |
| 735 | u32 res22[0x2]; | 740 | u32 res22[0x2]; |
| 736 | __be32 nand_autoboot_trgr; | 741 | __be32 nand_autoboot_trgr; |
| 737 | u32 res23; | 742 | u32 res23; |
| 738 | __be32 nand_mdr; | 743 | __be32 nand_mdr; |
| 739 | u32 res24[0x5C]; | 744 | u32 res24[0x1C]; |
| 745 | __be32 nand_dll_lowcfg0; | ||
| 746 | __be32 nand_dll_lowcfg1; | ||
| 747 | u32 res25; | ||
| 748 | __be32 nand_dll_lowstat; | ||
| 749 | u32 res26[0x3c]; | ||
| 740 | }; | 750 | }; |
| 741 | 751 | ||
| 742 | /* | 752 | /* |
| @@ -771,13 +781,12 @@ struct fsl_ifc_gpcm { | |||
| 771 | __be32 gpcm_erattr1; | 781 | __be32 gpcm_erattr1; |
| 772 | __be32 gpcm_erattr2; | 782 | __be32 gpcm_erattr2; |
| 773 | __be32 gpcm_stat; | 783 | __be32 gpcm_stat; |
| 774 | u32 res4[0x1F3]; | ||
| 775 | }; | 784 | }; |
| 776 | 785 | ||
| 777 | /* | 786 | /* |
| 778 | * IFC Controller Registers | 787 | * IFC Controller Registers |
| 779 | */ | 788 | */ |
| 780 | struct fsl_ifc_regs { | 789 | struct fsl_ifc_global { |
| 781 | __be32 ifc_rev; | 790 | __be32 ifc_rev; |
| 782 | u32 res1[0x2]; | 791 | u32 res1[0x2]; |
| 783 | struct { | 792 | struct { |
| @@ -803,21 +812,26 @@ struct fsl_ifc_regs { | |||
| 803 | } ftim_cs[FSL_IFC_BANK_COUNT]; | 812 | } ftim_cs[FSL_IFC_BANK_COUNT]; |
| 804 | u32 res9[0x30]; | 813 | u32 res9[0x30]; |
| 805 | __be32 rb_stat; | 814 | __be32 rb_stat; |
| 806 | u32 res10[0x2]; | 815 | __be32 rb_map; |
| 816 | __be32 wb_map; | ||
| 807 | __be32 ifc_gcr; | 817 | __be32 ifc_gcr; |
| 808 | u32 res11[0x2]; | 818 | u32 res10[0x2]; |
| 809 | __be32 cm_evter_stat; | 819 | __be32 cm_evter_stat; |
| 810 | u32 res12[0x2]; | 820 | u32 res11[0x2]; |
| 811 | __be32 cm_evter_en; | 821 | __be32 cm_evter_en; |
| 812 | u32 res13[0x2]; | 822 | u32 res12[0x2]; |
| 813 | __be32 cm_evter_intr_en; | 823 | __be32 cm_evter_intr_en; |
| 814 | u32 res14[0x2]; | 824 | u32 res13[0x2]; |
| 815 | __be32 cm_erattr0; | 825 | __be32 cm_erattr0; |
| 816 | __be32 cm_erattr1; | 826 | __be32 cm_erattr1; |
| 817 | u32 res15[0x2]; | 827 | u32 res14[0x2]; |
| 818 | __be32 ifc_ccr; | 828 | __be32 ifc_ccr; |
| 819 | __be32 ifc_csr; | 829 | __be32 ifc_csr; |
| 820 | u32 res16[0x2EB]; | 830 | __be32 ddr_ccr_low; |
| 831 | }; | ||
| 832 | |||
| 833 | |||
| 834 | struct fsl_ifc_runtime { | ||
| 821 | struct fsl_ifc_nand ifc_nand; | 835 | struct fsl_ifc_nand ifc_nand; |
| 822 | struct fsl_ifc_nor ifc_nor; | 836 | struct fsl_ifc_nor ifc_nor; |
| 823 | struct fsl_ifc_gpcm ifc_gpcm; | 837 | struct fsl_ifc_gpcm ifc_gpcm; |
| @@ -831,7 +845,8 @@ extern int fsl_ifc_find(phys_addr_t addr_base); | |||
| 831 | struct fsl_ifc_ctrl { | 845 | struct fsl_ifc_ctrl { |
| 832 | /* device info */ | 846 | /* device info */ |
| 833 | struct device *dev; | 847 | struct device *dev; |
| 834 | struct fsl_ifc_regs __iomem *regs; | 848 | struct fsl_ifc_global __iomem *gregs; |
| 849 | struct fsl_ifc_runtime __iomem *rregs; | ||
| 835 | int irq; | 850 | int irq; |
| 836 | int nand_irq; | 851 | int nand_irq; |
| 837 | spinlock_t lock; | 852 | spinlock_t lock; |
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index c8be32e9fc49..ad3c3488073c 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h | |||
| @@ -103,24 +103,6 @@ | |||
| 103 | 103 | ||
| 104 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) | 104 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) |
| 105 | 105 | ||
| 106 | /* | ||
| 107 | * There are 13 bytes of ecc for every 512 byte block in FSMC version 8 | ||
| 108 | * and it has to be read consecutively and immediately after the 512 | ||
| 109 | * byte data block for hardware to generate the error bit offsets | ||
| 110 | * Managing the ecc bytes in the following way is easier. This way is | ||
| 111 | * similar to oobfree structure maintained already in u-boot nand driver | ||
| 112 | */ | ||
| 113 | #define MAX_ECCPLACE_ENTRIES 32 | ||
| 114 | |||
| 115 | struct fsmc_nand_eccplace { | ||
| 116 | uint8_t offset; | ||
| 117 | uint8_t length; | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct fsmc_eccplace { | ||
| 121 | struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES]; | ||
| 122 | }; | ||
| 123 | |||
| 124 | struct fsmc_nand_timings { | 106 | struct fsmc_nand_timings { |
| 125 | uint8_t tclr; | 107 | uint8_t tclr; |
| 126 | uint8_t tar; | 108 | uint8_t tar; |
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 5e0eb7ccabd4..3aa56e3104bb 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h | |||
| @@ -122,18 +122,13 @@ | |||
| 122 | #endif | 122 | #endif |
| 123 | 123 | ||
| 124 | #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 | 124 | #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 |
| 125 | # ifdef map_bankwidth | 125 | /* always use indirect access for 256-bit to preserve kernel stack */ |
| 126 | # undef map_bankwidth | 126 | # undef map_bankwidth |
| 127 | # define map_bankwidth(map) ((map)->bankwidth) | 127 | # define map_bankwidth(map) ((map)->bankwidth) |
| 128 | # undef map_bankwidth_is_large | 128 | # undef map_bankwidth_is_large |
| 129 | # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) | 129 | # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) |
| 130 | # undef map_words | 130 | # undef map_words |
| 131 | # define map_words(map) map_calc_words(map) | 131 | # define map_words(map) map_calc_words(map) |
| 132 | # else | ||
| 133 | # define map_bankwidth(map) 32 | ||
| 134 | # define map_bankwidth_is_large(map) (1) | ||
| 135 | # define map_words(map) map_calc_words(map) | ||
| 136 | # endif | ||
| 137 | #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) | 132 | #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) |
| 138 | #undef MAX_MAP_BANKWIDTH | 133 | #undef MAX_MAP_BANKWIDTH |
| 139 | #define MAX_MAP_BANKWIDTH 32 | 134 | #define MAX_MAP_BANKWIDTH 32 |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index ef9fea4fc400..29a170612203 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
| @@ -96,16 +96,35 @@ struct mtd_oob_ops { | |||
| 96 | 96 | ||
| 97 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 | 97 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 |
| 98 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 | 98 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 |
| 99 | /** | ||
| 100 | * struct mtd_oob_region - oob region definition | ||
| 101 | * @offset: region offset | ||
| 102 | * @length: region length | ||
| 103 | * | ||
| 104 | * This structure describes a region of the OOB area, and is used | ||
| 105 | * to retrieve ECC or free bytes sections. | ||
| 106 | * Each section is defined by an offset within the OOB area and a | ||
| 107 | * length. | ||
| 108 | */ | ||
| 109 | struct mtd_oob_region { | ||
| 110 | u32 offset; | ||
| 111 | u32 length; | ||
| 112 | }; | ||
| 113 | |||
| 99 | /* | 114 | /* |
| 100 | * Internal ECC layout control structure. For historical reasons, there is a | 115 | * struct mtd_ooblayout_ops - NAND OOB layout operations |
| 101 | * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained | 116 | * @ecc: function returning an ECC region in the OOB area. |
| 102 | * for export to user-space via the ECCGETLAYOUT ioctl. | 117 | * Should return -ERANGE if %section exceeds the total number of |
| 103 | * nand_ecclayout should be expandable in the future simply by the above macros. | 118 | * ECC sections. |
| 119 | * @free: function returning a free region in the OOB area. | ||
| 120 | * Should return -ERANGE if %section exceeds the total number of | ||
| 121 | * free sections. | ||
| 104 | */ | 122 | */ |
| 105 | struct nand_ecclayout { | 123 | struct mtd_ooblayout_ops { |
| 106 | __u32 eccbytes; | 124 | int (*ecc)(struct mtd_info *mtd, int section, |
| 107 | __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; | 125 | struct mtd_oob_region *oobecc); |
| 108 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; | 126 | int (*free)(struct mtd_info *mtd, int section, |
| 127 | struct mtd_oob_region *oobfree); | ||
| 109 | }; | 128 | }; |
| 110 | 129 | ||
| 111 | struct module; /* only needed for owner field in mtd_info */ | 130 | struct module; /* only needed for owner field in mtd_info */ |
| @@ -166,8 +185,8 @@ struct mtd_info { | |||
| 166 | const char *name; | 185 | const char *name; |
| 167 | int index; | 186 | int index; |
| 168 | 187 | ||
| 169 | /* ECC layout structure pointer - read only! */ | 188 | /* OOB layout description */ |
| 170 | struct nand_ecclayout *ecclayout; | 189 | const struct mtd_ooblayout_ops *ooblayout; |
| 171 | 190 | ||
| 172 | /* the ecc step size. */ | 191 | /* the ecc step size. */ |
| 173 | unsigned int ecc_step_size; | 192 | unsigned int ecc_step_size; |
| @@ -253,6 +272,30 @@ struct mtd_info { | |||
| 253 | int usecount; | 272 | int usecount; |
| 254 | }; | 273 | }; |
| 255 | 274 | ||
| 275 | int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 276 | struct mtd_oob_region *oobecc); | ||
| 277 | int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, | ||
| 278 | int *section, | ||
| 279 | struct mtd_oob_region *oobregion); | ||
| 280 | int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, | ||
| 281 | const u8 *oobbuf, int start, int nbytes); | ||
| 282 | int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, | ||
| 283 | u8 *oobbuf, int start, int nbytes); | ||
| 284 | int mtd_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 285 | struct mtd_oob_region *oobfree); | ||
| 286 | int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, | ||
| 287 | const u8 *oobbuf, int start, int nbytes); | ||
| 288 | int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, | ||
| 289 | u8 *oobbuf, int start, int nbytes); | ||
| 290 | int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); | ||
| 291 | int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); | ||
| 292 | |||
| 293 | static inline void mtd_set_ooblayout(struct mtd_info *mtd, | ||
| 294 | const struct mtd_ooblayout_ops *ooblayout) | ||
| 295 | { | ||
| 296 | mtd->ooblayout = ooblayout; | ||
| 297 | } | ||
| 298 | |||
| 256 | static inline void mtd_set_of_node(struct mtd_info *mtd, | 299 | static inline void mtd_set_of_node(struct mtd_info *mtd, |
| 257 | struct device_node *np) | 300 | struct device_node *np) |
| 258 | { | 301 | { |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 56574ba36555..fbe8e164a4ee 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
| @@ -116,9 +116,14 @@ typedef enum { | |||
| 116 | NAND_ECC_HW, | 116 | NAND_ECC_HW, |
| 117 | NAND_ECC_HW_SYNDROME, | 117 | NAND_ECC_HW_SYNDROME, |
| 118 | NAND_ECC_HW_OOB_FIRST, | 118 | NAND_ECC_HW_OOB_FIRST, |
| 119 | NAND_ECC_SOFT_BCH, | ||
| 120 | } nand_ecc_modes_t; | 119 | } nand_ecc_modes_t; |
| 121 | 120 | ||
| 121 | enum nand_ecc_algo { | ||
| 122 | NAND_ECC_UNKNOWN, | ||
| 123 | NAND_ECC_HAMMING, | ||
| 124 | NAND_ECC_BCH, | ||
| 125 | }; | ||
| 126 | |||
| 122 | /* | 127 | /* |
| 123 | * Constants for Hardware ECC | 128 | * Constants for Hardware ECC |
| 124 | */ | 129 | */ |
| @@ -458,6 +463,7 @@ struct nand_hw_control { | |||
| 458 | /** | 463 | /** |
| 459 | * struct nand_ecc_ctrl - Control structure for ECC | 464 | * struct nand_ecc_ctrl - Control structure for ECC |
| 460 | * @mode: ECC mode | 465 | * @mode: ECC mode |
| 466 | * @algo: ECC algorithm | ||
| 461 | * @steps: number of ECC steps per page | 467 | * @steps: number of ECC steps per page |
| 462 | * @size: data bytes per ECC step | 468 | * @size: data bytes per ECC step |
| 463 | * @bytes: ECC bytes per step | 469 | * @bytes: ECC bytes per step |
| @@ -466,7 +472,6 @@ struct nand_hw_control { | |||
| 466 | * @prepad: padding information for syndrome based ECC generators | 472 | * @prepad: padding information for syndrome based ECC generators |
| 467 | * @postpad: padding information for syndrome based ECC generators | 473 | * @postpad: padding information for syndrome based ECC generators |
| 468 | * @options: ECC specific options (see NAND_ECC_XXX flags defined above) | 474 | * @options: ECC specific options (see NAND_ECC_XXX flags defined above) |
| 469 | * @layout: ECC layout control struct pointer | ||
| 470 | * @priv: pointer to private ECC control data | 475 | * @priv: pointer to private ECC control data |
| 471 | * @hwctl: function to control hardware ECC generator. Must only | 476 | * @hwctl: function to control hardware ECC generator. Must only |
| 472 | * be provided if an hardware ECC is available | 477 | * be provided if an hardware ECC is available |
| @@ -508,6 +513,7 @@ struct nand_hw_control { | |||
| 508 | */ | 513 | */ |
| 509 | struct nand_ecc_ctrl { | 514 | struct nand_ecc_ctrl { |
| 510 | nand_ecc_modes_t mode; | 515 | nand_ecc_modes_t mode; |
| 516 | enum nand_ecc_algo algo; | ||
| 511 | int steps; | 517 | int steps; |
| 512 | int size; | 518 | int size; |
| 513 | int bytes; | 519 | int bytes; |
| @@ -516,7 +522,6 @@ struct nand_ecc_ctrl { | |||
| 516 | int prepad; | 522 | int prepad; |
| 517 | int postpad; | 523 | int postpad; |
| 518 | unsigned int options; | 524 | unsigned int options; |
| 519 | struct nand_ecclayout *layout; | ||
| 520 | void *priv; | 525 | void *priv; |
| 521 | void (*hwctl)(struct mtd_info *mtd, int mode); | 526 | void (*hwctl)(struct mtd_info *mtd, int mode); |
| 522 | int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, | 527 | int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, |
| @@ -740,6 +745,9 @@ struct nand_chip { | |||
| 740 | void *priv; | 745 | void *priv; |
| 741 | }; | 746 | }; |
| 742 | 747 | ||
| 748 | extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; | ||
| 749 | extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops; | ||
| 750 | |||
| 743 | static inline void nand_set_flash_node(struct nand_chip *chip, | 751 | static inline void nand_set_flash_node(struct nand_chip *chip, |
| 744 | struct device_node *np) | 752 | struct device_node *np) |
| 745 | { | 753 | { |
| @@ -1070,4 +1078,18 @@ int nand_check_erased_ecc_chunk(void *data, int datalen, | |||
| 1070 | void *ecc, int ecclen, | 1078 | void *ecc, int ecclen, |
| 1071 | void *extraoob, int extraooblen, | 1079 | void *extraoob, int extraooblen, |
| 1072 | int threshold); | 1080 | int threshold); |
| 1081 | |||
| 1082 | /* Default write_oob implementation */ | ||
| 1083 | int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); | ||
| 1084 | |||
| 1085 | /* Default write_oob syndrome implementation */ | ||
| 1086 | int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
| 1087 | int page); | ||
| 1088 | |||
| 1089 | /* Default read_oob implementation */ | ||
| 1090 | int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); | ||
| 1091 | |||
| 1092 | /* Default read_oob syndrome implementation */ | ||
| 1093 | int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
| 1094 | int page); | ||
| 1073 | #endif /* __LINUX_MTD_NAND_H */ | 1095 | #endif /* __LINUX_MTD_NAND_H */ |
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 4596503c9da9..0aaa98b219a4 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h | |||
| @@ -80,7 +80,6 @@ struct onenand_bufferram { | |||
| 80 | * @page_buf: [INTERN] page main data buffer | 80 | * @page_buf: [INTERN] page main data buffer |
| 81 | * @oob_buf: [INTERN] page oob data buffer | 81 | * @oob_buf: [INTERN] page oob data buffer |
| 82 | * @subpagesize: [INTERN] holds the subpagesize | 82 | * @subpagesize: [INTERN] holds the subpagesize |
| 83 | * @ecclayout: [REPLACEABLE] the default ecc placement scheme | ||
| 84 | * @bbm: [REPLACEABLE] pointer to Bad Block Management | 83 | * @bbm: [REPLACEABLE] pointer to Bad Block Management |
| 85 | * @priv: [OPTIONAL] pointer to private chip date | 84 | * @priv: [OPTIONAL] pointer to private chip date |
| 86 | */ | 85 | */ |
| @@ -134,7 +133,6 @@ struct onenand_chip { | |||
| 134 | #endif | 133 | #endif |
| 135 | 134 | ||
| 136 | int subpagesize; | 135 | int subpagesize; |
| 137 | struct nand_ecclayout *ecclayout; | ||
| 138 | 136 | ||
| 139 | void *bbm; | 137 | void *bbm; |
| 140 | 138 | ||
diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h index 25f4d2a845c1..65e91d0fa981 100644 --- a/include/linux/mtd/sharpsl.h +++ b/include/linux/mtd/sharpsl.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | struct sharpsl_nand_platform_data { | 15 | struct sharpsl_nand_platform_data { |
| 16 | struct nand_bbt_descr *badblock_pattern; | 16 | struct nand_bbt_descr *badblock_pattern; |
| 17 | struct nand_ecclayout *ecc_layout; | 17 | const struct mtd_ooblayout_ops *ecc_layout; |
| 18 | struct mtd_partition *partitions; | 18 | struct mtd_partition *partitions; |
| 19 | unsigned int nr_partitions; | 19 | unsigned int nr_partitions; |
| 20 | }; | 20 | }; |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 3c36113a88e1..7f041bd88b82 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | * Sometimes these are the same as CFI IDs, but sometimes they aren't. | 21 | * Sometimes these are the same as CFI IDs, but sometimes they aren't. |
| 22 | */ | 22 | */ |
| 23 | #define SNOR_MFR_ATMEL CFI_MFR_ATMEL | 23 | #define SNOR_MFR_ATMEL CFI_MFR_ATMEL |
| 24 | #define SNOR_MFR_GIGADEVICE 0xc8 | ||
| 24 | #define SNOR_MFR_INTEL CFI_MFR_INTEL | 25 | #define SNOR_MFR_INTEL CFI_MFR_INTEL |
| 25 | #define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */ | 26 | #define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */ |
| 26 | #define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX | 27 | #define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX |
diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h deleted file mode 100644 index e266caa36402..000000000000 --- a/include/linux/of_mtd.h +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | ||
| 3 | * | ||
| 4 | * OF helpers for mtd. | ||
| 5 | * | ||
| 6 | * This file is released under the GPLv2 | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __LINUX_OF_MTD_H | ||
| 10 | #define __LINUX_OF_MTD_H | ||
| 11 | |||
| 12 | #ifdef CONFIG_OF_MTD | ||
| 13 | |||
| 14 | #include <linux/of.h> | ||
| 15 | int of_get_nand_ecc_mode(struct device_node *np); | ||
| 16 | int of_get_nand_ecc_step_size(struct device_node *np); | ||
| 17 | int of_get_nand_ecc_strength(struct device_node *np); | ||
| 18 | int of_get_nand_bus_width(struct device_node *np); | ||
| 19 | bool of_get_nand_on_flash_bbt(struct device_node *np); | ||
| 20 | |||
| 21 | #else /* CONFIG_OF_MTD */ | ||
| 22 | |||
| 23 | static inline int of_get_nand_ecc_mode(struct device_node *np) | ||
| 24 | { | ||
| 25 | return -ENOSYS; | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline int of_get_nand_ecc_step_size(struct device_node *np) | ||
| 29 | { | ||
| 30 | return -ENOSYS; | ||
| 31 | } | ||
| 32 | |||
| 33 | static inline int of_get_nand_ecc_strength(struct device_node *np) | ||
| 34 | { | ||
| 35 | return -ENOSYS; | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline int of_get_nand_bus_width(struct device_node *np) | ||
| 39 | { | ||
| 40 | return -ENOSYS; | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline bool of_get_nand_on_flash_bbt(struct device_node *np) | ||
| 44 | { | ||
| 45 | return false; | ||
| 46 | } | ||
| 47 | |||
| 48 | #endif /* CONFIG_OF_MTD */ | ||
| 49 | |||
| 50 | #endif /* __LINUX_OF_MTD_H */ | ||
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index d833eb4dd446..9e9d79e8efa5 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h | |||
| @@ -7,161 +7,53 @@ | |||
| 7 | * option) any later version. | 7 | * option) any later version. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | /* Maximum Number of Chip Selects */ | 10 | #include <linux/platform_data/gpmc-omap.h> |
| 11 | #define GPMC_CS_NUM 8 | ||
| 12 | 11 | ||
| 13 | #define GPMC_CONFIG_WP 0x00000005 | 12 | #define GPMC_CONFIG_WP 0x00000005 |
| 14 | 13 | ||
| 15 | #define GPMC_IRQ_FIFOEVENTENABLE 0x01 | 14 | /* IRQ numbers in GPMC IRQ domain for legacy boot use */ |
| 16 | #define GPMC_IRQ_COUNT_EVENT 0x02 | 15 | #define GPMC_IRQ_FIFOEVENTENABLE 0 |
| 17 | 16 | #define GPMC_IRQ_COUNT_EVENT 1 | |
| 18 | #define GPMC_BURST_4 4 /* 4 word burst */ | ||
| 19 | #define GPMC_BURST_8 8 /* 8 word burst */ | ||
| 20 | #define GPMC_BURST_16 16 /* 16 word burst */ | ||
| 21 | #define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ | ||
| 22 | #define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ | ||
| 23 | #define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ | ||
| 24 | #define GPMC_MUX_AD 2 /* Addr-Data multiplex */ | ||
| 25 | |||
| 26 | /* bool type time settings */ | ||
| 27 | struct gpmc_bool_timings { | ||
| 28 | bool cycle2cyclediffcsen; | ||
| 29 | bool cycle2cyclesamecsen; | ||
| 30 | bool we_extra_delay; | ||
| 31 | bool oe_extra_delay; | ||
| 32 | bool adv_extra_delay; | ||
| 33 | bool cs_extra_delay; | ||
| 34 | bool time_para_granularity; | ||
| 35 | }; | ||
| 36 | 17 | ||
| 37 | /* | 18 | /** |
| 38 | * Note that all values in this struct are in nanoseconds except sync_clk | 19 | * gpmc_nand_ops - Interface between NAND and GPMC |
| 39 | * (which is in picoseconds), while the register values are in gpmc_fck cycles. | 20 | * @nand_write_buffer_empty: get the NAND write buffer empty status. |
| 40 | */ | 21 | */ |
| 41 | struct gpmc_timings { | 22 | struct gpmc_nand_ops { |
| 42 | /* Minimum clock period for synchronous mode (in picoseconds) */ | 23 | bool (*nand_writebuffer_empty)(void); |
| 43 | u32 sync_clk; | ||
| 44 | |||
| 45 | /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ | ||
| 46 | u32 cs_on; /* Assertion time */ | ||
| 47 | u32 cs_rd_off; /* Read deassertion time */ | ||
| 48 | u32 cs_wr_off; /* Write deassertion time */ | ||
| 49 | |||
| 50 | /* ADV signal timings corresponding to GPMC_CONFIG3 */ | ||
| 51 | u32 adv_on; /* Assertion time */ | ||
| 52 | u32 adv_rd_off; /* Read deassertion time */ | ||
| 53 | u32 adv_wr_off; /* Write deassertion time */ | ||
| 54 | u32 adv_aad_mux_on; /* ADV assertion time for AAD */ | ||
| 55 | u32 adv_aad_mux_rd_off; /* ADV read deassertion time for AAD */ | ||
| 56 | u32 adv_aad_mux_wr_off; /* ADV write deassertion time for AAD */ | ||
| 57 | |||
| 58 | /* WE signals timings corresponding to GPMC_CONFIG4 */ | ||
| 59 | u32 we_on; /* WE assertion time */ | ||
| 60 | u32 we_off; /* WE deassertion time */ | ||
| 61 | |||
| 62 | /* OE signals timings corresponding to GPMC_CONFIG4 */ | ||
| 63 | u32 oe_on; /* OE assertion time */ | ||
| 64 | u32 oe_off; /* OE deassertion time */ | ||
| 65 | u32 oe_aad_mux_on; /* OE assertion time for AAD */ | ||
| 66 | u32 oe_aad_mux_off; /* OE deassertion time for AAD */ | ||
| 67 | |||
| 68 | /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ | ||
| 69 | u32 page_burst_access; /* Multiple access word delay */ | ||
| 70 | u32 access; /* Start-cycle to first data valid delay */ | ||
| 71 | u32 rd_cycle; /* Total read cycle time */ | ||
| 72 | u32 wr_cycle; /* Total write cycle time */ | ||
| 73 | |||
| 74 | u32 bus_turnaround; | ||
| 75 | u32 cycle2cycle_delay; | ||
| 76 | |||
| 77 | u32 wait_monitoring; | ||
| 78 | u32 clk_activation; | ||
| 79 | |||
| 80 | /* The following are only on OMAP3430 */ | ||
| 81 | u32 wr_access; /* WRACCESSTIME */ | ||
| 82 | u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ | ||
| 83 | |||
| 84 | struct gpmc_bool_timings bool_timings; | ||
| 85 | }; | 24 | }; |
| 86 | 25 | ||
| 87 | /* Device timings in picoseconds */ | 26 | struct gpmc_nand_regs; |
| 88 | struct gpmc_device_timings { | ||
| 89 | u32 t_ceasu; /* address setup to CS valid */ | ||
| 90 | u32 t_avdasu; /* address setup to ADV valid */ | ||
| 91 | /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is | ||
| 92 | * of tusb using these timings even for sync whilst | ||
| 93 | * ideally for adv_rd/(wr)_off it should have considered | ||
| 94 | * t_avdh instead. This indirectly necessitates r/w | ||
| 95 | * variations of t_avdp as it is possible to have one | ||
| 96 | * sync & other async | ||
| 97 | */ | ||
| 98 | u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ | ||
| 99 | u32 t_avdp_w; | ||
| 100 | u32 t_aavdh; /* address hold time */ | ||
| 101 | u32 t_oeasu; /* address setup to OE valid */ | ||
| 102 | u32 t_aa; /* access time from ADV assertion */ | ||
| 103 | u32 t_iaa; /* initial access time */ | ||
| 104 | u32 t_oe; /* access time from OE assertion */ | ||
| 105 | u32 t_ce; /* access time from CS asertion */ | ||
| 106 | u32 t_rd_cycle; /* read cycle time */ | ||
| 107 | u32 t_cez_r; /* read CS deassertion to high Z */ | ||
| 108 | u32 t_cez_w; /* write CS deassertion to high Z */ | ||
| 109 | u32 t_oez; /* OE deassertion to high Z */ | ||
| 110 | u32 t_weasu; /* address setup to WE valid */ | ||
| 111 | u32 t_wpl; /* write assertion time */ | ||
| 112 | u32 t_wph; /* write deassertion time */ | ||
| 113 | u32 t_wr_cycle; /* write cycle time */ | ||
| 114 | |||
| 115 | u32 clk; | ||
| 116 | u32 t_bacc; /* burst access valid clock to output delay */ | ||
| 117 | u32 t_ces; /* CS setup time to clk */ | ||
| 118 | u32 t_avds; /* ADV setup time to clk */ | ||
| 119 | u32 t_avdh; /* ADV hold time from clk */ | ||
| 120 | u32 t_ach; /* address hold time from clk */ | ||
| 121 | u32 t_rdyo; /* clk to ready valid */ | ||
| 122 | |||
| 123 | u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ | ||
| 124 | u32 t_ce_avd; /* CS on to ADV on delay */ | ||
| 125 | |||
| 126 | /* XXX: check the possibility of combining | ||
| 127 | * cyc_aavhd_oe & cyc_aavdh_we | ||
| 128 | */ | ||
| 129 | u8 cyc_aavdh_oe;/* read address hold time in cycles */ | ||
| 130 | u8 cyc_aavdh_we;/* write address hold time in cycles */ | ||
| 131 | u8 cyc_oe; /* access time from OE assertion in cycles */ | ||
| 132 | u8 cyc_wpl; /* write deassertion time in cycles */ | ||
| 133 | u32 cyc_iaa; /* initial access time in cycles */ | ||
| 134 | |||
| 135 | /* extra delays */ | ||
| 136 | bool ce_xdelay; | ||
| 137 | bool avd_xdelay; | ||
| 138 | bool oe_xdelay; | ||
| 139 | bool we_xdelay; | ||
| 140 | }; | ||
| 141 | 27 | ||
| 142 | struct gpmc_settings { | 28 | #if IS_ENABLED(CONFIG_OMAP_GPMC) |
| 143 | bool burst_wrap; /* enables wrap bursting */ | 29 | struct gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *regs, |
| 144 | bool burst_read; /* enables read page/burst mode */ | 30 | int cs); |
| 145 | bool burst_write; /* enables write page/burst mode */ | 31 | #else |
| 146 | bool device_nand; /* device is NAND */ | 32 | static inline gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *regs, |
| 147 | bool sync_read; /* enables synchronous reads */ | 33 | int cs) |
| 148 | bool sync_write; /* enables synchronous writes */ | 34 | { |
| 149 | bool wait_on_read; /* monitor wait on reads */ | 35 | return NULL; |
| 150 | bool wait_on_write; /* monitor wait on writes */ | 36 | } |
| 151 | u32 burst_len; /* page/burst length */ | 37 | #endif /* CONFIG_OMAP_GPMC */ |
| 152 | u32 device_width; /* device bus width (8 or 16 bit) */ | 38 | |
| 153 | u32 mux_add_data; /* multiplex address & data */ | 39 | /*--------------------------------*/ |
| 154 | u32 wait_pin; /* wait-pin to be used */ | 40 | |
| 155 | }; | 41 | /* deprecated APIs */ |
| 42 | #if IS_ENABLED(CONFIG_OMAP_GPMC) | ||
| 43 | void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); | ||
| 44 | #else | ||
| 45 | static inline void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | #endif /* CONFIG_OMAP_GPMC */ | ||
| 49 | /*--------------------------------*/ | ||
| 156 | 50 | ||
| 157 | extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | 51 | extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, |
| 158 | struct gpmc_settings *gpmc_s, | 52 | struct gpmc_settings *gpmc_s, |
| 159 | struct gpmc_device_timings *dev_t); | 53 | struct gpmc_device_timings *dev_t); |
| 160 | 54 | ||
| 161 | struct gpmc_nand_regs; | ||
| 162 | struct device_node; | 55 | struct device_node; |
| 163 | 56 | ||
| 164 | extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); | ||
| 165 | extern int gpmc_get_client_irq(unsigned irq_config); | 57 | extern int gpmc_get_client_irq(unsigned irq_config); |
| 166 | 58 | ||
| 167 | extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); | 59 | extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); |
diff --git a/include/linux/platform_data/gpmc-omap.h b/include/linux/platform_data/gpmc-omap.h new file mode 100644 index 000000000000..67ccdb0e1606 --- /dev/null +++ b/include/linux/platform_data/gpmc-omap.h | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | /* | ||
| 2 | * OMAP GPMC Platform data | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Texas Instruments, Inc. - http://www.ti.com | ||
| 5 | * Roger Quadros <rogerq@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms and conditions of the GNU General Public License, | ||
| 9 | * version 2, as published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _GPMC_OMAP_H_ | ||
| 13 | #define _GPMC_OMAP_H_ | ||
| 14 | |||
| 15 | /* Maximum Number of Chip Selects */ | ||
| 16 | #define GPMC_CS_NUM 8 | ||
| 17 | |||
| 18 | /* bool type time settings */ | ||
| 19 | struct gpmc_bool_timings { | ||
| 20 | bool cycle2cyclediffcsen; | ||
| 21 | bool cycle2cyclesamecsen; | ||
| 22 | bool we_extra_delay; | ||
| 23 | bool oe_extra_delay; | ||
| 24 | bool adv_extra_delay; | ||
| 25 | bool cs_extra_delay; | ||
| 26 | bool time_para_granularity; | ||
| 27 | }; | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Note that all values in this struct are in nanoseconds except sync_clk | ||
| 31 | * (which is in picoseconds), while the register values are in gpmc_fck cycles. | ||
| 32 | */ | ||
| 33 | struct gpmc_timings { | ||
| 34 | /* Minimum clock period for synchronous mode (in picoseconds) */ | ||
| 35 | u32 sync_clk; | ||
| 36 | |||
| 37 | /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ | ||
| 38 | u32 cs_on; /* Assertion time */ | ||
| 39 | u32 cs_rd_off; /* Read deassertion time */ | ||
| 40 | u32 cs_wr_off; /* Write deassertion time */ | ||
| 41 | |||
| 42 | /* ADV signal timings corresponding to GPMC_CONFIG3 */ | ||
| 43 | u32 adv_on; /* Assertion time */ | ||
| 44 | u32 adv_rd_off; /* Read deassertion time */ | ||
| 45 | u32 adv_wr_off; /* Write deassertion time */ | ||
| 46 | u32 adv_aad_mux_on; /* ADV assertion time for AAD */ | ||
| 47 | u32 adv_aad_mux_rd_off; /* ADV read deassertion time for AAD */ | ||
| 48 | u32 adv_aad_mux_wr_off; /* ADV write deassertion time for AAD */ | ||
| 49 | |||
| 50 | /* WE signals timings corresponding to GPMC_CONFIG4 */ | ||
| 51 | u32 we_on; /* WE assertion time */ | ||
| 52 | u32 we_off; /* WE deassertion time */ | ||
| 53 | |||
| 54 | /* OE signals timings corresponding to GPMC_CONFIG4 */ | ||
| 55 | u32 oe_on; /* OE assertion time */ | ||
| 56 | u32 oe_off; /* OE deassertion time */ | ||
| 57 | u32 oe_aad_mux_on; /* OE assertion time for AAD */ | ||
| 58 | u32 oe_aad_mux_off; /* OE deassertion time for AAD */ | ||
| 59 | |||
| 60 | /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ | ||
| 61 | u32 page_burst_access; /* Multiple access word delay */ | ||
| 62 | u32 access; /* Start-cycle to first data valid delay */ | ||
| 63 | u32 rd_cycle; /* Total read cycle time */ | ||
| 64 | u32 wr_cycle; /* Total write cycle time */ | ||
| 65 | |||
| 66 | u32 bus_turnaround; | ||
| 67 | u32 cycle2cycle_delay; | ||
| 68 | |||
| 69 | u32 wait_monitoring; | ||
| 70 | u32 clk_activation; | ||
| 71 | |||
| 72 | /* The following are only on OMAP3430 */ | ||
| 73 | u32 wr_access; /* WRACCESSTIME */ | ||
| 74 | u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ | ||
| 75 | |||
| 76 | struct gpmc_bool_timings bool_timings; | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Device timings in picoseconds */ | ||
| 80 | struct gpmc_device_timings { | ||
| 81 | u32 t_ceasu; /* address setup to CS valid */ | ||
| 82 | u32 t_avdasu; /* address setup to ADV valid */ | ||
| 83 | /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is | ||
| 84 | * of tusb using these timings even for sync whilst | ||
| 85 | * ideally for adv_rd/(wr)_off it should have considered | ||
| 86 | * t_avdh instead. This indirectly necessitates r/w | ||
| 87 | * variations of t_avdp as it is possible to have one | ||
| 88 | * sync & other async | ||
| 89 | */ | ||
| 90 | u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ | ||
| 91 | u32 t_avdp_w; | ||
| 92 | u32 t_aavdh; /* address hold time */ | ||
| 93 | u32 t_oeasu; /* address setup to OE valid */ | ||
| 94 | u32 t_aa; /* access time from ADV assertion */ | ||
| 95 | u32 t_iaa; /* initial access time */ | ||
| 96 | u32 t_oe; /* access time from OE assertion */ | ||
| 97 | u32 t_ce; /* access time from CS asertion */ | ||
| 98 | u32 t_rd_cycle; /* read cycle time */ | ||
| 99 | u32 t_cez_r; /* read CS deassertion to high Z */ | ||
| 100 | u32 t_cez_w; /* write CS deassertion to high Z */ | ||
| 101 | u32 t_oez; /* OE deassertion to high Z */ | ||
| 102 | u32 t_weasu; /* address setup to WE valid */ | ||
| 103 | u32 t_wpl; /* write assertion time */ | ||
| 104 | u32 t_wph; /* write deassertion time */ | ||
| 105 | u32 t_wr_cycle; /* write cycle time */ | ||
| 106 | |||
| 107 | u32 clk; | ||
| 108 | u32 t_bacc; /* burst access valid clock to output delay */ | ||
| 109 | u32 t_ces; /* CS setup time to clk */ | ||
| 110 | u32 t_avds; /* ADV setup time to clk */ | ||
| 111 | u32 t_avdh; /* ADV hold time from clk */ | ||
| 112 | u32 t_ach; /* address hold time from clk */ | ||
| 113 | u32 t_rdyo; /* clk to ready valid */ | ||
| 114 | |||
| 115 | u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ | ||
| 116 | u32 t_ce_avd; /* CS on to ADV on delay */ | ||
| 117 | |||
| 118 | /* XXX: check the possibility of combining | ||
| 119 | * cyc_aavhd_oe & cyc_aavdh_we | ||
| 120 | */ | ||
| 121 | u8 cyc_aavdh_oe;/* read address hold time in cycles */ | ||
| 122 | u8 cyc_aavdh_we;/* write address hold time in cycles */ | ||
| 123 | u8 cyc_oe; /* access time from OE assertion in cycles */ | ||
| 124 | u8 cyc_wpl; /* write deassertion time in cycles */ | ||
| 125 | u32 cyc_iaa; /* initial access time in cycles */ | ||
| 126 | |||
| 127 | /* extra delays */ | ||
| 128 | bool ce_xdelay; | ||
| 129 | bool avd_xdelay; | ||
| 130 | bool oe_xdelay; | ||
| 131 | bool we_xdelay; | ||
| 132 | }; | ||
| 133 | |||
| 134 | #define GPMC_BURST_4 4 /* 4 word burst */ | ||
| 135 | #define GPMC_BURST_8 8 /* 8 word burst */ | ||
| 136 | #define GPMC_BURST_16 16 /* 16 word burst */ | ||
| 137 | #define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ | ||
| 138 | #define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ | ||
| 139 | #define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ | ||
| 140 | #define GPMC_MUX_AD 2 /* Addr-Data multiplex */ | ||
| 141 | |||
| 142 | struct gpmc_settings { | ||
| 143 | bool burst_wrap; /* enables wrap bursting */ | ||
| 144 | bool burst_read; /* enables read page/burst mode */ | ||
| 145 | bool burst_write; /* enables write page/burst mode */ | ||
| 146 | bool device_nand; /* device is NAND */ | ||
| 147 | bool sync_read; /* enables synchronous reads */ | ||
| 148 | bool sync_write; /* enables synchronous writes */ | ||
| 149 | bool wait_on_read; /* monitor wait on reads */ | ||
| 150 | bool wait_on_write; /* monitor wait on writes */ | ||
| 151 | u32 burst_len; /* page/burst length */ | ||
| 152 | u32 device_width; /* device bus width (8 or 16 bit) */ | ||
| 153 | u32 mux_add_data; /* multiplex address & data */ | ||
| 154 | u32 wait_pin; /* wait-pin to be used */ | ||
| 155 | }; | ||
| 156 | |||
| 157 | /* Data for each chip select */ | ||
| 158 | struct gpmc_omap_cs_data { | ||
| 159 | bool valid; /* data is valid */ | ||
| 160 | bool is_nand; /* device within this CS is NAND */ | ||
| 161 | struct gpmc_settings *settings; | ||
| 162 | struct gpmc_device_timings *device_timings; | ||
| 163 | struct gpmc_timings *gpmc_timings; | ||
| 164 | struct platform_device *pdev; /* device within this CS region */ | ||
| 165 | unsigned int pdata_size; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct gpmc_omap_platform_data { | ||
| 169 | struct gpmc_omap_cs_data cs[GPMC_CS_NUM]; | ||
| 170 | }; | ||
| 171 | |||
| 172 | #endif /* _GPMC_OMAP_H */ | ||
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 090bbab0130a..17d57a18bac5 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h | |||
| @@ -45,7 +45,6 @@ enum omap_ecc { | |||
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | struct gpmc_nand_regs { | 47 | struct gpmc_nand_regs { |
| 48 | void __iomem *gpmc_status; | ||
| 49 | void __iomem *gpmc_nand_command; | 48 | void __iomem *gpmc_nand_command; |
| 50 | void __iomem *gpmc_nand_address; | 49 | void __iomem *gpmc_nand_address; |
| 51 | void __iomem *gpmc_nand_data; | 50 | void __iomem *gpmc_nand_data; |
| @@ -64,21 +63,24 @@ struct gpmc_nand_regs { | |||
| 64 | void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER]; | 63 | void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER]; |
| 65 | void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER]; | 64 | void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER]; |
| 66 | void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; | 65 | void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; |
| 66 | /* Deprecated. Do not use */ | ||
| 67 | void __iomem *gpmc_status; | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | struct omap_nand_platform_data { | 70 | struct omap_nand_platform_data { |
| 70 | int cs; | 71 | int cs; |
| 71 | struct mtd_partition *parts; | 72 | struct mtd_partition *parts; |
| 72 | int nr_parts; | 73 | int nr_parts; |
| 73 | bool dev_ready; | ||
| 74 | bool flash_bbt; | 74 | bool flash_bbt; |
| 75 | enum nand_io xfer_type; | 75 | enum nand_io xfer_type; |
| 76 | int devsize; | 76 | int devsize; |
| 77 | enum omap_ecc ecc_opt; | 77 | enum omap_ecc ecc_opt; |
| 78 | struct gpmc_nand_regs reg; | ||
| 79 | 78 | ||
| 80 | /* for passing the partitions */ | ||
| 81 | struct device_node *of_node; | ||
| 82 | struct device_node *elm_of_node; | 79 | struct device_node *elm_of_node; |
| 80 | |||
| 81 | /* deprecated */ | ||
| 82 | struct gpmc_nand_regs reg; | ||
| 83 | struct device_node *of_node; | ||
| 84 | bool dev_ready; | ||
| 83 | }; | 85 | }; |
| 84 | #endif | 86 | #endif |
diff --git a/include/uapi/mtd/mtd-abi.h b/include/uapi/mtd/mtd-abi.h index 763bb6950402..0ec1da2ef652 100644 --- a/include/uapi/mtd/mtd-abi.h +++ b/include/uapi/mtd/mtd-abi.h | |||
| @@ -228,7 +228,7 @@ struct nand_oobfree { | |||
| 228 | * complete set of ECC information. The ioctl truncates the larger internal | 228 | * complete set of ECC information. The ioctl truncates the larger internal |
| 229 | * structure to retain binary compatibility with the static declaration of the | 229 | * structure to retain binary compatibility with the static declaration of the |
| 230 | * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of | 230 | * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of |
| 231 | * the user struct, not the MAX size of the internal struct nand_ecclayout. | 231 | * the user struct, not the MAX size of the internal OOB layout representation. |
| 232 | */ | 232 | */ |
| 233 | struct nand_ecclayout_user { | 233 | struct nand_ecclayout_user { |
| 234 | __u32 eccbytes; | 234 | __u32 eccbytes; |
