diff options
author | Brian Norris <computersforpeace@gmail.com> | 2016-05-05 21:04:53 -0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2016-05-05 21:04:53 -0400 |
commit | 2cbaf5491cb7095252c72e74e79863b75ad2d8d0 (patch) | |
tree | 45bae656589e8e9bcce5b7c47687d96fa1d8ac94 | |
parent | abbbc60a0c69e05c965ce51cb75c0bee56dc0025 (diff) | |
parent | 666b65683dad9aa90efaa4aad24ef3710101e3aa (diff) |
Merge tag 'nand/for-4.7' of github.com:linux-nand/linux
Updates from Boris Brezillon:
This pull request contains the following infrastructure changes:
* introduction of the ECC algo concept to extend the ECC mode one
* replacement of the nand_ecclayout infrastructure by something more
future-proof.
* addition of an mtd-activity led trigger to replace the nand-activity
one
And a bunch of specific NAND driver improvements/fixes. Here are the
changes that are worth mentioning:
* rework of the OMAP GPMC and NAND drivers
* prepare the sunxi NAND driver to receive DMA support
* handle bitflips in erased pages on GPMI revisions that do not support
this in hardware.
* tag 'nand/for-4.7' of github.com:linux-nand/linux: (152 commits)
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
mtd: nand: sh_flctl: rely on generic DT parsing done in nand_scan_ident()
mtd: nand: mxc: rely on generic DT parsing done in nand_scan_ident()
...
80 files changed, 4387 insertions, 2896 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 c2546ced9c02..deb24cbdda82 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 934b15b5b575..a1c1afbbfc5d 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
@@ -50,20 +50,6 @@ static bool is_avt2; | |||
50 | #define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) | 50 | #define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) |
51 | 51 | ||
52 | /* NAND */ | 52 | /* NAND */ |
53 | static struct nand_ecclayout qi_lb60_ecclayout_1gb = { | ||
54 | .eccbytes = 36, | ||
55 | .eccpos = { | ||
56 | 6, 7, 8, 9, 10, 11, 12, 13, | ||
57 | 14, 15, 16, 17, 18, 19, 20, 21, | ||
58 | 22, 23, 24, 25, 26, 27, 28, 29, | ||
59 | 30, 31, 32, 33, 34, 35, 36, 37, | ||
60 | 38, 39, 40, 41 | ||
61 | }, | ||
62 | .oobfree = { | ||
63 | { .offset = 2, .length = 4 }, | ||
64 | { .offset = 42, .length = 22 } | ||
65 | }, | ||
66 | }; | ||
67 | 53 | ||
68 | /* Early prototypes of the QI LB60 had only 1GB of NAND. | 54 | /* Early prototypes of the QI LB60 had only 1GB of NAND. |
69 | * In order to support these devices as well the partition and ecc layout is | 55 | * In order to support these devices as well the partition and ecc layout is |
@@ -86,25 +72,6 @@ static struct mtd_partition qi_lb60_partitions_1gb[] = { | |||
86 | }, | 72 | }, |
87 | }; | 73 | }; |
88 | 74 | ||
89 | static struct nand_ecclayout qi_lb60_ecclayout_2gb = { | ||
90 | .eccbytes = 72, | ||
91 | .eccpos = { | ||
92 | 12, 13, 14, 15, 16, 17, 18, 19, | ||
93 | 20, 21, 22, 23, 24, 25, 26, 27, | ||
94 | 28, 29, 30, 31, 32, 33, 34, 35, | ||
95 | 36, 37, 38, 39, 40, 41, 42, 43, | ||
96 | 44, 45, 46, 47, 48, 49, 50, 51, | ||
97 | 52, 53, 54, 55, 56, 57, 58, 59, | ||
98 | 60, 61, 62, 63, 64, 65, 66, 67, | ||
99 | 68, 69, 70, 71, 72, 73, 74, 75, | ||
100 | 76, 77, 78, 79, 80, 81, 82, 83 | ||
101 | }, | ||
102 | .oobfree = { | ||
103 | { .offset = 2, .length = 10 }, | ||
104 | { .offset = 84, .length = 44 }, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | static struct mtd_partition qi_lb60_partitions_2gb[] = { | 75 | static struct mtd_partition qi_lb60_partitions_2gb[] = { |
109 | { | 76 | { |
110 | .name = "NAND BOOT partition", | 77 | .name = "NAND BOOT partition", |
@@ -123,19 +90,67 @@ static struct mtd_partition qi_lb60_partitions_2gb[] = { | |||
123 | }, | 90 | }, |
124 | }; | 91 | }; |
125 | 92 | ||
93 | static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
94 | struct mtd_oob_region *oobregion) | ||
95 | { | ||
96 | if (section) | ||
97 | return -ERANGE; | ||
98 | |||
99 | oobregion->length = 36; | ||
100 | oobregion->offset = 6; | ||
101 | |||
102 | if (mtd->oobsize == 128) { | ||
103 | oobregion->length *= 2; | ||
104 | oobregion->offset *= 2; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section, | ||
111 | struct mtd_oob_region *oobregion) | ||
112 | { | ||
113 | int eccbytes = 36, eccoff = 6; | ||
114 | |||
115 | if (section > 1) | ||
116 | return -ERANGE; | ||
117 | |||
118 | if (mtd->oobsize == 128) { | ||
119 | eccbytes *= 2; | ||
120 | eccoff *= 2; | ||
121 | } | ||
122 | |||
123 | if (!section) { | ||
124 | oobregion->offset = 2; | ||
125 | oobregion->length = eccoff - 2; | ||
126 | } else { | ||
127 | oobregion->offset = eccoff + eccbytes; | ||
128 | oobregion->length = mtd->oobsize - oobregion->offset; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = { | ||
135 | .ecc = qi_lb60_ooblayout_ecc, | ||
136 | .free = qi_lb60_ooblayout_free, | ||
137 | }; | ||
138 | |||
126 | static void qi_lb60_nand_ident(struct platform_device *pdev, | 139 | static void qi_lb60_nand_ident(struct platform_device *pdev, |
127 | struct nand_chip *chip, struct mtd_partition **partitions, | 140 | struct mtd_info *mtd, struct mtd_partition **partitions, |
128 | int *num_partitions) | 141 | int *num_partitions) |
129 | { | 142 | { |
143 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
144 | |||
130 | if (chip->page_shift == 12) { | 145 | if (chip->page_shift == 12) { |
131 | chip->ecc.layout = &qi_lb60_ecclayout_2gb; | ||
132 | *partitions = qi_lb60_partitions_2gb; | 146 | *partitions = qi_lb60_partitions_2gb; |
133 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); | 147 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); |
134 | } else { | 148 | } else { |
135 | chip->ecc.layout = &qi_lb60_ecclayout_1gb; | ||
136 | *partitions = qi_lb60_partitions_1gb; | 149 | *partitions = qi_lb60_partitions_1gb; |
137 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); | 150 | *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); |
138 | } | 151 | } |
152 | |||
153 | mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops); | ||
139 | } | 154 | } |
140 | 155 | ||
141 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { | 156 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { |
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 5bda6a9b56bb..beac8c31c51b 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig | |||
@@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK | |||
41 | This allows LEDs to be controlled by IDE disk activity. | 41 | This allows LEDs to be controlled by IDE disk activity. |
42 | If unsure, say Y. | 42 | If unsure, say Y. |
43 | 43 | ||
44 | config LEDS_TRIGGER_MTD | ||
45 | bool "LED MTD (NAND/NOR) Trigger" | ||
46 | depends on MTD | ||
47 | depends on LEDS_TRIGGERS | ||
48 | help | ||
49 | This allows LEDs to be controlled by MTD activity. | ||
50 | If unsure, say N. | ||
51 | |||
44 | config LEDS_TRIGGER_HEARTBEAT | 52 | config LEDS_TRIGGER_HEARTBEAT |
45 | tristate "LED Heartbeat Trigger" | 53 | tristate "LED Heartbeat Trigger" |
46 | depends on LEDS_TRIGGERS | 54 | depends on LEDS_TRIGGERS |
@@ -108,4 +116,11 @@ config LEDS_TRIGGER_CAMERA | |||
108 | This enables direct flash/torch on/off by the driver, kernel space. | 116 | This enables direct flash/torch on/off by the driver, kernel space. |
109 | If unsure, say Y. | 117 | If unsure, say Y. |
110 | 118 | ||
119 | config LEDS_TRIGGER_PANIC | ||
120 | bool "LED Panic Trigger" | ||
121 | depends on LEDS_TRIGGERS | ||
122 | help | ||
123 | This allows LEDs to be configured to blink on a kernel panic. | ||
124 | If unsure, say Y. | ||
125 | |||
111 | endif # LEDS_TRIGGERS | 126 | endif # LEDS_TRIGGERS |
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48dacf7e..8cc64a4f4e25 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o | 1 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o |
2 | obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o | 2 | obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o |
3 | obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o | 3 | obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o |
4 | obj-$(CONFIG_LEDS_TRIGGER_MTD) += ledtrig-mtd.o | ||
4 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o | 5 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o |
5 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o | 6 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o |
6 | obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o | 7 | obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o |
@@ -8,3 +9,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o | |||
8 | obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o | 9 | obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o |
9 | obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o | 10 | obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o |
10 | obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o | 11 | obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o |
12 | obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o | ||
diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c new file mode 100644 index 000000000000..99b5b0a4d826 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-mtd.c | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * LED MTD trigger | ||
3 | * | ||
4 | * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> | ||
5 | * | ||
6 | * Based on LED IDE-Disk Activity Trigger | ||
7 | * | ||
8 | * Copyright 2006 Openedhand Ltd. | ||
9 | * | ||
10 | * Author: Richard Purdie <rpurdie@openedhand.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/leds.h> | ||
21 | |||
22 | #define BLINK_DELAY 30 | ||
23 | |||
24 | DEFINE_LED_TRIGGER(ledtrig_mtd); | ||
25 | DEFINE_LED_TRIGGER(ledtrig_nand); | ||
26 | |||
27 | void ledtrig_mtd_activity(void) | ||
28 | { | ||
29 | unsigned long blink_delay = BLINK_DELAY; | ||
30 | |||
31 | led_trigger_blink_oneshot(ledtrig_mtd, | ||
32 | &blink_delay, &blink_delay, 0); | ||
33 | led_trigger_blink_oneshot(ledtrig_nand, | ||
34 | &blink_delay, &blink_delay, 0); | ||
35 | } | ||
36 | EXPORT_SYMBOL(ledtrig_mtd_activity); | ||
37 | |||
38 | static int __init ledtrig_mtd_init(void) | ||
39 | { | ||
40 | led_trigger_register_simple("mtd", &ledtrig_mtd); | ||
41 | led_trigger_register_simple("nand-disk", &ledtrig_nand); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | device_initcall(ledtrig_mtd_init); | ||
diff --git a/drivers/leds/trigger/ledtrig-panic.c b/drivers/leds/trigger/ledtrig-panic.c new file mode 100644 index 000000000000..627b350c5ec3 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-panic.c | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Kernel Panic LED Trigger | ||
3 | * | ||
4 | * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/leds.h> | ||
15 | |||
16 | static struct led_trigger *trigger; | ||
17 | |||
18 | static long led_panic_blink(int state) | ||
19 | { | ||
20 | led_trigger_event(trigger, state ? LED_FULL : LED_OFF); | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | static int __init ledtrig_panic_init(void) | ||
25 | { | ||
26 | led_trigger_register_simple("panic", &trigger); | ||
27 | panic_blink = led_panic_blink; | ||
28 | return 0; | ||
29 | } | ||
30 | device_initcall(ledtrig_panic_init); | ||
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 51d5cd20c26a..a9b1c1419bef 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/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/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 309625130b21..e3936b847c6b 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/reboot.h> | 41 | #include <linux/reboot.h> |
42 | #include <linux/kconfig.h> | 42 | #include <linux/kconfig.h> |
43 | #include <linux/leds.h> | ||
43 | 44 | ||
44 | #include <linux/mtd/mtd.h> | 45 | #include <linux/mtd/mtd.h> |
45 | #include <linux/mtd/partitions.h> | 46 | #include <linux/mtd/partitions.h> |
@@ -862,6 +863,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
862 | mtd_erase_callback(instr); | 863 | mtd_erase_callback(instr); |
863 | return 0; | 864 | return 0; |
864 | } | 865 | } |
866 | ledtrig_mtd_activity(); | ||
865 | return mtd->_erase(mtd, instr); | 867 | return mtd->_erase(mtd, instr); |
866 | } | 868 | } |
867 | EXPORT_SYMBOL_GPL(mtd_erase); | 869 | EXPORT_SYMBOL_GPL(mtd_erase); |
@@ -925,6 +927,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | |||
925 | if (!len) | 927 | if (!len) |
926 | return 0; | 928 | return 0; |
927 | 929 | ||
930 | ledtrig_mtd_activity(); | ||
928 | /* | 931 | /* |
929 | * In the absence of an error, drivers return a non-negative integer | 932 | * In the absence of an error, drivers return a non-negative integer |
930 | * representing the maximum number of bitflips that were corrected on | 933 | * representing the maximum number of bitflips that were corrected on |
@@ -949,6 +952,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | |||
949 | return -EROFS; | 952 | return -EROFS; |
950 | if (!len) | 953 | if (!len) |
951 | return 0; | 954 | return 0; |
955 | ledtrig_mtd_activity(); | ||
952 | return mtd->_write(mtd, to, len, retlen, buf); | 956 | return mtd->_write(mtd, to, len, retlen, buf); |
953 | } | 957 | } |
954 | EXPORT_SYMBOL_GPL(mtd_write); | 958 | EXPORT_SYMBOL_GPL(mtd_write); |
@@ -982,6 +986,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) | |||
982 | ops->retlen = ops->oobretlen = 0; | 986 | ops->retlen = ops->oobretlen = 0; |
983 | if (!mtd->_read_oob) | 987 | if (!mtd->_read_oob) |
984 | return -EOPNOTSUPP; | 988 | return -EOPNOTSUPP; |
989 | |||
990 | ledtrig_mtd_activity(); | ||
985 | /* | 991 | /* |
986 | * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics | 992 | * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics |
987 | * similar to mtd->_read(), returning a non-negative integer | 993 | * similar to mtd->_read(), returning a non-negative integer |
@@ -997,6 +1003,379 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) | |||
997 | } | 1003 | } |
998 | EXPORT_SYMBOL_GPL(mtd_read_oob); | 1004 | EXPORT_SYMBOL_GPL(mtd_read_oob); |
999 | 1005 | ||
1006 | int mtd_write_oob(struct mtd_info *mtd, loff_t to, | ||
1007 | struct mtd_oob_ops *ops) | ||
1008 | { | ||
1009 | ops->retlen = ops->oobretlen = 0; | ||
1010 | if (!mtd->_write_oob) | ||
1011 | return -EOPNOTSUPP; | ||
1012 | if (!(mtd->flags & MTD_WRITEABLE)) | ||
1013 | return -EROFS; | ||
1014 | ledtrig_mtd_activity(); | ||
1015 | return mtd->_write_oob(mtd, to, ops); | ||
1016 | } | ||
1017 | EXPORT_SYMBOL_GPL(mtd_write_oob); | ||
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 | |||
1000 | /* | 1379 | /* |
1001 | * Method to access the protection register area, present in some flash | 1380 | * Method to access the protection register area, present in some flash |
1002 | * 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 557b8462f55e..0b0dc29d2af7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -43,65 +43,100 @@ | |||
43 | #include <linux/mtd/nand_bch.h> | 43 | #include <linux/mtd/nand_bch.h> |
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/bitops.h> | 45 | #include <linux/bitops.h> |
46 | #include <linux/leds.h> | ||
47 | #include <linux/io.h> | 46 | #include <linux/io.h> |
48 | #include <linux/mtd/partitions.h> | 47 | #include <linux/mtd/partitions.h> |
49 | #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); | ||
50 | 54 | ||
51 | /* Define default oob placement schemes for large and small page devices */ | 55 | /* Define default oob placement schemes for large and small page devices */ |
52 | static struct nand_ecclayout nand_oob_8 = { | 56 | static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, |
53 | .eccbytes = 3, | 57 | struct mtd_oob_region *oobregion) |
54 | .eccpos = {0, 1, 2}, | 58 | { |
55 | .oobfree = { | 59 | struct nand_chip *chip = mtd_to_nand(mtd); |
56 | {.offset = 3, | 60 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
57 | .length = 2}, | ||
58 | {.offset = 6, | ||
59 | .length = 2} } | ||
60 | }; | ||
61 | 61 | ||
62 | static struct nand_ecclayout nand_oob_16 = { | 62 | if (section > 1) |
63 | .eccbytes = 6, | 63 | return -ERANGE; |
64 | .eccpos = {0, 1, 2, 3, 6, 7}, | ||
65 | .oobfree = { | ||
66 | {.offset = 8, | ||
67 | . length = 8} } | ||
68 | }; | ||
69 | 64 | ||
70 | static struct nand_ecclayout nand_oob_64 = { | 65 | if (!section) { |
71 | .eccbytes = 24, | 66 | oobregion->offset = 0; |
72 | .eccpos = { | 67 | oobregion->length = 4; |
73 | 40, 41, 42, 43, 44, 45, 46, 47, | 68 | } else { |
74 | 48, 49, 50, 51, 52, 53, 54, 55, | 69 | oobregion->offset = 6; |
75 | 56, 57, 58, 59, 60, 61, 62, 63}, | 70 | oobregion->length = ecc->total - 4; |
76 | .oobfree = { | 71 | } |
77 | {.offset = 2, | 72 | |
78 | .length = 38} } | 73 | return 0; |
79 | }; | 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; | ||
80 | 81 | ||
81 | static struct nand_ecclayout nand_oob_128 = { | 82 | if (mtd->oobsize == 16) { |
82 | .eccbytes = 48, | 83 | if (section) |
83 | .eccpos = { | 84 | return -ERANGE; |
84 | 80, 81, 82, 83, 84, 85, 86, 87, | 85 | |
85 | 88, 89, 90, 91, 92, 93, 94, 95, | 86 | oobregion->length = 8; |
86 | 96, 97, 98, 99, 100, 101, 102, 103, | 87 | oobregion->offset = 8; |
87 | 104, 105, 106, 107, 108, 109, 110, 111, | 88 | } else { |
88 | 112, 113, 114, 115, 116, 117, 118, 119, | 89 | oobregion->length = 2; |
89 | 120, 121, 122, 123, 124, 125, 126, 127}, | 90 | if (!section) |
90 | .oobfree = { | 91 | oobregion->offset = 3; |
91 | {.offset = 2, | 92 | else |
92 | .length = 78} } | 93 | oobregion->offset = 6; |
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = { | ||
100 | .ecc = nand_ooblayout_ecc_sp, | ||
101 | .free = nand_ooblayout_free_sp, | ||
93 | }; | 102 | }; |
103 | EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops); | ||
94 | 104 | ||
95 | 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; | ||
96 | 110 | ||
97 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | 111 | if (section) |
98 | struct mtd_oob_ops *ops); | 112 | return -ERANGE; |
99 | 113 | ||
100 | /* | 114 | oobregion->length = ecc->total; |
101 | * For devices which display every fart in the system on a separate LED. Is | 115 | oobregion->offset = mtd->oobsize - oobregion->length; |
102 | * compiled away when LED support is disabled. | 116 | |
103 | */ | 117 | return 0; |
104 | DEFINE_LED_TRIGGER(nand_led_trigger); | 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); | ||
105 | 140 | ||
106 | static int check_offs_len(struct mtd_info *mtd, | 141 | static int check_offs_len(struct mtd_info *mtd, |
107 | loff_t ofs, uint64_t len) | 142 | loff_t ofs, uint64_t len) |
@@ -540,19 +575,16 @@ void nand_wait_ready(struct mtd_info *mtd) | |||
540 | if (in_interrupt() || oops_in_progress) | 575 | if (in_interrupt() || oops_in_progress) |
541 | return panic_nand_wait_ready(mtd, timeo); | 576 | return panic_nand_wait_ready(mtd, timeo); |
542 | 577 | ||
543 | led_trigger_event(nand_led_trigger, LED_FULL); | ||
544 | /* Wait until command is processed or timeout occurs */ | 578 | /* Wait until command is processed or timeout occurs */ |
545 | timeo = jiffies + msecs_to_jiffies(timeo); | 579 | timeo = jiffies + msecs_to_jiffies(timeo); |
546 | do { | 580 | do { |
547 | if (chip->dev_ready(mtd)) | 581 | if (chip->dev_ready(mtd)) |
548 | goto out; | 582 | return; |
549 | cond_resched(); | 583 | cond_resched(); |
550 | } while (time_before(jiffies, timeo)); | 584 | } while (time_before(jiffies, timeo)); |
551 | 585 | ||
552 | if (!chip->dev_ready(mtd)) | 586 | if (!chip->dev_ready(mtd)) |
553 | pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); | 587 | pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); |
554 | out: | ||
555 | led_trigger_event(nand_led_trigger, LED_OFF); | ||
556 | } | 588 | } |
557 | EXPORT_SYMBOL_GPL(nand_wait_ready); | 589 | EXPORT_SYMBOL_GPL(nand_wait_ready); |
558 | 590 | ||
@@ -885,8 +917,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
885 | int status; | 917 | int status; |
886 | unsigned long timeo = 400; | 918 | unsigned long timeo = 400; |
887 | 919 | ||
888 | led_trigger_event(nand_led_trigger, LED_FULL); | ||
889 | |||
890 | /* | 920 | /* |
891 | * Apply this short delay always to ensure that we do wait tWB in any | 921 | * Apply this short delay always to ensure that we do wait tWB in any |
892 | * case on any machine. | 922 | * case on any machine. |
@@ -910,7 +940,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
910 | cond_resched(); | 940 | cond_resched(); |
911 | } while (time_before(jiffies, timeo)); | 941 | } while (time_before(jiffies, timeo)); |
912 | } | 942 | } |
913 | led_trigger_event(nand_led_trigger, LED_OFF); | ||
914 | 943 | ||
915 | status = (int)chip->read_byte(mtd); | 944 | status = (int)chip->read_byte(mtd); |
916 | /* This can happen if in case of timeout or buggy dev_ready */ | 945 | /* This can happen if in case of timeout or buggy dev_ready */ |
@@ -1292,13 +1321,12 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, | |||
1292 | 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, |
1293 | uint8_t *buf, int oob_required, int page) | 1322 | uint8_t *buf, int oob_required, int page) |
1294 | { | 1323 | { |
1295 | int i, eccsize = chip->ecc.size; | 1324 | int i, eccsize = chip->ecc.size, ret; |
1296 | int eccbytes = chip->ecc.bytes; | 1325 | int eccbytes = chip->ecc.bytes; |
1297 | int eccsteps = chip->ecc.steps; | 1326 | int eccsteps = chip->ecc.steps; |
1298 | uint8_t *p = buf; | 1327 | uint8_t *p = buf; |
1299 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1328 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1300 | uint8_t *ecc_code = chip->buffers->ecccode; | 1329 | uint8_t *ecc_code = chip->buffers->ecccode; |
1301 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
1302 | unsigned int max_bitflips = 0; | 1330 | unsigned int max_bitflips = 0; |
1303 | 1331 | ||
1304 | chip->ecc.read_page_raw(mtd, chip, buf, 1, page); | 1332 | chip->ecc.read_page_raw(mtd, chip, buf, 1, page); |
@@ -1306,8 +1334,10 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1306 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 1334 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
1307 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 1335 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1308 | 1336 | ||
1309 | for (i = 0; i < chip->ecc.total; i++) | 1337 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
1310 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1338 | chip->ecc.total); |
1339 | if (ret) | ||
1340 | return ret; | ||
1311 | 1341 | ||
1312 | eccsteps = chip->ecc.steps; | 1342 | eccsteps = chip->ecc.steps; |
1313 | p = buf; | 1343 | p = buf; |
@@ -1339,14 +1369,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1339 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, | 1369 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, |
1340 | int page) | 1370 | int page) |
1341 | { | 1371 | { |
1342 | int start_step, end_step, num_steps; | 1372 | int start_step, end_step, num_steps, ret; |
1343 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
1344 | uint8_t *p; | 1373 | uint8_t *p; |
1345 | int data_col_addr, i, gaps = 0; | 1374 | int data_col_addr, i, gaps = 0; |
1346 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1375 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1347 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1376 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1348 | int index; | 1377 | int index, section = 0; |
1349 | unsigned int max_bitflips = 0; | 1378 | unsigned int max_bitflips = 0; |
1379 | struct mtd_oob_region oobregion = { }; | ||
1350 | 1380 | ||
1351 | /* Column address within the page aligned to ECC size (256bytes) */ | 1381 | /* Column address within the page aligned to ECC size (256bytes) */ |
1352 | start_step = data_offs / chip->ecc.size; | 1382 | start_step = data_offs / chip->ecc.size; |
@@ -1374,12 +1404,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1374 | * The performance is faster if we position offsets according to | 1404 | * The performance is faster if we position offsets according to |
1375 | * 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. |
1376 | */ | 1406 | */ |
1377 | for (i = 0; i < eccfrag_len - 1; i++) { | 1407 | ret = mtd_ooblayout_find_eccregion(mtd, index, §ion, &oobregion); |
1378 | if (eccpos[i + index] + 1 != eccpos[i + index + 1]) { | 1408 | if (ret) |
1379 | gaps = 1; | 1409 | return ret; |
1380 | break; | 1410 | |
1381 | } | 1411 | if (oobregion.length < eccfrag_len) |
1382 | } | 1412 | gaps = 1; |
1413 | |||
1383 | if (gaps) { | 1414 | if (gaps) { |
1384 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | 1415 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); |
1385 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1416 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -1388,20 +1419,23 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1388 | * Send the command to read the particular ECC bytes take care | 1419 | * Send the command to read the particular ECC bytes take care |
1389 | * about buswidth alignment in read_buf. | 1420 | * about buswidth alignment in read_buf. |
1390 | */ | 1421 | */ |
1391 | aligned_pos = eccpos[index] & ~(busw - 1); | 1422 | aligned_pos = oobregion.offset & ~(busw - 1); |
1392 | aligned_len = eccfrag_len; | 1423 | aligned_len = eccfrag_len; |
1393 | if (eccpos[index] & (busw - 1)) | 1424 | if (oobregion.offset & (busw - 1)) |
1394 | aligned_len++; | 1425 | aligned_len++; |
1395 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) | 1426 | if ((oobregion.offset + (num_steps * chip->ecc.bytes)) & |
1427 | (busw - 1)) | ||
1396 | aligned_len++; | 1428 | aligned_len++; |
1397 | 1429 | ||
1398 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | 1430 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
1399 | mtd->writesize + aligned_pos, -1); | 1431 | mtd->writesize + aligned_pos, -1); |
1400 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | 1432 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); |
1401 | } | 1433 | } |
1402 | 1434 | ||
1403 | for (i = 0; i < eccfrag_len; i++) | 1435 | ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode, |
1404 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; | 1436 | chip->oob_poi, index, eccfrag_len); |
1437 | if (ret) | ||
1438 | return ret; | ||
1405 | 1439 | ||
1406 | p = bufpoi + data_col_addr; | 1440 | p = bufpoi + data_col_addr; |
1407 | 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) { |
@@ -1442,13 +1476,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1442 | 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, |
1443 | uint8_t *buf, int oob_required, int page) | 1477 | uint8_t *buf, int oob_required, int page) |
1444 | { | 1478 | { |
1445 | int i, eccsize = chip->ecc.size; | 1479 | int i, eccsize = chip->ecc.size, ret; |
1446 | int eccbytes = chip->ecc.bytes; | 1480 | int eccbytes = chip->ecc.bytes; |
1447 | int eccsteps = chip->ecc.steps; | 1481 | int eccsteps = chip->ecc.steps; |
1448 | uint8_t *p = buf; | 1482 | uint8_t *p = buf; |
1449 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1483 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1450 | uint8_t *ecc_code = chip->buffers->ecccode; | 1484 | uint8_t *ecc_code = chip->buffers->ecccode; |
1451 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
1452 | unsigned int max_bitflips = 0; | 1485 | unsigned int max_bitflips = 0; |
1453 | 1486 | ||
1454 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1487 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
@@ -1458,8 +1491,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1458 | } | 1491 | } |
1459 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1492 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1460 | 1493 | ||
1461 | for (i = 0; i < chip->ecc.total; i++) | 1494 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
1462 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1495 | chip->ecc.total); |
1496 | if (ret) | ||
1497 | return ret; | ||
1463 | 1498 | ||
1464 | eccsteps = chip->ecc.steps; | 1499 | eccsteps = chip->ecc.steps; |
1465 | p = buf; | 1500 | p = buf; |
@@ -1504,12 +1539,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1504 | 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, |
1505 | 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) |
1506 | { | 1541 | { |
1507 | int i, eccsize = chip->ecc.size; | 1542 | int i, eccsize = chip->ecc.size, ret; |
1508 | int eccbytes = chip->ecc.bytes; | 1543 | int eccbytes = chip->ecc.bytes; |
1509 | int eccsteps = chip->ecc.steps; | 1544 | int eccsteps = chip->ecc.steps; |
1510 | uint8_t *p = buf; | 1545 | uint8_t *p = buf; |
1511 | uint8_t *ecc_code = chip->buffers->ecccode; | 1546 | uint8_t *ecc_code = chip->buffers->ecccode; |
1512 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
1513 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1547 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1514 | unsigned int max_bitflips = 0; | 1548 | unsigned int max_bitflips = 0; |
1515 | 1549 | ||
@@ -1518,8 +1552,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
1518 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1552 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1519 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | 1553 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |
1520 | 1554 | ||
1521 | for (i = 0; i < chip->ecc.total; i++) | 1555 | ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, |
1522 | ecc_code[i] = chip->oob_poi[eccpos[i]]; | 1556 | chip->ecc.total); |
1557 | if (ret) | ||
1558 | return ret; | ||
1523 | 1559 | ||
1524 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1560 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1525 | int stat; | 1561 | int stat; |
@@ -1620,14 +1656,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1620 | 1656 | ||
1621 | /** | 1657 | /** |
1622 | * nand_transfer_oob - [INTERN] Transfer oob to client buffer | 1658 | * nand_transfer_oob - [INTERN] Transfer oob to client buffer |
1623 | * @chip: nand chip structure | 1659 | * @mtd: mtd info structure |
1624 | * @oob: oob destination address | 1660 | * @oob: oob destination address |
1625 | * @ops: oob ops structure | 1661 | * @ops: oob ops structure |
1626 | * @len: size of oob to transfer | 1662 | * @len: size of oob to transfer |
1627 | */ | 1663 | */ |
1628 | 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, |
1629 | struct mtd_oob_ops *ops, size_t len) | 1665 | struct mtd_oob_ops *ops, size_t len) |
1630 | { | 1666 | { |
1667 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
1668 | int ret; | ||
1669 | |||
1631 | switch (ops->mode) { | 1670 | switch (ops->mode) { |
1632 | 1671 | ||
1633 | case MTD_OPS_PLACE_OOB: | 1672 | case MTD_OPS_PLACE_OOB: |
@@ -1635,31 +1674,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
1635 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); | 1674 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); |
1636 | return oob + len; | 1675 | return oob + len; |
1637 | 1676 | ||
1638 | case MTD_OPS_AUTO_OOB: { | 1677 | case MTD_OPS_AUTO_OOB: |
1639 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 1678 | ret = mtd_ooblayout_get_databytes(mtd, oob, chip->oob_poi, |
1640 | uint32_t boffs = 0, roffs = ops->ooboffs; | 1679 | ops->ooboffs, len); |
1641 | size_t bytes = 0; | 1680 | BUG_ON(ret); |
1642 | 1681 | return oob + len; | |
1643 | for (; free->length && len; free++, len -= bytes) { | 1682 | |
1644 | /* Read request not from offset 0? */ | ||
1645 | if (unlikely(roffs)) { | ||
1646 | if (roffs >= free->length) { | ||
1647 | roffs -= free->length; | ||
1648 | continue; | ||
1649 | } | ||
1650 | boffs = free->offset + roffs; | ||
1651 | bytes = min_t(size_t, len, | ||
1652 | (free->length - roffs)); | ||
1653 | roffs = 0; | ||
1654 | } else { | ||
1655 | bytes = min_t(size_t, len, free->length); | ||
1656 | boffs = free->offset; | ||
1657 | } | ||
1658 | memcpy(oob, chip->oob_poi + boffs, bytes); | ||
1659 | oob += bytes; | ||
1660 | } | ||
1661 | return oob; | ||
1662 | } | ||
1663 | default: | 1683 | default: |
1664 | BUG(); | 1684 | BUG(); |
1665 | } | 1685 | } |
@@ -1793,7 +1813,7 @@ read_retry: | |||
1793 | int toread = min(oobreadlen, max_oobsize); | 1813 | int toread = min(oobreadlen, max_oobsize); |
1794 | 1814 | ||
1795 | if (toread) { | 1815 | if (toread) { |
1796 | oob = nand_transfer_oob(chip, | 1816 | oob = nand_transfer_oob(mtd, |
1797 | oob, ops, toread); | 1817 | oob, ops, toread); |
1798 | oobreadlen -= toread; | 1818 | oobreadlen -= toread; |
1799 | } | 1819 | } |
@@ -1906,13 +1926,13 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1906 | * @chip: nand chip info structure | 1926 | * @chip: nand chip info structure |
1907 | * @page: page number to read | 1927 | * @page: page number to read |
1908 | */ | 1928 | */ |
1909 | 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) |
1910 | int page) | ||
1911 | { | 1930 | { |
1912 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | 1931 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
1913 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1932 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1914 | return 0; | 1933 | return 0; |
1915 | } | 1934 | } |
1935 | EXPORT_SYMBOL(nand_read_oob_std); | ||
1916 | 1936 | ||
1917 | /** | 1937 | /** |
1918 | * 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 |
@@ -1921,8 +1941,8 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1921 | * @chip: nand chip info structure | 1941 | * @chip: nand chip info structure |
1922 | * @page: page number to read | 1942 | * @page: page number to read |
1923 | */ | 1943 | */ |
1924 | 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, |
1925 | int page) | 1945 | int page) |
1926 | { | 1946 | { |
1927 | int length = mtd->oobsize; | 1947 | int length = mtd->oobsize; |
1928 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 1948 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
@@ -1950,6 +1970,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1950 | 1970 | ||
1951 | return 0; | 1971 | return 0; |
1952 | } | 1972 | } |
1973 | EXPORT_SYMBOL(nand_read_oob_syndrome); | ||
1953 | 1974 | ||
1954 | /** | 1975 | /** |
1955 | * 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 |
@@ -1957,8 +1978,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1957 | * @chip: nand chip info structure | 1978 | * @chip: nand chip info structure |
1958 | * @page: page number to write | 1979 | * @page: page number to write |
1959 | */ | 1980 | */ |
1960 | 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) |
1961 | int page) | ||
1962 | { | 1982 | { |
1963 | int status = 0; | 1983 | int status = 0; |
1964 | const uint8_t *buf = chip->oob_poi; | 1984 | const uint8_t *buf = chip->oob_poi; |
@@ -1973,6 +1993,7 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1973 | 1993 | ||
1974 | return status & NAND_STATUS_FAIL ? -EIO : 0; | 1994 | return status & NAND_STATUS_FAIL ? -EIO : 0; |
1975 | } | 1995 | } |
1996 | EXPORT_SYMBOL(nand_write_oob_std); | ||
1976 | 1997 | ||
1977 | /** | 1998 | /** |
1978 | * 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 |
@@ -1981,8 +2002,8 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1981 | * @chip: nand chip info structure | 2002 | * @chip: nand chip info structure |
1982 | * @page: page number to write | 2003 | * @page: page number to write |
1983 | */ | 2004 | */ |
1984 | static int nand_write_oob_syndrome(struct mtd_info *mtd, | 2005 | int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1985 | struct nand_chip *chip, int page) | 2006 | int page) |
1986 | { | 2007 | { |
1987 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 2008 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
1988 | int eccsize = chip->ecc.size, length = mtd->oobsize; | 2009 | int eccsize = chip->ecc.size, length = mtd->oobsize; |
@@ -2032,6 +2053,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
2032 | 2053 | ||
2033 | return status & NAND_STATUS_FAIL ? -EIO : 0; | 2054 | return status & NAND_STATUS_FAIL ? -EIO : 0; |
2034 | } | 2055 | } |
2056 | EXPORT_SYMBOL(nand_write_oob_syndrome); | ||
2035 | 2057 | ||
2036 | /** | 2058 | /** |
2037 | * nand_do_read_oob - [INTERN] NAND read out-of-band | 2059 | * nand_do_read_oob - [INTERN] NAND read out-of-band |
@@ -2091,7 +2113,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
2091 | break; | 2113 | break; |
2092 | 2114 | ||
2093 | len = min(len, readlen); | 2115 | len = min(len, readlen); |
2094 | buf = nand_transfer_oob(chip, buf, ops, len); | 2116 | buf = nand_transfer_oob(mtd, buf, ops, len); |
2095 | 2117 | ||
2096 | if (chip->options & NAND_NEED_READRDY) { | 2118 | if (chip->options & NAND_NEED_READRDY) { |
2097 | /* Apply delay or wait for ready/busy pin */ | 2119 | /* Apply delay or wait for ready/busy pin */ |
@@ -2250,19 +2272,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
2250 | const uint8_t *buf, int oob_required, | 2272 | const uint8_t *buf, int oob_required, |
2251 | int page) | 2273 | int page) |
2252 | { | 2274 | { |
2253 | int i, eccsize = chip->ecc.size; | 2275 | int i, eccsize = chip->ecc.size, ret; |
2254 | int eccbytes = chip->ecc.bytes; | 2276 | int eccbytes = chip->ecc.bytes; |
2255 | int eccsteps = chip->ecc.steps; | 2277 | int eccsteps = chip->ecc.steps; |
2256 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 2278 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
2257 | const uint8_t *p = buf; | 2279 | const uint8_t *p = buf; |
2258 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
2259 | 2280 | ||
2260 | /* Software ECC calculation */ | 2281 | /* Software ECC calculation */ |
2261 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 2282 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
2262 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 2283 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
2263 | 2284 | ||
2264 | for (i = 0; i < chip->ecc.total; i++) | 2285 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
2265 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2286 | chip->ecc.total); |
2287 | if (ret) | ||
2288 | return ret; | ||
2266 | 2289 | ||
2267 | return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); | 2290 | return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); |
2268 | } | 2291 | } |
@@ -2279,12 +2302,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
2279 | const uint8_t *buf, int oob_required, | 2302 | const uint8_t *buf, int oob_required, |
2280 | int page) | 2303 | int page) |
2281 | { | 2304 | { |
2282 | int i, eccsize = chip->ecc.size; | 2305 | int i, eccsize = chip->ecc.size, ret; |
2283 | int eccbytes = chip->ecc.bytes; | 2306 | int eccbytes = chip->ecc.bytes; |
2284 | int eccsteps = chip->ecc.steps; | 2307 | int eccsteps = chip->ecc.steps; |
2285 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 2308 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
2286 | const uint8_t *p = buf; | 2309 | const uint8_t *p = buf; |
2287 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
2288 | 2310 | ||
2289 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 2311 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
2290 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | 2312 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
@@ -2292,8 +2314,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
2292 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 2314 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
2293 | } | 2315 | } |
2294 | 2316 | ||
2295 | for (i = 0; i < chip->ecc.total; i++) | 2317 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
2296 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2318 | chip->ecc.total); |
2319 | if (ret) | ||
2320 | return ret; | ||
2297 | 2321 | ||
2298 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 2322 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
2299 | 2323 | ||
@@ -2321,11 +2345,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, | |||
2321 | int ecc_size = chip->ecc.size; | 2345 | int ecc_size = chip->ecc.size; |
2322 | int ecc_bytes = chip->ecc.bytes; | 2346 | int ecc_bytes = chip->ecc.bytes; |
2323 | int ecc_steps = chip->ecc.steps; | 2347 | int ecc_steps = chip->ecc.steps; |
2324 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
2325 | uint32_t start_step = offset / ecc_size; | 2348 | uint32_t start_step = offset / ecc_size; |
2326 | uint32_t end_step = (offset + data_len - 1) / ecc_size; | 2349 | uint32_t end_step = (offset + data_len - 1) / ecc_size; |
2327 | int oob_bytes = mtd->oobsize / ecc_steps; | 2350 | int oob_bytes = mtd->oobsize / ecc_steps; |
2328 | int step, i; | 2351 | int step, ret; |
2329 | 2352 | ||
2330 | for (step = 0; step < ecc_steps; step++) { | 2353 | for (step = 0; step < ecc_steps; step++) { |
2331 | /* configure controller for WRITE access */ | 2354 | /* configure controller for WRITE access */ |
@@ -2353,8 +2376,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, | |||
2353 | /* copy calculated ECC for whole page to chip->buffer->oob */ | 2376 | /* copy calculated ECC for whole page to chip->buffer->oob */ |
2354 | /* this include masked-value(0xFF) for unwritten subpages */ | 2377 | /* this include masked-value(0xFF) for unwritten subpages */ |
2355 | ecc_calc = chip->buffers->ecccalc; | 2378 | ecc_calc = chip->buffers->ecccalc; |
2356 | for (i = 0; i < chip->ecc.total; i++) | 2379 | ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, |
2357 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2380 | chip->ecc.total); |
2381 | if (ret) | ||
2382 | return ret; | ||
2358 | 2383 | ||
2359 | /* write OOB buffer to NAND device */ | 2384 | /* write OOB buffer to NAND device */ |
2360 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 2385 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -2491,6 +2516,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, | |||
2491 | struct mtd_oob_ops *ops) | 2516 | struct mtd_oob_ops *ops) |
2492 | { | 2517 | { |
2493 | struct nand_chip *chip = mtd_to_nand(mtd); | 2518 | struct nand_chip *chip = mtd_to_nand(mtd); |
2519 | int ret; | ||
2494 | 2520 | ||
2495 | /* | 2521 | /* |
2496 | * 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 |
@@ -2505,31 +2531,12 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, | |||
2505 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); | 2531 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); |
2506 | return oob + len; | 2532 | return oob + len; |
2507 | 2533 | ||
2508 | case MTD_OPS_AUTO_OOB: { | 2534 | case MTD_OPS_AUTO_OOB: |
2509 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 2535 | ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi, |
2510 | uint32_t boffs = 0, woffs = ops->ooboffs; | 2536 | ops->ooboffs, len); |
2511 | size_t bytes = 0; | 2537 | BUG_ON(ret); |
2512 | 2538 | return oob + len; | |
2513 | for (; free->length && len; free++, len -= bytes) { | 2539 | |
2514 | /* Write request not from offset 0? */ | ||
2515 | if (unlikely(woffs)) { | ||
2516 | if (woffs >= free->length) { | ||
2517 | woffs -= free->length; | ||
2518 | continue; | ||
2519 | } | ||
2520 | boffs = free->offset + woffs; | ||
2521 | bytes = min_t(size_t, len, | ||
2522 | (free->length - woffs)); | ||
2523 | woffs = 0; | ||
2524 | } else { | ||
2525 | bytes = min_t(size_t, len, free->length); | ||
2526 | boffs = free->offset; | ||
2527 | } | ||
2528 | memcpy(chip->oob_poi + boffs, oob, bytes); | ||
2529 | oob += bytes; | ||
2530 | } | ||
2531 | return oob; | ||
2532 | } | ||
2533 | default: | 2540 | default: |
2534 | BUG(); | 2541 | BUG(); |
2535 | } | 2542 | } |
@@ -3964,10 +3971,115 @@ ident_done: | |||
3964 | return type; | 3971 | return type; |
3965 | } | 3972 | } |
3966 | 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 | |||
3967 | static int nand_dt_init(struct nand_chip *chip) | 4079 | static int nand_dt_init(struct nand_chip *chip) |
3968 | { | 4080 | { |
3969 | struct device_node *dn = nand_get_flash_node(chip); | 4081 | struct device_node *dn = nand_get_flash_node(chip); |
3970 | int ecc_mode, ecc_strength, ecc_step; | 4082 | int ecc_mode, ecc_algo, ecc_strength, ecc_step; |
3971 | 4083 | ||
3972 | if (!dn) | 4084 | if (!dn) |
3973 | return 0; | 4085 | return 0; |
@@ -3979,6 +4091,7 @@ static int nand_dt_init(struct nand_chip *chip) | |||
3979 | chip->bbt_options |= NAND_BBT_USE_FLASH; | 4091 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
3980 | 4092 | ||
3981 | 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); | ||
3982 | ecc_strength = of_get_nand_ecc_strength(dn); | 4095 | ecc_strength = of_get_nand_ecc_strength(dn); |
3983 | ecc_step = of_get_nand_ecc_step_size(dn); | 4096 | ecc_step = of_get_nand_ecc_step_size(dn); |
3984 | 4097 | ||
@@ -3991,6 +4104,9 @@ static int nand_dt_init(struct nand_chip *chip) | |||
3991 | if (ecc_mode >= 0) | 4104 | if (ecc_mode >= 0) |
3992 | chip->ecc.mode = ecc_mode; | 4105 | chip->ecc.mode = ecc_mode; |
3993 | 4106 | ||
4107 | if (ecc_algo >= 0) | ||
4108 | chip->ecc.algo = ecc_algo; | ||
4109 | |||
3994 | if (ecc_strength >= 0) | 4110 | if (ecc_strength >= 0) |
3995 | chip->ecc.strength = ecc_strength; | 4111 | chip->ecc.strength = ecc_strength; |
3996 | 4112 | ||
@@ -4067,6 +4183,82 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
4067 | } | 4183 | } |
4068 | EXPORT_SYMBOL(nand_scan_ident); | 4184 | EXPORT_SYMBOL(nand_scan_ident); |
4069 | 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 | |||
4070 | /* | 4262 | /* |
4071 | * Check if the chip configuration meet the datasheet requirements. | 4263 | * Check if the chip configuration meet the datasheet requirements. |
4072 | 4264 | ||
@@ -4111,14 +4303,15 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) | |||
4111 | */ | 4303 | */ |
4112 | int nand_scan_tail(struct mtd_info *mtd) | 4304 | int nand_scan_tail(struct mtd_info *mtd) |
4113 | { | 4305 | { |
4114 | int i; | ||
4115 | struct nand_chip *chip = mtd_to_nand(mtd); | 4306 | struct nand_chip *chip = mtd_to_nand(mtd); |
4116 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 4307 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
4117 | struct nand_buffers *nbuf; | 4308 | struct nand_buffers *nbuf; |
4309 | int ret; | ||
4118 | 4310 | ||
4119 | /* 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 */ |
4120 | BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && | 4312 | if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && |
4121 | !(chip->bbt_options & NAND_BBT_USE_FLASH)); | 4313 | !(chip->bbt_options & NAND_BBT_USE_FLASH))) |
4314 | return -EINVAL; | ||
4122 | 4315 | ||
4123 | if (!(chip->options & NAND_OWN_BUFFERS)) { | 4316 | if (!(chip->options & NAND_OWN_BUFFERS)) { |
4124 | nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize | 4317 | nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize |
@@ -4141,24 +4334,22 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4141 | /* | 4334 | /* |
4142 | * If no default placement scheme is given, select an appropriate one. | 4335 | * If no default placement scheme is given, select an appropriate one. |
4143 | */ | 4336 | */ |
4144 | if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) { | 4337 | if (!mtd->ooblayout && |
4338 | !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH)) { | ||
4145 | switch (mtd->oobsize) { | 4339 | switch (mtd->oobsize) { |
4146 | case 8: | 4340 | case 8: |
4147 | ecc->layout = &nand_oob_8; | ||
4148 | break; | ||
4149 | case 16: | 4341 | case 16: |
4150 | ecc->layout = &nand_oob_16; | 4342 | mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops); |
4151 | break; | 4343 | break; |
4152 | case 64: | 4344 | case 64: |
4153 | ecc->layout = &nand_oob_64; | ||
4154 | break; | ||
4155 | case 128: | 4345 | case 128: |
4156 | ecc->layout = &nand_oob_128; | 4346 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); |
4157 | break; | 4347 | break; |
4158 | default: | 4348 | default: |
4159 | pr_warn("No oob scheme defined for oobsize %d\n", | 4349 | WARN(1, "No oob scheme defined for oobsize %d\n", |
4160 | mtd->oobsize); | 4350 | mtd->oobsize); |
4161 | BUG(); | 4351 | ret = -EINVAL; |
4352 | goto err_free; | ||
4162 | } | 4353 | } |
4163 | } | 4354 | } |
4164 | 4355 | ||
@@ -4174,8 +4365,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4174 | case NAND_ECC_HW_OOB_FIRST: | 4365 | case NAND_ECC_HW_OOB_FIRST: |
4175 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ | 4366 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ |
4176 | if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { | 4367 | if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { |
4177 | pr_warn("No ECC functions supplied; hardware ECC not possible\n"); | 4368 | WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); |
4178 | BUG(); | 4369 | ret = -EINVAL; |
4370 | goto err_free; | ||
4179 | } | 4371 | } |
4180 | if (!ecc->read_page) | 4372 | if (!ecc->read_page) |
4181 | ecc->read_page = nand_read_page_hwecc_oob_first; | 4373 | ecc->read_page = nand_read_page_hwecc_oob_first; |
@@ -4205,8 +4397,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4205 | ecc->read_page == nand_read_page_hwecc || | 4397 | ecc->read_page == nand_read_page_hwecc || |
4206 | !ecc->write_page || | 4398 | !ecc->write_page || |
4207 | ecc->write_page == nand_write_page_hwecc)) { | 4399 | ecc->write_page == nand_write_page_hwecc)) { |
4208 | pr_warn("No ECC functions supplied; hardware ECC not possible\n"); | 4400 | WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); |
4209 | BUG(); | 4401 | ret = -EINVAL; |
4402 | goto err_free; | ||
4210 | } | 4403 | } |
4211 | /* Use standard syndrome read/write page function? */ | 4404 | /* Use standard syndrome read/write page function? */ |
4212 | if (!ecc->read_page) | 4405 | if (!ecc->read_page) |
@@ -4224,61 +4417,22 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4224 | 4417 | ||
4225 | if (mtd->writesize >= ecc->size) { | 4418 | if (mtd->writesize >= ecc->size) { |
4226 | if (!ecc->strength) { | 4419 | if (!ecc->strength) { |
4227 | 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"); |
4228 | BUG(); | 4421 | ret = -EINVAL; |
4422 | goto err_free; | ||
4229 | } | 4423 | } |
4230 | break; | 4424 | break; |
4231 | } | 4425 | } |
4232 | 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", |
4233 | ecc->size, mtd->writesize); | 4427 | ecc->size, mtd->writesize); |
4234 | ecc->mode = NAND_ECC_SOFT; | 4428 | ecc->mode = NAND_ECC_SOFT; |
4429 | ecc->algo = NAND_ECC_HAMMING; | ||
4235 | 4430 | ||
4236 | case NAND_ECC_SOFT: | 4431 | case NAND_ECC_SOFT: |
4237 | ecc->calculate = nand_calculate_ecc; | 4432 | ret = nand_set_ecc_soft_ops(mtd); |
4238 | ecc->correct = nand_correct_data; | 4433 | if (ret) { |
4239 | ecc->read_page = nand_read_page_swecc; | 4434 | ret = -EINVAL; |
4240 | ecc->read_subpage = nand_read_subpage; | 4435 | goto err_free; |
4241 | ecc->write_page = nand_write_page_swecc; | ||
4242 | ecc->read_page_raw = nand_read_page_raw; | ||
4243 | ecc->write_page_raw = nand_write_page_raw; | ||
4244 | ecc->read_oob = nand_read_oob_std; | ||
4245 | ecc->write_oob = nand_write_oob_std; | ||
4246 | if (!ecc->size) | ||
4247 | ecc->size = 256; | ||
4248 | ecc->bytes = 3; | ||
4249 | ecc->strength = 1; | ||
4250 | break; | ||
4251 | |||
4252 | case NAND_ECC_SOFT_BCH: | ||
4253 | if (!mtd_nand_has_bch()) { | ||
4254 | pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | ||
4255 | BUG(); | ||
4256 | } | ||
4257 | ecc->calculate = nand_bch_calculate_ecc; | ||
4258 | ecc->correct = nand_bch_correct_data; | ||
4259 | ecc->read_page = nand_read_page_swecc; | ||
4260 | ecc->read_subpage = nand_read_subpage; | ||
4261 | ecc->write_page = nand_write_page_swecc; | ||
4262 | ecc->read_page_raw = nand_read_page_raw; | ||
4263 | ecc->write_page_raw = nand_write_page_raw; | ||
4264 | ecc->read_oob = nand_read_oob_std; | ||
4265 | ecc->write_oob = nand_write_oob_std; | ||
4266 | /* | ||
4267 | * Board driver should supply ecc.size and ecc.strength values | ||
4268 | * to select how many bits are correctable. Otherwise, default | ||
4269 | * to 4 bits for large page devices. | ||
4270 | */ | ||
4271 | if (!ecc->size && (mtd->oobsize >= 64)) { | ||
4272 | ecc->size = 512; | ||
4273 | ecc->strength = 4; | ||
4274 | } | ||
4275 | |||
4276 | /* See nand_bch_init() for details. */ | ||
4277 | ecc->bytes = 0; | ||
4278 | ecc->priv = nand_bch_init(mtd); | ||
4279 | if (!ecc->priv) { | ||
4280 | pr_warn("BCH ECC initialization failed!\n"); | ||
4281 | BUG(); | ||
4282 | } | 4436 | } |
4283 | break; | 4437 | break; |
4284 | 4438 | ||
@@ -4296,8 +4450,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4296 | break; | 4450 | break; |
4297 | 4451 | ||
4298 | default: | 4452 | default: |
4299 | pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode); | 4453 | WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode); |
4300 | BUG(); | 4454 | ret = -EINVAL; |
4455 | goto err_free; | ||
4301 | } | 4456 | } |
4302 | 4457 | ||
4303 | /* For many systems, the standard OOB write also works for raw */ | 4458 | /* For many systems, the standard OOB write also works for raw */ |
@@ -4306,20 +4461,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4306 | if (!ecc->write_oob_raw) | 4461 | if (!ecc->write_oob_raw) |
4307 | ecc->write_oob_raw = ecc->write_oob; | 4462 | ecc->write_oob_raw = ecc->write_oob; |
4308 | 4463 | ||
4309 | /* | 4464 | /* propagate ecc info to mtd_info */ |
4310 | * The number of bytes available for a client to place data into | 4465 | mtd->ecc_strength = ecc->strength; |
4311 | * the out of band area. | 4466 | mtd->ecc_step_size = ecc->size; |
4312 | */ | ||
4313 | mtd->oobavail = 0; | ||
4314 | if (ecc->layout) { | ||
4315 | for (i = 0; ecc->layout->oobfree[i].length; i++) | ||
4316 | mtd->oobavail += ecc->layout->oobfree[i].length; | ||
4317 | } | ||
4318 | |||
4319 | /* ECC sanity check: warn if it's too weak */ | ||
4320 | if (!nand_ecc_strength_good(mtd)) | ||
4321 | pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", | ||
4322 | mtd->name); | ||
4323 | 4467 | ||
4324 | /* | 4468 | /* |
4325 | * 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 |
@@ -4327,11 +4471,27 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4327 | */ | 4471 | */ |
4328 | ecc->steps = mtd->writesize / ecc->size; | 4472 | ecc->steps = mtd->writesize / ecc->size; |
4329 | if (ecc->steps * ecc->size != mtd->writesize) { | 4473 | if (ecc->steps * ecc->size != mtd->writesize) { |
4330 | pr_warn("Invalid ECC parameters\n"); | 4474 | WARN(1, "Invalid ECC parameters\n"); |
4331 | BUG(); | 4475 | ret = -EINVAL; |
4476 | goto err_free; | ||
4332 | } | 4477 | } |
4333 | ecc->total = ecc->steps * ecc->bytes; | 4478 | ecc->total = ecc->steps * ecc->bytes; |
4334 | 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 | |||
4335 | /* 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 */ |
4336 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { | 4496 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { |
4337 | switch (ecc->steps) { | 4497 | switch (ecc->steps) { |
@@ -4356,7 +4516,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4356 | /* Large page NAND with SOFT_ECC should support subpage reads */ | 4516 | /* Large page NAND with SOFT_ECC should support subpage reads */ |
4357 | switch (ecc->mode) { | 4517 | switch (ecc->mode) { |
4358 | case NAND_ECC_SOFT: | 4518 | case NAND_ECC_SOFT: |
4359 | case NAND_ECC_SOFT_BCH: | ||
4360 | if (chip->page_shift > 9) | 4519 | if (chip->page_shift > 9) |
4361 | chip->options |= NAND_SUBPAGE_READ; | 4520 | chip->options |= NAND_SUBPAGE_READ; |
4362 | break; | 4521 | break; |
@@ -4388,10 +4547,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4388 | mtd->_block_markbad = nand_block_markbad; | 4547 | mtd->_block_markbad = nand_block_markbad; |
4389 | mtd->writebufsize = mtd->writesize; | 4548 | mtd->writebufsize = mtd->writesize; |
4390 | 4549 | ||
4391 | /* propagate ecc info to mtd_info */ | ||
4392 | mtd->ecclayout = ecc->layout; | ||
4393 | mtd->ecc_strength = ecc->strength; | ||
4394 | mtd->ecc_step_size = ecc->size; | ||
4395 | /* | 4550 | /* |
4396 | * Initialize bitflip_threshold to its default prior scan_bbt() call. | 4551 | * Initialize bitflip_threshold to its default prior scan_bbt() call. |
4397 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be | 4552 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be |
@@ -4406,6 +4561,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4406 | 4561 | ||
4407 | /* Build bad block table */ | 4562 | /* Build bad block table */ |
4408 | 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; | ||
4409 | } | 4568 | } |
4410 | EXPORT_SYMBOL(nand_scan_tail); | 4569 | EXPORT_SYMBOL(nand_scan_tail); |
4411 | 4570 | ||
@@ -4449,7 +4608,8 @@ void nand_release(struct mtd_info *mtd) | |||
4449 | { | 4608 | { |
4450 | struct nand_chip *chip = mtd_to_nand(mtd); | 4609 | struct nand_chip *chip = mtd_to_nand(mtd); |
4451 | 4610 | ||
4452 | if (chip->ecc.mode == NAND_ECC_SOFT_BCH) | 4611 | if (chip->ecc.mode == NAND_ECC_SOFT && |
4612 | chip->ecc.algo == NAND_ECC_BCH) | ||
4453 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); | 4613 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); |
4454 | 4614 | ||
4455 | mtd_device_unregister(mtd); | 4615 | mtd_device_unregister(mtd); |
@@ -4466,20 +4626,6 @@ void nand_release(struct mtd_info *mtd) | |||
4466 | } | 4626 | } |
4467 | EXPORT_SYMBOL_GPL(nand_release); | 4627 | EXPORT_SYMBOL_GPL(nand_release); |
4468 | 4628 | ||
4469 | static int __init nand_base_init(void) | ||
4470 | { | ||
4471 | led_trigger_register_simple("nand-disk", &nand_led_trigger); | ||
4472 | return 0; | ||
4473 | } | ||
4474 | |||
4475 | static void __exit nand_base_exit(void) | ||
4476 | { | ||
4477 | led_trigger_unregister_simple(nand_led_trigger); | ||
4478 | } | ||
4479 | |||
4480 | module_init(nand_base_init); | ||
4481 | module_exit(nand_base_exit); | ||
4482 | |||
4483 | MODULE_LICENSE("GPL"); | 4629 | MODULE_LICENSE("GPL"); |
4484 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); | 4630 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); |
4485 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | 4631 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); |
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index b585bae37929..28ef7b178eac 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 probaly 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 1fd519503bb1..794745dff7f1 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/of/Makefile b/drivers/of/Makefile index 156c072b3117..e31bdc123c6e 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/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/leds.h b/include/linux/leds.h index f203a8f89d30..19eb10278bea 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h | |||
@@ -329,6 +329,12 @@ extern void ledtrig_ide_activity(void); | |||
329 | static inline void ledtrig_ide_activity(void) {} | 329 | static inline void ledtrig_ide_activity(void) {} |
330 | #endif | 330 | #endif |
331 | 331 | ||
332 | #ifdef CONFIG_LEDS_TRIGGER_MTD | ||
333 | extern void ledtrig_mtd_activity(void); | ||
334 | #else | ||
335 | static inline void ledtrig_mtd_activity(void) {} | ||
336 | #endif | ||
337 | |||
332 | #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE) | 338 | #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE) |
333 | extern void ledtrig_flash_ctrl(bool on); | 339 | extern void ledtrig_flash_ctrl(bool on); |
334 | extern void ledtrig_torch_ctrl(bool on); | 340 | extern void ledtrig_torch_ctrl(bool on); |
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/mtd.h b/include/linux/mtd/mtd.h index 771272187316..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 | { |
@@ -283,17 +326,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | |||
283 | const u_char *buf); | 326 | const u_char *buf); |
284 | 327 | ||
285 | int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); | 328 | int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); |
286 | 329 | int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); | |
287 | static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, | ||
288 | struct mtd_oob_ops *ops) | ||
289 | { | ||
290 | ops->retlen = ops->oobretlen = 0; | ||
291 | if (!mtd->_write_oob) | ||
292 | return -EOPNOTSUPP; | ||
293 | if (!(mtd->flags & MTD_WRITEABLE)) | ||
294 | return -EROFS; | ||
295 | return mtd->_write_oob(mtd, to, ops); | ||
296 | } | ||
297 | 330 | ||
298 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, | 331 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
299 | struct otp_info *buf); | 332 | struct otp_info *buf); |
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/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; |