diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_elbc_nand.c | 482 |
2 files changed, 198 insertions, 285 deletions
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"); |