aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-10-05 06:14:21 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2009-11-12 02:33:18 -0500
commit9467114ef43c971f0ae8aee3729d412125a2f432 (patch)
tree51f0abdfb14cd5b89fabdd1b5bf6efa6307a24a9 /drivers/mtd/nand
parent2d69c7fadd8580a7cea3ae0caa90a1c2a92ab021 (diff)
mxc_nand: Add NFC V2 support
The v2 version of this controller is used on i.MX35/25 SoCs. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/mxc_nand.c81
1 files changed, 68 insertions, 13 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 09b9aab6823d..4a696820d6d4 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -33,9 +33,13 @@
33 33
34#include <asm/mach/flash.h> 34#include <asm/mach/flash.h>
35#include <mach/mxc_nand.h> 35#include <mach/mxc_nand.h>
36#include <mach/hardware.h>
36 37
37#define DRIVER_NAME "mxc_nand" 38#define DRIVER_NAME "mxc_nand"
38 39
40#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
41#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27())
42
39/* Addresses for NFC registers */ 43/* Addresses for NFC registers */
40#define NFC_BUF_SIZE 0xE00 44#define NFC_BUF_SIZE 0xE00
41#define NFC_BUF_ADDR 0xE04 45#define NFC_BUF_ADDR 0xE04
@@ -46,8 +50,10 @@
46#define NFC_RSLTMAIN_AREA 0xE0E 50#define NFC_RSLTMAIN_AREA 0xE0E
47#define NFC_RSLTSPARE_AREA 0xE10 51#define NFC_RSLTSPARE_AREA 0xE10
48#define NFC_WRPROT 0xE12 52#define NFC_WRPROT 0xE12
49#define NFC_UNLOCKSTART_BLKADDR 0xE14 53#define NFC_V1_UNLOCKSTART_BLKADDR 0xe14
50#define NFC_UNLOCKEND_BLKADDR 0xE16 54#define NFC_V1_UNLOCKEND_BLKADDR 0xe16
55#define NFC_V21_UNLOCKSTART_BLKADDR 0xe20
56#define NFC_V21_UNLOCKEND_BLKADDR 0xe22
51#define NFC_NF_WRPRST 0xE18 57#define NFC_NF_WRPRST 0xE18
52#define NFC_CONFIG1 0xE1A 58#define NFC_CONFIG1 0xE1A
53#define NFC_CONFIG2 0xE1C 59#define NFC_CONFIG2 0xE1C
@@ -116,19 +122,47 @@ struct mxc_nand_host {
116#define TROP_US_DELAY 2000 122#define TROP_US_DELAY 2000
117 123
118/* OOB placement block for use with hardware ecc generation */ 124/* OOB placement block for use with hardware ecc generation */
119static struct nand_ecclayout nand_hw_eccoob_smallpage = { 125static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
120 .eccbytes = 5, 126 .eccbytes = 5,
121 .eccpos = {6, 7, 8, 9, 10}, 127 .eccpos = {6, 7, 8, 9, 10},
122 .oobfree = {{0, 5}, {12, 4}, } 128 .oobfree = {{0, 5}, {12, 4}, }
123}; 129};
124 130
125static struct nand_ecclayout nand_hw_eccoob_largepage = { 131static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
126 .eccbytes = 20, 132 .eccbytes = 20,
127 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, 133 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
128 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, 134 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
129 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, } 135 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
130}; 136};
131 137
138/* OOB description for 512 byte pages with 16 byte OOB */
139static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
140 .eccbytes = 1 * 9,
141 .eccpos = {
142 7, 8, 9, 10, 11, 12, 13, 14, 15
143 },
144 .oobfree = {
145 {.offset = 0, .length = 5}
146 }
147};
148
149/* OOB description for 2048 byte pages with 64 byte OOB */
150static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
151 .eccbytes = 4 * 9,
152 .eccpos = {
153 7, 8, 9, 10, 11, 12, 13, 14, 15,
154 23, 24, 25, 26, 27, 28, 29, 30, 31,
155 39, 40, 41, 42, 43, 44, 45, 46, 47,
156 55, 56, 57, 58, 59, 60, 61, 62, 63
157 },
158 .oobfree = {
159 {.offset = 2, .length = 4},
160 {.offset = 16, .length = 7},
161 {.offset = 32, .length = 7},
162 {.offset = 48, .length = 7}
163 }
164};
165
132#ifdef CONFIG_MTD_PARTITIONS 166#ifdef CONFIG_MTD_PARTITIONS
133static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; 167static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
134#endif 168#endif
@@ -219,7 +253,7 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
219 struct mxc_nand_host *host = nand_chip->priv; 253 struct mxc_nand_host *host = nand_chip->priv;
220 int bufs, i; 254 int bufs, i;
221 255
222 if (mtd->writesize > 512) 256 if (nfc_is_v1() && mtd->writesize > 512)
223 bufs = 4; 257 bufs = 4;
224 else 258 else
225 bufs = 1; 259 bufs = 1;
@@ -613,6 +647,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
613 send_cmd(host, command, true); 647 send_cmd(host, command, true);
614 mxc_do_addr_cycle(mtd, column, page_addr); 648 mxc_do_addr_cycle(mtd, column, page_addr);
615 send_read_id(host); 649 send_read_id(host);
650 host->buf_start = column;
616 break; 651 break;
617 652
618 case NAND_CMD_ERASE1: 653 case NAND_CMD_ERASE1:
@@ -633,6 +668,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
633 struct resource *res; 668 struct resource *res;
634 uint16_t tmp; 669 uint16_t tmp;
635 int err = 0, nr_parts = 0; 670 int err = 0, nr_parts = 0;
671 struct nand_ecclayout *oob_smallpage, *oob_largepage;
636 672
637 /* Allocate memory for MTD device structure and private data */ 673 /* Allocate memory for MTD device structure and private data */
638 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + 674 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
@@ -641,7 +677,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
641 return -ENOMEM; 677 return -ENOMEM;
642 678
643 host->data_buf = (uint8_t *)(host + 1); 679 host->data_buf = (uint8_t *)(host + 1);
644 host->spare_len = 16;
645 680
646 host->dev = &pdev->dev; 681 host->dev = &pdev->dev;
647 /* structures must be linked */ 682 /* structures must be linked */
@@ -686,10 +721,23 @@ static int __init mxcnd_probe(struct platform_device *pdev)
686 goto eres; 721 goto eres;
687 } 722 }
688 723
689 host->regs = host->base;
690 host->main_area0 = host->base; 724 host->main_area0 = host->base;
691 host->main_area1 = host->base + 0x200; 725 host->main_area1 = host->base + 0x200;
692 host->spare0 = host->base + 0x800; 726
727 if (nfc_is_v21()) {
728 host->regs = host->base + 0x1000;
729 host->spare0 = host->base + 0x1000;
730 host->spare_len = 64;
731 oob_smallpage = &nandv2_hw_eccoob_smallpage;
732 oob_largepage = &nandv2_hw_eccoob_largepage;
733 } else if (nfc_is_v1()) {
734 host->regs = host->base;
735 host->spare0 = host->base + 0x800;
736 host->spare_len = 16;
737 oob_smallpage = &nandv1_hw_eccoob_smallpage;
738 oob_largepage = &nandv1_hw_eccoob_largepage;
739 } else
740 BUG();
693 741
694 tmp = readw(host->regs + NFC_CONFIG1); 742 tmp = readw(host->regs + NFC_CONFIG1);
695 tmp |= NFC_INT_MSK; 743 tmp |= NFC_INT_MSK;
@@ -711,15 +759,22 @@ static int __init mxcnd_probe(struct platform_device *pdev)
711 writew(0x2, host->regs + NFC_CONFIG); 759 writew(0x2, host->regs + NFC_CONFIG);
712 760
713 /* Blocks to be unlocked */ 761 /* Blocks to be unlocked */
714 writew(0x0, host->regs + NFC_UNLOCKSTART_BLKADDR); 762 if (nfc_is_v21()) {
715 writew(0x4000, host->regs + NFC_UNLOCKEND_BLKADDR); 763 writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
764 writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
765 this->ecc.bytes = 9;
766 } else if (nfc_is_v1()) {
767 writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
768 writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
769 this->ecc.bytes = 3;
770 } else
771 BUG();
716 772
717 /* Unlock Block Command for given address range */ 773 /* Unlock Block Command for given address range */
718 writew(0x4, host->regs + NFC_WRPROT); 774 writew(0x4, host->regs + NFC_WRPROT);
719 775
720 this->ecc.size = 512; 776 this->ecc.size = 512;
721 this->ecc.bytes = 3; 777 this->ecc.layout = oob_smallpage;
722 this->ecc.layout = &nand_hw_eccoob_smallpage;
723 778
724 if (pdata->hw_ecc) { 779 if (pdata->hw_ecc) {
725 this->ecc.calculate = mxc_nand_calculate_ecc; 780 this->ecc.calculate = mxc_nand_calculate_ecc;
@@ -747,7 +802,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
747 } 802 }
748 803
749 if (mtd->writesize == 2048) 804 if (mtd->writesize == 2048)
750 this->ecc.layout = &nand_hw_eccoob_largepage; 805 this->ecc.layout = oob_largepage;
751 806
752 /* second phase scan */ 807 /* second phase scan */
753 if (nand_scan_tail(mtd)) { 808 if (nand_scan_tail(mtd)) {