You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.4 KiB
117 lines
3.4 KiB
From cc77f36d2ea812027dc2a8a94c788c4c145f82dc Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <blogic@openwrt.org>
|
|
Date: Mon, 22 Oct 2012 10:25:39 +0200
|
|
Subject: [PATCH 33/40] MTD: lantiq: xway: make nand actually work
|
|
|
|
http://lists.infradead.org/pipermail/linux-mtd/2012-September/044240.html
|
|
|
|
Signed-off-by: John Crispin <blogic@openwrt.org>
|
|
---
|
|
drivers/mtd/nand/xway_nand.c | 54 +++++++++++++++++++++++++++++++++++-------
|
|
1 file changed, 45 insertions(+), 9 deletions(-)
|
|
|
|
--- a/drivers/mtd/nand/xway_nand.c
|
|
+++ b/drivers/mtd/nand/xway_nand.c
|
|
@@ -54,19 +54,29 @@
|
|
#define NAND_CON_CSMUX (1 << 1)
|
|
#define NAND_CON_NANDM 1
|
|
|
|
+static u32 xway_latchcmd;
|
|
+
|
|
static void xway_reset_chip(struct nand_chip *chip)
|
|
{
|
|
unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
|
|
unsigned long flags;
|
|
+ unsigned long timeout;
|
|
|
|
nandaddr &= ~NAND_WRITE_ADDR;
|
|
nandaddr |= NAND_WRITE_CMD;
|
|
|
|
/* finish with a reset */
|
|
+ timeout = jiffies + msecs_to_jiffies(200);
|
|
+
|
|
spin_lock_irqsave(&ebu_lock, flags);
|
|
+
|
|
writeb(NAND_WRITE_CMD_RESET, (void __iomem *) nandaddr);
|
|
- while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
|
|
- ;
|
|
+ do {
|
|
+ if ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
|
|
+ break;
|
|
+ cond_resched();
|
|
+ } while (!time_after_eq(jiffies, timeout));
|
|
+
|
|
spin_unlock_irqrestore(&ebu_lock, flags);
|
|
}
|
|
|
|
@@ -94,17 +104,15 @@ static void xway_cmd_ctrl(struct mtd_inf
|
|
unsigned long flags;
|
|
|
|
if (ctrl & NAND_CTRL_CHANGE) {
|
|
- nandaddr &= ~(NAND_WRITE_CMD | NAND_WRITE_ADDR);
|
|
if (ctrl & NAND_CLE)
|
|
- nandaddr |= NAND_WRITE_CMD;
|
|
- else
|
|
- nandaddr |= NAND_WRITE_ADDR;
|
|
- this->IO_ADDR_W = (void __iomem *) nandaddr;
|
|
+ xway_latchcmd = NAND_WRITE_CMD;
|
|
+ else if (ctrl & NAND_ALE)
|
|
+ xway_latchcmd = NAND_WRITE_ADDR;
|
|
}
|
|
|
|
if (cmd != NAND_CMD_NONE) {
|
|
spin_lock_irqsave(&ebu_lock, flags);
|
|
- writeb(cmd, this->IO_ADDR_W);
|
|
+ writeb(cmd, (void __iomem *) (nandaddr | xway_latchcmd));
|
|
while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
|
|
;
|
|
spin_unlock_irqrestore(&ebu_lock, flags);
|
|
@@ -124,12 +132,38 @@ static unsigned char xway_read_byte(stru
|
|
int ret;
|
|
|
|
spin_lock_irqsave(&ebu_lock, flags);
|
|
- ret = ltq_r8((void __iomem *)(nandaddr + NAND_READ_DATA));
|
|
+ ret = ltq_r8((void __iomem *)(nandaddr | NAND_READ_DATA));
|
|
spin_unlock_irqrestore(&ebu_lock, flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
+static void xway_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
|
+{
|
|
+ struct nand_chip *this = mtd->priv;
|
|
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_R;
|
|
+ unsigned long flags;
|
|
+ int i;
|
|
+
|
|
+ spin_lock_irqsave(&ebu_lock, flags);
|
|
+ for (i = 0; i < len; i++)
|
|
+ buf[i] = ltq_r8((void __iomem *)(nandaddr | NAND_READ_DATA));
|
|
+ spin_unlock_irqrestore(&ebu_lock, flags);
|
|
+}
|
|
+
|
|
+static void xway_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
|
+{
|
|
+ struct nand_chip *this = mtd->priv;
|
|
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
|
|
+ unsigned long flags;
|
|
+ int i;
|
|
+
|
|
+ spin_lock_irqsave(&ebu_lock, flags);
|
|
+ for (i = 0; i < len; i++)
|
|
+ ltq_w8(buf[i], (void __iomem *)nandaddr);
|
|
+ spin_unlock_irqrestore(&ebu_lock, flags);
|
|
+}
|
|
+
|
|
static int xway_nand_probe(struct platform_device *pdev)
|
|
{
|
|
struct nand_chip *this = platform_get_drvdata(pdev);
|
|
@@ -175,6 +209,8 @@ static struct platform_nand_data xway_na
|
|
.dev_ready = xway_dev_ready,
|
|
.select_chip = xway_select_chip,
|
|
.read_byte = xway_read_byte,
|
|
+ .read_buf = xway_read_buf,
|
|
+ .write_buf = xway_write_buf,
|
|
}
|
|
};
|
|
|
|
|