Commit d178e3e8 authored by Baruch Siach's avatar Baruch Siach Committed by David Woodhouse

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: default avatarBaruch Siach <baruch@tkos.co.il>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 61c4f2c8
...@@ -56,8 +56,14 @@ ...@@ -56,8 +56,14 @@
#define NFC_V1_V2_WRPROT (host->regs + 0x12) #define NFC_V1_V2_WRPROT (host->regs + 0x12)
#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
#define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) #define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
#define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) #define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
...@@ -152,6 +158,7 @@ struct mxc_nand_host { ...@@ -152,6 +158,7 @@ struct mxc_nand_host {
int clk_act; int clk_act;
int irq; int irq;
int eccsize; int eccsize;
int active_cs;
struct completion op_completion; struct completion op_completion;
...@@ -445,7 +452,7 @@ static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) ...@@ -445,7 +452,7 @@ static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
for (i = 0; i < bufs; i++) { for (i = 0; i < bufs; i++) {
/* NANDFC buffer 0 is used for page read/write */ /* NANDFC buffer 0 is used for page read/write */
writew(i, NFC_V1_V2_BUF_ADDR); writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
writew(ops, NFC_V1_V2_CONFIG2); writew(ops, NFC_V1_V2_CONFIG2);
...@@ -470,7 +477,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) ...@@ -470,7 +477,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host)
struct nand_chip *this = &host->nand; struct nand_chip *this = &host->nand;
/* NANDFC buffer 0 is used for device ID output */ /* NANDFC buffer 0 is used for device ID output */
writew(0x0, NFC_V1_V2_BUF_ADDR); writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
writew(NFC_ID, NFC_V1_V2_CONFIG2); writew(NFC_ID, NFC_V1_V2_CONFIG2);
...@@ -505,7 +512,7 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) ...@@ -505,7 +512,7 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
uint32_t store; uint32_t store;
uint16_t ret; uint16_t ret;
writew(0x0, NFC_V1_V2_BUF_ADDR); writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
/* /*
* The device status is stored in main_area0. To * 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,24 +693,24 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
struct nand_chip *nand_chip = mtd->priv; struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv; struct mxc_nand_host *host = nand_chip->priv;
switch (chip) { if (chip == -1) {
case -1:
/* Disable the NFC clock */ /* Disable the NFC clock */
if (host->clk_act) { if (host->clk_act) {
clk_disable(host->clk); clk_disable(host->clk);
host->clk_act = 0; host->clk_act = 0;
} }
break; return;
case 0: }
if (!host->clk_act) {
/* Enable the NFC clock */ /* Enable the NFC clock */
if (!host->clk_act) { clk_enable(host->clk);
clk_enable(host->clk); host->clk_act = 1;
host->clk_act = 1; }
}
break;
default: if (nfc_is_v21()) {
break; host->active_cs = chip;
writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
} }
} }
...@@ -834,8 +841,14 @@ static void preset_v1_v2(struct mtd_info *mtd) ...@@ -834,8 +841,14 @@ static void preset_v1_v2(struct mtd_info *mtd)
/* Blocks to be unlocked */ /* Blocks to be unlocked */
if (nfc_is_v21()) { if (nfc_is_v21()) {
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
} else if (nfc_is_v1()) { } else if (nfc_is_v1()) {
writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
...@@ -1200,7 +1213,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) ...@@ -1200,7 +1213,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
irq_control_v1_v2(host, 1); irq_control_v1_v2(host, 1);
/* first scan to find the device and get the page size */ /* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1, NULL)) { if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
err = -ENXIO; err = -ENXIO;
goto escan; goto escan;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment