diff options
author | Baruch Siach <baruch@tkos.co.il> | 2011-03-14 03:01:56 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2011-05-24 20:47:08 -0400 |
commit | d178e3e88f538323eb483df1563c8edfb71fdb39 (patch) | |
tree | c22ccf56a1910eab2688e2d68e70ccaac24cdfea /drivers/mtd/nand/mxc_nand.c | |
parent | 61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (diff) |
mtd: mxc_nand: add support for multiple chips on V21 devices
Do the following to add support for up to 4 chips on V21 devices (i.MX25 and
i.MX35):
* implement .select_chip for V21
* adjust existing NFC_V1_V2_BUF_ADDR writes to take chip select into account
* unlock all chip selects at preset_v1_v2()
* scan up to 4 devices at .probe
This has been tested on i.MX25 with two attached NAND chip (on one die).
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 42a95fb41504..b4efdb704ed2 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -56,8 +56,14 @@ | |||
56 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) | 56 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) |
57 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) | 57 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) |
58 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) | 58 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) |
59 | #define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) | 59 | #define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20) |
60 | #define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) | 60 | #define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24) |
61 | #define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28) | ||
62 | #define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c) | ||
63 | #define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22) | ||
64 | #define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26) | ||
65 | #define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a) | ||
66 | #define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e) | ||
61 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) | 67 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) |
62 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) | 68 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) |
63 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) | 69 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) |
@@ -152,6 +158,7 @@ struct mxc_nand_host { | |||
152 | int clk_act; | 158 | int clk_act; |
153 | int irq; | 159 | int irq; |
154 | int eccsize; | 160 | int eccsize; |
161 | int active_cs; | ||
155 | 162 | ||
156 | struct completion op_completion; | 163 | struct completion op_completion; |
157 | 164 | ||
@@ -445,7 +452,7 @@ static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | |||
445 | for (i = 0; i < bufs; i++) { | 452 | for (i = 0; i < bufs; i++) { |
446 | 453 | ||
447 | /* NANDFC buffer 0 is used for page read/write */ | 454 | /* NANDFC buffer 0 is used for page read/write */ |
448 | writew(i, NFC_V1_V2_BUF_ADDR); | 455 | writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR); |
449 | 456 | ||
450 | writew(ops, NFC_V1_V2_CONFIG2); | 457 | writew(ops, NFC_V1_V2_CONFIG2); |
451 | 458 | ||
@@ -470,7 +477,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
470 | struct nand_chip *this = &host->nand; | 477 | struct nand_chip *this = &host->nand; |
471 | 478 | ||
472 | /* NANDFC buffer 0 is used for device ID output */ | 479 | /* NANDFC buffer 0 is used for device ID output */ |
473 | writew(0x0, NFC_V1_V2_BUF_ADDR); | 480 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); |
474 | 481 | ||
475 | writew(NFC_ID, NFC_V1_V2_CONFIG2); | 482 | writew(NFC_ID, NFC_V1_V2_CONFIG2); |
476 | 483 | ||
@@ -505,7 +512,7 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) | |||
505 | uint32_t store; | 512 | uint32_t store; |
506 | uint16_t ret; | 513 | uint16_t ret; |
507 | 514 | ||
508 | writew(0x0, NFC_V1_V2_BUF_ADDR); | 515 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); |
509 | 516 | ||
510 | /* | 517 | /* |
511 | * The device status is stored in main_area0. To | 518 | * The device status is stored in main_area0. To |
@@ -686,24 +693,24 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
686 | struct nand_chip *nand_chip = mtd->priv; | 693 | struct nand_chip *nand_chip = mtd->priv; |
687 | struct mxc_nand_host *host = nand_chip->priv; | 694 | struct mxc_nand_host *host = nand_chip->priv; |
688 | 695 | ||
689 | switch (chip) { | 696 | if (chip == -1) { |
690 | case -1: | ||
691 | /* Disable the NFC clock */ | 697 | /* Disable the NFC clock */ |
692 | if (host->clk_act) { | 698 | if (host->clk_act) { |
693 | clk_disable(host->clk); | 699 | clk_disable(host->clk); |
694 | host->clk_act = 0; | 700 | host->clk_act = 0; |
695 | } | 701 | } |
696 | break; | 702 | return; |
697 | case 0: | 703 | } |
704 | |||
705 | if (!host->clk_act) { | ||
698 | /* Enable the NFC clock */ | 706 | /* Enable the NFC clock */ |
699 | if (!host->clk_act) { | 707 | clk_enable(host->clk); |
700 | clk_enable(host->clk); | 708 | host->clk_act = 1; |
701 | host->clk_act = 1; | 709 | } |
702 | } | ||
703 | break; | ||
704 | 710 | ||
705 | default: | 711 | if (nfc_is_v21()) { |
706 | break; | 712 | host->active_cs = chip; |
713 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
707 | } | 714 | } |
708 | } | 715 | } |
709 | 716 | ||
@@ -834,8 +841,14 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
834 | 841 | ||
835 | /* Blocks to be unlocked */ | 842 | /* Blocks to be unlocked */ |
836 | if (nfc_is_v21()) { | 843 | if (nfc_is_v21()) { |
837 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); | 844 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); |
838 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); | 845 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); |
846 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); | ||
847 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); | ||
848 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); | ||
849 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); | ||
850 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); | ||
851 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); | ||
839 | } else if (nfc_is_v1()) { | 852 | } else if (nfc_is_v1()) { |
840 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | 853 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
841 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); | 854 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); |
@@ -1200,7 +1213,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1200 | irq_control_v1_v2(host, 1); | 1213 | irq_control_v1_v2(host, 1); |
1201 | 1214 | ||
1202 | /* first scan to find the device and get the page size */ | 1215 | /* first scan to find the device and get the page size */ |
1203 | if (nand_scan_ident(mtd, 1, NULL)) { | 1216 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { |
1204 | err = -ENXIO; | 1217 | err = -ENXIO; |
1205 | goto escan; | 1218 | goto escan; |
1206 | } | 1219 | } |