diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 6 | ||||
-rw-r--r-- | drivers/mtd/devices/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/pmc551.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/slram.c | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/pcmciamtd.c | 1 | ||||
-rw-r--r-- | drivers/mtd/mtdchar.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 14 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/ams-delta.c | 74 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 136 | ||||
-rw-r--r-- | drivers/mtd/nand/bcm_umi_nand.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_ifc_nand.c | 1072 | ||||
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 21 | ||||
-rw-r--r-- | drivers/mtd/onenand/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 14 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 30 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 14 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 16 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 12 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 21 |
22 files changed, 1302 insertions, 140 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 58c6020d4182..5760c1a4b3f6 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | menuconfig MTD | 1 | menuconfig MTD |
2 | tristate "Memory Technology Device (MTD) support" | 2 | tristate "Memory Technology Device (MTD) support" |
3 | depends on HAS_IOMEM | 3 | depends on GENERIC_IO |
4 | help | 4 | help |
5 | Memory Technology Devices are flash, RAM and similar chips, often | 5 | Memory Technology Devices are flash, RAM and similar chips, often |
6 | used for solid state file systems on embedded devices. This option | 6 | used for solid state file systems on embedded devices. This option |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index bfee5b3a9217..dbbd2edfb812 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -2525,12 +2525,10 @@ static void cfi_intelext_restore_locks(struct mtd_info *mtd) | |||
2525 | if (!region->lockmap) | 2525 | if (!region->lockmap) |
2526 | continue; | 2526 | continue; |
2527 | 2527 | ||
2528 | for (block = 0; block < region->numblocks; block++) { | 2528 | for_each_clear_bit(block, region->lockmap, region->numblocks) { |
2529 | len = region->erasesize; | 2529 | len = region->erasesize; |
2530 | adr = region->offset + block * len; | 2530 | adr = region->offset + block * len; |
2531 | 2531 | cfi_intelext_unlock(mtd, adr, len); | |
2532 | if (!test_bit(block, region->lockmap)) | ||
2533 | cfi_intelext_unlock(mtd, adr, len); | ||
2534 | } | 2532 | } |
2535 | } | 2533 | } |
2536 | } | 2534 | } |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 98206b034c01..4cdb2af7bf44 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | menu "Self-contained MTD device drivers" | 1 | menu "Self-contained MTD device drivers" |
2 | depends on MTD!=n | 2 | depends on MTD!=n |
3 | depends on HAS_IOMEM | ||
3 | 4 | ||
4 | config MTD_PMC551 | 5 | config MTD_PMC551 |
5 | tristate "Ramix PMC551 PCI Mezzanine RAM card support" | 6 | tristate "Ramix PMC551 PCI Mezzanine RAM card support" |
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index c4368ec39d5c..0c51b988e1f8 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -93,7 +93,6 @@ | |||
93 | #include <linux/fs.h> | 93 | #include <linux/fs.h> |
94 | #include <linux/ioctl.h> | 94 | #include <linux/ioctl.h> |
95 | #include <asm/io.h> | 95 | #include <asm/io.h> |
96 | #include <asm/system.h> | ||
97 | #include <linux/pci.h> | 96 | #include <linux/pci.h> |
98 | #include <linux/mtd/mtd.h> | 97 | #include <linux/mtd/mtd.h> |
99 | 98 | ||
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index ccd39ff509b1..8f52fc858e48 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/ioctl.h> | 42 | #include <linux/ioctl.h> |
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <asm/io.h> | 44 | #include <asm/io.h> |
45 | #include <asm/system.h> | ||
46 | 45 | ||
47 | #include <linux/mtd/mtd.h> | 46 | #include <linux/mtd/mtd.h> |
48 | 47 | ||
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 6c5c431c64af..8af67cfd671a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | menu "Mapping drivers for chip access" | 1 | menu "Mapping drivers for chip access" |
2 | depends on MTD!=n | 2 | depends on MTD!=n |
3 | depends on HAS_IOMEM | ||
3 | 4 | ||
4 | config MTD_COMPLEX_MAPPINGS | 5 | config MTD_COMPLEX_MAPPINGS |
5 | bool "Support non-linear mappings of flash chips" | 6 | bool "Support non-linear mappings of flash chips" |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 7d5cf369f0ad..a3cfad392ed6 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/system.h> | ||
18 | 17 | ||
19 | #include <pcmcia/cistpl.h> | 18 | #include <pcmcia/cistpl.h> |
20 | #include <pcmcia/ds.h> | 19 | #include <pcmcia/ds.h> |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 426640eaf818..55d82321d307 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -31,13 +31,13 @@ | |||
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
33 | #include <linux/blkpg.h> | 33 | #include <linux/blkpg.h> |
34 | #include <linux/magic.h> | ||
34 | #include <linux/mtd/mtd.h> | 35 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
36 | #include <linux/mtd/map.h> | 37 | #include <linux/mtd/map.h> |
37 | 38 | ||
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
39 | 40 | ||
40 | #define MTD_INODE_FS_MAGIC 0x11307854 | ||
41 | static DEFINE_MUTEX(mtd_mutex); | 41 | static DEFINE_MUTEX(mtd_mutex); |
42 | static struct vfsmount *mtd_inode_mnt __read_mostly; | 42 | static struct vfsmount *mtd_inode_mnt __read_mostly; |
43 | 43 | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 0ea7084eabdc..7d17cecad69d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -187,7 +187,7 @@ config MTD_NAND_PPCHAMELEONEVB | |||
187 | 187 | ||
188 | config MTD_NAND_S3C2410 | 188 | config MTD_NAND_S3C2410 |
189 | tristate "NAND Flash support for Samsung S3C SoCs" | 189 | tristate "NAND Flash support for Samsung S3C SoCs" |
190 | depends on ARCH_S3C2410 || ARCH_S3C64XX | 190 | depends on ARCH_S3C24XX || ARCH_S3C64XX |
191 | help | 191 | help |
192 | This enables the NAND flash controller on the S3C24xx and S3C64xx | 192 | This enables the NAND flash controller on the S3C24xx and S3C64xx |
193 | SoCs | 193 | SoCs |
@@ -246,6 +246,7 @@ config MTD_NAND_BCM_UMI_HWCS | |||
246 | config MTD_NAND_DISKONCHIP | 246 | config MTD_NAND_DISKONCHIP |
247 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" | 247 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" |
248 | depends on EXPERIMENTAL | 248 | depends on EXPERIMENTAL |
249 | depends on HAS_IOMEM | ||
249 | select REED_SOLOMON | 250 | select REED_SOLOMON |
250 | select REED_SOLOMON_DEC16 | 251 | select REED_SOLOMON_DEC16 |
251 | help | 252 | help |
@@ -450,6 +451,7 @@ config MTD_NAND_GPMI_NAND | |||
450 | 451 | ||
451 | config MTD_NAND_PLATFORM | 452 | config MTD_NAND_PLATFORM |
452 | tristate "Support for generic platform NAND driver" | 453 | tristate "Support for generic platform NAND driver" |
454 | depends on HAS_IOMEM | ||
453 | help | 455 | help |
454 | This implements a generic NAND driver for on-SOC platform | 456 | This implements a generic NAND driver for on-SOC platform |
455 | devices. You will need to provide platform-specific functions | 457 | devices. You will need to provide platform-specific functions |
@@ -481,6 +483,16 @@ config MTD_NAND_FSL_ELBC | |||
481 | Enabling this option will enable you to use this to control | 483 | Enabling this option will enable you to use this to control |
482 | external NAND devices. | 484 | external NAND devices. |
483 | 485 | ||
486 | config MTD_NAND_FSL_IFC | ||
487 | tristate "NAND support for Freescale IFC controller" | ||
488 | depends on MTD_NAND && FSL_SOC | ||
489 | select FSL_IFC | ||
490 | help | ||
491 | Various Freescale chips e.g P1010, include a NAND Flash machine | ||
492 | with built-in hardware ECC capabilities. | ||
493 | Enabling this option will enable you to use this to control | ||
494 | external NAND devices. | ||
495 | |||
484 | config MTD_NAND_FSL_UPM | 496 | config MTD_NAND_FSL_UPM |
485 | tristate "Support for NAND on Freescale UPM" | 497 | tristate "Support for NAND on Freescale UPM" |
486 | depends on PPC_83xx || PPC_85xx | 498 | depends on PPC_83xx || PPC_85xx |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 36c26ab2ae16..d4b4d8739bd8 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_MTD_ALAUDA) += alauda.o | |||
38 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o | 38 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o |
39 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o | 39 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o |
40 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o | 40 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o |
41 | obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o | ||
41 | obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o | 42 | obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o |
42 | obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o | 43 | obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o |
43 | obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o | 44 | obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 3197e9764fcd..73416951f4c1 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
28 | #include <asm/sizes.h> | 28 | #include <asm/sizes.h> |
29 | #include <asm/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <plat/board-ams-delta.h> | 30 | #include <plat/board-ams-delta.h> |
31 | 31 | ||
32 | /* | 32 | /* |
@@ -34,8 +34,6 @@ | |||
34 | */ | 34 | */ |
35 | static struct mtd_info *ams_delta_mtd = NULL; | 35 | static struct mtd_info *ams_delta_mtd = NULL; |
36 | 36 | ||
37 | #define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP) | ||
38 | |||
39 | /* | 37 | /* |
40 | * Define partitions for flash devices | 38 | * Define partitions for flash devices |
41 | */ | 39 | */ |
@@ -68,10 +66,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) | |||
68 | 66 | ||
69 | writew(0, io_base + OMAP_MPUIO_IO_CNTL); | 67 | writew(0, io_base + OMAP_MPUIO_IO_CNTL); |
70 | writew(byte, this->IO_ADDR_W); | 68 | writew(byte, this->IO_ADDR_W); |
71 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0); | 69 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0); |
72 | ndelay(40); | 70 | ndelay(40); |
73 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, | 71 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); |
74 | AMS_DELTA_LATCH2_NAND_NWE); | ||
75 | } | 72 | } |
76 | 73 | ||
77 | static u_char ams_delta_read_byte(struct mtd_info *mtd) | 74 | static u_char ams_delta_read_byte(struct mtd_info *mtd) |
@@ -80,12 +77,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd) | |||
80 | struct nand_chip *this = mtd->priv; | 77 | struct nand_chip *this = mtd->priv; |
81 | void __iomem *io_base = this->priv; | 78 | void __iomem *io_base = this->priv; |
82 | 79 | ||
83 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0); | 80 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); |
84 | ndelay(40); | 81 | ndelay(40); |
85 | writew(~0, io_base + OMAP_MPUIO_IO_CNTL); | 82 | writew(~0, io_base + OMAP_MPUIO_IO_CNTL); |
86 | res = readw(this->IO_ADDR_R); | 83 | res = readw(this->IO_ADDR_R); |
87 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, | 84 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1); |
88 | AMS_DELTA_LATCH2_NAND_NRE); | ||
89 | 85 | ||
90 | return res; | 86 | return res; |
91 | } | 87 | } |
@@ -132,15 +128,12 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, | |||
132 | { | 128 | { |
133 | 129 | ||
134 | if (ctrl & NAND_CTRL_CHANGE) { | 130 | if (ctrl & NAND_CTRL_CHANGE) { |
135 | unsigned long bits; | 131 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE, |
136 | 132 | (ctrl & NAND_NCE) == 0); | |
137 | bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0; | 133 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE, |
138 | bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0; | 134 | (ctrl & NAND_CLE) != 0); |
139 | bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0; | 135 | gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE, |
140 | 136 | (ctrl & NAND_ALE) != 0); | |
141 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE | | ||
142 | AMS_DELTA_LATCH2_NAND_ALE | | ||
143 | AMS_DELTA_LATCH2_NAND_NCE, bits); | ||
144 | } | 137 | } |
145 | 138 | ||
146 | if (cmd != NAND_CMD_NONE) | 139 | if (cmd != NAND_CMD_NONE) |
@@ -152,6 +145,39 @@ static int ams_delta_nand_ready(struct mtd_info *mtd) | |||
152 | return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); | 145 | return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); |
153 | } | 146 | } |
154 | 147 | ||
148 | static const struct gpio _mandatory_gpio[] = { | ||
149 | { | ||
150 | .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE, | ||
151 | .flags = GPIOF_OUT_INIT_HIGH, | ||
152 | .label = "nand_nce", | ||
153 | }, | ||
154 | { | ||
155 | .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE, | ||
156 | .flags = GPIOF_OUT_INIT_HIGH, | ||
157 | .label = "nand_nre", | ||
158 | }, | ||
159 | { | ||
160 | .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP, | ||
161 | .flags = GPIOF_OUT_INIT_HIGH, | ||
162 | .label = "nand_nwp", | ||
163 | }, | ||
164 | { | ||
165 | .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE, | ||
166 | .flags = GPIOF_OUT_INIT_HIGH, | ||
167 | .label = "nand_nwe", | ||
168 | }, | ||
169 | { | ||
170 | .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE, | ||
171 | .flags = GPIOF_OUT_INIT_LOW, | ||
172 | .label = "nand_ale", | ||
173 | }, | ||
174 | { | ||
175 | .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE, | ||
176 | .flags = GPIOF_OUT_INIT_LOW, | ||
177 | .label = "nand_cle", | ||
178 | }, | ||
179 | }; | ||
180 | |||
155 | /* | 181 | /* |
156 | * Main initialization routine | 182 | * Main initialization routine |
157 | */ | 183 | */ |
@@ -223,10 +249,9 @@ static int __devinit ams_delta_init(struct platform_device *pdev) | |||
223 | platform_set_drvdata(pdev, io_base); | 249 | platform_set_drvdata(pdev, io_base); |
224 | 250 | ||
225 | /* Set chip enabled, but */ | 251 | /* Set chip enabled, but */ |
226 | ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | | 252 | err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); |
227 | AMS_DELTA_LATCH2_NAND_NWE | | 253 | if (err) |
228 | AMS_DELTA_LATCH2_NAND_NCE | | 254 | goto out_gpio; |
229 | AMS_DELTA_LATCH2_NAND_NWP); | ||
230 | 255 | ||
231 | /* Scan to find existence of the device */ | 256 | /* Scan to find existence of the device */ |
232 | if (nand_scan(ams_delta_mtd, 1)) { | 257 | if (nand_scan(ams_delta_mtd, 1)) { |
@@ -241,7 +266,10 @@ static int __devinit ams_delta_init(struct platform_device *pdev) | |||
241 | goto out; | 266 | goto out; |
242 | 267 | ||
243 | out_mtd: | 268 | out_mtd: |
269 | gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); | ||
270 | out_gpio: | ||
244 | platform_set_drvdata(pdev, NULL); | 271 | platform_set_drvdata(pdev, NULL); |
272 | gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); | ||
245 | iounmap(io_base); | 273 | iounmap(io_base); |
246 | out_release_io: | 274 | out_release_io: |
247 | release_mem_region(res->start, resource_size(res)); | 275 | release_mem_region(res->start, resource_size(res)); |
@@ -262,6 +290,8 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev) | |||
262 | /* Release resources, unregister device */ | 290 | /* Release resources, unregister device */ |
263 | nand_release(ams_delta_mtd); | 291 | nand_release(ams_delta_mtd); |
264 | 292 | ||
293 | gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); | ||
294 | gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); | ||
265 | iounmap(io_base); | 295 | iounmap(io_base); |
266 | release_mem_region(res->start, resource_size(res)); | 296 | release_mem_region(res->start, resource_size(res)); |
267 | 297 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 662abf08061a..2165576a1c67 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -27,6 +27,10 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/of_gpio.h> | ||
33 | #include <linux/of_mtd.h> | ||
30 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/nand.h> | 35 | #include <linux/mtd/nand.h> |
32 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
@@ -34,22 +38,10 @@ | |||
34 | #include <linux/dmaengine.h> | 38 | #include <linux/dmaengine.h> |
35 | #include <linux/gpio.h> | 39 | #include <linux/gpio.h> |
36 | #include <linux/io.h> | 40 | #include <linux/io.h> |
41 | #include <linux/platform_data/atmel.h> | ||
37 | 42 | ||
38 | #include <mach/board.h> | ||
39 | #include <mach/cpu.h> | 43 | #include <mach/cpu.h> |
40 | 44 | ||
41 | #ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW | ||
42 | #define hard_ecc 1 | ||
43 | #else | ||
44 | #define hard_ecc 0 | ||
45 | #endif | ||
46 | |||
47 | #ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE | ||
48 | #define no_ecc 1 | ||
49 | #else | ||
50 | #define no_ecc 0 | ||
51 | #endif | ||
52 | |||
53 | static int use_dma = 1; | 45 | static int use_dma = 1; |
54 | module_param(use_dma, int, 0); | 46 | module_param(use_dma, int, 0); |
55 | 47 | ||
@@ -95,7 +87,7 @@ struct atmel_nand_host { | |||
95 | struct mtd_info mtd; | 87 | struct mtd_info mtd; |
96 | void __iomem *io_base; | 88 | void __iomem *io_base; |
97 | dma_addr_t io_phys; | 89 | dma_addr_t io_phys; |
98 | struct atmel_nand_data *board; | 90 | struct atmel_nand_data board; |
99 | struct device *dev; | 91 | struct device *dev; |
100 | void __iomem *ecc; | 92 | void __iomem *ecc; |
101 | 93 | ||
@@ -113,8 +105,8 @@ static int cpu_has_dma(void) | |||
113 | */ | 105 | */ |
114 | static void atmel_nand_enable(struct atmel_nand_host *host) | 106 | static void atmel_nand_enable(struct atmel_nand_host *host) |
115 | { | 107 | { |
116 | if (gpio_is_valid(host->board->enable_pin)) | 108 | if (gpio_is_valid(host->board.enable_pin)) |
117 | gpio_set_value(host->board->enable_pin, 0); | 109 | gpio_set_value(host->board.enable_pin, 0); |
118 | } | 110 | } |
119 | 111 | ||
120 | /* | 112 | /* |
@@ -122,8 +114,8 @@ static void atmel_nand_enable(struct atmel_nand_host *host) | |||
122 | */ | 114 | */ |
123 | static void atmel_nand_disable(struct atmel_nand_host *host) | 115 | static void atmel_nand_disable(struct atmel_nand_host *host) |
124 | { | 116 | { |
125 | if (gpio_is_valid(host->board->enable_pin)) | 117 | if (gpio_is_valid(host->board.enable_pin)) |
126 | gpio_set_value(host->board->enable_pin, 1); | 118 | gpio_set_value(host->board.enable_pin, 1); |
127 | } | 119 | } |
128 | 120 | ||
129 | /* | 121 | /* |
@@ -144,9 +136,9 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl | |||
144 | return; | 136 | return; |
145 | 137 | ||
146 | if (ctrl & NAND_CLE) | 138 | if (ctrl & NAND_CLE) |
147 | writeb(cmd, host->io_base + (1 << host->board->cle)); | 139 | writeb(cmd, host->io_base + (1 << host->board.cle)); |
148 | else | 140 | else |
149 | writeb(cmd, host->io_base + (1 << host->board->ale)); | 141 | writeb(cmd, host->io_base + (1 << host->board.ale)); |
150 | } | 142 | } |
151 | 143 | ||
152 | /* | 144 | /* |
@@ -157,8 +149,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) | |||
157 | struct nand_chip *nand_chip = mtd->priv; | 149 | struct nand_chip *nand_chip = mtd->priv; |
158 | struct atmel_nand_host *host = nand_chip->priv; | 150 | struct atmel_nand_host *host = nand_chip->priv; |
159 | 151 | ||
160 | return gpio_get_value(host->board->rdy_pin) ^ | 152 | return gpio_get_value(host->board.rdy_pin) ^ |
161 | !!host->board->rdy_pin_active_low; | 153 | !!host->board.rdy_pin_active_low; |
162 | } | 154 | } |
163 | 155 | ||
164 | /* | 156 | /* |
@@ -273,7 +265,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
273 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) | 265 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) |
274 | return; | 266 | return; |
275 | 267 | ||
276 | if (host->board->bus_width_16) | 268 | if (host->board.bus_width_16) |
277 | atmel_read_buf16(mtd, buf, len); | 269 | atmel_read_buf16(mtd, buf, len); |
278 | else | 270 | else |
279 | atmel_read_buf8(mtd, buf, len); | 271 | atmel_read_buf8(mtd, buf, len); |
@@ -289,7 +281,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
289 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) | 281 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) |
290 | return; | 282 | return; |
291 | 283 | ||
292 | if (host->board->bus_width_16) | 284 | if (host->board.bus_width_16) |
293 | atmel_write_buf16(mtd, buf, len); | 285 | atmel_write_buf16(mtd, buf, len); |
294 | else | 286 | else |
295 | atmel_write_buf8(mtd, buf, len); | 287 | atmel_write_buf8(mtd, buf, len); |
@@ -481,6 +473,56 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
481 | } | 473 | } |
482 | } | 474 | } |
483 | 475 | ||
476 | #if defined(CONFIG_OF) | ||
477 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | ||
478 | struct device_node *np) | ||
479 | { | ||
480 | u32 val; | ||
481 | int ecc_mode; | ||
482 | struct atmel_nand_data *board = &host->board; | ||
483 | enum of_gpio_flags flags; | ||
484 | |||
485 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | ||
486 | if (val >= 32) { | ||
487 | dev_err(host->dev, "invalid addr-offset %u\n", val); | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | board->ale = val; | ||
491 | } | ||
492 | |||
493 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { | ||
494 | if (val >= 32) { | ||
495 | dev_err(host->dev, "invalid cmd-offset %u\n", val); | ||
496 | return -EINVAL; | ||
497 | } | ||
498 | board->cle = val; | ||
499 | } | ||
500 | |||
501 | ecc_mode = of_get_nand_ecc_mode(np); | ||
502 | |||
503 | board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; | ||
504 | |||
505 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); | ||
506 | |||
507 | if (of_get_nand_bus_width(np) == 16) | ||
508 | board->bus_width_16 = 1; | ||
509 | |||
510 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); | ||
511 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); | ||
512 | |||
513 | board->enable_pin = of_get_gpio(np, 1); | ||
514 | board->det_pin = of_get_gpio(np, 2); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | #else | ||
519 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | ||
520 | struct device_node *np) | ||
521 | { | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | #endif | ||
525 | |||
484 | /* | 526 | /* |
485 | * Probe for the NAND device. | 527 | * Probe for the NAND device. |
486 | */ | 528 | */ |
@@ -491,6 +533,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
491 | struct nand_chip *nand_chip; | 533 | struct nand_chip *nand_chip; |
492 | struct resource *regs; | 534 | struct resource *regs; |
493 | struct resource *mem; | 535 | struct resource *mem; |
536 | struct mtd_part_parser_data ppdata = {}; | ||
494 | int res; | 537 | int res; |
495 | 538 | ||
496 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 539 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -517,8 +560,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
517 | 560 | ||
518 | mtd = &host->mtd; | 561 | mtd = &host->mtd; |
519 | nand_chip = &host->nand_chip; | 562 | nand_chip = &host->nand_chip; |
520 | host->board = pdev->dev.platform_data; | ||
521 | host->dev = &pdev->dev; | 563 | host->dev = &pdev->dev; |
564 | if (pdev->dev.of_node) { | ||
565 | res = atmel_of_init_port(host, pdev->dev.of_node); | ||
566 | if (res) | ||
567 | goto err_nand_ioremap; | ||
568 | } else { | ||
569 | memcpy(&host->board, pdev->dev.platform_data, | ||
570 | sizeof(struct atmel_nand_data)); | ||
571 | } | ||
522 | 572 | ||
523 | nand_chip->priv = host; /* link the private data structures */ | 573 | nand_chip->priv = host; /* link the private data structures */ |
524 | mtd->priv = nand_chip; | 574 | mtd->priv = nand_chip; |
@@ -529,26 +579,25 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
529 | nand_chip->IO_ADDR_W = host->io_base; | 579 | nand_chip->IO_ADDR_W = host->io_base; |
530 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; | 580 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; |
531 | 581 | ||
532 | if (gpio_is_valid(host->board->rdy_pin)) | 582 | if (gpio_is_valid(host->board.rdy_pin)) |
533 | nand_chip->dev_ready = atmel_nand_device_ready; | 583 | nand_chip->dev_ready = atmel_nand_device_ready; |
534 | 584 | ||
585 | nand_chip->ecc.mode = host->board.ecc_mode; | ||
586 | |||
535 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 587 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
536 | if (!regs && hard_ecc) { | 588 | if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { |
537 | printk(KERN_ERR "atmel_nand: can't get I/O resource " | 589 | printk(KERN_ERR "atmel_nand: can't get I/O resource " |
538 | "regs\nFalling back on software ECC\n"); | 590 | "regs\nFalling back on software ECC\n"); |
591 | nand_chip->ecc.mode = NAND_ECC_SOFT; | ||
539 | } | 592 | } |
540 | 593 | ||
541 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ | 594 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
542 | if (no_ecc) | ||
543 | nand_chip->ecc.mode = NAND_ECC_NONE; | ||
544 | if (hard_ecc && regs) { | ||
545 | host->ecc = ioremap(regs->start, resource_size(regs)); | 595 | host->ecc = ioremap(regs->start, resource_size(regs)); |
546 | if (host->ecc == NULL) { | 596 | if (host->ecc == NULL) { |
547 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); | 597 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); |
548 | res = -EIO; | 598 | res = -EIO; |
549 | goto err_ecc_ioremap; | 599 | goto err_ecc_ioremap; |
550 | } | 600 | } |
551 | nand_chip->ecc.mode = NAND_ECC_HW; | ||
552 | nand_chip->ecc.calculate = atmel_nand_calculate; | 601 | nand_chip->ecc.calculate = atmel_nand_calculate; |
553 | nand_chip->ecc.correct = atmel_nand_correct; | 602 | nand_chip->ecc.correct = atmel_nand_correct; |
554 | nand_chip->ecc.hwctl = atmel_nand_hwctl; | 603 | nand_chip->ecc.hwctl = atmel_nand_hwctl; |
@@ -559,7 +608,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
559 | 608 | ||
560 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 609 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
561 | 610 | ||
562 | if (host->board->bus_width_16) /* 16-bit bus width */ | 611 | if (host->board.bus_width_16) /* 16-bit bus width */ |
563 | nand_chip->options |= NAND_BUSWIDTH_16; | 612 | nand_chip->options |= NAND_BUSWIDTH_16; |
564 | 613 | ||
565 | nand_chip->read_buf = atmel_read_buf; | 614 | nand_chip->read_buf = atmel_read_buf; |
@@ -568,15 +617,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
568 | platform_set_drvdata(pdev, host); | 617 | platform_set_drvdata(pdev, host); |
569 | atmel_nand_enable(host); | 618 | atmel_nand_enable(host); |
570 | 619 | ||
571 | if (gpio_is_valid(host->board->det_pin)) { | 620 | if (gpio_is_valid(host->board.det_pin)) { |
572 | if (gpio_get_value(host->board->det_pin)) { | 621 | if (gpio_get_value(host->board.det_pin)) { |
573 | printk(KERN_INFO "No SmartMedia card inserted.\n"); | 622 | printk(KERN_INFO "No SmartMedia card inserted.\n"); |
574 | res = -ENXIO; | 623 | res = -ENXIO; |
575 | goto err_no_card; | 624 | goto err_no_card; |
576 | } | 625 | } |
577 | } | 626 | } |
578 | 627 | ||
579 | if (on_flash_bbt) { | 628 | if (host->board.on_flash_bbt || on_flash_bbt) { |
580 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); | 629 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); |
581 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | 630 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
582 | } | 631 | } |
@@ -651,8 +700,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
651 | } | 700 | } |
652 | 701 | ||
653 | mtd->name = "atmel_nand"; | 702 | mtd->name = "atmel_nand"; |
654 | res = mtd_device_parse_register(mtd, NULL, NULL, host->board->parts, | 703 | ppdata.of_node = pdev->dev.of_node; |
655 | host->board->num_parts); | 704 | res = mtd_device_parse_register(mtd, NULL, &ppdata, |
705 | host->board.parts, host->board.num_parts); | ||
656 | if (!res) | 706 | if (!res) |
657 | return res; | 707 | return res; |
658 | 708 | ||
@@ -696,11 +746,21 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) | |||
696 | return 0; | 746 | return 0; |
697 | } | 747 | } |
698 | 748 | ||
749 | #if defined(CONFIG_OF) | ||
750 | static const struct of_device_id atmel_nand_dt_ids[] = { | ||
751 | { .compatible = "atmel,at91rm9200-nand" }, | ||
752 | { /* sentinel */ } | ||
753 | }; | ||
754 | |||
755 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); | ||
756 | #endif | ||
757 | |||
699 | static struct platform_driver atmel_nand_driver = { | 758 | static struct platform_driver atmel_nand_driver = { |
700 | .remove = __exit_p(atmel_nand_remove), | 759 | .remove = __exit_p(atmel_nand_remove), |
701 | .driver = { | 760 | .driver = { |
702 | .name = "atmel_nand", | 761 | .name = "atmel_nand", |
703 | .owner = THIS_MODULE, | 762 | .owner = THIS_MODULE, |
763 | .of_match_table = of_match_ptr(atmel_nand_dt_ids), | ||
704 | }, | 764 | }, |
705 | }; | 765 | }; |
706 | 766 | ||
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index fc600431f519..6908cdde3065 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | 32 | ||
33 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
34 | #include <asm/system.h> | ||
35 | 34 | ||
36 | #include <mach/reg_nand.h> | 35 | #include <mach/reg_nand.h> |
37 | #include <mach/reg_umi.h> | 36 | #include <mach/reg_umi.h> |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c new file mode 100644 index 000000000000..c30ac7b83d28 --- /dev/null +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -0,0 +1,1072 @@ | |||
1 | /* | ||
2 | * Freescale Integrated Flash Controller NAND driver | ||
3 | * | ||
4 | * Copyright 2011-2012 Freescale Semiconductor, Inc | ||
5 | * | ||
6 | * Author: Dipen Dudhat <Dipen.Dudhat@freescale.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mtd/mtd.h> | ||
29 | #include <linux/mtd/nand.h> | ||
30 | #include <linux/mtd/partitions.h> | ||
31 | #include <linux/mtd/nand_ecc.h> | ||
32 | #include <asm/fsl_ifc.h> | ||
33 | |||
34 | #define ERR_BYTE 0xFF /* Value returned for read | ||
35 | bytes when read failed */ | ||
36 | #define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait | ||
37 | for IFC NAND Machine */ | ||
38 | |||
39 | struct fsl_ifc_ctrl; | ||
40 | |||
41 | /* mtd information per set */ | ||
42 | struct fsl_ifc_mtd { | ||
43 | struct mtd_info mtd; | ||
44 | struct nand_chip chip; | ||
45 | struct fsl_ifc_ctrl *ctrl; | ||
46 | |||
47 | struct device *dev; | ||
48 | int bank; /* Chip select bank number */ | ||
49 | unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */ | ||
50 | u8 __iomem *vbase; /* Chip select base virtual address */ | ||
51 | }; | ||
52 | |||
53 | /* overview of the fsl ifc controller */ | ||
54 | struct fsl_ifc_nand_ctrl { | ||
55 | struct nand_hw_control controller; | ||
56 | struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT]; | ||
57 | |||
58 | u8 __iomem *addr; /* Address of assigned IFC buffer */ | ||
59 | unsigned int page; /* Last page written to / read from */ | ||
60 | unsigned int read_bytes;/* Number of bytes read during command */ | ||
61 | unsigned int column; /* Saved column from SEQIN */ | ||
62 | unsigned int index; /* Pointer to next byte to 'read' */ | ||
63 | unsigned int oob; /* Non zero if operating on OOB data */ | ||
64 | unsigned int eccread; /* Non zero for a full-page ECC read */ | ||
65 | unsigned int counter; /* counter for the initializations */ | ||
66 | }; | ||
67 | |||
68 | static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; | ||
69 | |||
70 | /* 512-byte page with 4-bit ECC, 8-bit */ | ||
71 | static struct nand_ecclayout oob_512_8bit_ecc4 = { | ||
72 | .eccbytes = 8, | ||
73 | .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, | ||
74 | .oobfree = { {0, 5}, {6, 2} }, | ||
75 | }; | ||
76 | |||
77 | /* 512-byte page with 4-bit ECC, 16-bit */ | ||
78 | static struct nand_ecclayout oob_512_16bit_ecc4 = { | ||
79 | .eccbytes = 8, | ||
80 | .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, | ||
81 | .oobfree = { {2, 6}, }, | ||
82 | }; | ||
83 | |||
84 | /* 2048-byte page size with 4-bit ECC */ | ||
85 | static struct nand_ecclayout oob_2048_ecc4 = { | ||
86 | .eccbytes = 32, | ||
87 | .eccpos = { | ||
88 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
89 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
90 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
91 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
92 | }, | ||
93 | .oobfree = { {2, 6}, {40, 24} }, | ||
94 | }; | ||
95 | |||
96 | /* 4096-byte page size with 4-bit ECC */ | ||
97 | static struct nand_ecclayout oob_4096_ecc4 = { | ||
98 | .eccbytes = 64, | ||
99 | .eccpos = { | ||
100 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
101 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
102 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
103 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
104 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
105 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
106 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
107 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
108 | }, | ||
109 | .oobfree = { {2, 6}, {72, 56} }, | ||
110 | }; | ||
111 | |||
112 | /* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */ | ||
113 | static struct nand_ecclayout oob_4096_ecc8 = { | ||
114 | .eccbytes = 128, | ||
115 | .eccpos = { | ||
116 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
117 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
118 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
119 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
120 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
121 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
122 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
123 | 64, 65, 66, 67, 68, 69, 70, 71, | ||
124 | 72, 73, 74, 75, 76, 77, 78, 79, | ||
125 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
126 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
127 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
128 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
129 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
130 | 120, 121, 122, 123, 124, 125, 126, 127, | ||
131 | 128, 129, 130, 131, 132, 133, 134, 135, | ||
132 | }, | ||
133 | .oobfree = { {2, 6}, {136, 82} }, | ||
134 | }; | ||
135 | |||
136 | |||
137 | /* | ||
138 | * Generic flash bbt descriptors | ||
139 | */ | ||
140 | static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; | ||
141 | static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; | ||
142 | |||
143 | static struct nand_bbt_descr bbt_main_descr = { | ||
144 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | | ||
145 | NAND_BBT_2BIT | NAND_BBT_VERSION, | ||
146 | .offs = 2, /* 0 on 8-bit small page */ | ||
147 | .len = 4, | ||
148 | .veroffs = 6, | ||
149 | .maxblocks = 4, | ||
150 | .pattern = bbt_pattern, | ||
151 | }; | ||
152 | |||
153 | static struct nand_bbt_descr bbt_mirror_descr = { | ||
154 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | | ||
155 | NAND_BBT_2BIT | NAND_BBT_VERSION, | ||
156 | .offs = 2, /* 0 on 8-bit small page */ | ||
157 | .len = 4, | ||
158 | .veroffs = 6, | ||
159 | .maxblocks = 4, | ||
160 | .pattern = mirror_pattern, | ||
161 | }; | ||
162 | |||
163 | /* | ||
164 | * Set up the IFC hardware block and page address fields, and the ifc nand | ||
165 | * structure addr field to point to the correct IFC buffer in memory | ||
166 | */ | ||
167 | static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | ||
168 | { | ||
169 | struct nand_chip *chip = mtd->priv; | ||
170 | struct fsl_ifc_mtd *priv = chip->priv; | ||
171 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
172 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
173 | int buf_num; | ||
174 | |||
175 | ifc_nand_ctrl->page = page_addr; | ||
176 | /* Program ROW0/COL0 */ | ||
177 | out_be32(&ifc->ifc_nand.row0, page_addr); | ||
178 | out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column); | ||
179 | |||
180 | buf_num = page_addr & priv->bufnum_mask; | ||
181 | |||
182 | ifc_nand_ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2); | ||
183 | ifc_nand_ctrl->index = column; | ||
184 | |||
185 | /* for OOB data point to the second half of the buffer */ | ||
186 | if (oob) | ||
187 | ifc_nand_ctrl->index += mtd->writesize; | ||
188 | } | ||
189 | |||
190 | static int is_blank(struct mtd_info *mtd, unsigned int bufnum) | ||
191 | { | ||
192 | struct nand_chip *chip = mtd->priv; | ||
193 | struct fsl_ifc_mtd *priv = chip->priv; | ||
194 | u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); | ||
195 | u32 __iomem *mainarea = (u32 *)addr; | ||
196 | u8 __iomem *oob = addr + mtd->writesize; | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; i < mtd->writesize / 4; i++) { | ||
200 | if (__raw_readl(&mainarea[i]) != 0xffffffff) | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | for (i = 0; i < chip->ecc.layout->eccbytes; i++) { | ||
205 | int pos = chip->ecc.layout->eccpos[i]; | ||
206 | |||
207 | if (__raw_readb(&oob[pos]) != 0xff) | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | return 1; | ||
212 | } | ||
213 | |||
214 | /* returns nonzero if entire page is blank */ | ||
215 | static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl, | ||
216 | u32 *eccstat, unsigned int bufnum) | ||
217 | { | ||
218 | u32 reg = eccstat[bufnum / 4]; | ||
219 | int errors; | ||
220 | |||
221 | errors = (reg >> ((3 - bufnum % 4) * 8)) & 15; | ||
222 | |||
223 | return errors; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * execute IFC NAND command and wait for it to complete | ||
228 | */ | ||
229 | static void fsl_ifc_run_command(struct mtd_info *mtd) | ||
230 | { | ||
231 | struct nand_chip *chip = mtd->priv; | ||
232 | struct fsl_ifc_mtd *priv = chip->priv; | ||
233 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
234 | struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; | ||
235 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
236 | u32 eccstat[4]; | ||
237 | int i; | ||
238 | |||
239 | /* set the chip select for NAND Transaction */ | ||
240 | out_be32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT); | ||
241 | |||
242 | dev_vdbg(priv->dev, | ||
243 | "%s: fir0=%08x fcr0=%08x\n", | ||
244 | __func__, | ||
245 | in_be32(&ifc->ifc_nand.nand_fir0), | ||
246 | in_be32(&ifc->ifc_nand.nand_fcr0)); | ||
247 | |||
248 | ctrl->nand_stat = 0; | ||
249 | |||
250 | /* start read/write seq */ | ||
251 | out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT); | ||
252 | |||
253 | /* wait for command complete flag or timeout */ | ||
254 | wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, | ||
255 | IFC_TIMEOUT_MSECS * HZ/1000); | ||
256 | |||
257 | /* ctrl->nand_stat will be updated from IRQ context */ | ||
258 | if (!ctrl->nand_stat) | ||
259 | dev_err(priv->dev, "Controller is not responding\n"); | ||
260 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER) | ||
261 | dev_err(priv->dev, "NAND Flash Timeout Error\n"); | ||
262 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER) | ||
263 | dev_err(priv->dev, "NAND Flash Write Protect Error\n"); | ||
264 | |||
265 | if (nctrl->eccread) { | ||
266 | int errors; | ||
267 | int bufnum = nctrl->page & priv->bufnum_mask; | ||
268 | int sector = bufnum * chip->ecc.steps; | ||
269 | int sector_end = sector + chip->ecc.steps - 1; | ||
270 | |||
271 | for (i = sector / 4; i <= sector_end / 4; i++) | ||
272 | eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]); | ||
273 | |||
274 | for (i = sector; i <= sector_end; i++) { | ||
275 | errors = check_read_ecc(mtd, ctrl, eccstat, i); | ||
276 | |||
277 | if (errors == 15) { | ||
278 | /* | ||
279 | * Uncorrectable error. | ||
280 | * OK only if the whole page is blank. | ||
281 | * | ||
282 | * We disable ECCER reporting due to... | ||
283 | * erratum IFC-A002770 -- so report it now if we | ||
284 | * see an uncorrectable error in ECCSTAT. | ||
285 | */ | ||
286 | if (!is_blank(mtd, bufnum)) | ||
287 | ctrl->nand_stat |= | ||
288 | IFC_NAND_EVTER_STAT_ECCER; | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | mtd->ecc_stats.corrected += errors; | ||
293 | } | ||
294 | |||
295 | nctrl->eccread = 0; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | static void fsl_ifc_do_read(struct nand_chip *chip, | ||
300 | int oob, | ||
301 | struct mtd_info *mtd) | ||
302 | { | ||
303 | struct fsl_ifc_mtd *priv = chip->priv; | ||
304 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
305 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
306 | |||
307 | /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ | ||
308 | if (mtd->writesize > 512) { | ||
309 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
310 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
311 | (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | | ||
312 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | | ||
313 | (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | | ||
314 | (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT)); | ||
315 | out_be32(&ifc->ifc_nand.nand_fir1, 0x0); | ||
316 | |||
317 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
318 | (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | | ||
319 | (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT)); | ||
320 | } else { | ||
321 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
322 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
323 | (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | | ||
324 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | | ||
325 | (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT)); | ||
326 | out_be32(&ifc->ifc_nand.nand_fir1, 0x0); | ||
327 | |||
328 | if (oob) | ||
329 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
330 | NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT); | ||
331 | else | ||
332 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
333 | NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /* cmdfunc send commands to the IFC NAND Machine */ | ||
338 | static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, | ||
339 | int column, int page_addr) { | ||
340 | struct nand_chip *chip = mtd->priv; | ||
341 | struct fsl_ifc_mtd *priv = chip->priv; | ||
342 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
343 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
344 | |||
345 | /* clear the read buffer */ | ||
346 | ifc_nand_ctrl->read_bytes = 0; | ||
347 | if (command != NAND_CMD_PAGEPROG) | ||
348 | ifc_nand_ctrl->index = 0; | ||
349 | |||
350 | switch (command) { | ||
351 | /* READ0 read the entire buffer to use hardware ECC. */ | ||
352 | case NAND_CMD_READ0: | ||
353 | out_be32(&ifc->ifc_nand.nand_fbcr, 0); | ||
354 | set_addr(mtd, 0, page_addr, 0); | ||
355 | |||
356 | ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize; | ||
357 | ifc_nand_ctrl->index += column; | ||
358 | |||
359 | if (chip->ecc.mode == NAND_ECC_HW) | ||
360 | ifc_nand_ctrl->eccread = 1; | ||
361 | |||
362 | fsl_ifc_do_read(chip, 0, mtd); | ||
363 | fsl_ifc_run_command(mtd); | ||
364 | return; | ||
365 | |||
366 | /* READOOB reads only the OOB because no ECC is performed. */ | ||
367 | case NAND_CMD_READOOB: | ||
368 | out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column); | ||
369 | set_addr(mtd, column, page_addr, 1); | ||
370 | |||
371 | ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize; | ||
372 | |||
373 | fsl_ifc_do_read(chip, 1, mtd); | ||
374 | fsl_ifc_run_command(mtd); | ||
375 | |||
376 | return; | ||
377 | |||
378 | /* READID must read all 8 possible bytes */ | ||
379 | case NAND_CMD_READID: | ||
380 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
381 | (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
382 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | | ||
383 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); | ||
384 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
385 | NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); | ||
386 | /* 8 bytes for manuf, device and exts */ | ||
387 | out_be32(&ifc->ifc_nand.nand_fbcr, 8); | ||
388 | ifc_nand_ctrl->read_bytes = 8; | ||
389 | |||
390 | set_addr(mtd, 0, 0, 0); | ||
391 | fsl_ifc_run_command(mtd); | ||
392 | return; | ||
393 | |||
394 | /* ERASE1 stores the block and page address */ | ||
395 | case NAND_CMD_ERASE1: | ||
396 | set_addr(mtd, 0, page_addr, 0); | ||
397 | return; | ||
398 | |||
399 | /* ERASE2 uses the block and page address from ERASE1 */ | ||
400 | case NAND_CMD_ERASE2: | ||
401 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
402 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
403 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) | | ||
404 | (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT)); | ||
405 | |||
406 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
407 | (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) | | ||
408 | (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT)); | ||
409 | |||
410 | out_be32(&ifc->ifc_nand.nand_fbcr, 0); | ||
411 | ifc_nand_ctrl->read_bytes = 0; | ||
412 | fsl_ifc_run_command(mtd); | ||
413 | return; | ||
414 | |||
415 | /* SEQIN sets up the addr buffer and all registers except the length */ | ||
416 | case NAND_CMD_SEQIN: { | ||
417 | u32 nand_fcr0; | ||
418 | ifc_nand_ctrl->column = column; | ||
419 | ifc_nand_ctrl->oob = 0; | ||
420 | |||
421 | if (mtd->writesize > 512) { | ||
422 | nand_fcr0 = | ||
423 | (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) | | ||
424 | (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT); | ||
425 | |||
426 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
427 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
428 | (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | | ||
429 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | | ||
430 | (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | | ||
431 | (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT)); | ||
432 | } else { | ||
433 | nand_fcr0 = ((NAND_CMD_PAGEPROG << | ||
434 | IFC_NAND_FCR0_CMD1_SHIFT) | | ||
435 | (NAND_CMD_SEQIN << | ||
436 | IFC_NAND_FCR0_CMD2_SHIFT)); | ||
437 | |||
438 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
439 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
440 | (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) | | ||
441 | (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) | | ||
442 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | | ||
443 | (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT)); | ||
444 | out_be32(&ifc->ifc_nand.nand_fir1, | ||
445 | (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT)); | ||
446 | |||
447 | if (column >= mtd->writesize) | ||
448 | nand_fcr0 |= | ||
449 | NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT; | ||
450 | else | ||
451 | nand_fcr0 |= | ||
452 | NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT; | ||
453 | } | ||
454 | |||
455 | if (column >= mtd->writesize) { | ||
456 | /* OOB area --> READOOB */ | ||
457 | column -= mtd->writesize; | ||
458 | ifc_nand_ctrl->oob = 1; | ||
459 | } | ||
460 | out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0); | ||
461 | set_addr(mtd, column, page_addr, ifc_nand_ctrl->oob); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | ||
466 | case NAND_CMD_PAGEPROG: { | ||
467 | if (ifc_nand_ctrl->oob) { | ||
468 | out_be32(&ifc->ifc_nand.nand_fbcr, | ||
469 | ifc_nand_ctrl->index - ifc_nand_ctrl->column); | ||
470 | } else { | ||
471 | out_be32(&ifc->ifc_nand.nand_fbcr, 0); | ||
472 | } | ||
473 | |||
474 | fsl_ifc_run_command(mtd); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | case NAND_CMD_STATUS: | ||
479 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
480 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
481 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT)); | ||
482 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
483 | NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT); | ||
484 | out_be32(&ifc->ifc_nand.nand_fbcr, 1); | ||
485 | set_addr(mtd, 0, 0, 0); | ||
486 | ifc_nand_ctrl->read_bytes = 1; | ||
487 | |||
488 | fsl_ifc_run_command(mtd); | ||
489 | |||
490 | /* | ||
491 | * The chip always seems to report that it is | ||
492 | * write-protected, even when it is not. | ||
493 | */ | ||
494 | setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP); | ||
495 | return; | ||
496 | |||
497 | case NAND_CMD_RESET: | ||
498 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
499 | IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT); | ||
500 | out_be32(&ifc->ifc_nand.nand_fcr0, | ||
501 | NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT); | ||
502 | fsl_ifc_run_command(mtd); | ||
503 | return; | ||
504 | |||
505 | default: | ||
506 | dev_err(priv->dev, "%s: error, unsupported command 0x%x.\n", | ||
507 | __func__, command); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) | ||
512 | { | ||
513 | /* The hardware does not seem to support multiple | ||
514 | * chips per bank. | ||
515 | */ | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | * Write buf to the IFC NAND Controller Data Buffer | ||
520 | */ | ||
521 | static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | ||
522 | { | ||
523 | struct nand_chip *chip = mtd->priv; | ||
524 | struct fsl_ifc_mtd *priv = chip->priv; | ||
525 | unsigned int bufsize = mtd->writesize + mtd->oobsize; | ||
526 | |||
527 | if (len <= 0) { | ||
528 | dev_err(priv->dev, "%s: len %d bytes", __func__, len); | ||
529 | return; | ||
530 | } | ||
531 | |||
532 | if ((unsigned int)len > bufsize - ifc_nand_ctrl->index) { | ||
533 | dev_err(priv->dev, | ||
534 | "%s: beyond end of buffer (%d requested, %u available)\n", | ||
535 | __func__, len, bufsize - ifc_nand_ctrl->index); | ||
536 | len = bufsize - ifc_nand_ctrl->index; | ||
537 | } | ||
538 | |||
539 | memcpy_toio(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index], buf, len); | ||
540 | ifc_nand_ctrl->index += len; | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * Read a byte from either the IFC hardware buffer | ||
545 | * read function for 8-bit buswidth | ||
546 | */ | ||
547 | static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) | ||
548 | { | ||
549 | struct nand_chip *chip = mtd->priv; | ||
550 | struct fsl_ifc_mtd *priv = chip->priv; | ||
551 | |||
552 | /* | ||
553 | * If there are still bytes in the IFC buffer, then use the | ||
554 | * next byte. | ||
555 | */ | ||
556 | if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) | ||
557 | return in_8(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index++]); | ||
558 | |||
559 | dev_err(priv->dev, "%s: beyond end of buffer\n", __func__); | ||
560 | return ERR_BYTE; | ||
561 | } | ||
562 | |||
563 | /* | ||
564 | * Read two bytes from the IFC hardware buffer | ||
565 | * read function for 16-bit buswith | ||
566 | */ | ||
567 | static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) | ||
568 | { | ||
569 | struct nand_chip *chip = mtd->priv; | ||
570 | struct fsl_ifc_mtd *priv = chip->priv; | ||
571 | uint16_t data; | ||
572 | |||
573 | /* | ||
574 | * If there are still bytes in the IFC buffer, then use the | ||
575 | * next byte. | ||
576 | */ | ||
577 | if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) { | ||
578 | data = in_be16((uint16_t *)&ifc_nand_ctrl-> | ||
579 | addr[ifc_nand_ctrl->index]); | ||
580 | ifc_nand_ctrl->index += 2; | ||
581 | return (uint8_t) data; | ||
582 | } | ||
583 | |||
584 | dev_err(priv->dev, "%s: beyond end of buffer\n", __func__); | ||
585 | return ERR_BYTE; | ||
586 | } | ||
587 | |||
588 | /* | ||
589 | * Read from the IFC Controller Data Buffer | ||
590 | */ | ||
591 | static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) | ||
592 | { | ||
593 | struct nand_chip *chip = mtd->priv; | ||
594 | struct fsl_ifc_mtd *priv = chip->priv; | ||
595 | int avail; | ||
596 | |||
597 | if (len < 0) { | ||
598 | dev_err(priv->dev, "%s: len %d bytes", __func__, len); | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | avail = min((unsigned int)len, | ||
603 | ifc_nand_ctrl->read_bytes - ifc_nand_ctrl->index); | ||
604 | memcpy_fromio(buf, &ifc_nand_ctrl->addr[ifc_nand_ctrl->index], avail); | ||
605 | ifc_nand_ctrl->index += avail; | ||
606 | |||
607 | if (len > avail) | ||
608 | dev_err(priv->dev, | ||
609 | "%s: beyond end of buffer (%d requested, %d available)\n", | ||
610 | __func__, len, avail); | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * Verify buffer against the IFC Controller Data Buffer | ||
615 | */ | ||
616 | static int fsl_ifc_verify_buf(struct mtd_info *mtd, | ||
617 | const u_char *buf, int len) | ||
618 | { | ||
619 | struct nand_chip *chip = mtd->priv; | ||
620 | struct fsl_ifc_mtd *priv = chip->priv; | ||
621 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
622 | struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; | ||
623 | int i; | ||
624 | |||
625 | if (len < 0) { | ||
626 | dev_err(priv->dev, "%s: write_buf of %d bytes", __func__, len); | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | |||
630 | if ((unsigned int)len > nctrl->read_bytes - nctrl->index) { | ||
631 | dev_err(priv->dev, | ||
632 | "%s: beyond end of buffer (%d requested, %u available)\n", | ||
633 | __func__, len, nctrl->read_bytes - nctrl->index); | ||
634 | |||
635 | nctrl->index = nctrl->read_bytes; | ||
636 | return -EINVAL; | ||
637 | } | ||
638 | |||
639 | for (i = 0; i < len; i++) | ||
640 | if (in_8(&nctrl->addr[nctrl->index + i]) != buf[i]) | ||
641 | break; | ||
642 | |||
643 | nctrl->index += len; | ||
644 | |||
645 | if (i != len) | ||
646 | return -EIO; | ||
647 | if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) | ||
648 | return -EIO; | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * This function is called after Program and Erase Operations to | ||
655 | * check for success or failure. | ||
656 | */ | ||
657 | static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) | ||
658 | { | ||
659 | struct fsl_ifc_mtd *priv = chip->priv; | ||
660 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
661 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
662 | u32 nand_fsr; | ||
663 | |||
664 | /* Use READ_STATUS command, but wait for the device to be ready */ | ||
665 | out_be32(&ifc->ifc_nand.nand_fir0, | ||
666 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | | ||
667 | (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT)); | ||
668 | out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS << | ||
669 | IFC_NAND_FCR0_CMD0_SHIFT); | ||
670 | out_be32(&ifc->ifc_nand.nand_fbcr, 1); | ||
671 | set_addr(mtd, 0, 0, 0); | ||
672 | ifc_nand_ctrl->read_bytes = 1; | ||
673 | |||
674 | fsl_ifc_run_command(mtd); | ||
675 | |||
676 | nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr); | ||
677 | |||
678 | /* | ||
679 | * The chip always seems to report that it is | ||
680 | * write-protected, even when it is not. | ||
681 | */ | ||
682 | return nand_fsr | NAND_STATUS_WP; | ||
683 | } | ||
684 | |||
685 | static int fsl_ifc_read_page(struct mtd_info *mtd, | ||
686 | struct nand_chip *chip, | ||
687 | uint8_t *buf, int page) | ||
688 | { | ||
689 | struct fsl_ifc_mtd *priv = chip->priv; | ||
690 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
691 | |||
692 | fsl_ifc_read_buf(mtd, buf, mtd->writesize); | ||
693 | fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
694 | |||
695 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) | ||
696 | dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n"); | ||
697 | |||
698 | if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) | ||
699 | mtd->ecc_stats.failed++; | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | /* ECC will be calculated automatically, and errors will be detected in | ||
705 | * waitfunc. | ||
706 | */ | ||
707 | static void fsl_ifc_write_page(struct mtd_info *mtd, | ||
708 | struct nand_chip *chip, | ||
709 | const uint8_t *buf) | ||
710 | { | ||
711 | fsl_ifc_write_buf(mtd, buf, mtd->writesize); | ||
712 | fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
713 | } | ||
714 | |||
715 | static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) | ||
716 | { | ||
717 | struct nand_chip *chip = mtd->priv; | ||
718 | struct fsl_ifc_mtd *priv = chip->priv; | ||
719 | |||
720 | dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, | ||
721 | chip->numchips); | ||
722 | dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__, | ||
723 | chip->chipsize); | ||
724 | dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__, | ||
725 | chip->pagemask); | ||
726 | dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__, | ||
727 | chip->chip_delay); | ||
728 | dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__, | ||
729 | chip->badblockpos); | ||
730 | dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__, | ||
731 | chip->chip_shift); | ||
732 | dev_dbg(priv->dev, "%s: nand->page_shift = %d\n", __func__, | ||
733 | chip->page_shift); | ||
734 | dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__, | ||
735 | chip->phys_erase_shift); | ||
736 | dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__, | ||
737 | chip->ecclayout); | ||
738 | dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__, | ||
739 | chip->ecc.mode); | ||
740 | dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__, | ||
741 | chip->ecc.steps); | ||
742 | dev_dbg(priv->dev, "%s: nand->ecc.bytes = %d\n", __func__, | ||
743 | chip->ecc.bytes); | ||
744 | dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__, | ||
745 | chip->ecc.total); | ||
746 | dev_dbg(priv->dev, "%s: nand->ecc.layout = %p\n", __func__, | ||
747 | chip->ecc.layout); | ||
748 | dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags); | ||
749 | dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size); | ||
750 | dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__, | ||
751 | mtd->erasesize); | ||
752 | dev_dbg(priv->dev, "%s: mtd->writesize = %d\n", __func__, | ||
753 | mtd->writesize); | ||
754 | dev_dbg(priv->dev, "%s: mtd->oobsize = %d\n", __func__, | ||
755 | mtd->oobsize); | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | ||
761 | { | ||
762 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | ||
763 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | ||
764 | struct nand_chip *chip = &priv->chip; | ||
765 | struct nand_ecclayout *layout; | ||
766 | u32 csor; | ||
767 | |||
768 | /* Fill in fsl_ifc_mtd structure */ | ||
769 | priv->mtd.priv = chip; | ||
770 | priv->mtd.owner = THIS_MODULE; | ||
771 | |||
772 | /* fill in nand_chip structure */ | ||
773 | /* set up function call table */ | ||
774 | if ((in_be32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) | ||
775 | chip->read_byte = fsl_ifc_read_byte16; | ||
776 | else | ||
777 | chip->read_byte = fsl_ifc_read_byte; | ||
778 | |||
779 | chip->write_buf = fsl_ifc_write_buf; | ||
780 | chip->read_buf = fsl_ifc_read_buf; | ||
781 | chip->verify_buf = fsl_ifc_verify_buf; | ||
782 | chip->select_chip = fsl_ifc_select_chip; | ||
783 | chip->cmdfunc = fsl_ifc_cmdfunc; | ||
784 | chip->waitfunc = fsl_ifc_wait; | ||
785 | |||
786 | chip->bbt_td = &bbt_main_descr; | ||
787 | chip->bbt_md = &bbt_mirror_descr; | ||
788 | |||
789 | out_be32(&ifc->ifc_nand.ncfgr, 0x0); | ||
790 | |||
791 | /* set up nand options */ | ||
792 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; | ||
793 | chip->bbt_options = NAND_BBT_USE_FLASH; | ||
794 | |||
795 | |||
796 | if (in_be32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { | ||
797 | chip->read_byte = fsl_ifc_read_byte16; | ||
798 | chip->options |= NAND_BUSWIDTH_16; | ||
799 | } else { | ||
800 | chip->read_byte = fsl_ifc_read_byte; | ||
801 | } | ||
802 | |||
803 | chip->controller = &ifc_nand_ctrl->controller; | ||
804 | chip->priv = priv; | ||
805 | |||
806 | chip->ecc.read_page = fsl_ifc_read_page; | ||
807 | chip->ecc.write_page = fsl_ifc_write_page; | ||
808 | |||
809 | csor = in_be32(&ifc->csor_cs[priv->bank].csor); | ||
810 | |||
811 | /* Hardware generates ECC per 512 Bytes */ | ||
812 | chip->ecc.size = 512; | ||
813 | chip->ecc.bytes = 8; | ||
814 | |||
815 | switch (csor & CSOR_NAND_PGS_MASK) { | ||
816 | case CSOR_NAND_PGS_512: | ||
817 | if (chip->options & NAND_BUSWIDTH_16) { | ||
818 | layout = &oob_512_16bit_ecc4; | ||
819 | } else { | ||
820 | layout = &oob_512_8bit_ecc4; | ||
821 | |||
822 | /* Avoid conflict with bad block marker */ | ||
823 | bbt_main_descr.offs = 0; | ||
824 | bbt_mirror_descr.offs = 0; | ||
825 | } | ||
826 | |||
827 | priv->bufnum_mask = 15; | ||
828 | break; | ||
829 | |||
830 | case CSOR_NAND_PGS_2K: | ||
831 | layout = &oob_2048_ecc4; | ||
832 | priv->bufnum_mask = 3; | ||
833 | break; | ||
834 | |||
835 | case CSOR_NAND_PGS_4K: | ||
836 | if ((csor & CSOR_NAND_ECC_MODE_MASK) == | ||
837 | CSOR_NAND_ECC_MODE_4) { | ||
838 | layout = &oob_4096_ecc4; | ||
839 | } else { | ||
840 | layout = &oob_4096_ecc8; | ||
841 | chip->ecc.bytes = 16; | ||
842 | } | ||
843 | |||
844 | priv->bufnum_mask = 1; | ||
845 | break; | ||
846 | |||
847 | default: | ||
848 | dev_err(priv->dev, "bad csor %#x: bad page size\n", csor); | ||
849 | return -ENODEV; | ||
850 | } | ||
851 | |||
852 | /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */ | ||
853 | if (csor & CSOR_NAND_ECC_DEC_EN) { | ||
854 | chip->ecc.mode = NAND_ECC_HW; | ||
855 | chip->ecc.layout = layout; | ||
856 | } else { | ||
857 | chip->ecc.mode = NAND_ECC_SOFT; | ||
858 | } | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) | ||
864 | { | ||
865 | nand_release(&priv->mtd); | ||
866 | |||
867 | kfree(priv->mtd.name); | ||
868 | |||
869 | if (priv->vbase) | ||
870 | iounmap(priv->vbase); | ||
871 | |||
872 | ifc_nand_ctrl->chips[priv->bank] = NULL; | ||
873 | dev_set_drvdata(priv->dev, NULL); | ||
874 | kfree(priv); | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, | ||
880 | phys_addr_t addr) | ||
881 | { | ||
882 | u32 cspr = in_be32(&ifc->cspr_cs[bank].cspr); | ||
883 | |||
884 | if (!(cspr & CSPR_V)) | ||
885 | return 0; | ||
886 | if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND) | ||
887 | return 0; | ||
888 | |||
889 | return (cspr & CSPR_BA) == convert_ifc_address(addr); | ||
890 | } | ||
891 | |||
892 | static DEFINE_MUTEX(fsl_ifc_nand_mutex); | ||
893 | |||
894 | static int __devinit fsl_ifc_nand_probe(struct platform_device *dev) | ||
895 | { | ||
896 | struct fsl_ifc_regs __iomem *ifc; | ||
897 | struct fsl_ifc_mtd *priv; | ||
898 | struct resource res; | ||
899 | static const char *part_probe_types[] | ||
900 | = { "cmdlinepart", "RedBoot", "ofpart", NULL }; | ||
901 | int ret; | ||
902 | int bank; | ||
903 | struct device_node *node = dev->dev.of_node; | ||
904 | struct mtd_part_parser_data ppdata; | ||
905 | |||
906 | ppdata.of_node = dev->dev.of_node; | ||
907 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) | ||
908 | return -ENODEV; | ||
909 | ifc = fsl_ifc_ctrl_dev->regs; | ||
910 | |||
911 | /* get, allocate and map the memory resource */ | ||
912 | ret = of_address_to_resource(node, 0, &res); | ||
913 | if (ret) { | ||
914 | dev_err(&dev->dev, "%s: failed to get resource\n", __func__); | ||
915 | return ret; | ||
916 | } | ||
917 | |||
918 | /* find which chip select it is connected to */ | ||
919 | for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) { | ||
920 | if (match_bank(ifc, bank, res.start)) | ||
921 | break; | ||
922 | } | ||
923 | |||
924 | if (bank >= FSL_IFC_BANK_COUNT) { | ||
925 | dev_err(&dev->dev, "%s: address did not match any chip selects\n", | ||
926 | __func__); | ||
927 | return -ENODEV; | ||
928 | } | ||
929 | |||
930 | priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); | ||
931 | if (!priv) | ||
932 | return -ENOMEM; | ||
933 | |||
934 | mutex_lock(&fsl_ifc_nand_mutex); | ||
935 | if (!fsl_ifc_ctrl_dev->nand) { | ||
936 | ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL); | ||
937 | if (!ifc_nand_ctrl) { | ||
938 | dev_err(&dev->dev, "failed to allocate memory\n"); | ||
939 | mutex_unlock(&fsl_ifc_nand_mutex); | ||
940 | return -ENOMEM; | ||
941 | } | ||
942 | |||
943 | ifc_nand_ctrl->read_bytes = 0; | ||
944 | ifc_nand_ctrl->index = 0; | ||
945 | ifc_nand_ctrl->addr = NULL; | ||
946 | fsl_ifc_ctrl_dev->nand = ifc_nand_ctrl; | ||
947 | |||
948 | spin_lock_init(&ifc_nand_ctrl->controller.lock); | ||
949 | init_waitqueue_head(&ifc_nand_ctrl->controller.wq); | ||
950 | } else { | ||
951 | ifc_nand_ctrl = fsl_ifc_ctrl_dev->nand; | ||
952 | } | ||
953 | mutex_unlock(&fsl_ifc_nand_mutex); | ||
954 | |||
955 | ifc_nand_ctrl->chips[bank] = priv; | ||
956 | priv->bank = bank; | ||
957 | priv->ctrl = fsl_ifc_ctrl_dev; | ||
958 | priv->dev = &dev->dev; | ||
959 | |||
960 | priv->vbase = ioremap(res.start, resource_size(&res)); | ||
961 | if (!priv->vbase) { | ||
962 | dev_err(priv->dev, "%s: failed to map chip region\n", __func__); | ||
963 | ret = -ENOMEM; | ||
964 | goto err; | ||
965 | } | ||
966 | |||
967 | dev_set_drvdata(priv->dev, priv); | ||
968 | |||
969 | out_be32(&ifc->ifc_nand.nand_evter_en, | ||
970 | IFC_NAND_EVTER_EN_OPC_EN | | ||
971 | IFC_NAND_EVTER_EN_FTOER_EN | | ||
972 | IFC_NAND_EVTER_EN_WPER_EN); | ||
973 | |||
974 | /* enable NAND Machine Interrupts */ | ||
975 | out_be32(&ifc->ifc_nand.nand_evter_intr_en, | ||
976 | IFC_NAND_EVTER_INTR_OPCIR_EN | | ||
977 | IFC_NAND_EVTER_INTR_FTOERIR_EN | | ||
978 | IFC_NAND_EVTER_INTR_WPERIR_EN); | ||
979 | |||
980 | priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start); | ||
981 | if (!priv->mtd.name) { | ||
982 | ret = -ENOMEM; | ||
983 | goto err; | ||
984 | } | ||
985 | |||
986 | ret = fsl_ifc_chip_init(priv); | ||
987 | if (ret) | ||
988 | goto err; | ||
989 | |||
990 | ret = nand_scan_ident(&priv->mtd, 1, NULL); | ||
991 | if (ret) | ||
992 | goto err; | ||
993 | |||
994 | ret = fsl_ifc_chip_init_tail(&priv->mtd); | ||
995 | if (ret) | ||
996 | goto err; | ||
997 | |||
998 | ret = nand_scan_tail(&priv->mtd); | ||
999 | if (ret) | ||
1000 | goto err; | ||
1001 | |||
1002 | /* First look for RedBoot table or partitions on the command | ||
1003 | * line, these take precedence over device tree information */ | ||
1004 | mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata, | ||
1005 | NULL, 0); | ||
1006 | |||
1007 | dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n", | ||
1008 | (unsigned long long)res.start, priv->bank); | ||
1009 | return 0; | ||
1010 | |||
1011 | err: | ||
1012 | fsl_ifc_chip_remove(priv); | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | static int fsl_ifc_nand_remove(struct platform_device *dev) | ||
1017 | { | ||
1018 | struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev); | ||
1019 | |||
1020 | fsl_ifc_chip_remove(priv); | ||
1021 | |||
1022 | mutex_lock(&fsl_ifc_nand_mutex); | ||
1023 | ifc_nand_ctrl->counter--; | ||
1024 | if (!ifc_nand_ctrl->counter) { | ||
1025 | fsl_ifc_ctrl_dev->nand = NULL; | ||
1026 | kfree(ifc_nand_ctrl); | ||
1027 | } | ||
1028 | mutex_unlock(&fsl_ifc_nand_mutex); | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static const struct of_device_id fsl_ifc_nand_match[] = { | ||
1034 | { | ||
1035 | .compatible = "fsl,ifc-nand", | ||
1036 | }, | ||
1037 | {} | ||
1038 | }; | ||
1039 | |||
1040 | static struct platform_driver fsl_ifc_nand_driver = { | ||
1041 | .driver = { | ||
1042 | .name = "fsl,ifc-nand", | ||
1043 | .owner = THIS_MODULE, | ||
1044 | .of_match_table = fsl_ifc_nand_match, | ||
1045 | }, | ||
1046 | .probe = fsl_ifc_nand_probe, | ||
1047 | .remove = fsl_ifc_nand_remove, | ||
1048 | }; | ||
1049 | |||
1050 | static int __init fsl_ifc_nand_init(void) | ||
1051 | { | ||
1052 | int ret; | ||
1053 | |||
1054 | ret = platform_driver_register(&fsl_ifc_nand_driver); | ||
1055 | if (ret) | ||
1056 | printk(KERN_ERR "fsl-ifc: Failed to register platform" | ||
1057 | "driver\n"); | ||
1058 | |||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | static void __exit fsl_ifc_nand_exit(void) | ||
1063 | { | ||
1064 | platform_driver_unregister(&fsl_ifc_nand_driver); | ||
1065 | } | ||
1066 | |||
1067 | module_init(fsl_ifc_nand_init); | ||
1068 | module_exit(fsl_ifc_nand_exit); | ||
1069 | |||
1070 | MODULE_LICENSE("GPL"); | ||
1071 | MODULE_AUTHOR("Freescale"); | ||
1072 | MODULE_DESCRIPTION("Freescale Integrated Flash Controller MTD NAND driver"); | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index c34dab17682e..e8ea7107932e 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
@@ -835,7 +835,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) | |||
835 | | BM_GPMI_CTRL0_ADDRESS_INCREMENT | 835 | | BM_GPMI_CTRL0_ADDRESS_INCREMENT |
836 | | BF_GPMI_CTRL0_XFER_COUNT(this->command_length); | 836 | | BF_GPMI_CTRL0_XFER_COUNT(this->command_length); |
837 | pio[1] = pio[2] = 0; | 837 | pio[1] = pio[2] = 0; |
838 | desc = channel->device->device_prep_slave_sg(channel, | 838 | desc = dmaengine_prep_slave_sg(channel, |
839 | (struct scatterlist *)pio, | 839 | (struct scatterlist *)pio, |
840 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); | 840 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); |
841 | if (!desc) { | 841 | if (!desc) { |
@@ -848,7 +848,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) | |||
848 | 848 | ||
849 | sg_init_one(sgl, this->cmd_buffer, this->command_length); | 849 | sg_init_one(sgl, this->cmd_buffer, this->command_length); |
850 | dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); | 850 | dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); |
851 | desc = channel->device->device_prep_slave_sg(channel, | 851 | desc = dmaengine_prep_slave_sg(channel, |
852 | sgl, 1, DMA_MEM_TO_DEV, | 852 | sgl, 1, DMA_MEM_TO_DEV, |
853 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 853 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
854 | 854 | ||
@@ -882,8 +882,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) | |||
882 | | BF_GPMI_CTRL0_ADDRESS(address) | 882 | | BF_GPMI_CTRL0_ADDRESS(address) |
883 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); | 883 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); |
884 | pio[1] = 0; | 884 | pio[1] = 0; |
885 | desc = channel->device->device_prep_slave_sg(channel, | 885 | desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio, |
886 | (struct scatterlist *)pio, | ||
887 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); | 886 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); |
888 | if (!desc) { | 887 | if (!desc) { |
889 | pr_err("step 1 error\n"); | 888 | pr_err("step 1 error\n"); |
@@ -892,7 +891,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) | |||
892 | 891 | ||
893 | /* [2] send DMA request */ | 892 | /* [2] send DMA request */ |
894 | prepare_data_dma(this, DMA_TO_DEVICE); | 893 | prepare_data_dma(this, DMA_TO_DEVICE); |
895 | desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, | 894 | desc = dmaengine_prep_slave_sg(channel, &this->data_sgl, |
896 | 1, DMA_MEM_TO_DEV, | 895 | 1, DMA_MEM_TO_DEV, |
897 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 896 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
898 | if (!desc) { | 897 | if (!desc) { |
@@ -919,7 +918,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) | |||
919 | | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA) | 918 | | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA) |
920 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); | 919 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); |
921 | pio[1] = 0; | 920 | pio[1] = 0; |
922 | desc = channel->device->device_prep_slave_sg(channel, | 921 | desc = dmaengine_prep_slave_sg(channel, |
923 | (struct scatterlist *)pio, | 922 | (struct scatterlist *)pio, |
924 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); | 923 | ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); |
925 | if (!desc) { | 924 | if (!desc) { |
@@ -929,7 +928,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) | |||
929 | 928 | ||
930 | /* [2] : send DMA request */ | 929 | /* [2] : send DMA request */ |
931 | prepare_data_dma(this, DMA_FROM_DEVICE); | 930 | prepare_data_dma(this, DMA_FROM_DEVICE); |
932 | desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, | 931 | desc = dmaengine_prep_slave_sg(channel, &this->data_sgl, |
933 | 1, DMA_DEV_TO_MEM, | 932 | 1, DMA_DEV_TO_MEM, |
934 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 933 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
935 | if (!desc) { | 934 | if (!desc) { |
@@ -976,7 +975,7 @@ int gpmi_send_page(struct gpmi_nand_data *this, | |||
976 | pio[4] = payload; | 975 | pio[4] = payload; |
977 | pio[5] = auxiliary; | 976 | pio[5] = auxiliary; |
978 | 977 | ||
979 | desc = channel->device->device_prep_slave_sg(channel, | 978 | desc = dmaengine_prep_slave_sg(channel, |
980 | (struct scatterlist *)pio, | 979 | (struct scatterlist *)pio, |
981 | ARRAY_SIZE(pio), DMA_TRANS_NONE, | 980 | ARRAY_SIZE(pio), DMA_TRANS_NONE, |
982 | DMA_CTRL_ACK); | 981 | DMA_CTRL_ACK); |
@@ -1012,7 +1011,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, | |||
1012 | | BF_GPMI_CTRL0_ADDRESS(address) | 1011 | | BF_GPMI_CTRL0_ADDRESS(address) |
1013 | | BF_GPMI_CTRL0_XFER_COUNT(0); | 1012 | | BF_GPMI_CTRL0_XFER_COUNT(0); |
1014 | pio[1] = 0; | 1013 | pio[1] = 0; |
1015 | desc = channel->device->device_prep_slave_sg(channel, | 1014 | desc = dmaengine_prep_slave_sg(channel, |
1016 | (struct scatterlist *)pio, 2, | 1015 | (struct scatterlist *)pio, 2, |
1017 | DMA_TRANS_NONE, 0); | 1016 | DMA_TRANS_NONE, 0); |
1018 | if (!desc) { | 1017 | if (!desc) { |
@@ -1041,7 +1040,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, | |||
1041 | pio[3] = geo->page_size; | 1040 | pio[3] = geo->page_size; |
1042 | pio[4] = payload; | 1041 | pio[4] = payload; |
1043 | pio[5] = auxiliary; | 1042 | pio[5] = auxiliary; |
1044 | desc = channel->device->device_prep_slave_sg(channel, | 1043 | desc = dmaengine_prep_slave_sg(channel, |
1045 | (struct scatterlist *)pio, | 1044 | (struct scatterlist *)pio, |
1046 | ARRAY_SIZE(pio), DMA_TRANS_NONE, | 1045 | ARRAY_SIZE(pio), DMA_TRANS_NONE, |
1047 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 1046 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
@@ -1062,7 +1061,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, | |||
1062 | | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); | 1061 | | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); |
1063 | pio[1] = 0; | 1062 | pio[1] = 0; |
1064 | pio[2] = 0; /* clear GPMI_HW_GPMI_ECCCTRL, disable the BCH. */ | 1063 | pio[2] = 0; /* clear GPMI_HW_GPMI_ECCCTRL, disable the BCH. */ |
1065 | desc = channel->device->device_prep_slave_sg(channel, | 1064 | desc = dmaengine_prep_slave_sg(channel, |
1066 | (struct scatterlist *)pio, 3, | 1065 | (struct scatterlist *)pio, 3, |
1067 | DMA_TRANS_NONE, | 1066 | DMA_TRANS_NONE, |
1068 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 1067 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 772ad2966619..91467bb03634 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | menuconfig MTD_ONENAND | 1 | menuconfig MTD_ONENAND |
2 | tristate "OneNAND Device Support" | 2 | tristate "OneNAND Device Support" |
3 | depends on MTD | 3 | depends on MTD |
4 | depends on HAS_IOMEM | ||
4 | help | 5 | help |
5 | This enables support for accessing all type of OneNAND flash | 6 | This enables support for accessing all type of OneNAND flash |
6 | devices. For further information see | 7 | devices. For further information see |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 115749f20f9e..0fde9fc7d2e5 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -945,12 +945,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
945 | goto out_free; | 945 | goto out_free; |
946 | 946 | ||
947 | err = -ENOMEM; | 947 | err = -ENOMEM; |
948 | ubi->peb_buf1 = vmalloc(ubi->peb_size); | 948 | ubi->peb_buf = vmalloc(ubi->peb_size); |
949 | if (!ubi->peb_buf1) | 949 | if (!ubi->peb_buf) |
950 | goto out_free; | ||
951 | |||
952 | ubi->peb_buf2 = vmalloc(ubi->peb_size); | ||
953 | if (!ubi->peb_buf2) | ||
954 | goto out_free; | 950 | goto out_free; |
955 | 951 | ||
956 | err = ubi_debugging_init_dev(ubi); | 952 | err = ubi_debugging_init_dev(ubi); |
@@ -1029,8 +1025,7 @@ out_detach: | |||
1029 | out_debugging: | 1025 | out_debugging: |
1030 | ubi_debugging_exit_dev(ubi); | 1026 | ubi_debugging_exit_dev(ubi); |
1031 | out_free: | 1027 | out_free: |
1032 | vfree(ubi->peb_buf1); | 1028 | vfree(ubi->peb_buf); |
1033 | vfree(ubi->peb_buf2); | ||
1034 | if (ref) | 1029 | if (ref) |
1035 | put_device(&ubi->dev); | 1030 | put_device(&ubi->dev); |
1036 | else | 1031 | else |
@@ -1101,8 +1096,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
1101 | vfree(ubi->vtbl); | 1096 | vfree(ubi->vtbl); |
1102 | put_mtd_device(ubi->mtd); | 1097 | put_mtd_device(ubi->mtd); |
1103 | ubi_debugging_exit_dev(ubi); | 1098 | ubi_debugging_exit_dev(ubi); |
1104 | vfree(ubi->peb_buf1); | 1099 | vfree(ubi->peb_buf); |
1105 | vfree(ubi->peb_buf2); | ||
1106 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); | 1100 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); |
1107 | put_device(&ubi->dev); | 1101 | put_device(&ubi->dev); |
1108 | return 0; | 1102 | return 0; |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index cd26da8ad225..2455d620d96b 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -529,18 +529,18 @@ retry: | |||
529 | 529 | ||
530 | data_size = offset + len; | 530 | data_size = offset + len; |
531 | mutex_lock(&ubi->buf_mutex); | 531 | mutex_lock(&ubi->buf_mutex); |
532 | memset(ubi->peb_buf1 + offset, 0xFF, len); | 532 | memset(ubi->peb_buf + offset, 0xFF, len); |
533 | 533 | ||
534 | /* Read everything before the area where the write failure happened */ | 534 | /* Read everything before the area where the write failure happened */ |
535 | if (offset > 0) { | 535 | if (offset > 0) { |
536 | err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset); | 536 | err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset); |
537 | if (err && err != UBI_IO_BITFLIPS) | 537 | if (err && err != UBI_IO_BITFLIPS) |
538 | goto out_unlock; | 538 | goto out_unlock; |
539 | } | 539 | } |
540 | 540 | ||
541 | memcpy(ubi->peb_buf1 + offset, buf, len); | 541 | memcpy(ubi->peb_buf + offset, buf, len); |
542 | 542 | ||
543 | err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size); | 543 | err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); |
544 | if (err) { | 544 | if (err) { |
545 | mutex_unlock(&ubi->buf_mutex); | 545 | mutex_unlock(&ubi->buf_mutex); |
546 | goto write_error; | 546 | goto write_error; |
@@ -979,7 +979,7 @@ static int is_error_sane(int err) | |||
979 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this | 979 | * physical eraseblock @to. The @vid_hdr buffer may be changed by this |
980 | * function. Returns: | 980 | * function. Returns: |
981 | * o %0 in case of success; | 981 | * o %0 in case of success; |
982 | * o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_CANCEL_BITFLIPS, etc; | 982 | * o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_TARGET_BITFLIPS, etc; |
983 | * o a negative error code in case of failure. | 983 | * o a negative error code in case of failure. |
984 | */ | 984 | */ |
985 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | 985 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, |
@@ -1053,13 +1053,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1053 | 1053 | ||
1054 | /* | 1054 | /* |
1055 | * OK, now the LEB is locked and we can safely start moving it. Since | 1055 | * OK, now the LEB is locked and we can safely start moving it. Since |
1056 | * this function utilizes the @ubi->peb_buf1 buffer which is shared | 1056 | * this function utilizes the @ubi->peb_buf buffer which is shared |
1057 | * with some other functions - we lock the buffer by taking the | 1057 | * with some other functions - we lock the buffer by taking the |
1058 | * @ubi->buf_mutex. | 1058 | * @ubi->buf_mutex. |
1059 | */ | 1059 | */ |
1060 | mutex_lock(&ubi->buf_mutex); | 1060 | mutex_lock(&ubi->buf_mutex); |
1061 | dbg_wl("read %d bytes of data", aldata_size); | 1061 | dbg_wl("read %d bytes of data", aldata_size); |
1062 | err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size); | 1062 | err = ubi_io_read_data(ubi, ubi->peb_buf, from, 0, aldata_size); |
1063 | if (err && err != UBI_IO_BITFLIPS) { | 1063 | if (err && err != UBI_IO_BITFLIPS) { |
1064 | ubi_warn("error %d while reading data from PEB %d", | 1064 | ubi_warn("error %d while reading data from PEB %d", |
1065 | err, from); | 1065 | err, from); |
@@ -1079,10 +1079,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1079 | */ | 1079 | */ |
1080 | if (vid_hdr->vol_type == UBI_VID_DYNAMIC) | 1080 | if (vid_hdr->vol_type == UBI_VID_DYNAMIC) |
1081 | aldata_size = data_size = | 1081 | aldata_size = data_size = |
1082 | ubi_calc_data_len(ubi, ubi->peb_buf1, data_size); | 1082 | ubi_calc_data_len(ubi, ubi->peb_buf, data_size); |
1083 | 1083 | ||
1084 | cond_resched(); | 1084 | cond_resched(); |
1085 | crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size); | 1085 | crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size); |
1086 | cond_resched(); | 1086 | cond_resched(); |
1087 | 1087 | ||
1088 | /* | 1088 | /* |
@@ -1116,12 +1116,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1116 | if (is_error_sane(err)) | 1116 | if (is_error_sane(err)) |
1117 | err = MOVE_TARGET_RD_ERR; | 1117 | err = MOVE_TARGET_RD_ERR; |
1118 | } else | 1118 | } else |
1119 | err = MOVE_CANCEL_BITFLIPS; | 1119 | err = MOVE_TARGET_BITFLIPS; |
1120 | goto out_unlock_buf; | 1120 | goto out_unlock_buf; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | if (data_size > 0) { | 1123 | if (data_size > 0) { |
1124 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); | 1124 | err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size); |
1125 | if (err) { | 1125 | if (err) { |
1126 | if (err == -EIO) | 1126 | if (err == -EIO) |
1127 | err = MOVE_TARGET_WR_ERR; | 1127 | err = MOVE_TARGET_WR_ERR; |
@@ -1134,8 +1134,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1134 | * We've written the data and are going to read it back to make | 1134 | * We've written the data and are going to read it back to make |
1135 | * sure it was written correctly. | 1135 | * sure it was written correctly. |
1136 | */ | 1136 | */ |
1137 | 1137 | memset(ubi->peb_buf, 0xFF, aldata_size); | |
1138 | err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); | 1138 | err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size); |
1139 | if (err) { | 1139 | if (err) { |
1140 | if (err != UBI_IO_BITFLIPS) { | 1140 | if (err != UBI_IO_BITFLIPS) { |
1141 | ubi_warn("error %d while reading data back " | 1141 | ubi_warn("error %d while reading data back " |
@@ -1143,13 +1143,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1143 | if (is_error_sane(err)) | 1143 | if (is_error_sane(err)) |
1144 | err = MOVE_TARGET_RD_ERR; | 1144 | err = MOVE_TARGET_RD_ERR; |
1145 | } else | 1145 | } else |
1146 | err = MOVE_CANCEL_BITFLIPS; | 1146 | err = MOVE_TARGET_BITFLIPS; |
1147 | goto out_unlock_buf; | 1147 | goto out_unlock_buf; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | cond_resched(); | 1150 | cond_resched(); |
1151 | 1151 | ||
1152 | if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) { | 1152 | if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) { |
1153 | ubi_warn("read data back from PEB %d and it is " | 1153 | ubi_warn("read data back from PEB %d and it is " |
1154 | "different", to); | 1154 | "different", to); |
1155 | err = -EINVAL; | 1155 | err = -EINVAL; |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 5cde4e5ca3e5..43f1a0011a55 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -431,11 +431,11 @@ static int torture_peb(struct ubi_device *ubi, int pnum) | |||
431 | goto out; | 431 | goto out; |
432 | 432 | ||
433 | /* Make sure the PEB contains only 0xFF bytes */ | 433 | /* Make sure the PEB contains only 0xFF bytes */ |
434 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); | 434 | err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size); |
435 | if (err) | 435 | if (err) |
436 | goto out; | 436 | goto out; |
437 | 437 | ||
438 | err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size); | 438 | err = ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->peb_size); |
439 | if (err == 0) { | 439 | if (err == 0) { |
440 | ubi_err("erased PEB %d, but a non-0xFF byte found", | 440 | ubi_err("erased PEB %d, but a non-0xFF byte found", |
441 | pnum); | 441 | pnum); |
@@ -444,17 +444,17 @@ static int torture_peb(struct ubi_device *ubi, int pnum) | |||
444 | } | 444 | } |
445 | 445 | ||
446 | /* Write a pattern and check it */ | 446 | /* Write a pattern and check it */ |
447 | memset(ubi->peb_buf1, patterns[i], ubi->peb_size); | 447 | memset(ubi->peb_buf, patterns[i], ubi->peb_size); |
448 | err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); | 448 | err = ubi_io_write(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size); |
449 | if (err) | 449 | if (err) |
450 | goto out; | 450 | goto out; |
451 | 451 | ||
452 | memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size); | 452 | memset(ubi->peb_buf, ~patterns[i], ubi->peb_size); |
453 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); | 453 | err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size); |
454 | if (err) | 454 | if (err) |
455 | goto out; | 455 | goto out; |
456 | 456 | ||
457 | err = ubi_check_pattern(ubi->peb_buf1, patterns[i], | 457 | err = ubi_check_pattern(ubi->peb_buf, patterns[i], |
458 | ubi->peb_size); | 458 | ubi->peb_size); |
459 | if (err == 0) { | 459 | if (err == 0) { |
460 | ubi_err("pattern %x checking failed for PEB %d", | 460 | ubi_err("pattern %x checking failed for PEB %d", |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 0cb17d936b5a..12c43b44f815 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -789,9 +789,9 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
789 | int err; | 789 | int err; |
790 | 790 | ||
791 | mutex_lock(&ubi->buf_mutex); | 791 | mutex_lock(&ubi->buf_mutex); |
792 | memset(ubi->peb_buf1, 0x00, ubi->leb_size); | 792 | memset(ubi->peb_buf, 0x00, ubi->leb_size); |
793 | 793 | ||
794 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start, | 794 | err = ubi_io_read(ubi, ubi->peb_buf, pnum, ubi->leb_start, |
795 | ubi->leb_size); | 795 | ubi->leb_size); |
796 | if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) { | 796 | if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) { |
797 | /* | 797 | /* |
@@ -808,7 +808,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
808 | if (err) | 808 | if (err) |
809 | goto out_unlock; | 809 | goto out_unlock; |
810 | 810 | ||
811 | if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) | 811 | if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size)) |
812 | goto out_unlock; | 812 | goto out_unlock; |
813 | 813 | ||
814 | ubi_err("PEB %d contains corrupted VID header, and the data does not " | 814 | ubi_err("PEB %d contains corrupted VID header, and the data does not " |
@@ -818,7 +818,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
818 | dbg_msg("hexdump of PEB %d offset %d, length %d", | 818 | dbg_msg("hexdump of PEB %d offset %d, length %d", |
819 | pnum, ubi->leb_start, ubi->leb_size); | 819 | pnum, ubi->leb_start, ubi->leb_size); |
820 | ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | 820 | ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, |
821 | ubi->peb_buf1, ubi->leb_size, 1); | 821 | ubi->peb_buf, ubi->leb_size, 1); |
822 | err = 1; | 822 | err = 1; |
823 | 823 | ||
824 | out_unlock: | 824 | out_unlock: |
@@ -1174,7 +1174,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
1174 | 1174 | ||
1175 | ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); | 1175 | ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); |
1176 | if (!ech) | 1176 | if (!ech) |
1177 | goto out_slab; | 1177 | goto out_si; |
1178 | 1178 | ||
1179 | vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); | 1179 | vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); |
1180 | if (!vidh) | 1180 | if (!vidh) |
@@ -1235,8 +1235,6 @@ out_vidh: | |||
1235 | ubi_free_vid_hdr(ubi, vidh); | 1235 | ubi_free_vid_hdr(ubi, vidh); |
1236 | out_ech: | 1236 | out_ech: |
1237 | kfree(ech); | 1237 | kfree(ech); |
1238 | out_slab: | ||
1239 | kmem_cache_destroy(si->scan_leb_slab); | ||
1240 | out_si: | 1238 | out_si: |
1241 | ubi_scan_destroy_si(si); | 1239 | ubi_scan_destroy_si(si); |
1242 | return ERR_PTR(err); | 1240 | return ERR_PTR(err); |
@@ -1325,7 +1323,9 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) | |||
1325 | } | 1323 | } |
1326 | } | 1324 | } |
1327 | 1325 | ||
1328 | kmem_cache_destroy(si->scan_leb_slab); | 1326 | if (si->scan_leb_slab) |
1327 | kmem_cache_destroy(si->scan_leb_slab); | ||
1328 | |||
1329 | kfree(si); | 1329 | kfree(si); |
1330 | } | 1330 | } |
1331 | 1331 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index d51d75d34446..b162790790a9 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -118,7 +118,7 @@ enum { | |||
118 | * PEB | 118 | * PEB |
119 | * MOVE_TARGET_WR_ERR: canceled because there was a write error to the target | 119 | * MOVE_TARGET_WR_ERR: canceled because there was a write error to the target |
120 | * PEB | 120 | * PEB |
121 | * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the | 121 | * MOVE_TARGET_BITFLIPS: canceled because a bit-flip was detected in the |
122 | * target PEB | 122 | * target PEB |
123 | * MOVE_RETRY: retry scrubbing the PEB | 123 | * MOVE_RETRY: retry scrubbing the PEB |
124 | */ | 124 | */ |
@@ -127,7 +127,7 @@ enum { | |||
127 | MOVE_SOURCE_RD_ERR, | 127 | MOVE_SOURCE_RD_ERR, |
128 | MOVE_TARGET_RD_ERR, | 128 | MOVE_TARGET_RD_ERR, |
129 | MOVE_TARGET_WR_ERR, | 129 | MOVE_TARGET_WR_ERR, |
130 | MOVE_CANCEL_BITFLIPS, | 130 | MOVE_TARGET_BITFLIPS, |
131 | MOVE_RETRY, | 131 | MOVE_RETRY, |
132 | }; | 132 | }; |
133 | 133 | ||
@@ -387,9 +387,8 @@ struct ubi_wl_entry; | |||
387 | * time (MTD write buffer size) | 387 | * time (MTD write buffer size) |
388 | * @mtd: MTD device descriptor | 388 | * @mtd: MTD device descriptor |
389 | * | 389 | * |
390 | * @peb_buf1: a buffer of PEB size used for different purposes | 390 | * @peb_buf: a buffer of PEB size used for different purposes |
391 | * @peb_buf2: another buffer of PEB size used for different purposes | 391 | * @buf_mutex: protects @peb_buf |
392 | * @buf_mutex: protects @peb_buf1 and @peb_buf2 | ||
393 | * @ckvol_mutex: serializes static volume checking when opening | 392 | * @ckvol_mutex: serializes static volume checking when opening |
394 | * | 393 | * |
395 | * @dbg: debugging information for this UBI device | 394 | * @dbg: debugging information for this UBI device |
@@ -471,8 +470,7 @@ struct ubi_device { | |||
471 | int max_write_size; | 470 | int max_write_size; |
472 | struct mtd_info *mtd; | 471 | struct mtd_info *mtd; |
473 | 472 | ||
474 | void *peb_buf1; | 473 | void *peb_buf; |
475 | void *peb_buf2; | ||
476 | struct mutex buf_mutex; | 474 | struct mutex buf_mutex; |
477 | struct mutex ckvol_mutex; | 475 | struct mutex ckvol_mutex; |
478 | 476 | ||
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 0696e36b0539..7c1a9bf8ac86 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -350,18 +350,19 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e) | |||
350 | /** | 350 | /** |
351 | * find_wl_entry - find wear-leveling entry closest to certain erase counter. | 351 | * find_wl_entry - find wear-leveling entry closest to certain erase counter. |
352 | * @root: the RB-tree where to look for | 352 | * @root: the RB-tree where to look for |
353 | * @max: highest possible erase counter | 353 | * @diff: maximum possible difference from the smallest erase counter |
354 | * | 354 | * |
355 | * This function looks for a wear leveling entry with erase counter closest to | 355 | * This function looks for a wear leveling entry with erase counter closest to |
356 | * @max and less than @max. | 356 | * min + @diff, where min is the smallest erase counter. |
357 | */ | 357 | */ |
358 | static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max) | 358 | static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff) |
359 | { | 359 | { |
360 | struct rb_node *p; | 360 | struct rb_node *p; |
361 | struct ubi_wl_entry *e; | 361 | struct ubi_wl_entry *e; |
362 | int max; | ||
362 | 363 | ||
363 | e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb); | 364 | e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb); |
364 | max += e->ec; | 365 | max = e->ec + diff; |
365 | 366 | ||
366 | p = root->rb_node; | 367 | p = root->rb_node; |
367 | while (p) { | 368 | while (p) { |
@@ -389,7 +390,7 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max) | |||
389 | */ | 390 | */ |
390 | int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) | 391 | int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) |
391 | { | 392 | { |
392 | int err, medium_ec; | 393 | int err; |
393 | struct ubi_wl_entry *e, *first, *last; | 394 | struct ubi_wl_entry *e, *first, *last; |
394 | 395 | ||
395 | ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM || | 396 | ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM || |
@@ -427,7 +428,7 @@ retry: | |||
427 | * For unknown data we pick a physical eraseblock with medium | 428 | * For unknown data we pick a physical eraseblock with medium |
428 | * erase counter. But we by no means can pick a physical | 429 | * erase counter. But we by no means can pick a physical |
429 | * eraseblock with erase counter greater or equivalent than the | 430 | * eraseblock with erase counter greater or equivalent than the |
430 | * lowest erase counter plus %WL_FREE_MAX_DIFF. | 431 | * lowest erase counter plus %WL_FREE_MAX_DIFF/2. |
431 | */ | 432 | */ |
432 | first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, | 433 | first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, |
433 | u.rb); | 434 | u.rb); |
@@ -436,10 +437,8 @@ retry: | |||
436 | if (last->ec - first->ec < WL_FREE_MAX_DIFF) | 437 | if (last->ec - first->ec < WL_FREE_MAX_DIFF) |
437 | e = rb_entry(ubi->free.rb_node, | 438 | e = rb_entry(ubi->free.rb_node, |
438 | struct ubi_wl_entry, u.rb); | 439 | struct ubi_wl_entry, u.rb); |
439 | else { | 440 | else |
440 | medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; | 441 | e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2); |
441 | e = find_wl_entry(&ubi->free, medium_ec); | ||
442 | } | ||
443 | break; | 442 | break; |
444 | case UBI_SHORTTERM: | 443 | case UBI_SHORTTERM: |
445 | /* | 444 | /* |
@@ -799,7 +798,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | |||
799 | scrubbing = 1; | 798 | scrubbing = 1; |
800 | goto out_not_moved; | 799 | goto out_not_moved; |
801 | } | 800 | } |
802 | if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR || | 801 | if (err == MOVE_TARGET_BITFLIPS || err == MOVE_TARGET_WR_ERR || |
803 | err == MOVE_TARGET_RD_ERR) { | 802 | err == MOVE_TARGET_RD_ERR) { |
804 | /* | 803 | /* |
805 | * Target PEB had bit-flips or write error - torture it. | 804 | * Target PEB had bit-flips or write error - torture it. |