diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 17:56:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 17:56:26 -0400 |
commit | 22ae77bc7ac115b9d518d5cbc13d39317079b2b0 (patch) | |
tree | 574b7af678c0b1ad2c891ac5066292746788ece8 /drivers/mtd/nand | |
parent | e379ec7c42343c6b6ef06a98de7c94db41c1423e (diff) | |
parent | 30bbf1406714cf464c56e96e4ad6a291907f5023 (diff) |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (53 commits)
[MTD] struct device - replace bus_id with dev_name(), dev_set_name()
[MTD] [NOR] Fixup for Numonyx M29W128 chips
[MTD] mtdpart: Make ecc_stats more realistic.
powerpc/85xx: TQM8548: Update DTS file for multi-chip support
powerpc: NAND: FSL UPM: document new bindings
[MTD] [NAND] FSL-UPM: Add wait flags to support board/chip specific delays
[MTD] [NAND] FSL-UPM: add multi chip support
[MTD] [NOR] Add device parent info to physmap_of
[MTD] [NAND] Add support for NAND on the Socrates board
[MTD] [NAND] Add support for 4KiB pages.
[MTD] sysfs support should not depend on CONFIG_PROC_FS
[MTD] [NAND] Add parent info for CAFÉ controller
[MTD] support driver model updates
[MTD] driver model updates (part 2)
[MTD] driver model updates
[MTD] [NAND] move gen_nand's probe function to .devinit.text
[MTD] [MAPS] move sa1100 flash's probe function to .devinit.text
[MTD] fix use after free in register_mtd_blktrans
[MTD] [MAPS] Drop now unused sharpsl-flash map
[MTD] ofpart: Check name property to determine partition nodes.
...
Manually fix trivial conflict in drivers/mtd/maps/Makefile
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 21 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/bf5xx_nand.c | 18 | ||||
-rw-r--r-- | drivers/mtd/nand/cafe_nand.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 570 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_upm.c | 119 | ||||
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 125 | ||||
-rw-r--r-- | drivers/mtd/nand/plat_nand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 119 | ||||
-rw-r--r-- | drivers/mtd/nand/sh_flctl.c | 18 | ||||
-rw-r--r-- | drivers/mtd/nand/socrates_nand.c | 325 | ||||
-rw-r--r-- | drivers/mtd/nand/txx9ndfmc.c | 428 |
13 files changed, 1695 insertions, 55 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 2ff88791cebc..890936d0275e 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -334,7 +334,7 @@ config MTD_NAND_ATMEL_ECC_NONE | |||
334 | endchoice | 334 | endchoice |
335 | 335 | ||
336 | config MTD_NAND_PXA3xx | 336 | config MTD_NAND_PXA3xx |
337 | bool "Support for NAND flash devices on PXA3xx" | 337 | tristate "Support for NAND flash devices on PXA3xx" |
338 | depends on MTD_NAND && PXA3xx | 338 | depends on MTD_NAND && PXA3xx |
339 | help | 339 | help |
340 | This enables the driver for the NAND flash device found on | 340 | This enables the driver for the NAND flash device found on |
@@ -427,4 +427,23 @@ config MTD_NAND_SH_FLCTL | |||
427 | Several Renesas SuperH CPU has FLCTL. This option enables support | 427 | Several Renesas SuperH CPU has FLCTL. This option enables support |
428 | for NAND Flash using FLCTL. This driver support SH7723. | 428 | for NAND Flash using FLCTL. This driver support SH7723. |
429 | 429 | ||
430 | config MTD_NAND_DAVINCI | ||
431 | tristate "Support NAND on DaVinci SoC" | ||
432 | depends on ARCH_DAVINCI | ||
433 | help | ||
434 | Enable the driver for NAND flash chips on Texas Instruments | ||
435 | DaVinci processors. | ||
436 | |||
437 | config MTD_NAND_TXX9NDFMC | ||
438 | tristate "NAND Flash support for TXx9 SoC" | ||
439 | depends on SOC_TX4938 || SOC_TX4939 | ||
440 | help | ||
441 | This enables the NAND flash controller on the TXx9 SoCs. | ||
442 | |||
443 | config MTD_NAND_SOCRATES | ||
444 | tristate "Support for NAND on Socrates board" | ||
445 | depends on MTD_NAND && SOCRATES | ||
446 | help | ||
447 | Enables support for NAND Flash chips wired onto Socrates board. | ||
448 | |||
430 | endif # MTD_NAND | 449 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index b661586afbfc..d33860ac42c3 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o | |||
14 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o | 14 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o |
15 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | 15 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o |
16 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o | 16 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o |
17 | obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o | ||
17 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o | 18 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o |
18 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o | 19 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o |
19 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o | 20 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o |
@@ -36,5 +37,7 @@ obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o | |||
36 | obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o | 37 | obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o |
37 | obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o | 38 | obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o |
38 | obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o | 39 | obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o |
40 | obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o | ||
41 | obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o | ||
39 | 42 | ||
40 | nand-objs := nand_base.o nand_bbt.o | 43 | nand-objs := nand_base.o nand_bbt.o |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 9af2a2cc1153..4c2a67ca801e 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -552,7 +552,6 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, | |||
552 | static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) | 552 | static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) |
553 | { | 553 | { |
554 | int ret; | 554 | int ret; |
555 | unsigned short val; | ||
556 | 555 | ||
557 | /* Do not use dma */ | 556 | /* Do not use dma */ |
558 | if (!hardware_ecc) | 557 | if (!hardware_ecc) |
@@ -560,13 +559,6 @@ static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) | |||
560 | 559 | ||
561 | init_completion(&info->dma_completion); | 560 | init_completion(&info->dma_completion); |
562 | 561 | ||
563 | #ifdef CONFIG_BF54x | ||
564 | /* Setup DMAC1 channel mux for NFC which shared with SDH */ | ||
565 | val = bfin_read_DMAC1_PERIMUX(); | ||
566 | val &= 0xFFFE; | ||
567 | bfin_write_DMAC1_PERIMUX(val); | ||
568 | SSYNC(); | ||
569 | #endif | ||
570 | /* Request NFC DMA channel */ | 562 | /* Request NFC DMA channel */ |
571 | ret = request_dma(CH_NFC, "BF5XX NFC driver"); | 563 | ret = request_dma(CH_NFC, "BF5XX NFC driver"); |
572 | if (ret < 0) { | 564 | if (ret < 0) { |
@@ -574,7 +566,13 @@ static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) | |||
574 | return ret; | 566 | return ret; |
575 | } | 567 | } |
576 | 568 | ||
577 | set_dma_callback(CH_NFC, (void *) bf5xx_nand_dma_irq, (void *) info); | 569 | #ifdef CONFIG_BF54x |
570 | /* Setup DMAC1 channel mux for NFC which shared with SDH */ | ||
571 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() & ~1); | ||
572 | SSYNC(); | ||
573 | #endif | ||
574 | |||
575 | set_dma_callback(CH_NFC, bf5xx_nand_dma_irq, info); | ||
578 | 576 | ||
579 | /* Turn off the DMA channel first */ | 577 | /* Turn off the DMA channel first */ |
580 | disable_dma(CH_NFC); | 578 | disable_dma(CH_NFC); |
@@ -632,7 +630,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
632 | /* | 630 | /* |
633 | * Device management interface | 631 | * Device management interface |
634 | */ | 632 | */ |
635 | static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | 633 | static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) |
636 | { | 634 | { |
637 | struct mtd_info *mtd = &info->mtd; | 635 | struct mtd_info *mtd = &info->mtd; |
638 | 636 | ||
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 22a6b2e50e91..7c5b257ce8e4 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -654,6 +654,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
654 | } | 654 | } |
655 | cafe = (void *)(&mtd[1]); | 655 | cafe = (void *)(&mtd[1]); |
656 | 656 | ||
657 | mtd->dev.parent = &pdev->dev; | ||
657 | mtd->priv = cafe; | 658 | mtd->priv = cafe; |
658 | mtd->owner = THIS_MODULE; | 659 | mtd->owner = THIS_MODULE; |
659 | 660 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c new file mode 100644 index 000000000000..0119220de7d0 --- /dev/null +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -0,0 +1,570 @@ | |||
1 | /* | ||
2 | * davinci_nand.c - NAND Flash Driver for DaVinci family chips | ||
3 | * | ||
4 | * Copyright © 2006 Texas Instruments. | ||
5 | * | ||
6 | * Port to 2.6.23 Copyright © 2008 by: | ||
7 | * Sander Huijsen <Shuijsen@optelecom-nkf.com> | ||
8 | * Troy Kisky <troy.kisky@boundarydevices.com> | ||
9 | * Dirk Behme <Dirk.Behme@gmail.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/err.h> | ||
31 | #include <linux/clk.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <linux/mtd/nand.h> | ||
34 | #include <linux/mtd/partitions.h> | ||
35 | |||
36 | #include <mach/nand.h> | ||
37 | |||
38 | #include <asm/mach-types.h> | ||
39 | |||
40 | |||
41 | /* | ||
42 | * This is a device driver for the NAND flash controller found on the | ||
43 | * various DaVinci family chips. It handles up to four SoC chipselects, | ||
44 | * and some flavors of secondary chipselect (e.g. based on A12) as used | ||
45 | * with multichip packages. | ||
46 | * | ||
47 | * The 1-bit ECC hardware is supported, but not yet the newer 4-bit ECC | ||
48 | * available on chips like the DM355 and OMAP-L137 and needed with the | ||
49 | * more error-prone MLC NAND chips. | ||
50 | * | ||
51 | * This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY | ||
52 | * outputs in a "wire-AND" configuration, with no per-chip signals. | ||
53 | */ | ||
54 | struct davinci_nand_info { | ||
55 | struct mtd_info mtd; | ||
56 | struct nand_chip chip; | ||
57 | |||
58 | struct device *dev; | ||
59 | struct clk *clk; | ||
60 | bool partitioned; | ||
61 | |||
62 | void __iomem *base; | ||
63 | void __iomem *vaddr; | ||
64 | |||
65 | uint32_t ioaddr; | ||
66 | uint32_t current_cs; | ||
67 | |||
68 | uint32_t mask_chipsel; | ||
69 | uint32_t mask_ale; | ||
70 | uint32_t mask_cle; | ||
71 | |||
72 | uint32_t core_chipsel; | ||
73 | }; | ||
74 | |||
75 | static DEFINE_SPINLOCK(davinci_nand_lock); | ||
76 | |||
77 | #define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd) | ||
78 | |||
79 | |||
80 | static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info, | ||
81 | int offset) | ||
82 | { | ||
83 | return __raw_readl(info->base + offset); | ||
84 | } | ||
85 | |||
86 | static inline void davinci_nand_writel(struct davinci_nand_info *info, | ||
87 | int offset, unsigned long value) | ||
88 | { | ||
89 | __raw_writel(value, info->base + offset); | ||
90 | } | ||
91 | |||
92 | /*----------------------------------------------------------------------*/ | ||
93 | |||
94 | /* | ||
95 | * Access to hardware control lines: ALE, CLE, secondary chipselect. | ||
96 | */ | ||
97 | |||
98 | static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, | ||
99 | unsigned int ctrl) | ||
100 | { | ||
101 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
102 | uint32_t addr = info->current_cs; | ||
103 | struct nand_chip *nand = mtd->priv; | ||
104 | |||
105 | /* Did the control lines change? */ | ||
106 | if (ctrl & NAND_CTRL_CHANGE) { | ||
107 | if ((ctrl & NAND_CTRL_CLE) == NAND_CTRL_CLE) | ||
108 | addr |= info->mask_cle; | ||
109 | else if ((ctrl & NAND_CTRL_ALE) == NAND_CTRL_ALE) | ||
110 | addr |= info->mask_ale; | ||
111 | |||
112 | nand->IO_ADDR_W = (void __iomem __force *)addr; | ||
113 | } | ||
114 | |||
115 | if (cmd != NAND_CMD_NONE) | ||
116 | iowrite8(cmd, nand->IO_ADDR_W); | ||
117 | } | ||
118 | |||
119 | static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) | ||
120 | { | ||
121 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
122 | uint32_t addr = info->ioaddr; | ||
123 | |||
124 | /* maybe kick in a second chipselect */ | ||
125 | if (chip > 0) | ||
126 | addr |= info->mask_chipsel; | ||
127 | info->current_cs = addr; | ||
128 | |||
129 | info->chip.IO_ADDR_W = (void __iomem __force *)addr; | ||
130 | info->chip.IO_ADDR_R = info->chip.IO_ADDR_W; | ||
131 | } | ||
132 | |||
133 | /*----------------------------------------------------------------------*/ | ||
134 | |||
135 | /* | ||
136 | * 1-bit hardware ECC ... context maintained for each core chipselect | ||
137 | */ | ||
138 | |||
139 | static inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd) | ||
140 | { | ||
141 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
142 | |||
143 | return davinci_nand_readl(info, NANDF1ECC_OFFSET | ||
144 | + 4 * info->core_chipsel); | ||
145 | } | ||
146 | |||
147 | static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode) | ||
148 | { | ||
149 | struct davinci_nand_info *info; | ||
150 | uint32_t nandcfr; | ||
151 | unsigned long flags; | ||
152 | |||
153 | info = to_davinci_nand(mtd); | ||
154 | |||
155 | /* Reset ECC hardware */ | ||
156 | nand_davinci_readecc_1bit(mtd); | ||
157 | |||
158 | spin_lock_irqsave(&davinci_nand_lock, flags); | ||
159 | |||
160 | /* Restart ECC hardware */ | ||
161 | nandcfr = davinci_nand_readl(info, NANDFCR_OFFSET); | ||
162 | nandcfr |= BIT(8 + info->core_chipsel); | ||
163 | davinci_nand_writel(info, NANDFCR_OFFSET, nandcfr); | ||
164 | |||
165 | spin_unlock_irqrestore(&davinci_nand_lock, flags); | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Read hardware ECC value and pack into three bytes | ||
170 | */ | ||
171 | static int nand_davinci_calculate_1bit(struct mtd_info *mtd, | ||
172 | const u_char *dat, u_char *ecc_code) | ||
173 | { | ||
174 | unsigned int ecc_val = nand_davinci_readecc_1bit(mtd); | ||
175 | unsigned int ecc24 = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4); | ||
176 | |||
177 | /* invert so that erased block ecc is correct */ | ||
178 | ecc24 = ~ecc24; | ||
179 | ecc_code[0] = (u_char)(ecc24); | ||
180 | ecc_code[1] = (u_char)(ecc24 >> 8); | ||
181 | ecc_code[2] = (u_char)(ecc24 >> 16); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, | ||
187 | u_char *read_ecc, u_char *calc_ecc) | ||
188 | { | ||
189 | struct nand_chip *chip = mtd->priv; | ||
190 | uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) | | ||
191 | (read_ecc[2] << 16); | ||
192 | uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) | | ||
193 | (calc_ecc[2] << 16); | ||
194 | uint32_t diff = eccCalc ^ eccNand; | ||
195 | |||
196 | if (diff) { | ||
197 | if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) { | ||
198 | /* Correctable error */ | ||
199 | if ((diff >> (12 + 3)) < chip->ecc.size) { | ||
200 | dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7); | ||
201 | return 1; | ||
202 | } else { | ||
203 | return -1; | ||
204 | } | ||
205 | } else if (!(diff & (diff - 1))) { | ||
206 | /* Single bit ECC error in the ECC itself, | ||
207 | * nothing to fix */ | ||
208 | return 1; | ||
209 | } else { | ||
210 | /* Uncorrectable error */ | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | } | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /*----------------------------------------------------------------------*/ | ||
219 | |||
220 | /* | ||
221 | * NOTE: NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's | ||
222 | * how these chips are normally wired. This translates to both 8 and 16 | ||
223 | * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4). | ||
224 | * | ||
225 | * For now we assume that configuration, or any other one which ignores | ||
226 | * the two LSBs for NAND access ... so we can issue 32-bit reads/writes | ||
227 | * and have that transparently morphed into multiple NAND operations. | ||
228 | */ | ||
229 | static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
230 | { | ||
231 | struct nand_chip *chip = mtd->priv; | ||
232 | |||
233 | if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) | ||
234 | ioread32_rep(chip->IO_ADDR_R, buf, len >> 2); | ||
235 | else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0) | ||
236 | ioread16_rep(chip->IO_ADDR_R, buf, len >> 1); | ||
237 | else | ||
238 | ioread8_rep(chip->IO_ADDR_R, buf, len); | ||
239 | } | ||
240 | |||
241 | static void nand_davinci_write_buf(struct mtd_info *mtd, | ||
242 | const uint8_t *buf, int len) | ||
243 | { | ||
244 | struct nand_chip *chip = mtd->priv; | ||
245 | |||
246 | if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) | ||
247 | iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2); | ||
248 | else if ((0x01 & ((unsigned)buf)) == 0 && (0x01 & len) == 0) | ||
249 | iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1); | ||
250 | else | ||
251 | iowrite8_rep(chip->IO_ADDR_R, buf, len); | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Check hardware register for wait status. Returns 1 if device is ready, | ||
256 | * 0 if it is still busy. | ||
257 | */ | ||
258 | static int nand_davinci_dev_ready(struct mtd_info *mtd) | ||
259 | { | ||
260 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
261 | |||
262 | return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); | ||
263 | } | ||
264 | |||
265 | static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info) | ||
266 | { | ||
267 | uint32_t regval, a1cr; | ||
268 | |||
269 | /* | ||
270 | * NAND FLASH timings @ PLL1 == 459 MHz | ||
271 | * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz | ||
272 | * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns | ||
273 | */ | ||
274 | regval = 0 | ||
275 | | (0 << 31) /* selectStrobe */ | ||
276 | | (0 << 30) /* extWait (never with NAND) */ | ||
277 | | (1 << 26) /* writeSetup 10 ns */ | ||
278 | | (3 << 20) /* writeStrobe 40 ns */ | ||
279 | | (1 << 17) /* writeHold 10 ns */ | ||
280 | | (0 << 13) /* readSetup 10 ns */ | ||
281 | | (3 << 7) /* readStrobe 60 ns */ | ||
282 | | (0 << 4) /* readHold 10 ns */ | ||
283 | | (3 << 2) /* turnAround ?? ns */ | ||
284 | | (0 << 0) /* asyncSize 8-bit bus */ | ||
285 | ; | ||
286 | a1cr = davinci_nand_readl(info, A1CR_OFFSET); | ||
287 | if (a1cr != regval) { | ||
288 | dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \ | ||
289 | "reg to 0x%08x, was 0x%08x, should be done by " \ | ||
290 | "bootloader.\n", regval, a1cr); | ||
291 | davinci_nand_writel(info, A1CR_OFFSET, regval); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /*----------------------------------------------------------------------*/ | ||
296 | |||
297 | static int __init nand_davinci_probe(struct platform_device *pdev) | ||
298 | { | ||
299 | struct davinci_nand_pdata *pdata = pdev->dev.platform_data; | ||
300 | struct davinci_nand_info *info; | ||
301 | struct resource *res1; | ||
302 | struct resource *res2; | ||
303 | void __iomem *vaddr; | ||
304 | void __iomem *base; | ||
305 | int ret; | ||
306 | uint32_t val; | ||
307 | nand_ecc_modes_t ecc_mode; | ||
308 | |||
309 | /* which external chipselect will we be managing? */ | ||
310 | if (pdev->id < 0 || pdev->id > 3) | ||
311 | return -ENODEV; | ||
312 | |||
313 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
314 | if (!info) { | ||
315 | dev_err(&pdev->dev, "unable to allocate memory\n"); | ||
316 | ret = -ENOMEM; | ||
317 | goto err_nomem; | ||
318 | } | ||
319 | |||
320 | platform_set_drvdata(pdev, info); | ||
321 | |||
322 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
323 | res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
324 | if (!res1 || !res2) { | ||
325 | dev_err(&pdev->dev, "resource missing\n"); | ||
326 | ret = -EINVAL; | ||
327 | goto err_nomem; | ||
328 | } | ||
329 | |||
330 | vaddr = ioremap(res1->start, res1->end - res1->start); | ||
331 | base = ioremap(res2->start, res2->end - res2->start); | ||
332 | if (!vaddr || !base) { | ||
333 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
334 | ret = -EINVAL; | ||
335 | goto err_ioremap; | ||
336 | } | ||
337 | |||
338 | info->dev = &pdev->dev; | ||
339 | info->base = base; | ||
340 | info->vaddr = vaddr; | ||
341 | |||
342 | info->mtd.priv = &info->chip; | ||
343 | info->mtd.name = dev_name(&pdev->dev); | ||
344 | info->mtd.owner = THIS_MODULE; | ||
345 | |||
346 | info->mtd.dev.parent = &pdev->dev; | ||
347 | |||
348 | info->chip.IO_ADDR_R = vaddr; | ||
349 | info->chip.IO_ADDR_W = vaddr; | ||
350 | info->chip.chip_delay = 0; | ||
351 | info->chip.select_chip = nand_davinci_select_chip; | ||
352 | |||
353 | /* options such as NAND_USE_FLASH_BBT or 16-bit widths */ | ||
354 | info->chip.options = pdata ? pdata->options : 0; | ||
355 | |||
356 | info->ioaddr = (uint32_t __force) vaddr; | ||
357 | |||
358 | info->current_cs = info->ioaddr; | ||
359 | info->core_chipsel = pdev->id; | ||
360 | info->mask_chipsel = pdata->mask_chipsel; | ||
361 | |||
362 | /* use nandboot-capable ALE/CLE masks by default */ | ||
363 | if (pdata && pdata->mask_ale) | ||
364 | info->mask_ale = pdata->mask_cle; | ||
365 | else | ||
366 | info->mask_ale = MASK_ALE; | ||
367 | if (pdata && pdata->mask_cle) | ||
368 | info->mask_cle = pdata->mask_cle; | ||
369 | else | ||
370 | info->mask_cle = MASK_CLE; | ||
371 | |||
372 | /* Set address of hardware control function */ | ||
373 | info->chip.cmd_ctrl = nand_davinci_hwcontrol; | ||
374 | info->chip.dev_ready = nand_davinci_dev_ready; | ||
375 | |||
376 | /* Speed up buffer I/O */ | ||
377 | info->chip.read_buf = nand_davinci_read_buf; | ||
378 | info->chip.write_buf = nand_davinci_write_buf; | ||
379 | |||
380 | /* use board-specific ECC config; else, the best available */ | ||
381 | if (pdata) | ||
382 | ecc_mode = pdata->ecc_mode; | ||
383 | else | ||
384 | ecc_mode = NAND_ECC_HW; | ||
385 | |||
386 | switch (ecc_mode) { | ||
387 | case NAND_ECC_NONE: | ||
388 | case NAND_ECC_SOFT: | ||
389 | break; | ||
390 | case NAND_ECC_HW: | ||
391 | info->chip.ecc.calculate = nand_davinci_calculate_1bit; | ||
392 | info->chip.ecc.correct = nand_davinci_correct_1bit; | ||
393 | info->chip.ecc.hwctl = nand_davinci_hwctl_1bit; | ||
394 | info->chip.ecc.size = 512; | ||
395 | info->chip.ecc.bytes = 3; | ||
396 | break; | ||
397 | case NAND_ECC_HW_SYNDROME: | ||
398 | /* FIXME implement */ | ||
399 | info->chip.ecc.size = 512; | ||
400 | info->chip.ecc.bytes = 10; | ||
401 | |||
402 | dev_warn(&pdev->dev, "4-bit ECC nyet supported\n"); | ||
403 | /* FALL THROUGH */ | ||
404 | default: | ||
405 | ret = -EINVAL; | ||
406 | goto err_ecc; | ||
407 | } | ||
408 | info->chip.ecc.mode = ecc_mode; | ||
409 | |||
410 | info->clk = clk_get(&pdev->dev, "AEMIFCLK"); | ||
411 | if (IS_ERR(info->clk)) { | ||
412 | ret = PTR_ERR(info->clk); | ||
413 | dev_dbg(&pdev->dev, "unable to get AEMIFCLK, err %d\n", ret); | ||
414 | goto err_clk; | ||
415 | } | ||
416 | |||
417 | ret = clk_enable(info->clk); | ||
418 | if (ret < 0) { | ||
419 | dev_dbg(&pdev->dev, "unable to enable AEMIFCLK, err %d\n", ret); | ||
420 | goto err_clk_enable; | ||
421 | } | ||
422 | |||
423 | /* EMIF timings should normally be set by the boot loader, | ||
424 | * especially after boot-from-NAND. The *only* reason to | ||
425 | * have this special casing for the DM6446 EVM is to work | ||
426 | * with boot-from-NOR ... with CS0 manually re-jumpered | ||
427 | * (after startup) so it addresses the NAND flash, not NOR. | ||
428 | * Even for dev boards, that's unusually rude... | ||
429 | */ | ||
430 | if (machine_is_davinci_evm()) | ||
431 | nand_dm6446evm_flash_init(info); | ||
432 | |||
433 | spin_lock_irq(&davinci_nand_lock); | ||
434 | |||
435 | /* put CSxNAND into NAND mode */ | ||
436 | val = davinci_nand_readl(info, NANDFCR_OFFSET); | ||
437 | val |= BIT(info->core_chipsel); | ||
438 | davinci_nand_writel(info, NANDFCR_OFFSET, val); | ||
439 | |||
440 | spin_unlock_irq(&davinci_nand_lock); | ||
441 | |||
442 | /* Scan to find existence of the device(s) */ | ||
443 | ret = nand_scan(&info->mtd, pdata->mask_chipsel ? 2 : 1); | ||
444 | if (ret < 0) { | ||
445 | dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); | ||
446 | goto err_scan; | ||
447 | } | ||
448 | |||
449 | if (mtd_has_partitions()) { | ||
450 | struct mtd_partition *mtd_parts = NULL; | ||
451 | int mtd_parts_nb = 0; | ||
452 | |||
453 | if (mtd_has_cmdlinepart()) { | ||
454 | static const char *probes[] __initconst = | ||
455 | { "cmdlinepart", NULL }; | ||
456 | |||
457 | const char *master_name; | ||
458 | |||
459 | /* Set info->mtd.name = 0 temporarily */ | ||
460 | master_name = info->mtd.name; | ||
461 | info->mtd.name = (char *)0; | ||
462 | |||
463 | /* info->mtd.name == 0, means: don't bother checking | ||
464 | <mtd-id> */ | ||
465 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, | ||
466 | &mtd_parts, 0); | ||
467 | |||
468 | /* Restore info->mtd.name */ | ||
469 | info->mtd.name = master_name; | ||
470 | } | ||
471 | |||
472 | if (mtd_parts_nb <= 0 && pdata) { | ||
473 | mtd_parts = pdata->parts; | ||
474 | mtd_parts_nb = pdata->nr_parts; | ||
475 | } | ||
476 | |||
477 | /* Register any partitions */ | ||
478 | if (mtd_parts_nb > 0) { | ||
479 | ret = add_mtd_partitions(&info->mtd, | ||
480 | mtd_parts, mtd_parts_nb); | ||
481 | if (ret == 0) | ||
482 | info->partitioned = true; | ||
483 | } | ||
484 | |||
485 | } else if (pdata && pdata->nr_parts) { | ||
486 | dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n", | ||
487 | pdata->nr_parts, info->mtd.name); | ||
488 | } | ||
489 | |||
490 | /* If there's no partition info, just package the whole chip | ||
491 | * as a single MTD device. | ||
492 | */ | ||
493 | if (!info->partitioned) | ||
494 | ret = add_mtd_device(&info->mtd) ? -ENODEV : 0; | ||
495 | |||
496 | if (ret < 0) | ||
497 | goto err_scan; | ||
498 | |||
499 | val = davinci_nand_readl(info, NRCSR_OFFSET); | ||
500 | dev_info(&pdev->dev, "controller rev. %d.%d\n", | ||
501 | (val >> 8) & 0xff, val & 0xff); | ||
502 | |||
503 | return 0; | ||
504 | |||
505 | err_scan: | ||
506 | clk_disable(info->clk); | ||
507 | |||
508 | err_clk_enable: | ||
509 | clk_put(info->clk); | ||
510 | |||
511 | err_ecc: | ||
512 | err_clk: | ||
513 | err_ioremap: | ||
514 | if (base) | ||
515 | iounmap(base); | ||
516 | if (vaddr) | ||
517 | iounmap(vaddr); | ||
518 | |||
519 | err_nomem: | ||
520 | kfree(info); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | static int __exit nand_davinci_remove(struct platform_device *pdev) | ||
525 | { | ||
526 | struct davinci_nand_info *info = platform_get_drvdata(pdev); | ||
527 | int status; | ||
528 | |||
529 | if (mtd_has_partitions() && info->partitioned) | ||
530 | status = del_mtd_partitions(&info->mtd); | ||
531 | else | ||
532 | status = del_mtd_device(&info->mtd); | ||
533 | |||
534 | iounmap(info->base); | ||
535 | iounmap(info->vaddr); | ||
536 | |||
537 | nand_release(&info->mtd); | ||
538 | |||
539 | clk_disable(info->clk); | ||
540 | clk_put(info->clk); | ||
541 | |||
542 | kfree(info); | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static struct platform_driver nand_davinci_driver = { | ||
548 | .remove = __exit_p(nand_davinci_remove), | ||
549 | .driver = { | ||
550 | .name = "davinci_nand", | ||
551 | }, | ||
552 | }; | ||
553 | MODULE_ALIAS("platform:davinci_nand"); | ||
554 | |||
555 | static int __init nand_davinci_init(void) | ||
556 | { | ||
557 | return platform_driver_probe(&nand_davinci_driver, nand_davinci_probe); | ||
558 | } | ||
559 | module_init(nand_davinci_init); | ||
560 | |||
561 | static void __exit nand_davinci_exit(void) | ||
562 | { | ||
563 | platform_driver_unregister(&nand_davinci_driver); | ||
564 | } | ||
565 | module_exit(nand_davinci_exit); | ||
566 | |||
567 | MODULE_LICENSE("GPL"); | ||
568 | MODULE_AUTHOR("Texas Instruments"); | ||
569 | MODULE_DESCRIPTION("Davinci NAND flash driver"); | ||
570 | |||
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 7815a404a632..d120cd8d7267 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -23,6 +23,10 @@ | |||
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/fsl_lbc.h> | 24 | #include <asm/fsl_lbc.h> |
25 | 25 | ||
26 | #define FSL_UPM_WAIT_RUN_PATTERN 0x1 | ||
27 | #define FSL_UPM_WAIT_WRITE_BYTE 0x2 | ||
28 | #define FSL_UPM_WAIT_WRITE_BUFFER 0x4 | ||
29 | |||
26 | struct fsl_upm_nand { | 30 | struct fsl_upm_nand { |
27 | struct device *dev; | 31 | struct device *dev; |
28 | struct mtd_info mtd; | 32 | struct mtd_info mtd; |
@@ -36,8 +40,12 @@ struct fsl_upm_nand { | |||
36 | uint8_t upm_addr_offset; | 40 | uint8_t upm_addr_offset; |
37 | uint8_t upm_cmd_offset; | 41 | uint8_t upm_cmd_offset; |
38 | void __iomem *io_base; | 42 | void __iomem *io_base; |
39 | int rnb_gpio; | 43 | int rnb_gpio[NAND_MAX_CHIPS]; |
44 | uint32_t mchip_offsets[NAND_MAX_CHIPS]; | ||
45 | uint32_t mchip_count; | ||
46 | uint32_t mchip_number; | ||
40 | int chip_delay; | 47 | int chip_delay; |
48 | uint32_t wait_flags; | ||
41 | }; | 49 | }; |
42 | 50 | ||
43 | #define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd) | 51 | #define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd) |
@@ -46,7 +54,7 @@ static int fun_chip_ready(struct mtd_info *mtd) | |||
46 | { | 54 | { |
47 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | 55 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); |
48 | 56 | ||
49 | if (gpio_get_value(fun->rnb_gpio)) | 57 | if (gpio_get_value(fun->rnb_gpio[fun->mchip_number])) |
50 | return 1; | 58 | return 1; |
51 | 59 | ||
52 | dev_vdbg(fun->dev, "busy\n"); | 60 | dev_vdbg(fun->dev, "busy\n"); |
@@ -55,9 +63,9 @@ static int fun_chip_ready(struct mtd_info *mtd) | |||
55 | 63 | ||
56 | static void fun_wait_rnb(struct fsl_upm_nand *fun) | 64 | static void fun_wait_rnb(struct fsl_upm_nand *fun) |
57 | { | 65 | { |
58 | int cnt = 1000000; | 66 | if (fun->rnb_gpio[fun->mchip_number] >= 0) { |
67 | int cnt = 1000000; | ||
59 | 68 | ||
60 | if (fun->rnb_gpio >= 0) { | ||
61 | while (--cnt && !fun_chip_ready(&fun->mtd)) | 69 | while (--cnt && !fun_chip_ready(&fun->mtd)) |
62 | cpu_relax(); | 70 | cpu_relax(); |
63 | if (!cnt) | 71 | if (!cnt) |
@@ -69,7 +77,9 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun) | |||
69 | 77 | ||
70 | static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 78 | static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
71 | { | 79 | { |
80 | struct nand_chip *chip = mtd->priv; | ||
72 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | 81 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); |
82 | u32 mar; | ||
73 | 83 | ||
74 | if (!(ctrl & fun->last_ctrl)) { | 84 | if (!(ctrl & fun->last_ctrl)) { |
75 | fsl_upm_end_pattern(&fun->upm); | 85 | fsl_upm_end_pattern(&fun->upm); |
@@ -87,9 +97,28 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
87 | fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); | 97 | fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); |
88 | } | 98 | } |
89 | 99 | ||
90 | fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd); | 100 | mar = (cmd << (32 - fun->upm.width)) | |
101 | fun->mchip_offsets[fun->mchip_number]; | ||
102 | fsl_upm_run_pattern(&fun->upm, chip->IO_ADDR_R, mar); | ||
103 | |||
104 | if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN) | ||
105 | fun_wait_rnb(fun); | ||
106 | } | ||
107 | |||
108 | static void fun_select_chip(struct mtd_info *mtd, int mchip_nr) | ||
109 | { | ||
110 | struct nand_chip *chip = mtd->priv; | ||
111 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
91 | 112 | ||
92 | fun_wait_rnb(fun); | 113 | if (mchip_nr == -1) { |
114 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); | ||
115 | } else if (mchip_nr >= 0) { | ||
116 | fun->mchip_number = mchip_nr; | ||
117 | chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; | ||
118 | chip->IO_ADDR_W = chip->IO_ADDR_R; | ||
119 | } else { | ||
120 | BUG(); | ||
121 | } | ||
93 | } | 122 | } |
94 | 123 | ||
95 | static uint8_t fun_read_byte(struct mtd_info *mtd) | 124 | static uint8_t fun_read_byte(struct mtd_info *mtd) |
@@ -115,8 +144,11 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
115 | 144 | ||
116 | for (i = 0; i < len; i++) { | 145 | for (i = 0; i < len; i++) { |
117 | out_8(fun->chip.IO_ADDR_W, buf[i]); | 146 | out_8(fun->chip.IO_ADDR_W, buf[i]); |
118 | fun_wait_rnb(fun); | 147 | if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE) |
148 | fun_wait_rnb(fun); | ||
119 | } | 149 | } |
150 | if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER) | ||
151 | fun_wait_rnb(fun); | ||
120 | } | 152 | } |
121 | 153 | ||
122 | static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | 154 | static int __devinit fun_chip_init(struct fsl_upm_nand *fun, |
@@ -137,8 +169,10 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
137 | fun->chip.read_buf = fun_read_buf; | 169 | fun->chip.read_buf = fun_read_buf; |
138 | fun->chip.write_buf = fun_write_buf; | 170 | fun->chip.write_buf = fun_write_buf; |
139 | fun->chip.ecc.mode = NAND_ECC_SOFT; | 171 | fun->chip.ecc.mode = NAND_ECC_SOFT; |
172 | if (fun->mchip_count > 1) | ||
173 | fun->chip.select_chip = fun_select_chip; | ||
140 | 174 | ||
141 | if (fun->rnb_gpio >= 0) | 175 | if (fun->rnb_gpio[0] >= 0) |
142 | fun->chip.dev_ready = fun_chip_ready; | 176 | fun->chip.dev_ready = fun_chip_ready; |
143 | 177 | ||
144 | fun->mtd.priv = &fun->chip; | 178 | fun->mtd.priv = &fun->chip; |
@@ -155,7 +189,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
155 | goto err; | 189 | goto err; |
156 | } | 190 | } |
157 | 191 | ||
158 | ret = nand_scan(&fun->mtd, 1); | 192 | ret = nand_scan(&fun->mtd, fun->mchip_count); |
159 | if (ret) | 193 | if (ret) |
160 | goto err; | 194 | goto err; |
161 | 195 | ||
@@ -185,8 +219,10 @@ static int __devinit fun_probe(struct of_device *ofdev, | |||
185 | struct fsl_upm_nand *fun; | 219 | struct fsl_upm_nand *fun; |
186 | struct resource io_res; | 220 | struct resource io_res; |
187 | const uint32_t *prop; | 221 | const uint32_t *prop; |
222 | int rnb_gpio; | ||
188 | int ret; | 223 | int ret; |
189 | int size; | 224 | int size; |
225 | int i; | ||
190 | 226 | ||
191 | fun = kzalloc(sizeof(*fun), GFP_KERNEL); | 227 | fun = kzalloc(sizeof(*fun), GFP_KERNEL); |
192 | if (!fun) | 228 | if (!fun) |
@@ -208,7 +244,7 @@ static int __devinit fun_probe(struct of_device *ofdev, | |||
208 | if (!prop || size != sizeof(uint32_t)) { | 244 | if (!prop || size != sizeof(uint32_t)) { |
209 | dev_err(&ofdev->dev, "can't get UPM address offset\n"); | 245 | dev_err(&ofdev->dev, "can't get UPM address offset\n"); |
210 | ret = -EINVAL; | 246 | ret = -EINVAL; |
211 | goto err2; | 247 | goto err1; |
212 | } | 248 | } |
213 | fun->upm_addr_offset = *prop; | 249 | fun->upm_addr_offset = *prop; |
214 | 250 | ||
@@ -216,21 +252,40 @@ static int __devinit fun_probe(struct of_device *ofdev, | |||
216 | if (!prop || size != sizeof(uint32_t)) { | 252 | if (!prop || size != sizeof(uint32_t)) { |
217 | dev_err(&ofdev->dev, "can't get UPM command offset\n"); | 253 | dev_err(&ofdev->dev, "can't get UPM command offset\n"); |
218 | ret = -EINVAL; | 254 | ret = -EINVAL; |
219 | goto err2; | 255 | goto err1; |
220 | } | 256 | } |
221 | fun->upm_cmd_offset = *prop; | 257 | fun->upm_cmd_offset = *prop; |
222 | 258 | ||
223 | fun->rnb_gpio = of_get_gpio(ofdev->node, 0); | 259 | prop = of_get_property(ofdev->node, |
224 | if (fun->rnb_gpio >= 0) { | 260 | "fsl,upm-addr-line-cs-offsets", &size); |
225 | ret = gpio_request(fun->rnb_gpio, dev_name(&ofdev->dev)); | 261 | if (prop && (size / sizeof(uint32_t)) > 0) { |
226 | if (ret) { | 262 | fun->mchip_count = size / sizeof(uint32_t); |
227 | dev_err(&ofdev->dev, "can't request RNB gpio\n"); | 263 | if (fun->mchip_count >= NAND_MAX_CHIPS) { |
264 | dev_err(&ofdev->dev, "too much multiple chips\n"); | ||
265 | goto err1; | ||
266 | } | ||
267 | for (i = 0; i < fun->mchip_count; i++) | ||
268 | fun->mchip_offsets[i] = prop[i]; | ||
269 | } else { | ||
270 | fun->mchip_count = 1; | ||
271 | } | ||
272 | |||
273 | for (i = 0; i < fun->mchip_count; i++) { | ||
274 | fun->rnb_gpio[i] = -1; | ||
275 | rnb_gpio = of_get_gpio(ofdev->node, i); | ||
276 | if (rnb_gpio >= 0) { | ||
277 | ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev)); | ||
278 | if (ret) { | ||
279 | dev_err(&ofdev->dev, | ||
280 | "can't request RNB gpio #%d\n", i); | ||
281 | goto err2; | ||
282 | } | ||
283 | gpio_direction_input(rnb_gpio); | ||
284 | fun->rnb_gpio[i] = rnb_gpio; | ||
285 | } else if (rnb_gpio == -EINVAL) { | ||
286 | dev_err(&ofdev->dev, "RNB gpio #%d is invalid\n", i); | ||
228 | goto err2; | 287 | goto err2; |
229 | } | 288 | } |
230 | gpio_direction_input(fun->rnb_gpio); | ||
231 | } else if (fun->rnb_gpio == -EINVAL) { | ||
232 | dev_err(&ofdev->dev, "specified RNB gpio is invalid\n"); | ||
233 | goto err2; | ||
234 | } | 289 | } |
235 | 290 | ||
236 | prop = of_get_property(ofdev->node, "chip-delay", NULL); | 291 | prop = of_get_property(ofdev->node, "chip-delay", NULL); |
@@ -239,8 +294,15 @@ static int __devinit fun_probe(struct of_device *ofdev, | |||
239 | else | 294 | else |
240 | fun->chip_delay = 50; | 295 | fun->chip_delay = 50; |
241 | 296 | ||
297 | prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size); | ||
298 | if (prop && size == sizeof(uint32_t)) | ||
299 | fun->wait_flags = *prop; | ||
300 | else | ||
301 | fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | | ||
302 | FSL_UPM_WAIT_WRITE_BYTE; | ||
303 | |||
242 | fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start, | 304 | fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start, |
243 | io_res.end - io_res.start + 1); | 305 | io_res.end - io_res.start + 1); |
244 | if (!fun->io_base) { | 306 | if (!fun->io_base) { |
245 | ret = -ENOMEM; | 307 | ret = -ENOMEM; |
246 | goto err2; | 308 | goto err2; |
@@ -257,8 +319,11 @@ static int __devinit fun_probe(struct of_device *ofdev, | |||
257 | 319 | ||
258 | return 0; | 320 | return 0; |
259 | err2: | 321 | err2: |
260 | if (fun->rnb_gpio >= 0) | 322 | for (i = 0; i < fun->mchip_count; i++) { |
261 | gpio_free(fun->rnb_gpio); | 323 | if (fun->rnb_gpio[i] < 0) |
324 | break; | ||
325 | gpio_free(fun->rnb_gpio[i]); | ||
326 | } | ||
262 | err1: | 327 | err1: |
263 | kfree(fun); | 328 | kfree(fun); |
264 | 329 | ||
@@ -268,12 +333,16 @@ err1: | |||
268 | static int __devexit fun_remove(struct of_device *ofdev) | 333 | static int __devexit fun_remove(struct of_device *ofdev) |
269 | { | 334 | { |
270 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); | 335 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); |
336 | int i; | ||
271 | 337 | ||
272 | nand_release(&fun->mtd); | 338 | nand_release(&fun->mtd); |
273 | kfree(fun->mtd.name); | 339 | kfree(fun->mtd.name); |
274 | 340 | ||
275 | if (fun->rnb_gpio >= 0) | 341 | for (i = 0; i < fun->mchip_count; i++) { |
276 | gpio_free(fun->rnb_gpio); | 342 | if (fun->rnb_gpio[i] < 0) |
343 | break; | ||
344 | gpio_free(fun->rnb_gpio[i]); | ||
345 | } | ||
277 | 346 | ||
278 | kfree(fun); | 347 | kfree(fun); |
279 | 348 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index bad048aca89a..f3548d048014 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -866,6 +866,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
866 | mtd = &host->mtd; | 866 | mtd = &host->mtd; |
867 | mtd->priv = this; | 867 | mtd->priv = this; |
868 | mtd->owner = THIS_MODULE; | 868 | mtd->owner = THIS_MODULE; |
869 | mtd->dev.parent = &pdev->dev; | ||
869 | 870 | ||
870 | /* 50 us command delay time */ | 871 | /* 50 us command delay time */ |
871 | this->chip_delay = 5; | 872 | this->chip_delay = 5; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5f71371eb1b0..3d7ed432fa41 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -82,6 +82,20 @@ static struct nand_ecclayout nand_oob_64 = { | |||
82 | .length = 38}} | 82 | .length = 38}} |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static struct nand_ecclayout nand_oob_128 = { | ||
86 | .eccbytes = 48, | ||
87 | .eccpos = { | ||
88 | 80, 81, 82, 83, 84, 85, 86, 87, | ||
89 | 88, 89, 90, 91, 92, 93, 94, 95, | ||
90 | 96, 97, 98, 99, 100, 101, 102, 103, | ||
91 | 104, 105, 106, 107, 108, 109, 110, 111, | ||
92 | 112, 113, 114, 115, 116, 117, 118, 119, | ||
93 | 120, 121, 122, 123, 124, 125, 126, 127}, | ||
94 | .oobfree = { | ||
95 | {.offset = 2, | ||
96 | .length = 78}} | ||
97 | }; | ||
98 | |||
85 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, | 99 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, |
86 | int new_state); | 100 | int new_state); |
87 | 101 | ||
@@ -748,6 +762,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
748 | * @mtd: mtd info structure | 762 | * @mtd: mtd info structure |
749 | * @chip: nand chip info structure | 763 | * @chip: nand chip info structure |
750 | * @buf: buffer to store read data | 764 | * @buf: buffer to store read data |
765 | * | ||
766 | * Not for syndrome calculating ecc controllers, which use a special oob layout | ||
751 | */ | 767 | */ |
752 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 768 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
753 | uint8_t *buf) | 769 | uint8_t *buf) |
@@ -758,6 +774,47 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
758 | } | 774 | } |
759 | 775 | ||
760 | /** | 776 | /** |
777 | * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc | ||
778 | * @mtd: mtd info structure | ||
779 | * @chip: nand chip info structure | ||
780 | * @buf: buffer to store read data | ||
781 | * | ||
782 | * We need a special oob layout and handling even when OOB isn't used. | ||
783 | */ | ||
784 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
785 | uint8_t *buf) | ||
786 | { | ||
787 | int eccsize = chip->ecc.size; | ||
788 | int eccbytes = chip->ecc.bytes; | ||
789 | uint8_t *oob = chip->oob_poi; | ||
790 | int steps, size; | ||
791 | |||
792 | for (steps = chip->ecc.steps; steps > 0; steps--) { | ||
793 | chip->read_buf(mtd, buf, eccsize); | ||
794 | buf += eccsize; | ||
795 | |||
796 | if (chip->ecc.prepad) { | ||
797 | chip->read_buf(mtd, oob, chip->ecc.prepad); | ||
798 | oob += chip->ecc.prepad; | ||
799 | } | ||
800 | |||
801 | chip->read_buf(mtd, oob, eccbytes); | ||
802 | oob += eccbytes; | ||
803 | |||
804 | if (chip->ecc.postpad) { | ||
805 | chip->read_buf(mtd, oob, chip->ecc.postpad); | ||
806 | oob += chip->ecc.postpad; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | size = mtd->oobsize - (oob - chip->oob_poi); | ||
811 | if (size) | ||
812 | chip->read_buf(mtd, oob, size); | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | /** | ||
761 | * nand_read_page_swecc - [REPLACABLE] software ecc based page read function | 818 | * nand_read_page_swecc - [REPLACABLE] software ecc based page read function |
762 | * @mtd: mtd info structure | 819 | * @mtd: mtd info structure |
763 | * @chip: nand chip info structure | 820 | * @chip: nand chip info structure |
@@ -1482,6 +1539,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1482 | * @mtd: mtd info structure | 1539 | * @mtd: mtd info structure |
1483 | * @chip: nand chip info structure | 1540 | * @chip: nand chip info structure |
1484 | * @buf: data buffer | 1541 | * @buf: data buffer |
1542 | * | ||
1543 | * Not for syndrome calculating ecc controllers, which use a special oob layout | ||
1485 | */ | 1544 | */ |
1486 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1545 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1487 | const uint8_t *buf) | 1546 | const uint8_t *buf) |
@@ -1491,6 +1550,44 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1491 | } | 1550 | } |
1492 | 1551 | ||
1493 | /** | 1552 | /** |
1553 | * nand_write_page_raw_syndrome - [Intern] raw page write function | ||
1554 | * @mtd: mtd info structure | ||
1555 | * @chip: nand chip info structure | ||
1556 | * @buf: data buffer | ||
1557 | * | ||
1558 | * We need a special oob layout and handling even when ECC isn't checked. | ||
1559 | */ | ||
1560 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
1561 | const uint8_t *buf) | ||
1562 | { | ||
1563 | int eccsize = chip->ecc.size; | ||
1564 | int eccbytes = chip->ecc.bytes; | ||
1565 | uint8_t *oob = chip->oob_poi; | ||
1566 | int steps, size; | ||
1567 | |||
1568 | for (steps = chip->ecc.steps; steps > 0; steps--) { | ||
1569 | chip->write_buf(mtd, buf, eccsize); | ||
1570 | buf += eccsize; | ||
1571 | |||
1572 | if (chip->ecc.prepad) { | ||
1573 | chip->write_buf(mtd, oob, chip->ecc.prepad); | ||
1574 | oob += chip->ecc.prepad; | ||
1575 | } | ||
1576 | |||
1577 | chip->read_buf(mtd, oob, eccbytes); | ||
1578 | oob += eccbytes; | ||
1579 | |||
1580 | if (chip->ecc.postpad) { | ||
1581 | chip->write_buf(mtd, oob, chip->ecc.postpad); | ||
1582 | oob += chip->ecc.postpad; | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | size = mtd->oobsize - (oob - chip->oob_poi); | ||
1587 | if (size) | ||
1588 | chip->write_buf(mtd, oob, size); | ||
1589 | } | ||
1590 | /** | ||
1494 | * nand_write_page_swecc - [REPLACABLE] software ecc based page write function | 1591 | * nand_write_page_swecc - [REPLACABLE] software ecc based page write function |
1495 | * @mtd: mtd info structure | 1592 | * @mtd: mtd info structure |
1496 | * @chip: nand chip info structure | 1593 | * @chip: nand chip info structure |
@@ -1863,7 +1960,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
1863 | } | 1960 | } |
1864 | 1961 | ||
1865 | if (unlikely(ops->ooboffs >= len)) { | 1962 | if (unlikely(ops->ooboffs >= len)) { |
1866 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | 1963 | DEBUG(MTD_DEBUG_LEVEL0, "nand_do_write_oob: " |
1867 | "Attempt to start write outside oob\n"); | 1964 | "Attempt to start write outside oob\n"); |
1868 | return -EINVAL; | 1965 | return -EINVAL; |
1869 | } | 1966 | } |
@@ -1873,7 +1970,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
1873 | ops->ooboffs + ops->ooblen > | 1970 | ops->ooboffs + ops->ooblen > |
1874 | ((mtd->size >> chip->page_shift) - | 1971 | ((mtd->size >> chip->page_shift) - |
1875 | (to >> chip->page_shift)) * len)) { | 1972 | (to >> chip->page_shift)) * len)) { |
1876 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | 1973 | DEBUG(MTD_DEBUG_LEVEL0, "nand_do_write_oob: " |
1877 | "Attempt write beyond end of device\n"); | 1974 | "Attempt write beyond end of device\n"); |
1878 | return -EINVAL; | 1975 | return -EINVAL; |
1879 | } | 1976 | } |
@@ -1929,8 +2026,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
1929 | 2026 | ||
1930 | /* Do not allow writes past end of device */ | 2027 | /* Do not allow writes past end of device */ |
1931 | if (ops->datbuf && (to + ops->len) > mtd->size) { | 2028 | if (ops->datbuf && (to + ops->len) > mtd->size) { |
1932 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | 2029 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " |
1933 | "Attempt read beyond end of device\n"); | 2030 | "Attempt write beyond end of device\n"); |
1934 | return -EINVAL; | 2031 | return -EINVAL; |
1935 | } | 2032 | } |
1936 | 2033 | ||
@@ -2555,6 +2652,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2555 | case 64: | 2652 | case 64: |
2556 | chip->ecc.layout = &nand_oob_64; | 2653 | chip->ecc.layout = &nand_oob_64; |
2557 | break; | 2654 | break; |
2655 | case 128: | ||
2656 | chip->ecc.layout = &nand_oob_128; | ||
2657 | break; | ||
2558 | default: | 2658 | default: |
2559 | printk(KERN_WARNING "No oob scheme defined for " | 2659 | printk(KERN_WARNING "No oob scheme defined for " |
2560 | "oobsize %d\n", mtd->oobsize); | 2660 | "oobsize %d\n", mtd->oobsize); |
@@ -2569,10 +2669,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2569 | * check ECC mode, default to software if 3byte/512byte hardware ECC is | 2669 | * check ECC mode, default to software if 3byte/512byte hardware ECC is |
2570 | * selected and we have 256 byte pagesize fallback to software ECC | 2670 | * selected and we have 256 byte pagesize fallback to software ECC |
2571 | */ | 2671 | */ |
2572 | if (!chip->ecc.read_page_raw) | ||
2573 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2574 | if (!chip->ecc.write_page_raw) | ||
2575 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2576 | 2672 | ||
2577 | switch (chip->ecc.mode) { | 2673 | switch (chip->ecc.mode) { |
2578 | case NAND_ECC_HW: | 2674 | case NAND_ECC_HW: |
@@ -2581,6 +2677,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2581 | chip->ecc.read_page = nand_read_page_hwecc; | 2677 | chip->ecc.read_page = nand_read_page_hwecc; |
2582 | if (!chip->ecc.write_page) | 2678 | if (!chip->ecc.write_page) |
2583 | chip->ecc.write_page = nand_write_page_hwecc; | 2679 | chip->ecc.write_page = nand_write_page_hwecc; |
2680 | if (!chip->ecc.read_page_raw) | ||
2681 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2682 | if (!chip->ecc.write_page_raw) | ||
2683 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2584 | if (!chip->ecc.read_oob) | 2684 | if (!chip->ecc.read_oob) |
2585 | chip->ecc.read_oob = nand_read_oob_std; | 2685 | chip->ecc.read_oob = nand_read_oob_std; |
2586 | if (!chip->ecc.write_oob) | 2686 | if (!chip->ecc.write_oob) |
@@ -2602,6 +2702,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2602 | chip->ecc.read_page = nand_read_page_syndrome; | 2702 | chip->ecc.read_page = nand_read_page_syndrome; |
2603 | if (!chip->ecc.write_page) | 2703 | if (!chip->ecc.write_page) |
2604 | chip->ecc.write_page = nand_write_page_syndrome; | 2704 | chip->ecc.write_page = nand_write_page_syndrome; |
2705 | if (!chip->ecc.read_page_raw) | ||
2706 | chip->ecc.read_page_raw = nand_read_page_raw_syndrome; | ||
2707 | if (!chip->ecc.write_page_raw) | ||
2708 | chip->ecc.write_page_raw = nand_write_page_raw_syndrome; | ||
2605 | if (!chip->ecc.read_oob) | 2709 | if (!chip->ecc.read_oob) |
2606 | chip->ecc.read_oob = nand_read_oob_syndrome; | 2710 | chip->ecc.read_oob = nand_read_oob_syndrome; |
2607 | if (!chip->ecc.write_oob) | 2711 | if (!chip->ecc.write_oob) |
@@ -2620,6 +2724,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2620 | chip->ecc.read_page = nand_read_page_swecc; | 2724 | chip->ecc.read_page = nand_read_page_swecc; |
2621 | chip->ecc.read_subpage = nand_read_subpage; | 2725 | chip->ecc.read_subpage = nand_read_subpage; |
2622 | chip->ecc.write_page = nand_write_page_swecc; | 2726 | chip->ecc.write_page = nand_write_page_swecc; |
2727 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2728 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2623 | chip->ecc.read_oob = nand_read_oob_std; | 2729 | chip->ecc.read_oob = nand_read_oob_std; |
2624 | chip->ecc.write_oob = nand_write_oob_std; | 2730 | chip->ecc.write_oob = nand_write_oob_std; |
2625 | chip->ecc.size = 256; | 2731 | chip->ecc.size = 256; |
@@ -2632,6 +2738,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2632 | chip->ecc.read_page = nand_read_page_raw; | 2738 | chip->ecc.read_page = nand_read_page_raw; |
2633 | chip->ecc.write_page = nand_write_page_raw; | 2739 | chip->ecc.write_page = nand_write_page_raw; |
2634 | chip->ecc.read_oob = nand_read_oob_std; | 2740 | chip->ecc.read_oob = nand_read_oob_std; |
2741 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2742 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2635 | chip->ecc.write_oob = nand_write_oob_std; | 2743 | chip->ecc.write_oob = nand_write_oob_std; |
2636 | chip->ecc.size = mtd->writesize; | 2744 | chip->ecc.size = mtd->writesize; |
2637 | chip->ecc.bytes = 0; | 2745 | chip->ecc.bytes = 0; |
@@ -2676,6 +2784,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2676 | break; | 2784 | break; |
2677 | case 4: | 2785 | case 4: |
2678 | case 8: | 2786 | case 8: |
2787 | case 16: | ||
2679 | mtd->subpage_sft = 2; | 2788 | mtd->subpage_sft = 2; |
2680 | break; | 2789 | break; |
2681 | } | 2790 | } |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 75f9f4874ecf..86e1d08eee00 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -30,7 +30,7 @@ struct plat_nand_data { | |||
30 | /* | 30 | /* |
31 | * Probe for the NAND device. | 31 | * Probe for the NAND device. |
32 | */ | 32 | */ |
33 | static int __init plat_nand_probe(struct platform_device *pdev) | 33 | static int __devinit plat_nand_probe(struct platform_device *pdev) |
34 | { | 34 | { |
35 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 35 | struct platform_nand_data *pdata = pdev->dev.platform_data; |
36 | struct plat_nand_data *data; | 36 | struct plat_nand_data *data; |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 61b69cc40009..30a8ce6d3e69 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -170,7 +170,13 @@ static int use_dma = 1; | |||
170 | module_param(use_dma, bool, 0444); | 170 | module_param(use_dma, bool, 0444); |
171 | MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); | 171 | MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); |
172 | 172 | ||
173 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | 173 | /* |
174 | * Default NAND flash controller configuration setup by the | ||
175 | * bootloader. This configuration is used only when pdata->keep_config is set | ||
176 | */ | ||
177 | static struct pxa3xx_nand_timing default_timing; | ||
178 | static struct pxa3xx_nand_flash default_flash; | ||
179 | |||
174 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { | 180 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { |
175 | .read1 = 0x0000, | 181 | .read1 = 0x0000, |
176 | .read2 = 0x0050, | 182 | .read2 = 0x0050, |
@@ -197,6 +203,7 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = { | |||
197 | .lock_status = 0x007A, | 203 | .lock_status = 0x007A, |
198 | }; | 204 | }; |
199 | 205 | ||
206 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | ||
200 | static struct pxa3xx_nand_timing samsung512MbX16_timing = { | 207 | static struct pxa3xx_nand_timing samsung512MbX16_timing = { |
201 | .tCH = 10, | 208 | .tCH = 10, |
202 | .tCS = 0, | 209 | .tCS = 0, |
@@ -296,9 +303,23 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = { | |||
296 | #define NDTR1_tWHR(c) (min((c), 15) << 4) | 303 | #define NDTR1_tWHR(c) (min((c), 15) << 4) |
297 | #define NDTR1_tAR(c) (min((c), 15) << 0) | 304 | #define NDTR1_tAR(c) (min((c), 15) << 0) |
298 | 305 | ||
306 | #define tCH_NDTR0(r) (((r) >> 19) & 0x7) | ||
307 | #define tCS_NDTR0(r) (((r) >> 16) & 0x7) | ||
308 | #define tWH_NDTR0(r) (((r) >> 11) & 0x7) | ||
309 | #define tWP_NDTR0(r) (((r) >> 8) & 0x7) | ||
310 | #define tRH_NDTR0(r) (((r) >> 3) & 0x7) | ||
311 | #define tRP_NDTR0(r) (((r) >> 0) & 0x7) | ||
312 | |||
313 | #define tR_NDTR1(r) (((r) >> 16) & 0xffff) | ||
314 | #define tWHR_NDTR1(r) (((r) >> 4) & 0xf) | ||
315 | #define tAR_NDTR1(r) (((r) >> 0) & 0xf) | ||
316 | |||
299 | /* convert nano-seconds to nand flash controller clock cycles */ | 317 | /* convert nano-seconds to nand flash controller clock cycles */ |
300 | #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) - 1) | 318 | #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) - 1) |
301 | 319 | ||
320 | /* convert nand flash controller clock cycles to nano-seconds */ | ||
321 | #define cycle2ns(c, clk) ((((c) + 1) * 1000000 + clk / 500) / (clk / 1000)) | ||
322 | |||
302 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 323 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, |
303 | const struct pxa3xx_nand_timing *t) | 324 | const struct pxa3xx_nand_timing *t) |
304 | { | 325 | { |
@@ -920,6 +941,82 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
920 | return 0; | 941 | return 0; |
921 | } | 942 | } |
922 | 943 | ||
944 | static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info, | ||
945 | struct pxa3xx_nand_timing *t) | ||
946 | { | ||
947 | unsigned long nand_clk = clk_get_rate(info->clk); | ||
948 | uint32_t ndtr0 = nand_readl(info, NDTR0CS0); | ||
949 | uint32_t ndtr1 = nand_readl(info, NDTR1CS0); | ||
950 | |||
951 | t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk); | ||
952 | t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk); | ||
953 | t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk); | ||
954 | t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk); | ||
955 | t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk); | ||
956 | t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk); | ||
957 | |||
958 | t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk); | ||
959 | t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk); | ||
960 | t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk); | ||
961 | } | ||
962 | |||
963 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | ||
964 | { | ||
965 | uint32_t ndcr = nand_readl(info, NDCR); | ||
966 | struct nand_flash_dev *type = NULL; | ||
967 | uint32_t id = -1; | ||
968 | int i; | ||
969 | |||
970 | default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; | ||
971 | default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | ||
972 | default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; | ||
973 | default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; | ||
974 | |||
975 | if (default_flash.page_size == 2048) | ||
976 | default_flash.cmdset = &largepage_cmdset; | ||
977 | else | ||
978 | default_flash.cmdset = &smallpage_cmdset; | ||
979 | |||
980 | /* set info fields needed to __readid */ | ||
981 | info->flash_info = &default_flash; | ||
982 | info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; | ||
983 | info->reg_ndcr = ndcr; | ||
984 | |||
985 | if (__readid(info, &id)) | ||
986 | return -ENODEV; | ||
987 | |||
988 | /* Lookup the flash id */ | ||
989 | id = (id >> 8) & 0xff; /* device id is byte 2 */ | ||
990 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | ||
991 | if (id == nand_flash_ids[i].id) { | ||
992 | type = &nand_flash_ids[i]; | ||
993 | break; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | if (!type) | ||
998 | return -ENODEV; | ||
999 | |||
1000 | /* fill the missing flash information */ | ||
1001 | i = __ffs(default_flash.page_per_block * default_flash.page_size); | ||
1002 | default_flash.num_blocks = type->chipsize << (20 - i); | ||
1003 | |||
1004 | info->oob_size = (default_flash.page_size == 2048) ? 64 : 16; | ||
1005 | |||
1006 | /* calculate addressing information */ | ||
1007 | info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1; | ||
1008 | |||
1009 | if (default_flash.num_blocks * default_flash.page_per_block > 65536) | ||
1010 | info->row_addr_cycles = 3; | ||
1011 | else | ||
1012 | info->row_addr_cycles = 2; | ||
1013 | |||
1014 | pxa3xx_nand_detect_timing(info, &default_timing); | ||
1015 | default_flash.timing = &default_timing; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
923 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | 1020 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, |
924 | const struct pxa3xx_nand_platform_data *pdata) | 1021 | const struct pxa3xx_nand_platform_data *pdata) |
925 | { | 1022 | { |
@@ -927,6 +1024,10 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | |||
927 | uint32_t id = -1; | 1024 | uint32_t id = -1; |
928 | int i; | 1025 | int i; |
929 | 1026 | ||
1027 | if (pdata->keep_config) | ||
1028 | if (pxa3xx_nand_detect_config(info) == 0) | ||
1029 | return 0; | ||
1030 | |||
930 | for (i = 0; i<pdata->num_flash; ++i) { | 1031 | for (i = 0; i<pdata->num_flash; ++i) { |
931 | f = pdata->flash + i; | 1032 | f = pdata->flash + i; |
932 | 1033 | ||
@@ -1078,6 +1179,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1078 | 1179 | ||
1079 | this = &info->nand_chip; | 1180 | this = &info->nand_chip; |
1080 | mtd->priv = info; | 1181 | mtd->priv = info; |
1182 | mtd->owner = THIS_MODULE; | ||
1081 | 1183 | ||
1082 | info->clk = clk_get(&pdev->dev, NULL); | 1184 | info->clk = clk_get(&pdev->dev, NULL); |
1083 | if (IS_ERR(info->clk)) { | 1185 | if (IS_ERR(info->clk)) { |
@@ -1117,14 +1219,14 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1117 | goto fail_put_clk; | 1219 | goto fail_put_clk; |
1118 | } | 1220 | } |
1119 | 1221 | ||
1120 | r = request_mem_region(r->start, r->end - r->start + 1, pdev->name); | 1222 | r = request_mem_region(r->start, resource_size(r), pdev->name); |
1121 | if (r == NULL) { | 1223 | if (r == NULL) { |
1122 | dev_err(&pdev->dev, "failed to request memory resource\n"); | 1224 | dev_err(&pdev->dev, "failed to request memory resource\n"); |
1123 | ret = -EBUSY; | 1225 | ret = -EBUSY; |
1124 | goto fail_put_clk; | 1226 | goto fail_put_clk; |
1125 | } | 1227 | } |
1126 | 1228 | ||
1127 | info->mmio_base = ioremap(r->start, r->end - r->start + 1); | 1229 | info->mmio_base = ioremap(r->start, resource_size(r)); |
1128 | if (info->mmio_base == NULL) { | 1230 | if (info->mmio_base == NULL) { |
1129 | dev_err(&pdev->dev, "ioremap() failed\n"); | 1231 | dev_err(&pdev->dev, "ioremap() failed\n"); |
1130 | ret = -ENODEV; | 1232 | ret = -ENODEV; |
@@ -1173,7 +1275,7 @@ fail_free_buf: | |||
1173 | fail_free_io: | 1275 | fail_free_io: |
1174 | iounmap(info->mmio_base); | 1276 | iounmap(info->mmio_base); |
1175 | fail_free_res: | 1277 | fail_free_res: |
1176 | release_mem_region(r->start, r->end - r->start + 1); | 1278 | release_mem_region(r->start, resource_size(r)); |
1177 | fail_put_clk: | 1279 | fail_put_clk: |
1178 | clk_disable(info->clk); | 1280 | clk_disable(info->clk); |
1179 | clk_put(info->clk); | 1281 | clk_put(info->clk); |
@@ -1186,6 +1288,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1186 | { | 1288 | { |
1187 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1289 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1188 | struct pxa3xx_nand_info *info = mtd->priv; | 1290 | struct pxa3xx_nand_info *info = mtd->priv; |
1291 | struct resource *r; | ||
1189 | 1292 | ||
1190 | platform_set_drvdata(pdev, NULL); | 1293 | platform_set_drvdata(pdev, NULL); |
1191 | 1294 | ||
@@ -1198,6 +1301,14 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1198 | info->data_buff, info->data_buff_phys); | 1301 | info->data_buff, info->data_buff_phys); |
1199 | } else | 1302 | } else |
1200 | kfree(info->data_buff); | 1303 | kfree(info->data_buff); |
1304 | |||
1305 | iounmap(info->mmio_base); | ||
1306 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1307 | release_mem_region(r->start, resource_size(r)); | ||
1308 | |||
1309 | clk_disable(info->clk); | ||
1310 | clk_put(info->clk); | ||
1311 | |||
1201 | kfree(mtd); | 1312 | kfree(mtd); |
1202 | return 0; | 1313 | return 0; |
1203 | } | 1314 | } |
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 821acb08ff1c..2bc896623e2d 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -58,7 +58,7 @@ static struct nand_bbt_descr flctl_4secc_smallpage = { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct nand_bbt_descr flctl_4secc_largepage = { | 60 | static struct nand_bbt_descr flctl_4secc_largepage = { |
61 | .options = 0, | 61 | .options = NAND_BBT_SCAN2NDPAGE, |
62 | .offs = 58, | 62 | .offs = 58, |
63 | .len = 2, | 63 | .len = 2, |
64 | .pattern = scan_ff_pattern, | 64 | .pattern = scan_ff_pattern, |
@@ -149,7 +149,7 @@ static void wait_wfifo_ready(struct sh_flctl *flctl) | |||
149 | printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n"); | 149 | printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n"); |
150 | } | 150 | } |
151 | 151 | ||
152 | static int wait_recfifo_ready(struct sh_flctl *flctl) | 152 | static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number) |
153 | { | 153 | { |
154 | uint32_t timeout = LOOP_TIMEOUT_MAX; | 154 | uint32_t timeout = LOOP_TIMEOUT_MAX; |
155 | int checked[4]; | 155 | int checked[4]; |
@@ -183,7 +183,12 @@ static int wait_recfifo_ready(struct sh_flctl *flctl) | |||
183 | uint8_t org; | 183 | uint8_t org; |
184 | int index; | 184 | int index; |
185 | 185 | ||
186 | index = data >> 16; | 186 | if (flctl->page_size) |
187 | index = (512 * sector_number) + | ||
188 | (data >> 16); | ||
189 | else | ||
190 | index = data >> 16; | ||
191 | |||
187 | org = flctl->done_buff[index]; | 192 | org = flctl->done_buff[index]; |
188 | flctl->done_buff[index] = org ^ (data & 0xFF); | 193 | flctl->done_buff[index] = org ^ (data & 0xFF); |
189 | checked[i] = 1; | 194 | checked[i] = 1; |
@@ -238,14 +243,14 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) | |||
238 | } | 243 | } |
239 | } | 244 | } |
240 | 245 | ||
241 | static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff) | 246 | static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff, int sector) |
242 | { | 247 | { |
243 | int i; | 248 | int i; |
244 | unsigned long *ecc_buf = (unsigned long *)buff; | 249 | unsigned long *ecc_buf = (unsigned long *)buff; |
245 | void *fifo_addr = (void *)FLECFIFO(flctl); | 250 | void *fifo_addr = (void *)FLECFIFO(flctl); |
246 | 251 | ||
247 | for (i = 0; i < 4; i++) { | 252 | for (i = 0; i < 4; i++) { |
248 | if (wait_recfifo_ready(flctl)) | 253 | if (wait_recfifo_ready(flctl , sector)) |
249 | return 1; | 254 | return 1; |
250 | ecc_buf[i] = readl(fifo_addr); | 255 | ecc_buf[i] = readl(fifo_addr); |
251 | ecc_buf[i] = be32_to_cpu(ecc_buf[i]); | 256 | ecc_buf[i] = be32_to_cpu(ecc_buf[i]); |
@@ -384,7 +389,8 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) | |||
384 | read_fiforeg(flctl, 512, 512 * sector); | 389 | read_fiforeg(flctl, 512, 512 * sector); |
385 | 390 | ||
386 | ret = read_ecfiforeg(flctl, | 391 | ret = read_ecfiforeg(flctl, |
387 | &flctl->done_buff[mtd->writesize + 16 * sector]); | 392 | &flctl->done_buff[mtd->writesize + 16 * sector], |
393 | sector); | ||
388 | 394 | ||
389 | if (ret) | 395 | if (ret) |
390 | flctl->hwecc_cant_correct[sector] = 1; | 396 | flctl->hwecc_cant_correct[sector] = 1; |
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c new file mode 100644 index 000000000000..a4519a7bd683 --- /dev/null +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/socrates_nand.c | ||
3 | * | ||
4 | * Copyright © 2008 Ilya Yanok, Emcraft Systems | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/mtd/mtd.h> | ||
16 | #include <linux/mtd/nand.h> | ||
17 | #include <linux/mtd/partitions.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #define FPGA_NAND_CMD_MASK (0x7 << 28) | ||
22 | #define FPGA_NAND_CMD_COMMAND (0x0 << 28) | ||
23 | #define FPGA_NAND_CMD_ADDR (0x1 << 28) | ||
24 | #define FPGA_NAND_CMD_READ (0x2 << 28) | ||
25 | #define FPGA_NAND_CMD_WRITE (0x3 << 28) | ||
26 | #define FPGA_NAND_BUSY (0x1 << 15) | ||
27 | #define FPGA_NAND_ENABLE (0x1 << 31) | ||
28 | #define FPGA_NAND_DATA_SHIFT 16 | ||
29 | |||
30 | struct socrates_nand_host { | ||
31 | struct nand_chip nand_chip; | ||
32 | struct mtd_info mtd; | ||
33 | void __iomem *io_base; | ||
34 | struct device *dev; | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * socrates_nand_write_buf - write buffer to chip | ||
39 | * @mtd: MTD device structure | ||
40 | * @buf: data buffer | ||
41 | * @len: number of bytes to write | ||
42 | */ | ||
43 | static void socrates_nand_write_buf(struct mtd_info *mtd, | ||
44 | const uint8_t *buf, int len) | ||
45 | { | ||
46 | int i; | ||
47 | struct nand_chip *this = mtd->priv; | ||
48 | struct socrates_nand_host *host = this->priv; | ||
49 | |||
50 | for (i = 0; i < len; i++) { | ||
51 | out_be32(host->io_base, FPGA_NAND_ENABLE | | ||
52 | FPGA_NAND_CMD_WRITE | | ||
53 | (buf[i] << FPGA_NAND_DATA_SHIFT)); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * socrates_nand_read_buf - read chip data into buffer | ||
59 | * @mtd: MTD device structure | ||
60 | * @buf: buffer to store date | ||
61 | * @len: number of bytes to read | ||
62 | */ | ||
63 | static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
64 | { | ||
65 | int i; | ||
66 | struct nand_chip *this = mtd->priv; | ||
67 | struct socrates_nand_host *host = this->priv; | ||
68 | uint32_t val; | ||
69 | |||
70 | val = FPGA_NAND_ENABLE | FPGA_NAND_CMD_READ; | ||
71 | |||
72 | out_be32(host->io_base, val); | ||
73 | for (i = 0; i < len; i++) { | ||
74 | buf[i] = (in_be32(host->io_base) >> | ||
75 | FPGA_NAND_DATA_SHIFT) & 0xff; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * socrates_nand_read_byte - read one byte from the chip | ||
81 | * @mtd: MTD device structure | ||
82 | */ | ||
83 | static uint8_t socrates_nand_read_byte(struct mtd_info *mtd) | ||
84 | { | ||
85 | uint8_t byte; | ||
86 | socrates_nand_read_buf(mtd, &byte, sizeof(byte)); | ||
87 | return byte; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * socrates_nand_read_word - read one word from the chip | ||
92 | * @mtd: MTD device structure | ||
93 | */ | ||
94 | static uint16_t socrates_nand_read_word(struct mtd_info *mtd) | ||
95 | { | ||
96 | uint16_t word; | ||
97 | socrates_nand_read_buf(mtd, (uint8_t *)&word, sizeof(word)); | ||
98 | return word; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * socrates_nand_verify_buf - Verify chip data against buffer | ||
103 | * @mtd: MTD device structure | ||
104 | * @buf: buffer containing the data to compare | ||
105 | * @len: number of bytes to compare | ||
106 | */ | ||
107 | static int socrates_nand_verify_buf(struct mtd_info *mtd, const u8 *buf, | ||
108 | int len) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < len; i++) { | ||
113 | if (buf[i] != socrates_nand_read_byte(mtd)) | ||
114 | return -EFAULT; | ||
115 | } | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Hardware specific access to control-lines | ||
121 | */ | ||
122 | static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, | ||
123 | unsigned int ctrl) | ||
124 | { | ||
125 | struct nand_chip *nand_chip = mtd->priv; | ||
126 | struct socrates_nand_host *host = nand_chip->priv; | ||
127 | uint32_t val; | ||
128 | |||
129 | if (cmd == NAND_CMD_NONE) | ||
130 | return; | ||
131 | |||
132 | if (ctrl & NAND_CLE) | ||
133 | val = FPGA_NAND_CMD_COMMAND; | ||
134 | else | ||
135 | val = FPGA_NAND_CMD_ADDR; | ||
136 | |||
137 | if (ctrl & NAND_NCE) | ||
138 | val |= FPGA_NAND_ENABLE; | ||
139 | |||
140 | val |= (cmd & 0xff) << FPGA_NAND_DATA_SHIFT; | ||
141 | |||
142 | out_be32(host->io_base, val); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Read the Device Ready pin. | ||
147 | */ | ||
148 | static int socrates_nand_device_ready(struct mtd_info *mtd) | ||
149 | { | ||
150 | struct nand_chip *nand_chip = mtd->priv; | ||
151 | struct socrates_nand_host *host = nand_chip->priv; | ||
152 | |||
153 | if (in_be32(host->io_base) & FPGA_NAND_BUSY) | ||
154 | return 0; /* busy */ | ||
155 | return 1; | ||
156 | } | ||
157 | |||
158 | #ifdef CONFIG_MTD_PARTITIONS | ||
159 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
160 | #endif | ||
161 | |||
162 | /* | ||
163 | * Probe for the NAND device. | ||
164 | */ | ||
165 | static int __devinit socrates_nand_probe(struct of_device *ofdev, | ||
166 | const struct of_device_id *ofid) | ||
167 | { | ||
168 | struct socrates_nand_host *host; | ||
169 | struct mtd_info *mtd; | ||
170 | struct nand_chip *nand_chip; | ||
171 | int res; | ||
172 | |||
173 | #ifdef CONFIG_MTD_PARTITIONS | ||
174 | struct mtd_partition *partitions = NULL; | ||
175 | int num_partitions = 0; | ||
176 | #endif | ||
177 | |||
178 | /* Allocate memory for the device structure (and zero it) */ | ||
179 | host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); | ||
180 | if (!host) { | ||
181 | printk(KERN_ERR | ||
182 | "socrates_nand: failed to allocate device structure.\n"); | ||
183 | return -ENOMEM; | ||
184 | } | ||
185 | |||
186 | host->io_base = of_iomap(ofdev->node, 0); | ||
187 | if (host->io_base == NULL) { | ||
188 | printk(KERN_ERR "socrates_nand: ioremap failed\n"); | ||
189 | kfree(host); | ||
190 | return -EIO; | ||
191 | } | ||
192 | |||
193 | mtd = &host->mtd; | ||
194 | nand_chip = &host->nand_chip; | ||
195 | host->dev = &ofdev->dev; | ||
196 | |||
197 | nand_chip->priv = host; /* link the private data structures */ | ||
198 | mtd->priv = nand_chip; | ||
199 | mtd->name = "socrates_nand"; | ||
200 | mtd->owner = THIS_MODULE; | ||
201 | mtd->dev.parent = &ofdev->dev; | ||
202 | |||
203 | /*should never be accessed directly */ | ||
204 | nand_chip->IO_ADDR_R = (void *)0xdeadbeef; | ||
205 | nand_chip->IO_ADDR_W = (void *)0xdeadbeef; | ||
206 | |||
207 | nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; | ||
208 | nand_chip->read_byte = socrates_nand_read_byte; | ||
209 | nand_chip->read_word = socrates_nand_read_word; | ||
210 | nand_chip->write_buf = socrates_nand_write_buf; | ||
211 | nand_chip->read_buf = socrates_nand_read_buf; | ||
212 | nand_chip->verify_buf = socrates_nand_verify_buf; | ||
213 | nand_chip->dev_ready = socrates_nand_device_ready; | ||
214 | |||
215 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ | ||
216 | |||
217 | /* TODO: I have no idea what real delay is. */ | ||
218 | nand_chip->chip_delay = 20; /* 20us command delay time */ | ||
219 | |||
220 | dev_set_drvdata(&ofdev->dev, host); | ||
221 | |||
222 | /* first scan to find the device and get the page size */ | ||
223 | if (nand_scan_ident(mtd, 1)) { | ||
224 | res = -ENXIO; | ||
225 | goto out; | ||
226 | } | ||
227 | |||
228 | /* second phase scan */ | ||
229 | if (nand_scan_tail(mtd)) { | ||
230 | res = -ENXIO; | ||
231 | goto out; | ||
232 | } | ||
233 | |||
234 | #ifdef CONFIG_MTD_PARTITIONS | ||
235 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
236 | num_partitions = parse_mtd_partitions(mtd, part_probes, | ||
237 | &partitions, 0); | ||
238 | if (num_partitions < 0) { | ||
239 | res = num_partitions; | ||
240 | goto release; | ||
241 | } | ||
242 | #endif | ||
243 | |||
244 | #ifdef CONFIG_MTD_OF_PARTS | ||
245 | if (num_partitions == 0) { | ||
246 | num_partitions = of_mtd_parse_partitions(&ofdev->dev, | ||
247 | ofdev->node, | ||
248 | &partitions); | ||
249 | if (num_partitions < 0) { | ||
250 | res = num_partitions; | ||
251 | goto release; | ||
252 | } | ||
253 | } | ||
254 | #endif | ||
255 | if (partitions && (num_partitions > 0)) | ||
256 | res = add_mtd_partitions(mtd, partitions, num_partitions); | ||
257 | else | ||
258 | #endif | ||
259 | res = add_mtd_device(mtd); | ||
260 | |||
261 | if (!res) | ||
262 | return res; | ||
263 | |||
264 | #ifdef CONFIG_MTD_PARTITIONS | ||
265 | release: | ||
266 | #endif | ||
267 | nand_release(mtd); | ||
268 | |||
269 | out: | ||
270 | dev_set_drvdata(&ofdev->dev, NULL); | ||
271 | iounmap(host->io_base); | ||
272 | kfree(host); | ||
273 | return res; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Remove a NAND device. | ||
278 | */ | ||
279 | static int __devexit socrates_nand_remove(struct of_device *ofdev) | ||
280 | { | ||
281 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); | ||
282 | struct mtd_info *mtd = &host->mtd; | ||
283 | |||
284 | nand_release(mtd); | ||
285 | |||
286 | dev_set_drvdata(&ofdev->dev, NULL); | ||
287 | iounmap(host->io_base); | ||
288 | kfree(host); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static struct of_device_id socrates_nand_match[] = | ||
294 | { | ||
295 | { | ||
296 | .compatible = "abb,socrates-nand", | ||
297 | }, | ||
298 | {}, | ||
299 | }; | ||
300 | |||
301 | MODULE_DEVICE_TABLE(of, socrates_nand_match); | ||
302 | |||
303 | static struct of_platform_driver socrates_nand_driver = { | ||
304 | .name = "socrates_nand", | ||
305 | .match_table = socrates_nand_match, | ||
306 | .probe = socrates_nand_probe, | ||
307 | .remove = __devexit_p(socrates_nand_remove), | ||
308 | }; | ||
309 | |||
310 | static int __init socrates_nand_init(void) | ||
311 | { | ||
312 | return of_register_platform_driver(&socrates_nand_driver); | ||
313 | } | ||
314 | |||
315 | static void __exit socrates_nand_exit(void) | ||
316 | { | ||
317 | of_unregister_platform_driver(&socrates_nand_driver); | ||
318 | } | ||
319 | |||
320 | module_init(socrates_nand_init); | ||
321 | module_exit(socrates_nand_exit); | ||
322 | |||
323 | MODULE_LICENSE("GPL"); | ||
324 | MODULE_AUTHOR("Ilya Yanok"); | ||
325 | MODULE_DESCRIPTION("NAND driver for Socrates board"); | ||
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c new file mode 100644 index 000000000000..812479264896 --- /dev/null +++ b/drivers/mtd/nand/txx9ndfmc.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * TXx9 NAND flash memory controller driver | ||
3 | * Based on RBTX49xx patch from CELF patch archive. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * (C) Copyright TOSHIBA CORPORATION 2004-2007 | ||
10 | * All Rights Reserved. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/mtd/mtd.h> | ||
18 | #include <linux/mtd/nand.h> | ||
19 | #include <linux/mtd/nand_ecc.h> | ||
20 | #include <linux/mtd/partitions.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <asm/txx9/ndfmc.h> | ||
23 | |||
24 | /* TXX9 NDFMC Registers */ | ||
25 | #define TXX9_NDFDTR 0x00 | ||
26 | #define TXX9_NDFMCR 0x04 | ||
27 | #define TXX9_NDFSR 0x08 | ||
28 | #define TXX9_NDFISR 0x0c | ||
29 | #define TXX9_NDFIMR 0x10 | ||
30 | #define TXX9_NDFSPR 0x14 | ||
31 | #define TXX9_NDFRSTR 0x18 /* not TX4939 */ | ||
32 | |||
33 | /* NDFMCR : NDFMC Mode Control */ | ||
34 | #define TXX9_NDFMCR_WE 0x80 | ||
35 | #define TXX9_NDFMCR_ECC_ALL 0x60 | ||
36 | #define TXX9_NDFMCR_ECC_RESET 0x60 | ||
37 | #define TXX9_NDFMCR_ECC_READ 0x40 | ||
38 | #define TXX9_NDFMCR_ECC_ON 0x20 | ||
39 | #define TXX9_NDFMCR_ECC_OFF 0x00 | ||
40 | #define TXX9_NDFMCR_CE 0x10 | ||
41 | #define TXX9_NDFMCR_BSPRT 0x04 /* TX4925/TX4926 only */ | ||
42 | #define TXX9_NDFMCR_ALE 0x02 | ||
43 | #define TXX9_NDFMCR_CLE 0x01 | ||
44 | /* TX4939 only */ | ||
45 | #define TXX9_NDFMCR_X16 0x0400 | ||
46 | #define TXX9_NDFMCR_DMAREQ_MASK 0x0300 | ||
47 | #define TXX9_NDFMCR_DMAREQ_NODMA 0x0000 | ||
48 | #define TXX9_NDFMCR_DMAREQ_128 0x0100 | ||
49 | #define TXX9_NDFMCR_DMAREQ_256 0x0200 | ||
50 | #define TXX9_NDFMCR_DMAREQ_512 0x0300 | ||
51 | #define TXX9_NDFMCR_CS_MASK 0x0c | ||
52 | #define TXX9_NDFMCR_CS(ch) ((ch) << 2) | ||
53 | |||
54 | /* NDFMCR : NDFMC Status */ | ||
55 | #define TXX9_NDFSR_BUSY 0x80 | ||
56 | /* TX4939 only */ | ||
57 | #define TXX9_NDFSR_DMARUN 0x40 | ||
58 | |||
59 | /* NDFMCR : NDFMC Reset */ | ||
60 | #define TXX9_NDFRSTR_RST 0x01 | ||
61 | |||
62 | struct txx9ndfmc_priv { | ||
63 | struct platform_device *dev; | ||
64 | struct nand_chip chip; | ||
65 | struct mtd_info mtd; | ||
66 | int cs; | ||
67 | char mtdname[BUS_ID_SIZE + 2]; | ||
68 | }; | ||
69 | |||
70 | #define MAX_TXX9NDFMC_DEV 4 | ||
71 | struct txx9ndfmc_drvdata { | ||
72 | struct mtd_info *mtds[MAX_TXX9NDFMC_DEV]; | ||
73 | void __iomem *base; | ||
74 | unsigned char hold; /* in gbusclock */ | ||
75 | unsigned char spw; /* in gbusclock */ | ||
76 | struct nand_hw_control hw_control; | ||
77 | #ifdef CONFIG_MTD_PARTITIONS | ||
78 | struct mtd_partition *parts[MAX_TXX9NDFMC_DEV]; | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) | ||
83 | { | ||
84 | struct nand_chip *chip = mtd->priv; | ||
85 | struct txx9ndfmc_priv *txx9_priv = chip->priv; | ||
86 | return txx9_priv->dev; | ||
87 | } | ||
88 | |||
89 | static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg) | ||
90 | { | ||
91 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | ||
92 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | ||
93 | |||
94 | return drvdata->base + (reg << plat->shift); | ||
95 | } | ||
96 | |||
97 | static u32 txx9ndfmc_read(struct platform_device *dev, unsigned int reg) | ||
98 | { | ||
99 | return __raw_readl(ndregaddr(dev, reg)); | ||
100 | } | ||
101 | |||
102 | static void txx9ndfmc_write(struct platform_device *dev, | ||
103 | u32 val, unsigned int reg) | ||
104 | { | ||
105 | __raw_writel(val, ndregaddr(dev, reg)); | ||
106 | } | ||
107 | |||
108 | static uint8_t txx9ndfmc_read_byte(struct mtd_info *mtd) | ||
109 | { | ||
110 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
111 | |||
112 | return txx9ndfmc_read(dev, TXX9_NDFDTR); | ||
113 | } | ||
114 | |||
115 | static void txx9ndfmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, | ||
116 | int len) | ||
117 | { | ||
118 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
119 | void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); | ||
120 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); | ||
121 | |||
122 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_WE, TXX9_NDFMCR); | ||
123 | while (len--) | ||
124 | __raw_writel(*buf++, ndfdtr); | ||
125 | txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); | ||
126 | } | ||
127 | |||
128 | static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
129 | { | ||
130 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
131 | void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); | ||
132 | |||
133 | while (len--) | ||
134 | *buf++ = __raw_readl(ndfdtr); | ||
135 | } | ||
136 | |||
137 | static int txx9ndfmc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, | ||
138 | int len) | ||
139 | { | ||
140 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
141 | void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); | ||
142 | |||
143 | while (len--) | ||
144 | if (*buf++ != (uint8_t)__raw_readl(ndfdtr)) | ||
145 | return -EFAULT; | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, | ||
150 | unsigned int ctrl) | ||
151 | { | ||
152 | struct nand_chip *chip = mtd->priv; | ||
153 | struct txx9ndfmc_priv *txx9_priv = chip->priv; | ||
154 | struct platform_device *dev = txx9_priv->dev; | ||
155 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | ||
156 | |||
157 | if (ctrl & NAND_CTRL_CHANGE) { | ||
158 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); | ||
159 | |||
160 | mcr &= ~(TXX9_NDFMCR_CLE | TXX9_NDFMCR_ALE | TXX9_NDFMCR_CE); | ||
161 | mcr |= ctrl & NAND_CLE ? TXX9_NDFMCR_CLE : 0; | ||
162 | mcr |= ctrl & NAND_ALE ? TXX9_NDFMCR_ALE : 0; | ||
163 | /* TXX9_NDFMCR_CE bit is 0:high 1:low */ | ||
164 | mcr |= ctrl & NAND_NCE ? TXX9_NDFMCR_CE : 0; | ||
165 | if (txx9_priv->cs >= 0 && (ctrl & NAND_NCE)) { | ||
166 | mcr &= ~TXX9_NDFMCR_CS_MASK; | ||
167 | mcr |= TXX9_NDFMCR_CS(txx9_priv->cs); | ||
168 | } | ||
169 | txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); | ||
170 | } | ||
171 | if (cmd != NAND_CMD_NONE) | ||
172 | txx9ndfmc_write(dev, cmd & 0xff, TXX9_NDFDTR); | ||
173 | if (plat->flags & NDFMC_PLAT_FLAG_DUMMYWRITE) { | ||
174 | /* dummy write to update external latch */ | ||
175 | if ((ctrl & NAND_CTRL_CHANGE) && cmd == NAND_CMD_NONE) | ||
176 | txx9ndfmc_write(dev, 0, TXX9_NDFDTR); | ||
177 | } | ||
178 | mmiowb(); | ||
179 | } | ||
180 | |||
181 | static int txx9ndfmc_dev_ready(struct mtd_info *mtd) | ||
182 | { | ||
183 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
184 | |||
185 | return !(txx9ndfmc_read(dev, TXX9_NDFSR) & TXX9_NDFSR_BUSY); | ||
186 | } | ||
187 | |||
188 | static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, | ||
189 | uint8_t *ecc_code) | ||
190 | { | ||
191 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
192 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); | ||
193 | |||
194 | mcr &= ~TXX9_NDFMCR_ECC_ALL; | ||
195 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); | ||
196 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_READ, TXX9_NDFMCR); | ||
197 | ecc_code[1] = txx9ndfmc_read(dev, TXX9_NDFDTR); | ||
198 | ecc_code[0] = txx9ndfmc_read(dev, TXX9_NDFDTR); | ||
199 | ecc_code[2] = txx9ndfmc_read(dev, TXX9_NDFDTR); | ||
200 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
205 | { | ||
206 | struct platform_device *dev = mtd_to_platdev(mtd); | ||
207 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); | ||
208 | |||
209 | mcr &= ~TXX9_NDFMCR_ECC_ALL; | ||
210 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_RESET, TXX9_NDFMCR); | ||
211 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); | ||
212 | txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_ON, TXX9_NDFMCR); | ||
213 | } | ||
214 | |||
215 | static void txx9ndfmc_initialize(struct platform_device *dev) | ||
216 | { | ||
217 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | ||
218 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | ||
219 | int tmout = 100; | ||
220 | |||
221 | if (plat->flags & NDFMC_PLAT_FLAG_NO_RSTR) | ||
222 | ; /* no NDFRSTR. Write to NDFSPR resets the NDFMC. */ | ||
223 | else { | ||
224 | /* reset NDFMC */ | ||
225 | txx9ndfmc_write(dev, | ||
226 | txx9ndfmc_read(dev, TXX9_NDFRSTR) | | ||
227 | TXX9_NDFRSTR_RST, | ||
228 | TXX9_NDFRSTR); | ||
229 | while (txx9ndfmc_read(dev, TXX9_NDFRSTR) & TXX9_NDFRSTR_RST) { | ||
230 | if (--tmout == 0) { | ||
231 | dev_err(&dev->dev, "reset failed.\n"); | ||
232 | break; | ||
233 | } | ||
234 | udelay(1); | ||
235 | } | ||
236 | } | ||
237 | /* setup Hold Time, Strobe Pulse Width */ | ||
238 | txx9ndfmc_write(dev, (drvdata->hold << 4) | drvdata->spw, TXX9_NDFSPR); | ||
239 | txx9ndfmc_write(dev, | ||
240 | (plat->flags & NDFMC_PLAT_FLAG_USE_BSPRT) ? | ||
241 | TXX9_NDFMCR_BSPRT : 0, TXX9_NDFMCR); | ||
242 | } | ||
243 | |||
244 | #define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \ | ||
245 | DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000) | ||
246 | |||
247 | static int __init txx9ndfmc_probe(struct platform_device *dev) | ||
248 | { | ||
249 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | ||
250 | #ifdef CONFIG_MTD_PARTITIONS | ||
251 | static const char *probes[] = { "cmdlinepart", NULL }; | ||
252 | #endif | ||
253 | int hold, spw; | ||
254 | int i; | ||
255 | struct txx9ndfmc_drvdata *drvdata; | ||
256 | unsigned long gbusclk = plat->gbus_clock; | ||
257 | struct resource *res; | ||
258 | |||
259 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
260 | if (!res) | ||
261 | return -ENODEV; | ||
262 | drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
263 | if (!drvdata) | ||
264 | return -ENOMEM; | ||
265 | if (!devm_request_mem_region(&dev->dev, res->start, | ||
266 | resource_size(res), dev_name(&dev->dev))) | ||
267 | return -EBUSY; | ||
268 | drvdata->base = devm_ioremap(&dev->dev, res->start, | ||
269 | resource_size(res)); | ||
270 | if (!drvdata->base) | ||
271 | return -EBUSY; | ||
272 | |||
273 | hold = plat->hold ?: 20; /* tDH */ | ||
274 | spw = plat->spw ?: 90; /* max(tREADID, tWP, tRP) */ | ||
275 | |||
276 | hold = TXX9NDFMC_NS_TO_CYC(gbusclk, hold); | ||
277 | spw = TXX9NDFMC_NS_TO_CYC(gbusclk, spw); | ||
278 | if (plat->flags & NDFMC_PLAT_FLAG_HOLDADD) | ||
279 | hold -= 2; /* actual hold time : (HOLD + 2) BUSCLK */ | ||
280 | spw -= 1; /* actual wait time : (SPW + 1) BUSCLK */ | ||
281 | hold = clamp(hold, 1, 15); | ||
282 | drvdata->hold = hold; | ||
283 | spw = clamp(spw, 1, 15); | ||
284 | drvdata->spw = spw; | ||
285 | dev_info(&dev->dev, "CLK:%ldMHz HOLD:%d SPW:%d\n", | ||
286 | (gbusclk + 500000) / 1000000, hold, spw); | ||
287 | |||
288 | spin_lock_init(&drvdata->hw_control.lock); | ||
289 | init_waitqueue_head(&drvdata->hw_control.wq); | ||
290 | |||
291 | platform_set_drvdata(dev, drvdata); | ||
292 | txx9ndfmc_initialize(dev); | ||
293 | |||
294 | for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { | ||
295 | struct txx9ndfmc_priv *txx9_priv; | ||
296 | struct nand_chip *chip; | ||
297 | struct mtd_info *mtd; | ||
298 | #ifdef CONFIG_MTD_PARTITIONS | ||
299 | int nr_parts; | ||
300 | #endif | ||
301 | |||
302 | if (!(plat->ch_mask & (1 << i))) | ||
303 | continue; | ||
304 | txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv), | ||
305 | GFP_KERNEL); | ||
306 | if (!txx9_priv) { | ||
307 | dev_err(&dev->dev, "Unable to allocate " | ||
308 | "TXx9 NDFMC MTD device structure.\n"); | ||
309 | continue; | ||
310 | } | ||
311 | chip = &txx9_priv->chip; | ||
312 | mtd = &txx9_priv->mtd; | ||
313 | mtd->owner = THIS_MODULE; | ||
314 | |||
315 | mtd->priv = chip; | ||
316 | |||
317 | chip->read_byte = txx9ndfmc_read_byte; | ||
318 | chip->read_buf = txx9ndfmc_read_buf; | ||
319 | chip->write_buf = txx9ndfmc_write_buf; | ||
320 | chip->verify_buf = txx9ndfmc_verify_buf; | ||
321 | chip->cmd_ctrl = txx9ndfmc_cmd_ctrl; | ||
322 | chip->dev_ready = txx9ndfmc_dev_ready; | ||
323 | chip->ecc.calculate = txx9ndfmc_calculate_ecc; | ||
324 | chip->ecc.correct = nand_correct_data; | ||
325 | chip->ecc.hwctl = txx9ndfmc_enable_hwecc; | ||
326 | chip->ecc.mode = NAND_ECC_HW; | ||
327 | chip->ecc.size = 256; | ||
328 | chip->ecc.bytes = 3; | ||
329 | chip->chip_delay = 100; | ||
330 | chip->controller = &drvdata->hw_control; | ||
331 | |||
332 | chip->priv = txx9_priv; | ||
333 | txx9_priv->dev = dev; | ||
334 | |||
335 | if (plat->ch_mask != 1) { | ||
336 | txx9_priv->cs = i; | ||
337 | sprintf(txx9_priv->mtdname, "%s.%u", | ||
338 | dev_name(&dev->dev), i); | ||
339 | } else { | ||
340 | txx9_priv->cs = -1; | ||
341 | strcpy(txx9_priv->mtdname, dev_name(&dev->dev)); | ||
342 | } | ||
343 | if (plat->wide_mask & (1 << i)) | ||
344 | chip->options |= NAND_BUSWIDTH_16; | ||
345 | |||
346 | if (nand_scan(mtd, 1)) { | ||
347 | kfree(txx9_priv); | ||
348 | continue; | ||
349 | } | ||
350 | mtd->name = txx9_priv->mtdname; | ||
351 | |||
352 | #ifdef CONFIG_MTD_PARTITIONS | ||
353 | nr_parts = parse_mtd_partitions(mtd, probes, | ||
354 | &drvdata->parts[i], 0); | ||
355 | if (nr_parts > 0) | ||
356 | add_mtd_partitions(mtd, drvdata->parts[i], nr_parts); | ||
357 | #endif | ||
358 | add_mtd_device(mtd); | ||
359 | drvdata->mtds[i] = mtd; | ||
360 | } | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int __exit txx9ndfmc_remove(struct platform_device *dev) | ||
366 | { | ||
367 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | ||
368 | int i; | ||
369 | |||
370 | platform_set_drvdata(dev, NULL); | ||
371 | if (!drvdata) | ||
372 | return 0; | ||
373 | for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { | ||
374 | struct mtd_info *mtd = drvdata->mtds[i]; | ||
375 | struct nand_chip *chip; | ||
376 | struct txx9ndfmc_priv *txx9_priv; | ||
377 | |||
378 | if (!mtd) | ||
379 | continue; | ||
380 | chip = mtd->priv; | ||
381 | txx9_priv = chip->priv; | ||
382 | |||
383 | #ifdef CONFIG_MTD_PARTITIONS | ||
384 | del_mtd_partitions(mtd); | ||
385 | kfree(drvdata->parts[i]); | ||
386 | #endif | ||
387 | del_mtd_device(mtd); | ||
388 | kfree(txx9_priv); | ||
389 | } | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | #ifdef CONFIG_PM | ||
394 | static int txx9ndfmc_resume(struct platform_device *dev) | ||
395 | { | ||
396 | if (platform_get_drvdata(dev)) | ||
397 | txx9ndfmc_initialize(dev); | ||
398 | return 0; | ||
399 | } | ||
400 | #else | ||
401 | #define txx9ndfmc_resume NULL | ||
402 | #endif | ||
403 | |||
404 | static struct platform_driver txx9ndfmc_driver = { | ||
405 | .remove = __exit_p(txx9ndfmc_remove), | ||
406 | .resume = txx9ndfmc_resume, | ||
407 | .driver = { | ||
408 | .name = "txx9ndfmc", | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static int __init txx9ndfmc_init(void) | ||
414 | { | ||
415 | return platform_driver_probe(&txx9ndfmc_driver, txx9ndfmc_probe); | ||
416 | } | ||
417 | |||
418 | static void __exit txx9ndfmc_exit(void) | ||
419 | { | ||
420 | platform_driver_unregister(&txx9ndfmc_driver); | ||
421 | } | ||
422 | |||
423 | module_init(txx9ndfmc_init); | ||
424 | module_exit(txx9ndfmc_exit); | ||
425 | |||
426 | MODULE_LICENSE("GPL"); | ||
427 | MODULE_DESCRIPTION("TXx9 SoC NAND flash controller driver"); | ||
428 | MODULE_ALIAS("platform:txx9ndfmc"); | ||