diff options
83 files changed, 3181 insertions, 647 deletions
diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt index 03855c8c492a..b53f92e252d4 100644 --- a/Documentation/devicetree/bindings/mtd/nand.txt +++ b/Documentation/devicetree/bindings/mtd/nand.txt | |||
@@ -5,3 +5,17 @@ | |||
5 | "soft_bch". | 5 | "soft_bch". |
6 | - nand-bus-width : 8 or 16 bus width if not present 8 | 6 | - 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 | 7 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false |
8 | |||
9 | - nand-ecc-strength: integer representing the number of bits to correct | ||
10 | per ECC step. | ||
11 | |||
12 | - nand-ecc-step-size: integer representing the number of data bytes | ||
13 | that are covered by a single ECC step. | ||
14 | |||
15 | The ECC strength and ECC step size properties define the correction capability | ||
16 | of a controller. Together, they say a controller can correct "{strength} bit | ||
17 | errors per {size} bytes". | ||
18 | |||
19 | The interpretation of these parameters is implementation-defined, so not all | ||
20 | implementations must support all possible combinations. However, implementations | ||
21 | are encouraged to further specify the value(s) they support. | ||
diff --git a/Documentation/devicetree/bindings/mtd/st-fsm.txt b/Documentation/devicetree/bindings/mtd/st-fsm.txt new file mode 100644 index 000000000000..c2489391c437 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/st-fsm.txt | |||
@@ -0,0 +1,26 @@ | |||
1 | * ST-Microelectronics SPI FSM Serial (NOR) Flash Controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : Should be "st,spi-fsm" | ||
5 | - reg : Contains register's location and length. | ||
6 | - reg-names : Should contain the reg names "spi-fsm" | ||
7 | - interrupts : The interrupt number | ||
8 | - pinctrl-0 : Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt) | ||
9 | |||
10 | Optional properties: | ||
11 | - st,syscfg : Phandle to boot-device system configuration registers | ||
12 | - st,boot-device-reg : Address of the aforementioned boot-device register(s) | ||
13 | - st,boot-device-spi : Expected boot-device value if booted via this device | ||
14 | |||
15 | Example: | ||
16 | spifsm: spifsm@fe902000{ | ||
17 | compatible = "st,spi-fsm"; | ||
18 | reg = <0xfe902000 0x1000>; | ||
19 | reg-names = "spi-fsm"; | ||
20 | pinctrl-0 = <&pinctrl_fsm>; | ||
21 | st,syscfg = <&syscfg_rear>; | ||
22 | st,boot-device-reg = <0x958>; | ||
23 | st,boot-device-spi = <0x1a>; | ||
24 | status = "okay"; | ||
25 | }; | ||
26 | |||
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 5ebcda39f554..5d49a2129618 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -150,7 +150,7 @@ config MTD_BCM63XX_PARTS | |||
150 | 150 | ||
151 | config MTD_BCM47XX_PARTS | 151 | config MTD_BCM47XX_PARTS |
152 | tristate "BCM47XX partitioning support" | 152 | tristate "BCM47XX partitioning support" |
153 | depends on BCM47XX | 153 | depends on BCM47XX || ARCH_BCM_5301X |
154 | help | 154 | help |
155 | This provides partitions parser for devices based on BCM47xx | 155 | This provides partitions parser for devices based on BCM47xx |
156 | boards. | 156 | boards. |
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index de1eb92e42f5..adfa74c1bc45 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
16 | #include <linux/mtd/partitions.h> | 16 | #include <linux/mtd/partitions.h> |
17 | #include <bcm47xx_nvram.h> | ||
18 | 17 | ||
19 | /* 10 parts were found on sflash on Netgear WNDR4500 */ | 18 | /* 10 parts were found on sflash on Netgear WNDR4500 */ |
20 | #define BCM47XXPART_MAX_PARTS 12 | 19 | #define BCM47XXPART_MAX_PARTS 12 |
@@ -30,6 +29,7 @@ | |||
30 | #define BOARD_DATA_MAGIC2 0xBD0D0BBD | 29 | #define BOARD_DATA_MAGIC2 0xBD0D0BBD |
31 | #define CFE_MAGIC 0x43464531 /* 1EFC */ | 30 | #define CFE_MAGIC 0x43464531 /* 1EFC */ |
32 | #define FACTORY_MAGIC 0x59544346 /* FCTY */ | 31 | #define FACTORY_MAGIC 0x59544346 /* FCTY */ |
32 | #define NVRAM_HEADER 0x48534C46 /* FLSH */ | ||
33 | #define POT_MAGIC1 0x54544f50 /* POTT */ | 33 | #define POT_MAGIC1 0x54544f50 /* POTT */ |
34 | #define POT_MAGIC2 0x504f /* OP */ | 34 | #define POT_MAGIC2 0x504f /* OP */ |
35 | #define ML_MAGIC1 0x39685a42 | 35 | #define ML_MAGIC1 0x39685a42 |
@@ -91,7 +91,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
91 | if (offset >= 0x2000000) | 91 | if (offset >= 0x2000000) |
92 | break; | 92 | break; |
93 | 93 | ||
94 | if (curr_part > BCM47XXPART_MAX_PARTS) { | 94 | if (curr_part >= BCM47XXPART_MAX_PARTS) { |
95 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); | 95 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); |
96 | break; | 96 | break; |
97 | } | 97 | } |
@@ -147,6 +147,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
147 | 147 | ||
148 | /* TRX */ | 148 | /* TRX */ |
149 | if (buf[0x000 / 4] == TRX_MAGIC) { | 149 | if (buf[0x000 / 4] == TRX_MAGIC) { |
150 | if (BCM47XXPART_MAX_PARTS - curr_part < 4) { | ||
151 | pr_warn("Not enough partitions left to register trx, scanning stopped!\n"); | ||
152 | break; | ||
153 | } | ||
154 | |||
150 | trx = (struct trx_header *)buf; | 155 | trx = (struct trx_header *)buf; |
151 | 156 | ||
152 | trx_part = curr_part; | 157 | trx_part = curr_part; |
@@ -212,7 +217,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
212 | 217 | ||
213 | /* Look for NVRAM at the end of the last block. */ | 218 | /* Look for NVRAM at the end of the last block. */ |
214 | for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) { | 219 | for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) { |
215 | if (curr_part > BCM47XXPART_MAX_PARTS) { | 220 | if (curr_part >= BCM47XXPART_MAX_PARTS) { |
216 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); | 221 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); |
217 | break; | 222 | break; |
218 | } | 223 | } |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 77514430f1fe..e4ec355704a6 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/init.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <asm/byteorder.h> | 25 | #include <asm/byteorder.h> |
27 | 26 | ||
@@ -69,10 +68,10 @@ static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, s | |||
69 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 68 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
70 | static int cfi_intelext_write_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 69 | static int cfi_intelext_write_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
71 | static int cfi_intelext_lock_user_prot_reg (struct mtd_info *, loff_t, size_t); | 70 | static int cfi_intelext_lock_user_prot_reg (struct mtd_info *, loff_t, size_t); |
72 | static int cfi_intelext_get_fact_prot_info (struct mtd_info *, | 71 | static int cfi_intelext_get_fact_prot_info(struct mtd_info *, size_t, |
73 | struct otp_info *, size_t); | 72 | size_t *, struct otp_info *); |
74 | static int cfi_intelext_get_user_prot_info (struct mtd_info *, | 73 | static int cfi_intelext_get_user_prot_info(struct mtd_info *, size_t, |
75 | struct otp_info *, size_t); | 74 | size_t *, struct otp_info *); |
76 | #endif | 75 | #endif |
77 | static int cfi_intelext_suspend (struct mtd_info *); | 76 | static int cfi_intelext_suspend (struct mtd_info *); |
78 | static void cfi_intelext_resume (struct mtd_info *); | 77 | static void cfi_intelext_resume (struct mtd_info *); |
@@ -435,10 +434,8 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
435 | int i; | 434 | int i; |
436 | 435 | ||
437 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); | 436 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); |
438 | if (!mtd) { | 437 | if (!mtd) |
439 | printk(KERN_ERR "Failed to allocate memory for MTD device\n"); | ||
440 | return NULL; | 438 | return NULL; |
441 | } | ||
442 | mtd->priv = map; | 439 | mtd->priv = map; |
443 | mtd->type = MTD_NORFLASH; | 440 | mtd->type = MTD_NORFLASH; |
444 | 441 | ||
@@ -564,10 +561,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) | |||
564 | mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; | 561 | mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; |
565 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) | 562 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) |
566 | * mtd->numeraseregions, GFP_KERNEL); | 563 | * mtd->numeraseregions, GFP_KERNEL); |
567 | if (!mtd->eraseregions) { | 564 | if (!mtd->eraseregions) |
568 | printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); | ||
569 | goto setup_err; | 565 | goto setup_err; |
570 | } | ||
571 | 566 | ||
572 | for (i=0; i<cfi->cfiq->NumEraseRegions; i++) { | 567 | for (i=0; i<cfi->cfiq->NumEraseRegions; i++) { |
573 | unsigned long ernum, ersize; | 568 | unsigned long ernum, ersize; |
@@ -2399,24 +2394,19 @@ static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd, | |||
2399 | NULL, do_otp_lock, 1); | 2394 | NULL, do_otp_lock, 1); |
2400 | } | 2395 | } |
2401 | 2396 | ||
2402 | static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, | 2397 | static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, size_t len, |
2403 | struct otp_info *buf, size_t len) | 2398 | size_t *retlen, struct otp_info *buf) |
2404 | { | ||
2405 | size_t retlen; | ||
2406 | int ret; | ||
2407 | 2399 | ||
2408 | ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 0); | 2400 | { |
2409 | return ret ? : retlen; | 2401 | return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf, |
2402 | NULL, 0); | ||
2410 | } | 2403 | } |
2411 | 2404 | ||
2412 | static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd, | 2405 | static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd, size_t len, |
2413 | struct otp_info *buf, size_t len) | 2406 | size_t *retlen, struct otp_info *buf) |
2414 | { | 2407 | { |
2415 | size_t retlen; | 2408 | return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf, |
2416 | int ret; | 2409 | NULL, 1); |
2417 | |||
2418 | ret = cfi_intelext_otp_walk(mtd, 0, len, &retlen, (u_char *)buf, NULL, 1); | ||
2419 | return ret ? : retlen; | ||
2420 | } | 2410 | } |
2421 | 2411 | ||
2422 | #endif | 2412 | #endif |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 89b9d6891532..e21fde9d4d7e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/init.h> | ||
28 | #include <asm/io.h> | 27 | #include <asm/io.h> |
29 | #include <asm/byteorder.h> | 28 | #include <asm/byteorder.h> |
30 | 29 | ||
@@ -507,10 +506,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
507 | int i; | 506 | int i; |
508 | 507 | ||
509 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); | 508 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); |
510 | if (!mtd) { | 509 | if (!mtd) |
511 | printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); | ||
512 | return NULL; | 510 | return NULL; |
513 | } | ||
514 | mtd->priv = map; | 511 | mtd->priv = map; |
515 | mtd->type = MTD_NORFLASH; | 512 | mtd->type = MTD_NORFLASH; |
516 | 513 | ||
@@ -661,10 +658,8 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) | |||
661 | mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; | 658 | mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; |
662 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) | 659 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) |
663 | * mtd->numeraseregions, GFP_KERNEL); | 660 | * mtd->numeraseregions, GFP_KERNEL); |
664 | if (!mtd->eraseregions) { | 661 | if (!mtd->eraseregions) |
665 | printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n"); | ||
666 | goto setup_err; | 662 | goto setup_err; |
667 | } | ||
668 | 663 | ||
669 | for (i=0; i<cfi->cfiq->NumEraseRegions; i++) { | 664 | for (i=0; i<cfi->cfiq->NumEraseRegions; i++) { |
670 | unsigned long ernum, ersize; | 665 | unsigned long ernum, ersize; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 096993f9711e..6293855fb5ee 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/init.h> | ||
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
28 | 27 | ||
@@ -176,7 +175,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) | |||
176 | //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); | 175 | //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); |
177 | 176 | ||
178 | if (!mtd) { | 177 | if (!mtd) { |
179 | printk(KERN_ERR "Failed to allocate memory for MTD device\n"); | ||
180 | kfree(cfi->cmdset_priv); | 178 | kfree(cfi->cmdset_priv); |
181 | return NULL; | 179 | return NULL; |
182 | } | 180 | } |
@@ -189,7 +187,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) | |||
189 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) | 187 | mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) |
190 | * mtd->numeraseregions, GFP_KERNEL); | 188 | * mtd->numeraseregions, GFP_KERNEL); |
191 | if (!mtd->eraseregions) { | 189 | if (!mtd->eraseregions) { |
192 | printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); | ||
193 | kfree(cfi->cmdset_priv); | 190 | kfree(cfi->cmdset_priv); |
194 | kfree(mtd); | 191 | kfree(mtd); |
195 | return NULL; | 192 | return NULL; |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index d25535279404..e8d0164498b0 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -168,10 +168,8 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); | 170 | cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); |
171 | if (!cfi->cfiq) { | 171 | if (!cfi->cfiq) |
172 | printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); | ||
173 | return 0; | 172 | return 0; |
174 | } | ||
175 | 173 | ||
176 | memset(cfi->cfiq,0,sizeof(struct cfi_ident)); | 174 | memset(cfi->cfiq,0,sizeof(struct cfi_ident)); |
177 | 175 | ||
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index f992418f40a8..08049f6eea60 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -116,10 +116,8 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n | |||
116 | printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr); | 116 | printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr); |
117 | 117 | ||
118 | extp = kmalloc(size, GFP_KERNEL); | 118 | extp = kmalloc(size, GFP_KERNEL); |
119 | if (!extp) { | 119 | if (!extp) |
120 | printk(KERN_ERR "Failed to allocate memory\n"); | ||
121 | goto out; | 120 | goto out; |
122 | } | ||
123 | 121 | ||
124 | #ifdef CONFIG_MTD_XIP | 122 | #ifdef CONFIG_MTD_XIP |
125 | local_irq_disable(); | 123 | local_irq_disable(); |
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index ffb36ba8a6e0..b57ceea21513 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c | |||
@@ -114,7 +114,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi | |||
114 | mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG); | 114 | mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG); |
115 | chip_map = kzalloc(mapsize, GFP_KERNEL); | 115 | chip_map = kzalloc(mapsize, GFP_KERNEL); |
116 | if (!chip_map) { | 116 | if (!chip_map) { |
117 | printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); | ||
118 | kfree(cfi.cfiq); | 117 | kfree(cfi.cfiq); |
119 | return NULL; | 118 | return NULL; |
120 | } | 119 | } |
@@ -139,7 +138,6 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi | |||
139 | retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL); | 138 | retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL); |
140 | 139 | ||
141 | if (!retcfi) { | 140 | if (!retcfi) { |
142 | printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name); | ||
143 | kfree(cfi.cfiq); | 141 | kfree(cfi.cfiq); |
144 | kfree(chip_map); | 142 | kfree(chip_map); |
145 | return NULL; | 143 | return NULL; |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 01281382180b..1210bc2923b7 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -210,6 +210,14 @@ config MTD_DOCG3 | |||
210 | M-Systems and now Sandisk. The support is very experimental, | 210 | M-Systems and now Sandisk. The support is very experimental, |
211 | and doesn't give access to any write operations. | 211 | and doesn't give access to any write operations. |
212 | 212 | ||
213 | config MTD_ST_SPI_FSM | ||
214 | tristate "ST Microelectronics SPI FSM Serial Flash Controller" | ||
215 | depends on ARM || SH | ||
216 | help | ||
217 | This provides an MTD device driver for the ST Microelectronics | ||
218 | SPI Fast Sequence Mode (FSM) Serial Flash Controller and support | ||
219 | for a subset of connected Serial Flash devices. | ||
220 | |||
213 | if MTD_DOCG3 | 221 | if MTD_DOCG3 |
214 | config BCH_CONST_M | 222 | config BCH_CONST_M |
215 | default 14 | 223 | default 14 |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index d83bd73096f6..c68868f60588 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH) += elm.o | |||
16 | obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o | 16 | obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o |
17 | obj-$(CONFIG_MTD_SST25L) += sst25l.o | 17 | obj-$(CONFIG_MTD_SST25L) += sst25l.o |
18 | obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o | 18 | obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o |
19 | obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o | ||
19 | 20 | ||
20 | 21 | ||
21 | CFLAGS_docg3.o += -I$(src) | 22 | CFLAGS_docg3.o += -I$(src) |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index d9fd87a4c8dc..66f0405f7e53 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -209,7 +209,6 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) | |||
209 | } | 209 | } |
210 | 210 | ||
211 | 211 | ||
212 | /* FIXME: ensure that mtd->size % erase_size == 0 */ | ||
213 | static struct block2mtd_dev *add_device(char *devname, int erase_size) | 212 | static struct block2mtd_dev *add_device(char *devname, int erase_size) |
214 | { | 213 | { |
215 | const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; | 214 | const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; |
@@ -240,13 +239,18 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
240 | 239 | ||
241 | if (IS_ERR(bdev)) { | 240 | if (IS_ERR(bdev)) { |
242 | pr_err("error: cannot open device %s\n", devname); | 241 | pr_err("error: cannot open device %s\n", devname); |
243 | goto devinit_err; | 242 | goto err_free_block2mtd; |
244 | } | 243 | } |
245 | dev->blkdev = bdev; | 244 | dev->blkdev = bdev; |
246 | 245 | ||
247 | if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { | 246 | if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { |
248 | pr_err("attempting to use an MTD device as a block device\n"); | 247 | pr_err("attempting to use an MTD device as a block device\n"); |
249 | goto devinit_err; | 248 | goto err_free_block2mtd; |
249 | } | ||
250 | |||
251 | if ((long)dev->blkdev->bd_inode->i_size % erase_size) { | ||
252 | pr_err("erasesize must be a divisor of device size\n"); | ||
253 | goto err_free_block2mtd; | ||
250 | } | 254 | } |
251 | 255 | ||
252 | mutex_init(&dev->write_mutex); | 256 | mutex_init(&dev->write_mutex); |
@@ -255,7 +259,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
255 | /* make the name contain the block device in */ | 259 | /* make the name contain the block device in */ |
256 | name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname); | 260 | name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname); |
257 | if (!name) | 261 | if (!name) |
258 | goto devinit_err; | 262 | goto err_destroy_mutex; |
259 | 263 | ||
260 | dev->mtd.name = name; | 264 | dev->mtd.name = name; |
261 | 265 | ||
@@ -274,7 +278,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
274 | 278 | ||
275 | if (mtd_device_register(&dev->mtd, NULL, 0)) { | 279 | if (mtd_device_register(&dev->mtd, NULL, 0)) { |
276 | /* Device didn't get added, so free the entry */ | 280 | /* Device didn't get added, so free the entry */ |
277 | goto devinit_err; | 281 | goto err_destroy_mutex; |
278 | } | 282 | } |
279 | list_add(&dev->list, &blkmtd_device_list); | 283 | list_add(&dev->list, &blkmtd_device_list); |
280 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", | 284 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", |
@@ -283,7 +287,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
283 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); | 287 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); |
284 | return dev; | 288 | return dev; |
285 | 289 | ||
286 | devinit_err: | 290 | err_destroy_mutex: |
291 | mutex_destroy(&dev->write_mutex); | ||
292 | err_free_block2mtd: | ||
287 | block2mtd_free_device(dev); | 293 | block2mtd_free_device(dev); |
288 | return NULL; | 294 | return NULL; |
289 | } | 295 | } |
@@ -448,6 +454,7 @@ static void block2mtd_exit(void) | |||
448 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); | 454 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); |
449 | block2mtd_sync(&dev->mtd); | 455 | block2mtd_sync(&dev->mtd); |
450 | mtd_device_unregister(&dev->mtd); | 456 | mtd_device_unregister(&dev->mtd); |
457 | mutex_destroy(&dev->write_mutex); | ||
451 | pr_info("mtd%d: [%s] removed\n", | 458 | pr_info("mtd%d: [%s] removed\n", |
452 | dev->mtd.index, | 459 | dev->mtd.index, |
453 | dev->mtd.name + strlen("block2mtd: ")); | 460 | dev->mtd.name + strlen("block2mtd: ")); |
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c index d1dd6a33a050..1fd4a0f77967 100644 --- a/drivers/mtd/devices/elm.c +++ b/drivers/mtd/devices/elm.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define DRIVER_NAME "omap-elm" | ||
19 | |||
18 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
19 | #include <linux/module.h> | 21 | #include <linux/module.h> |
20 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
@@ -84,6 +86,8 @@ struct elm_info { | |||
84 | struct list_head list; | 86 | struct list_head list; |
85 | enum bch_ecc bch_type; | 87 | enum bch_ecc bch_type; |
86 | struct elm_registers elm_regs; | 88 | struct elm_registers elm_regs; |
89 | int ecc_steps; | ||
90 | int ecc_syndrome_size; | ||
87 | }; | 91 | }; |
88 | 92 | ||
89 | static LIST_HEAD(elm_devices); | 93 | static LIST_HEAD(elm_devices); |
@@ -103,7 +107,8 @@ static u32 elm_read_reg(struct elm_info *info, int offset) | |||
103 | * @dev: ELM device | 107 | * @dev: ELM device |
104 | * @bch_type: Type of BCH ecc | 108 | * @bch_type: Type of BCH ecc |
105 | */ | 109 | */ |
106 | int elm_config(struct device *dev, enum bch_ecc bch_type) | 110 | int elm_config(struct device *dev, enum bch_ecc bch_type, |
111 | int ecc_steps, int ecc_step_size, int ecc_syndrome_size) | ||
107 | { | 112 | { |
108 | u32 reg_val; | 113 | u32 reg_val; |
109 | struct elm_info *info = dev_get_drvdata(dev); | 114 | struct elm_info *info = dev_get_drvdata(dev); |
@@ -112,10 +117,22 @@ int elm_config(struct device *dev, enum bch_ecc bch_type) | |||
112 | dev_err(dev, "Unable to configure elm - device not probed?\n"); | 117 | dev_err(dev, "Unable to configure elm - device not probed?\n"); |
113 | return -ENODEV; | 118 | return -ENODEV; |
114 | } | 119 | } |
120 | /* ELM cannot detect ECC errors for chunks > 1KB */ | ||
121 | if (ecc_step_size > ((ELM_ECC_SIZE + 1) / 2)) { | ||
122 | dev_err(dev, "unsupported config ecc-size=%d\n", ecc_step_size); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | /* ELM support 8 error syndrome process */ | ||
126 | if (ecc_steps > ERROR_VECTOR_MAX) { | ||
127 | dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps); | ||
128 | return -EINVAL; | ||
129 | } | ||
115 | 130 | ||
116 | reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16); | 131 | reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16); |
117 | elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val); | 132 | elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val); |
118 | info->bch_type = bch_type; | 133 | info->bch_type = bch_type; |
134 | info->ecc_steps = ecc_steps; | ||
135 | info->ecc_syndrome_size = ecc_syndrome_size; | ||
119 | 136 | ||
120 | return 0; | 137 | return 0; |
121 | } | 138 | } |
@@ -157,17 +174,15 @@ static void elm_load_syndrome(struct elm_info *info, | |||
157 | int i, offset; | 174 | int i, offset; |
158 | u32 val; | 175 | u32 val; |
159 | 176 | ||
160 | for (i = 0; i < ERROR_VECTOR_MAX; i++) { | 177 | for (i = 0; i < info->ecc_steps; i++) { |
161 | 178 | ||
162 | /* Check error reported */ | 179 | /* Check error reported */ |
163 | if (err_vec[i].error_reported) { | 180 | if (err_vec[i].error_reported) { |
164 | elm_configure_page_mode(info, i, true); | 181 | elm_configure_page_mode(info, i, true); |
165 | offset = ELM_SYNDROME_FRAGMENT_0 + | 182 | offset = ELM_SYNDROME_FRAGMENT_0 + |
166 | SYNDROME_FRAGMENT_REG_SIZE * i; | 183 | SYNDROME_FRAGMENT_REG_SIZE * i; |
167 | 184 | switch (info->bch_type) { | |
168 | /* BCH8 */ | 185 | case BCH8_ECC: |
169 | if (info->bch_type) { | ||
170 | |||
171 | /* syndrome fragment 0 = ecc[9-12B] */ | 186 | /* syndrome fragment 0 = ecc[9-12B] */ |
172 | val = cpu_to_be32(*(u32 *) &ecc[9]); | 187 | val = cpu_to_be32(*(u32 *) &ecc[9]); |
173 | elm_write_reg(info, offset, val); | 188 | elm_write_reg(info, offset, val); |
@@ -186,7 +201,8 @@ static void elm_load_syndrome(struct elm_info *info, | |||
186 | offset += 4; | 201 | offset += 4; |
187 | val = ecc[0]; | 202 | val = ecc[0]; |
188 | elm_write_reg(info, offset, val); | 203 | elm_write_reg(info, offset, val); |
189 | } else { | 204 | break; |
205 | case BCH4_ECC: | ||
190 | /* syndrome fragment 0 = ecc[20-52b] bits */ | 206 | /* syndrome fragment 0 = ecc[20-52b] bits */ |
191 | val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | | 207 | val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | |
192 | ((ecc[2] & 0xf) << 28); | 208 | ((ecc[2] & 0xf) << 28); |
@@ -196,11 +212,14 @@ static void elm_load_syndrome(struct elm_info *info, | |||
196 | offset += 4; | 212 | offset += 4; |
197 | val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; | 213 | val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; |
198 | elm_write_reg(info, offset, val); | 214 | elm_write_reg(info, offset, val); |
215 | break; | ||
216 | default: | ||
217 | pr_err("invalid config bch_type\n"); | ||
199 | } | 218 | } |
200 | } | 219 | } |
201 | 220 | ||
202 | /* Update ecc pointer with ecc byte size */ | 221 | /* Update ecc pointer with ecc byte size */ |
203 | ecc += info->bch_type ? BCH8_SIZE : BCH4_SIZE; | 222 | ecc += info->ecc_syndrome_size; |
204 | } | 223 | } |
205 | } | 224 | } |
206 | 225 | ||
@@ -223,7 +242,7 @@ static void elm_start_processing(struct elm_info *info, | |||
223 | * Set syndrome vector valid, so that ELM module | 242 | * Set syndrome vector valid, so that ELM module |
224 | * will process it for vectors error is reported | 243 | * will process it for vectors error is reported |
225 | */ | 244 | */ |
226 | for (i = 0; i < ERROR_VECTOR_MAX; i++) { | 245 | for (i = 0; i < info->ecc_steps; i++) { |
227 | if (err_vec[i].error_reported) { | 246 | if (err_vec[i].error_reported) { |
228 | offset = ELM_SYNDROME_FRAGMENT_6 + | 247 | offset = ELM_SYNDROME_FRAGMENT_6 + |
229 | SYNDROME_FRAGMENT_REG_SIZE * i; | 248 | SYNDROME_FRAGMENT_REG_SIZE * i; |
@@ -252,7 +271,7 @@ static void elm_error_correction(struct elm_info *info, | |||
252 | int offset; | 271 | int offset; |
253 | u32 reg_val; | 272 | u32 reg_val; |
254 | 273 | ||
255 | for (i = 0; i < ERROR_VECTOR_MAX; i++) { | 274 | for (i = 0; i < info->ecc_steps; i++) { |
256 | 275 | ||
257 | /* Check error reported */ | 276 | /* Check error reported */ |
258 | if (err_vec[i].error_reported) { | 277 | if (err_vec[i].error_reported) { |
@@ -354,10 +373,8 @@ static int elm_probe(struct platform_device *pdev) | |||
354 | struct elm_info *info; | 373 | struct elm_info *info; |
355 | 374 | ||
356 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 375 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
357 | if (!info) { | 376 | if (!info) |
358 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
359 | return -ENOMEM; | 377 | return -ENOMEM; |
360 | } | ||
361 | 378 | ||
362 | info->dev = &pdev->dev; | 379 | info->dev = &pdev->dev; |
363 | 380 | ||
@@ -380,7 +397,7 @@ static int elm_probe(struct platform_device *pdev) | |||
380 | } | 397 | } |
381 | 398 | ||
382 | pm_runtime_enable(&pdev->dev); | 399 | pm_runtime_enable(&pdev->dev); |
383 | if (pm_runtime_get_sync(&pdev->dev)) { | 400 | if (pm_runtime_get_sync(&pdev->dev) < 0) { |
384 | ret = -EINVAL; | 401 | ret = -EINVAL; |
385 | pm_runtime_disable(&pdev->dev); | 402 | pm_runtime_disable(&pdev->dev); |
386 | dev_err(&pdev->dev, "can't enable clock\n"); | 403 | dev_err(&pdev->dev, "can't enable clock\n"); |
@@ -505,7 +522,7 @@ MODULE_DEVICE_TABLE(of, elm_of_match); | |||
505 | 522 | ||
506 | static struct platform_driver elm_driver = { | 523 | static struct platform_driver elm_driver = { |
507 | .driver = { | 524 | .driver = { |
508 | .name = "elm", | 525 | .name = DRIVER_NAME, |
509 | .owner = THIS_MODULE, | 526 | .owner = THIS_MODULE, |
510 | .of_match_table = of_match_ptr(elm_of_match), | 527 | .of_match_table = of_match_ptr(elm_of_match), |
511 | .pm = &elm_pm_ops, | 528 | .pm = &elm_pm_ops, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index ad1913909702..524dab3ac938 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/err.h> | 18 | #include <linux/err.h> |
20 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
21 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -41,7 +40,8 @@ | |||
41 | #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ | 40 | #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ |
42 | #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ | 41 | #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ |
43 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ | 42 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ |
44 | #define OPCODE_QUAD_READ 0x6b /* Read data bytes */ | 43 | #define OPCODE_DUAL_READ 0x3b /* Read data bytes (Dual SPI) */ |
44 | #define OPCODE_QUAD_READ 0x6b /* Read data bytes (Quad SPI) */ | ||
45 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ | 45 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ |
46 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ | 46 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ |
47 | #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ | 47 | #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ |
@@ -54,7 +54,8 @@ | |||
54 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ | 54 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ |
55 | #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ | 55 | #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ |
56 | #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ | 56 | #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ |
57 | #define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes */ | 57 | #define OPCODE_DUAL_READ_4B 0x3c /* Read data bytes (Dual SPI) */ |
58 | #define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes (Quad SPI) */ | ||
58 | #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ | 59 | #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ |
59 | #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ | 60 | #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ |
60 | 61 | ||
@@ -95,6 +96,7 @@ | |||
95 | enum read_type { | 96 | enum read_type { |
96 | M25P80_NORMAL = 0, | 97 | M25P80_NORMAL = 0, |
97 | M25P80_FAST, | 98 | M25P80_FAST, |
99 | M25P80_DUAL, | ||
98 | M25P80_QUAD, | 100 | M25P80_QUAD, |
99 | }; | 101 | }; |
100 | 102 | ||
@@ -479,6 +481,7 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash) | |||
479 | { | 481 | { |
480 | switch (flash->flash_read) { | 482 | switch (flash->flash_read) { |
481 | case M25P80_FAST: | 483 | case M25P80_FAST: |
484 | case M25P80_DUAL: | ||
482 | case M25P80_QUAD: | 485 | case M25P80_QUAD: |
483 | return 1; | 486 | return 1; |
484 | case M25P80_NORMAL: | 487 | case M25P80_NORMAL: |
@@ -492,6 +495,8 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash) | |||
492 | static inline unsigned int m25p80_rx_nbits(const struct m25p *flash) | 495 | static inline unsigned int m25p80_rx_nbits(const struct m25p *flash) |
493 | { | 496 | { |
494 | switch (flash->flash_read) { | 497 | switch (flash->flash_read) { |
498 | case M25P80_DUAL: | ||
499 | return 2; | ||
495 | case M25P80_QUAD: | 500 | case M25P80_QUAD: |
496 | return 4; | 501 | return 4; |
497 | default: | 502 | default: |
@@ -855,7 +860,8 @@ struct flash_info { | |||
855 | #define SST_WRITE 0x04 /* use SST byte programming */ | 860 | #define SST_WRITE 0x04 /* use SST byte programming */ |
856 | #define M25P_NO_FR 0x08 /* Can't do fastread */ | 861 | #define M25P_NO_FR 0x08 /* Can't do fastread */ |
857 | #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ | 862 | #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ |
858 | #define M25P80_QUAD_READ 0x20 /* Flash supports Quad Read */ | 863 | #define M25P80_DUAL_READ 0x20 /* Flash supports Dual Read */ |
864 | #define M25P80_QUAD_READ 0x40 /* Flash supports Quad Read */ | ||
859 | }; | 865 | }; |
860 | 866 | ||
861 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 867 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
@@ -934,6 +940,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
934 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, | 940 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, |
935 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, | 941 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, |
936 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) }, | 942 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) }, |
943 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, M25P80_QUAD_READ) }, | ||
937 | 944 | ||
938 | /* Micron */ | 945 | /* Micron */ |
939 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, | 946 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, |
@@ -953,8 +960,8 @@ static const struct spi_device_id m25p_ids[] = { | |||
953 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, | 960 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, |
954 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, | 961 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, |
955 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, | 962 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, |
956 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_QUAD_READ) }, | 963 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_DUAL_READ | M25P80_QUAD_READ) }, |
957 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_QUAD_READ) }, | 964 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_DUAL_READ | M25P80_QUAD_READ) }, |
958 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 965 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
959 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 966 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
960 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 967 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
@@ -965,6 +972,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
965 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, | 972 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, |
966 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, | 973 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, |
967 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, | 974 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, |
975 | { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | ||
968 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, | 976 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, |
969 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 977 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
970 | 978 | ||
@@ -1072,9 +1080,8 @@ static const struct spi_device_id *jedec_probe(struct spi_device *spi) | |||
1072 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { | 1080 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { |
1073 | info = (void *)m25p_ids[tmp].driver_data; | 1081 | info = (void *)m25p_ids[tmp].driver_data; |
1074 | if (info->jedec_id == jedec) { | 1082 | if (info->jedec_id == jedec) { |
1075 | if (info->ext_id != 0 && info->ext_id != ext_jedec) | 1083 | if (info->ext_id == 0 || info->ext_id == ext_jedec) |
1076 | continue; | 1084 | return &m25p_ids[tmp]; |
1077 | return &m25p_ids[tmp]; | ||
1078 | } | 1085 | } |
1079 | } | 1086 | } |
1080 | dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); | 1087 | dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); |
@@ -1226,7 +1233,7 @@ static int m25p_probe(struct spi_device *spi) | |||
1226 | if (info->flags & M25P_NO_FR) | 1233 | if (info->flags & M25P_NO_FR) |
1227 | flash->flash_read = M25P80_NORMAL; | 1234 | flash->flash_read = M25P80_NORMAL; |
1228 | 1235 | ||
1229 | /* Quad-read mode takes precedence over fast/normal */ | 1236 | /* Quad/Dual-read mode takes precedence over fast/normal */ |
1230 | if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) { | 1237 | if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) { |
1231 | ret = set_quad_mode(flash, info->jedec_id); | 1238 | ret = set_quad_mode(flash, info->jedec_id); |
1232 | if (ret) { | 1239 | if (ret) { |
@@ -1234,6 +1241,8 @@ static int m25p_probe(struct spi_device *spi) | |||
1234 | return ret; | 1241 | return ret; |
1235 | } | 1242 | } |
1236 | flash->flash_read = M25P80_QUAD; | 1243 | flash->flash_read = M25P80_QUAD; |
1244 | } else if (spi->mode & SPI_RX_DUAL && info->flags & M25P80_DUAL_READ) { | ||
1245 | flash->flash_read = M25P80_DUAL; | ||
1237 | } | 1246 | } |
1238 | 1247 | ||
1239 | /* Default commands */ | 1248 | /* Default commands */ |
@@ -1241,6 +1250,9 @@ static int m25p_probe(struct spi_device *spi) | |||
1241 | case M25P80_QUAD: | 1250 | case M25P80_QUAD: |
1242 | flash->read_opcode = OPCODE_QUAD_READ; | 1251 | flash->read_opcode = OPCODE_QUAD_READ; |
1243 | break; | 1252 | break; |
1253 | case M25P80_DUAL: | ||
1254 | flash->read_opcode = OPCODE_DUAL_READ; | ||
1255 | break; | ||
1244 | case M25P80_FAST: | 1256 | case M25P80_FAST: |
1245 | flash->read_opcode = OPCODE_FAST_READ; | 1257 | flash->read_opcode = OPCODE_FAST_READ; |
1246 | break; | 1258 | break; |
@@ -1265,6 +1277,9 @@ static int m25p_probe(struct spi_device *spi) | |||
1265 | case M25P80_QUAD: | 1277 | case M25P80_QUAD: |
1266 | flash->read_opcode = OPCODE_QUAD_READ_4B; | 1278 | flash->read_opcode = OPCODE_QUAD_READ_4B; |
1267 | break; | 1279 | break; |
1280 | case M25P80_DUAL: | ||
1281 | flash->read_opcode = OPCODE_DUAL_READ_4B; | ||
1282 | break; | ||
1268 | case M25P80_FAST: | 1283 | case M25P80_FAST: |
1269 | flash->read_opcode = OPCODE_FAST_READ_4B; | 1284 | flash->read_opcode = OPCODE_FAST_READ_4B; |
1270 | break; | 1285 | break; |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 624069de4f28..dd22ce2cc9ad 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | */ | 11 | */ |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
@@ -440,8 +439,8 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
440 | 439 | ||
441 | #ifdef CONFIG_MTD_DATAFLASH_OTP | 440 | #ifdef CONFIG_MTD_DATAFLASH_OTP |
442 | 441 | ||
443 | static int dataflash_get_otp_info(struct mtd_info *mtd, | 442 | static int dataflash_get_otp_info(struct mtd_info *mtd, size_t len, |
444 | struct otp_info *info, size_t len) | 443 | size_t *retlen, struct otp_info *info) |
445 | { | 444 | { |
446 | /* Report both blocks as identical: bytes 0..64, locked. | 445 | /* Report both blocks as identical: bytes 0..64, locked. |
447 | * Unless the user block changed from all-ones, we can't | 446 | * Unless the user block changed from all-ones, we can't |
@@ -450,7 +449,8 @@ static int dataflash_get_otp_info(struct mtd_info *mtd, | |||
450 | info->start = 0; | 449 | info->start = 0; |
451 | info->length = 64; | 450 | info->length = 64; |
452 | info->locked = 1; | 451 | info->locked = 1; |
453 | return sizeof(*info); | 452 | *retlen = sizeof(*info); |
453 | return 0; | ||
454 | } | 454 | } |
455 | 455 | ||
456 | static ssize_t otp_read(struct spi_device *spi, unsigned base, | 456 | static ssize_t otp_read(struct spi_device *spi, unsigned base, |
@@ -542,14 +542,18 @@ static int dataflash_write_user_otp(struct mtd_info *mtd, | |||
542 | struct dataflash *priv = mtd->priv; | 542 | struct dataflash *priv = mtd->priv; |
543 | int status; | 543 | int status; |
544 | 544 | ||
545 | if (len > 64) | 545 | if (from >= 64) { |
546 | return -EINVAL; | 546 | /* |
547 | * Attempting to write beyond the end of OTP memory, | ||
548 | * no data can be written. | ||
549 | */ | ||
550 | *retlen = 0; | ||
551 | return 0; | ||
552 | } | ||
547 | 553 | ||
548 | /* Strictly speaking, we *could* truncate the write ... but | 554 | /* Truncate the write to fit into OTP memory. */ |
549 | * let's not do that for the only write that's ever possible. | ||
550 | */ | ||
551 | if ((from + len) > 64) | 555 | if ((from + len) > 64) |
552 | return -EINVAL; | 556 | len = 64 - from; |
553 | 557 | ||
554 | /* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes | 558 | /* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes |
555 | * IN: ignore all | 559 | * IN: ignore all |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index e1f2aebaa489..2cceebfb251e 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -205,6 +205,8 @@ static inline void kill_final_newline(char *str) | |||
205 | return 1; \ | 205 | return 1; \ |
206 | } while (0) | 206 | } while (0) |
207 | 207 | ||
208 | #ifndef MODULE | ||
209 | static int phram_init_called; | ||
208 | /* | 210 | /* |
209 | * This shall contain the module parameter if any. It is of the form: | 211 | * This shall contain the module parameter if any. It is of the form: |
210 | * - phram=<device>,<address>,<size> for module case | 212 | * - phram=<device>,<address>,<size> for module case |
@@ -213,9 +215,10 @@ static inline void kill_final_newline(char *str) | |||
213 | * size. | 215 | * size. |
214 | * Example: phram.phram=rootfs,0xa0000000,512Mi | 216 | * Example: phram.phram=rootfs,0xa0000000,512Mi |
215 | */ | 217 | */ |
216 | static __initdata char phram_paramline[64 + 20 + 20]; | 218 | static char phram_paramline[64 + 20 + 20]; |
219 | #endif | ||
217 | 220 | ||
218 | static int __init phram_setup(const char *val) | 221 | static int phram_setup(const char *val) |
219 | { | 222 | { |
220 | char buf[64 + 20 + 20], *str = buf; | 223 | char buf[64 + 20 + 20], *str = buf; |
221 | char *token[3]; | 224 | char *token[3]; |
@@ -264,17 +267,36 @@ static int __init phram_setup(const char *val) | |||
264 | return ret; | 267 | return ret; |
265 | } | 268 | } |
266 | 269 | ||
267 | static int __init phram_param_call(const char *val, struct kernel_param *kp) | 270 | static int phram_param_call(const char *val, struct kernel_param *kp) |
268 | { | 271 | { |
272 | #ifdef MODULE | ||
273 | return phram_setup(val); | ||
274 | #else | ||
269 | /* | 275 | /* |
270 | * This function is always called before 'init_phram()', whether | 276 | * If more parameters are later passed in via |
271 | * built-in or module. | 277 | * /sys/module/phram/parameters/phram |
278 | * and init_phram() has already been called, | ||
279 | * we can parse the argument now. | ||
272 | */ | 280 | */ |
281 | |||
282 | if (phram_init_called) | ||
283 | return phram_setup(val); | ||
284 | |||
285 | /* | ||
286 | * During early boot stage, we only save the parameters | ||
287 | * here. We must parse them later: if the param passed | ||
288 | * from kernel boot command line, phram_param_call() is | ||
289 | * called so early that it is not possible to resolve | ||
290 | * the device (even kmalloc() fails). Defer that work to | ||
291 | * phram_setup(). | ||
292 | */ | ||
293 | |||
273 | if (strlen(val) >= sizeof(phram_paramline)) | 294 | if (strlen(val) >= sizeof(phram_paramline)) |
274 | return -ENOSPC; | 295 | return -ENOSPC; |
275 | strcpy(phram_paramline, val); | 296 | strcpy(phram_paramline, val); |
276 | 297 | ||
277 | return 0; | 298 | return 0; |
299 | #endif | ||
278 | } | 300 | } |
279 | 301 | ||
280 | module_param_call(phram, phram_param_call, NULL, NULL, 000); | 302 | module_param_call(phram, phram_param_call, NULL, NULL, 000); |
@@ -283,10 +305,15 @@ MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\" | |||
283 | 305 | ||
284 | static int __init init_phram(void) | 306 | static int __init init_phram(void) |
285 | { | 307 | { |
308 | int ret = 0; | ||
309 | |||
310 | #ifndef MODULE | ||
286 | if (phram_paramline[0]) | 311 | if (phram_paramline[0]) |
287 | return phram_setup(phram_paramline); | 312 | ret = phram_setup(phram_paramline); |
313 | phram_init_called = 1; | ||
314 | #endif | ||
288 | 315 | ||
289 | return 0; | 316 | return ret; |
290 | } | 317 | } |
291 | 318 | ||
292 | static void __exit cleanup_phram(void) | 319 | static void __exit cleanup_phram(void) |
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 0c51b988e1f8..f02603e1bfeb 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -725,16 +725,11 @@ static int __init init_pmc551(void) | |||
725 | } | 725 | } |
726 | 726 | ||
727 | mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); | 727 | mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); |
728 | if (!mtd) { | 728 | if (!mtd) |
729 | printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " | ||
730 | "device.\n"); | ||
731 | break; | 729 | break; |
732 | } | ||
733 | 730 | ||
734 | priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL); | 731 | priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL); |
735 | if (!priv) { | 732 | if (!priv) { |
736 | printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " | ||
737 | "device.\n"); | ||
738 | kfree(mtd); | 733 | kfree(mtd); |
739 | break; | 734 | break; |
740 | } | 735 | } |
diff --git a/drivers/mtd/devices/serial_flash_cmds.h b/drivers/mtd/devices/serial_flash_cmds.h new file mode 100644 index 000000000000..4f0c2c7c898e --- /dev/null +++ b/drivers/mtd/devices/serial_flash_cmds.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Generic/SFDP Flash Commands and Device Capabilities | ||
3 | * | ||
4 | * Copyright (C) 2013 Lee Jones <lee.jones@lianro.org> | ||
5 | * | ||
6 | * This code 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 | #ifndef _MTD_SERIAL_FLASH_CMDS_H | ||
13 | #define _MTD_SERIAL_FLASH_CMDS_H | ||
14 | |||
15 | /* Generic Flash Commands/OPCODEs */ | ||
16 | #define FLASH_CMD_WREN 0x06 | ||
17 | #define FLASH_CMD_WRDI 0x04 | ||
18 | #define FLASH_CMD_RDID 0x9f | ||
19 | #define FLASH_CMD_RDSR 0x05 | ||
20 | #define FLASH_CMD_RDSR2 0x35 | ||
21 | #define FLASH_CMD_WRSR 0x01 | ||
22 | #define FLASH_CMD_SE_4K 0x20 | ||
23 | #define FLASH_CMD_SE_32K 0x52 | ||
24 | #define FLASH_CMD_SE 0xd8 | ||
25 | #define FLASH_CMD_CHIPERASE 0xc7 | ||
26 | #define FLASH_CMD_WRVCR 0x81 | ||
27 | #define FLASH_CMD_RDVCR 0x85 | ||
28 | |||
29 | /* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */ | ||
30 | #define FLASH_CMD_READ 0x03 /* READ */ | ||
31 | #define FLASH_CMD_READ_FAST 0x0b /* FAST READ */ | ||
32 | #define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */ | ||
33 | #define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */ | ||
34 | #define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */ | ||
35 | #define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */ | ||
36 | |||
37 | #define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */ | ||
38 | #define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ | ||
39 | #define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ | ||
40 | #define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ | ||
41 | #define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ | ||
42 | |||
43 | #define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */ | ||
44 | #define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */ | ||
45 | |||
46 | /* READ commands with 32-bit addressing */ | ||
47 | #define FLASH_CMD_READ4 0x13 | ||
48 | #define FLASH_CMD_READ4_FAST 0x0c | ||
49 | #define FLASH_CMD_READ4_1_1_2 0x3c | ||
50 | #define FLASH_CMD_READ4_1_2_2 0xbc | ||
51 | #define FLASH_CMD_READ4_1_1_4 0x6c | ||
52 | #define FLASH_CMD_READ4_1_4_4 0xec | ||
53 | |||
54 | /* Configuration flags */ | ||
55 | #define FLASH_FLAG_SINGLE 0x000000ff | ||
56 | #define FLASH_FLAG_READ_WRITE 0x00000001 | ||
57 | #define FLASH_FLAG_READ_FAST 0x00000002 | ||
58 | #define FLASH_FLAG_SE_4K 0x00000004 | ||
59 | #define FLASH_FLAG_SE_32K 0x00000008 | ||
60 | #define FLASH_FLAG_CE 0x00000010 | ||
61 | #define FLASH_FLAG_32BIT_ADDR 0x00000020 | ||
62 | #define FLASH_FLAG_RESET 0x00000040 | ||
63 | #define FLASH_FLAG_DYB_LOCKING 0x00000080 | ||
64 | |||
65 | #define FLASH_FLAG_DUAL 0x0000ff00 | ||
66 | #define FLASH_FLAG_READ_1_1_2 0x00000100 | ||
67 | #define FLASH_FLAG_READ_1_2_2 0x00000200 | ||
68 | #define FLASH_FLAG_READ_2_2_2 0x00000400 | ||
69 | #define FLASH_FLAG_WRITE_1_1_2 0x00001000 | ||
70 | #define FLASH_FLAG_WRITE_1_2_2 0x00002000 | ||
71 | #define FLASH_FLAG_WRITE_2_2_2 0x00004000 | ||
72 | |||
73 | #define FLASH_FLAG_QUAD 0x00ff0000 | ||
74 | #define FLASH_FLAG_READ_1_1_4 0x00010000 | ||
75 | #define FLASH_FLAG_READ_1_4_4 0x00020000 | ||
76 | #define FLASH_FLAG_READ_4_4_4 0x00040000 | ||
77 | #define FLASH_FLAG_WRITE_1_1_4 0x00100000 | ||
78 | #define FLASH_FLAG_WRITE_1_4_4 0x00200000 | ||
79 | #define FLASH_FLAG_WRITE_4_4_4 0x00400000 | ||
80 | |||
81 | #endif /* _MTD_SERIAL_FLASH_CMDS_H */ | ||
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 423821412062..363da96e6891 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
@@ -913,7 +913,6 @@ static int spear_smi_probe(struct platform_device *pdev) | |||
913 | if (np) { | 913 | if (np) { |
914 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 914 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
915 | if (!pdata) { | 915 | if (!pdata) { |
916 | pr_err("%s: ERROR: no memory", __func__); | ||
917 | ret = -ENOMEM; | 916 | ret = -ENOMEM; |
918 | goto err; | 917 | goto err; |
919 | } | 918 | } |
@@ -943,7 +942,6 @@ static int spear_smi_probe(struct platform_device *pdev) | |||
943 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_ATOMIC); | 942 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_ATOMIC); |
944 | if (!dev) { | 943 | if (!dev) { |
945 | ret = -ENOMEM; | 944 | ret = -ENOMEM; |
946 | dev_err(&pdev->dev, "mem alloc fail\n"); | ||
947 | goto err; | 945 | goto err; |
948 | } | 946 | } |
949 | 947 | ||
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 687bf27ec850..c63ecbcad0b7 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/device.h> | 19 | #include <linux/device.h> |
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c new file mode 100644 index 000000000000..1957d7c8e185 --- /dev/null +++ b/drivers/mtd/devices/st_spi_fsm.c | |||
@@ -0,0 +1,2108 @@ | |||
1 | /* | ||
2 | * st_spi_fsm.c - ST Fast Sequence Mode (FSM) Serial Flash Controller | ||
3 | * | ||
4 | * Author: Angus Clark <angus.clark@st.com> | ||
5 | * | ||
6 | * Copyright (C) 2010-2014 STMicroelectronics Limited | ||
7 | * | ||
8 | * JEDEC probe based on drivers/mtd/devices/m25p80.c | ||
9 | * | ||
10 | * This code is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/mfd/syscon.h> | ||
20 | #include <linux/mtd/mtd.h> | ||
21 | #include <linux/mtd/partitions.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/of.h> | ||
26 | |||
27 | #include "serial_flash_cmds.h" | ||
28 | |||
29 | /* | ||
30 | * FSM SPI Controller Registers | ||
31 | */ | ||
32 | #define SPI_CLOCKDIV 0x0010 | ||
33 | #define SPI_MODESELECT 0x0018 | ||
34 | #define SPI_CONFIGDATA 0x0020 | ||
35 | #define SPI_STA_MODE_CHANGE 0x0028 | ||
36 | #define SPI_FAST_SEQ_TRANSFER_SIZE 0x0100 | ||
37 | #define SPI_FAST_SEQ_ADD1 0x0104 | ||
38 | #define SPI_FAST_SEQ_ADD2 0x0108 | ||
39 | #define SPI_FAST_SEQ_ADD_CFG 0x010c | ||
40 | #define SPI_FAST_SEQ_OPC1 0x0110 | ||
41 | #define SPI_FAST_SEQ_OPC2 0x0114 | ||
42 | #define SPI_FAST_SEQ_OPC3 0x0118 | ||
43 | #define SPI_FAST_SEQ_OPC4 0x011c | ||
44 | #define SPI_FAST_SEQ_OPC5 0x0120 | ||
45 | #define SPI_MODE_BITS 0x0124 | ||
46 | #define SPI_DUMMY_BITS 0x0128 | ||
47 | #define SPI_FAST_SEQ_FLASH_STA_DATA 0x012c | ||
48 | #define SPI_FAST_SEQ_1 0x0130 | ||
49 | #define SPI_FAST_SEQ_2 0x0134 | ||
50 | #define SPI_FAST_SEQ_3 0x0138 | ||
51 | #define SPI_FAST_SEQ_4 0x013c | ||
52 | #define SPI_FAST_SEQ_CFG 0x0140 | ||
53 | #define SPI_FAST_SEQ_STA 0x0144 | ||
54 | #define SPI_QUAD_BOOT_SEQ_INIT_1 0x0148 | ||
55 | #define SPI_QUAD_BOOT_SEQ_INIT_2 0x014c | ||
56 | #define SPI_QUAD_BOOT_READ_SEQ_1 0x0150 | ||
57 | #define SPI_QUAD_BOOT_READ_SEQ_2 0x0154 | ||
58 | #define SPI_PROGRAM_ERASE_TIME 0x0158 | ||
59 | #define SPI_MULT_PAGE_REPEAT_SEQ_1 0x015c | ||
60 | #define SPI_MULT_PAGE_REPEAT_SEQ_2 0x0160 | ||
61 | #define SPI_STATUS_WR_TIME_REG 0x0164 | ||
62 | #define SPI_FAST_SEQ_DATA_REG 0x0300 | ||
63 | |||
64 | /* | ||
65 | * Register: SPI_MODESELECT | ||
66 | */ | ||
67 | #define SPI_MODESELECT_CONTIG 0x01 | ||
68 | #define SPI_MODESELECT_FASTREAD 0x02 | ||
69 | #define SPI_MODESELECT_DUALIO 0x04 | ||
70 | #define SPI_MODESELECT_FSM 0x08 | ||
71 | #define SPI_MODESELECT_QUADBOOT 0x10 | ||
72 | |||
73 | /* | ||
74 | * Register: SPI_CONFIGDATA | ||
75 | */ | ||
76 | #define SPI_CFG_DEVICE_ST 0x1 | ||
77 | #define SPI_CFG_DEVICE_ATMEL 0x4 | ||
78 | #define SPI_CFG_MIN_CS_HIGH(x) (((x) & 0xfff) << 4) | ||
79 | #define SPI_CFG_CS_SETUPHOLD(x) (((x) & 0xff) << 16) | ||
80 | #define SPI_CFG_DATA_HOLD(x) (((x) & 0xff) << 24) | ||
81 | |||
82 | #define SPI_CFG_DEFAULT_MIN_CS_HIGH SPI_CFG_MIN_CS_HIGH(0x0AA) | ||
83 | #define SPI_CFG_DEFAULT_CS_SETUPHOLD SPI_CFG_CS_SETUPHOLD(0xA0) | ||
84 | #define SPI_CFG_DEFAULT_DATA_HOLD SPI_CFG_DATA_HOLD(0x00) | ||
85 | |||
86 | /* | ||
87 | * Register: SPI_FAST_SEQ_TRANSFER_SIZE | ||
88 | */ | ||
89 | #define TRANSFER_SIZE(x) ((x) * 8) | ||
90 | |||
91 | /* | ||
92 | * Register: SPI_FAST_SEQ_ADD_CFG | ||
93 | */ | ||
94 | #define ADR_CFG_CYCLES_ADD1(x) ((x) << 0) | ||
95 | #define ADR_CFG_PADS_1_ADD1 (0x0 << 6) | ||
96 | #define ADR_CFG_PADS_2_ADD1 (0x1 << 6) | ||
97 | #define ADR_CFG_PADS_4_ADD1 (0x3 << 6) | ||
98 | #define ADR_CFG_CSDEASSERT_ADD1 (1 << 8) | ||
99 | #define ADR_CFG_CYCLES_ADD2(x) ((x) << (0+16)) | ||
100 | #define ADR_CFG_PADS_1_ADD2 (0x0 << (6+16)) | ||
101 | #define ADR_CFG_PADS_2_ADD2 (0x1 << (6+16)) | ||
102 | #define ADR_CFG_PADS_4_ADD2 (0x3 << (6+16)) | ||
103 | #define ADR_CFG_CSDEASSERT_ADD2 (1 << (8+16)) | ||
104 | |||
105 | /* | ||
106 | * Register: SPI_FAST_SEQ_n | ||
107 | */ | ||
108 | #define SEQ_OPC_OPCODE(x) ((x) << 0) | ||
109 | #define SEQ_OPC_CYCLES(x) ((x) << 8) | ||
110 | #define SEQ_OPC_PADS_1 (0x0 << 14) | ||
111 | #define SEQ_OPC_PADS_2 (0x1 << 14) | ||
112 | #define SEQ_OPC_PADS_4 (0x3 << 14) | ||
113 | #define SEQ_OPC_CSDEASSERT (1 << 16) | ||
114 | |||
115 | /* | ||
116 | * Register: SPI_FAST_SEQ_CFG | ||
117 | */ | ||
118 | #define SEQ_CFG_STARTSEQ (1 << 0) | ||
119 | #define SEQ_CFG_SWRESET (1 << 5) | ||
120 | #define SEQ_CFG_CSDEASSERT (1 << 6) | ||
121 | #define SEQ_CFG_READNOTWRITE (1 << 7) | ||
122 | #define SEQ_CFG_ERASE (1 << 8) | ||
123 | #define SEQ_CFG_PADS_1 (0x0 << 16) | ||
124 | #define SEQ_CFG_PADS_2 (0x1 << 16) | ||
125 | #define SEQ_CFG_PADS_4 (0x3 << 16) | ||
126 | |||
127 | /* | ||
128 | * Register: SPI_MODE_BITS | ||
129 | */ | ||
130 | #define MODE_DATA(x) (x & 0xff) | ||
131 | #define MODE_CYCLES(x) ((x & 0x3f) << 16) | ||
132 | #define MODE_PADS_1 (0x0 << 22) | ||
133 | #define MODE_PADS_2 (0x1 << 22) | ||
134 | #define MODE_PADS_4 (0x3 << 22) | ||
135 | #define DUMMY_CSDEASSERT (1 << 24) | ||
136 | |||
137 | /* | ||
138 | * Register: SPI_DUMMY_BITS | ||
139 | */ | ||
140 | #define DUMMY_CYCLES(x) ((x & 0x3f) << 16) | ||
141 | #define DUMMY_PADS_1 (0x0 << 22) | ||
142 | #define DUMMY_PADS_2 (0x1 << 22) | ||
143 | #define DUMMY_PADS_4 (0x3 << 22) | ||
144 | #define DUMMY_CSDEASSERT (1 << 24) | ||
145 | |||
146 | /* | ||
147 | * Register: SPI_FAST_SEQ_FLASH_STA_DATA | ||
148 | */ | ||
149 | #define STA_DATA_BYTE1(x) ((x & 0xff) << 0) | ||
150 | #define STA_DATA_BYTE2(x) ((x & 0xff) << 8) | ||
151 | #define STA_PADS_1 (0x0 << 16) | ||
152 | #define STA_PADS_2 (0x1 << 16) | ||
153 | #define STA_PADS_4 (0x3 << 16) | ||
154 | #define STA_CSDEASSERT (0x1 << 20) | ||
155 | #define STA_RDNOTWR (0x1 << 21) | ||
156 | |||
157 | /* | ||
158 | * FSM SPI Instruction Opcodes | ||
159 | */ | ||
160 | #define STFSM_OPC_CMD 0x1 | ||
161 | #define STFSM_OPC_ADD 0x2 | ||
162 | #define STFSM_OPC_STA 0x3 | ||
163 | #define STFSM_OPC_MODE 0x4 | ||
164 | #define STFSM_OPC_DUMMY 0x5 | ||
165 | #define STFSM_OPC_DATA 0x6 | ||
166 | #define STFSM_OPC_WAIT 0x7 | ||
167 | #define STFSM_OPC_JUMP 0x8 | ||
168 | #define STFSM_OPC_GOTO 0x9 | ||
169 | #define STFSM_OPC_STOP 0xF | ||
170 | |||
171 | /* | ||
172 | * FSM SPI Instructions (== opcode + operand). | ||
173 | */ | ||
174 | #define STFSM_INSTR(cmd, op) ((cmd) | ((op) << 4)) | ||
175 | |||
176 | #define STFSM_INST_CMD1 STFSM_INSTR(STFSM_OPC_CMD, 1) | ||
177 | #define STFSM_INST_CMD2 STFSM_INSTR(STFSM_OPC_CMD, 2) | ||
178 | #define STFSM_INST_CMD3 STFSM_INSTR(STFSM_OPC_CMD, 3) | ||
179 | #define STFSM_INST_CMD4 STFSM_INSTR(STFSM_OPC_CMD, 4) | ||
180 | #define STFSM_INST_CMD5 STFSM_INSTR(STFSM_OPC_CMD, 5) | ||
181 | #define STFSM_INST_ADD1 STFSM_INSTR(STFSM_OPC_ADD, 1) | ||
182 | #define STFSM_INST_ADD2 STFSM_INSTR(STFSM_OPC_ADD, 2) | ||
183 | |||
184 | #define STFSM_INST_DATA_WRITE STFSM_INSTR(STFSM_OPC_DATA, 1) | ||
185 | #define STFSM_INST_DATA_READ STFSM_INSTR(STFSM_OPC_DATA, 2) | ||
186 | |||
187 | #define STFSM_INST_STA_RD1 STFSM_INSTR(STFSM_OPC_STA, 0x1) | ||
188 | #define STFSM_INST_STA_WR1 STFSM_INSTR(STFSM_OPC_STA, 0x1) | ||
189 | #define STFSM_INST_STA_RD2 STFSM_INSTR(STFSM_OPC_STA, 0x2) | ||
190 | #define STFSM_INST_STA_WR1_2 STFSM_INSTR(STFSM_OPC_STA, 0x3) | ||
191 | |||
192 | #define STFSM_INST_MODE STFSM_INSTR(STFSM_OPC_MODE, 0) | ||
193 | #define STFSM_INST_DUMMY STFSM_INSTR(STFSM_OPC_DUMMY, 0) | ||
194 | #define STFSM_INST_WAIT STFSM_INSTR(STFSM_OPC_WAIT, 0) | ||
195 | #define STFSM_INST_STOP STFSM_INSTR(STFSM_OPC_STOP, 0) | ||
196 | |||
197 | #define STFSM_DEFAULT_EMI_FREQ 100000000UL /* 100 MHz */ | ||
198 | #define STFSM_DEFAULT_WR_TIME (STFSM_DEFAULT_EMI_FREQ * (15/1000)) /* 15ms */ | ||
199 | |||
200 | #define STFSM_FLASH_SAFE_FREQ 10000000UL /* 10 MHz */ | ||
201 | |||
202 | #define STFSM_MAX_WAIT_SEQ_MS 1000 /* FSM execution time */ | ||
203 | |||
204 | /* Flash Commands */ | ||
205 | #define FLASH_CMD_WREN 0x06 | ||
206 | #define FLASH_CMD_WRDI 0x04 | ||
207 | #define FLASH_CMD_RDID 0x9f | ||
208 | #define FLASH_CMD_RDSR 0x05 | ||
209 | #define FLASH_CMD_RDSR2 0x35 | ||
210 | #define FLASH_CMD_WRSR 0x01 | ||
211 | #define FLASH_CMD_SE_4K 0x20 | ||
212 | #define FLASH_CMD_SE_32K 0x52 | ||
213 | #define FLASH_CMD_SE 0xd8 | ||
214 | #define FLASH_CMD_CHIPERASE 0xc7 | ||
215 | #define FLASH_CMD_WRVCR 0x81 | ||
216 | #define FLASH_CMD_RDVCR 0x85 | ||
217 | |||
218 | #define FLASH_CMD_READ 0x03 /* READ */ | ||
219 | #define FLASH_CMD_READ_FAST 0x0b /* FAST READ */ | ||
220 | #define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */ | ||
221 | #define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */ | ||
222 | #define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */ | ||
223 | #define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */ | ||
224 | |||
225 | #define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */ | ||
226 | #define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ | ||
227 | #define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ | ||
228 | #define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ | ||
229 | #define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ | ||
230 | |||
231 | #define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */ | ||
232 | #define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */ | ||
233 | |||
234 | /* READ commands with 32-bit addressing (N25Q256 and S25FLxxxS) */ | ||
235 | #define FLASH_CMD_READ4 0x13 | ||
236 | #define FLASH_CMD_READ4_FAST 0x0c | ||
237 | #define FLASH_CMD_READ4_1_1_2 0x3c | ||
238 | #define FLASH_CMD_READ4_1_2_2 0xbc | ||
239 | #define FLASH_CMD_READ4_1_1_4 0x6c | ||
240 | #define FLASH_CMD_READ4_1_4_4 0xec | ||
241 | |||
242 | /* S25FLxxxS commands */ | ||
243 | #define S25FL_CMD_WRITE4_1_1_4 0x34 | ||
244 | #define S25FL_CMD_SE4 0xdc | ||
245 | #define S25FL_CMD_CLSR 0x30 | ||
246 | #define S25FL_CMD_DYBWR 0xe1 | ||
247 | #define S25FL_CMD_DYBRD 0xe0 | ||
248 | #define S25FL_CMD_WRITE4 0x12 /* Note, opcode clashes with | ||
249 | * 'FLASH_CMD_WRITE_1_4_4' | ||
250 | * as found on N25Qxxx devices! */ | ||
251 | |||
252 | /* Status register */ | ||
253 | #define FLASH_STATUS_BUSY 0x01 | ||
254 | #define FLASH_STATUS_WEL 0x02 | ||
255 | #define FLASH_STATUS_BP0 0x04 | ||
256 | #define FLASH_STATUS_BP1 0x08 | ||
257 | #define FLASH_STATUS_BP2 0x10 | ||
258 | #define FLASH_STATUS_SRWP0 0x80 | ||
259 | #define FLASH_STATUS_TIMEOUT 0xff | ||
260 | /* S25FL Error Flags */ | ||
261 | #define S25FL_STATUS_E_ERR 0x20 | ||
262 | #define S25FL_STATUS_P_ERR 0x40 | ||
263 | |||
264 | #define FLASH_PAGESIZE 256 /* In Bytes */ | ||
265 | #define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */ | ||
266 | #define FLASH_MAX_BUSY_WAIT (300 * HZ) /* Maximum 'CHIPERASE' time */ | ||
267 | |||
268 | /* | ||
269 | * Flags to tweak operation of default read/write/erase routines | ||
270 | */ | ||
271 | #define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001 | ||
272 | #define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002 | ||
273 | #define CFG_WRITE_EX_32BIT_ADDR_DELAY 0x00000004 | ||
274 | #define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008 | ||
275 | #define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010 | ||
276 | |||
277 | struct stfsm_seq { | ||
278 | uint32_t data_size; | ||
279 | uint32_t addr1; | ||
280 | uint32_t addr2; | ||
281 | uint32_t addr_cfg; | ||
282 | uint32_t seq_opc[5]; | ||
283 | uint32_t mode; | ||
284 | uint32_t dummy; | ||
285 | uint32_t status; | ||
286 | uint8_t seq[16]; | ||
287 | uint32_t seq_cfg; | ||
288 | } __packed __aligned(4); | ||
289 | |||
290 | struct stfsm { | ||
291 | struct device *dev; | ||
292 | void __iomem *base; | ||
293 | struct resource *region; | ||
294 | struct mtd_info mtd; | ||
295 | struct mutex lock; | ||
296 | struct flash_info *info; | ||
297 | |||
298 | uint32_t configuration; | ||
299 | uint32_t fifo_dir_delay; | ||
300 | bool booted_from_spi; | ||
301 | bool reset_signal; | ||
302 | bool reset_por; | ||
303 | |||
304 | struct stfsm_seq stfsm_seq_read; | ||
305 | struct stfsm_seq stfsm_seq_write; | ||
306 | struct stfsm_seq stfsm_seq_en_32bit_addr; | ||
307 | }; | ||
308 | |||
309 | /* Parameters to configure a READ or WRITE FSM sequence */ | ||
310 | struct seq_rw_config { | ||
311 | uint32_t flags; /* flags to support config */ | ||
312 | uint8_t cmd; /* FLASH command */ | ||
313 | int write; /* Write Sequence */ | ||
314 | uint8_t addr_pads; /* No. of addr pads (MODE & DUMMY) */ | ||
315 | uint8_t data_pads; /* No. of data pads */ | ||
316 | uint8_t mode_data; /* MODE data */ | ||
317 | uint8_t mode_cycles; /* No. of MODE cycles */ | ||
318 | uint8_t dummy_cycles; /* No. of DUMMY cycles */ | ||
319 | }; | ||
320 | |||
321 | /* SPI Flash Device Table */ | ||
322 | struct flash_info { | ||
323 | char *name; | ||
324 | /* | ||
325 | * JEDEC id zero means "no ID" (most older chips); otherwise it has | ||
326 | * a high byte of zero plus three data bytes: the manufacturer id, | ||
327 | * then a two byte device id. | ||
328 | */ | ||
329 | u32 jedec_id; | ||
330 | u16 ext_id; | ||
331 | /* | ||
332 | * The size listed here is what works with FLASH_CMD_SE, which isn't | ||
333 | * necessarily called a "sector" by the vendor. | ||
334 | */ | ||
335 | unsigned sector_size; | ||
336 | u16 n_sectors; | ||
337 | u32 flags; | ||
338 | /* | ||
339 | * Note, where FAST_READ is supported, freq_max specifies the | ||
340 | * FAST_READ frequency, not the READ frequency. | ||
341 | */ | ||
342 | u32 max_freq; | ||
343 | int (*config)(struct stfsm *); | ||
344 | }; | ||
345 | |||
346 | static int stfsm_n25q_config(struct stfsm *fsm); | ||
347 | static int stfsm_mx25_config(struct stfsm *fsm); | ||
348 | static int stfsm_s25fl_config(struct stfsm *fsm); | ||
349 | static int stfsm_w25q_config(struct stfsm *fsm); | ||
350 | |||
351 | static struct flash_info flash_types[] = { | ||
352 | /* | ||
353 | * ST Microelectronics/Numonyx -- | ||
354 | * (newer production versions may have feature updates | ||
355 | * (eg faster operating frequency) | ||
356 | */ | ||
357 | #define M25P_FLAG (FLASH_FLAG_READ_WRITE | FLASH_FLAG_READ_FAST) | ||
358 | { "m25p40", 0x202013, 0, 64 * 1024, 8, M25P_FLAG, 25, NULL }, | ||
359 | { "m25p80", 0x202014, 0, 64 * 1024, 16, M25P_FLAG, 25, NULL }, | ||
360 | { "m25p16", 0x202015, 0, 64 * 1024, 32, M25P_FLAG, 25, NULL }, | ||
361 | { "m25p32", 0x202016, 0, 64 * 1024, 64, M25P_FLAG, 50, NULL }, | ||
362 | { "m25p64", 0x202017, 0, 64 * 1024, 128, M25P_FLAG, 50, NULL }, | ||
363 | { "m25p128", 0x202018, 0, 256 * 1024, 64, M25P_FLAG, 50, NULL }, | ||
364 | |||
365 | #define M25PX_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
366 | FLASH_FLAG_READ_FAST | \ | ||
367 | FLASH_FLAG_READ_1_1_2 | \ | ||
368 | FLASH_FLAG_WRITE_1_1_2) | ||
369 | { "m25px32", 0x207116, 0, 64 * 1024, 64, M25PX_FLAG, 75, NULL }, | ||
370 | { "m25px64", 0x207117, 0, 64 * 1024, 128, M25PX_FLAG, 75, NULL }, | ||
371 | |||
372 | #define MX25_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
373 | FLASH_FLAG_READ_FAST | \ | ||
374 | FLASH_FLAG_READ_1_1_2 | \ | ||
375 | FLASH_FLAG_READ_1_2_2 | \ | ||
376 | FLASH_FLAG_READ_1_1_4 | \ | ||
377 | FLASH_FLAG_READ_1_4_4 | \ | ||
378 | FLASH_FLAG_SE_4K | \ | ||
379 | FLASH_FLAG_SE_32K) | ||
380 | { "mx25l25635e", 0xc22019, 0, 64*1024, 512, | ||
381 | (MX25_FLAG | FLASH_FLAG_32BIT_ADDR | FLASH_FLAG_RESET), 70, | ||
382 | stfsm_mx25_config }, | ||
383 | |||
384 | #define N25Q_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
385 | FLASH_FLAG_READ_FAST | \ | ||
386 | FLASH_FLAG_READ_1_1_2 | \ | ||
387 | FLASH_FLAG_READ_1_2_2 | \ | ||
388 | FLASH_FLAG_READ_1_1_4 | \ | ||
389 | FLASH_FLAG_READ_1_4_4 | \ | ||
390 | FLASH_FLAG_WRITE_1_1_2 | \ | ||
391 | FLASH_FLAG_WRITE_1_2_2 | \ | ||
392 | FLASH_FLAG_WRITE_1_1_4 | \ | ||
393 | FLASH_FLAG_WRITE_1_4_4) | ||
394 | { "n25q128", 0x20ba18, 0, 64 * 1024, 256, N25Q_FLAG, 108, | ||
395 | stfsm_n25q_config }, | ||
396 | { "n25q256", 0x20ba19, 0, 64 * 1024, 512, | ||
397 | N25Q_FLAG | FLASH_FLAG_32BIT_ADDR, 108, stfsm_n25q_config }, | ||
398 | |||
399 | /* | ||
400 | * Spansion S25FLxxxP | ||
401 | * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) | ||
402 | */ | ||
403 | #define S25FLXXXP_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
404 | FLASH_FLAG_READ_1_1_2 | \ | ||
405 | FLASH_FLAG_READ_1_2_2 | \ | ||
406 | FLASH_FLAG_READ_1_1_4 | \ | ||
407 | FLASH_FLAG_READ_1_4_4 | \ | ||
408 | FLASH_FLAG_WRITE_1_1_4 | \ | ||
409 | FLASH_FLAG_READ_FAST) | ||
410 | { "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, S25FLXXXP_FLAG, 80, | ||
411 | stfsm_s25fl_config }, | ||
412 | { "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, S25FLXXXP_FLAG, 80, | ||
413 | stfsm_s25fl_config }, | ||
414 | |||
415 | /* | ||
416 | * Spansion S25FLxxxS | ||
417 | * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) | ||
418 | * - RESET# signal supported by die but not bristled out on all | ||
419 | * package types. The package type is a function of board design, | ||
420 | * so this information is captured in the board's flags. | ||
421 | * - Supports 'DYB' sector protection. Depending on variant, sectors | ||
422 | * may default to locked state on power-on. | ||
423 | */ | ||
424 | #define S25FLXXXS_FLAG (S25FLXXXP_FLAG | \ | ||
425 | FLASH_FLAG_RESET | \ | ||
426 | FLASH_FLAG_DYB_LOCKING) | ||
427 | { "s25fl128s0", 0x012018, 0x0300, 256 * 1024, 64, S25FLXXXS_FLAG, 80, | ||
428 | stfsm_s25fl_config }, | ||
429 | { "s25fl128s1", 0x012018, 0x0301, 64 * 1024, 256, S25FLXXXS_FLAG, 80, | ||
430 | stfsm_s25fl_config }, | ||
431 | { "s25fl256s0", 0x010219, 0x4d00, 256 * 1024, 128, | ||
432 | S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config }, | ||
433 | { "s25fl256s1", 0x010219, 0x4d01, 64 * 1024, 512, | ||
434 | S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config }, | ||
435 | |||
436 | /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ | ||
437 | #define W25X_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
438 | FLASH_FLAG_READ_FAST | \ | ||
439 | FLASH_FLAG_READ_1_1_2 | \ | ||
440 | FLASH_FLAG_WRITE_1_1_2) | ||
441 | { "w25x40", 0xef3013, 0, 64 * 1024, 8, W25X_FLAG, 75, NULL }, | ||
442 | { "w25x80", 0xef3014, 0, 64 * 1024, 16, W25X_FLAG, 75, NULL }, | ||
443 | { "w25x16", 0xef3015, 0, 64 * 1024, 32, W25X_FLAG, 75, NULL }, | ||
444 | { "w25x32", 0xef3016, 0, 64 * 1024, 64, W25X_FLAG, 75, NULL }, | ||
445 | { "w25x64", 0xef3017, 0, 64 * 1024, 128, W25X_FLAG, 75, NULL }, | ||
446 | |||
447 | /* Winbond -- w25q "blocks" are 64K, "sectors" are 4KiB */ | ||
448 | #define W25Q_FLAG (FLASH_FLAG_READ_WRITE | \ | ||
449 | FLASH_FLAG_READ_FAST | \ | ||
450 | FLASH_FLAG_READ_1_1_2 | \ | ||
451 | FLASH_FLAG_READ_1_2_2 | \ | ||
452 | FLASH_FLAG_READ_1_1_4 | \ | ||
453 | FLASH_FLAG_READ_1_4_4 | \ | ||
454 | FLASH_FLAG_WRITE_1_1_4) | ||
455 | { "w25q80", 0xef4014, 0, 64 * 1024, 16, W25Q_FLAG, 80, | ||
456 | stfsm_w25q_config }, | ||
457 | { "w25q16", 0xef4015, 0, 64 * 1024, 32, W25Q_FLAG, 80, | ||
458 | stfsm_w25q_config }, | ||
459 | { "w25q32", 0xef4016, 0, 64 * 1024, 64, W25Q_FLAG, 80, | ||
460 | stfsm_w25q_config }, | ||
461 | { "w25q64", 0xef4017, 0, 64 * 1024, 128, W25Q_FLAG, 80, | ||
462 | stfsm_w25q_config }, | ||
463 | |||
464 | /* Sentinel */ | ||
465 | { NULL, 0x000000, 0, 0, 0, 0, 0, NULL }, | ||
466 | }; | ||
467 | |||
468 | /* | ||
469 | * FSM message sequence configurations: | ||
470 | * | ||
471 | * All configs are presented in order of preference | ||
472 | */ | ||
473 | |||
474 | /* Default READ configurations, in order of preference */ | ||
475 | static struct seq_rw_config default_read_configs[] = { | ||
476 | {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ_1_4_4, 0, 4, 4, 0x00, 2, 4}, | ||
477 | {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ_1_1_4, 0, 1, 4, 0x00, 4, 0}, | ||
478 | {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ_1_2_2, 0, 2, 2, 0x00, 4, 0}, | ||
479 | {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ_1_1_2, 0, 1, 2, 0x00, 0, 8}, | ||
480 | {FLASH_FLAG_READ_FAST, FLASH_CMD_READ_FAST, 0, 1, 1, 0x00, 0, 8}, | ||
481 | {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ, 0, 1, 1, 0x00, 0, 0}, | ||
482 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
483 | }; | ||
484 | |||
485 | /* Default WRITE configurations */ | ||
486 | static struct seq_rw_config default_write_configs[] = { | ||
487 | {FLASH_FLAG_WRITE_1_4_4, FLASH_CMD_WRITE_1_4_4, 1, 4, 4, 0x00, 0, 0}, | ||
488 | {FLASH_FLAG_WRITE_1_1_4, FLASH_CMD_WRITE_1_1_4, 1, 1, 4, 0x00, 0, 0}, | ||
489 | {FLASH_FLAG_WRITE_1_2_2, FLASH_CMD_WRITE_1_2_2, 1, 2, 2, 0x00, 0, 0}, | ||
490 | {FLASH_FLAG_WRITE_1_1_2, FLASH_CMD_WRITE_1_1_2, 1, 1, 2, 0x00, 0, 0}, | ||
491 | {FLASH_FLAG_READ_WRITE, FLASH_CMD_WRITE, 1, 1, 1, 0x00, 0, 0}, | ||
492 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
493 | }; | ||
494 | |||
495 | /* | ||
496 | * [N25Qxxx] Configuration | ||
497 | */ | ||
498 | #define N25Q_VCR_DUMMY_CYCLES(x) (((x) & 0xf) << 4) | ||
499 | #define N25Q_VCR_XIP_DISABLED ((uint8_t)0x1 << 3) | ||
500 | #define N25Q_VCR_WRAP_CONT 0x3 | ||
501 | |||
502 | /* N25Q 3-byte Address READ configurations | ||
503 | * - 'FAST' variants configured for 8 dummy cycles. | ||
504 | * | ||
505 | * Note, the number of dummy cycles used for 'FAST' READ operations is | ||
506 | * configurable and would normally be tuned according to the READ command and | ||
507 | * operating frequency. However, this applies universally to all 'FAST' READ | ||
508 | * commands, including those used by the SPIBoot controller, and remains in | ||
509 | * force until the device is power-cycled. Since the SPIBoot controller is | ||
510 | * hard-wired to use 8 dummy cycles, we must configure the device to also use 8 | ||
511 | * cycles. | ||
512 | */ | ||
513 | static struct seq_rw_config n25q_read3_configs[] = { | ||
514 | {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ_1_4_4, 0, 4, 4, 0x00, 0, 8}, | ||
515 | {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ_1_1_4, 0, 1, 4, 0x00, 0, 8}, | ||
516 | {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ_1_2_2, 0, 2, 2, 0x00, 0, 8}, | ||
517 | {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ_1_1_2, 0, 1, 2, 0x00, 0, 8}, | ||
518 | {FLASH_FLAG_READ_FAST, FLASH_CMD_READ_FAST, 0, 1, 1, 0x00, 0, 8}, | ||
519 | {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ, 0, 1, 1, 0x00, 0, 0}, | ||
520 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
521 | }; | ||
522 | |||
523 | /* N25Q 4-byte Address READ configurations | ||
524 | * - use special 4-byte address READ commands (reduces overheads, and | ||
525 | * reduces risk of hitting watchdog reset issues). | ||
526 | * - 'FAST' variants configured for 8 dummy cycles (see note above.) | ||
527 | */ | ||
528 | static struct seq_rw_config n25q_read4_configs[] = { | ||
529 | {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ4_1_4_4, 0, 4, 4, 0x00, 0, 8}, | ||
530 | {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, | ||
531 | {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ4_1_2_2, 0, 2, 2, 0x00, 0, 8}, | ||
532 | {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, | ||
533 | {FLASH_FLAG_READ_FAST, FLASH_CMD_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, | ||
534 | {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ4, 0, 1, 1, 0x00, 0, 0}, | ||
535 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
536 | }; | ||
537 | |||
538 | /* | ||
539 | * [MX25xxx] Configuration | ||
540 | */ | ||
541 | #define MX25_STATUS_QE (0x1 << 6) | ||
542 | |||
543 | static int stfsm_mx25_en_32bit_addr_seq(struct stfsm_seq *seq) | ||
544 | { | ||
545 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
546 | SEQ_OPC_CYCLES(8) | | ||
547 | SEQ_OPC_OPCODE(FLASH_CMD_EN4B_ADDR) | | ||
548 | SEQ_OPC_CSDEASSERT); | ||
549 | |||
550 | seq->seq[0] = STFSM_INST_CMD1; | ||
551 | seq->seq[1] = STFSM_INST_WAIT; | ||
552 | seq->seq[2] = STFSM_INST_STOP; | ||
553 | |||
554 | seq->seq_cfg = (SEQ_CFG_PADS_1 | | ||
555 | SEQ_CFG_ERASE | | ||
556 | SEQ_CFG_READNOTWRITE | | ||
557 | SEQ_CFG_CSDEASSERT | | ||
558 | SEQ_CFG_STARTSEQ); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | /* | ||
564 | * [S25FLxxx] Configuration | ||
565 | */ | ||
566 | #define STFSM_S25FL_CONFIG_QE (0x1 << 1) | ||
567 | |||
568 | /* | ||
569 | * S25FLxxxS devices provide three ways of supporting 32-bit addressing: Bank | ||
570 | * Register, Extended Address Modes, and a 32-bit address command set. The | ||
571 | * 32-bit address command set is used here, since it avoids any problems with | ||
572 | * entering a state that is incompatible with the SPIBoot Controller. | ||
573 | */ | ||
574 | static struct seq_rw_config stfsm_s25fl_read4_configs[] = { | ||
575 | {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4}, | ||
576 | {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, | ||
577 | {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0}, | ||
578 | {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, | ||
579 | {FLASH_FLAG_READ_FAST, FLASH_CMD_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, | ||
580 | {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ4, 0, 1, 1, 0x00, 0, 0}, | ||
581 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
582 | }; | ||
583 | |||
584 | static struct seq_rw_config stfsm_s25fl_write4_configs[] = { | ||
585 | {FLASH_FLAG_WRITE_1_1_4, S25FL_CMD_WRITE4_1_1_4, 1, 1, 4, 0x00, 0, 0}, | ||
586 | {FLASH_FLAG_READ_WRITE, S25FL_CMD_WRITE4, 1, 1, 1, 0x00, 0, 0}, | ||
587 | {0x00, 0, 0, 0, 0, 0x00, 0, 0}, | ||
588 | }; | ||
589 | |||
590 | /* | ||
591 | * [W25Qxxx] Configuration | ||
592 | */ | ||
593 | #define W25Q_STATUS_QE (0x1 << 9) | ||
594 | |||
595 | static struct stfsm_seq stfsm_seq_read_jedec = { | ||
596 | .data_size = TRANSFER_SIZE(8), | ||
597 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
598 | SEQ_OPC_CYCLES(8) | | ||
599 | SEQ_OPC_OPCODE(FLASH_CMD_RDID)), | ||
600 | .seq = { | ||
601 | STFSM_INST_CMD1, | ||
602 | STFSM_INST_DATA_READ, | ||
603 | STFSM_INST_STOP, | ||
604 | }, | ||
605 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
606 | SEQ_CFG_READNOTWRITE | | ||
607 | SEQ_CFG_CSDEASSERT | | ||
608 | SEQ_CFG_STARTSEQ), | ||
609 | }; | ||
610 | |||
611 | static struct stfsm_seq stfsm_seq_read_status_fifo = { | ||
612 | .data_size = TRANSFER_SIZE(4), | ||
613 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
614 | SEQ_OPC_CYCLES(8) | | ||
615 | SEQ_OPC_OPCODE(FLASH_CMD_RDSR)), | ||
616 | .seq = { | ||
617 | STFSM_INST_CMD1, | ||
618 | STFSM_INST_DATA_READ, | ||
619 | STFSM_INST_STOP, | ||
620 | }, | ||
621 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
622 | SEQ_CFG_READNOTWRITE | | ||
623 | SEQ_CFG_CSDEASSERT | | ||
624 | SEQ_CFG_STARTSEQ), | ||
625 | }; | ||
626 | |||
627 | static struct stfsm_seq stfsm_seq_erase_sector = { | ||
628 | /* 'addr_cfg' configured during initialisation */ | ||
629 | .seq_opc = { | ||
630 | (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
631 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), | ||
632 | |||
633 | (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
634 | SEQ_OPC_OPCODE(FLASH_CMD_SE)), | ||
635 | }, | ||
636 | .seq = { | ||
637 | STFSM_INST_CMD1, | ||
638 | STFSM_INST_CMD2, | ||
639 | STFSM_INST_ADD1, | ||
640 | STFSM_INST_ADD2, | ||
641 | STFSM_INST_STOP, | ||
642 | }, | ||
643 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
644 | SEQ_CFG_READNOTWRITE | | ||
645 | SEQ_CFG_CSDEASSERT | | ||
646 | SEQ_CFG_STARTSEQ), | ||
647 | }; | ||
648 | |||
649 | static struct stfsm_seq stfsm_seq_erase_chip = { | ||
650 | .seq_opc = { | ||
651 | (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
652 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), | ||
653 | |||
654 | (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
655 | SEQ_OPC_OPCODE(FLASH_CMD_CHIPERASE) | SEQ_OPC_CSDEASSERT), | ||
656 | }, | ||
657 | .seq = { | ||
658 | STFSM_INST_CMD1, | ||
659 | STFSM_INST_CMD2, | ||
660 | STFSM_INST_WAIT, | ||
661 | STFSM_INST_STOP, | ||
662 | }, | ||
663 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
664 | SEQ_CFG_ERASE | | ||
665 | SEQ_CFG_READNOTWRITE | | ||
666 | SEQ_CFG_CSDEASSERT | | ||
667 | SEQ_CFG_STARTSEQ), | ||
668 | }; | ||
669 | |||
670 | static struct stfsm_seq stfsm_seq_write_status = { | ||
671 | .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
672 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), | ||
673 | .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
674 | SEQ_OPC_OPCODE(FLASH_CMD_WRSR)), | ||
675 | .seq = { | ||
676 | STFSM_INST_CMD1, | ||
677 | STFSM_INST_CMD2, | ||
678 | STFSM_INST_STA_WR1, | ||
679 | STFSM_INST_STOP, | ||
680 | }, | ||
681 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
682 | SEQ_CFG_READNOTWRITE | | ||
683 | SEQ_CFG_CSDEASSERT | | ||
684 | SEQ_CFG_STARTSEQ), | ||
685 | }; | ||
686 | |||
687 | static struct stfsm_seq stfsm_seq_wrvcr = { | ||
688 | .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
689 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), | ||
690 | .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
691 | SEQ_OPC_OPCODE(FLASH_CMD_WRVCR)), | ||
692 | .seq = { | ||
693 | STFSM_INST_CMD1, | ||
694 | STFSM_INST_CMD2, | ||
695 | STFSM_INST_STA_WR1, | ||
696 | STFSM_INST_STOP, | ||
697 | }, | ||
698 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
699 | SEQ_CFG_READNOTWRITE | | ||
700 | SEQ_CFG_CSDEASSERT | | ||
701 | SEQ_CFG_STARTSEQ), | ||
702 | }; | ||
703 | |||
704 | static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) | ||
705 | { | ||
706 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
707 | SEQ_OPC_OPCODE(FLASH_CMD_EN4B_ADDR)); | ||
708 | seq->seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
709 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | | ||
710 | SEQ_OPC_CSDEASSERT); | ||
711 | |||
712 | seq->seq[0] = STFSM_INST_CMD2; | ||
713 | seq->seq[1] = STFSM_INST_CMD1; | ||
714 | seq->seq[2] = STFSM_INST_WAIT; | ||
715 | seq->seq[3] = STFSM_INST_STOP; | ||
716 | |||
717 | seq->seq_cfg = (SEQ_CFG_PADS_1 | | ||
718 | SEQ_CFG_ERASE | | ||
719 | SEQ_CFG_READNOTWRITE | | ||
720 | SEQ_CFG_CSDEASSERT | | ||
721 | SEQ_CFG_STARTSEQ); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static inline int stfsm_is_idle(struct stfsm *fsm) | ||
727 | { | ||
728 | return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10; | ||
729 | } | ||
730 | |||
731 | static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) | ||
732 | { | ||
733 | return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; | ||
734 | } | ||
735 | |||
736 | static void stfsm_clear_fifo(struct stfsm *fsm) | ||
737 | { | ||
738 | uint32_t avail; | ||
739 | |||
740 | for (;;) { | ||
741 | avail = stfsm_fifo_available(fsm); | ||
742 | if (!avail) | ||
743 | break; | ||
744 | |||
745 | while (avail) { | ||
746 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
747 | avail--; | ||
748 | } | ||
749 | } | ||
750 | } | ||
751 | |||
752 | static inline void stfsm_load_seq(struct stfsm *fsm, | ||
753 | const struct stfsm_seq *seq) | ||
754 | { | ||
755 | void __iomem *dst = fsm->base + SPI_FAST_SEQ_TRANSFER_SIZE; | ||
756 | const uint32_t *src = (const uint32_t *)seq; | ||
757 | int words = sizeof(*seq) / sizeof(*src); | ||
758 | |||
759 | BUG_ON(!stfsm_is_idle(fsm)); | ||
760 | |||
761 | while (words--) { | ||
762 | writel(*src, dst); | ||
763 | src++; | ||
764 | dst += 4; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | static void stfsm_wait_seq(struct stfsm *fsm) | ||
769 | { | ||
770 | unsigned long deadline; | ||
771 | int timeout = 0; | ||
772 | |||
773 | deadline = jiffies + msecs_to_jiffies(STFSM_MAX_WAIT_SEQ_MS); | ||
774 | |||
775 | while (!timeout) { | ||
776 | if (time_after_eq(jiffies, deadline)) | ||
777 | timeout = 1; | ||
778 | |||
779 | if (stfsm_is_idle(fsm)) | ||
780 | return; | ||
781 | |||
782 | cond_resched(); | ||
783 | } | ||
784 | |||
785 | dev_err(fsm->dev, "timeout on sequence completion\n"); | ||
786 | } | ||
787 | |||
788 | static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, uint32_t size) | ||
789 | { | ||
790 | uint32_t remaining = size >> 2; | ||
791 | uint32_t avail; | ||
792 | uint32_t words; | ||
793 | |||
794 | dev_dbg(fsm->dev, "Reading %d bytes from FIFO\n", size); | ||
795 | |||
796 | BUG_ON((((uint32_t)buf) & 0x3) || (size & 0x3)); | ||
797 | |||
798 | while (remaining) { | ||
799 | for (;;) { | ||
800 | avail = stfsm_fifo_available(fsm); | ||
801 | if (avail) | ||
802 | break; | ||
803 | udelay(1); | ||
804 | } | ||
805 | words = min(avail, remaining); | ||
806 | remaining -= words; | ||
807 | |||
808 | readsl(fsm->base + SPI_FAST_SEQ_DATA_REG, buf, words); | ||
809 | buf += words; | ||
810 | } | ||
811 | } | ||
812 | |||
813 | static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf, | ||
814 | uint32_t size) | ||
815 | { | ||
816 | uint32_t words = size >> 2; | ||
817 | |||
818 | dev_dbg(fsm->dev, "writing %d bytes to FIFO\n", size); | ||
819 | |||
820 | BUG_ON((((uint32_t)buf) & 0x3) || (size & 0x3)); | ||
821 | |||
822 | writesl(fsm->base + SPI_FAST_SEQ_DATA_REG, buf, words); | ||
823 | |||
824 | return size; | ||
825 | } | ||
826 | |||
827 | static int stfsm_enter_32bit_addr(struct stfsm *fsm, int enter) | ||
828 | { | ||
829 | struct stfsm_seq *seq = &fsm->stfsm_seq_en_32bit_addr; | ||
830 | uint32_t cmd = enter ? FLASH_CMD_EN4B_ADDR : FLASH_CMD_EX4B_ADDR; | ||
831 | |||
832 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
833 | SEQ_OPC_CYCLES(8) | | ||
834 | SEQ_OPC_OPCODE(cmd) | | ||
835 | SEQ_OPC_CSDEASSERT); | ||
836 | |||
837 | stfsm_load_seq(fsm, seq); | ||
838 | |||
839 | stfsm_wait_seq(fsm); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static uint8_t stfsm_wait_busy(struct stfsm *fsm) | ||
845 | { | ||
846 | struct stfsm_seq *seq = &stfsm_seq_read_status_fifo; | ||
847 | unsigned long deadline; | ||
848 | uint32_t status; | ||
849 | int timeout = 0; | ||
850 | |||
851 | /* Use RDRS1 */ | ||
852 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
853 | SEQ_OPC_CYCLES(8) | | ||
854 | SEQ_OPC_OPCODE(FLASH_CMD_RDSR)); | ||
855 | |||
856 | /* Load read_status sequence */ | ||
857 | stfsm_load_seq(fsm, seq); | ||
858 | |||
859 | /* | ||
860 | * Repeat until busy bit is deasserted, or timeout, or error (S25FLxxxS) | ||
861 | */ | ||
862 | deadline = jiffies + FLASH_MAX_BUSY_WAIT; | ||
863 | while (!timeout) { | ||
864 | if (time_after_eq(jiffies, deadline)) | ||
865 | timeout = 1; | ||
866 | |||
867 | stfsm_wait_seq(fsm); | ||
868 | |||
869 | stfsm_read_fifo(fsm, &status, 4); | ||
870 | |||
871 | if ((status & FLASH_STATUS_BUSY) == 0) | ||
872 | return 0; | ||
873 | |||
874 | if ((fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) && | ||
875 | ((status & S25FL_STATUS_P_ERR) || | ||
876 | (status & S25FL_STATUS_E_ERR))) | ||
877 | return (uint8_t)(status & 0xff); | ||
878 | |||
879 | if (!timeout) | ||
880 | /* Restart */ | ||
881 | writel(seq->seq_cfg, fsm->base + SPI_FAST_SEQ_CFG); | ||
882 | |||
883 | cond_resched(); | ||
884 | } | ||
885 | |||
886 | dev_err(fsm->dev, "timeout on wait_busy\n"); | ||
887 | |||
888 | return FLASH_STATUS_TIMEOUT; | ||
889 | } | ||
890 | |||
891 | static int stfsm_read_status(struct stfsm *fsm, uint8_t cmd, | ||
892 | uint8_t *status) | ||
893 | { | ||
894 | struct stfsm_seq *seq = &stfsm_seq_read_status_fifo; | ||
895 | uint32_t tmp; | ||
896 | |||
897 | dev_dbg(fsm->dev, "reading STA[%s]\n", | ||
898 | (cmd == FLASH_CMD_RDSR) ? "1" : "2"); | ||
899 | |||
900 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
901 | SEQ_OPC_CYCLES(8) | | ||
902 | SEQ_OPC_OPCODE(cmd)), | ||
903 | |||
904 | stfsm_load_seq(fsm, seq); | ||
905 | |||
906 | stfsm_read_fifo(fsm, &tmp, 4); | ||
907 | |||
908 | *status = (uint8_t)(tmp >> 24); | ||
909 | |||
910 | stfsm_wait_seq(fsm); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static int stfsm_write_status(struct stfsm *fsm, uint16_t status, | ||
916 | int sta_bytes) | ||
917 | { | ||
918 | struct stfsm_seq *seq = &stfsm_seq_write_status; | ||
919 | |||
920 | dev_dbg(fsm->dev, "writing STA[%s] 0x%04x\n", | ||
921 | (sta_bytes == 1) ? "1" : "1+2", status); | ||
922 | |||
923 | seq->status = (uint32_t)status | STA_PADS_1 | STA_CSDEASSERT; | ||
924 | seq->seq[2] = (sta_bytes == 1) ? | ||
925 | STFSM_INST_STA_WR1 : STFSM_INST_STA_WR1_2; | ||
926 | |||
927 | stfsm_load_seq(fsm, seq); | ||
928 | |||
929 | stfsm_wait_seq(fsm); | ||
930 | |||
931 | return 0; | ||
932 | }; | ||
933 | |||
934 | static int stfsm_wrvcr(struct stfsm *fsm, uint8_t data) | ||
935 | { | ||
936 | struct stfsm_seq *seq = &stfsm_seq_wrvcr; | ||
937 | |||
938 | dev_dbg(fsm->dev, "writing VCR 0x%02x\n", data); | ||
939 | |||
940 | seq->status = (STA_DATA_BYTE1(data) | STA_PADS_1 | STA_CSDEASSERT); | ||
941 | |||
942 | stfsm_load_seq(fsm, seq); | ||
943 | |||
944 | stfsm_wait_seq(fsm); | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | /* | ||
950 | * SoC reset on 'boot-from-spi' systems | ||
951 | * | ||
952 | * Certain modes of operation cause the Flash device to enter a particular state | ||
953 | * for a period of time (e.g. 'Erase Sector', 'Quad Enable', and 'Enter 32-bit | ||
954 | * Addr' commands). On boot-from-spi systems, it is important to consider what | ||
955 | * happens if a warm reset occurs during this period. The SPIBoot controller | ||
956 | * assumes that Flash device is in its default reset state, 24-bit address mode, | ||
957 | * and ready to accept commands. This can be achieved using some form of | ||
958 | * on-board logic/controller to force a device POR in response to a SoC-level | ||
959 | * reset or by making use of the device reset signal if available (limited | ||
960 | * number of devices only). | ||
961 | * | ||
962 | * Failure to take such precautions can cause problems following a warm reset. | ||
963 | * For some operations (e.g. ERASE), there is little that can be done. For | ||
964 | * other modes of operation (e.g. 32-bit addressing), options are often | ||
965 | * available that can help minimise the window in which a reset could cause a | ||
966 | * problem. | ||
967 | * | ||
968 | */ | ||
969 | static bool stfsm_can_handle_soc_reset(struct stfsm *fsm) | ||
970 | { | ||
971 | /* Reset signal is available on the board and supported by the device */ | ||
972 | if (fsm->reset_signal && fsm->info->flags & FLASH_FLAG_RESET) | ||
973 | return true; | ||
974 | |||
975 | /* Board-level logic forces a power-on-reset */ | ||
976 | if (fsm->reset_por) | ||
977 | return true; | ||
978 | |||
979 | /* Reset is not properly handled and may result in failure to reboot */ | ||
980 | return false; | ||
981 | } | ||
982 | |||
983 | /* Configure 'addr_cfg' according to addressing mode */ | ||
984 | static void stfsm_prepare_erasesec_seq(struct stfsm *fsm, | ||
985 | struct stfsm_seq *seq) | ||
986 | { | ||
987 | int addr1_cycles = fsm->info->flags & FLASH_FLAG_32BIT_ADDR ? 16 : 8; | ||
988 | |||
989 | seq->addr_cfg = (ADR_CFG_CYCLES_ADD1(addr1_cycles) | | ||
990 | ADR_CFG_PADS_1_ADD1 | | ||
991 | ADR_CFG_CYCLES_ADD2(16) | | ||
992 | ADR_CFG_PADS_1_ADD2 | | ||
993 | ADR_CFG_CSDEASSERT_ADD2); | ||
994 | } | ||
995 | |||
996 | /* Search for preferred configuration based on available flags */ | ||
997 | static struct seq_rw_config * | ||
998 | stfsm_search_seq_rw_configs(struct stfsm *fsm, | ||
999 | struct seq_rw_config cfgs[]) | ||
1000 | { | ||
1001 | struct seq_rw_config *config; | ||
1002 | int flags = fsm->info->flags; | ||
1003 | |||
1004 | for (config = cfgs; config->cmd != 0; config++) | ||
1005 | if ((config->flags & flags) == config->flags) | ||
1006 | return config; | ||
1007 | |||
1008 | return NULL; | ||
1009 | } | ||
1010 | |||
1011 | /* Prepare a READ/WRITE sequence according to configuration parameters */ | ||
1012 | static void stfsm_prepare_rw_seq(struct stfsm *fsm, | ||
1013 | struct stfsm_seq *seq, | ||
1014 | struct seq_rw_config *cfg) | ||
1015 | { | ||
1016 | int addr1_cycles, addr2_cycles; | ||
1017 | int i = 0; | ||
1018 | |||
1019 | memset(seq, 0, sizeof(*seq)); | ||
1020 | |||
1021 | /* Add READ/WRITE OPC */ | ||
1022 | seq->seq_opc[i++] = (SEQ_OPC_PADS_1 | | ||
1023 | SEQ_OPC_CYCLES(8) | | ||
1024 | SEQ_OPC_OPCODE(cfg->cmd)); | ||
1025 | |||
1026 | /* Add WREN OPC for a WRITE sequence */ | ||
1027 | if (cfg->write) | ||
1028 | seq->seq_opc[i++] = (SEQ_OPC_PADS_1 | | ||
1029 | SEQ_OPC_CYCLES(8) | | ||
1030 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | | ||
1031 | SEQ_OPC_CSDEASSERT); | ||
1032 | |||
1033 | /* Address configuration (24 or 32-bit addresses) */ | ||
1034 | addr1_cycles = (fsm->info->flags & FLASH_FLAG_32BIT_ADDR) ? 16 : 8; | ||
1035 | addr1_cycles /= cfg->addr_pads; | ||
1036 | addr2_cycles = 16 / cfg->addr_pads; | ||
1037 | seq->addr_cfg = ((addr1_cycles & 0x3f) << 0 | /* ADD1 cycles */ | ||
1038 | (cfg->addr_pads - 1) << 6 | /* ADD1 pads */ | ||
1039 | (addr2_cycles & 0x3f) << 16 | /* ADD2 cycles */ | ||
1040 | ((cfg->addr_pads - 1) << 22)); /* ADD2 pads */ | ||
1041 | |||
1042 | /* Data/Sequence configuration */ | ||
1043 | seq->seq_cfg = ((cfg->data_pads - 1) << 16 | | ||
1044 | SEQ_CFG_STARTSEQ | | ||
1045 | SEQ_CFG_CSDEASSERT); | ||
1046 | if (!cfg->write) | ||
1047 | seq->seq_cfg |= SEQ_CFG_READNOTWRITE; | ||
1048 | |||
1049 | /* Mode configuration (no. of pads taken from addr cfg) */ | ||
1050 | seq->mode = ((cfg->mode_data & 0xff) << 0 | /* data */ | ||
1051 | (cfg->mode_cycles & 0x3f) << 16 | /* cycles */ | ||
1052 | (cfg->addr_pads - 1) << 22); /* pads */ | ||
1053 | |||
1054 | /* Dummy configuration (no. of pads taken from addr cfg) */ | ||
1055 | seq->dummy = ((cfg->dummy_cycles & 0x3f) << 16 | /* cycles */ | ||
1056 | (cfg->addr_pads - 1) << 22); /* pads */ | ||
1057 | |||
1058 | |||
1059 | /* Instruction sequence */ | ||
1060 | i = 0; | ||
1061 | if (cfg->write) | ||
1062 | seq->seq[i++] = STFSM_INST_CMD2; | ||
1063 | |||
1064 | seq->seq[i++] = STFSM_INST_CMD1; | ||
1065 | |||
1066 | seq->seq[i++] = STFSM_INST_ADD1; | ||
1067 | seq->seq[i++] = STFSM_INST_ADD2; | ||
1068 | |||
1069 | if (cfg->mode_cycles) | ||
1070 | seq->seq[i++] = STFSM_INST_MODE; | ||
1071 | |||
1072 | if (cfg->dummy_cycles) | ||
1073 | seq->seq[i++] = STFSM_INST_DUMMY; | ||
1074 | |||
1075 | seq->seq[i++] = | ||
1076 | cfg->write ? STFSM_INST_DATA_WRITE : STFSM_INST_DATA_READ; | ||
1077 | seq->seq[i++] = STFSM_INST_STOP; | ||
1078 | } | ||
1079 | |||
1080 | static int stfsm_search_prepare_rw_seq(struct stfsm *fsm, | ||
1081 | struct stfsm_seq *seq, | ||
1082 | struct seq_rw_config *cfgs) | ||
1083 | { | ||
1084 | struct seq_rw_config *config; | ||
1085 | |||
1086 | config = stfsm_search_seq_rw_configs(fsm, cfgs); | ||
1087 | if (!config) { | ||
1088 | dev_err(fsm->dev, "failed to find suitable config\n"); | ||
1089 | return -EINVAL; | ||
1090 | } | ||
1091 | |||
1092 | stfsm_prepare_rw_seq(fsm, seq, config); | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | /* Prepare a READ/WRITE/ERASE 'default' sequences */ | ||
1098 | static int stfsm_prepare_rwe_seqs_default(struct stfsm *fsm) | ||
1099 | { | ||
1100 | uint32_t flags = fsm->info->flags; | ||
1101 | int ret; | ||
1102 | |||
1103 | /* Configure 'READ' sequence */ | ||
1104 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, | ||
1105 | default_read_configs); | ||
1106 | if (ret) { | ||
1107 | dev_err(fsm->dev, | ||
1108 | "failed to prep READ sequence with flags [0x%08x]\n", | ||
1109 | flags); | ||
1110 | return ret; | ||
1111 | } | ||
1112 | |||
1113 | /* Configure 'WRITE' sequence */ | ||
1114 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, | ||
1115 | default_write_configs); | ||
1116 | if (ret) { | ||
1117 | dev_err(fsm->dev, | ||
1118 | "failed to prep WRITE sequence with flags [0x%08x]\n", | ||
1119 | flags); | ||
1120 | return ret; | ||
1121 | } | ||
1122 | |||
1123 | /* Configure 'ERASE_SECTOR' sequence */ | ||
1124 | stfsm_prepare_erasesec_seq(fsm, &stfsm_seq_erase_sector); | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static int stfsm_mx25_config(struct stfsm *fsm) | ||
1130 | { | ||
1131 | uint32_t flags = fsm->info->flags; | ||
1132 | uint32_t data_pads; | ||
1133 | uint8_t sta; | ||
1134 | int ret; | ||
1135 | bool soc_reset; | ||
1136 | |||
1137 | /* | ||
1138 | * Use default READ/WRITE sequences | ||
1139 | */ | ||
1140 | ret = stfsm_prepare_rwe_seqs_default(fsm); | ||
1141 | if (ret) | ||
1142 | return ret; | ||
1143 | |||
1144 | /* | ||
1145 | * Configure 32-bit Address Support | ||
1146 | */ | ||
1147 | if (flags & FLASH_FLAG_32BIT_ADDR) { | ||
1148 | /* Configure 'enter_32bitaddr' FSM sequence */ | ||
1149 | stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); | ||
1150 | |||
1151 | soc_reset = stfsm_can_handle_soc_reset(fsm); | ||
1152 | if (soc_reset || !fsm->booted_from_spi) { | ||
1153 | /* If we can handle SoC resets, we enable 32-bit address | ||
1154 | * mode pervasively */ | ||
1155 | stfsm_enter_32bit_addr(fsm, 1); | ||
1156 | |||
1157 | } else { | ||
1158 | /* Else, enable/disable 32-bit addressing before/after | ||
1159 | * each operation */ | ||
1160 | fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR | | ||
1161 | CFG_WRITE_TOGGLE_32BIT_ADDR | | ||
1162 | CFG_ERASESEC_TOGGLE_32BIT_ADDR); | ||
1163 | /* It seems a small delay is required after exiting | ||
1164 | * 32-bit mode following a write operation. The issue | ||
1165 | * is under investigation. | ||
1166 | */ | ||
1167 | fsm->configuration |= CFG_WRITE_EX_32BIT_ADDR_DELAY; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | /* For QUAD mode, set 'QE' STATUS bit */ | ||
1172 | data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; | ||
1173 | if (data_pads == 4) { | ||
1174 | stfsm_read_status(fsm, FLASH_CMD_RDSR, &sta); | ||
1175 | sta |= MX25_STATUS_QE; | ||
1176 | stfsm_write_status(fsm, sta, 1); | ||
1177 | } | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | static int stfsm_n25q_config(struct stfsm *fsm) | ||
1183 | { | ||
1184 | uint32_t flags = fsm->info->flags; | ||
1185 | uint8_t vcr; | ||
1186 | int ret = 0; | ||
1187 | bool soc_reset; | ||
1188 | |||
1189 | /* Configure 'READ' sequence */ | ||
1190 | if (flags & FLASH_FLAG_32BIT_ADDR) | ||
1191 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, | ||
1192 | n25q_read4_configs); | ||
1193 | else | ||
1194 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, | ||
1195 | n25q_read3_configs); | ||
1196 | if (ret) { | ||
1197 | dev_err(fsm->dev, | ||
1198 | "failed to prepare READ sequence with flags [0x%08x]\n", | ||
1199 | flags); | ||
1200 | return ret; | ||
1201 | } | ||
1202 | |||
1203 | /* Configure 'WRITE' sequence (default configs) */ | ||
1204 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, | ||
1205 | default_write_configs); | ||
1206 | if (ret) { | ||
1207 | dev_err(fsm->dev, | ||
1208 | "preparing WRITE sequence using flags [0x%08x] failed\n", | ||
1209 | flags); | ||
1210 | return ret; | ||
1211 | } | ||
1212 | |||
1213 | /* * Configure 'ERASE_SECTOR' sequence */ | ||
1214 | stfsm_prepare_erasesec_seq(fsm, &stfsm_seq_erase_sector); | ||
1215 | |||
1216 | /* Configure 32-bit address support */ | ||
1217 | if (flags & FLASH_FLAG_32BIT_ADDR) { | ||
1218 | stfsm_n25q_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); | ||
1219 | |||
1220 | soc_reset = stfsm_can_handle_soc_reset(fsm); | ||
1221 | if (soc_reset || !fsm->booted_from_spi) { | ||
1222 | /* | ||
1223 | * If we can handle SoC resets, we enable 32-bit | ||
1224 | * address mode pervasively | ||
1225 | */ | ||
1226 | stfsm_enter_32bit_addr(fsm, 1); | ||
1227 | } else { | ||
1228 | /* | ||
1229 | * If not, enable/disable for WRITE and ERASE | ||
1230 | * operations (READ uses special commands) | ||
1231 | */ | ||
1232 | fsm->configuration = (CFG_WRITE_TOGGLE_32BIT_ADDR | | ||
1233 | CFG_ERASESEC_TOGGLE_32BIT_ADDR); | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | /* | ||
1238 | * Configure device to use 8 dummy cycles | ||
1239 | */ | ||
1240 | vcr = (N25Q_VCR_DUMMY_CYCLES(8) | N25Q_VCR_XIP_DISABLED | | ||
1241 | N25Q_VCR_WRAP_CONT); | ||
1242 | stfsm_wrvcr(fsm, vcr); | ||
1243 | |||
1244 | return 0; | ||
1245 | } | ||
1246 | |||
1247 | static void stfsm_s25fl_prepare_erasesec_seq_32(struct stfsm_seq *seq) | ||
1248 | { | ||
1249 | seq->seq_opc[1] = (SEQ_OPC_PADS_1 | | ||
1250 | SEQ_OPC_CYCLES(8) | | ||
1251 | SEQ_OPC_OPCODE(S25FL_CMD_SE4)); | ||
1252 | |||
1253 | seq->addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | | ||
1254 | ADR_CFG_PADS_1_ADD1 | | ||
1255 | ADR_CFG_CYCLES_ADD2(16) | | ||
1256 | ADR_CFG_PADS_1_ADD2 | | ||
1257 | ADR_CFG_CSDEASSERT_ADD2); | ||
1258 | } | ||
1259 | |||
1260 | static void stfsm_s25fl_read_dyb(struct stfsm *fsm, uint32_t offs, uint8_t *dby) | ||
1261 | { | ||
1262 | uint32_t tmp; | ||
1263 | struct stfsm_seq seq = { | ||
1264 | .data_size = TRANSFER_SIZE(4), | ||
1265 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
1266 | SEQ_OPC_CYCLES(8) | | ||
1267 | SEQ_OPC_OPCODE(S25FL_CMD_DYBRD)), | ||
1268 | .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | | ||
1269 | ADR_CFG_PADS_1_ADD1 | | ||
1270 | ADR_CFG_CYCLES_ADD2(16) | | ||
1271 | ADR_CFG_PADS_1_ADD2), | ||
1272 | .addr1 = (offs >> 16) & 0xffff, | ||
1273 | .addr2 = offs & 0xffff, | ||
1274 | .seq = { | ||
1275 | STFSM_INST_CMD1, | ||
1276 | STFSM_INST_ADD1, | ||
1277 | STFSM_INST_ADD2, | ||
1278 | STFSM_INST_DATA_READ, | ||
1279 | STFSM_INST_STOP, | ||
1280 | }, | ||
1281 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
1282 | SEQ_CFG_READNOTWRITE | | ||
1283 | SEQ_CFG_CSDEASSERT | | ||
1284 | SEQ_CFG_STARTSEQ), | ||
1285 | }; | ||
1286 | |||
1287 | stfsm_load_seq(fsm, &seq); | ||
1288 | |||
1289 | stfsm_read_fifo(fsm, &tmp, 4); | ||
1290 | |||
1291 | *dby = (uint8_t)(tmp >> 24); | ||
1292 | |||
1293 | stfsm_wait_seq(fsm); | ||
1294 | } | ||
1295 | |||
1296 | static void stfsm_s25fl_write_dyb(struct stfsm *fsm, uint32_t offs, uint8_t dby) | ||
1297 | { | ||
1298 | struct stfsm_seq seq = { | ||
1299 | .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
1300 | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | | ||
1301 | SEQ_OPC_CSDEASSERT), | ||
1302 | .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | ||
1303 | SEQ_OPC_OPCODE(S25FL_CMD_DYBWR)), | ||
1304 | .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | | ||
1305 | ADR_CFG_PADS_1_ADD1 | | ||
1306 | ADR_CFG_CYCLES_ADD2(16) | | ||
1307 | ADR_CFG_PADS_1_ADD2), | ||
1308 | .status = (uint32_t)dby | STA_PADS_1 | STA_CSDEASSERT, | ||
1309 | .addr1 = (offs >> 16) & 0xffff, | ||
1310 | .addr2 = offs & 0xffff, | ||
1311 | .seq = { | ||
1312 | STFSM_INST_CMD1, | ||
1313 | STFSM_INST_CMD2, | ||
1314 | STFSM_INST_ADD1, | ||
1315 | STFSM_INST_ADD2, | ||
1316 | STFSM_INST_STA_WR1, | ||
1317 | STFSM_INST_STOP, | ||
1318 | }, | ||
1319 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
1320 | SEQ_CFG_READNOTWRITE | | ||
1321 | SEQ_CFG_CSDEASSERT | | ||
1322 | SEQ_CFG_STARTSEQ), | ||
1323 | }; | ||
1324 | |||
1325 | stfsm_load_seq(fsm, &seq); | ||
1326 | stfsm_wait_seq(fsm); | ||
1327 | |||
1328 | stfsm_wait_busy(fsm); | ||
1329 | } | ||
1330 | |||
1331 | static int stfsm_s25fl_clear_status_reg(struct stfsm *fsm) | ||
1332 | { | ||
1333 | struct stfsm_seq seq = { | ||
1334 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
1335 | SEQ_OPC_CYCLES(8) | | ||
1336 | SEQ_OPC_OPCODE(S25FL_CMD_CLSR) | | ||
1337 | SEQ_OPC_CSDEASSERT), | ||
1338 | .seq_opc[1] = (SEQ_OPC_PADS_1 | | ||
1339 | SEQ_OPC_CYCLES(8) | | ||
1340 | SEQ_OPC_OPCODE(FLASH_CMD_WRDI) | | ||
1341 | SEQ_OPC_CSDEASSERT), | ||
1342 | .seq = { | ||
1343 | STFSM_INST_CMD1, | ||
1344 | STFSM_INST_CMD2, | ||
1345 | STFSM_INST_WAIT, | ||
1346 | STFSM_INST_STOP, | ||
1347 | }, | ||
1348 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
1349 | SEQ_CFG_ERASE | | ||
1350 | SEQ_CFG_READNOTWRITE | | ||
1351 | SEQ_CFG_CSDEASSERT | | ||
1352 | SEQ_CFG_STARTSEQ), | ||
1353 | }; | ||
1354 | |||
1355 | stfsm_load_seq(fsm, &seq); | ||
1356 | |||
1357 | stfsm_wait_seq(fsm); | ||
1358 | |||
1359 | return 0; | ||
1360 | } | ||
1361 | |||
1362 | static int stfsm_s25fl_config(struct stfsm *fsm) | ||
1363 | { | ||
1364 | struct flash_info *info = fsm->info; | ||
1365 | uint32_t flags = info->flags; | ||
1366 | uint32_t data_pads; | ||
1367 | uint32_t offs; | ||
1368 | uint16_t sta_wr; | ||
1369 | uint8_t sr1, cr1, dyb; | ||
1370 | int ret; | ||
1371 | |||
1372 | if (flags & FLASH_FLAG_32BIT_ADDR) { | ||
1373 | /* | ||
1374 | * Prepare Read/Write/Erase sequences according to S25FLxxx | ||
1375 | * 32-bit address command set | ||
1376 | */ | ||
1377 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, | ||
1378 | stfsm_s25fl_read4_configs); | ||
1379 | if (ret) | ||
1380 | return ret; | ||
1381 | |||
1382 | ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, | ||
1383 | stfsm_s25fl_write4_configs); | ||
1384 | if (ret) | ||
1385 | return ret; | ||
1386 | |||
1387 | stfsm_s25fl_prepare_erasesec_seq_32(&stfsm_seq_erase_sector); | ||
1388 | |||
1389 | } else { | ||
1390 | /* Use default configurations for 24-bit addressing */ | ||
1391 | ret = stfsm_prepare_rwe_seqs_default(fsm); | ||
1392 | if (ret) | ||
1393 | return ret; | ||
1394 | } | ||
1395 | |||
1396 | /* | ||
1397 | * For devices that support 'DYB' sector locking, check lock status and | ||
1398 | * unlock sectors if necessary (some variants power-on with sectors | ||
1399 | * locked by default) | ||
1400 | */ | ||
1401 | if (flags & FLASH_FLAG_DYB_LOCKING) { | ||
1402 | offs = 0; | ||
1403 | for (offs = 0; offs < info->sector_size * info->n_sectors;) { | ||
1404 | stfsm_s25fl_read_dyb(fsm, offs, &dyb); | ||
1405 | if (dyb == 0x00) | ||
1406 | stfsm_s25fl_write_dyb(fsm, offs, 0xff); | ||
1407 | |||
1408 | /* Handle bottom/top 4KiB parameter sectors */ | ||
1409 | if ((offs < info->sector_size * 2) || | ||
1410 | (offs >= (info->sector_size - info->n_sectors * 4))) | ||
1411 | offs += 0x1000; | ||
1412 | else | ||
1413 | offs += 0x10000; | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1417 | /* Check status of 'QE' bit */ | ||
1418 | data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; | ||
1419 | stfsm_read_status(fsm, FLASH_CMD_RDSR2, &cr1); | ||
1420 | if (data_pads == 4) { | ||
1421 | if (!(cr1 & STFSM_S25FL_CONFIG_QE)) { | ||
1422 | /* Set 'QE' */ | ||
1423 | cr1 |= STFSM_S25FL_CONFIG_QE; | ||
1424 | |||
1425 | stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1); | ||
1426 | sta_wr = ((uint16_t)cr1 << 8) | sr1; | ||
1427 | |||
1428 | stfsm_write_status(fsm, sta_wr, 2); | ||
1429 | |||
1430 | stfsm_wait_busy(fsm); | ||
1431 | } | ||
1432 | } else { | ||
1433 | if ((cr1 & STFSM_S25FL_CONFIG_QE)) { | ||
1434 | /* Clear 'QE' */ | ||
1435 | cr1 &= ~STFSM_S25FL_CONFIG_QE; | ||
1436 | |||
1437 | stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1); | ||
1438 | sta_wr = ((uint16_t)cr1 << 8) | sr1; | ||
1439 | |||
1440 | stfsm_write_status(fsm, sta_wr, 2); | ||
1441 | |||
1442 | stfsm_wait_busy(fsm); | ||
1443 | } | ||
1444 | |||
1445 | } | ||
1446 | |||
1447 | /* | ||
1448 | * S25FLxxx devices support Program and Error error flags. | ||
1449 | * Configure driver to check flags and clear if necessary. | ||
1450 | */ | ||
1451 | fsm->configuration |= CFG_S25FL_CHECK_ERROR_FLAGS; | ||
1452 | |||
1453 | return 0; | ||
1454 | } | ||
1455 | |||
1456 | static int stfsm_w25q_config(struct stfsm *fsm) | ||
1457 | { | ||
1458 | uint32_t data_pads; | ||
1459 | uint16_t sta_wr; | ||
1460 | uint8_t sta1, sta2; | ||
1461 | int ret; | ||
1462 | |||
1463 | ret = stfsm_prepare_rwe_seqs_default(fsm); | ||
1464 | if (ret) | ||
1465 | return ret; | ||
1466 | |||
1467 | /* If using QUAD mode, set QE STATUS bit */ | ||
1468 | data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; | ||
1469 | if (data_pads == 4) { | ||
1470 | stfsm_read_status(fsm, FLASH_CMD_RDSR, &sta1); | ||
1471 | stfsm_read_status(fsm, FLASH_CMD_RDSR2, &sta2); | ||
1472 | |||
1473 | sta_wr = ((uint16_t)sta2 << 8) | sta1; | ||
1474 | |||
1475 | sta_wr |= W25Q_STATUS_QE; | ||
1476 | |||
1477 | stfsm_write_status(fsm, sta_wr, 2); | ||
1478 | |||
1479 | stfsm_wait_busy(fsm); | ||
1480 | } | ||
1481 | |||
1482 | return 0; | ||
1483 | } | ||
1484 | |||
1485 | static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size, | ||
1486 | uint32_t offset) | ||
1487 | { | ||
1488 | struct stfsm_seq *seq = &fsm->stfsm_seq_read; | ||
1489 | uint32_t data_pads; | ||
1490 | uint32_t read_mask; | ||
1491 | uint32_t size_ub; | ||
1492 | uint32_t size_lb; | ||
1493 | uint32_t size_mop; | ||
1494 | uint32_t tmp[4]; | ||
1495 | uint32_t page_buf[FLASH_PAGESIZE_32]; | ||
1496 | uint8_t *p; | ||
1497 | |||
1498 | dev_dbg(fsm->dev, "reading %d bytes from 0x%08x\n", size, offset); | ||
1499 | |||
1500 | /* Enter 32-bit address mode, if required */ | ||
1501 | if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) | ||
1502 | stfsm_enter_32bit_addr(fsm, 1); | ||
1503 | |||
1504 | /* Must read in multiples of 32 cycles (or 32*pads/8 Bytes) */ | ||
1505 | data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; | ||
1506 | read_mask = (data_pads << 2) - 1; | ||
1507 | |||
1508 | /* Handle non-aligned buf */ | ||
1509 | p = ((uint32_t)buf & 0x3) ? (uint8_t *)page_buf : buf; | ||
1510 | |||
1511 | /* Handle non-aligned size */ | ||
1512 | size_ub = (size + read_mask) & ~read_mask; | ||
1513 | size_lb = size & ~read_mask; | ||
1514 | size_mop = size & read_mask; | ||
1515 | |||
1516 | seq->data_size = TRANSFER_SIZE(size_ub); | ||
1517 | seq->addr1 = (offset >> 16) & 0xffff; | ||
1518 | seq->addr2 = offset & 0xffff; | ||
1519 | |||
1520 | stfsm_load_seq(fsm, seq); | ||
1521 | |||
1522 | if (size_lb) | ||
1523 | stfsm_read_fifo(fsm, (uint32_t *)p, size_lb); | ||
1524 | |||
1525 | if (size_mop) { | ||
1526 | stfsm_read_fifo(fsm, tmp, read_mask + 1); | ||
1527 | memcpy(p + size_lb, &tmp, size_mop); | ||
1528 | } | ||
1529 | |||
1530 | /* Handle non-aligned buf */ | ||
1531 | if ((uint32_t)buf & 0x3) | ||
1532 | memcpy(buf, page_buf, size); | ||
1533 | |||
1534 | /* Wait for sequence to finish */ | ||
1535 | stfsm_wait_seq(fsm); | ||
1536 | |||
1537 | stfsm_clear_fifo(fsm); | ||
1538 | |||
1539 | /* Exit 32-bit address mode, if required */ | ||
1540 | if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) | ||
1541 | stfsm_enter_32bit_addr(fsm, 0); | ||
1542 | |||
1543 | return 0; | ||
1544 | } | ||
1545 | |||
1546 | static int stfsm_write(struct stfsm *fsm, const uint8_t *buf, | ||
1547 | uint32_t size, uint32_t offset) | ||
1548 | { | ||
1549 | struct stfsm_seq *seq = &fsm->stfsm_seq_write; | ||
1550 | uint32_t data_pads; | ||
1551 | uint32_t write_mask; | ||
1552 | uint32_t size_ub; | ||
1553 | uint32_t size_lb; | ||
1554 | uint32_t size_mop; | ||
1555 | uint32_t tmp[4]; | ||
1556 | uint32_t page_buf[FLASH_PAGESIZE_32]; | ||
1557 | uint8_t *t = (uint8_t *)&tmp; | ||
1558 | const uint8_t *p; | ||
1559 | int ret; | ||
1560 | int i; | ||
1561 | |||
1562 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); | ||
1563 | |||
1564 | /* Enter 32-bit address mode, if required */ | ||
1565 | if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) | ||
1566 | stfsm_enter_32bit_addr(fsm, 1); | ||
1567 | |||
1568 | /* Must write in multiples of 32 cycles (or 32*pads/8 bytes) */ | ||
1569 | data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; | ||
1570 | write_mask = (data_pads << 2) - 1; | ||
1571 | |||
1572 | /* Handle non-aligned buf */ | ||
1573 | if ((uint32_t)buf & 0x3) { | ||
1574 | memcpy(page_buf, buf, size); | ||
1575 | p = (uint8_t *)page_buf; | ||
1576 | } else { | ||
1577 | p = buf; | ||
1578 | } | ||
1579 | |||
1580 | /* Handle non-aligned size */ | ||
1581 | size_ub = (size + write_mask) & ~write_mask; | ||
1582 | size_lb = size & ~write_mask; | ||
1583 | size_mop = size & write_mask; | ||
1584 | |||
1585 | seq->data_size = TRANSFER_SIZE(size_ub); | ||
1586 | seq->addr1 = (offset >> 16) & 0xffff; | ||
1587 | seq->addr2 = offset & 0xffff; | ||
1588 | |||
1589 | /* Need to set FIFO to write mode, before writing data to FIFO (see | ||
1590 | * GNBvb79594) | ||
1591 | */ | ||
1592 | writel(0x00040000, fsm->base + SPI_FAST_SEQ_CFG); | ||
1593 | |||
1594 | /* | ||
1595 | * Before writing data to the FIFO, apply a small delay to allow a | ||
1596 | * potential change of FIFO direction to complete. | ||
1597 | */ | ||
1598 | if (fsm->fifo_dir_delay == 0) | ||
1599 | readl(fsm->base + SPI_FAST_SEQ_CFG); | ||
1600 | else | ||
1601 | udelay(fsm->fifo_dir_delay); | ||
1602 | |||
1603 | |||
1604 | /* Write data to FIFO, before starting sequence (see GNBvd79593) */ | ||
1605 | if (size_lb) { | ||
1606 | stfsm_write_fifo(fsm, (uint32_t *)p, size_lb); | ||
1607 | p += size_lb; | ||
1608 | } | ||
1609 | |||
1610 | /* Handle non-aligned size */ | ||
1611 | if (size_mop) { | ||
1612 | memset(t, 0xff, write_mask + 1); /* fill with 0xff's */ | ||
1613 | for (i = 0; i < size_mop; i++) | ||
1614 | t[i] = *p++; | ||
1615 | |||
1616 | stfsm_write_fifo(fsm, tmp, write_mask + 1); | ||
1617 | } | ||
1618 | |||
1619 | /* Start sequence */ | ||
1620 | stfsm_load_seq(fsm, seq); | ||
1621 | |||
1622 | /* Wait for sequence to finish */ | ||
1623 | stfsm_wait_seq(fsm); | ||
1624 | |||
1625 | /* Wait for completion */ | ||
1626 | ret = stfsm_wait_busy(fsm); | ||
1627 | if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) | ||
1628 | stfsm_s25fl_clear_status_reg(fsm); | ||
1629 | |||
1630 | /* Exit 32-bit address mode, if required */ | ||
1631 | if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) { | ||
1632 | stfsm_enter_32bit_addr(fsm, 0); | ||
1633 | if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY) | ||
1634 | udelay(1); | ||
1635 | } | ||
1636 | |||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * Read an address range from the flash chip. The address range | ||
1642 | * may be any size provided it is within the physical boundaries. | ||
1643 | */ | ||
1644 | static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
1645 | size_t *retlen, u_char *buf) | ||
1646 | { | ||
1647 | struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); | ||
1648 | uint32_t bytes; | ||
1649 | |||
1650 | dev_dbg(fsm->dev, "%s from 0x%08x, len %zd\n", | ||
1651 | __func__, (u32)from, len); | ||
1652 | |||
1653 | mutex_lock(&fsm->lock); | ||
1654 | |||
1655 | while (len > 0) { | ||
1656 | bytes = min_t(size_t, len, FLASH_PAGESIZE); | ||
1657 | |||
1658 | stfsm_read(fsm, buf, bytes, from); | ||
1659 | |||
1660 | buf += bytes; | ||
1661 | from += bytes; | ||
1662 | len -= bytes; | ||
1663 | |||
1664 | *retlen += bytes; | ||
1665 | } | ||
1666 | |||
1667 | mutex_unlock(&fsm->lock); | ||
1668 | |||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1672 | static int stfsm_erase_sector(struct stfsm *fsm, uint32_t offset) | ||
1673 | { | ||
1674 | struct stfsm_seq *seq = &stfsm_seq_erase_sector; | ||
1675 | int ret; | ||
1676 | |||
1677 | dev_dbg(fsm->dev, "erasing sector at 0x%08x\n", offset); | ||
1678 | |||
1679 | /* Enter 32-bit address mode, if required */ | ||
1680 | if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) | ||
1681 | stfsm_enter_32bit_addr(fsm, 1); | ||
1682 | |||
1683 | seq->addr1 = (offset >> 16) & 0xffff; | ||
1684 | seq->addr2 = offset & 0xffff; | ||
1685 | |||
1686 | stfsm_load_seq(fsm, seq); | ||
1687 | |||
1688 | stfsm_wait_seq(fsm); | ||
1689 | |||
1690 | /* Wait for completion */ | ||
1691 | ret = stfsm_wait_busy(fsm); | ||
1692 | if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) | ||
1693 | stfsm_s25fl_clear_status_reg(fsm); | ||
1694 | |||
1695 | /* Exit 32-bit address mode, if required */ | ||
1696 | if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) | ||
1697 | stfsm_enter_32bit_addr(fsm, 0); | ||
1698 | |||
1699 | return ret; | ||
1700 | } | ||
1701 | |||
1702 | static int stfsm_erase_chip(struct stfsm *fsm) | ||
1703 | { | ||
1704 | const struct stfsm_seq *seq = &stfsm_seq_erase_chip; | ||
1705 | |||
1706 | dev_dbg(fsm->dev, "erasing chip\n"); | ||
1707 | |||
1708 | stfsm_load_seq(fsm, seq); | ||
1709 | |||
1710 | stfsm_wait_seq(fsm); | ||
1711 | |||
1712 | return stfsm_wait_busy(fsm); | ||
1713 | } | ||
1714 | |||
1715 | /* | ||
1716 | * Write an address range to the flash chip. Data must be written in | ||
1717 | * FLASH_PAGESIZE chunks. The address range may be any size provided | ||
1718 | * it is within the physical boundaries. | ||
1719 | */ | ||
1720 | static int stfsm_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
1721 | size_t *retlen, const u_char *buf) | ||
1722 | { | ||
1723 | struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); | ||
1724 | |||
1725 | u32 page_offs; | ||
1726 | u32 bytes; | ||
1727 | uint8_t *b = (uint8_t *)buf; | ||
1728 | int ret = 0; | ||
1729 | |||
1730 | dev_dbg(fsm->dev, "%s to 0x%08x, len %zd\n", __func__, (u32)to, len); | ||
1731 | |||
1732 | /* Offset within page */ | ||
1733 | page_offs = to % FLASH_PAGESIZE; | ||
1734 | |||
1735 | mutex_lock(&fsm->lock); | ||
1736 | |||
1737 | while (len) { | ||
1738 | /* Write up to page boundary */ | ||
1739 | bytes = min(FLASH_PAGESIZE - page_offs, len); | ||
1740 | |||
1741 | ret = stfsm_write(fsm, b, bytes, to); | ||
1742 | if (ret) | ||
1743 | goto out1; | ||
1744 | |||
1745 | b += bytes; | ||
1746 | len -= bytes; | ||
1747 | to += bytes; | ||
1748 | |||
1749 | /* We are now page-aligned */ | ||
1750 | page_offs = 0; | ||
1751 | |||
1752 | *retlen += bytes; | ||
1753 | |||
1754 | } | ||
1755 | |||
1756 | out1: | ||
1757 | mutex_unlock(&fsm->lock); | ||
1758 | |||
1759 | return ret; | ||
1760 | } | ||
1761 | |||
1762 | /* | ||
1763 | * Erase an address range on the flash chip. The address range may extend | ||
1764 | * one or more erase sectors. Return an error is there is a problem erasing. | ||
1765 | */ | ||
1766 | static int stfsm_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
1767 | { | ||
1768 | struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); | ||
1769 | u32 addr, len; | ||
1770 | int ret; | ||
1771 | |||
1772 | dev_dbg(fsm->dev, "%s at 0x%llx, len %lld\n", __func__, | ||
1773 | (long long)instr->addr, (long long)instr->len); | ||
1774 | |||
1775 | addr = instr->addr; | ||
1776 | len = instr->len; | ||
1777 | |||
1778 | mutex_lock(&fsm->lock); | ||
1779 | |||
1780 | /* Whole-chip erase? */ | ||
1781 | if (len == mtd->size) { | ||
1782 | ret = stfsm_erase_chip(fsm); | ||
1783 | if (ret) | ||
1784 | goto out1; | ||
1785 | } else { | ||
1786 | while (len) { | ||
1787 | ret = stfsm_erase_sector(fsm, addr); | ||
1788 | if (ret) | ||
1789 | goto out1; | ||
1790 | |||
1791 | addr += mtd->erasesize; | ||
1792 | len -= mtd->erasesize; | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | mutex_unlock(&fsm->lock); | ||
1797 | |||
1798 | instr->state = MTD_ERASE_DONE; | ||
1799 | mtd_erase_callback(instr); | ||
1800 | |||
1801 | return 0; | ||
1802 | |||
1803 | out1: | ||
1804 | instr->state = MTD_ERASE_FAILED; | ||
1805 | mutex_unlock(&fsm->lock); | ||
1806 | |||
1807 | return ret; | ||
1808 | } | ||
1809 | |||
1810 | static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *jedec) | ||
1811 | { | ||
1812 | const struct stfsm_seq *seq = &stfsm_seq_read_jedec; | ||
1813 | uint32_t tmp[2]; | ||
1814 | |||
1815 | stfsm_load_seq(fsm, seq); | ||
1816 | |||
1817 | stfsm_read_fifo(fsm, tmp, 8); | ||
1818 | |||
1819 | memcpy(jedec, tmp, 5); | ||
1820 | |||
1821 | stfsm_wait_seq(fsm); | ||
1822 | } | ||
1823 | |||
1824 | static struct flash_info *stfsm_jedec_probe(struct stfsm *fsm) | ||
1825 | { | ||
1826 | struct flash_info *info; | ||
1827 | u16 ext_jedec; | ||
1828 | u32 jedec; | ||
1829 | u8 id[5]; | ||
1830 | |||
1831 | stfsm_read_jedec(fsm, id); | ||
1832 | |||
1833 | jedec = id[0] << 16 | id[1] << 8 | id[2]; | ||
1834 | /* | ||
1835 | * JEDEC also defines an optional "extended device information" | ||
1836 | * string for after vendor-specific data, after the three bytes | ||
1837 | * we use here. Supporting some chips might require using it. | ||
1838 | */ | ||
1839 | ext_jedec = id[3] << 8 | id[4]; | ||
1840 | |||
1841 | dev_dbg(fsm->dev, "JEDEC = 0x%08x [%02x %02x %02x %02x %02x]\n", | ||
1842 | jedec, id[0], id[1], id[2], id[3], id[4]); | ||
1843 | |||
1844 | for (info = flash_types; info->name; info++) { | ||
1845 | if (info->jedec_id == jedec) { | ||
1846 | if (info->ext_id && info->ext_id != ext_jedec) | ||
1847 | continue; | ||
1848 | return info; | ||
1849 | } | ||
1850 | } | ||
1851 | dev_err(fsm->dev, "Unrecognized JEDEC id %06x\n", jedec); | ||
1852 | |||
1853 | return NULL; | ||
1854 | } | ||
1855 | |||
1856 | static int stfsm_set_mode(struct stfsm *fsm, uint32_t mode) | ||
1857 | { | ||
1858 | int ret, timeout = 10; | ||
1859 | |||
1860 | /* Wait for controller to accept mode change */ | ||
1861 | while (--timeout) { | ||
1862 | ret = readl(fsm->base + SPI_STA_MODE_CHANGE); | ||
1863 | if (ret & 0x1) | ||
1864 | break; | ||
1865 | udelay(1); | ||
1866 | } | ||
1867 | |||
1868 | if (!timeout) | ||
1869 | return -EBUSY; | ||
1870 | |||
1871 | writel(mode, fsm->base + SPI_MODESELECT); | ||
1872 | |||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | static void stfsm_set_freq(struct stfsm *fsm, uint32_t spi_freq) | ||
1877 | { | ||
1878 | uint32_t emi_freq; | ||
1879 | uint32_t clk_div; | ||
1880 | |||
1881 | /* TODO: Make this dynamic */ | ||
1882 | emi_freq = STFSM_DEFAULT_EMI_FREQ; | ||
1883 | |||
1884 | /* | ||
1885 | * Calculate clk_div - values between 2 and 128 | ||
1886 | * Multiple of 2, rounded up | ||
1887 | */ | ||
1888 | clk_div = 2 * DIV_ROUND_UP(emi_freq, 2 * spi_freq); | ||
1889 | if (clk_div < 2) | ||
1890 | clk_div = 2; | ||
1891 | else if (clk_div > 128) | ||
1892 | clk_div = 128; | ||
1893 | |||
1894 | /* | ||
1895 | * Determine a suitable delay for the IP to complete a change of | ||
1896 | * direction of the FIFO. The required delay is related to the clock | ||
1897 | * divider used. The following heuristics are based on empirical tests, | ||
1898 | * using a 100MHz EMI clock. | ||
1899 | */ | ||
1900 | if (clk_div <= 4) | ||
1901 | fsm->fifo_dir_delay = 0; | ||
1902 | else if (clk_div <= 10) | ||
1903 | fsm->fifo_dir_delay = 1; | ||
1904 | else | ||
1905 | fsm->fifo_dir_delay = DIV_ROUND_UP(clk_div, 10); | ||
1906 | |||
1907 | dev_dbg(fsm->dev, "emi_clk = %uHZ, spi_freq = %uHZ, clk_div = %u\n", | ||
1908 | emi_freq, spi_freq, clk_div); | ||
1909 | |||
1910 | writel(clk_div, fsm->base + SPI_CLOCKDIV); | ||
1911 | } | ||
1912 | |||
1913 | static int stfsm_init(struct stfsm *fsm) | ||
1914 | { | ||
1915 | int ret; | ||
1916 | |||
1917 | /* Perform a soft reset of the FSM controller */ | ||
1918 | writel(SEQ_CFG_SWRESET, fsm->base + SPI_FAST_SEQ_CFG); | ||
1919 | udelay(1); | ||
1920 | writel(0, fsm->base + SPI_FAST_SEQ_CFG); | ||
1921 | |||
1922 | /* Set clock to 'safe' frequency initially */ | ||
1923 | stfsm_set_freq(fsm, STFSM_FLASH_SAFE_FREQ); | ||
1924 | |||
1925 | /* Switch to FSM */ | ||
1926 | ret = stfsm_set_mode(fsm, SPI_MODESELECT_FSM); | ||
1927 | if (ret) | ||
1928 | return ret; | ||
1929 | |||
1930 | /* Set timing parameters */ | ||
1931 | writel(SPI_CFG_DEVICE_ST | | ||
1932 | SPI_CFG_DEFAULT_MIN_CS_HIGH | | ||
1933 | SPI_CFG_DEFAULT_CS_SETUPHOLD | | ||
1934 | SPI_CFG_DEFAULT_DATA_HOLD, | ||
1935 | fsm->base + SPI_CONFIGDATA); | ||
1936 | writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG); | ||
1937 | |||
1938 | /* Clear FIFO, just in case */ | ||
1939 | stfsm_clear_fifo(fsm); | ||
1940 | |||
1941 | return 0; | ||
1942 | } | ||
1943 | |||
1944 | static void stfsm_fetch_platform_configs(struct platform_device *pdev) | ||
1945 | { | ||
1946 | struct stfsm *fsm = platform_get_drvdata(pdev); | ||
1947 | struct device_node *np = pdev->dev.of_node; | ||
1948 | struct regmap *regmap; | ||
1949 | uint32_t boot_device_reg; | ||
1950 | uint32_t boot_device_spi; | ||
1951 | uint32_t boot_device; /* Value we read from *boot_device_reg */ | ||
1952 | int ret; | ||
1953 | |||
1954 | /* Booting from SPI NOR Flash is the default */ | ||
1955 | fsm->booted_from_spi = true; | ||
1956 | |||
1957 | regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
1958 | if (IS_ERR(regmap)) | ||
1959 | goto boot_device_fail; | ||
1960 | |||
1961 | fsm->reset_signal = of_property_read_bool(np, "st,reset-signal"); | ||
1962 | |||
1963 | fsm->reset_por = of_property_read_bool(np, "st,reset-por"); | ||
1964 | |||
1965 | /* Where in the syscon the boot device information lives */ | ||
1966 | ret = of_property_read_u32(np, "st,boot-device-reg", &boot_device_reg); | ||
1967 | if (ret) | ||
1968 | goto boot_device_fail; | ||
1969 | |||
1970 | /* Boot device value when booted from SPI NOR */ | ||
1971 | ret = of_property_read_u32(np, "st,boot-device-spi", &boot_device_spi); | ||
1972 | if (ret) | ||
1973 | goto boot_device_fail; | ||
1974 | |||
1975 | ret = regmap_read(regmap, boot_device_reg, &boot_device); | ||
1976 | if (ret) | ||
1977 | goto boot_device_fail; | ||
1978 | |||
1979 | if (boot_device != boot_device_spi) | ||
1980 | fsm->booted_from_spi = false; | ||
1981 | |||
1982 | return; | ||
1983 | |||
1984 | boot_device_fail: | ||
1985 | dev_warn(&pdev->dev, | ||
1986 | "failed to fetch boot device, assuming boot from SPI\n"); | ||
1987 | } | ||
1988 | |||
1989 | static int stfsm_probe(struct platform_device *pdev) | ||
1990 | { | ||
1991 | struct device_node *np = pdev->dev.of_node; | ||
1992 | struct mtd_part_parser_data ppdata; | ||
1993 | struct flash_info *info; | ||
1994 | struct resource *res; | ||
1995 | struct stfsm *fsm; | ||
1996 | int ret; | ||
1997 | |||
1998 | if (!np) { | ||
1999 | dev_err(&pdev->dev, "No DT found\n"); | ||
2000 | return -EINVAL; | ||
2001 | } | ||
2002 | ppdata.of_node = np; | ||
2003 | |||
2004 | fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL); | ||
2005 | if (!fsm) | ||
2006 | return -ENOMEM; | ||
2007 | |||
2008 | fsm->dev = &pdev->dev; | ||
2009 | |||
2010 | platform_set_drvdata(pdev, fsm); | ||
2011 | |||
2012 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2013 | if (!res) { | ||
2014 | dev_err(&pdev->dev, "Resource not found\n"); | ||
2015 | return -ENODEV; | ||
2016 | } | ||
2017 | |||
2018 | fsm->base = devm_ioremap_resource(&pdev->dev, res); | ||
2019 | if (IS_ERR(fsm->base)) { | ||
2020 | dev_err(&pdev->dev, | ||
2021 | "Failed to reserve memory region %pR\n", res); | ||
2022 | return PTR_ERR(fsm->base); | ||
2023 | } | ||
2024 | |||
2025 | mutex_init(&fsm->lock); | ||
2026 | |||
2027 | ret = stfsm_init(fsm); | ||
2028 | if (ret) { | ||
2029 | dev_err(&pdev->dev, "Failed to initialise FSM Controller\n"); | ||
2030 | return ret; | ||
2031 | } | ||
2032 | |||
2033 | stfsm_fetch_platform_configs(pdev); | ||
2034 | |||
2035 | /* Detect SPI FLASH device */ | ||
2036 | info = stfsm_jedec_probe(fsm); | ||
2037 | if (!info) | ||
2038 | return -ENODEV; | ||
2039 | fsm->info = info; | ||
2040 | |||
2041 | /* Use device size to determine address width */ | ||
2042 | if (info->sector_size * info->n_sectors > 0x1000000) | ||
2043 | info->flags |= FLASH_FLAG_32BIT_ADDR; | ||
2044 | |||
2045 | /* | ||
2046 | * Configure READ/WRITE/ERASE sequences according to platform and | ||
2047 | * device flags. | ||
2048 | */ | ||
2049 | if (info->config) { | ||
2050 | ret = info->config(fsm); | ||
2051 | if (ret) | ||
2052 | return ret; | ||
2053 | } else { | ||
2054 | ret = stfsm_prepare_rwe_seqs_default(fsm); | ||
2055 | if (ret) | ||
2056 | return ret; | ||
2057 | } | ||
2058 | |||
2059 | fsm->mtd.name = info->name; | ||
2060 | fsm->mtd.dev.parent = &pdev->dev; | ||
2061 | fsm->mtd.type = MTD_NORFLASH; | ||
2062 | fsm->mtd.writesize = 4; | ||
2063 | fsm->mtd.writebufsize = fsm->mtd.writesize; | ||
2064 | fsm->mtd.flags = MTD_CAP_NORFLASH; | ||
2065 | fsm->mtd.size = info->sector_size * info->n_sectors; | ||
2066 | fsm->mtd.erasesize = info->sector_size; | ||
2067 | |||
2068 | fsm->mtd._read = stfsm_mtd_read; | ||
2069 | fsm->mtd._write = stfsm_mtd_write; | ||
2070 | fsm->mtd._erase = stfsm_mtd_erase; | ||
2071 | |||
2072 | dev_info(&pdev->dev, | ||
2073 | "Found serial flash device: %s\n" | ||
2074 | " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", | ||
2075 | info->name, | ||
2076 | (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), | ||
2077 | fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); | ||
2078 | |||
2079 | return mtd_device_parse_register(&fsm->mtd, NULL, &ppdata, NULL, 0); | ||
2080 | } | ||
2081 | |||
2082 | static int stfsm_remove(struct platform_device *pdev) | ||
2083 | { | ||
2084 | struct stfsm *fsm = platform_get_drvdata(pdev); | ||
2085 | |||
2086 | return mtd_device_unregister(&fsm->mtd); | ||
2087 | } | ||
2088 | |||
2089 | static struct of_device_id stfsm_match[] = { | ||
2090 | { .compatible = "st,spi-fsm", }, | ||
2091 | {}, | ||
2092 | }; | ||
2093 | MODULE_DEVICE_TABLE(of, stfsm_match); | ||
2094 | |||
2095 | static struct platform_driver stfsm_driver = { | ||
2096 | .probe = stfsm_probe, | ||
2097 | .remove = stfsm_remove, | ||
2098 | .driver = { | ||
2099 | .name = "st-spi-fsm", | ||
2100 | .owner = THIS_MODULE, | ||
2101 | .of_match_table = stfsm_match, | ||
2102 | }, | ||
2103 | }; | ||
2104 | module_platform_driver(stfsm_driver); | ||
2105 | |||
2106 | MODULE_AUTHOR("Angus Clark <angus.clark@st.com>"); | ||
2107 | MODULE_DESCRIPTION("ST SPI FSM driver"); | ||
2108 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 4adc0374fb6b..487e64f411a5 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/init.h> | ||
34 | #include <linux/mtd/mtd.h> | 33 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/nftl.h> | 34 | #include <linux/mtd/nftl.h> |
36 | #include <linux/mtd/inftl.h> | 35 | #include <linux/mtd/inftl.h> |
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index d38b6460d505..018c75faadb3 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c | |||
@@ -55,10 +55,8 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) | |||
55 | int i, j; | 55 | int i, j; |
56 | 56 | ||
57 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); | 57 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); |
58 | if (!mtd) { | 58 | if (!mtd) |
59 | printk(KERN_ERR "Failed to allocate memory for MTD device\n"); | ||
60 | return NULL; | 59 | return NULL; |
61 | } | ||
62 | mtd->priv = map; | 60 | mtd->priv = map; |
63 | mtd->type = MTD_NORFLASH; | 61 | mtd->type = MTD_NORFLASH; |
64 | 62 | ||
diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c index 45abed67f1ef..69f2112340b1 100644 --- a/drivers/mtd/lpddr/qinfo_probe.c +++ b/drivers/mtd/lpddr/qinfo_probe.c | |||
@@ -135,11 +135,8 @@ static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr) | |||
135 | { | 135 | { |
136 | 136 | ||
137 | lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL); | 137 | lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL); |
138 | if (!lpddr->qinfo) { | 138 | if (!lpddr->qinfo) |
139 | printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n", | ||
140 | map->name); | ||
141 | return 0; | 139 | return 0; |
142 | } | ||
143 | 140 | ||
144 | /* Get the ManuID */ | 141 | /* Get the ManuID */ |
145 | lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID)); | 142 | lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID)); |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 310dc7c93425..fce23fe043f7 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -66,11 +66,11 @@ config MTD_PHYSMAP_BANKWIDTH | |||
66 | used internally by the CFI drivers. | 66 | used internally by the CFI drivers. |
67 | 67 | ||
68 | config MTD_PHYSMAP_OF | 68 | config MTD_PHYSMAP_OF |
69 | tristate "Flash device in physical memory map based on OF description" | 69 | tristate "Memory device in physical memory map based on OF description" |
70 | depends on OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM) | 70 | depends on OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_RAM) |
71 | help | 71 | help |
72 | This provides a 'mapping' driver which allows the NOR Flash and | 72 | This provides a 'mapping' driver which allows the NOR Flash, ROM |
73 | ROM driver code to communicate with chips which are mapped | 73 | and RAM driver code to communicate with chips which are mapped |
74 | physically into the CPU's memory. The mapping description here is | 74 | physically into the CPU's memory. The mapping description here is |
75 | taken from OF device tree. | 75 | taken from OF device tree. |
76 | 76 | ||
@@ -124,7 +124,7 @@ config MTD_NETSC520 | |||
124 | 124 | ||
125 | config MTD_TS5500 | 125 | config MTD_TS5500 |
126 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" | 126 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" |
127 | depends on X86 | 127 | depends on TS5500 || COMPILE_TEST |
128 | select MTD_JEDECPROBE | 128 | select MTD_JEDECPROBE |
129 | select MTD_CFI_AMDSTD | 129 | select MTD_CFI_AMDSTD |
130 | help | 130 | help |
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 5434d8ded015..6ea51e549045 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * Licensed under the GPL-2 or later. | 14 | * Licensed under the GPL-2 or later. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index 1adba86474a5..a4c477b9fdd6 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/io.h> | 17 | #include <linux/io.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index 46d195fca942..5ab71f0e1bcd 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/init.h> | ||
35 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
36 | #include <linux/mtd/map.h> | 35 | #include <linux/mtd/map.h> |
37 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index d6b2451eab1d..6a589f1e2880 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/string.h> | 20 | #include <linux/string.h> |
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index 93c507a6f862..7aa682cd4d7e 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
18 | #include <linux/mtd/map.h> | 17 | #include <linux/mtd/map.h> |
19 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index 98bb5d5375d7..cadfbe051873 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * kind, whether express or implied. | 10 | * kind, whether express or implied. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 36da518915b5..eb0242e0b2d9 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
19 | 18 | ||
20 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index d11109762ac5..217c25d7381b 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/init.h> | ||
19 | #include <linux/device.h> | 18 | #include <linux/device.h> |
20 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
21 | #include <linux/mtd/map.h> | 20 | #include <linux/mtd/map.h> |
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 10196f5a897d..d597e89f2692 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
29 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
@@ -138,7 +137,6 @@ static int platram_probe(struct platform_device *pdev) | |||
138 | 137 | ||
139 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 138 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
140 | if (info == NULL) { | 139 | if (info == NULL) { |
141 | dev_err(&pdev->dev, "no memory for flash info\n"); | ||
142 | err = -ENOMEM; | 140 | err = -ENOMEM; |
143 | goto exit_error; | 141 | goto exit_error; |
144 | } | 142 | } |
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 9aad854fe912..cb4d92eea9fe 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
18 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/map.h> | 18 | #include <linux/mtd/map.h> |
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c index 93525121d69d..146b6047ed2b 100644 --- a/drivers/mtd/maps/rbtx4939-flash.c +++ b/drivers/mtd/maps/rbtx4939-flash.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/device.h> | 17 | #include <linux/device.h> |
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 3051c4c36240..b7a22a612a46 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/types.h> | 48 | #include <linux/types.h> |
49 | #include <linux/kernel.h> | 49 | #include <linux/kernel.h> |
50 | #include <linux/init.h> | ||
51 | #include <asm/io.h> | 50 | #include <asm/io.h> |
52 | #include <linux/mtd/mtd.h> | 51 | #include <linux/mtd/mtd.h> |
53 | #include <linux/mtd/map.h> | 52 | #include <linux/mtd/map.h> |
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 39cc4181f025..b6f1aac3510c 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
16 | #include <linux/of.h> | 15 | #include <linux/of.h> |
17 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 5073cbc796d8..0b2ccb68c0d0 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/blkpg.h> | 30 | #include <linux/blkpg.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/hdreg.h> | 32 | #include <linux/hdreg.h> |
33 | #include <linux/init.h> | ||
34 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
35 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
36 | 35 | ||
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 2147e733533b..7d4e7b9da3a1 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -324,6 +324,15 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c | |||
324 | default: | 324 | default: |
325 | ret = mtd_write(mtd, *ppos, len, &retlen, kbuf); | 325 | ret = mtd_write(mtd, *ppos, len, &retlen, kbuf); |
326 | } | 326 | } |
327 | |||
328 | /* | ||
329 | * Return -ENOSPC only if no data could be written at all. | ||
330 | * Otherwise just return the number of bytes that actually | ||
331 | * have been written. | ||
332 | */ | ||
333 | if ((ret == -ENOSPC) && (total_retlen)) | ||
334 | break; | ||
335 | |||
327 | if (!ret) { | 336 | if (!ret) { |
328 | *ppos += retlen; | 337 | *ppos += retlen; |
329 | total_retlen += retlen; | 338 | total_retlen += retlen; |
@@ -889,25 +898,26 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) | |||
889 | case OTPGETREGIONINFO: | 898 | case OTPGETREGIONINFO: |
890 | { | 899 | { |
891 | struct otp_info *buf = kmalloc(4096, GFP_KERNEL); | 900 | struct otp_info *buf = kmalloc(4096, GFP_KERNEL); |
901 | size_t retlen; | ||
892 | if (!buf) | 902 | if (!buf) |
893 | return -ENOMEM; | 903 | return -ENOMEM; |
894 | switch (mfi->mode) { | 904 | switch (mfi->mode) { |
895 | case MTD_FILE_MODE_OTP_FACTORY: | 905 | case MTD_FILE_MODE_OTP_FACTORY: |
896 | ret = mtd_get_fact_prot_info(mtd, buf, 4096); | 906 | ret = mtd_get_fact_prot_info(mtd, 4096, &retlen, buf); |
897 | break; | 907 | break; |
898 | case MTD_FILE_MODE_OTP_USER: | 908 | case MTD_FILE_MODE_OTP_USER: |
899 | ret = mtd_get_user_prot_info(mtd, buf, 4096); | 909 | ret = mtd_get_user_prot_info(mtd, 4096, &retlen, buf); |
900 | break; | 910 | break; |
901 | default: | 911 | default: |
902 | ret = -EINVAL; | 912 | ret = -EINVAL; |
903 | break; | 913 | break; |
904 | } | 914 | } |
905 | if (ret >= 0) { | 915 | if (!ret) { |
906 | if (cmd == OTPGETREGIONCOUNT) { | 916 | if (cmd == OTPGETREGIONCOUNT) { |
907 | int nbr = ret / sizeof(struct otp_info); | 917 | int nbr = retlen / sizeof(struct otp_info); |
908 | ret = copy_to_user(argp, &nbr, sizeof(int)); | 918 | ret = copy_to_user(argp, &nbr, sizeof(int)); |
909 | } else | 919 | } else |
910 | ret = copy_to_user(argp, buf, ret); | 920 | ret = copy_to_user(argp, buf, retlen); |
911 | if (ret) | 921 | if (ret) |
912 | ret = -EFAULT; | 922 | ret = -EFAULT; |
913 | } | 923 | } |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 34c0b16aed5c..d201feeb3ca6 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -883,14 +883,14 @@ EXPORT_SYMBOL_GPL(mtd_read_oob); | |||
883 | * devices. The user data is one time programmable but the factory data is read | 883 | * devices. The user data is one time programmable but the factory data is read |
884 | * only. | 884 | * only. |
885 | */ | 885 | */ |
886 | int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | 886 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
887 | size_t len) | 887 | struct otp_info *buf) |
888 | { | 888 | { |
889 | if (!mtd->_get_fact_prot_info) | 889 | if (!mtd->_get_fact_prot_info) |
890 | return -EOPNOTSUPP; | 890 | return -EOPNOTSUPP; |
891 | if (!len) | 891 | if (!len) |
892 | return 0; | 892 | return 0; |
893 | return mtd->_get_fact_prot_info(mtd, buf, len); | 893 | return mtd->_get_fact_prot_info(mtd, len, retlen, buf); |
894 | } | 894 | } |
895 | EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info); | 895 | EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info); |
896 | 896 | ||
@@ -906,14 +906,14 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | |||
906 | } | 906 | } |
907 | EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg); | 907 | EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg); |
908 | 908 | ||
909 | int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, | 909 | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
910 | size_t len) | 910 | struct otp_info *buf) |
911 | { | 911 | { |
912 | if (!mtd->_get_user_prot_info) | 912 | if (!mtd->_get_user_prot_info) |
913 | return -EOPNOTSUPP; | 913 | return -EOPNOTSUPP; |
914 | if (!len) | 914 | if (!len) |
915 | return 0; | 915 | return 0; |
916 | return mtd->_get_user_prot_info(mtd, buf, len); | 916 | return mtd->_get_user_prot_info(mtd, len, retlen, buf); |
917 | } | 917 | } |
918 | EXPORT_SYMBOL_GPL(mtd_get_user_prot_info); | 918 | EXPORT_SYMBOL_GPL(mtd_get_user_prot_info); |
919 | 919 | ||
@@ -932,12 +932,22 @@ EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg); | |||
932 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | 932 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, |
933 | size_t *retlen, u_char *buf) | 933 | size_t *retlen, u_char *buf) |
934 | { | 934 | { |
935 | int ret; | ||
936 | |||
935 | *retlen = 0; | 937 | *retlen = 0; |
936 | if (!mtd->_write_user_prot_reg) | 938 | if (!mtd->_write_user_prot_reg) |
937 | return -EOPNOTSUPP; | 939 | return -EOPNOTSUPP; |
938 | if (!len) | 940 | if (!len) |
939 | return 0; | 941 | return 0; |
940 | return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); | 942 | ret = mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); |
943 | if (ret) | ||
944 | return ret; | ||
945 | |||
946 | /* | ||
947 | * If no data could be written at all, we are out of memory and | ||
948 | * must return -ENOSPC. | ||
949 | */ | ||
950 | return (*retlen) ? 0 : -ENOSPC; | ||
941 | } | 951 | } |
942 | EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg); | 952 | EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg); |
943 | 953 | ||
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 3c7d6d7623c1..1ca9aec141ff 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -150,11 +150,12 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, | |||
150 | retlen, buf); | 150 | retlen, buf); |
151 | } | 151 | } |
152 | 152 | ||
153 | static int part_get_user_prot_info(struct mtd_info *mtd, | 153 | static int part_get_user_prot_info(struct mtd_info *mtd, size_t len, |
154 | struct otp_info *buf, size_t len) | 154 | size_t *retlen, struct otp_info *buf) |
155 | { | 155 | { |
156 | struct mtd_part *part = PART(mtd); | 156 | struct mtd_part *part = PART(mtd); |
157 | return part->master->_get_user_prot_info(part->master, buf, len); | 157 | return part->master->_get_user_prot_info(part->master, len, retlen, |
158 | buf); | ||
158 | } | 159 | } |
159 | 160 | ||
160 | static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | 161 | static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, |
@@ -165,11 +166,12 @@ static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | |||
165 | retlen, buf); | 166 | retlen, buf); |
166 | } | 167 | } |
167 | 168 | ||
168 | static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | 169 | static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len, |
169 | size_t len) | 170 | size_t *retlen, struct otp_info *buf) |
170 | { | 171 | { |
171 | struct mtd_part *part = PART(mtd); | 172 | struct mtd_part *part = PART(mtd); |
172 | return part->master->_get_fact_prot_info(part->master, buf, len); | 173 | return part->master->_get_fact_prot_info(part->master, len, retlen, |
174 | buf); | ||
173 | } | 175 | } |
174 | 176 | ||
175 | static int part_write(struct mtd_info *mtd, loff_t to, size_t len, | 177 | static int part_write(struct mtd_info *mtd, loff_t to, size_t len, |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index a4bee41ad5cb..f1cf503517fd 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -460,6 +460,8 @@ config MTD_NAND_MXC | |||
460 | config MTD_NAND_SH_FLCTL | 460 | config MTD_NAND_SH_FLCTL |
461 | tristate "Support for NAND on Renesas SuperH FLCTL" | 461 | tristate "Support for NAND on Renesas SuperH FLCTL" |
462 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | 462 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST |
463 | depends on HAS_IOMEM | ||
464 | depends on HAS_DMA | ||
463 | help | 465 | help |
464 | Several Renesas SuperH CPU has FLCTL. This option enables support | 466 | Several Renesas SuperH CPU has FLCTL. This option enables support |
465 | for NAND Flash using FLCTL. | 467 | for NAND Flash using FLCTL. |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 8611eb4b45fc..4936e9e0002f 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -17,7 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | 20 | #include <linux/module.h> |
22 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
23 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index c36e9b84487c..4ce181a35bcd 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -430,7 +430,7 @@ err_dma: | |||
430 | dma_unmap_single(dma_dev->dev, phys_addr, len, dir); | 430 | dma_unmap_single(dma_dev->dev, phys_addr, len, dir); |
431 | err_buf: | 431 | err_buf: |
432 | if (err != 0) | 432 | if (err != 0) |
433 | dev_warn(host->dev, "Fall back to CPU I/O\n"); | 433 | dev_dbg(host->dev, "Fall back to CPU I/O\n"); |
434 | return err; | 434 | return err; |
435 | } | 435 | } |
436 | 436 | ||
@@ -1220,6 +1220,7 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1220 | goto err; | 1220 | goto err; |
1221 | } | 1221 | } |
1222 | 1222 | ||
1223 | nand_chip->options |= NAND_NO_SUBPAGE_WRITE; | ||
1223 | nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; | 1224 | nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; |
1224 | nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; | 1225 | nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; |
1225 | 1226 | ||
@@ -1659,8 +1660,8 @@ static void nfc_select_chip(struct mtd_info *mtd, int chip) | |||
1659 | nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE); | 1660 | nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE); |
1660 | } | 1661 | } |
1661 | 1662 | ||
1662 | static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr, | 1663 | static int nfc_make_addr(struct mtd_info *mtd, int command, int column, |
1663 | unsigned int *addr1234, unsigned int *cycle0) | 1664 | int page_addr, unsigned int *addr1234, unsigned int *cycle0) |
1664 | { | 1665 | { |
1665 | struct nand_chip *chip = mtd->priv; | 1666 | struct nand_chip *chip = mtd->priv; |
1666 | 1667 | ||
@@ -1674,7 +1675,8 @@ static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr, | |||
1674 | *addr1234 = 0; | 1675 | *addr1234 = 0; |
1675 | 1676 | ||
1676 | if (column != -1) { | 1677 | if (column != -1) { |
1677 | if (chip->options & NAND_BUSWIDTH_16) | 1678 | if (chip->options & NAND_BUSWIDTH_16 && |
1679 | !nand_opcode_8bits(command)) | ||
1678 | column >>= 1; | 1680 | column >>= 1; |
1679 | addr_bytes[acycle++] = column & 0xff; | 1681 | addr_bytes[acycle++] = column & 0xff; |
1680 | if (mtd->writesize > 512) | 1682 | if (mtd->writesize > 512) |
@@ -1787,8 +1789,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, | |||
1787 | } | 1789 | } |
1788 | 1790 | ||
1789 | if (do_addr) | 1791 | if (do_addr) |
1790 | acycle = nfc_make_addr(mtd, column, page_addr, &addr1234, | 1792 | acycle = nfc_make_addr(mtd, command, column, page_addr, |
1791 | &cycle0); | 1793 | &addr1234, &cycle0); |
1792 | 1794 | ||
1793 | nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; | 1795 | nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; |
1794 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); | 1796 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 2880d888cfc5..bc5c518828d2 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/gpio.h> | 13 | #include <linux/gpio.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
17 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
@@ -308,7 +307,8 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i | |||
308 | /* Serially input address */ | 307 | /* Serially input address */ |
309 | if (column != -1) { | 308 | if (column != -1) { |
310 | /* Adjust columns for 16 bit buswidth */ | 309 | /* Adjust columns for 16 bit buswidth */ |
311 | if (this->options & NAND_BUSWIDTH_16) | 310 | if (this->options & NAND_BUSWIDTH_16 && |
311 | !nand_opcode_8bits(command)) | ||
312 | column >>= 1; | 312 | column >>= 1; |
313 | ctx->write_byte(mtd, column); | 313 | ctx->write_byte(mtd, column); |
314 | } | 314 | } |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 94f55dbde995..b7a24946ca26 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -37,7 +37,6 @@ | |||
37 | 37 | ||
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/types.h> | 39 | #include <linux/types.h> |
40 | #include <linux/init.h> | ||
41 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
42 | #include <linux/string.h> | 41 | #include <linux/string.h> |
43 | #include <linux/ioport.h> | 42 | #include <linux/ioport.h> |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index f2f64addb5e8..4e66726da9aa 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
627 | struct cafe_priv *cafe; | 627 | struct cafe_priv *cafe; |
628 | uint32_t ctrl; | 628 | uint32_t ctrl; |
629 | int err = 0; | 629 | int err = 0; |
630 | int old_dma; | ||
631 | struct nand_buffers *nbuf; | ||
630 | 632 | ||
631 | /* Very old versions shared the same PCI ident for all three | 633 | /* Very old versions shared the same PCI ident for all three |
632 | functions on the chip. Verify the class too... */ | 634 | functions on the chip. Verify the class too... */ |
@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
655 | err = -ENOMEM; | 657 | err = -ENOMEM; |
656 | goto out_free_mtd; | 658 | goto out_free_mtd; |
657 | } | 659 | } |
658 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers), | ||
659 | &cafe->dmaaddr, GFP_KERNEL); | ||
660 | if (!cafe->dmabuf) { | ||
661 | err = -ENOMEM; | ||
662 | goto out_ior; | ||
663 | } | ||
664 | cafe->nand.buffers = (void *)cafe->dmabuf + 2112; | ||
665 | 660 | ||
666 | cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); | 661 | cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); |
667 | if (!cafe->rs) { | 662 | if (!cafe->rs) { |
@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
721 | "CAFE NAND", mtd); | 716 | "CAFE NAND", mtd); |
722 | if (err) { | 717 | if (err) { |
723 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); | 718 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); |
724 | goto out_free_dma; | 719 | goto out_ior; |
725 | } | 720 | } |
726 | 721 | ||
727 | /* Disable master reset, enable NAND clock */ | 722 | /* Disable master reset, enable NAND clock */ |
@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
735 | cafe_writel(cafe, 0x7006, GLOBAL_CTRL); | 730 | cafe_writel(cafe, 0x7006, GLOBAL_CTRL); |
736 | cafe_writel(cafe, 0x700a, GLOBAL_CTRL); | 731 | cafe_writel(cafe, 0x700a, GLOBAL_CTRL); |
737 | 732 | ||
733 | /* Enable NAND IRQ in global IRQ mask register */ | ||
734 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); | ||
735 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | ||
736 | cafe_readl(cafe, GLOBAL_CTRL), | ||
737 | cafe_readl(cafe, GLOBAL_IRQ_MASK)); | ||
738 | |||
739 | /* Do not use the DMA for the nand_scan_ident() */ | ||
740 | old_dma = usedma; | ||
741 | usedma = 0; | ||
742 | |||
743 | /* Scan to find existence of the device */ | ||
744 | if (nand_scan_ident(mtd, 2, NULL)) { | ||
745 | err = -ENXIO; | ||
746 | goto out_irq; | ||
747 | } | ||
748 | |||
749 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, | ||
750 | 2112 + sizeof(struct nand_buffers) + | ||
751 | mtd->writesize + mtd->oobsize, | ||
752 | &cafe->dmaaddr, GFP_KERNEL); | ||
753 | if (!cafe->dmabuf) { | ||
754 | err = -ENOMEM; | ||
755 | goto out_irq; | ||
756 | } | ||
757 | cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112; | ||
758 | |||
738 | /* Set up DMA address */ | 759 | /* Set up DMA address */ |
739 | cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); | 760 | cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); |
740 | if (sizeof(cafe->dmaaddr) > 4) | 761 | if (sizeof(cafe->dmaaddr) > 4) |
@@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
746 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", | 767 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", |
747 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); | 768 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); |
748 | 769 | ||
749 | /* Enable NAND IRQ in global IRQ mask register */ | 770 | /* this driver does not need the @ecccalc and @ecccode */ |
750 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); | 771 | nbuf->ecccalc = NULL; |
751 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | 772 | nbuf->ecccode = NULL; |
752 | cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); | 773 | nbuf->databuf = (uint8_t *)(nbuf + 1); |
753 | 774 | ||
754 | /* Scan to find existence of the device */ | 775 | /* Restore the DMA flag */ |
755 | if (nand_scan_ident(mtd, 2, NULL)) { | 776 | usedma = old_dma; |
756 | err = -ENXIO; | ||
757 | goto out_irq; | ||
758 | } | ||
759 | 777 | ||
760 | cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ | 778 | cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ |
761 | if (mtd->writesize == 2048) | 779 | if (mtd->writesize == 2048) |
@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
773 | } else { | 791 | } else { |
774 | printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", | 792 | printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", |
775 | mtd->writesize); | 793 | mtd->writesize); |
776 | goto out_irq; | 794 | goto out_free_dma; |
777 | } | 795 | } |
778 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 796 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
779 | cafe->nand.ecc.size = mtd->writesize; | 797 | cafe->nand.ecc.size = mtd->writesize; |
@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
790 | 808 | ||
791 | err = nand_scan_tail(mtd); | 809 | err = nand_scan_tail(mtd); |
792 | if (err) | 810 | if (err) |
793 | goto out_irq; | 811 | goto out_free_dma; |
794 | 812 | ||
795 | pci_set_drvdata(pdev, mtd); | 813 | pci_set_drvdata(pdev, mtd); |
796 | 814 | ||
@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
799 | 817 | ||
800 | goto out; | 818 | goto out; |
801 | 819 | ||
820 | out_free_dma: | ||
821 | dma_free_coherent(&cafe->pdev->dev, | ||
822 | 2112 + sizeof(struct nand_buffers) + | ||
823 | mtd->writesize + mtd->oobsize, | ||
824 | cafe->dmabuf, cafe->dmaaddr); | ||
802 | out_irq: | 825 | out_irq: |
803 | /* Disable NAND IRQ in global IRQ mask register */ | 826 | /* Disable NAND IRQ in global IRQ mask register */ |
804 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); | 827 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); |
805 | free_irq(pdev->irq, mtd); | 828 | free_irq(pdev->irq, mtd); |
806 | out_free_dma: | ||
807 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | ||
808 | out_ior: | 829 | out_ior: |
809 | pci_iounmap(pdev, cafe->mmio); | 830 | pci_iounmap(pdev, cafe->mmio); |
810 | out_free_mtd: | 831 | out_free_mtd: |
@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev) | |||
824 | nand_release(mtd); | 845 | nand_release(mtd); |
825 | free_rs(cafe->rs); | 846 | free_rs(cafe->rs); |
826 | pci_iounmap(pdev, cafe->mmio); | 847 | pci_iounmap(pdev, cafe->mmio); |
827 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | 848 | dma_free_coherent(&cafe->pdev->dev, |
849 | 2112 + sizeof(struct nand_buffers) + | ||
850 | mtd->writesize + mtd->oobsize, | ||
851 | cafe->dmabuf, cafe->dmaaddr); | ||
828 | kfree(mtd); | 852 | kfree(mtd); |
829 | } | 853 | } |
830 | 854 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8eb6a36f125a..4615d79fc93f 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -24,7 +24,6 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
30 | #include <linux/err.h> | 29 | #include <linux/err.h> |
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index babb02c4b220..35cb17f57800 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c | |||
@@ -30,24 +30,6 @@ struct denali_dt { | |||
30 | struct clk *clk; | 30 | struct clk *clk; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static void __iomem *request_and_map(struct device *dev, | ||
34 | const struct resource *res) | ||
35 | { | ||
36 | void __iomem *ptr; | ||
37 | |||
38 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | ||
39 | "denali-dt")) { | ||
40 | dev_err(dev, "unable to request %s\n", res->name); | ||
41 | return NULL; | ||
42 | } | ||
43 | |||
44 | ptr = devm_ioremap_nocache(dev, res->start, resource_size(res)); | ||
45 | if (!ptr) | ||
46 | dev_err(dev, "ioremap_nocache of %s failed!", res->name); | ||
47 | |||
48 | return ptr; | ||
49 | } | ||
50 | |||
51 | static const struct of_device_id denali_nand_dt_ids[] = { | 33 | static const struct of_device_id denali_nand_dt_ids[] = { |
52 | { .compatible = "denali,denali-nand-dt" }, | 34 | { .compatible = "denali,denali-nand-dt" }, |
53 | { /* sentinel */ } | 35 | { /* sentinel */ } |
@@ -78,13 +60,6 @@ static int denali_dt_probe(struct platform_device *ofdev) | |||
78 | return -ENOMEM; | 60 | return -ENOMEM; |
79 | denali = &dt->denali; | 61 | denali = &dt->denali; |
80 | 62 | ||
81 | denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); | ||
82 | nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); | ||
83 | if (!denali_reg || !nand_data) { | ||
84 | dev_err(&ofdev->dev, "resources not completely defined\n"); | ||
85 | return -EINVAL; | ||
86 | } | ||
87 | |||
88 | denali->platform = DT; | 63 | denali->platform = DT; |
89 | denali->dev = &ofdev->dev; | 64 | denali->dev = &ofdev->dev; |
90 | denali->irq = platform_get_irq(ofdev, 0); | 65 | denali->irq = platform_get_irq(ofdev, 0); |
@@ -93,13 +68,15 @@ static int denali_dt_probe(struct platform_device *ofdev) | |||
93 | return denali->irq; | 68 | return denali->irq; |
94 | } | 69 | } |
95 | 70 | ||
96 | denali->flash_reg = request_and_map(&ofdev->dev, denali_reg); | 71 | denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); |
97 | if (!denali->flash_reg) | 72 | denali->flash_reg = devm_ioremap_resource(&ofdev->dev, denali_reg); |
98 | return -ENOMEM; | 73 | if (IS_ERR(denali->flash_reg)) |
74 | return PTR_ERR(denali->flash_reg); | ||
99 | 75 | ||
100 | denali->flash_mem = request_and_map(&ofdev->dev, nand_data); | 76 | nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); |
101 | if (!denali->flash_mem) | 77 | denali->flash_mem = devm_ioremap_resource(&ofdev->dev, nand_data); |
102 | return -ENOMEM; | 78 | if (IS_ERR(denali->flash_mem)) |
79 | return PTR_ERR(denali->flash_mem); | ||
103 | 80 | ||
104 | if (!of_property_read_u32(ofdev->dev.of_node, | 81 | if (!of_property_read_u32(ofdev->dev.of_node, |
105 | "dma-mask", (u32 *)&denali_dma_mask)) { | 82 | "dma-mask", (u32 *)&denali_dma_mask)) { |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fec31d71b84e..f68a7bccecdc 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -698,7 +698,8 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu | |||
698 | /* Serially input address */ | 698 | /* Serially input address */ |
699 | if (column != -1) { | 699 | if (column != -1) { |
700 | /* Adjust columns for 16 bit buswidth */ | 700 | /* Adjust columns for 16 bit buswidth */ |
701 | if (this->options & NAND_BUSWIDTH_16) | 701 | if (this->options & NAND_BUSWIDTH_16 && |
702 | !nand_opcode_8bits(command)) | ||
702 | column >>= 1; | 703 | column >>= 1; |
703 | WriteDOC(column, docptr, Mplus_FlashAddress); | 704 | WriteDOC(column, docptr, Mplus_FlashAddress); |
704 | } | 705 | } |
@@ -1438,7 +1439,7 @@ static int __init doc_probe(unsigned long physadr) | |||
1438 | int reg, len, numchips; | 1439 | int reg, len, numchips; |
1439 | int ret = 0; | 1440 | int ret = 0; |
1440 | 1441 | ||
1441 | if (!request_mem_region(physadr, DOC_IOREMAP_LEN, NULL)) | 1442 | if (!request_mem_region(physadr, DOC_IOREMAP_LEN, "DiskOnChip")) |
1442 | return -EBUSY; | 1443 | return -EBUSY; |
1443 | virtadr = ioremap(physadr, DOC_IOREMAP_LEN); | 1444 | virtadr = ioremap(physadr, DOC_IOREMAP_LEN); |
1444 | if (!virtadr) { | 1445 | if (!virtadr) { |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index bcf60800c3ce..ec549cd9849f 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/init.h> | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
29 | #include <linux/string.h> | 28 | #include <linux/string.h> |
30 | #include <linux/ioport.h> | 29 | #include <linux/ioport.h> |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 50d9161c4faf..cb45d2f8e208 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/init.h> | ||
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 8e6148aa4539..117ce333fdd4 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
@@ -18,7 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
24 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index ca6369fe91ff..bb77f750e75a 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
28 | #include <linux/of_mtd.h> | 28 | #include <linux/of_mtd.h> |
29 | #include "gpmi-nand.h" | 29 | #include "gpmi-nand.h" |
30 | #include "bch-regs.h" | ||
30 | 31 | ||
31 | /* Resource names for the GPMI NAND driver. */ | 32 | /* Resource names for the GPMI NAND driver. */ |
32 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" | 33 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" |
@@ -985,7 +986,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
985 | int ret; | 986 | int ret; |
986 | 987 | ||
987 | dev_dbg(this->dev, "page number is : %d\n", page); | 988 | dev_dbg(this->dev, "page number is : %d\n", page); |
988 | ret = read_page_prepare(this, buf, mtd->writesize, | 989 | ret = read_page_prepare(this, buf, nfc_geo->payload_size, |
989 | this->payload_virt, this->payload_phys, | 990 | this->payload_virt, this->payload_phys, |
990 | nfc_geo->payload_size, | 991 | nfc_geo->payload_size, |
991 | &payload_virt, &payload_phys); | 992 | &payload_virt, &payload_phys); |
@@ -999,7 +1000,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
999 | 1000 | ||
1000 | /* go! */ | 1001 | /* go! */ |
1001 | ret = gpmi_read_page(this, payload_phys, auxiliary_phys); | 1002 | ret = gpmi_read_page(this, payload_phys, auxiliary_phys); |
1002 | read_page_end(this, buf, mtd->writesize, | 1003 | read_page_end(this, buf, nfc_geo->payload_size, |
1003 | this->payload_virt, this->payload_phys, | 1004 | this->payload_virt, this->payload_phys, |
1004 | nfc_geo->payload_size, | 1005 | nfc_geo->payload_size, |
1005 | payload_virt, payload_phys); | 1006 | payload_virt, payload_phys); |
@@ -1041,7 +1042,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1041 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; | 1042 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; |
1042 | } | 1043 | } |
1043 | 1044 | ||
1044 | read_page_swap_end(this, buf, mtd->writesize, | 1045 | read_page_swap_end(this, buf, nfc_geo->payload_size, |
1045 | this->payload_virt, this->payload_phys, | 1046 | this->payload_virt, this->payload_phys, |
1046 | nfc_geo->payload_size, | 1047 | nfc_geo->payload_size, |
1047 | payload_virt, payload_phys); | 1048 | payload_virt, payload_phys); |
@@ -1049,6 +1050,90 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1049 | return max_bitflips; | 1050 | return max_bitflips; |
1050 | } | 1051 | } |
1051 | 1052 | ||
1053 | /* Fake a virtual small page for the subpage read */ | ||
1054 | static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||
1055 | uint32_t offs, uint32_t len, uint8_t *buf, int page) | ||
1056 | { | ||
1057 | struct gpmi_nand_data *this = chip->priv; | ||
1058 | void __iomem *bch_regs = this->resources.bch_regs; | ||
1059 | struct bch_geometry old_geo = this->bch_geometry; | ||
1060 | struct bch_geometry *geo = &this->bch_geometry; | ||
1061 | int size = chip->ecc.size; /* ECC chunk size */ | ||
1062 | int meta, n, page_size; | ||
1063 | u32 r1_old, r2_old, r1_new, r2_new; | ||
1064 | unsigned int max_bitflips; | ||
1065 | int first, last, marker_pos; | ||
1066 | int ecc_parity_size; | ||
1067 | int col = 0; | ||
1068 | |||
1069 | /* The size of ECC parity */ | ||
1070 | ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; | ||
1071 | |||
1072 | /* Align it with the chunk size */ | ||
1073 | first = offs / size; | ||
1074 | last = (offs + len - 1) / size; | ||
1075 | |||
1076 | /* | ||
1077 | * Find the chunk which contains the Block Marker. If this chunk is | ||
1078 | * in the range of [first, last], we have to read out the whole page. | ||
1079 | * Why? since we had swapped the data at the position of Block Marker | ||
1080 | * to the metadata which is bound with the chunk 0. | ||
1081 | */ | ||
1082 | marker_pos = geo->block_mark_byte_offset / size; | ||
1083 | if (last >= marker_pos && first <= marker_pos) { | ||
1084 | dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n", | ||
1085 | page, first, last, marker_pos); | ||
1086 | return gpmi_ecc_read_page(mtd, chip, buf, 0, page); | ||
1087 | } | ||
1088 | |||
1089 | meta = geo->metadata_size; | ||
1090 | if (first) { | ||
1091 | col = meta + (size + ecc_parity_size) * first; | ||
1092 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1); | ||
1093 | |||
1094 | meta = 0; | ||
1095 | buf = buf + first * size; | ||
1096 | } | ||
1097 | |||
1098 | /* Save the old environment */ | ||
1099 | r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0); | ||
1100 | r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1); | ||
1101 | |||
1102 | /* change the BCH registers and bch_geometry{} */ | ||
1103 | n = last - first + 1; | ||
1104 | page_size = meta + (size + ecc_parity_size) * n; | ||
1105 | |||
1106 | r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS | | ||
1107 | BM_BCH_FLASH0LAYOUT0_META_SIZE); | ||
1108 | r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1) | ||
1109 | | BF_BCH_FLASH0LAYOUT0_META_SIZE(meta); | ||
1110 | writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0); | ||
1111 | |||
1112 | r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE; | ||
1113 | r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size); | ||
1114 | writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1); | ||
1115 | |||
1116 | geo->ecc_chunk_count = n; | ||
1117 | geo->payload_size = n * size; | ||
1118 | geo->page_size = page_size; | ||
1119 | geo->auxiliary_status_offset = ALIGN(meta, 4); | ||
1120 | |||
1121 | dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n", | ||
1122 | page, offs, len, col, first, n, page_size); | ||
1123 | |||
1124 | /* Read the subpage now */ | ||
1125 | this->swap_block_mark = false; | ||
1126 | max_bitflips = gpmi_ecc_read_page(mtd, chip, buf, 0, page); | ||
1127 | |||
1128 | /* Restore */ | ||
1129 | writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); | ||
1130 | writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); | ||
1131 | this->bch_geometry = old_geo; | ||
1132 | this->swap_block_mark = true; | ||
1133 | |||
1134 | return max_bitflips; | ||
1135 | } | ||
1136 | |||
1052 | static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1137 | static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1053 | const uint8_t *buf, int oob_required) | 1138 | const uint8_t *buf, int oob_required) |
1054 | { | 1139 | { |
@@ -1566,6 +1651,17 @@ static int gpmi_init_last(struct gpmi_nand_data *this) | |||
1566 | ecc->layout = &gpmi_hw_ecclayout; | 1651 | ecc->layout = &gpmi_hw_ecclayout; |
1567 | 1652 | ||
1568 | /* | 1653 | /* |
1654 | * We only enable the subpage read when: | ||
1655 | * (1) the chip is imx6, and | ||
1656 | * (2) the size of the ECC parity is byte aligned. | ||
1657 | */ | ||
1658 | if (GPMI_IS_MX6Q(this) && | ||
1659 | ((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) { | ||
1660 | ecc->read_subpage = gpmi_ecc_read_subpage; | ||
1661 | chip->options |= NAND_SUBPAGE_READ; | ||
1662 | } | ||
1663 | |||
1664 | /* | ||
1569 | * Can we enable the extra features? such as EDO or Sync mode. | 1665 | * Can we enable the extra features? such as EDO or Sync mode. |
1570 | * | 1666 | * |
1571 | * We do not check the return value now. That's means if we fail in | 1667 | * We do not check the return value now. That's means if we fail in |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 31ee7cfbc12b..e78841a2dcc3 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/init.h> | ||
34 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
35 | #include <linux/io.h> | 34 | #include <linux/io.h> |
36 | #include <linux/mtd/mtd.h> | 35 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index e9a4835c4dd9..dba262bf766f 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -1501,6 +1501,8 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
1501 | init_completion(&host->op_completion); | 1501 | init_completion(&host->op_completion); |
1502 | 1502 | ||
1503 | host->irq = platform_get_irq(pdev, 0); | 1503 | host->irq = platform_get_irq(pdev, 0); |
1504 | if (host->irq < 0) | ||
1505 | return host->irq; | ||
1504 | 1506 | ||
1505 | /* | 1507 | /* |
1506 | * Use host->devtype_data->irq_control() here instead of irq_control() | 1508 | * Use host->devtype_data->irq_control() here instead of irq_control() |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 9715a7ba164a..9d01c4df838c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -589,7 +589,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
589 | /* Serially input address */ | 589 | /* Serially input address */ |
590 | if (column != -1) { | 590 | if (column != -1) { |
591 | /* Adjust columns for 16 bit buswidth */ | 591 | /* Adjust columns for 16 bit buswidth */ |
592 | if (chip->options & NAND_BUSWIDTH_16) | 592 | if (chip->options & NAND_BUSWIDTH_16 && |
593 | !nand_opcode_8bits(command)) | ||
593 | column >>= 1; | 594 | column >>= 1; |
594 | chip->cmd_ctrl(mtd, column, ctrl); | 595 | chip->cmd_ctrl(mtd, column, ctrl); |
595 | ctrl &= ~NAND_CTRL_CHANGE; | 596 | ctrl &= ~NAND_CTRL_CHANGE; |
@@ -680,7 +681,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
680 | /* Serially input address */ | 681 | /* Serially input address */ |
681 | if (column != -1) { | 682 | if (column != -1) { |
682 | /* Adjust columns for 16 bit buswidth */ | 683 | /* Adjust columns for 16 bit buswidth */ |
683 | if (chip->options & NAND_BUSWIDTH_16) | 684 | if (chip->options & NAND_BUSWIDTH_16 && |
685 | !nand_opcode_8bits(command)) | ||
684 | column >>= 1; | 686 | column >>= 1; |
685 | chip->cmd_ctrl(mtd, column, ctrl); | 687 | chip->cmd_ctrl(mtd, column, ctrl); |
686 | ctrl &= ~NAND_CTRL_CHANGE; | 688 | ctrl &= ~NAND_CTRL_CHANGE; |
@@ -1160,9 +1162,11 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1160 | * @data_offs: offset of requested data within the page | 1162 | * @data_offs: offset of requested data within the page |
1161 | * @readlen: data length | 1163 | * @readlen: data length |
1162 | * @bufpoi: buffer to store read data | 1164 | * @bufpoi: buffer to store read data |
1165 | * @page: page number to read | ||
1163 | */ | 1166 | */ |
1164 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | 1167 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
1165 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 1168 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, |
1169 | int page) | ||
1166 | { | 1170 | { |
1167 | int start_step, end_step, num_steps; | 1171 | int start_step, end_step, num_steps; |
1168 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1172 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
@@ -1170,13 +1174,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1170 | int data_col_addr, i, gaps = 0; | 1174 | int data_col_addr, i, gaps = 0; |
1171 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1175 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1172 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1176 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1173 | int index = 0; | 1177 | int index; |
1174 | unsigned int max_bitflips = 0; | 1178 | unsigned int max_bitflips = 0; |
1175 | 1179 | ||
1176 | /* Column address within the page aligned to ECC size (256bytes) */ | 1180 | /* Column address within the page aligned to ECC size (256bytes) */ |
1177 | start_step = data_offs / chip->ecc.size; | 1181 | start_step = data_offs / chip->ecc.size; |
1178 | end_step = (data_offs + readlen - 1) / chip->ecc.size; | 1182 | end_step = (data_offs + readlen - 1) / chip->ecc.size; |
1179 | num_steps = end_step - start_step + 1; | 1183 | num_steps = end_step - start_step + 1; |
1184 | index = start_step * chip->ecc.bytes; | ||
1180 | 1185 | ||
1181 | /* Data size aligned to ECC ecc.size */ | 1186 | /* Data size aligned to ECC ecc.size */ |
1182 | datafrag_len = num_steps * chip->ecc.size; | 1187 | datafrag_len = num_steps * chip->ecc.size; |
@@ -1213,8 +1218,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1213 | * Send the command to read the particular ECC bytes take care | 1218 | * Send the command to read the particular ECC bytes take care |
1214 | * about buswidth alignment in read_buf. | 1219 | * about buswidth alignment in read_buf. |
1215 | */ | 1220 | */ |
1216 | index = start_step * chip->ecc.bytes; | ||
1217 | |||
1218 | aligned_pos = eccpos[index] & ~(busw - 1); | 1221 | aligned_pos = eccpos[index] & ~(busw - 1); |
1219 | aligned_len = eccfrag_len; | 1222 | aligned_len = eccfrag_len; |
1220 | if (eccpos[index] & (busw - 1)) | 1223 | if (eccpos[index] & (busw - 1)) |
@@ -1538,7 +1541,8 @@ read_retry: | |||
1538 | else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && | 1541 | else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && |
1539 | !oob) | 1542 | !oob) |
1540 | ret = chip->ecc.read_subpage(mtd, chip, | 1543 | ret = chip->ecc.read_subpage(mtd, chip, |
1541 | col, bytes, bufpoi); | 1544 | col, bytes, bufpoi, |
1545 | page); | ||
1542 | else | 1546 | else |
1543 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1547 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1544 | oob_required, page); | 1548 | oob_required, page); |
@@ -2000,7 +2004,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, | |||
2000 | oob += chip->ecc.prepad; | 2004 | oob += chip->ecc.prepad; |
2001 | } | 2005 | } |
2002 | 2006 | ||
2003 | chip->read_buf(mtd, oob, eccbytes); | 2007 | chip->write_buf(mtd, oob, eccbytes); |
2004 | oob += eccbytes; | 2008 | oob += eccbytes; |
2005 | 2009 | ||
2006 | if (chip->ecc.postpad) { | 2010 | if (chip->ecc.postpad) { |
@@ -3063,7 +3067,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
3063 | int *busw) | 3067 | int *busw) |
3064 | { | 3068 | { |
3065 | struct nand_onfi_params *p = &chip->onfi_params; | 3069 | struct nand_onfi_params *p = &chip->onfi_params; |
3066 | int i; | 3070 | int i, j; |
3067 | int val; | 3071 | int val; |
3068 | 3072 | ||
3069 | /* Try ONFI for unknown chip or LP */ | 3073 | /* Try ONFI for unknown chip or LP */ |
@@ -3072,18 +3076,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
3072 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | 3076 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') |
3073 | return 0; | 3077 | return 0; |
3074 | 3078 | ||
3075 | /* | ||
3076 | * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not | ||
3077 | * with NAND_BUSWIDTH_16 | ||
3078 | */ | ||
3079 | if (chip->options & NAND_BUSWIDTH_16) { | ||
3080 | pr_err("ONFI cannot be probed in 16-bit mode; aborting\n"); | ||
3081 | return 0; | ||
3082 | } | ||
3083 | |||
3084 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | 3079 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); |
3085 | for (i = 0; i < 3; i++) { | 3080 | for (i = 0; i < 3; i++) { |
3086 | chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); | 3081 | for (j = 0; j < sizeof(*p); j++) |
3082 | ((uint8_t *)p)[j] = chip->read_byte(mtd); | ||
3087 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == | 3083 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == |
3088 | le16_to_cpu(p->crc)) { | 3084 | le16_to_cpu(p->crc)) { |
3089 | break; | 3085 | break; |
@@ -3169,6 +3165,87 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
3169 | } | 3165 | } |
3170 | 3166 | ||
3171 | /* | 3167 | /* |
3168 | * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. | ||
3169 | */ | ||
3170 | static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, | ||
3171 | int *busw) | ||
3172 | { | ||
3173 | struct nand_jedec_params *p = &chip->jedec_params; | ||
3174 | struct jedec_ecc_info *ecc; | ||
3175 | int val; | ||
3176 | int i, j; | ||
3177 | |||
3178 | /* Try JEDEC for unknown chip or LP */ | ||
3179 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1); | ||
3180 | if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' || | ||
3181 | chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' || | ||
3182 | chip->read_byte(mtd) != 'C') | ||
3183 | return 0; | ||
3184 | |||
3185 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1); | ||
3186 | for (i = 0; i < 3; i++) { | ||
3187 | for (j = 0; j < sizeof(*p); j++) | ||
3188 | ((uint8_t *)p)[j] = chip->read_byte(mtd); | ||
3189 | |||
3190 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == | ||
3191 | le16_to_cpu(p->crc)) | ||
3192 | break; | ||
3193 | } | ||
3194 | |||
3195 | if (i == 3) { | ||
3196 | pr_err("Could not find valid JEDEC parameter page; aborting\n"); | ||
3197 | return 0; | ||
3198 | } | ||
3199 | |||
3200 | /* Check version */ | ||
3201 | val = le16_to_cpu(p->revision); | ||
3202 | if (val & (1 << 2)) | ||
3203 | chip->jedec_version = 10; | ||
3204 | else if (val & (1 << 1)) | ||
3205 | chip->jedec_version = 1; /* vendor specific version */ | ||
3206 | |||
3207 | if (!chip->jedec_version) { | ||
3208 | pr_info("unsupported JEDEC version: %d\n", val); | ||
3209 | return 0; | ||
3210 | } | ||
3211 | |||
3212 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | ||
3213 | sanitize_string(p->model, sizeof(p->model)); | ||
3214 | if (!mtd->name) | ||
3215 | mtd->name = p->model; | ||
3216 | |||
3217 | mtd->writesize = le32_to_cpu(p->byte_per_page); | ||
3218 | |||
3219 | /* Please reference to the comment for nand_flash_detect_onfi. */ | ||
3220 | mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); | ||
3221 | mtd->erasesize *= mtd->writesize; | ||
3222 | |||
3223 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | ||
3224 | |||
3225 | /* Please reference to the comment for nand_flash_detect_onfi. */ | ||
3226 | chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); | ||
3227 | chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; | ||
3228 | chip->bits_per_cell = p->bits_per_cell; | ||
3229 | |||
3230 | if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS) | ||
3231 | *busw = NAND_BUSWIDTH_16; | ||
3232 | else | ||
3233 | *busw = 0; | ||
3234 | |||
3235 | /* ECC info */ | ||
3236 | ecc = &p->ecc_info[0]; | ||
3237 | |||
3238 | if (ecc->codeword_size >= 9) { | ||
3239 | chip->ecc_strength_ds = ecc->ecc_bits; | ||
3240 | chip->ecc_step_ds = 1 << ecc->codeword_size; | ||
3241 | } else { | ||
3242 | pr_warn("Invalid codeword size\n"); | ||
3243 | } | ||
3244 | |||
3245 | return 1; | ||
3246 | } | ||
3247 | |||
3248 | /* | ||
3172 | * nand_id_has_period - Check if an ID string has a given wraparound period | 3249 | * nand_id_has_period - Check if an ID string has a given wraparound period |
3173 | * @id_data: the ID string | 3250 | * @id_data: the ID string |
3174 | * @arrlen: the length of the @id_data array | 3251 | * @arrlen: the length of the @id_data array |
@@ -3474,10 +3551,10 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, | |||
3474 | */ | 3551 | */ |
3475 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 3552 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, |
3476 | struct nand_chip *chip, | 3553 | struct nand_chip *chip, |
3477 | int busw, | ||
3478 | int *maf_id, int *dev_id, | 3554 | int *maf_id, int *dev_id, |
3479 | struct nand_flash_dev *type) | 3555 | struct nand_flash_dev *type) |
3480 | { | 3556 | { |
3557 | int busw; | ||
3481 | int i, maf_idx; | 3558 | int i, maf_idx; |
3482 | u8 id_data[8]; | 3559 | u8 id_data[8]; |
3483 | 3560 | ||
@@ -3533,6 +3610,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3533 | /* Check is chip is ONFI compliant */ | 3610 | /* Check is chip is ONFI compliant */ |
3534 | if (nand_flash_detect_onfi(mtd, chip, &busw)) | 3611 | if (nand_flash_detect_onfi(mtd, chip, &busw)) |
3535 | goto ident_done; | 3612 | goto ident_done; |
3613 | |||
3614 | /* Check if the chip is JEDEC compliant */ | ||
3615 | if (nand_flash_detect_jedec(mtd, chip, &busw)) | ||
3616 | goto ident_done; | ||
3536 | } | 3617 | } |
3537 | 3618 | ||
3538 | if (!type->name) | 3619 | if (!type->name) |
@@ -3612,8 +3693,17 @@ ident_done: | |||
3612 | 3693 | ||
3613 | pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", | 3694 | pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", |
3614 | *maf_id, *dev_id); | 3695 | *maf_id, *dev_id); |
3615 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | 3696 | |
3616 | chip->onfi_version ? chip->onfi_params.model : type->name); | 3697 | if (chip->onfi_version) |
3698 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||
3699 | chip->onfi_params.model); | ||
3700 | else if (chip->jedec_version) | ||
3701 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||
3702 | chip->jedec_params.model); | ||
3703 | else | ||
3704 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||
3705 | type->name); | ||
3706 | |||
3617 | pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", | 3707 | pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", |
3618 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | 3708 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", |
3619 | mtd->writesize, mtd->oobsize); | 3709 | mtd->writesize, mtd->oobsize); |
@@ -3634,18 +3724,16 @@ ident_done: | |||
3634 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, | 3724 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, |
3635 | struct nand_flash_dev *table) | 3725 | struct nand_flash_dev *table) |
3636 | { | 3726 | { |
3637 | int i, busw, nand_maf_id, nand_dev_id; | 3727 | int i, nand_maf_id, nand_dev_id; |
3638 | struct nand_chip *chip = mtd->priv; | 3728 | struct nand_chip *chip = mtd->priv; |
3639 | struct nand_flash_dev *type; | 3729 | struct nand_flash_dev *type; |
3640 | 3730 | ||
3641 | /* Get buswidth to select the correct functions */ | ||
3642 | busw = chip->options & NAND_BUSWIDTH_16; | ||
3643 | /* Set the default functions */ | 3731 | /* Set the default functions */ |
3644 | nand_set_defaults(chip, busw); | 3732 | nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); |
3645 | 3733 | ||
3646 | /* Read the flash type */ | 3734 | /* Read the flash type */ |
3647 | type = nand_get_flash_type(mtd, chip, busw, | 3735 | type = nand_get_flash_type(mtd, chip, &nand_maf_id, |
3648 | &nand_maf_id, &nand_dev_id, table); | 3736 | &nand_dev_id, table); |
3649 | 3737 | ||
3650 | if (IS_ERR(type)) { | 3738 | if (IS_ERR(type)) { |
3651 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 3739 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) |
@@ -3696,15 +3784,26 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3696 | int i; | 3784 | int i; |
3697 | struct nand_chip *chip = mtd->priv; | 3785 | struct nand_chip *chip = mtd->priv; |
3698 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 3786 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
3787 | struct nand_buffers *nbuf; | ||
3699 | 3788 | ||
3700 | /* New bad blocks should be marked in OOB, flash-based BBT, or both */ | 3789 | /* New bad blocks should be marked in OOB, flash-based BBT, or both */ |
3701 | BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && | 3790 | BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && |
3702 | !(chip->bbt_options & NAND_BBT_USE_FLASH)); | 3791 | !(chip->bbt_options & NAND_BBT_USE_FLASH)); |
3703 | 3792 | ||
3704 | if (!(chip->options & NAND_OWN_BUFFERS)) | 3793 | if (!(chip->options & NAND_OWN_BUFFERS)) { |
3705 | chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); | 3794 | nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize |
3706 | if (!chip->buffers) | 3795 | + mtd->oobsize * 3, GFP_KERNEL); |
3707 | return -ENOMEM; | 3796 | if (!nbuf) |
3797 | return -ENOMEM; | ||
3798 | nbuf->ecccalc = (uint8_t *)(nbuf + 1); | ||
3799 | nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; | ||
3800 | nbuf->databuf = nbuf->ecccode + mtd->oobsize; | ||
3801 | |||
3802 | chip->buffers = nbuf; | ||
3803 | } else { | ||
3804 | if (!chip->buffers) | ||
3805 | return -ENOMEM; | ||
3806 | } | ||
3708 | 3807 | ||
3709 | /* Set the internal oob buffer location, just after the page data */ | 3808 | /* Set the internal oob buffer location, just after the page data */ |
3710 | chip->oob_poi = chip->buffers->databuf + mtd->writesize; | 3809 | chip->oob_poi = chip->buffers->databuf + mtd->writesize; |
@@ -3825,7 +3924,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3825 | 3924 | ||
3826 | case NAND_ECC_SOFT_BCH: | 3925 | case NAND_ECC_SOFT_BCH: |
3827 | if (!mtd_nand_has_bch()) { | 3926 | if (!mtd_nand_has_bch()) { |
3828 | pr_warn("CONFIG_MTD_ECC_BCH not enabled\n"); | 3927 | pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); |
3829 | BUG(); | 3928 | BUG(); |
3830 | } | 3929 | } |
3831 | ecc->calculate = nand_bch_calculate_ecc; | 3930 | ecc->calculate = nand_bch_calculate_ecc; |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index daa2faacd7d0..3d7c89fc1031 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -43,6 +43,9 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
43 | {"TC58NVG6D2 64G 3.3V 8-bit", | 43 | {"TC58NVG6D2 64G 3.3V 8-bit", |
44 | { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, | 44 | { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, |
45 | SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, | 45 | SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, |
46 | {"SDTNRGAMA 64G 3.3V 8-bit", | ||
47 | { .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} }, | ||
48 | SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, | ||
46 | 49 | ||
47 | LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), | 50 | LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), |
48 | LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), | 51 | LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), |
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 9ee09a8177c6..e8a5fffd6ab2 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
16 | #include <linux/io.h> | 15 | #include <linux/io.h> |
@@ -152,7 +151,8 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
152 | if (column != -1 || page_addr != -1) { | 151 | if (column != -1 || page_addr != -1) { |
153 | 152 | ||
154 | if (column != -1) { | 153 | if (column != -1) { |
155 | if (chip->options & NAND_BUSWIDTH_16) | 154 | if (chip->options & NAND_BUSWIDTH_16 && |
155 | !nand_opcode_8bits(command)) | ||
156 | column >>= 1; | 156 | column >>= 1; |
157 | write_addr_reg(nand, column); | 157 | write_addr_reg(nand, column); |
158 | write_addr_reg(nand, column >> 8 | ENDADDR); | 158 | write_addr_reg(nand, column >> 8 | ENDADDR); |
@@ -225,7 +225,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand) | |||
225 | val = __raw_readl(nand->reg + REG_FMICSR); | 225 | val = __raw_readl(nand->reg + REG_FMICSR); |
226 | 226 | ||
227 | if (!(val & NAND_EN)) | 227 | if (!(val & NAND_EN)) |
228 | __raw_writel(val | NAND_EN, REG_FMICSR); | 228 | __raw_writel(val | NAND_EN, nand->reg + REG_FMICSR); |
229 | 229 | ||
230 | val = __raw_readl(nand->reg + REG_SMCSR); | 230 | val = __raw_readl(nand->reg + REG_SMCSR); |
231 | 231 | ||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index bf642ceef681..1ff49b80bdaf 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -118,14 +118,9 @@ | |||
118 | 118 | ||
119 | #define OMAP24XX_DMA_GPMC 4 | 119 | #define OMAP24XX_DMA_GPMC 4 |
120 | 120 | ||
121 | #define BCH8_MAX_ERROR 8 /* upto 8 bit correctable */ | ||
122 | #define BCH4_MAX_ERROR 4 /* upto 4 bit correctable */ | ||
123 | |||
124 | #define SECTOR_BYTES 512 | 121 | #define SECTOR_BYTES 512 |
125 | /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ | 122 | /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ |
126 | #define BCH4_BIT_PAD 4 | 123 | #define BCH4_BIT_PAD 4 |
127 | #define BCH8_ECC_MAX ((SECTOR_BYTES + BCH8_ECC_OOB_BYTES) * 8) | ||
128 | #define BCH4_ECC_MAX ((SECTOR_BYTES + BCH4_ECC_OOB_BYTES) * 8) | ||
129 | 124 | ||
130 | /* GPMC ecc engine settings for read */ | 125 | /* GPMC ecc engine settings for read */ |
131 | #define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ | 126 | #define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ |
@@ -159,7 +154,7 @@ struct omap_nand_info { | |||
159 | 154 | ||
160 | int gpmc_cs; | 155 | int gpmc_cs; |
161 | unsigned long phys_base; | 156 | unsigned long phys_base; |
162 | unsigned long mem_size; | 157 | enum omap_ecc ecc_opt; |
163 | struct completion comp; | 158 | struct completion comp; |
164 | struct dma_chan *dma; | 159 | struct dma_chan *dma; |
165 | int gpmc_irq_fifo; | 160 | int gpmc_irq_fifo; |
@@ -172,7 +167,6 @@ struct omap_nand_info { | |||
172 | int buf_len; | 167 | int buf_len; |
173 | struct gpmc_nand_regs reg; | 168 | struct gpmc_nand_regs reg; |
174 | /* fields specific for BCHx_HW ECC scheme */ | 169 | /* fields specific for BCHx_HW ECC scheme */ |
175 | bool is_elm_used; | ||
176 | struct device *elm_dev; | 170 | struct device *elm_dev; |
177 | struct device_node *of_node; | 171 | struct device_node *of_node; |
178 | }; | 172 | }; |
@@ -1043,9 +1037,8 @@ static int omap_dev_ready(struct mtd_info *mtd) | |||
1043 | } | 1037 | } |
1044 | } | 1038 | } |
1045 | 1039 | ||
1046 | #if defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH) | ||
1047 | /** | 1040 | /** |
1048 | * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction | 1041 | * omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation |
1049 | * @mtd: MTD device structure | 1042 | * @mtd: MTD device structure |
1050 | * @mode: Read/Write mode | 1043 | * @mode: Read/Write mode |
1051 | * | 1044 | * |
@@ -1056,50 +1049,73 @@ static int omap_dev_ready(struct mtd_info *mtd) | |||
1056 | * eccsize0 = 0 (no additional protected byte in spare area) | 1049 | * eccsize0 = 0 (no additional protected byte in spare area) |
1057 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) | 1050 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) |
1058 | */ | 1051 | */ |
1059 | static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) | 1052 | static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) |
1060 | { | 1053 | { |
1061 | int nerrors; | 1054 | unsigned int bch_type; |
1062 | unsigned int dev_width, nsectors; | 1055 | unsigned int dev_width, nsectors; |
1063 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 1056 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
1064 | mtd); | 1057 | mtd); |
1058 | enum omap_ecc ecc_opt = info->ecc_opt; | ||
1065 | struct nand_chip *chip = mtd->priv; | 1059 | struct nand_chip *chip = mtd->priv; |
1066 | u32 val, wr_mode; | 1060 | u32 val, wr_mode; |
1067 | unsigned int ecc_size1, ecc_size0; | 1061 | unsigned int ecc_size1, ecc_size0; |
1068 | 1062 | ||
1069 | /* Using wrapping mode 6 for writing */ | 1063 | /* GPMC configurations for calculating ECC */ |
1070 | wr_mode = BCH_WRAPMODE_6; | 1064 | switch (ecc_opt) { |
1071 | 1065 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | |
1072 | /* | 1066 | bch_type = 0; |
1073 | * ECC engine enabled for valid ecc_size0 nibbles | 1067 | nsectors = 1; |
1074 | * and disabled for ecc_size1 nibbles. | 1068 | if (mode == NAND_ECC_READ) { |
1075 | */ | 1069 | wr_mode = BCH_WRAPMODE_6; |
1076 | ecc_size0 = BCH_ECC_SIZE0; | 1070 | ecc_size0 = BCH_ECC_SIZE0; |
1077 | ecc_size1 = BCH_ECC_SIZE1; | 1071 | ecc_size1 = BCH_ECC_SIZE1; |
1078 | 1072 | } else { | |
1079 | /* Perform ecc calculation on 512-byte sector */ | 1073 | wr_mode = BCH_WRAPMODE_6; |
1080 | nsectors = 1; | 1074 | ecc_size0 = BCH_ECC_SIZE0; |
1081 | 1075 | ecc_size1 = BCH_ECC_SIZE1; | |
1082 | /* Update number of error correction */ | 1076 | } |
1083 | nerrors = info->nand.ecc.strength; | 1077 | break; |
1084 | 1078 | case OMAP_ECC_BCH4_CODE_HW: | |
1085 | /* Multi sector reading/writing for NAND flash with page size < 4096 */ | 1079 | bch_type = 0; |
1086 | if (info->is_elm_used && (mtd->writesize <= 4096)) { | 1080 | nsectors = chip->ecc.steps; |
1087 | if (mode == NAND_ECC_READ) { | 1081 | if (mode == NAND_ECC_READ) { |
1088 | /* Using wrapping mode 1 for reading */ | 1082 | wr_mode = BCH_WRAPMODE_1; |
1089 | wr_mode = BCH_WRAPMODE_1; | 1083 | ecc_size0 = BCH4R_ECC_SIZE0; |
1090 | 1084 | ecc_size1 = BCH4R_ECC_SIZE1; | |
1091 | /* | 1085 | } else { |
1092 | * ECC engine enabled for ecc_size0 nibbles | 1086 | wr_mode = BCH_WRAPMODE_6; |
1093 | * and disabled for ecc_size1 nibbles. | 1087 | ecc_size0 = BCH_ECC_SIZE0; |
1094 | */ | 1088 | ecc_size1 = BCH_ECC_SIZE1; |
1095 | ecc_size0 = (nerrors == 8) ? | ||
1096 | BCH8R_ECC_SIZE0 : BCH4R_ECC_SIZE0; | ||
1097 | ecc_size1 = (nerrors == 8) ? | ||
1098 | BCH8R_ECC_SIZE1 : BCH4R_ECC_SIZE1; | ||
1099 | } | 1089 | } |
1100 | 1090 | break; | |
1101 | /* Perform ecc calculation for one page (< 4096) */ | 1091 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: |
1102 | nsectors = info->nand.ecc.steps; | 1092 | bch_type = 1; |
1093 | nsectors = 1; | ||
1094 | if (mode == NAND_ECC_READ) { | ||
1095 | wr_mode = BCH_WRAPMODE_6; | ||
1096 | ecc_size0 = BCH_ECC_SIZE0; | ||
1097 | ecc_size1 = BCH_ECC_SIZE1; | ||
1098 | } else { | ||
1099 | wr_mode = BCH_WRAPMODE_6; | ||
1100 | ecc_size0 = BCH_ECC_SIZE0; | ||
1101 | ecc_size1 = BCH_ECC_SIZE1; | ||
1102 | } | ||
1103 | break; | ||
1104 | case OMAP_ECC_BCH8_CODE_HW: | ||
1105 | bch_type = 1; | ||
1106 | nsectors = chip->ecc.steps; | ||
1107 | if (mode == NAND_ECC_READ) { | ||
1108 | wr_mode = BCH_WRAPMODE_1; | ||
1109 | ecc_size0 = BCH8R_ECC_SIZE0; | ||
1110 | ecc_size1 = BCH8R_ECC_SIZE1; | ||
1111 | } else { | ||
1112 | wr_mode = BCH_WRAPMODE_6; | ||
1113 | ecc_size0 = BCH_ECC_SIZE0; | ||
1114 | ecc_size1 = BCH_ECC_SIZE1; | ||
1115 | } | ||
1116 | break; | ||
1117 | default: | ||
1118 | return; | ||
1103 | } | 1119 | } |
1104 | 1120 | ||
1105 | writel(ECC1, info->reg.gpmc_ecc_control); | 1121 | writel(ECC1, info->reg.gpmc_ecc_control); |
@@ -1112,7 +1128,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
1112 | 1128 | ||
1113 | /* BCH configuration */ | 1129 | /* BCH configuration */ |
1114 | val = ((1 << 16) | /* enable BCH */ | 1130 | val = ((1 << 16) | /* enable BCH */ |
1115 | (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ | 1131 | (bch_type << 12) | /* BCH4/BCH8/BCH16 */ |
1116 | (wr_mode << 8) | /* wrap mode */ | 1132 | (wr_mode << 8) | /* wrap mode */ |
1117 | (dev_width << 7) | /* bus width */ | 1133 | (dev_width << 7) | /* bus width */ |
1118 | (((nsectors-1) & 0x7) << 4) | /* number of sectors */ | 1134 | (((nsectors-1) & 0x7) << 4) | /* number of sectors */ |
@@ -1124,132 +1140,40 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
1124 | /* Clear ecc and enable bits */ | 1140 | /* Clear ecc and enable bits */ |
1125 | writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); | 1141 | writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); |
1126 | } | 1142 | } |
1127 | #endif | ||
1128 | |||
1129 | #ifdef CONFIG_MTD_NAND_ECC_BCH | ||
1130 | /** | ||
1131 | * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes | ||
1132 | * @mtd: MTD device structure | ||
1133 | * @dat: The pointer to data on which ecc is computed | ||
1134 | * @ecc_code: The ecc_code buffer | ||
1135 | */ | ||
1136 | static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, | ||
1137 | u_char *ecc_code) | ||
1138 | { | ||
1139 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1140 | mtd); | ||
1141 | unsigned long nsectors, val1, val2; | ||
1142 | int i; | ||
1143 | |||
1144 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; | ||
1145 | |||
1146 | for (i = 0; i < nsectors; i++) { | ||
1147 | 1143 | ||
1148 | /* Read hw-computed remainder */ | 1144 | static u8 bch4_polynomial[] = {0x28, 0x13, 0xcc, 0x39, 0x96, 0xac, 0x7f}; |
1149 | val1 = readl(info->reg.gpmc_bch_result0[i]); | 1145 | static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, |
1150 | val2 = readl(info->reg.gpmc_bch_result1[i]); | 1146 | 0x97, 0x79, 0xe5, 0x24, 0xb5}; |
1151 | |||
1152 | /* | ||
1153 | * Add constant polynomial to remainder, in order to get an ecc | ||
1154 | * sequence of 0xFFs for a buffer filled with 0xFFs; and | ||
1155 | * left-justify the resulting polynomial. | ||
1156 | */ | ||
1157 | *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF); | ||
1158 | *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF); | ||
1159 | *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); | ||
1160 | *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF); | ||
1161 | *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF); | ||
1162 | *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF); | ||
1163 | *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4); | ||
1164 | } | ||
1165 | |||
1166 | return 0; | ||
1167 | } | ||
1168 | 1147 | ||
1169 | /** | 1148 | /** |
1170 | * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes | 1149 | * omap_calculate_ecc_bch - Generate bytes of ECC bytes |
1171 | * @mtd: MTD device structure | ||
1172 | * @dat: The pointer to data on which ecc is computed | ||
1173 | * @ecc_code: The ecc_code buffer | ||
1174 | */ | ||
1175 | static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, | ||
1176 | u_char *ecc_code) | ||
1177 | { | ||
1178 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1179 | mtd); | ||
1180 | unsigned long nsectors, val1, val2, val3, val4; | ||
1181 | int i; | ||
1182 | |||
1183 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; | ||
1184 | |||
1185 | for (i = 0; i < nsectors; i++) { | ||
1186 | |||
1187 | /* Read hw-computed remainder */ | ||
1188 | val1 = readl(info->reg.gpmc_bch_result0[i]); | ||
1189 | val2 = readl(info->reg.gpmc_bch_result1[i]); | ||
1190 | val3 = readl(info->reg.gpmc_bch_result2[i]); | ||
1191 | val4 = readl(info->reg.gpmc_bch_result3[i]); | ||
1192 | |||
1193 | /* | ||
1194 | * Add constant polynomial to remainder, in order to get an ecc | ||
1195 | * sequence of 0xFFs for a buffer filled with 0xFFs. | ||
1196 | */ | ||
1197 | *ecc_code++ = 0xef ^ (val4 & 0xFF); | ||
1198 | *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF); | ||
1199 | *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF); | ||
1200 | *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF); | ||
1201 | *ecc_code++ = 0xed ^ (val3 & 0xFF); | ||
1202 | *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF); | ||
1203 | *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF); | ||
1204 | *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF); | ||
1205 | *ecc_code++ = 0x97 ^ (val2 & 0xFF); | ||
1206 | *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF); | ||
1207 | *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF); | ||
1208 | *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF); | ||
1209 | *ecc_code++ = 0xb5 ^ (val1 & 0xFF); | ||
1210 | } | ||
1211 | |||
1212 | return 0; | ||
1213 | } | ||
1214 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ | ||
1215 | |||
1216 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
1217 | /** | ||
1218 | * omap3_calculate_ecc_bch - Generate bytes of ECC bytes | ||
1219 | * @mtd: MTD device structure | 1150 | * @mtd: MTD device structure |
1220 | * @dat: The pointer to data on which ecc is computed | 1151 | * @dat: The pointer to data on which ecc is computed |
1221 | * @ecc_code: The ecc_code buffer | 1152 | * @ecc_code: The ecc_code buffer |
1222 | * | 1153 | * |
1223 | * Support calculating of BCH4/8 ecc vectors for the page | 1154 | * Support calculating of BCH4/8 ecc vectors for the page |
1224 | */ | 1155 | */ |
1225 | static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, | 1156 | static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, |
1226 | u_char *ecc_code) | 1157 | const u_char *dat, u_char *ecc_calc) |
1227 | { | 1158 | { |
1228 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 1159 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
1229 | mtd); | 1160 | mtd); |
1161 | int eccbytes = info->nand.ecc.bytes; | ||
1162 | struct gpmc_nand_regs *gpmc_regs = &info->reg; | ||
1163 | u8 *ecc_code; | ||
1230 | unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; | 1164 | unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; |
1231 | int i, eccbchtsel; | 1165 | int i; |
1232 | 1166 | ||
1233 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; | 1167 | nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; |
1234 | /* | ||
1235 | * find BCH scheme used | ||
1236 | * 0 -> BCH4 | ||
1237 | * 1 -> BCH8 | ||
1238 | */ | ||
1239 | eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3); | ||
1240 | |||
1241 | for (i = 0; i < nsectors; i++) { | 1168 | for (i = 0; i < nsectors; i++) { |
1242 | 1169 | ecc_code = ecc_calc; | |
1243 | /* Read hw-computed remainder */ | 1170 | switch (info->ecc_opt) { |
1244 | bch_val1 = readl(info->reg.gpmc_bch_result0[i]); | 1171 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: |
1245 | bch_val2 = readl(info->reg.gpmc_bch_result1[i]); | 1172 | case OMAP_ECC_BCH8_CODE_HW: |
1246 | if (eccbchtsel) { | 1173 | bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); |
1247 | bch_val3 = readl(info->reg.gpmc_bch_result2[i]); | 1174 | bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); |
1248 | bch_val4 = readl(info->reg.gpmc_bch_result3[i]); | 1175 | bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); |
1249 | } | 1176 | bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); |
1250 | |||
1251 | if (eccbchtsel) { | ||
1252 | /* BCH8 ecc scheme */ | ||
1253 | *ecc_code++ = (bch_val4 & 0xFF); | 1177 | *ecc_code++ = (bch_val4 & 0xFF); |
1254 | *ecc_code++ = ((bch_val3 >> 24) & 0xFF); | 1178 | *ecc_code++ = ((bch_val3 >> 24) & 0xFF); |
1255 | *ecc_code++ = ((bch_val3 >> 16) & 0xFF); | 1179 | *ecc_code++ = ((bch_val3 >> 16) & 0xFF); |
@@ -1263,14 +1187,11 @@ static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, | |||
1263 | *ecc_code++ = ((bch_val1 >> 16) & 0xFF); | 1187 | *ecc_code++ = ((bch_val1 >> 16) & 0xFF); |
1264 | *ecc_code++ = ((bch_val1 >> 8) & 0xFF); | 1188 | *ecc_code++ = ((bch_val1 >> 8) & 0xFF); |
1265 | *ecc_code++ = (bch_val1 & 0xFF); | 1189 | *ecc_code++ = (bch_val1 & 0xFF); |
1266 | /* | 1190 | break; |
1267 | * Setting 14th byte to zero to handle | 1191 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
1268 | * erased page & maintain compatibility | 1192 | case OMAP_ECC_BCH4_CODE_HW: |
1269 | * with RBL | 1193 | bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); |
1270 | */ | 1194 | bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); |
1271 | *ecc_code++ = 0x0; | ||
1272 | } else { | ||
1273 | /* BCH4 ecc scheme */ | ||
1274 | *ecc_code++ = ((bch_val2 >> 12) & 0xFF); | 1195 | *ecc_code++ = ((bch_val2 >> 12) & 0xFF); |
1275 | *ecc_code++ = ((bch_val2 >> 4) & 0xFF); | 1196 | *ecc_code++ = ((bch_val2 >> 4) & 0xFF); |
1276 | *ecc_code++ = ((bch_val2 & 0xF) << 4) | | 1197 | *ecc_code++ = ((bch_val2 & 0xF) << 4) | |
@@ -1279,12 +1200,38 @@ static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, | |||
1279 | *ecc_code++ = ((bch_val1 >> 12) & 0xFF); | 1200 | *ecc_code++ = ((bch_val1 >> 12) & 0xFF); |
1280 | *ecc_code++ = ((bch_val1 >> 4) & 0xFF); | 1201 | *ecc_code++ = ((bch_val1 >> 4) & 0xFF); |
1281 | *ecc_code++ = ((bch_val1 & 0xF) << 4); | 1202 | *ecc_code++ = ((bch_val1 & 0xF) << 4); |
1282 | /* | 1203 | break; |
1283 | * Setting 8th byte to zero to handle | 1204 | default: |
1284 | * erased page | 1205 | return -EINVAL; |
1285 | */ | ||
1286 | *ecc_code++ = 0x0; | ||
1287 | } | 1206 | } |
1207 | |||
1208 | /* ECC scheme specific syndrome customizations */ | ||
1209 | switch (info->ecc_opt) { | ||
1210 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | ||
1211 | /* Add constant polynomial to remainder, so that | ||
1212 | * ECC of blank pages results in 0x0 on reading back */ | ||
1213 | for (i = 0; i < eccbytes; i++) | ||
1214 | ecc_calc[i] ^= bch4_polynomial[i]; | ||
1215 | break; | ||
1216 | case OMAP_ECC_BCH4_CODE_HW: | ||
1217 | /* Set 8th ECC byte as 0x0 for ROM compatibility */ | ||
1218 | ecc_calc[eccbytes - 1] = 0x0; | ||
1219 | break; | ||
1220 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: | ||
1221 | /* Add constant polynomial to remainder, so that | ||
1222 | * ECC of blank pages results in 0x0 on reading back */ | ||
1223 | for (i = 0; i < eccbytes; i++) | ||
1224 | ecc_calc[i] ^= bch8_polynomial[i]; | ||
1225 | break; | ||
1226 | case OMAP_ECC_BCH8_CODE_HW: | ||
1227 | /* Set 14th ECC byte as 0x0 for ROM compatibility */ | ||
1228 | ecc_calc[eccbytes - 1] = 0x0; | ||
1229 | break; | ||
1230 | default: | ||
1231 | return -EINVAL; | ||
1232 | } | ||
1233 | |||
1234 | ecc_calc += eccbytes; | ||
1288 | } | 1235 | } |
1289 | 1236 | ||
1290 | return 0; | 1237 | return 0; |
@@ -1329,6 +1276,7 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, | |||
1329 | return flip_bits; | 1276 | return flip_bits; |
1330 | } | 1277 | } |
1331 | 1278 | ||
1279 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
1332 | /** | 1280 | /** |
1333 | * omap_elm_correct_data - corrects page data area in case error reported | 1281 | * omap_elm_correct_data - corrects page data area in case error reported |
1334 | * @mtd: MTD device structure | 1282 | * @mtd: MTD device structure |
@@ -1337,55 +1285,46 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, | |||
1337 | * @calc_ecc: ecc read from HW ECC registers | 1285 | * @calc_ecc: ecc read from HW ECC registers |
1338 | * | 1286 | * |
1339 | * Calculated ecc vector reported as zero in case of non-error pages. | 1287 | * Calculated ecc vector reported as zero in case of non-error pages. |
1340 | * In case of error/erased pages non-zero error vector is reported. | 1288 | * In case of non-zero ecc vector, first filter out erased-pages, and |
1341 | * In case of non-zero ecc vector, check read_ecc at fixed offset | 1289 | * then process data via ELM to detect bit-flips. |
1342 | * (x = 13/7 in case of BCH8/4 == 0) to find page programmed or not. | ||
1343 | * To handle bit flips in this data, count the number of 0's in | ||
1344 | * read_ecc[x] and check if it greater than 4. If it is less, it is | ||
1345 | * programmed page, else erased page. | ||
1346 | * | ||
1347 | * 1. If page is erased, check with standard ecc vector (ecc vector | ||
1348 | * for erased page to find any bit flip). If check fails, bit flip | ||
1349 | * is present in erased page. Count the bit flips in erased page and | ||
1350 | * if it falls under correctable level, report page with 0xFF and | ||
1351 | * update the correctable bit information. | ||
1352 | * 2. If error is reported on programmed page, update elm error | ||
1353 | * vector and correct the page with ELM error correction routine. | ||
1354 | * | ||
1355 | */ | 1290 | */ |
1356 | static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | 1291 | static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, |
1357 | u_char *read_ecc, u_char *calc_ecc) | 1292 | u_char *read_ecc, u_char *calc_ecc) |
1358 | { | 1293 | { |
1359 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 1294 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
1360 | mtd); | 1295 | mtd); |
1296 | struct nand_ecc_ctrl *ecc = &info->nand.ecc; | ||
1361 | int eccsteps = info->nand.ecc.steps; | 1297 | int eccsteps = info->nand.ecc.steps; |
1362 | int i , j, stat = 0; | 1298 | int i , j, stat = 0; |
1363 | int eccsize, eccflag, ecc_vector_size; | 1299 | int eccflag, actual_eccbytes; |
1364 | struct elm_errorvec err_vec[ERROR_VECTOR_MAX]; | 1300 | struct elm_errorvec err_vec[ERROR_VECTOR_MAX]; |
1365 | u_char *ecc_vec = calc_ecc; | 1301 | u_char *ecc_vec = calc_ecc; |
1366 | u_char *spare_ecc = read_ecc; | 1302 | u_char *spare_ecc = read_ecc; |
1367 | u_char *erased_ecc_vec; | 1303 | u_char *erased_ecc_vec; |
1368 | enum bch_ecc type; | 1304 | u_char *buf; |
1305 | int bitflip_count; | ||
1369 | bool is_error_reported = false; | 1306 | bool is_error_reported = false; |
1307 | u32 bit_pos, byte_pos, error_max, pos; | ||
1308 | int err; | ||
1370 | 1309 | ||
1371 | /* Initialize elm error vector to zero */ | 1310 | switch (info->ecc_opt) { |
1372 | memset(err_vec, 0, sizeof(err_vec)); | 1311 | case OMAP_ECC_BCH4_CODE_HW: |
1373 | 1312 | /* omit 7th ECC byte reserved for ROM code compatibility */ | |
1374 | if (info->nand.ecc.strength == BCH8_MAX_ERROR) { | 1313 | actual_eccbytes = ecc->bytes - 1; |
1375 | type = BCH8_ECC; | ||
1376 | erased_ecc_vec = bch8_vector; | ||
1377 | } else { | ||
1378 | type = BCH4_ECC; | ||
1379 | erased_ecc_vec = bch4_vector; | 1314 | erased_ecc_vec = bch4_vector; |
1315 | break; | ||
1316 | case OMAP_ECC_BCH8_CODE_HW: | ||
1317 | /* omit 14th ECC byte reserved for ROM code compatibility */ | ||
1318 | actual_eccbytes = ecc->bytes - 1; | ||
1319 | erased_ecc_vec = bch8_vector; | ||
1320 | break; | ||
1321 | default: | ||
1322 | pr_err("invalid driver configuration\n"); | ||
1323 | return -EINVAL; | ||
1380 | } | 1324 | } |
1381 | 1325 | ||
1382 | ecc_vector_size = info->nand.ecc.bytes; | 1326 | /* Initialize elm error vector to zero */ |
1383 | 1327 | memset(err_vec, 0, sizeof(err_vec)); | |
1384 | /* | ||
1385 | * Remove extra byte padding for BCH8 RBL | ||
1386 | * compatibility and erased page handling | ||
1387 | */ | ||
1388 | eccsize = ecc_vector_size - 1; | ||
1389 | 1328 | ||
1390 | for (i = 0; i < eccsteps ; i++) { | 1329 | for (i = 0; i < eccsteps ; i++) { |
1391 | eccflag = 0; /* initialize eccflag */ | 1330 | eccflag = 0; /* initialize eccflag */ |
@@ -1394,8 +1333,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1394 | * Check any error reported, | 1333 | * Check any error reported, |
1395 | * In case of error, non zero ecc reported. | 1334 | * In case of error, non zero ecc reported. |
1396 | */ | 1335 | */ |
1397 | 1336 | for (j = 0; j < actual_eccbytes; j++) { | |
1398 | for (j = 0; (j < eccsize); j++) { | ||
1399 | if (calc_ecc[j] != 0) { | 1337 | if (calc_ecc[j] != 0) { |
1400 | eccflag = 1; /* non zero ecc, error present */ | 1338 | eccflag = 1; /* non zero ecc, error present */ |
1401 | break; | 1339 | break; |
@@ -1403,50 +1341,43 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1403 | } | 1341 | } |
1404 | 1342 | ||
1405 | if (eccflag == 1) { | 1343 | if (eccflag == 1) { |
1406 | /* | 1344 | if (memcmp(calc_ecc, erased_ecc_vec, |
1407 | * Set threshold to minimum of 4, half of ecc.strength/2 | 1345 | actual_eccbytes) == 0) { |
1408 | * to allow max bit flip in byte to 4 | ||
1409 | */ | ||
1410 | unsigned int threshold = min_t(unsigned int, 4, | ||
1411 | info->nand.ecc.strength / 2); | ||
1412 | |||
1413 | /* | ||
1414 | * Check data area is programmed by counting | ||
1415 | * number of 0's at fixed offset in spare area. | ||
1416 | * Checking count of 0's against threshold. | ||
1417 | * In case programmed page expects at least threshold | ||
1418 | * zeros in byte. | ||
1419 | * If zeros are less than threshold for programmed page/ | ||
1420 | * zeros are more than threshold erased page, either | ||
1421 | * case page reported as uncorrectable. | ||
1422 | */ | ||
1423 | if (hweight8(~read_ecc[eccsize]) >= threshold) { | ||
1424 | /* | 1346 | /* |
1425 | * Update elm error vector as | 1347 | * calc_ecc[] matches pattern for ECC(all 0xff) |
1426 | * data area is programmed | 1348 | * so this is definitely an erased-page |
1427 | */ | 1349 | */ |
1428 | err_vec[i].error_reported = true; | ||
1429 | is_error_reported = true; | ||
1430 | } else { | 1350 | } else { |
1431 | /* Error reported in erased page */ | 1351 | buf = &data[info->nand.ecc.size * i]; |
1432 | int bitflip_count; | 1352 | /* |
1433 | u_char *buf = &data[info->nand.ecc.size * i]; | 1353 | * count number of 0-bits in read_buf. |
1434 | 1354 | * This check can be removed once a similar | |
1435 | if (memcmp(calc_ecc, erased_ecc_vec, eccsize)) { | 1355 | * check is introduced in generic NAND driver |
1436 | bitflip_count = erased_sector_bitflips( | 1356 | */ |
1437 | buf, read_ecc, info); | 1357 | bitflip_count = erased_sector_bitflips( |
1438 | 1358 | buf, read_ecc, info); | |
1439 | if (bitflip_count) | 1359 | if (bitflip_count) { |
1440 | stat += bitflip_count; | 1360 | /* |
1441 | else | 1361 | * number of 0-bits within ECC limits |
1442 | return -EINVAL; | 1362 | * So this may be an erased-page |
1363 | */ | ||
1364 | stat += bitflip_count; | ||
1365 | } else { | ||
1366 | /* | ||
1367 | * Too many 0-bits. It may be a | ||
1368 | * - programmed-page, OR | ||
1369 | * - erased-page with many bit-flips | ||
1370 | * So this page requires check by ELM | ||
1371 | */ | ||
1372 | err_vec[i].error_reported = true; | ||
1373 | is_error_reported = true; | ||
1443 | } | 1374 | } |
1444 | } | 1375 | } |
1445 | } | 1376 | } |
1446 | 1377 | ||
1447 | /* Update the ecc vector */ | 1378 | /* Update the ecc vector */ |
1448 | calc_ecc += ecc_vector_size; | 1379 | calc_ecc += ecc->bytes; |
1449 | read_ecc += ecc_vector_size; | 1380 | read_ecc += ecc->bytes; |
1450 | } | 1381 | } |
1451 | 1382 | ||
1452 | /* Check if any error reported */ | 1383 | /* Check if any error reported */ |
@@ -1456,23 +1387,26 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1456 | /* Decode BCH error using ELM module */ | 1387 | /* Decode BCH error using ELM module */ |
1457 | elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); | 1388 | elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); |
1458 | 1389 | ||
1390 | err = 0; | ||
1459 | for (i = 0; i < eccsteps; i++) { | 1391 | for (i = 0; i < eccsteps; i++) { |
1460 | if (err_vec[i].error_reported) { | 1392 | if (err_vec[i].error_uncorrectable) { |
1393 | pr_err("nand: uncorrectable bit-flips found\n"); | ||
1394 | err = -EBADMSG; | ||
1395 | } else if (err_vec[i].error_reported) { | ||
1461 | for (j = 0; j < err_vec[i].error_count; j++) { | 1396 | for (j = 0; j < err_vec[i].error_count; j++) { |
1462 | u32 bit_pos, byte_pos, error_max, pos; | 1397 | switch (info->ecc_opt) { |
1463 | 1398 | case OMAP_ECC_BCH4_CODE_HW: | |
1464 | if (type == BCH8_ECC) | 1399 | /* Add 4 bits to take care of padding */ |
1465 | error_max = BCH8_ECC_MAX; | ||
1466 | else | ||
1467 | error_max = BCH4_ECC_MAX; | ||
1468 | |||
1469 | if (info->nand.ecc.strength == BCH8_MAX_ERROR) | ||
1470 | pos = err_vec[i].error_loc[j]; | ||
1471 | else | ||
1472 | /* Add 4 to take care 4 bit padding */ | ||
1473 | pos = err_vec[i].error_loc[j] + | 1400 | pos = err_vec[i].error_loc[j] + |
1474 | BCH4_BIT_PAD; | 1401 | BCH4_BIT_PAD; |
1475 | 1402 | break; | |
1403 | case OMAP_ECC_BCH8_CODE_HW: | ||
1404 | pos = err_vec[i].error_loc[j]; | ||
1405 | break; | ||
1406 | default: | ||
1407 | return -EINVAL; | ||
1408 | } | ||
1409 | error_max = (ecc->size + actual_eccbytes) * 8; | ||
1476 | /* Calculate bit position of error */ | 1410 | /* Calculate bit position of error */ |
1477 | bit_pos = pos % 8; | 1411 | bit_pos = pos % 8; |
1478 | 1412 | ||
@@ -1480,13 +1414,22 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1480 | byte_pos = (error_max - pos - 1) / 8; | 1414 | byte_pos = (error_max - pos - 1) / 8; |
1481 | 1415 | ||
1482 | if (pos < error_max) { | 1416 | if (pos < error_max) { |
1483 | if (byte_pos < 512) | 1417 | if (byte_pos < 512) { |
1418 | pr_debug("bitflip@dat[%d]=%x\n", | ||
1419 | byte_pos, data[byte_pos]); | ||
1484 | data[byte_pos] ^= 1 << bit_pos; | 1420 | data[byte_pos] ^= 1 << bit_pos; |
1485 | else | 1421 | } else { |
1422 | pr_debug("bitflip@oob[%d]=%x\n", | ||
1423 | (byte_pos - 512), | ||
1424 | spare_ecc[byte_pos - 512]); | ||
1486 | spare_ecc[byte_pos - 512] ^= | 1425 | spare_ecc[byte_pos - 512] ^= |
1487 | 1 << bit_pos; | 1426 | 1 << bit_pos; |
1427 | } | ||
1428 | } else { | ||
1429 | pr_err("invalid bit-flip @ %d:%d\n", | ||
1430 | byte_pos, bit_pos); | ||
1431 | err = -EBADMSG; | ||
1488 | } | 1432 | } |
1489 | /* else, not interested to correct ecc */ | ||
1490 | } | 1433 | } |
1491 | } | 1434 | } |
1492 | 1435 | ||
@@ -1494,16 +1437,11 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1494 | stat += err_vec[i].error_count; | 1437 | stat += err_vec[i].error_count; |
1495 | 1438 | ||
1496 | /* Update page data with sector size */ | 1439 | /* Update page data with sector size */ |
1497 | data += info->nand.ecc.size; | 1440 | data += ecc->size; |
1498 | spare_ecc += ecc_vector_size; | 1441 | spare_ecc += ecc->bytes; |
1499 | } | 1442 | } |
1500 | 1443 | ||
1501 | for (i = 0; i < eccsteps; i++) | 1444 | return (err) ? err : stat; |
1502 | /* Return error if uncorrectable error present */ | ||
1503 | if (err_vec[i].error_uncorrectable) | ||
1504 | return -EINVAL; | ||
1505 | |||
1506 | return stat; | ||
1507 | } | 1445 | } |
1508 | 1446 | ||
1509 | /** | 1447 | /** |
@@ -1601,7 +1539,8 @@ static int is_elm_present(struct omap_nand_info *info, | |||
1601 | struct device_node *elm_node, enum bch_ecc bch_type) | 1539 | struct device_node *elm_node, enum bch_ecc bch_type) |
1602 | { | 1540 | { |
1603 | struct platform_device *pdev; | 1541 | struct platform_device *pdev; |
1604 | info->is_elm_used = false; | 1542 | struct nand_ecc_ctrl *ecc = &info->nand.ecc; |
1543 | int err; | ||
1605 | /* check whether elm-id is passed via DT */ | 1544 | /* check whether elm-id is passed via DT */ |
1606 | if (!elm_node) { | 1545 | if (!elm_node) { |
1607 | pr_err("nand: error: ELM DT node not found\n"); | 1546 | pr_err("nand: error: ELM DT node not found\n"); |
@@ -1615,10 +1554,10 @@ static int is_elm_present(struct omap_nand_info *info, | |||
1615 | } | 1554 | } |
1616 | /* ELM module available, now configure it */ | 1555 | /* ELM module available, now configure it */ |
1617 | info->elm_dev = &pdev->dev; | 1556 | info->elm_dev = &pdev->dev; |
1618 | if (elm_config(info->elm_dev, bch_type)) | 1557 | err = elm_config(info->elm_dev, bch_type, |
1619 | return -ENODEV; | 1558 | (info->mtd.writesize / ecc->size), ecc->size, ecc->bytes); |
1620 | info->is_elm_used = true; | 1559 | |
1621 | return 0; | 1560 | return err; |
1622 | } | 1561 | } |
1623 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ | 1562 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ |
1624 | 1563 | ||
@@ -1657,6 +1596,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1657 | info->gpmc_cs = pdata->cs; | 1596 | info->gpmc_cs = pdata->cs; |
1658 | info->reg = pdata->reg; | 1597 | info->reg = pdata->reg; |
1659 | info->of_node = pdata->of_node; | 1598 | info->of_node = pdata->of_node; |
1599 | info->ecc_opt = pdata->ecc_opt; | ||
1660 | mtd = &info->mtd; | 1600 | mtd = &info->mtd; |
1661 | mtd->priv = &info->nand; | 1601 | mtd->priv = &info->nand; |
1662 | mtd->name = dev_name(&pdev->dev); | 1602 | mtd->name = dev_name(&pdev->dev); |
@@ -1666,27 +1606,11 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1666 | nand_chip->options |= NAND_SKIP_BBTSCAN; | 1606 | nand_chip->options |= NAND_SKIP_BBTSCAN; |
1667 | 1607 | ||
1668 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1608 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1669 | if (res == NULL) { | 1609 | nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); |
1670 | err = -EINVAL; | 1610 | if (IS_ERR(nand_chip->IO_ADDR_R)) |
1671 | dev_err(&pdev->dev, "error getting memory resource\n"); | 1611 | return PTR_ERR(nand_chip->IO_ADDR_R); |
1672 | goto return_error; | ||
1673 | } | ||
1674 | 1612 | ||
1675 | info->phys_base = res->start; | 1613 | info->phys_base = res->start; |
1676 | info->mem_size = resource_size(res); | ||
1677 | |||
1678 | if (!devm_request_mem_region(&pdev->dev, info->phys_base, | ||
1679 | info->mem_size, pdev->dev.driver->name)) { | ||
1680 | err = -EBUSY; | ||
1681 | goto return_error; | ||
1682 | } | ||
1683 | |||
1684 | nand_chip->IO_ADDR_R = devm_ioremap(&pdev->dev, info->phys_base, | ||
1685 | info->mem_size); | ||
1686 | if (!nand_chip->IO_ADDR_R) { | ||
1687 | err = -ENOMEM; | ||
1688 | goto return_error; | ||
1689 | } | ||
1690 | 1614 | ||
1691 | nand_chip->controller = &info->controller; | 1615 | nand_chip->controller = &info->controller; |
1692 | 1616 | ||
@@ -1812,7 +1736,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1812 | /* populate MTD interface based on ECC scheme */ | 1736 | /* populate MTD interface based on ECC scheme */ |
1813 | nand_chip->ecc.layout = &omap_oobinfo; | 1737 | nand_chip->ecc.layout = &omap_oobinfo; |
1814 | ecclayout = &omap_oobinfo; | 1738 | ecclayout = &omap_oobinfo; |
1815 | switch (pdata->ecc_opt) { | 1739 | switch (info->ecc_opt) { |
1816 | case OMAP_ECC_HAM1_CODE_HW: | 1740 | case OMAP_ECC_HAM1_CODE_HW: |
1817 | pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); | 1741 | pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); |
1818 | nand_chip->ecc.mode = NAND_ECC_HW; | 1742 | nand_chip->ecc.mode = NAND_ECC_HW; |
@@ -1844,9 +1768,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1844 | nand_chip->ecc.size = 512; | 1768 | nand_chip->ecc.size = 512; |
1845 | nand_chip->ecc.bytes = 7; | 1769 | nand_chip->ecc.bytes = 7; |
1846 | nand_chip->ecc.strength = 4; | 1770 | nand_chip->ecc.strength = 4; |
1847 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1771 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
1848 | nand_chip->ecc.correct = nand_bch_correct_data; | 1772 | nand_chip->ecc.correct = nand_bch_correct_data; |
1849 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch4; | 1773 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
1850 | /* define ECC layout */ | 1774 | /* define ECC layout */ |
1851 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1775 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
1852 | (mtd->writesize / | 1776 | (mtd->writesize / |
@@ -1884,9 +1808,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1884 | /* 14th bit is kept reserved for ROM-code compatibility */ | 1808 | /* 14th bit is kept reserved for ROM-code compatibility */ |
1885 | nand_chip->ecc.bytes = 7 + 1; | 1809 | nand_chip->ecc.bytes = 7 + 1; |
1886 | nand_chip->ecc.strength = 4; | 1810 | nand_chip->ecc.strength = 4; |
1887 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1811 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
1888 | nand_chip->ecc.correct = omap_elm_correct_data; | 1812 | nand_chip->ecc.correct = omap_elm_correct_data; |
1889 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch; | 1813 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
1890 | nand_chip->ecc.read_page = omap_read_page_bch; | 1814 | nand_chip->ecc.read_page = omap_read_page_bch; |
1891 | nand_chip->ecc.write_page = omap_write_page_bch; | 1815 | nand_chip->ecc.write_page = omap_write_page_bch; |
1892 | /* define ECC layout */ | 1816 | /* define ECC layout */ |
@@ -1919,9 +1843,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1919 | nand_chip->ecc.size = 512; | 1843 | nand_chip->ecc.size = 512; |
1920 | nand_chip->ecc.bytes = 13; | 1844 | nand_chip->ecc.bytes = 13; |
1921 | nand_chip->ecc.strength = 8; | 1845 | nand_chip->ecc.strength = 8; |
1922 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1846 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
1923 | nand_chip->ecc.correct = nand_bch_correct_data; | 1847 | nand_chip->ecc.correct = nand_bch_correct_data; |
1924 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch8; | 1848 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
1925 | /* define ECC layout */ | 1849 | /* define ECC layout */ |
1926 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1850 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
1927 | (mtd->writesize / | 1851 | (mtd->writesize / |
@@ -1960,9 +1884,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1960 | /* 14th bit is kept reserved for ROM-code compatibility */ | 1884 | /* 14th bit is kept reserved for ROM-code compatibility */ |
1961 | nand_chip->ecc.bytes = 13 + 1; | 1885 | nand_chip->ecc.bytes = 13 + 1; |
1962 | nand_chip->ecc.strength = 8; | 1886 | nand_chip->ecc.strength = 8; |
1963 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1887 | nand_chip->ecc.hwctl = omap_enable_hwecc_bch; |
1964 | nand_chip->ecc.correct = omap_elm_correct_data; | 1888 | nand_chip->ecc.correct = omap_elm_correct_data; |
1965 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch; | 1889 | nand_chip->ecc.calculate = omap_calculate_ecc_bch; |
1966 | nand_chip->ecc.read_page = omap_read_page_bch; | 1890 | nand_chip->ecc.read_page = omap_read_page_bch; |
1967 | nand_chip->ecc.write_page = omap_write_page_bch; | 1891 | nand_chip->ecc.write_page = omap_write_page_bch; |
1968 | /* This ECC scheme requires ELM H/W block */ | 1892 | /* This ECC scheme requires ELM H/W block */ |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 90f871acb0ef..2c98f9da7471 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #undef DEBUG | 23 | #undef DEBUG |
24 | 24 | ||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/mtd/mtd.h> | 27 | #include <linux/mtd/mtd.h> |
29 | #include <linux/mtd/nand.h> | 28 | #include <linux/mtd/nand.h> |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2a7a0b27ac38..7588fe2c127f 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #include <linux/platform_data/mtd-nand-pxa3xx.h> | 39 | #include <linux/platform_data/mtd-nand-pxa3xx.h> |
40 | 40 | ||
41 | #define NAND_DEV_READY_TIMEOUT 50 | ||
42 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | 41 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) |
43 | #define NAND_STOP_DELAY (2 * HZ/50) | 42 | #define NAND_STOP_DELAY (2 * HZ/50) |
44 | #define PAGE_CHUNK_SIZE (2048) | 43 | #define PAGE_CHUNK_SIZE (2048) |
@@ -1531,7 +1530,7 @@ KEEP_CONFIG: | |||
1531 | if (!ret) { | 1530 | if (!ret) { |
1532 | dev_err(&info->pdev->dev, | 1531 | dev_err(&info->pdev->dev, |
1533 | "ECC strength %d at page size %d is not supported\n", | 1532 | "ECC strength %d at page size %d is not supported\n", |
1534 | chip->ecc_strength_ds, mtd->writesize); | 1533 | ecc_strength, mtd->writesize); |
1535 | return -ENODEV; | 1534 | return -ENODEV; |
1536 | } | 1535 | } |
1537 | 1536 | ||
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index f0918e7411d9..79acbb8691b5 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/init.h> | ||
33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
34 | #include <linux/string.h> | 33 | #include <linux/string.h> |
35 | #include <linux/io.h> | 34 | #include <linux/io.h> |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 8e1919b6f074..093c29ac1a13 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
19 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 6547c84afc3a..d945473c3882 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | ||
29 | #include <linux/mtd/mtd.h> | 28 | #include <linux/mtd/mtd.h> |
30 | #include <linux/mtd/onenand.h> | 29 | #include <linux/mtd/onenand.h> |
31 | #include <linux/mtd/partitions.h> | 30 | #include <linux/mtd/partitions.h> |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 1de33b5d3903..635ee0027691 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/init.h> | ||
28 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
@@ -3238,20 +3237,17 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len, | |||
3238 | /** | 3237 | /** |
3239 | * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info | 3238 | * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info |
3240 | * @param mtd MTD device structure | 3239 | * @param mtd MTD device structure |
3241 | * @param buf the databuffer to put/get data | ||
3242 | * @param len number of bytes to read | 3240 | * @param len number of bytes to read |
3241 | * @param retlen pointer to variable to store the number of read bytes | ||
3242 | * @param buf the databuffer to put/get data | ||
3243 | * | 3243 | * |
3244 | * Read factory OTP info. | 3244 | * Read factory OTP info. |
3245 | */ | 3245 | */ |
3246 | static int onenand_get_fact_prot_info(struct mtd_info *mtd, | 3246 | static int onenand_get_fact_prot_info(struct mtd_info *mtd, size_t len, |
3247 | struct otp_info *buf, size_t len) | 3247 | size_t *retlen, struct otp_info *buf) |
3248 | { | 3248 | { |
3249 | size_t retlen; | 3249 | return onenand_otp_walk(mtd, 0, len, retlen, (u_char *) buf, NULL, |
3250 | int ret; | 3250 | MTD_OTP_FACTORY); |
3251 | |||
3252 | ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY); | ||
3253 | |||
3254 | return ret ? : retlen; | ||
3255 | } | 3251 | } |
3256 | 3252 | ||
3257 | /** | 3253 | /** |
@@ -3273,20 +3269,17 @@ static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | |||
3273 | /** | 3269 | /** |
3274 | * onenand_get_user_prot_info - [MTD Interface] Read user OTP info | 3270 | * onenand_get_user_prot_info - [MTD Interface] Read user OTP info |
3275 | * @param mtd MTD device structure | 3271 | * @param mtd MTD device structure |
3276 | * @param buf the databuffer to put/get data | 3272 | * @param retlen pointer to variable to store the number of read bytes |
3277 | * @param len number of bytes to read | 3273 | * @param len number of bytes to read |
3274 | * @param buf the databuffer to put/get data | ||
3278 | * | 3275 | * |
3279 | * Read user OTP info. | 3276 | * Read user OTP info. |
3280 | */ | 3277 | */ |
3281 | static int onenand_get_user_prot_info(struct mtd_info *mtd, | 3278 | static int onenand_get_user_prot_info(struct mtd_info *mtd, size_t len, |
3282 | struct otp_info *buf, size_t len) | 3279 | size_t *retlen, struct otp_info *buf) |
3283 | { | 3280 | { |
3284 | size_t retlen; | 3281 | return onenand_otp_walk(mtd, 0, len, retlen, (u_char *) buf, NULL, |
3285 | int ret; | 3282 | MTD_OTP_USER); |
3286 | |||
3287 | ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER); | ||
3288 | |||
3289 | return ret ? : retlen; | ||
3290 | } | 3283 | } |
3291 | 3284 | ||
3292 | /** | 3285 | /** |
@@ -3995,11 +3988,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
3995 | /* Allocate buffers, if necessary */ | 3988 | /* Allocate buffers, if necessary */ |
3996 | if (!this->page_buf) { | 3989 | if (!this->page_buf) { |
3997 | this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL); | 3990 | this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL); |
3998 | if (!this->page_buf) { | 3991 | if (!this->page_buf) |
3999 | printk(KERN_ERR "%s: Can't allocate page_buf\n", | ||
4000 | __func__); | ||
4001 | return -ENOMEM; | 3992 | return -ENOMEM; |
4002 | } | ||
4003 | #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE | 3993 | #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE |
4004 | this->verify_buf = kzalloc(mtd->writesize, GFP_KERNEL); | 3994 | this->verify_buf = kzalloc(mtd->writesize, GFP_KERNEL); |
4005 | if (!this->verify_buf) { | 3995 | if (!this->verify_buf) { |
@@ -4012,8 +4002,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
4012 | if (!this->oob_buf) { | 4002 | if (!this->oob_buf) { |
4013 | this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL); | 4003 | this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL); |
4014 | if (!this->oob_buf) { | 4004 | if (!this->oob_buf) { |
4015 | printk(KERN_ERR "%s: Can't allocate oob_buf\n", | ||
4016 | __func__); | ||
4017 | if (this->options & ONENAND_PAGEBUF_ALLOC) { | 4005 | if (this->options & ONENAND_PAGEBUF_ALLOC) { |
4018 | this->options &= ~ONENAND_PAGEBUF_ALLOC; | 4006 | this->options &= ~ONENAND_PAGEBUF_ALLOC; |
4019 | kfree(this->page_buf); | 4007 | kfree(this->page_buf); |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index df7400dd4df8..b1a792fd1c23 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -872,10 +872,8 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
872 | 872 | ||
873 | size = sizeof(struct mtd_info) + sizeof(struct onenand_chip); | 873 | size = sizeof(struct mtd_info) + sizeof(struct onenand_chip); |
874 | mtd = kzalloc(size, GFP_KERNEL); | 874 | mtd = kzalloc(size, GFP_KERNEL); |
875 | if (!mtd) { | 875 | if (!mtd) |
876 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
877 | return -ENOMEM; | 876 | return -ENOMEM; |
878 | } | ||
879 | 877 | ||
880 | onenand = kzalloc(sizeof(struct s3c_onenand), GFP_KERNEL); | 878 | onenand = kzalloc(sizeof(struct s3c_onenand), GFP_KERNEL); |
881 | if (!onenand) { | 879 | if (!onenand) { |
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 233b946e5d66..d1cbf26db2c0 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
@@ -602,8 +602,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr) | |||
602 | if (rc) { | 602 | if (rc) { |
603 | printk(KERN_ERR PREFIX "error writing '%s' at " | 603 | printk(KERN_ERR PREFIX "error writing '%s' at " |
604 | "0x%lx\n", part->mbd.mtd->name, addr); | 604 | "0x%lx\n", part->mbd.mtd->name, addr); |
605 | if (rc) | 605 | goto err; |
606 | goto err; | ||
607 | } | 606 | } |
608 | if (block == part->current_block) | 607 | if (block == part->current_block) |
609 | part->header_cache[offset + HEADER_MAP_OFFSET] = del; | 608 | part->header_cache[offset + HEADER_MAP_OFFSET] = del; |
@@ -675,8 +674,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, | |||
675 | if (rc) { | 674 | if (rc) { |
676 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", | 675 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", |
677 | part->mbd.mtd->name, addr); | 676 | part->mbd.mtd->name, addr); |
678 | if (rc) | 677 | goto err; |
679 | goto err; | ||
680 | } | 678 | } |
681 | 679 | ||
682 | part->sector_map[sector] = addr; | 680 | part->sector_map[sector] = addr; |
@@ -695,8 +693,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, | |||
695 | if (rc) { | 693 | if (rc) { |
696 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", | 694 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", |
697 | part->mbd.mtd->name, addr); | 695 | part->mbd.mtd->name, addr); |
698 | if (rc) | 696 | goto err; |
699 | goto err; | ||
700 | } | 697 | } |
701 | block->used_sectors++; | 698 | block->used_sectors++; |
702 | block->free_sectors--; | 699 | block->free_sectors--; |
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 4b8e89583f2a..cf49c22673b9 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c | |||
@@ -59,15 +59,12 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) | |||
59 | struct attribute_group *attr_group; | 59 | struct attribute_group *attr_group; |
60 | struct attribute **attributes; | 60 | struct attribute **attributes; |
61 | struct sm_sysfs_attribute *vendor_attribute; | 61 | struct sm_sysfs_attribute *vendor_attribute; |
62 | char *vendor; | ||
62 | 63 | ||
63 | int vendor_len = strnlen(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, | 64 | vendor = kstrndup(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, |
64 | SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET); | 65 | SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET, GFP_KERNEL); |
65 | |||
66 | char *vendor = kmalloc(vendor_len, GFP_KERNEL); | ||
67 | if (!vendor) | 66 | if (!vendor) |
68 | goto error1; | 67 | goto error1; |
69 | memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len); | ||
70 | vendor[vendor_len] = 0; | ||
71 | 68 | ||
72 | /* Initialize sysfs attributes */ | 69 | /* Initialize sysfs attributes */ |
73 | vendor_attribute = | 70 | vendor_attribute = |
@@ -78,7 +75,7 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) | |||
78 | sysfs_attr_init(&vendor_attribute->dev_attr.attr); | 75 | sysfs_attr_init(&vendor_attribute->dev_attr.attr); |
79 | 76 | ||
80 | vendor_attribute->data = vendor; | 77 | vendor_attribute->data = vendor; |
81 | vendor_attribute->len = vendor_len; | 78 | vendor_attribute->len = strlen(vendor); |
82 | vendor_attribute->dev_attr.attr.name = "vendor"; | 79 | vendor_attribute->dev_attr.attr.name = "vendor"; |
83 | vendor_attribute->dev_attr.attr.mode = S_IRUGO; | 80 | vendor_attribute->dev_attr.attr.mode = S_IRUGO; |
84 | vendor_attribute->dev_attr.show = sm_attr_show; | 81 | vendor_attribute->dev_attr.show = sm_attr_show; |
diff --git a/drivers/mtd/tests/mtd_test.c b/drivers/mtd/tests/mtd_test.c index c818a63532e7..111ee46a7428 100644 --- a/drivers/mtd/tests/mtd_test.c +++ b/drivers/mtd/tests/mtd_test.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #define pr_fmt(fmt) "mtd_test: " fmt | 1 | #define pr_fmt(fmt) "mtd_test: " fmt |
2 | 2 | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/module.h> | 3 | #include <linux/module.h> |
5 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
6 | #include <linux/printk.h> | 5 | #include <linux/printk.h> |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 0ba8b0a28838..7bf416329c19 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -22,7 +22,6 @@ | |||
22 | #ifndef __UBI_UBI_H__ | 22 | #ifndef __UBI_UBI_H__ |
23 | #define __UBI_UBI_H__ | 23 | #define __UBI_UBI_H__ |
24 | 24 | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/types.h> | 25 | #include <linux/types.h> |
27 | #include <linux/list.h> | 26 | #include <linux/list.h> |
28 | #include <linux/rbtree.h> | 27 | #include <linux/rbtree.h> |
diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c index a27ec94877e4..b7361ed70537 100644 --- a/drivers/of/of_mtd.c +++ b/drivers/of/of_mtd.c | |||
@@ -50,6 +50,40 @@ int of_get_nand_ecc_mode(struct device_node *np) | |||
50 | EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode); | 50 | EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode); |
51 | 51 | ||
52 | /** | 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 | /** | ||
53 | * of_get_nand_bus_width - Get nand bus witdh for given device_node | 87 | * of_get_nand_bus_width - Get nand bus witdh for given device_node |
54 | * @np: Pointer to the given device_node | 88 | * @np: Pointer to the given device_node |
55 | * | 89 | * |
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 16a5047903a6..406d9cc84ba8 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c | |||
@@ -33,7 +33,7 @@ static int jffs2_rtime_compress(unsigned char *data_in, | |||
33 | unsigned char *cpage_out, | 33 | unsigned char *cpage_out, |
34 | uint32_t *sourcelen, uint32_t *dstlen) | 34 | uint32_t *sourcelen, uint32_t *dstlen) |
35 | { | 35 | { |
36 | short positions[256]; | 36 | unsigned short positions[256]; |
37 | int outpos = 0; | 37 | int outpos = 0; |
38 | int pos=0; | 38 | int pos=0; |
39 | 39 | ||
@@ -74,7 +74,7 @@ static int jffs2_rtime_decompress(unsigned char *data_in, | |||
74 | unsigned char *cpage_out, | 74 | unsigned char *cpage_out, |
75 | uint32_t srclen, uint32_t destlen) | 75 | uint32_t srclen, uint32_t destlen) |
76 | { | 76 | { |
77 | short positions[256]; | 77 | unsigned short positions[256]; |
78 | int outpos = 0; | 78 | int outpos = 0; |
79 | int pos=0; | 79 | int pos=0; |
80 | 80 | ||
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index f73991522672..601afd1afddf 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -457,12 +457,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r | |||
457 | The umask is only applied if there's no default ACL */ | 457 | The umask is only applied if there's no default ACL */ |
458 | ret = jffs2_init_acl_pre(dir_i, inode, &mode); | 458 | ret = jffs2_init_acl_pre(dir_i, inode, &mode); |
459 | if (ret) { | 459 | if (ret) { |
460 | make_bad_inode(inode); | 460 | mutex_unlock(&f->sem); |
461 | iput(inode); | 461 | make_bad_inode(inode); |
462 | return ERR_PTR(ret); | 462 | iput(inode); |
463 | return ERR_PTR(ret); | ||
463 | } | 464 | } |
464 | ret = jffs2_do_new_inode (c, f, mode, ri); | 465 | ret = jffs2_do_new_inode (c, f, mode, ri); |
465 | if (ret) { | 466 | if (ret) { |
467 | mutex_unlock(&f->sem); | ||
466 | make_bad_inode(inode); | 468 | make_bad_inode(inode); |
467 | iput(inode); | 469 | iput(inode); |
468 | return ERR_PTR(ret); | 470 | return ERR_PTR(ret); |
@@ -479,6 +481,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r | |||
479 | inode->i_size = 0; | 481 | inode->i_size = 0; |
480 | 482 | ||
481 | if (insert_inode_locked(inode) < 0) { | 483 | if (insert_inode_locked(inode) < 0) { |
484 | mutex_unlock(&f->sem); | ||
482 | make_bad_inode(inode); | 485 | make_bad_inode(inode); |
483 | iput(inode); | 486 | iput(inode); |
484 | return ERR_PTR(-EINVAL); | 487 | return ERR_PTR(-EINVAL); |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index e4619b00f7c5..fa35ff79ab35 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -231,7 +231,7 @@ struct jffs2_tmp_dnode_info | |||
231 | uint32_t version; | 231 | uint32_t version; |
232 | uint32_t data_crc; | 232 | uint32_t data_crc; |
233 | uint32_t partial_crc; | 233 | uint32_t partial_crc; |
234 | uint16_t csize; | 234 | uint32_t csize; |
235 | uint16_t overlapped; | 235 | uint16_t overlapped; |
236 | }; | 236 | }; |
237 | 237 | ||
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 03310721712f..b6bd4affd9ad 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -179,6 +179,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
179 | spin_unlock(&c->erase_completion_lock); | 179 | spin_unlock(&c->erase_completion_lock); |
180 | 180 | ||
181 | schedule(); | 181 | schedule(); |
182 | remove_wait_queue(&c->erase_wait, &wait); | ||
182 | } else | 183 | } else |
183 | spin_unlock(&c->erase_completion_lock); | 184 | spin_unlock(&c->erase_completion_lock); |
184 | } else if (ret) | 185 | } else if (ret) |
@@ -211,20 +212,25 @@ out: | |||
211 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, | 212 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, |
212 | uint32_t *len, uint32_t sumsize) | 213 | uint32_t *len, uint32_t sumsize) |
213 | { | 214 | { |
214 | int ret = -EAGAIN; | 215 | int ret; |
215 | minsize = PAD(minsize); | 216 | minsize = PAD(minsize); |
216 | 217 | ||
217 | jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize); | 218 | jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize); |
218 | 219 | ||
219 | spin_lock(&c->erase_completion_lock); | 220 | while (true) { |
220 | while(ret == -EAGAIN) { | 221 | spin_lock(&c->erase_completion_lock); |
221 | ret = jffs2_do_reserve_space(c, minsize, len, sumsize); | 222 | ret = jffs2_do_reserve_space(c, minsize, len, sumsize); |
222 | if (ret) { | 223 | if (ret) { |
223 | jffs2_dbg(1, "%s(): looping, ret is %d\n", | 224 | jffs2_dbg(1, "%s(): looping, ret is %d\n", |
224 | __func__, ret); | 225 | __func__, ret); |
225 | } | 226 | } |
227 | spin_unlock(&c->erase_completion_lock); | ||
228 | |||
229 | if (ret == -EAGAIN) | ||
230 | cond_resched(); | ||
231 | else | ||
232 | break; | ||
226 | } | 233 | } |
227 | spin_unlock(&c->erase_completion_lock); | ||
228 | if (!ret) | 234 | if (!ret) |
229 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); | 235 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); |
230 | 236 | ||
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 8cc0e2fb6894..a1b0b4c8fd79 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -204,12 +204,12 @@ struct mtd_info { | |||
204 | struct mtd_oob_ops *ops); | 204 | struct mtd_oob_ops *ops); |
205 | int (*_write_oob) (struct mtd_info *mtd, loff_t to, | 205 | int (*_write_oob) (struct mtd_info *mtd, loff_t to, |
206 | struct mtd_oob_ops *ops); | 206 | struct mtd_oob_ops *ops); |
207 | int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 207 | int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, |
208 | size_t len); | 208 | size_t *retlen, struct otp_info *buf); |
209 | int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, | 209 | int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, |
210 | size_t len, size_t *retlen, u_char *buf); | 210 | size_t len, size_t *retlen, u_char *buf); |
211 | int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 211 | int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, |
212 | size_t len); | 212 | size_t *retlen, struct otp_info *buf); |
213 | int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, | 213 | int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
214 | size_t len, size_t *retlen, u_char *buf); | 214 | size_t len, size_t *retlen, u_char *buf); |
215 | int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, | 215 | int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, |
@@ -278,12 +278,12 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, | |||
278 | return mtd->_write_oob(mtd, to, ops); | 278 | return mtd->_write_oob(mtd, to, ops); |
279 | } | 279 | } |
280 | 280 | ||
281 | int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | 281 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
282 | size_t len); | 282 | struct otp_info *buf); |
283 | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | 283 | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
284 | size_t *retlen, u_char *buf); | 284 | size_t *retlen, u_char *buf); |
285 | int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, | 285 | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
286 | size_t len); | 286 | struct otp_info *buf); |
287 | int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | 287 | int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
288 | size_t *retlen, u_char *buf); | 288 | size_t *retlen, u_char *buf); |
289 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | 289 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 32f8612469d8..450d61ec7f06 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -52,14 +52,6 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
52 | #define NAND_MAX_CHIPS 8 | 52 | #define NAND_MAX_CHIPS 8 |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * This constant declares the max. oobsize / page, which | ||
56 | * is supported now. If you add a chip with bigger oobsize/page | ||
57 | * adjust this accordingly. | ||
58 | */ | ||
59 | #define NAND_MAX_OOBSIZE 744 | ||
60 | #define NAND_MAX_PAGESIZE 8192 | ||
61 | |||
62 | /* | ||
63 | * Constants for hardware specific CLE/ALE/NCE function | 55 | * Constants for hardware specific CLE/ALE/NCE function |
64 | * | 56 | * |
65 | * These are bits which can be or'ed to set/clear multiple | 57 | * These are bits which can be or'ed to set/clear multiple |
@@ -350,6 +342,84 @@ struct nand_onfi_vendor_micron { | |||
350 | u8 param_revision; | 342 | u8 param_revision; |
351 | } __packed; | 343 | } __packed; |
352 | 344 | ||
345 | struct jedec_ecc_info { | ||
346 | u8 ecc_bits; | ||
347 | u8 codeword_size; | ||
348 | __le16 bb_per_lun; | ||
349 | __le16 block_endurance; | ||
350 | u8 reserved[2]; | ||
351 | } __packed; | ||
352 | |||
353 | /* JEDEC features */ | ||
354 | #define JEDEC_FEATURE_16_BIT_BUS (1 << 0) | ||
355 | |||
356 | struct nand_jedec_params { | ||
357 | /* rev info and features block */ | ||
358 | /* 'J' 'E' 'S' 'D' */ | ||
359 | u8 sig[4]; | ||
360 | __le16 revision; | ||
361 | __le16 features; | ||
362 | u8 opt_cmd[3]; | ||
363 | __le16 sec_cmd; | ||
364 | u8 num_of_param_pages; | ||
365 | u8 reserved0[18]; | ||
366 | |||
367 | /* manufacturer information block */ | ||
368 | char manufacturer[12]; | ||
369 | char model[20]; | ||
370 | u8 jedec_id[6]; | ||
371 | u8 reserved1[10]; | ||
372 | |||
373 | /* memory organization block */ | ||
374 | __le32 byte_per_page; | ||
375 | __le16 spare_bytes_per_page; | ||
376 | u8 reserved2[6]; | ||
377 | __le32 pages_per_block; | ||
378 | __le32 blocks_per_lun; | ||
379 | u8 lun_count; | ||
380 | u8 addr_cycles; | ||
381 | u8 bits_per_cell; | ||
382 | u8 programs_per_page; | ||
383 | u8 multi_plane_addr; | ||
384 | u8 multi_plane_op_attr; | ||
385 | u8 reserved3[38]; | ||
386 | |||
387 | /* electrical parameter block */ | ||
388 | __le16 async_sdr_speed_grade; | ||
389 | __le16 toggle_ddr_speed_grade; | ||
390 | __le16 sync_ddr_speed_grade; | ||
391 | u8 async_sdr_features; | ||
392 | u8 toggle_ddr_features; | ||
393 | u8 sync_ddr_features; | ||
394 | __le16 t_prog; | ||
395 | __le16 t_bers; | ||
396 | __le16 t_r; | ||
397 | __le16 t_r_multi_plane; | ||
398 | __le16 t_ccs; | ||
399 | __le16 io_pin_capacitance_typ; | ||
400 | __le16 input_pin_capacitance_typ; | ||
401 | __le16 clk_pin_capacitance_typ; | ||
402 | u8 driver_strength_support; | ||
403 | __le16 t_ald; | ||
404 | u8 reserved4[36]; | ||
405 | |||
406 | /* ECC and endurance block */ | ||
407 | u8 guaranteed_good_blocks; | ||
408 | __le16 guaranteed_block_endurance; | ||
409 | struct jedec_ecc_info ecc_info[4]; | ||
410 | u8 reserved5[29]; | ||
411 | |||
412 | /* reserved */ | ||
413 | u8 reserved6[148]; | ||
414 | |||
415 | /* vendor */ | ||
416 | __le16 vendor_rev_num; | ||
417 | u8 reserved7[88]; | ||
418 | |||
419 | /* CRC for Parameter Page */ | ||
420 | __le16 crc; | ||
421 | } __packed; | ||
422 | |||
353 | /** | 423 | /** |
354 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices | 424 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices |
355 | * @lock: protection lock | 425 | * @lock: protection lock |
@@ -418,7 +488,7 @@ struct nand_ecc_ctrl { | |||
418 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, | 488 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, |
419 | uint8_t *buf, int oob_required, int page); | 489 | uint8_t *buf, int oob_required, int page); |
420 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | 490 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |
421 | uint32_t offs, uint32_t len, uint8_t *buf); | 491 | uint32_t offs, uint32_t len, uint8_t *buf, int page); |
422 | int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | 492 | int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |
423 | uint32_t offset, uint32_t data_len, | 493 | uint32_t offset, uint32_t data_len, |
424 | const uint8_t *data_buf, int oob_required); | 494 | const uint8_t *data_buf, int oob_required); |
@@ -435,17 +505,17 @@ struct nand_ecc_ctrl { | |||
435 | 505 | ||
436 | /** | 506 | /** |
437 | * struct nand_buffers - buffer structure for read/write | 507 | * struct nand_buffers - buffer structure for read/write |
438 | * @ecccalc: buffer for calculated ECC | 508 | * @ecccalc: buffer pointer for calculated ECC, size is oobsize. |
439 | * @ecccode: buffer for ECC read from flash | 509 | * @ecccode: buffer pointer for ECC read from flash, size is oobsize. |
440 | * @databuf: buffer for data - dynamically sized | 510 | * @databuf: buffer pointer for data, size is (page size + oobsize). |
441 | * | 511 | * |
442 | * Do not change the order of buffers. databuf and oobrbuf must be in | 512 | * Do not change the order of buffers. databuf and oobrbuf must be in |
443 | * consecutive order. | 513 | * consecutive order. |
444 | */ | 514 | */ |
445 | struct nand_buffers { | 515 | struct nand_buffers { |
446 | uint8_t ecccalc[NAND_MAX_OOBSIZE]; | 516 | uint8_t *ecccalc; |
447 | uint8_t ecccode[NAND_MAX_OOBSIZE]; | 517 | uint8_t *ecccode; |
448 | uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; | 518 | uint8_t *databuf; |
449 | }; | 519 | }; |
450 | 520 | ||
451 | /** | 521 | /** |
@@ -523,8 +593,12 @@ struct nand_buffers { | |||
523 | * @subpagesize: [INTERN] holds the subpagesize | 593 | * @subpagesize: [INTERN] holds the subpagesize |
524 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), | 594 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), |
525 | * non 0 if ONFI supported. | 595 | * non 0 if ONFI supported. |
596 | * @jedec_version: [INTERN] holds the chip JEDEC version (BCD encoded), | ||
597 | * non 0 if JEDEC supported. | ||
526 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is | 598 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is |
527 | * supported, 0 otherwise. | 599 | * supported, 0 otherwise. |
600 | * @jedec_params: [INTERN] holds the JEDEC parameter page when JEDEC is | ||
601 | * supported, 0 otherwise. | ||
528 | * @read_retries: [INTERN] the number of read retry modes supported | 602 | * @read_retries: [INTERN] the number of read retry modes supported |
529 | * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand | 603 | * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand |
530 | * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand | 604 | * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand |
@@ -597,7 +671,11 @@ struct nand_chip { | |||
597 | int badblockbits; | 671 | int badblockbits; |
598 | 672 | ||
599 | int onfi_version; | 673 | int onfi_version; |
600 | struct nand_onfi_params onfi_params; | 674 | int jedec_version; |
675 | union { | ||
676 | struct nand_onfi_params onfi_params; | ||
677 | struct nand_jedec_params jedec_params; | ||
678 | }; | ||
601 | 679 | ||
602 | int read_retries; | 680 | int read_retries; |
603 | 681 | ||
@@ -840,4 +918,29 @@ static inline bool nand_is_slc(struct nand_chip *chip) | |||
840 | { | 918 | { |
841 | return chip->bits_per_cell == 1; | 919 | return chip->bits_per_cell == 1; |
842 | } | 920 | } |
921 | |||
922 | /** | ||
923 | * Check if the opcode's address should be sent only on the lower 8 bits | ||
924 | * @command: opcode to check | ||
925 | */ | ||
926 | static inline int nand_opcode_8bits(unsigned int command) | ||
927 | { | ||
928 | switch (command) { | ||
929 | case NAND_CMD_READID: | ||
930 | case NAND_CMD_PARAM: | ||
931 | case NAND_CMD_GET_FEATURES: | ||
932 | case NAND_CMD_SET_FEATURES: | ||
933 | return 1; | ||
934 | default: | ||
935 | break; | ||
936 | } | ||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | /* return the supported JEDEC features. */ | ||
941 | static inline int jedec_feature(struct nand_chip *chip) | ||
942 | { | ||
943 | return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features) | ||
944 | : 0; | ||
945 | } | ||
843 | #endif /* __LINUX_MTD_NAND_H */ | 946 | #endif /* __LINUX_MTD_NAND_H */ |
diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h index cb32d9c1e8dc..e266caa36402 100644 --- a/include/linux/of_mtd.h +++ b/include/linux/of_mtd.h | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | int of_get_nand_ecc_mode(struct device_node *np); | 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); | ||
16 | int of_get_nand_bus_width(struct device_node *np); | 18 | int of_get_nand_bus_width(struct device_node *np); |
17 | bool of_get_nand_on_flash_bbt(struct device_node *np); | 19 | bool of_get_nand_on_flash_bbt(struct device_node *np); |
18 | 20 | ||
@@ -23,6 +25,16 @@ static inline int of_get_nand_ecc_mode(struct device_node *np) | |||
23 | return -ENOSYS; | 25 | return -ENOSYS; |
24 | } | 26 | } |
25 | 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 | |||
26 | static inline int of_get_nand_bus_width(struct device_node *np) | 38 | static inline int of_get_nand_bus_width(struct device_node *np) |
27 | { | 39 | { |
28 | return -ENOSYS; | 40 | return -ENOSYS; |
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h index bf0a83b7ed9d..4edb40676b3f 100644 --- a/include/linux/platform_data/elm.h +++ b/include/linux/platform_data/elm.h | |||
@@ -26,13 +26,6 @@ enum bch_ecc { | |||
26 | /* ELM support 8 error syndrome process */ | 26 | /* ELM support 8 error syndrome process */ |
27 | #define ERROR_VECTOR_MAX 8 | 27 | #define ERROR_VECTOR_MAX 8 |
28 | 28 | ||
29 | #define BCH8_ECC_OOB_BYTES 13 | ||
30 | #define BCH4_ECC_OOB_BYTES 7 | ||
31 | /* RBL requires 14 byte even though BCH8 uses only 13 byte */ | ||
32 | #define BCH8_SIZE (BCH8_ECC_OOB_BYTES + 1) | ||
33 | /* Uses 1 extra byte to handle erased pages */ | ||
34 | #define BCH4_SIZE (BCH4_ECC_OOB_BYTES + 1) | ||
35 | |||
36 | /** | 29 | /** |
37 | * struct elm_errorvec - error vector for elm | 30 | * struct elm_errorvec - error vector for elm |
38 | * @error_reported: set true for vectors error is reported | 31 | * @error_reported: set true for vectors error is reported |
@@ -50,5 +43,6 @@ struct elm_errorvec { | |||
50 | 43 | ||
51 | void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc, | 44 | void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc, |
52 | struct elm_errorvec *err_vec); | 45 | struct elm_errorvec *err_vec); |
53 | int elm_config(struct device *dev, enum bch_ecc bch_type); | 46 | int elm_config(struct device *dev, enum bch_ecc bch_type, |
47 | int ecc_steps, int ecc_step_size, int ecc_syndrome_size); | ||
54 | #endif /* __ELM_H */ | 48 | #endif /* __ELM_H */ |
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h index b64115fa93a4..36bb92172f47 100644 --- a/include/linux/platform_data/mtd-nand-s3c2410.h +++ b/include/linux/platform_data/mtd-nand-s3c2410.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/nand.h | 1 | /* |
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | 2 | * Copyright (c) 2004 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 3 | * Ben Dooks <ben@simtec.co.uk> |
5 | * | 4 | * |
@@ -10,6 +9,9 @@ | |||
10 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
11 | */ | 10 | */ |
12 | 11 | ||
12 | #ifndef __MTD_NAND_S3C2410_H | ||
13 | #define __MTD_NAND_S3C2410_H | ||
14 | |||
13 | /** | 15 | /** |
14 | * struct s3c2410_nand_set - define a set of one or more nand chips | 16 | * struct s3c2410_nand_set - define a set of one or more nand chips |
15 | * @disable_ecc: Entirely disable ECC - Dangerous | 17 | * @disable_ecc: Entirely disable ECC - Dangerous |
@@ -65,3 +67,5 @@ struct s3c2410_platform_nand { | |||
65 | * it with the s3c_device_nand. This allows @nand to be __initdata. | 67 | * it with the s3c_device_nand. This allows @nand to be __initdata. |
66 | */ | 68 | */ |
67 | extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand); | 69 | extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand); |
70 | |||
71 | #endif /*__MTD_NAND_S3C2410_H */ | ||