diff options
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 636 |
1 files changed, 444 insertions, 192 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9e374e9bd296..c58e6a93f445 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/irq.h> | 33 | #include <linux/irq.h> |
34 | #include <linux/completion.h> | 34 | #include <linux/completion.h> |
35 | #include <linux/of_device.h> | ||
36 | #include <linux/of_mtd.h> | ||
35 | 37 | ||
36 | #include <asm/mach/flash.h> | 38 | #include <asm/mach/flash.h> |
37 | #include <mach/mxc_nand.h> | 39 | #include <mach/mxc_nand.h> |
@@ -140,13 +142,47 @@ | |||
140 | 142 | ||
141 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) | 143 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) |
142 | 144 | ||
145 | struct mxc_nand_host; | ||
146 | |||
147 | struct mxc_nand_devtype_data { | ||
148 | void (*preset)(struct mtd_info *); | ||
149 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
150 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
151 | void (*send_page)(struct mtd_info *, unsigned int); | ||
152 | void (*send_read_id)(struct mxc_nand_host *); | ||
153 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
154 | int (*check_int)(struct mxc_nand_host *); | ||
155 | void (*irq_control)(struct mxc_nand_host *, int); | ||
156 | u32 (*get_ecc_status)(struct mxc_nand_host *); | ||
157 | struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k; | ||
158 | void (*select_chip)(struct mtd_info *mtd, int chip); | ||
159 | int (*correct_data)(struct mtd_info *mtd, u_char *dat, | ||
160 | u_char *read_ecc, u_char *calc_ecc); | ||
161 | |||
162 | /* | ||
163 | * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked | ||
164 | * (CONFIG1:INT_MSK is set). To handle this the driver uses | ||
165 | * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK | ||
166 | */ | ||
167 | int irqpending_quirk; | ||
168 | int needs_ip; | ||
169 | |||
170 | size_t regs_offset; | ||
171 | size_t spare0_offset; | ||
172 | size_t axi_offset; | ||
173 | |||
174 | int spare_len; | ||
175 | int eccbytes; | ||
176 | int eccsize; | ||
177 | }; | ||
178 | |||
143 | struct mxc_nand_host { | 179 | struct mxc_nand_host { |
144 | struct mtd_info mtd; | 180 | struct mtd_info mtd; |
145 | struct nand_chip nand; | 181 | struct nand_chip nand; |
146 | struct device *dev; | 182 | struct device *dev; |
147 | 183 | ||
148 | void *spare0; | 184 | void __iomem *spare0; |
149 | void *main_area0; | 185 | void __iomem *main_area0; |
150 | 186 | ||
151 | void __iomem *base; | 187 | void __iomem *base; |
152 | void __iomem *regs; | 188 | void __iomem *regs; |
@@ -163,16 +199,9 @@ struct mxc_nand_host { | |||
163 | 199 | ||
164 | uint8_t *data_buf; | 200 | uint8_t *data_buf; |
165 | unsigned int buf_start; | 201 | unsigned int buf_start; |
166 | int spare_len; | 202 | |
167 | 203 | const struct mxc_nand_devtype_data *devtype_data; | |
168 | void (*preset)(struct mtd_info *); | 204 | struct mxc_nand_platform_data pdata; |
169 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
170 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
171 | void (*send_page)(struct mtd_info *, unsigned int); | ||
172 | void (*send_read_id)(struct mxc_nand_host *); | ||
173 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
174 | int (*check_int)(struct mxc_nand_host *); | ||
175 | void (*irq_control)(struct mxc_nand_host *, int); | ||
176 | }; | 205 | }; |
177 | 206 | ||
178 | /* OOB placement block for use with hardware ecc generation */ | 207 | /* OOB placement block for use with hardware ecc generation */ |
@@ -242,21 +271,7 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { | |||
242 | } | 271 | } |
243 | }; | 272 | }; |
244 | 273 | ||
245 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; | 274 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; |
246 | |||
247 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | ||
248 | { | ||
249 | struct mxc_nand_host *host = dev_id; | ||
250 | |||
251 | if (!host->check_int(host)) | ||
252 | return IRQ_NONE; | ||
253 | |||
254 | host->irq_control(host, 0); | ||
255 | |||
256 | complete(&host->op_completion); | ||
257 | |||
258 | return IRQ_HANDLED; | ||
259 | } | ||
260 | 275 | ||
261 | static int check_int_v3(struct mxc_nand_host *host) | 276 | static int check_int_v3(struct mxc_nand_host *host) |
262 | { | 277 | { |
@@ -280,26 +295,12 @@ static int check_int_v1_v2(struct mxc_nand_host *host) | |||
280 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | 295 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) |
281 | return 0; | 296 | return 0; |
282 | 297 | ||
283 | if (!cpu_is_mx21()) | 298 | if (!host->devtype_data->irqpending_quirk) |
284 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | 299 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); |
285 | 300 | ||
286 | return 1; | 301 | return 1; |
287 | } | 302 | } |
288 | 303 | ||
289 | /* | ||
290 | * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit | ||
291 | * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the | ||
292 | * driver can enable/disable the irq line rather than simply masking the | ||
293 | * interrupts. | ||
294 | */ | ||
295 | static void irq_control_mx21(struct mxc_nand_host *host, int activate) | ||
296 | { | ||
297 | if (activate) | ||
298 | enable_irq(host->irq); | ||
299 | else | ||
300 | disable_irq_nosync(host->irq); | ||
301 | } | ||
302 | |||
303 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) | 304 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) |
304 | { | 305 | { |
305 | uint16_t tmp; | 306 | uint16_t tmp; |
@@ -328,6 +329,47 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate) | |||
328 | writel(tmp, NFC_V3_CONFIG2); | 329 | writel(tmp, NFC_V3_CONFIG2); |
329 | } | 330 | } |
330 | 331 | ||
332 | static void irq_control(struct mxc_nand_host *host, int activate) | ||
333 | { | ||
334 | if (host->devtype_data->irqpending_quirk) { | ||
335 | if (activate) | ||
336 | enable_irq(host->irq); | ||
337 | else | ||
338 | disable_irq_nosync(host->irq); | ||
339 | } else { | ||
340 | host->devtype_data->irq_control(host, activate); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static u32 get_ecc_status_v1(struct mxc_nand_host *host) | ||
345 | { | ||
346 | return readw(NFC_V1_V2_ECC_STATUS_RESULT); | ||
347 | } | ||
348 | |||
349 | static u32 get_ecc_status_v2(struct mxc_nand_host *host) | ||
350 | { | ||
351 | return readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
352 | } | ||
353 | |||
354 | static u32 get_ecc_status_v3(struct mxc_nand_host *host) | ||
355 | { | ||
356 | return readl(NFC_V3_ECC_STATUS_RESULT); | ||
357 | } | ||
358 | |||
359 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | ||
360 | { | ||
361 | struct mxc_nand_host *host = dev_id; | ||
362 | |||
363 | if (!host->devtype_data->check_int(host)) | ||
364 | return IRQ_NONE; | ||
365 | |||
366 | irq_control(host, 0); | ||
367 | |||
368 | complete(&host->op_completion); | ||
369 | |||
370 | return IRQ_HANDLED; | ||
371 | } | ||
372 | |||
331 | /* This function polls the NANDFC to wait for the basic operation to | 373 | /* This function polls the NANDFC to wait for the basic operation to |
332 | * complete by checking the INT bit of config2 register. | 374 | * complete by checking the INT bit of config2 register. |
333 | */ | 375 | */ |
@@ -336,14 +378,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
336 | int max_retries = 8000; | 378 | int max_retries = 8000; |
337 | 379 | ||
338 | if (useirq) { | 380 | if (useirq) { |
339 | if (!host->check_int(host)) { | 381 | if (!host->devtype_data->check_int(host)) { |
340 | INIT_COMPLETION(host->op_completion); | 382 | INIT_COMPLETION(host->op_completion); |
341 | host->irq_control(host, 1); | 383 | irq_control(host, 1); |
342 | wait_for_completion(&host->op_completion); | 384 | wait_for_completion(&host->op_completion); |
343 | } | 385 | } |
344 | } else { | 386 | } else { |
345 | while (max_retries-- > 0) { | 387 | while (max_retries-- > 0) { |
346 | if (host->check_int(host)) | 388 | if (host->devtype_data->check_int(host)) |
347 | break; | 389 | break; |
348 | 390 | ||
349 | udelay(1); | 391 | udelay(1); |
@@ -374,7 +416,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
374 | writew(cmd, NFC_V1_V2_FLASH_CMD); | 416 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
375 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); | 417 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
376 | 418 | ||
377 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { | 419 | if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) { |
378 | int max_retries = 100; | 420 | int max_retries = 100; |
379 | /* Reset completion is indicated by NFC_CONFIG2 */ | 421 | /* Reset completion is indicated by NFC_CONFIG2 */ |
380 | /* being set to 0 */ | 422 | /* being set to 0 */ |
@@ -433,13 +475,27 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) | |||
433 | wait_op_done(host, false); | 475 | wait_op_done(host, false); |
434 | } | 476 | } |
435 | 477 | ||
436 | static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | 478 | static void send_page_v2(struct mtd_info *mtd, unsigned int ops) |
479 | { | ||
480 | struct nand_chip *nand_chip = mtd->priv; | ||
481 | struct mxc_nand_host *host = nand_chip->priv; | ||
482 | |||
483 | /* NANDFC buffer 0 is used for page read/write */ | ||
484 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
485 | |||
486 | writew(ops, NFC_V1_V2_CONFIG2); | ||
487 | |||
488 | /* Wait for operation to complete */ | ||
489 | wait_op_done(host, true); | ||
490 | } | ||
491 | |||
492 | static void send_page_v1(struct mtd_info *mtd, unsigned int ops) | ||
437 | { | 493 | { |
438 | struct nand_chip *nand_chip = mtd->priv; | 494 | struct nand_chip *nand_chip = mtd->priv; |
439 | struct mxc_nand_host *host = nand_chip->priv; | 495 | struct mxc_nand_host *host = nand_chip->priv; |
440 | int bufs, i; | 496 | int bufs, i; |
441 | 497 | ||
442 | if (nfc_is_v1() && mtd->writesize > 512) | 498 | if (mtd->writesize > 512) |
443 | bufs = 4; | 499 | bufs = 4; |
444 | else | 500 | else |
445 | bufs = 1; | 501 | bufs = 1; |
@@ -463,7 +519,7 @@ static void send_read_id_v3(struct mxc_nand_host *host) | |||
463 | 519 | ||
464 | wait_op_done(host, true); | 520 | wait_op_done(host, true); |
465 | 521 | ||
466 | memcpy(host->data_buf, host->main_area0, 16); | 522 | memcpy_fromio(host->data_buf, host->main_area0, 16); |
467 | } | 523 | } |
468 | 524 | ||
469 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 525 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
@@ -479,7 +535,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
479 | /* Wait for operation to complete */ | 535 | /* Wait for operation to complete */ |
480 | wait_op_done(host, true); | 536 | wait_op_done(host, true); |
481 | 537 | ||
482 | memcpy(host->data_buf, host->main_area0, 16); | 538 | memcpy_fromio(host->data_buf, host->main_area0, 16); |
483 | 539 | ||
484 | if (this->options & NAND_BUSWIDTH_16) { | 540 | if (this->options & NAND_BUSWIDTH_16) { |
485 | /* compress the ID info */ | 541 | /* compress the ID info */ |
@@ -555,7 +611,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, | |||
555 | * additional correction. 2-Bit errors cannot be corrected by | 611 | * additional correction. 2-Bit errors cannot be corrected by |
556 | * HW ECC, so we need to return failure | 612 | * HW ECC, so we need to return failure |
557 | */ | 613 | */ |
558 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); | 614 | uint16_t ecc_status = get_ecc_status_v1(host); |
559 | 615 | ||
560 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 616 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
561 | pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); | 617 | pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); |
@@ -580,10 +636,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | |||
580 | 636 | ||
581 | no_subpages = mtd->writesize >> 9; | 637 | no_subpages = mtd->writesize >> 9; |
582 | 638 | ||
583 | if (nfc_is_v21()) | 639 | ecc_stat = host->devtype_data->get_ecc_status(host); |
584 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
585 | else | ||
586 | ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); | ||
587 | 640 | ||
588 | do { | 641 | do { |
589 | err = ecc_stat & ecc_bit_mask; | 642 | err = ecc_stat & ecc_bit_mask; |
@@ -616,7 +669,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
616 | 669 | ||
617 | /* Check for status request */ | 670 | /* Check for status request */ |
618 | if (host->status_request) | 671 | if (host->status_request) |
619 | return host->get_dev_status(host) & 0xFF; | 672 | return host->devtype_data->get_dev_status(host) & 0xFF; |
620 | 673 | ||
621 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 674 | ret = *(uint8_t *)(host->data_buf + host->buf_start); |
622 | host->buf_start++; | 675 | host->buf_start++; |
@@ -682,7 +735,7 @@ static int mxc_nand_verify_buf(struct mtd_info *mtd, | |||
682 | 735 | ||
683 | /* This function is used by upper layer for select and | 736 | /* This function is used by upper layer for select and |
684 | * deselect of the NAND chip */ | 737 | * deselect of the NAND chip */ |
685 | static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | 738 | static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) |
686 | { | 739 | { |
687 | struct nand_chip *nand_chip = mtd->priv; | 740 | struct nand_chip *nand_chip = mtd->priv; |
688 | struct mxc_nand_host *host = nand_chip->priv; | 741 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -701,11 +754,30 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
701 | clk_prepare_enable(host->clk); | 754 | clk_prepare_enable(host->clk); |
702 | host->clk_act = 1; | 755 | host->clk_act = 1; |
703 | } | 756 | } |
757 | } | ||
704 | 758 | ||
705 | if (nfc_is_v21()) { | 759 | static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) |
706 | host->active_cs = chip; | 760 | { |
707 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | 761 | struct nand_chip *nand_chip = mtd->priv; |
762 | struct mxc_nand_host *host = nand_chip->priv; | ||
763 | |||
764 | if (chip == -1) { | ||
765 | /* Disable the NFC clock */ | ||
766 | if (host->clk_act) { | ||
767 | clk_disable(host->clk); | ||
768 | host->clk_act = 0; | ||
769 | } | ||
770 | return; | ||
771 | } | ||
772 | |||
773 | if (!host->clk_act) { | ||
774 | /* Enable the NFC clock */ | ||
775 | clk_enable(host->clk); | ||
776 | host->clk_act = 1; | ||
708 | } | 777 | } |
778 | |||
779 | host->active_cs = chip; | ||
780 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
709 | } | 781 | } |
710 | 782 | ||
711 | /* | 783 | /* |
@@ -718,23 +790,23 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) | |||
718 | u16 i, j; | 790 | u16 i, j; |
719 | u16 n = mtd->writesize >> 9; | 791 | u16 n = mtd->writesize >> 9; |
720 | u8 *d = host->data_buf + mtd->writesize; | 792 | u8 *d = host->data_buf + mtd->writesize; |
721 | u8 *s = host->spare0; | 793 | u8 __iomem *s = host->spare0; |
722 | u16 t = host->spare_len; | 794 | u16 t = host->devtype_data->spare_len; |
723 | 795 | ||
724 | j = (mtd->oobsize / n >> 1) << 1; | 796 | j = (mtd->oobsize / n >> 1) << 1; |
725 | 797 | ||
726 | if (bfrom) { | 798 | if (bfrom) { |
727 | for (i = 0; i < n - 1; i++) | 799 | for (i = 0; i < n - 1; i++) |
728 | memcpy(d + i * j, s + i * t, j); | 800 | memcpy_fromio(d + i * j, s + i * t, j); |
729 | 801 | ||
730 | /* the last section */ | 802 | /* the last section */ |
731 | memcpy(d + i * j, s + i * t, mtd->oobsize - i * j); | 803 | memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); |
732 | } else { | 804 | } else { |
733 | for (i = 0; i < n - 1; i++) | 805 | for (i = 0; i < n - 1; i++) |
734 | memcpy(&s[i * t], &d[i * j], j); | 806 | memcpy_toio(&s[i * t], &d[i * j], j); |
735 | 807 | ||
736 | /* the last section */ | 808 | /* the last section */ |
737 | memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j); | 809 | memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); |
738 | } | 810 | } |
739 | } | 811 | } |
740 | 812 | ||
@@ -751,34 +823,44 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
751 | * perform a read/write buf operation, the saved column | 823 | * perform a read/write buf operation, the saved column |
752 | * address is used to index into the full page. | 824 | * address is used to index into the full page. |
753 | */ | 825 | */ |
754 | host->send_addr(host, 0, page_addr == -1); | 826 | host->devtype_data->send_addr(host, 0, page_addr == -1); |
755 | if (mtd->writesize > 512) | 827 | if (mtd->writesize > 512) |
756 | /* another col addr cycle for 2k page */ | 828 | /* another col addr cycle for 2k page */ |
757 | host->send_addr(host, 0, false); | 829 | host->devtype_data->send_addr(host, 0, false); |
758 | } | 830 | } |
759 | 831 | ||
760 | /* Write out page address, if necessary */ | 832 | /* Write out page address, if necessary */ |
761 | if (page_addr != -1) { | 833 | if (page_addr != -1) { |
762 | /* paddr_0 - p_addr_7 */ | 834 | /* paddr_0 - p_addr_7 */ |
763 | host->send_addr(host, (page_addr & 0xff), false); | 835 | host->devtype_data->send_addr(host, (page_addr & 0xff), false); |
764 | 836 | ||
765 | if (mtd->writesize > 512) { | 837 | if (mtd->writesize > 512) { |
766 | if (mtd->size >= 0x10000000) { | 838 | if (mtd->size >= 0x10000000) { |
767 | /* paddr_8 - paddr_15 */ | 839 | /* paddr_8 - paddr_15 */ |
768 | host->send_addr(host, (page_addr >> 8) & 0xff, false); | 840 | host->devtype_data->send_addr(host, |
769 | host->send_addr(host, (page_addr >> 16) & 0xff, true); | 841 | (page_addr >> 8) & 0xff, |
842 | false); | ||
843 | host->devtype_data->send_addr(host, | ||
844 | (page_addr >> 16) & 0xff, | ||
845 | true); | ||
770 | } else | 846 | } else |
771 | /* paddr_8 - paddr_15 */ | 847 | /* paddr_8 - paddr_15 */ |
772 | host->send_addr(host, (page_addr >> 8) & 0xff, true); | 848 | host->devtype_data->send_addr(host, |
849 | (page_addr >> 8) & 0xff, true); | ||
773 | } else { | 850 | } else { |
774 | /* One more address cycle for higher density devices */ | 851 | /* One more address cycle for higher density devices */ |
775 | if (mtd->size >= 0x4000000) { | 852 | if (mtd->size >= 0x4000000) { |
776 | /* paddr_8 - paddr_15 */ | 853 | /* paddr_8 - paddr_15 */ |
777 | host->send_addr(host, (page_addr >> 8) & 0xff, false); | 854 | host->devtype_data->send_addr(host, |
778 | host->send_addr(host, (page_addr >> 16) & 0xff, true); | 855 | (page_addr >> 8) & 0xff, |
856 | false); | ||
857 | host->devtype_data->send_addr(host, | ||
858 | (page_addr >> 16) & 0xff, | ||
859 | true); | ||
779 | } else | 860 | } else |
780 | /* paddr_8 - paddr_15 */ | 861 | /* paddr_8 - paddr_15 */ |
781 | host->send_addr(host, (page_addr >> 8) & 0xff, true); | 862 | host->devtype_data->send_addr(host, |
863 | (page_addr >> 8) & 0xff, true); | ||
782 | } | 864 | } |
783 | } | 865 | } |
784 | } | 866 | } |
@@ -800,7 +882,35 @@ static int get_eccsize(struct mtd_info *mtd) | |||
800 | return 8; | 882 | return 8; |
801 | } | 883 | } |
802 | 884 | ||
803 | static void preset_v1_v2(struct mtd_info *mtd) | 885 | static void preset_v1(struct mtd_info *mtd) |
886 | { | ||
887 | struct nand_chip *nand_chip = mtd->priv; | ||
888 | struct mxc_nand_host *host = nand_chip->priv; | ||
889 | uint16_t config1 = 0; | ||
890 | |||
891 | if (nand_chip->ecc.mode == NAND_ECC_HW) | ||
892 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | ||
893 | |||
894 | if (!host->devtype_data->irqpending_quirk) | ||
895 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; | ||
896 | |||
897 | host->eccsize = 1; | ||
898 | |||
899 | writew(config1, NFC_V1_V2_CONFIG1); | ||
900 | /* preset operation */ | ||
901 | |||
902 | /* Unlock the internal RAM Buffer */ | ||
903 | writew(0x2, NFC_V1_V2_CONFIG); | ||
904 | |||
905 | /* Blocks to be unlocked */ | ||
906 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | ||
907 | writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); | ||
908 | |||
909 | /* Unlock Block Command for given address range */ | ||
910 | writew(0x4, NFC_V1_V2_WRPROT); | ||
911 | } | ||
912 | |||
913 | static void preset_v2(struct mtd_info *mtd) | ||
804 | { | 914 | { |
805 | struct nand_chip *nand_chip = mtd->priv; | 915 | struct nand_chip *nand_chip = mtd->priv; |
806 | struct mxc_nand_host *host = nand_chip->priv; | 916 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -809,13 +919,12 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
809 | if (nand_chip->ecc.mode == NAND_ECC_HW) | 919 | if (nand_chip->ecc.mode == NAND_ECC_HW) |
810 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | 920 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
811 | 921 | ||
812 | if (nfc_is_v21()) | 922 | config1 |= NFC_V2_CONFIG1_FP_INT; |
813 | config1 |= NFC_V2_CONFIG1_FP_INT; | ||
814 | 923 | ||
815 | if (!cpu_is_mx21()) | 924 | if (!host->devtype_data->irqpending_quirk) |
816 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; | 925 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; |
817 | 926 | ||
818 | if (nfc_is_v21() && mtd->writesize) { | 927 | if (mtd->writesize) { |
819 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | 928 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; |
820 | 929 | ||
821 | host->eccsize = get_eccsize(mtd); | 930 | host->eccsize = get_eccsize(mtd); |
@@ -834,20 +943,14 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
834 | writew(0x2, NFC_V1_V2_CONFIG); | 943 | writew(0x2, NFC_V1_V2_CONFIG); |
835 | 944 | ||
836 | /* Blocks to be unlocked */ | 945 | /* Blocks to be unlocked */ |
837 | if (nfc_is_v21()) { | 946 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); |
838 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); | 947 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); |
839 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); | 948 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); |
840 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); | 949 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); |
841 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); | 950 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); |
842 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); | 951 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); |
843 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); | 952 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); |
844 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); | 953 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); |
845 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); | ||
846 | } else if (nfc_is_v1()) { | ||
847 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | ||
848 | writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); | ||
849 | } else | ||
850 | BUG(); | ||
851 | 954 | ||
852 | /* Unlock Block Command for given address range */ | 955 | /* Unlock Block Command for given address range */ |
853 | writew(0x4, NFC_V1_V2_WRPROT); | 956 | writew(0x4, NFC_V1_V2_WRPROT); |
@@ -937,15 +1040,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
937 | /* Command pre-processing step */ | 1040 | /* Command pre-processing step */ |
938 | switch (command) { | 1041 | switch (command) { |
939 | case NAND_CMD_RESET: | 1042 | case NAND_CMD_RESET: |
940 | host->preset(mtd); | 1043 | host->devtype_data->preset(mtd); |
941 | host->send_cmd(host, command, false); | 1044 | host->devtype_data->send_cmd(host, command, false); |
942 | break; | 1045 | break; |
943 | 1046 | ||
944 | case NAND_CMD_STATUS: | 1047 | case NAND_CMD_STATUS: |
945 | host->buf_start = 0; | 1048 | host->buf_start = 0; |
946 | host->status_request = true; | 1049 | host->status_request = true; |
947 | 1050 | ||
948 | host->send_cmd(host, command, true); | 1051 | host->devtype_data->send_cmd(host, command, true); |
949 | mxc_do_addr_cycle(mtd, column, page_addr); | 1052 | mxc_do_addr_cycle(mtd, column, page_addr); |
950 | break; | 1053 | break; |
951 | 1054 | ||
@@ -958,15 +1061,16 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
958 | 1061 | ||
959 | command = NAND_CMD_READ0; /* only READ0 is valid */ | 1062 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
960 | 1063 | ||
961 | host->send_cmd(host, command, false); | 1064 | host->devtype_data->send_cmd(host, command, false); |
962 | mxc_do_addr_cycle(mtd, column, page_addr); | 1065 | mxc_do_addr_cycle(mtd, column, page_addr); |
963 | 1066 | ||
964 | if (mtd->writesize > 512) | 1067 | if (mtd->writesize > 512) |
965 | host->send_cmd(host, NAND_CMD_READSTART, true); | 1068 | host->devtype_data->send_cmd(host, |
1069 | NAND_CMD_READSTART, true); | ||
966 | 1070 | ||
967 | host->send_page(mtd, NFC_OUTPUT); | 1071 | host->devtype_data->send_page(mtd, NFC_OUTPUT); |
968 | 1072 | ||
969 | memcpy(host->data_buf, host->main_area0, mtd->writesize); | 1073 | memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize); |
970 | copy_spare(mtd, true); | 1074 | copy_spare(mtd, true); |
971 | break; | 1075 | break; |
972 | 1076 | ||
@@ -977,28 +1081,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
977 | 1081 | ||
978 | host->buf_start = column; | 1082 | host->buf_start = column; |
979 | 1083 | ||
980 | host->send_cmd(host, command, false); | 1084 | host->devtype_data->send_cmd(host, command, false); |
981 | mxc_do_addr_cycle(mtd, column, page_addr); | 1085 | mxc_do_addr_cycle(mtd, column, page_addr); |
982 | break; | 1086 | break; |
983 | 1087 | ||
984 | case NAND_CMD_PAGEPROG: | 1088 | case NAND_CMD_PAGEPROG: |
985 | memcpy(host->main_area0, host->data_buf, mtd->writesize); | 1089 | memcpy_toio(host->main_area0, host->data_buf, mtd->writesize); |
986 | copy_spare(mtd, false); | 1090 | copy_spare(mtd, false); |
987 | host->send_page(mtd, NFC_INPUT); | 1091 | host->devtype_data->send_page(mtd, NFC_INPUT); |
988 | host->send_cmd(host, command, true); | 1092 | host->devtype_data->send_cmd(host, command, true); |
989 | mxc_do_addr_cycle(mtd, column, page_addr); | 1093 | mxc_do_addr_cycle(mtd, column, page_addr); |
990 | break; | 1094 | break; |
991 | 1095 | ||
992 | case NAND_CMD_READID: | 1096 | case NAND_CMD_READID: |
993 | host->send_cmd(host, command, true); | 1097 | host->devtype_data->send_cmd(host, command, true); |
994 | mxc_do_addr_cycle(mtd, column, page_addr); | 1098 | mxc_do_addr_cycle(mtd, column, page_addr); |
995 | host->send_read_id(host); | 1099 | host->devtype_data->send_read_id(host); |
996 | host->buf_start = column; | 1100 | host->buf_start = column; |
997 | break; | 1101 | break; |
998 | 1102 | ||
999 | case NAND_CMD_ERASE1: | 1103 | case NAND_CMD_ERASE1: |
1000 | case NAND_CMD_ERASE2: | 1104 | case NAND_CMD_ERASE2: |
1001 | host->send_cmd(host, command, false); | 1105 | host->devtype_data->send_cmd(host, command, false); |
1002 | mxc_do_addr_cycle(mtd, column, page_addr); | 1106 | mxc_do_addr_cycle(mtd, column, page_addr); |
1003 | 1107 | ||
1004 | break; | 1108 | break; |
@@ -1032,15 +1136,191 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1032 | .pattern = mirror_pattern, | 1136 | .pattern = mirror_pattern, |
1033 | }; | 1137 | }; |
1034 | 1138 | ||
1139 | /* v1 + irqpending_quirk: i.MX21 */ | ||
1140 | static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { | ||
1141 | .preset = preset_v1, | ||
1142 | .send_cmd = send_cmd_v1_v2, | ||
1143 | .send_addr = send_addr_v1_v2, | ||
1144 | .send_page = send_page_v1, | ||
1145 | .send_read_id = send_read_id_v1_v2, | ||
1146 | .get_dev_status = get_dev_status_v1_v2, | ||
1147 | .check_int = check_int_v1_v2, | ||
1148 | .irq_control = irq_control_v1_v2, | ||
1149 | .get_ecc_status = get_ecc_status_v1, | ||
1150 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | ||
1151 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
1152 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1153 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1154 | .correct_data = mxc_nand_correct_data_v1, | ||
1155 | .irqpending_quirk = 1, | ||
1156 | .needs_ip = 0, | ||
1157 | .regs_offset = 0xe00, | ||
1158 | .spare0_offset = 0x800, | ||
1159 | .spare_len = 16, | ||
1160 | .eccbytes = 3, | ||
1161 | .eccsize = 1, | ||
1162 | }; | ||
1163 | |||
1164 | /* v1 + !irqpending_quirk: i.MX27, i.MX31 */ | ||
1165 | static const struct mxc_nand_devtype_data imx27_nand_devtype_data = { | ||
1166 | .preset = preset_v1, | ||
1167 | .send_cmd = send_cmd_v1_v2, | ||
1168 | .send_addr = send_addr_v1_v2, | ||
1169 | .send_page = send_page_v1, | ||
1170 | .send_read_id = send_read_id_v1_v2, | ||
1171 | .get_dev_status = get_dev_status_v1_v2, | ||
1172 | .check_int = check_int_v1_v2, | ||
1173 | .irq_control = irq_control_v1_v2, | ||
1174 | .get_ecc_status = get_ecc_status_v1, | ||
1175 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | ||
1176 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
1177 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1178 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1179 | .correct_data = mxc_nand_correct_data_v1, | ||
1180 | .irqpending_quirk = 0, | ||
1181 | .needs_ip = 0, | ||
1182 | .regs_offset = 0xe00, | ||
1183 | .spare0_offset = 0x800, | ||
1184 | .axi_offset = 0, | ||
1185 | .spare_len = 16, | ||
1186 | .eccbytes = 3, | ||
1187 | .eccsize = 1, | ||
1188 | }; | ||
1189 | |||
1190 | /* v21: i.MX25, i.MX35 */ | ||
1191 | static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { | ||
1192 | .preset = preset_v2, | ||
1193 | .send_cmd = send_cmd_v1_v2, | ||
1194 | .send_addr = send_addr_v1_v2, | ||
1195 | .send_page = send_page_v2, | ||
1196 | .send_read_id = send_read_id_v1_v2, | ||
1197 | .get_dev_status = get_dev_status_v1_v2, | ||
1198 | .check_int = check_int_v1_v2, | ||
1199 | .irq_control = irq_control_v1_v2, | ||
1200 | .get_ecc_status = get_ecc_status_v2, | ||
1201 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | ||
1202 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
1203 | .ecclayout_4k = &nandv2_hw_eccoob_4k, | ||
1204 | .select_chip = mxc_nand_select_chip_v2, | ||
1205 | .correct_data = mxc_nand_correct_data_v2_v3, | ||
1206 | .irqpending_quirk = 0, | ||
1207 | .needs_ip = 0, | ||
1208 | .regs_offset = 0x1e00, | ||
1209 | .spare0_offset = 0x1000, | ||
1210 | .axi_offset = 0, | ||
1211 | .spare_len = 64, | ||
1212 | .eccbytes = 9, | ||
1213 | .eccsize = 0, | ||
1214 | }; | ||
1215 | |||
1216 | /* v3: i.MX51, i.MX53 */ | ||
1217 | static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { | ||
1218 | .preset = preset_v3, | ||
1219 | .send_cmd = send_cmd_v3, | ||
1220 | .send_addr = send_addr_v3, | ||
1221 | .send_page = send_page_v3, | ||
1222 | .send_read_id = send_read_id_v3, | ||
1223 | .get_dev_status = get_dev_status_v3, | ||
1224 | .check_int = check_int_v3, | ||
1225 | .irq_control = irq_control_v3, | ||
1226 | .get_ecc_status = get_ecc_status_v3, | ||
1227 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | ||
1228 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
1229 | .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1230 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1231 | .correct_data = mxc_nand_correct_data_v2_v3, | ||
1232 | .irqpending_quirk = 0, | ||
1233 | .needs_ip = 1, | ||
1234 | .regs_offset = 0, | ||
1235 | .spare0_offset = 0x1000, | ||
1236 | .axi_offset = 0x1e00, | ||
1237 | .spare_len = 64, | ||
1238 | .eccbytes = 0, | ||
1239 | .eccsize = 0, | ||
1240 | }; | ||
1241 | |||
1242 | #ifdef CONFIG_OF_MTD | ||
1243 | static const struct of_device_id mxcnd_dt_ids[] = { | ||
1244 | { | ||
1245 | .compatible = "fsl,imx21-nand", | ||
1246 | .data = &imx21_nand_devtype_data, | ||
1247 | }, { | ||
1248 | .compatible = "fsl,imx27-nand", | ||
1249 | .data = &imx27_nand_devtype_data, | ||
1250 | }, { | ||
1251 | .compatible = "fsl,imx25-nand", | ||
1252 | .data = &imx25_nand_devtype_data, | ||
1253 | }, { | ||
1254 | .compatible = "fsl,imx51-nand", | ||
1255 | .data = &imx51_nand_devtype_data, | ||
1256 | }, | ||
1257 | { /* sentinel */ } | ||
1258 | }; | ||
1259 | |||
1260 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | ||
1261 | { | ||
1262 | struct device_node *np = host->dev->of_node; | ||
1263 | struct mxc_nand_platform_data *pdata = &host->pdata; | ||
1264 | const struct of_device_id *of_id = | ||
1265 | of_match_device(mxcnd_dt_ids, host->dev); | ||
1266 | int buswidth; | ||
1267 | |||
1268 | if (!np) | ||
1269 | return 1; | ||
1270 | |||
1271 | if (of_get_nand_ecc_mode(np) >= 0) | ||
1272 | pdata->hw_ecc = 1; | ||
1273 | |||
1274 | pdata->flash_bbt = of_get_nand_on_flash_bbt(np); | ||
1275 | |||
1276 | buswidth = of_get_nand_bus_width(np); | ||
1277 | if (buswidth < 0) | ||
1278 | return buswidth; | ||
1279 | |||
1280 | pdata->width = buswidth / 8; | ||
1281 | |||
1282 | host->devtype_data = of_id->data; | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | #else | ||
1287 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | ||
1288 | { | ||
1289 | return 1; | ||
1290 | } | ||
1291 | #endif | ||
1292 | |||
1293 | static int __init mxcnd_probe_pdata(struct mxc_nand_host *host) | ||
1294 | { | ||
1295 | struct mxc_nand_platform_data *pdata = host->dev->platform_data; | ||
1296 | |||
1297 | if (!pdata) | ||
1298 | return -ENODEV; | ||
1299 | |||
1300 | host->pdata = *pdata; | ||
1301 | |||
1302 | if (nfc_is_v1()) { | ||
1303 | if (cpu_is_mx21()) | ||
1304 | host->devtype_data = &imx21_nand_devtype_data; | ||
1305 | else | ||
1306 | host->devtype_data = &imx27_nand_devtype_data; | ||
1307 | } else if (nfc_is_v21()) { | ||
1308 | host->devtype_data = &imx25_nand_devtype_data; | ||
1309 | } else if (nfc_is_v3_2()) { | ||
1310 | host->devtype_data = &imx51_nand_devtype_data; | ||
1311 | } else | ||
1312 | BUG(); | ||
1313 | |||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1035 | static int __init mxcnd_probe(struct platform_device *pdev) | 1317 | static int __init mxcnd_probe(struct platform_device *pdev) |
1036 | { | 1318 | { |
1037 | struct nand_chip *this; | 1319 | struct nand_chip *this; |
1038 | struct mtd_info *mtd; | 1320 | struct mtd_info *mtd; |
1039 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | ||
1040 | struct mxc_nand_host *host; | 1321 | struct mxc_nand_host *host; |
1041 | struct resource *res; | 1322 | struct resource *res; |
1042 | int err = 0; | 1323 | int err = 0; |
1043 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | ||
1044 | 1324 | ||
1045 | /* Allocate memory for MTD device structure and private data */ | 1325 | /* Allocate memory for MTD device structure and private data */ |
1046 | host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + | 1326 | host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + |
@@ -1065,7 +1345,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1065 | this->priv = host; | 1345 | this->priv = host; |
1066 | this->dev_ready = mxc_nand_dev_ready; | 1346 | this->dev_ready = mxc_nand_dev_ready; |
1067 | this->cmdfunc = mxc_nand_command; | 1347 | this->cmdfunc = mxc_nand_command; |
1068 | this->select_chip = mxc_nand_select_chip; | ||
1069 | this->read_byte = mxc_nand_read_byte; | 1348 | this->read_byte = mxc_nand_read_byte; |
1070 | this->read_word = mxc_nand_read_word; | 1349 | this->read_word = mxc_nand_read_word; |
1071 | this->write_buf = mxc_nand_write_buf; | 1350 | this->write_buf = mxc_nand_write_buf; |
@@ -1095,36 +1374,26 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1095 | 1374 | ||
1096 | host->main_area0 = host->base; | 1375 | host->main_area0 = host->base; |
1097 | 1376 | ||
1098 | if (nfc_is_v1() || nfc_is_v21()) { | 1377 | err = mxcnd_probe_dt(host); |
1099 | host->preset = preset_v1_v2; | 1378 | if (err > 0) |
1100 | host->send_cmd = send_cmd_v1_v2; | 1379 | err = mxcnd_probe_pdata(host); |
1101 | host->send_addr = send_addr_v1_v2; | 1380 | if (err < 0) |
1102 | host->send_page = send_page_v1_v2; | 1381 | goto eirq; |
1103 | host->send_read_id = send_read_id_v1_v2; | ||
1104 | host->get_dev_status = get_dev_status_v1_v2; | ||
1105 | host->check_int = check_int_v1_v2; | ||
1106 | if (cpu_is_mx21()) | ||
1107 | host->irq_control = irq_control_mx21; | ||
1108 | else | ||
1109 | host->irq_control = irq_control_v1_v2; | ||
1110 | } | ||
1111 | 1382 | ||
1112 | if (nfc_is_v21()) { | 1383 | if (host->devtype_data->regs_offset) |
1113 | host->regs = host->base + 0x1e00; | 1384 | host->regs = host->base + host->devtype_data->regs_offset; |
1114 | host->spare0 = host->base + 0x1000; | 1385 | host->spare0 = host->base + host->devtype_data->spare0_offset; |
1115 | host->spare_len = 64; | 1386 | if (host->devtype_data->axi_offset) |
1116 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1387 | host->regs_axi = host->base + host->devtype_data->axi_offset; |
1117 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1388 | |
1118 | this->ecc.bytes = 9; | 1389 | this->ecc.bytes = host->devtype_data->eccbytes; |
1119 | } else if (nfc_is_v1()) { | 1390 | host->eccsize = host->devtype_data->eccsize; |
1120 | host->regs = host->base + 0xe00; | 1391 | |
1121 | host->spare0 = host->base + 0x800; | 1392 | this->select_chip = host->devtype_data->select_chip; |
1122 | host->spare_len = 16; | 1393 | this->ecc.size = 512; |
1123 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 1394 | this->ecc.layout = host->devtype_data->ecclayout_512; |
1124 | oob_largepage = &nandv1_hw_eccoob_largepage; | 1395 | |
1125 | this->ecc.bytes = 3; | 1396 | if (host->devtype_data->needs_ip) { |
1126 | host->eccsize = 1; | ||
1127 | } else if (nfc_is_v3_2()) { | ||
1128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 1397 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
1129 | if (!res) { | 1398 | if (!res) { |
1130 | err = -ENODEV; | 1399 | err = -ENODEV; |
@@ -1135,42 +1404,22 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1135 | err = -ENOMEM; | 1404 | err = -ENOMEM; |
1136 | goto eirq; | 1405 | goto eirq; |
1137 | } | 1406 | } |
1138 | host->regs_axi = host->base + 0x1e00; | 1407 | } |
1139 | host->spare0 = host->base + 0x1000; | ||
1140 | host->spare_len = 64; | ||
1141 | host->preset = preset_v3; | ||
1142 | host->send_cmd = send_cmd_v3; | ||
1143 | host->send_addr = send_addr_v3; | ||
1144 | host->send_page = send_page_v3; | ||
1145 | host->send_read_id = send_read_id_v3; | ||
1146 | host->check_int = check_int_v3; | ||
1147 | host->get_dev_status = get_dev_status_v3; | ||
1148 | host->irq_control = irq_control_v3; | ||
1149 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | ||
1150 | oob_largepage = &nandv2_hw_eccoob_largepage; | ||
1151 | } else | ||
1152 | BUG(); | ||
1153 | |||
1154 | this->ecc.size = 512; | ||
1155 | this->ecc.layout = oob_smallpage; | ||
1156 | 1408 | ||
1157 | if (pdata->hw_ecc) { | 1409 | if (host->pdata.hw_ecc) { |
1158 | this->ecc.calculate = mxc_nand_calculate_ecc; | 1410 | this->ecc.calculate = mxc_nand_calculate_ecc; |
1159 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 1411 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
1160 | if (nfc_is_v1()) | 1412 | this->ecc.correct = host->devtype_data->correct_data; |
1161 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
1162 | else | ||
1163 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
1164 | this->ecc.mode = NAND_ECC_HW; | 1413 | this->ecc.mode = NAND_ECC_HW; |
1165 | } else { | 1414 | } else { |
1166 | this->ecc.mode = NAND_ECC_SOFT; | 1415 | this->ecc.mode = NAND_ECC_SOFT; |
1167 | } | 1416 | } |
1168 | 1417 | ||
1169 | /* NAND bus width determines access funtions used by upper layer */ | 1418 | /* NAND bus width determines access functions used by upper layer */ |
1170 | if (pdata->width == 2) | 1419 | if (host->pdata.width == 2) |
1171 | this->options |= NAND_BUSWIDTH_16; | 1420 | this->options |= NAND_BUSWIDTH_16; |
1172 | 1421 | ||
1173 | if (pdata->flash_bbt) { | 1422 | if (host->pdata.flash_bbt) { |
1174 | this->bbt_td = &bbt_main_descr; | 1423 | this->bbt_td = &bbt_main_descr; |
1175 | this->bbt_md = &bbt_mirror_descr; | 1424 | this->bbt_md = &bbt_mirror_descr; |
1176 | /* update flash based bbt */ | 1425 | /* update flash based bbt */ |
@@ -1182,28 +1431,25 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1182 | host->irq = platform_get_irq(pdev, 0); | 1431 | host->irq = platform_get_irq(pdev, 0); |
1183 | 1432 | ||
1184 | /* | 1433 | /* |
1185 | * mask the interrupt. For i.MX21 explicitely call | 1434 | * Use host->devtype_data->irq_control() here instead of irq_control() |
1186 | * irq_control_v1_v2 to use the mask bit. We can't call | 1435 | * because we must not disable_irq_nosync without having requested the |
1187 | * disable_irq_nosync() for an interrupt we do not own yet. | 1436 | * irq. |
1188 | */ | 1437 | */ |
1189 | if (cpu_is_mx21()) | 1438 | host->devtype_data->irq_control(host, 0); |
1190 | irq_control_v1_v2(host, 0); | ||
1191 | else | ||
1192 | host->irq_control(host, 0); | ||
1193 | 1439 | ||
1194 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); | 1440 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); |
1195 | if (err) | 1441 | if (err) |
1196 | goto eirq; | 1442 | goto eirq; |
1197 | 1443 | ||
1198 | host->irq_control(host, 0); | ||
1199 | |||
1200 | /* | 1444 | /* |
1201 | * Now that the interrupt is disabled make sure the interrupt | 1445 | * Now that we "own" the interrupt make sure the interrupt mask bit is |
1202 | * mask bit is cleared on i.MX21. Otherwise we can't read | 1446 | * cleared on i.MX21. Otherwise we can't read the interrupt status bit |
1203 | * the interrupt status bit on this machine. | 1447 | * on this machine. |
1204 | */ | 1448 | */ |
1205 | if (cpu_is_mx21()) | 1449 | if (host->devtype_data->irqpending_quirk) { |
1206 | irq_control_v1_v2(host, 1); | 1450 | disable_irq_nosync(host->irq); |
1451 | host->devtype_data->irq_control(host, 1); | ||
1452 | } | ||
1207 | 1453 | ||
1208 | /* first scan to find the device and get the page size */ | 1454 | /* first scan to find the device and get the page size */ |
1209 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { | 1455 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { |
@@ -1212,18 +1458,12 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1212 | } | 1458 | } |
1213 | 1459 | ||
1214 | /* Call preset again, with correct writesize this time */ | 1460 | /* Call preset again, with correct writesize this time */ |
1215 | host->preset(mtd); | 1461 | host->devtype_data->preset(mtd); |
1216 | 1462 | ||
1217 | if (mtd->writesize == 2048) | 1463 | if (mtd->writesize == 2048) |
1218 | this->ecc.layout = oob_largepage; | 1464 | this->ecc.layout = host->devtype_data->ecclayout_2k; |
1219 | if (nfc_is_v21() && mtd->writesize == 4096) | 1465 | else if (mtd->writesize == 4096) |
1220 | this->ecc.layout = &nandv2_hw_eccoob_4k; | 1466 | this->ecc.layout = host->devtype_data->ecclayout_4k; |
1221 | |||
1222 | /* second phase scan */ | ||
1223 | if (nand_scan_tail(mtd)) { | ||
1224 | err = -ENXIO; | ||
1225 | goto escan; | ||
1226 | } | ||
1227 | 1467 | ||
1228 | if (this->ecc.mode == NAND_ECC_HW) { | 1468 | if (this->ecc.mode == NAND_ECC_HW) { |
1229 | if (nfc_is_v1()) | 1469 | if (nfc_is_v1()) |
@@ -1232,9 +1472,19 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1232 | this->ecc.strength = (host->eccsize == 4) ? 4 : 8; | 1472 | this->ecc.strength = (host->eccsize == 4) ? 4 : 8; |
1233 | } | 1473 | } |
1234 | 1474 | ||
1475 | /* second phase scan */ | ||
1476 | if (nand_scan_tail(mtd)) { | ||
1477 | err = -ENXIO; | ||
1478 | goto escan; | ||
1479 | } | ||
1480 | |||
1235 | /* Register the partitions */ | 1481 | /* Register the partitions */ |
1236 | mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts, | 1482 | mtd_device_parse_register(mtd, part_probes, |
1237 | pdata->nr_parts); | 1483 | &(struct mtd_part_parser_data){ |
1484 | .of_node = pdev->dev.of_node, | ||
1485 | }, | ||
1486 | host->pdata.parts, | ||
1487 | host->pdata.nr_parts); | ||
1238 | 1488 | ||
1239 | platform_set_drvdata(pdev, host); | 1489 | platform_set_drvdata(pdev, host); |
1240 | 1490 | ||
@@ -1275,6 +1525,8 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
1275 | static struct platform_driver mxcnd_driver = { | 1525 | static struct platform_driver mxcnd_driver = { |
1276 | .driver = { | 1526 | .driver = { |
1277 | .name = DRIVER_NAME, | 1527 | .name = DRIVER_NAME, |
1528 | .owner = THIS_MODULE, | ||
1529 | .of_match_table = of_match_ptr(mxcnd_dt_ids), | ||
1278 | }, | 1530 | }, |
1279 | .remove = __devexit_p(mxcnd_remove), | 1531 | .remove = __devexit_p(mxcnd_remove), |
1280 | }; | 1532 | }; |