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"); |
