diff options
-rw-r--r-- | arch/powerpc/Kconfig | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/fsl_lbc.h | 33 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_lbc.c | 231 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_elbc_nand.c | 482 |
5 files changed, 426 insertions, 328 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 631e5a0fb6ab..44df1bac9701 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -687,9 +687,12 @@ config 4xx_SOC | |||
687 | bool | 687 | bool |
688 | 688 | ||
689 | config FSL_LBC | 689 | config FSL_LBC |
690 | bool | 690 | bool "Freescale Local Bus support" |
691 | depends on FSL_SOC | ||
691 | help | 692 | help |
692 | Freescale Localbus support | 693 | Enables reporting of errors from the Freescale local bus |
694 | controller. Also contains some common code used by | ||
695 | drivers for specific local bus peripherals. | ||
693 | 696 | ||
694 | config FSL_GTM | 697 | config FSL_GTM |
695 | bool | 698 | bool |
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 1b5a21041f9b..06a11124dde1 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h | |||
@@ -1,9 +1,10 @@ | |||
1 | /* Freescale Local Bus Controller | 1 | /* Freescale Local Bus Controller |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -26,6 +27,8 @@ | |||
26 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
27 | #include <linux/types.h> | 28 | #include <linux/types.h> |
28 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/device.h> | ||
31 | #include <linux/spinlock.h> | ||
29 | 32 | ||
30 | struct fsl_lbc_bank { | 33 | struct fsl_lbc_bank { |
31 | __be32 br; /**< Base Register */ | 34 | __be32 br; /**< Base Register */ |
@@ -125,13 +128,23 @@ struct fsl_lbc_regs { | |||
125 | #define LTESR_ATMW 0x00800000 | 128 | #define LTESR_ATMW 0x00800000 |
126 | #define LTESR_ATMR 0x00400000 | 129 | #define LTESR_ATMR 0x00400000 |
127 | #define LTESR_CS 0x00080000 | 130 | #define LTESR_CS 0x00080000 |
131 | #define LTESR_UPM 0x00000002 | ||
128 | #define LTESR_CC 0x00000001 | 132 | #define LTESR_CC 0x00000001 |
129 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) | 133 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) |
134 | #define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \ | ||
135 | | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \ | ||
136 | | LTESR_CC) | ||
137 | #define LTESR_CLEAR 0xFFFFFFFF | ||
138 | #define LTECCR_CLEAR 0xFFFFFFFF | ||
139 | #define LTESR_STATUS LTESR_MASK | ||
140 | #define LTEIR_ENABLE LTESR_MASK | ||
141 | #define LTEDR_ENABLE 0x00000000 | ||
130 | __be32 ltedr; /**< Transfer Error Disable Register */ | 142 | __be32 ltedr; /**< Transfer Error Disable Register */ |
131 | __be32 lteir; /**< Transfer Error Interrupt Register */ | 143 | __be32 lteir; /**< Transfer Error Interrupt Register */ |
132 | __be32 lteatr; /**< Transfer Error Attributes Register */ | 144 | __be32 lteatr; /**< Transfer Error Attributes Register */ |
133 | __be32 ltear; /**< Transfer Error Address Register */ | 145 | __be32 ltear; /**< Transfer Error Address Register */ |
134 | u8 res6[0xC]; | 146 | __be32 lteccr; /**< Transfer Error ECC Register */ |
147 | u8 res6[0x8]; | ||
135 | __be32 lbcr; /**< Configuration Register */ | 148 | __be32 lbcr; /**< Configuration Register */ |
136 | #define LBCR_LDIS 0x80000000 | 149 | #define LBCR_LDIS 0x80000000 |
137 | #define LBCR_LDIS_SHIFT 31 | 150 | #define LBCR_LDIS_SHIFT 31 |
@@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm) | |||
265 | cpu_relax(); | 278 | cpu_relax(); |
266 | } | 279 | } |
267 | 280 | ||
281 | /* overview of the fsl lbc controller */ | ||
282 | |||
283 | struct fsl_lbc_ctrl { | ||
284 | /* device info */ | ||
285 | struct device *dev; | ||
286 | struct fsl_lbc_regs __iomem *regs; | ||
287 | int irq; | ||
288 | wait_queue_head_t irq_wait; | ||
289 | spinlock_t lock; | ||
290 | void *nand; | ||
291 | |||
292 | /* status read from LTESR by irq handler */ | ||
293 | unsigned int irq_status; | ||
294 | }; | ||
295 | |||
268 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, | 296 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, |
269 | u32 mar); | 297 | u32 mar); |
298 | extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; | ||
270 | 299 | ||
271 | #endif /* __ASM_FSL_LBC_H */ | 300 | #endif /* __ASM_FSL_LBC_H */ |
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index dceb8d1a843d..91c9c53b1845 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale LBC and UPM routines. | 2 | * Freescale LBC and UPM routines. |
3 | * | 3 | * |
4 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | 4 | * Copyright © 2007-2008 MontaVista Software, Inc. |
5 | * Copyright © 2010 Freescale Semiconductor | ||
5 | * | 6 | * |
6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | 7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> |
8 | * Author: Jack Lan <Jack.Lan@freescale.com> | ||
9 | * Author: Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 10 | * |
8 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -19,39 +22,16 @@ | |||
19 | #include <linux/types.h> | 22 | #include <linux/types.h> |
20 | #include <linux/io.h> | 23 | #include <linux/io.h> |
21 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/slab.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/mod_devicetable.h> | ||
22 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
23 | #include <asm/fsl_lbc.h> | 30 | #include <asm/fsl_lbc.h> |
24 | 31 | ||
25 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); | 32 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); |
26 | static struct fsl_lbc_regs __iomem *fsl_lbc_regs; | 33 | struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; |
27 | 34 | EXPORT_SYMBOL(fsl_lbc_ctrl_dev); | |
28 | static char __initdata *compat_lbc[] = { | ||
29 | "fsl,pq2-localbus", | ||
30 | "fsl,pq2pro-localbus", | ||
31 | "fsl,pq3-localbus", | ||
32 | "fsl,elbc", | ||
33 | }; | ||
34 | |||
35 | static int __init fsl_lbc_init(void) | ||
36 | { | ||
37 | struct device_node *lbus; | ||
38 | int i; | ||
39 | |||
40 | for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { | ||
41 | lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); | ||
42 | if (lbus) | ||
43 | goto found; | ||
44 | } | ||
45 | return -ENODEV; | ||
46 | |||
47 | found: | ||
48 | fsl_lbc_regs = of_iomap(lbus, 0); | ||
49 | of_node_put(lbus); | ||
50 | if (!fsl_lbc_regs) | ||
51 | return -ENOMEM; | ||
52 | return 0; | ||
53 | } | ||
54 | arch_initcall(fsl_lbc_init); | ||
55 | 35 | ||
56 | /** | 36 | /** |
57 | * fsl_lbc_find - find Localbus bank | 37 | * fsl_lbc_find - find Localbus bank |
@@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init); | |||
65 | int fsl_lbc_find(phys_addr_t addr_base) | 45 | int fsl_lbc_find(phys_addr_t addr_base) |
66 | { | 46 | { |
67 | int i; | 47 | int i; |
48 | struct fsl_lbc_regs __iomem *lbc; | ||
68 | 49 | ||
69 | if (!fsl_lbc_regs) | 50 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
70 | return -ENODEV; | 51 | return -ENODEV; |
71 | 52 | ||
72 | for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { | 53 | lbc = fsl_lbc_ctrl_dev->regs; |
73 | __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); | 54 | for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) { |
74 | __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); | 55 | __be32 br = in_be32(&lbc->bank[i].br); |
56 | __be32 or = in_be32(&lbc->bank[i].or); | ||
75 | 57 | ||
76 | if (br & BR_V && (br & or & BR_BA) == addr_base) | 58 | if (br & BR_V && (br & or & BR_BA) == addr_base) |
77 | return i; | 59 | return i; |
@@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) | |||
94 | { | 76 | { |
95 | int bank; | 77 | int bank; |
96 | __be32 br; | 78 | __be32 br; |
79 | struct fsl_lbc_regs __iomem *lbc; | ||
97 | 80 | ||
98 | bank = fsl_lbc_find(addr_base); | 81 | bank = fsl_lbc_find(addr_base); |
99 | if (bank < 0) | 82 | if (bank < 0) |
100 | return bank; | 83 | return bank; |
101 | 84 | ||
102 | br = in_be32(&fsl_lbc_regs->bank[bank].br); | 85 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
86 | return -ENODEV; | ||
87 | |||
88 | lbc = fsl_lbc_ctrl_dev->regs; | ||
89 | br = in_be32(&lbc->bank[bank].br); | ||
103 | 90 | ||
104 | switch (br & BR_MSEL) { | 91 | switch (br & BR_MSEL) { |
105 | case BR_MS_UPMA: | 92 | case BR_MS_UPMA: |
106 | upm->mxmr = &fsl_lbc_regs->mamr; | 93 | upm->mxmr = &lbc->mamr; |
107 | break; | 94 | break; |
108 | case BR_MS_UPMB: | 95 | case BR_MS_UPMB: |
109 | upm->mxmr = &fsl_lbc_regs->mbmr; | 96 | upm->mxmr = &lbc->mbmr; |
110 | break; | 97 | break; |
111 | case BR_MS_UPMC: | 98 | case BR_MS_UPMC: |
112 | upm->mxmr = &fsl_lbc_regs->mcmr; | 99 | upm->mxmr = &lbc->mcmr; |
113 | break; | 100 | break; |
114 | default: | 101 | default: |
115 | return -EINVAL; | 102 | return -EINVAL; |
@@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
148 | int ret = 0; | 135 | int ret = 0; |
149 | unsigned long flags; | 136 | unsigned long flags; |
150 | 137 | ||
138 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
139 | return -ENODEV; | ||
140 | |||
151 | spin_lock_irqsave(&fsl_lbc_lock, flags); | 141 | spin_lock_irqsave(&fsl_lbc_lock, flags); |
152 | 142 | ||
153 | out_be32(&fsl_lbc_regs->mar, mar); | 143 | out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar); |
154 | 144 | ||
155 | switch (upm->width) { | 145 | switch (upm->width) { |
156 | case 8: | 146 | case 8: |
@@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
172 | return ret; | 162 | return ret; |
173 | } | 163 | } |
174 | EXPORT_SYMBOL(fsl_upm_run_pattern); | 164 | EXPORT_SYMBOL(fsl_upm_run_pattern); |
165 | |||
166 | static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl) | ||
167 | { | ||
168 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
169 | |||
170 | /* clear event registers */ | ||
171 | setbits32(&lbc->ltesr, LTESR_CLEAR); | ||
172 | out_be32(&lbc->lteatr, 0); | ||
173 | out_be32(&lbc->ltear, 0); | ||
174 | out_be32(&lbc->lteccr, LTECCR_CLEAR); | ||
175 | out_be32(&lbc->ltedr, LTEDR_ENABLE); | ||
176 | |||
177 | /* Enable interrupts for any detected events */ | ||
178 | out_be32(&lbc->lteir, LTEIR_ENABLE); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * NOTE: This interrupt is used to report localbus events of various kinds, | ||
185 | * such as transaction errors on the chipselects. | ||
186 | */ | ||
187 | |||
188 | static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data) | ||
189 | { | ||
190 | struct fsl_lbc_ctrl *ctrl = data; | ||
191 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
192 | u32 status; | ||
193 | |||
194 | status = in_be32(&lbc->ltesr); | ||
195 | if (!status) | ||
196 | return IRQ_NONE; | ||
197 | |||
198 | out_be32(&lbc->ltesr, LTESR_CLEAR); | ||
199 | out_be32(&lbc->lteatr, 0); | ||
200 | out_be32(&lbc->ltear, 0); | ||
201 | ctrl->irq_status = status; | ||
202 | |||
203 | if (status & LTESR_BM) | ||
204 | dev_err(ctrl->dev, "Local bus monitor time-out: " | ||
205 | "LTESR 0x%08X\n", status); | ||
206 | if (status & LTESR_WP) | ||
207 | dev_err(ctrl->dev, "Write protect error: " | ||
208 | "LTESR 0x%08X\n", status); | ||
209 | if (status & LTESR_ATMW) | ||
210 | dev_err(ctrl->dev, "Atomic write error: " | ||
211 | "LTESR 0x%08X\n", status); | ||
212 | if (status & LTESR_ATMR) | ||
213 | dev_err(ctrl->dev, "Atomic read error: " | ||
214 | "LTESR 0x%08X\n", status); | ||
215 | if (status & LTESR_CS) | ||
216 | dev_err(ctrl->dev, "Chip select error: " | ||
217 | "LTESR 0x%08X\n", status); | ||
218 | if (status & LTESR_UPM) | ||
219 | ; | ||
220 | if (status & LTESR_FCT) { | ||
221 | dev_err(ctrl->dev, "FCM command time-out: " | ||
222 | "LTESR 0x%08X\n", status); | ||
223 | smp_wmb(); | ||
224 | wake_up(&ctrl->irq_wait); | ||
225 | } | ||
226 | if (status & LTESR_PAR) { | ||
227 | dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: " | ||
228 | "LTESR 0x%08X\n", status); | ||
229 | smp_wmb(); | ||
230 | wake_up(&ctrl->irq_wait); | ||
231 | } | ||
232 | if (status & LTESR_CC) { | ||
233 | smp_wmb(); | ||
234 | wake_up(&ctrl->irq_wait); | ||
235 | } | ||
236 | if (status & ~LTESR_MASK) | ||
237 | dev_err(ctrl->dev, "Unknown error: " | ||
238 | "LTESR 0x%08X\n", status); | ||
239 | return IRQ_HANDLED; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * fsl_lbc_ctrl_probe | ||
244 | * | ||
245 | * called by device layer when it finds a device matching | ||
246 | * one our driver can handled. This code allocates all of | ||
247 | * the resources needed for the controller only. The | ||
248 | * resources for the NAND banks themselves are allocated | ||
249 | * in the chip probe function. | ||
250 | */ | ||
251 | |||
252 | static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) | ||
253 | { | ||
254 | int ret; | ||
255 | |||
256 | if (!dev->dev.of_node) { | ||
257 | dev_err(&dev->dev, "Device OF-Node is NULL"); | ||
258 | return -EFAULT; | ||
259 | } | ||
260 | |||
261 | fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL); | ||
262 | if (!fsl_lbc_ctrl_dev) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev); | ||
266 | |||
267 | spin_lock_init(&fsl_lbc_ctrl_dev->lock); | ||
268 | init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait); | ||
269 | |||
270 | fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); | ||
271 | if (!fsl_lbc_ctrl_dev->regs) { | ||
272 | dev_err(&dev->dev, "failed to get memory region\n"); | ||
273 | ret = -ENODEV; | ||
274 | goto err; | ||
275 | } | ||
276 | |||
277 | fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | ||
278 | if (fsl_lbc_ctrl_dev->irq == NO_IRQ) { | ||
279 | dev_err(&dev->dev, "failed to get irq resource\n"); | ||
280 | ret = -ENODEV; | ||
281 | goto err; | ||
282 | } | ||
283 | |||
284 | fsl_lbc_ctrl_dev->dev = &dev->dev; | ||
285 | |||
286 | ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev); | ||
287 | if (ret < 0) | ||
288 | goto err; | ||
289 | |||
290 | ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0, | ||
291 | "fsl-lbc", fsl_lbc_ctrl_dev); | ||
292 | if (ret != 0) { | ||
293 | dev_err(&dev->dev, "failed to install irq (%d)\n", | ||
294 | fsl_lbc_ctrl_dev->irq); | ||
295 | ret = fsl_lbc_ctrl_dev->irq; | ||
296 | goto err; | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | |||
301 | err: | ||
302 | iounmap(fsl_lbc_ctrl_dev->regs); | ||
303 | kfree(fsl_lbc_ctrl_dev); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static const struct of_device_id fsl_lbc_match[] = { | ||
308 | { .compatible = "fsl,elbc", }, | ||
309 | { .compatible = "fsl,pq3-localbus", }, | ||
310 | { .compatible = "fsl,pq2-localbus", }, | ||
311 | { .compatible = "fsl,pq2pro-localbus", }, | ||
312 | {}, | ||
313 | }; | ||
314 | |||
315 | static struct platform_driver fsl_lbc_ctrl_driver = { | ||
316 | .driver = { | ||
317 | .name = "fsl-lbc", | ||
318 | .of_match_table = fsl_lbc_match, | ||
319 | }, | ||
320 | .probe = fsl_lbc_ctrl_probe, | ||
321 | }; | ||
322 | |||
323 | static int __init fsl_lbc_init(void) | ||
324 | { | ||
325 | return platform_driver_register(&fsl_lbc_ctrl_driver); | ||
326 | } | ||
327 | module_init(fsl_lbc_init); | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index a494cce704b9..8229802b4346 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -451,6 +451,7 @@ config MTD_NAND_ORION | |||
451 | config MTD_NAND_FSL_ELBC | 451 | config MTD_NAND_FSL_ELBC |
452 | tristate "NAND support for Freescale eLBC controllers" | 452 | tristate "NAND support for Freescale eLBC controllers" |
453 | depends on PPC_OF | 453 | depends on PPC_OF |
454 | select FSL_LBC | ||
454 | help | 455 | help |
455 | Various Freescale chips, including the 8313, include a NAND Flash | 456 | Various Freescale chips, including the 8313, include a NAND Flash |
456 | Controller Module with built-in hardware ECC capabilities. | 457 | Controller Module with built-in hardware ECC capabilities. |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 80de0bff6c3a..cd8de29e38cc 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -1,9 +1,11 @@ | |||
1 | /* Freescale Enhanced Local Bus Controller NAND driver | 1 | /* Freescale Enhanced Local Bus Controller NAND driver |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
8 | * Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -27,6 +29,7 @@ | |||
27 | #include <linux/string.h> | 29 | #include <linux/string.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
29 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
32 | #include <linux/platform_device.h> | ||
30 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
31 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
32 | 35 | ||
@@ -42,14 +45,12 @@ | |||
42 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ | 45 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ |
43 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ | 46 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ |
44 | 47 | ||
45 | struct fsl_elbc_ctrl; | ||
46 | |||
47 | /* mtd information per set */ | 48 | /* mtd information per set */ |
48 | 49 | ||
49 | struct fsl_elbc_mtd { | 50 | struct fsl_elbc_mtd { |
50 | struct mtd_info mtd; | 51 | struct mtd_info mtd; |
51 | struct nand_chip chip; | 52 | struct nand_chip chip; |
52 | struct fsl_elbc_ctrl *ctrl; | 53 | struct fsl_lbc_ctrl *ctrl; |
53 | 54 | ||
54 | struct device *dev; | 55 | struct device *dev; |
55 | int bank; /* Chip select bank number */ | 56 | int bank; /* Chip select bank number */ |
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd { | |||
58 | unsigned int fmr; /* FCM Flash Mode Register value */ | 59 | unsigned int fmr; /* FCM Flash Mode Register value */ |
59 | }; | 60 | }; |
60 | 61 | ||
61 | /* overview of the fsl elbc controller */ | 62 | /* Freescale eLBC FCM controller infomation */ |
62 | 63 | ||
63 | struct fsl_elbc_ctrl { | 64 | struct fsl_elbc_fcm_ctrl { |
64 | struct nand_hw_control controller; | 65 | struct nand_hw_control controller; |
65 | struct fsl_elbc_mtd *chips[MAX_BANKS]; | 66 | struct fsl_elbc_mtd *chips[MAX_BANKS]; |
66 | 67 | ||
67 | /* device info */ | ||
68 | struct device *dev; | ||
69 | struct fsl_lbc_regs __iomem *regs; | ||
70 | int irq; | ||
71 | wait_queue_head_t irq_wait; | ||
72 | unsigned int irq_status; /* status read from LTESR by irq handler */ | ||
73 | u8 __iomem *addr; /* Address of assigned FCM buffer */ | 68 | u8 __iomem *addr; /* Address of assigned FCM buffer */ |
74 | unsigned int page; /* Last page written to / read from */ | 69 | unsigned int page; /* Last page written to / read from */ |
75 | unsigned int read_bytes; /* Number of bytes read during command */ | 70 | unsigned int read_bytes; /* Number of bytes read during command */ |
@@ -79,6 +74,7 @@ struct fsl_elbc_ctrl { | |||
79 | unsigned int mdr; /* UPM/FCM Data Register value */ | 74 | unsigned int mdr; /* UPM/FCM Data Register value */ |
80 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | 75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ |
81 | unsigned int oob; /* Non zero if operating on OOB data */ | 76 | unsigned int oob; /* Non zero if operating on OOB data */ |
77 | unsigned int counter; /* counter for the initializations */ | ||
82 | char *oob_poi; /* Place to write ECC after read back */ | 78 | char *oob_poi; /* Place to write ECC after read back */ |
83 | }; | 79 | }; |
84 | 80 | ||
@@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
164 | { | 160 | { |
165 | struct nand_chip *chip = mtd->priv; | 161 | struct nand_chip *chip = mtd->priv; |
166 | struct fsl_elbc_mtd *priv = chip->priv; | 162 | struct fsl_elbc_mtd *priv = chip->priv; |
167 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 163 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
168 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 164 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
165 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
169 | int buf_num; | 166 | int buf_num; |
170 | 167 | ||
171 | ctrl->page = page_addr; | 168 | elbc_fcm_ctrl->page = page_addr; |
172 | 169 | ||
173 | out_be32(&lbc->fbar, | 170 | out_be32(&lbc->fbar, |
174 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); | 171 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); |
@@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
185 | buf_num = page_addr & 7; | 182 | buf_num = page_addr & 7; |
186 | } | 183 | } |
187 | 184 | ||
188 | ctrl->addr = priv->vbase + buf_num * 1024; | 185 | elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024; |
189 | ctrl->index = column; | 186 | elbc_fcm_ctrl->index = column; |
190 | 187 | ||
191 | /* for OOB data point to the second half of the buffer */ | 188 | /* for OOB data point to the second half of the buffer */ |
192 | if (oob) | 189 | if (oob) |
193 | ctrl->index += priv->page_size ? 2048 : 512; | 190 | elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512; |
194 | 191 | ||
195 | dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), " | 192 | dev_vdbg(priv->dev, "set_addr: bank=%d, " |
193 | "elbc_fcm_ctrl->addr=0x%p (0x%p), " | ||
196 | "index %x, pes %d ps %d\n", | 194 | "index %x, pes %d ps %d\n", |
197 | buf_num, ctrl->addr, priv->vbase, ctrl->index, | 195 | buf_num, elbc_fcm_ctrl->addr, priv->vbase, |
196 | elbc_fcm_ctrl->index, | ||
198 | chip->phys_erase_shift, chip->page_shift); | 197 | chip->phys_erase_shift, chip->page_shift); |
199 | } | 198 | } |
200 | 199 | ||
@@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
205 | { | 204 | { |
206 | struct nand_chip *chip = mtd->priv; | 205 | struct nand_chip *chip = mtd->priv; |
207 | struct fsl_elbc_mtd *priv = chip->priv; | 206 | struct fsl_elbc_mtd *priv = chip->priv; |
208 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 207 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
208 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
210 | 210 | ||
211 | /* Setup the FMR[OP] to execute without write protection */ | 211 | /* Setup the FMR[OP] to execute without write protection */ |
212 | out_be32(&lbc->fmr, priv->fmr | 3); | 212 | out_be32(&lbc->fmr, priv->fmr | 3); |
213 | if (ctrl->use_mdr) | 213 | if (elbc_fcm_ctrl->use_mdr) |
214 | out_be32(&lbc->mdr, ctrl->mdr); | 214 | out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr); |
215 | 215 | ||
216 | dev_vdbg(ctrl->dev, | 216 | dev_vdbg(priv->dev, |
217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", | 217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", |
218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); | 218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); |
219 | dev_vdbg(ctrl->dev, | 219 | dev_vdbg(priv->dev, |
220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " | 220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " |
221 | "fbcr=%08x bank=%d\n", | 221 | "fbcr=%08x bank=%d\n", |
222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), | 222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), |
@@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
229 | /* wait for FCM complete flag or timeout */ | 229 | /* wait for FCM complete flag or timeout */ |
230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, | 230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, |
231 | FCM_TIMEOUT_MSECS * HZ/1000); | 231 | FCM_TIMEOUT_MSECS * HZ/1000); |
232 | ctrl->status = ctrl->irq_status; | 232 | elbc_fcm_ctrl->status = ctrl->irq_status; |
233 | |||
234 | /* store mdr value in case it was needed */ | 233 | /* store mdr value in case it was needed */ |
235 | if (ctrl->use_mdr) | 234 | if (elbc_fcm_ctrl->use_mdr) |
236 | ctrl->mdr = in_be32(&lbc->mdr); | 235 | elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr); |
237 | 236 | ||
238 | ctrl->use_mdr = 0; | 237 | elbc_fcm_ctrl->use_mdr = 0; |
239 | 238 | ||
240 | if (ctrl->status != LTESR_CC) { | 239 | if (elbc_fcm_ctrl->status != LTESR_CC) { |
241 | dev_info(ctrl->dev, | 240 | dev_info(priv->dev, |
242 | "command failed: fir %x fcr %x status %x mdr %x\n", | 241 | "command failed: fir %x fcr %x status %x mdr %x\n", |
243 | in_be32(&lbc->fir), in_be32(&lbc->fcr), | 242 | in_be32(&lbc->fir), in_be32(&lbc->fcr), |
244 | ctrl->status, ctrl->mdr); | 243 | elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr); |
245 | return -EIO; | 244 | return -EIO; |
246 | } | 245 | } |
247 | 246 | ||
@@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
251 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) | 250 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) |
252 | { | 251 | { |
253 | struct fsl_elbc_mtd *priv = chip->priv; | 252 | struct fsl_elbc_mtd *priv = chip->priv; |
254 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 253 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
255 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 254 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
256 | 255 | ||
257 | if (priv->page_size) { | 256 | if (priv->page_size) { |
@@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
284 | { | 283 | { |
285 | struct nand_chip *chip = mtd->priv; | 284 | struct nand_chip *chip = mtd->priv; |
286 | struct fsl_elbc_mtd *priv = chip->priv; | 285 | struct fsl_elbc_mtd *priv = chip->priv; |
287 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 286 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
287 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
289 | 289 | ||
290 | ctrl->use_mdr = 0; | 290 | elbc_fcm_ctrl->use_mdr = 0; |
291 | 291 | ||
292 | /* clear the read buffer */ | 292 | /* clear the read buffer */ |
293 | ctrl->read_bytes = 0; | 293 | elbc_fcm_ctrl->read_bytes = 0; |
294 | if (command != NAND_CMD_PAGEPROG) | 294 | if (command != NAND_CMD_PAGEPROG) |
295 | ctrl->index = 0; | 295 | elbc_fcm_ctrl->index = 0; |
296 | 296 | ||
297 | switch (command) { | 297 | switch (command) { |
298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ | 298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ |
@@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
301 | 301 | ||
302 | /* fall-through */ | 302 | /* fall-through */ |
303 | case NAND_CMD_READ0: | 303 | case NAND_CMD_READ0: |
304 | dev_dbg(ctrl->dev, | 304 | dev_dbg(priv->dev, |
305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" | 305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" |
306 | " 0x%x, column: 0x%x.\n", page_addr, column); | 306 | " 0x%x, column: 0x%x.\n", page_addr, column); |
307 | 307 | ||
@@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ | 309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ |
310 | set_addr(mtd, 0, page_addr, 0); | 310 | set_addr(mtd, 0, page_addr, 0); |
311 | 311 | ||
312 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 312 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
313 | ctrl->index += column; | 313 | elbc_fcm_ctrl->index += column; |
314 | 314 | ||
315 | fsl_elbc_do_read(chip, 0); | 315 | fsl_elbc_do_read(chip, 0); |
316 | fsl_elbc_run_command(mtd); | 316 | fsl_elbc_run_command(mtd); |
@@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
318 | 318 | ||
319 | /* READOOB reads only the OOB because no ECC is performed. */ | 319 | /* READOOB reads only the OOB because no ECC is performed. */ |
320 | case NAND_CMD_READOOB: | 320 | case NAND_CMD_READOOB: |
321 | dev_vdbg(ctrl->dev, | 321 | dev_vdbg(priv->dev, |
322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" | 322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" |
323 | " 0x%x, column: 0x%x.\n", page_addr, column); | 323 | " 0x%x, column: 0x%x.\n", page_addr, column); |
324 | 324 | ||
325 | out_be32(&lbc->fbcr, mtd->oobsize - column); | 325 | out_be32(&lbc->fbcr, mtd->oobsize - column); |
326 | set_addr(mtd, column, page_addr, 1); | 326 | set_addr(mtd, column, page_addr, 1); |
327 | 327 | ||
328 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 328 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
329 | 329 | ||
330 | fsl_elbc_do_read(chip, 1); | 330 | fsl_elbc_do_read(chip, 1); |
331 | fsl_elbc_run_command(mtd); | 331 | fsl_elbc_run_command(mtd); |
@@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
333 | 333 | ||
334 | /* READID must read all 5 possible bytes while CEB is active */ | 334 | /* READID must read all 5 possible bytes while CEB is active */ |
335 | case NAND_CMD_READID: | 335 | case NAND_CMD_READID: |
336 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); | 336 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); |
337 | 337 | ||
338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
339 | (FIR_OP_UA << FIR_OP1_SHIFT) | | 339 | (FIR_OP_UA << FIR_OP1_SHIFT) | |
@@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); | 341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); |
342 | /* 5 bytes for manuf, device and exts */ | 342 | /* 5 bytes for manuf, device and exts */ |
343 | out_be32(&lbc->fbcr, 5); | 343 | out_be32(&lbc->fbcr, 5); |
344 | ctrl->read_bytes = 5; | 344 | elbc_fcm_ctrl->read_bytes = 5; |
345 | ctrl->use_mdr = 1; | 345 | elbc_fcm_ctrl->use_mdr = 1; |
346 | ctrl->mdr = 0; | 346 | elbc_fcm_ctrl->mdr = 0; |
347 | 347 | ||
348 | set_addr(mtd, 0, 0, 0); | 348 | set_addr(mtd, 0, 0, 0); |
349 | fsl_elbc_run_command(mtd); | 349 | fsl_elbc_run_command(mtd); |
@@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
351 | 351 | ||
352 | /* ERASE1 stores the block and page address */ | 352 | /* ERASE1 stores the block and page address */ |
353 | case NAND_CMD_ERASE1: | 353 | case NAND_CMD_ERASE1: |
354 | dev_vdbg(ctrl->dev, | 354 | dev_vdbg(priv->dev, |
355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " | 355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " |
356 | "page_addr: 0x%x.\n", page_addr); | 356 | "page_addr: 0x%x.\n", page_addr); |
357 | set_addr(mtd, 0, page_addr, 0); | 357 | set_addr(mtd, 0, page_addr, 0); |
@@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
359 | 359 | ||
360 | /* ERASE2 uses the block and page address from ERASE1 */ | 360 | /* ERASE2 uses the block and page address from ERASE1 */ |
361 | case NAND_CMD_ERASE2: | 361 | case NAND_CMD_ERASE2: |
362 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); | 362 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); |
363 | 363 | ||
364 | out_be32(&lbc->fir, | 364 | out_be32(&lbc->fir, |
365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
@@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); | 374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); |
375 | 375 | ||
376 | out_be32(&lbc->fbcr, 0); | 376 | out_be32(&lbc->fbcr, 0); |
377 | ctrl->read_bytes = 0; | 377 | elbc_fcm_ctrl->read_bytes = 0; |
378 | ctrl->use_mdr = 1; | 378 | elbc_fcm_ctrl->use_mdr = 1; |
379 | 379 | ||
380 | fsl_elbc_run_command(mtd); | 380 | fsl_elbc_run_command(mtd); |
381 | return; | 381 | return; |
@@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
383 | /* SEQIN sets up the addr buffer and all registers except the length */ | 383 | /* SEQIN sets up the addr buffer and all registers except the length */ |
384 | case NAND_CMD_SEQIN: { | 384 | case NAND_CMD_SEQIN: { |
385 | __be32 fcr; | 385 | __be32 fcr; |
386 | dev_vdbg(ctrl->dev, | 386 | dev_vdbg(priv->dev, |
387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " | 387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " |
388 | "page_addr: 0x%x, column: 0x%x.\n", | 388 | "page_addr: 0x%x, column: 0x%x.\n", |
389 | page_addr, column); | 389 | page_addr, column); |
390 | 390 | ||
391 | ctrl->column = column; | 391 | elbc_fcm_ctrl->use_mdr = 1; |
392 | ctrl->oob = 0; | ||
393 | ctrl->use_mdr = 1; | ||
394 | 392 | ||
395 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | | 393 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | |
396 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | | 394 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | |
@@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
420 | /* OOB area --> READOOB */ | 418 | /* OOB area --> READOOB */ |
421 | column -= mtd->writesize; | 419 | column -= mtd->writesize; |
422 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; | 420 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; |
423 | ctrl->oob = 1; | 421 | elbc_fcm_ctrl->oob = 1; |
424 | } else { | 422 | } else { |
425 | WARN_ON(column != 0); | 423 | WARN_ON(column != 0); |
426 | /* First 256 bytes --> READ0 */ | 424 | /* First 256 bytes --> READ0 */ |
@@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
429 | } | 427 | } |
430 | 428 | ||
431 | out_be32(&lbc->fcr, fcr); | 429 | out_be32(&lbc->fcr, fcr); |
432 | set_addr(mtd, column, page_addr, ctrl->oob); | 430 | set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob); |
433 | return; | 431 | return; |
434 | } | 432 | } |
435 | 433 | ||
436 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | 434 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ |
437 | case NAND_CMD_PAGEPROG: { | 435 | case NAND_CMD_PAGEPROG: { |
438 | int full_page; | 436 | int full_page; |
439 | dev_vdbg(ctrl->dev, | 437 | dev_vdbg(priv->dev, |
440 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " | 438 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " |
441 | "writing %d bytes.\n", ctrl->index); | 439 | "writing %d bytes.\n", elbc_fcm_ctrl->index); |
442 | 440 | ||
443 | /* if the write did not start at 0 or is not a full page | 441 | /* if the write did not start at 0 or is not a full page |
444 | * then set the exact length, otherwise use a full page | 442 | * then set the exact length, otherwise use a full page |
445 | * write so the HW generates the ECC. | 443 | * write so the HW generates the ECC. |
446 | */ | 444 | */ |
447 | if (ctrl->oob || ctrl->column != 0 || | 445 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || |
448 | ctrl->index != mtd->writesize + mtd->oobsize) { | 446 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) { |
449 | out_be32(&lbc->fbcr, ctrl->index); | 447 | out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); |
450 | full_page = 0; | 448 | full_page = 0; |
451 | } else { | 449 | } else { |
452 | out_be32(&lbc->fbcr, 0); | 450 | out_be32(&lbc->fbcr, 0); |
@@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
458 | /* Read back the page in order to fill in the ECC for the | 456 | /* Read back the page in order to fill in the ECC for the |
459 | * caller. Is this really needed? | 457 | * caller. Is this really needed? |
460 | */ | 458 | */ |
461 | if (full_page && ctrl->oob_poi) { | 459 | if (full_page && elbc_fcm_ctrl->oob_poi) { |
462 | out_be32(&lbc->fbcr, 3); | 460 | out_be32(&lbc->fbcr, 3); |
463 | set_addr(mtd, 6, page_addr, 1); | 461 | set_addr(mtd, 6, page_addr, 1); |
464 | 462 | ||
465 | ctrl->read_bytes = mtd->writesize + 9; | 463 | elbc_fcm_ctrl->read_bytes = mtd->writesize + 9; |
466 | 464 | ||
467 | fsl_elbc_do_read(chip, 1); | 465 | fsl_elbc_do_read(chip, 1); |
468 | fsl_elbc_run_command(mtd); | 466 | fsl_elbc_run_command(mtd); |
469 | 467 | ||
470 | memcpy_fromio(ctrl->oob_poi + 6, | 468 | memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6, |
471 | &ctrl->addr[ctrl->index], 3); | 469 | &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3); |
472 | ctrl->index += 3; | 470 | elbc_fcm_ctrl->index += 3; |
473 | } | 471 | } |
474 | 472 | ||
475 | ctrl->oob_poi = NULL; | 473 | elbc_fcm_ctrl->oob_poi = NULL; |
476 | return; | 474 | return; |
477 | } | 475 | } |
478 | 476 | ||
@@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
485 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); | 483 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); |
486 | out_be32(&lbc->fbcr, 1); | 484 | out_be32(&lbc->fbcr, 1); |
487 | set_addr(mtd, 0, 0, 0); | 485 | set_addr(mtd, 0, 0, 0); |
488 | ctrl->read_bytes = 1; | 486 | elbc_fcm_ctrl->read_bytes = 1; |
489 | 487 | ||
490 | fsl_elbc_run_command(mtd); | 488 | fsl_elbc_run_command(mtd); |
491 | 489 | ||
492 | /* The chip always seems to report that it is | 490 | /* The chip always seems to report that it is |
493 | * write-protected, even when it is not. | 491 | * write-protected, even when it is not. |
494 | */ | 492 | */ |
495 | setbits8(ctrl->addr, NAND_STATUS_WP); | 493 | setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP); |
496 | return; | 494 | return; |
497 | 495 | ||
498 | /* RESET without waiting for the ready line */ | 496 | /* RESET without waiting for the ready line */ |
499 | case NAND_CMD_RESET: | 497 | case NAND_CMD_RESET: |
500 | dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); | 498 | dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); |
501 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); | 499 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); |
502 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); | 500 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); |
503 | fsl_elbc_run_command(mtd); | 501 | fsl_elbc_run_command(mtd); |
504 | return; | 502 | return; |
505 | 503 | ||
506 | default: | 504 | default: |
507 | dev_err(ctrl->dev, | 505 | dev_err(priv->dev, |
508 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", | 506 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", |
509 | command); | 507 | command); |
510 | } | 508 | } |
@@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
524 | { | 522 | { |
525 | struct nand_chip *chip = mtd->priv; | 523 | struct nand_chip *chip = mtd->priv; |
526 | struct fsl_elbc_mtd *priv = chip->priv; | 524 | struct fsl_elbc_mtd *priv = chip->priv; |
527 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 525 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
528 | unsigned int bufsize = mtd->writesize + mtd->oobsize; | 526 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
529 | 527 | ||
530 | if (len <= 0) { | 528 | if (len <= 0) { |
531 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 529 | dev_err(priv->dev, "write_buf of %d bytes", len); |
532 | ctrl->status = 0; | 530 | elbc_fcm_ctrl->status = 0; |
533 | return; | 531 | return; |
534 | } | 532 | } |
535 | 533 | ||
536 | if ((unsigned int)len > bufsize - ctrl->index) { | 534 | if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) { |
537 | dev_err(ctrl->dev, | 535 | dev_err(priv->dev, |
538 | "write_buf beyond end of buffer " | 536 | "write_buf beyond end of buffer " |
539 | "(%d requested, %u available)\n", | 537 | "(%d requested, %u available)\n", |
540 | len, bufsize - ctrl->index); | 538 | len, bufsize - elbc_fcm_ctrl->index); |
541 | len = bufsize - ctrl->index; | 539 | len = bufsize - elbc_fcm_ctrl->index; |
542 | } | 540 | } |
543 | 541 | ||
544 | memcpy_toio(&ctrl->addr[ctrl->index], buf, len); | 542 | memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len); |
545 | /* | 543 | /* |
546 | * This is workaround for the weird elbc hangs during nand write, | 544 | * This is workaround for the weird elbc hangs during nand write, |
547 | * Scott Wood says: "...perhaps difference in how long it takes a | 545 | * Scott Wood says: "...perhaps difference in how long it takes a |
@@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
549 | * is causing problems, and sync isn't helping for some reason." | 547 | * is causing problems, and sync isn't helping for some reason." |
550 | * Reading back the last byte helps though. | 548 | * Reading back the last byte helps though. |
551 | */ | 549 | */ |
552 | in_8(&ctrl->addr[ctrl->index] + len - 1); | 550 | in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1); |
553 | 551 | ||
554 | ctrl->index += len; | 552 | elbc_fcm_ctrl->index += len; |
555 | } | 553 | } |
556 | 554 | ||
557 | /* | 555 | /* |
@@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) | |||
562 | { | 560 | { |
563 | struct nand_chip *chip = mtd->priv; | 561 | struct nand_chip *chip = mtd->priv; |
564 | struct fsl_elbc_mtd *priv = chip->priv; | 562 | struct fsl_elbc_mtd *priv = chip->priv; |
565 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 563 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
566 | 564 | ||
567 | /* If there are still bytes in the FCM, then use the next byte. */ | 565 | /* If there are still bytes in the FCM, then use the next byte. */ |
568 | if (ctrl->index < ctrl->read_bytes) | 566 | if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes) |
569 | return in_8(&ctrl->addr[ctrl->index++]); | 567 | return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]); |
570 | 568 | ||
571 | dev_err(ctrl->dev, "read_byte beyond end of buffer\n"); | 569 | dev_err(priv->dev, "read_byte beyond end of buffer\n"); |
572 | return ERR_BYTE; | 570 | return ERR_BYTE; |
573 | } | 571 | } |
574 | 572 | ||
@@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
579 | { | 577 | { |
580 | struct nand_chip *chip = mtd->priv; | 578 | struct nand_chip *chip = mtd->priv; |
581 | struct fsl_elbc_mtd *priv = chip->priv; | 579 | struct fsl_elbc_mtd *priv = chip->priv; |
582 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 580 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
583 | int avail; | 581 | int avail; |
584 | 582 | ||
585 | if (len < 0) | 583 | if (len < 0) |
586 | return; | 584 | return; |
587 | 585 | ||
588 | avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index); | 586 | avail = min((unsigned int)len, |
589 | memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); | 587 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); |
590 | ctrl->index += avail; | 588 | memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail); |
589 | elbc_fcm_ctrl->index += avail; | ||
591 | 590 | ||
592 | if (len > avail) | 591 | if (len > avail) |
593 | dev_err(ctrl->dev, | 592 | dev_err(priv->dev, |
594 | "read_buf beyond end of buffer " | 593 | "read_buf beyond end of buffer " |
595 | "(%d requested, %d available)\n", | 594 | "(%d requested, %d available)\n", |
596 | len, avail); | 595 | len, avail); |
@@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
603 | { | 602 | { |
604 | struct nand_chip *chip = mtd->priv; | 603 | struct nand_chip *chip = mtd->priv; |
605 | struct fsl_elbc_mtd *priv = chip->priv; | 604 | struct fsl_elbc_mtd *priv = chip->priv; |
606 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 605 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
607 | int i; | 606 | int i; |
608 | 607 | ||
609 | if (len < 0) { | 608 | if (len < 0) { |
610 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 609 | dev_err(priv->dev, "write_buf of %d bytes", len); |
611 | return -EINVAL; | 610 | return -EINVAL; |
612 | } | 611 | } |
613 | 612 | ||
614 | if ((unsigned int)len > ctrl->read_bytes - ctrl->index) { | 613 | if ((unsigned int)len > |
615 | dev_err(ctrl->dev, | 614 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) { |
616 | "verify_buf beyond end of buffer " | 615 | dev_err(priv->dev, |
617 | "(%d requested, %u available)\n", | 616 | "verify_buf beyond end of buffer " |
618 | len, ctrl->read_bytes - ctrl->index); | 617 | "(%d requested, %u available)\n", |
618 | len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); | ||
619 | 619 | ||
620 | ctrl->index = ctrl->read_bytes; | 620 | elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes; |
621 | return -EINVAL; | 621 | return -EINVAL; |
622 | } | 622 | } |
623 | 623 | ||
624 | for (i = 0; i < len; i++) | 624 | for (i = 0; i < len; i++) |
625 | if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) | 625 | if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i]) |
626 | != buf[i]) | ||
626 | break; | 627 | break; |
627 | 628 | ||
628 | ctrl->index += len; | 629 | elbc_fcm_ctrl->index += len; |
629 | return i == len && ctrl->status == LTESR_CC ? 0 : -EIO; | 630 | return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO; |
630 | } | 631 | } |
631 | 632 | ||
632 | /* This function is called after Program and Erase Operations to | 633 | /* This function is called after Program and Erase Operations to |
@@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
635 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) | 636 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) |
636 | { | 637 | { |
637 | struct fsl_elbc_mtd *priv = chip->priv; | 638 | struct fsl_elbc_mtd *priv = chip->priv; |
638 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 639 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
639 | 640 | ||
640 | if (ctrl->status != LTESR_CC) | 641 | if (elbc_fcm_ctrl->status != LTESR_CC) |
641 | return NAND_STATUS_FAIL; | 642 | return NAND_STATUS_FAIL; |
642 | 643 | ||
643 | /* The chip always seems to report that it is | 644 | /* The chip always seems to report that it is |
644 | * write-protected, even when it is not. | 645 | * write-protected, even when it is not. |
645 | */ | 646 | */ |
646 | return (ctrl->mdr & 0xff) | NAND_STATUS_WP; | 647 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
647 | } | 648 | } |
648 | 649 | ||
649 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | 650 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) |
650 | { | 651 | { |
651 | struct nand_chip *chip = mtd->priv; | 652 | struct nand_chip *chip = mtd->priv; |
652 | struct fsl_elbc_mtd *priv = chip->priv; | 653 | struct fsl_elbc_mtd *priv = chip->priv; |
653 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 654 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
654 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 655 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
655 | unsigned int al; | 656 | unsigned int al; |
656 | 657 | ||
@@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
665 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ | 666 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ |
666 | (al << FMR_AL_SHIFT); | 667 | (al << FMR_AL_SHIFT); |
667 | 668 | ||
668 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n", | 669 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", |
669 | chip->numchips); | 670 | chip->numchips); |
670 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n", | 671 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", |
671 | chip->chipsize); | 672 | chip->chipsize); |
672 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n", | 673 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", |
673 | chip->pagemask); | 674 | chip->pagemask); |
674 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n", | 675 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", |
675 | chip->chip_delay); | 676 | chip->chip_delay); |
676 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n", | 677 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", |
677 | chip->badblockpos); | 678 | chip->badblockpos); |
678 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n", | 679 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", |
679 | chip->chip_shift); | 680 | chip->chip_shift); |
680 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n", | 681 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", |
681 | chip->page_shift); | 682 | chip->page_shift); |
682 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", | 683 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", |
683 | chip->phys_erase_shift); | 684 | chip->phys_erase_shift); |
684 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n", | 685 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n", |
685 | chip->ecclayout); | 686 | chip->ecclayout); |
686 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", | 687 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", |
687 | chip->ecc.mode); | 688 | chip->ecc.mode); |
688 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", | 689 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", |
689 | chip->ecc.steps); | 690 | chip->ecc.steps); |
690 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", | 691 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", |
691 | chip->ecc.bytes); | 692 | chip->ecc.bytes); |
692 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | 693 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", |
693 | chip->ecc.total); | 694 | chip->ecc.total); |
694 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", | 695 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", |
695 | chip->ecc.layout); | 696 | chip->ecc.layout); |
696 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | 697 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); |
697 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | 698 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); |
698 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | 699 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", |
699 | mtd->erasesize); | 700 | mtd->erasesize); |
700 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n", | 701 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", |
701 | mtd->writesize); | 702 | mtd->writesize); |
702 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n", | 703 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", |
703 | mtd->oobsize); | 704 | mtd->oobsize); |
704 | 705 | ||
705 | /* adjust Option Register and ECC to match Flash page size */ | 706 | /* adjust Option Register and ECC to match Flash page size */ |
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
719 | chip->badblock_pattern = &largepage_memorybased; | 720 | chip->badblock_pattern = &largepage_memorybased; |
720 | } | 721 | } |
721 | } else { | 722 | } else { |
722 | dev_err(ctrl->dev, | 723 | dev_err(priv->dev, |
723 | "fsl_elbc_init: page size %d is not supported\n", | 724 | "fsl_elbc_init: page size %d is not supported\n", |
724 | mtd->writesize); | 725 | mtd->writesize); |
725 | return -1; | 726 | return -1; |
@@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, | |||
750 | const uint8_t *buf) | 751 | const uint8_t *buf) |
751 | { | 752 | { |
752 | struct fsl_elbc_mtd *priv = chip->priv; | 753 | struct fsl_elbc_mtd *priv = chip->priv; |
753 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 754 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
754 | 755 | ||
755 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | 756 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
756 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 757 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
757 | 758 | ||
758 | ctrl->oob_poi = chip->oob_poi; | 759 | elbc_fcm_ctrl->oob_poi = chip->oob_poi; |
759 | } | 760 | } |
760 | 761 | ||
761 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 762 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
762 | { | 763 | { |
763 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 764 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
764 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 765 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
766 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
765 | struct nand_chip *chip = &priv->chip; | 767 | struct nand_chip *chip = &priv->chip; |
766 | 768 | ||
767 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); | 769 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
@@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
790 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | | 792 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | |
791 | NAND_USE_FLASH_BBT; | 793 | NAND_USE_FLASH_BBT; |
792 | 794 | ||
793 | chip->controller = &ctrl->controller; | 795 | chip->controller = &elbc_fcm_ctrl->controller; |
794 | chip->priv = priv; | 796 | chip->priv = priv; |
795 | 797 | ||
796 | chip->ecc.read_page = fsl_elbc_read_page; | 798 | chip->ecc.read_page = fsl_elbc_read_page; |
@@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
815 | 817 | ||
816 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | 818 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) |
817 | { | 819 | { |
818 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 820 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
819 | |||
820 | nand_release(&priv->mtd); | 821 | nand_release(&priv->mtd); |
821 | 822 | ||
822 | kfree(priv->mtd.name); | 823 | kfree(priv->mtd.name); |
@@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
824 | if (priv->vbase) | 825 | if (priv->vbase) |
825 | iounmap(priv->vbase); | 826 | iounmap(priv->vbase); |
826 | 827 | ||
827 | ctrl->chips[priv->bank] = NULL; | 828 | elbc_fcm_ctrl->chips[priv->bank] = NULL; |
828 | kfree(priv); | 829 | kfree(priv); |
829 | 830 | kfree(elbc_fcm_ctrl); | |
830 | return 0; | 831 | return 0; |
831 | } | 832 | } |
832 | 833 | ||
833 | static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | 834 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); |
834 | struct device_node *node) | 835 | |
836 | static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | ||
835 | { | 837 | { |
836 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 838 | struct fsl_lbc_regs __iomem *lbc; |
837 | struct fsl_elbc_mtd *priv; | 839 | struct fsl_elbc_mtd *priv; |
838 | struct resource res; | 840 | struct resource res; |
841 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; | ||
842 | |||
839 | #ifdef CONFIG_MTD_PARTITIONS | 843 | #ifdef CONFIG_MTD_PARTITIONS |
840 | static const char *part_probe_types[] | 844 | static const char *part_probe_types[] |
841 | = { "cmdlinepart", "RedBoot", NULL }; | 845 | = { "cmdlinepart", "RedBoot", NULL }; |
@@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
843 | #endif | 847 | #endif |
844 | int ret; | 848 | int ret; |
845 | int bank; | 849 | int bank; |
850 | struct device *dev; | ||
851 | struct device_node *node = pdev->dev.of_node; | ||
852 | |||
853 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
854 | return -ENODEV; | ||
855 | lbc = fsl_lbc_ctrl_dev->regs; | ||
856 | dev = fsl_lbc_ctrl_dev->dev; | ||
846 | 857 | ||
847 | /* get, allocate and map the memory resource */ | 858 | /* get, allocate and map the memory resource */ |
848 | ret = of_address_to_resource(node, 0, &res); | 859 | ret = of_address_to_resource(node, 0, &res); |
849 | if (ret) { | 860 | if (ret) { |
850 | dev_err(ctrl->dev, "failed to get resource\n"); | 861 | dev_err(dev, "failed to get resource\n"); |
851 | return ret; | 862 | return ret; |
852 | } | 863 | } |
853 | 864 | ||
@@ -861,7 +872,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
861 | break; | 872 | break; |
862 | 873 | ||
863 | if (bank >= MAX_BANKS) { | 874 | if (bank >= MAX_BANKS) { |
864 | dev_err(ctrl->dev, "address did not match any chip selects\n"); | 875 | dev_err(dev, "address did not match any chip selects\n"); |
865 | return -ENODEV; | 876 | return -ENODEV; |
866 | } | 877 | } |
867 | 878 | ||
@@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
869 | if (!priv) | 880 | if (!priv) |
870 | return -ENOMEM; | 881 | return -ENOMEM; |
871 | 882 | ||
872 | ctrl->chips[bank] = priv; | 883 | mutex_lock(&fsl_elbc_nand_mutex); |
884 | if (!fsl_lbc_ctrl_dev->nand) { | ||
885 | elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); | ||
886 | if (!elbc_fcm_ctrl) { | ||
887 | dev_err(dev, "failed to allocate memory\n"); | ||
888 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
889 | ret = -ENOMEM; | ||
890 | goto err; | ||
891 | } | ||
892 | elbc_fcm_ctrl->counter++; | ||
893 | |||
894 | spin_lock_init(&elbc_fcm_ctrl->controller.lock); | ||
895 | init_waitqueue_head(&elbc_fcm_ctrl->controller.wq); | ||
896 | fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl; | ||
897 | } else { | ||
898 | elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | ||
899 | } | ||
900 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
901 | |||
902 | elbc_fcm_ctrl->chips[bank] = priv; | ||
873 | priv->bank = bank; | 903 | priv->bank = bank; |
874 | priv->ctrl = ctrl; | 904 | priv->ctrl = fsl_lbc_ctrl_dev; |
875 | priv->dev = ctrl->dev; | 905 | priv->dev = dev; |
876 | 906 | ||
877 | priv->vbase = ioremap(res.start, resource_size(&res)); | 907 | priv->vbase = ioremap(res.start, resource_size(&res)); |
878 | if (!priv->vbase) { | 908 | if (!priv->vbase) { |
879 | dev_err(ctrl->dev, "failed to map chip region\n"); | 909 | dev_err(dev, "failed to map chip region\n"); |
880 | ret = -ENOMEM; | 910 | ret = -ENOMEM; |
881 | goto err; | 911 | goto err; |
882 | } | 912 | } |
@@ -933,171 +963,53 @@ err: | |||
933 | return ret; | 963 | return ret; |
934 | } | 964 | } |
935 | 965 | ||
936 | static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | 966 | static int fsl_elbc_nand_remove(struct platform_device *pdev) |
937 | { | 967 | { |
938 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
939 | |||
940 | /* | ||
941 | * NAND transactions can tie up the bus for a long time, so set the | ||
942 | * bus timeout to max by clearing LBCR[BMT] (highest base counter | ||
943 | * value) and setting LBCR[BMTPS] to the highest prescaler value. | ||
944 | */ | ||
945 | clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15); | ||
946 | |||
947 | /* clear event registers */ | ||
948 | setbits32(&lbc->ltesr, LTESR_NAND_MASK); | ||
949 | out_be32(&lbc->lteatr, 0); | ||
950 | |||
951 | /* Enable interrupts for any detected events */ | ||
952 | out_be32(&lbc->lteir, LTESR_NAND_MASK); | ||
953 | |||
954 | ctrl->read_bytes = 0; | ||
955 | ctrl->index = 0; | ||
956 | ctrl->addr = NULL; | ||
957 | |||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) | ||
962 | { | ||
963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); | ||
964 | int i; | 968 | int i; |
965 | 969 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | |
966 | for (i = 0; i < MAX_BANKS; i++) | 970 | for (i = 0; i < MAX_BANKS; i++) |
967 | if (ctrl->chips[i]) | 971 | if (elbc_fcm_ctrl->chips[i]) |
968 | fsl_elbc_chip_remove(ctrl->chips[i]); | 972 | fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]); |
969 | 973 | ||
970 | if (ctrl->irq) | 974 | mutex_lock(&fsl_elbc_nand_mutex); |
971 | free_irq(ctrl->irq, ctrl); | 975 | elbc_fcm_ctrl->counter--; |
972 | 976 | if (!elbc_fcm_ctrl->counter) { | |
973 | if (ctrl->regs) | 977 | fsl_lbc_ctrl_dev->nand = NULL; |
974 | iounmap(ctrl->regs); | 978 | kfree(elbc_fcm_ctrl); |
975 | |||
976 | dev_set_drvdata(&ofdev->dev, NULL); | ||
977 | kfree(ctrl); | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* NOTE: This interrupt is also used to report other localbus events, | ||
982 | * such as transaction errors on other chipselects. If we want to | ||
983 | * capture those, we'll need to move the IRQ code into a shared | ||
984 | * LBC driver. | ||
985 | */ | ||
986 | |||
987 | static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | ||
988 | { | ||
989 | struct fsl_elbc_ctrl *ctrl = data; | ||
990 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
991 | __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK; | ||
992 | |||
993 | if (status) { | ||
994 | out_be32(&lbc->ltesr, status); | ||
995 | out_be32(&lbc->lteatr, 0); | ||
996 | |||
997 | ctrl->irq_status = status; | ||
998 | smp_wmb(); | ||
999 | wake_up(&ctrl->irq_wait); | ||
1000 | |||
1001 | return IRQ_HANDLED; | ||
1002 | } | 979 | } |
1003 | 980 | mutex_unlock(&fsl_elbc_nand_mutex); | |
1004 | return IRQ_NONE; | ||
1005 | } | ||
1006 | |||
1007 | /* fsl_elbc_ctrl_probe | ||
1008 | * | ||
1009 | * called by device layer when it finds a device matching | ||
1010 | * one our driver can handled. This code allocates all of | ||
1011 | * the resources needed for the controller only. The | ||
1012 | * resources for the NAND banks themselves are allocated | ||
1013 | * in the chip probe function. | ||
1014 | */ | ||
1015 | |||
1016 | static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, | ||
1017 | const struct of_device_id *match) | ||
1018 | { | ||
1019 | struct device_node *child; | ||
1020 | struct fsl_elbc_ctrl *ctrl; | ||
1021 | int ret; | ||
1022 | |||
1023 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | ||
1024 | if (!ctrl) | ||
1025 | return -ENOMEM; | ||
1026 | |||
1027 | dev_set_drvdata(&ofdev->dev, ctrl); | ||
1028 | |||
1029 | spin_lock_init(&ctrl->controller.lock); | ||
1030 | init_waitqueue_head(&ctrl->controller.wq); | ||
1031 | init_waitqueue_head(&ctrl->irq_wait); | ||
1032 | |||
1033 | ctrl->regs = of_iomap(ofdev->dev.of_node, 0); | ||
1034 | if (!ctrl->regs) { | ||
1035 | dev_err(&ofdev->dev, "failed to get memory region\n"); | ||
1036 | ret = -ENODEV; | ||
1037 | goto err; | ||
1038 | } | ||
1039 | |||
1040 | ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | ||
1041 | if (ctrl->irq == NO_IRQ) { | ||
1042 | dev_err(&ofdev->dev, "failed to get irq resource\n"); | ||
1043 | ret = -ENODEV; | ||
1044 | goto err; | ||
1045 | } | ||
1046 | |||
1047 | ctrl->dev = &ofdev->dev; | ||
1048 | |||
1049 | ret = fsl_elbc_ctrl_init(ctrl); | ||
1050 | if (ret < 0) | ||
1051 | goto err; | ||
1052 | |||
1053 | ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl); | ||
1054 | if (ret != 0) { | ||
1055 | dev_err(&ofdev->dev, "failed to install irq (%d)\n", | ||
1056 | ctrl->irq); | ||
1057 | ret = ctrl->irq; | ||
1058 | goto err; | ||
1059 | } | ||
1060 | |||
1061 | for_each_child_of_node(ofdev->dev.of_node, child) | ||
1062 | if (of_device_is_compatible(child, "fsl,elbc-fcm-nand")) | ||
1063 | fsl_elbc_chip_probe(ctrl, child); | ||
1064 | 981 | ||
1065 | return 0; | 982 | return 0; |
1066 | 983 | ||
1067 | err: | ||
1068 | fsl_elbc_ctrl_remove(ofdev); | ||
1069 | return ret; | ||
1070 | } | 984 | } |
1071 | 985 | ||
1072 | static const struct of_device_id fsl_elbc_match[] = { | 986 | static const struct of_device_id fsl_elbc_nand_match[] = { |
1073 | { | 987 | { .compatible = "fsl,elbc-fcm-nand", }, |
1074 | .compatible = "fsl,elbc", | ||
1075 | }, | ||
1076 | {} | 988 | {} |
1077 | }; | 989 | }; |
1078 | 990 | ||
1079 | static struct of_platform_driver fsl_elbc_ctrl_driver = { | 991 | static struct platform_driver fsl_elbc_nand_driver = { |
1080 | .driver = { | 992 | .driver = { |
1081 | .name = "fsl-elbc", | 993 | .name = "fsl,elbc-fcm-nand", |
1082 | .owner = THIS_MODULE, | 994 | .owner = THIS_MODULE, |
1083 | .of_match_table = fsl_elbc_match, | 995 | .of_match_table = fsl_elbc_nand_match, |
1084 | }, | 996 | }, |
1085 | .probe = fsl_elbc_ctrl_probe, | 997 | .probe = fsl_elbc_nand_probe, |
1086 | .remove = fsl_elbc_ctrl_remove, | 998 | .remove = fsl_elbc_nand_remove, |
1087 | }; | 999 | }; |
1088 | 1000 | ||
1089 | static int __init fsl_elbc_init(void) | 1001 | static int __init fsl_elbc_nand_init(void) |
1090 | { | 1002 | { |
1091 | return of_register_platform_driver(&fsl_elbc_ctrl_driver); | 1003 | return platform_driver_register(&fsl_elbc_nand_driver); |
1092 | } | 1004 | } |
1093 | 1005 | ||
1094 | static void __exit fsl_elbc_exit(void) | 1006 | static void __exit fsl_elbc_nand_exit(void) |
1095 | { | 1007 | { |
1096 | of_unregister_platform_driver(&fsl_elbc_ctrl_driver); | 1008 | platform_driver_unregister(&fsl_elbc_nand_driver); |
1097 | } | 1009 | } |
1098 | 1010 | ||
1099 | module_init(fsl_elbc_init); | 1011 | module_init(fsl_elbc_nand_init); |
1100 | module_exit(fsl_elbc_exit); | 1012 | module_exit(fsl_elbc_nand_exit); |
1101 | 1013 | ||
1102 | MODULE_LICENSE("GPL"); | 1014 | MODULE_LICENSE("GPL"); |
1103 | MODULE_AUTHOR("Freescale"); | 1015 | MODULE_AUTHOR("Freescale"); |