[PATCH] [MTD] S3C24XX NAND: Use interrupt based RnB
Harald Welte
laforge at openmoko.org
Tue Oct 21 22:49:07 CEST 2008
With this patch, you can define USE_IRQ and switch the driver
from busy-waiting for RnB to an interrupt + completion based
method.
Signed-off-by: Harald Welte <laforge at openmoko.org>
---
drivers/mtd/nand/s3c2410.c | 73 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 72 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index eeb48ed..cb4c00e 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -52,6 +52,8 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -119,6 +121,7 @@ struct s3c2410_nand_info {
void __iomem *sel_reg;
int sel_bit;
int mtd_count;
+ struct completion rnb_completion;
enum s3c_cpu_type cpu_type;
};
@@ -225,9 +228,14 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
+#ifdef USE_IRQ
+ /* enable the controller, enable RnB IRQ and de-assert nFCE */
+ writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_RNBINT_EN,
+ info->regs + S3C2440_NFCONT);
+#else
/* enable the controller and de-assert nFCE */
-
writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
+#endif
}
dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
@@ -505,12 +513,56 @@ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int
writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
}
+#ifdef USE_IRQ
+static irqreturn_t s3c2440_nand_irq(int irq, void *dev_id)
+{
+ struct s3c2410_nand_info *info = dev_id;
+ u_int8_t stat = readb(info->regs + S3C2440_NFSTAT);
+
+ if (stat & S3C2440_NFSTAT_RnB_CHANGE) {
+ //dev_err(info->device, "RnB IRQ\n");
+ /* clear the RnB change status */
+ writeb(stat | S3C2440_NFSTAT_RnB_CHANGE,
+ info->regs + S3C2440_NFSTAT);
+ /* FIXME: should we check RnB status ? */
+ complete(&info->rnb_completion);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void s3c2440_nand_wait_ready(struct mtd_info *mtd)
+{
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+
+ /* FIXME: do we have a race condition? How to solve it? */
+ if (s3c2440_nand_devready(mtd)) {
+ dev_err(info->device, "immediately ready\n");
+ return;
+ }
+
+ //dev_err(info->device, "waiting for completion\n");
+ wait_for_completion(&info->rnb_completion);
+ //dev_err(info->device, "completed\n");
+}
+#endif /* USE_IRQ */
+
/* device management functions */
static int s3c2410_nand_remove(struct platform_device *pdev)
{
struct s3c2410_nand_info *info = to_nand_info(pdev);
+ switch (info->cpu_type) {
+ case TYPE_S3C2440:
+#ifdef USE_IRQ
+ free_irq(IRQ_NFCON, s3c2440_nand_irq);
+#endif /* USE_IRQ */
+ break;
+ default:
+ break;
+ }
+
platform_set_drvdata(pdev, NULL);
if (info == NULL)
@@ -633,6 +685,9 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
info->sel_bit = S3C2440_NFCONT_nFCE;
chip->cmd_ctrl = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
+#ifdef USE_IRQ
+ chip->wait_ready= s3c2440_nand_wait_ready;
+#endif
chip->read_buf = s3c2440_nand_read_buf;
chip->write_buf = s3c2440_nand_write_buf;
break;
@@ -777,6 +832,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
info->platform = plat;
info->regs = ioremap(res->start, size);
info->cpu_type = cpu_type;
+ init_completion(&info->rnb_completion);
if (info->regs == NULL) {
dev_err(&pdev->dev, "cannot reserve register region\n");
@@ -786,6 +842,21 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
+ switch (cpu_type) {
+ case TYPE_S3C2440:
+#ifdef USE_IRQ
+ if (request_irq(IRQ_NFCON, s3c2440_nand_irq, 0,
+ "s3c2440_nand", info)) {
+ dev_err(&pdev->dev, "cannot request interrupt");
+ err = -EIO;
+ goto exit_error;
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+
/* initialise the hardware */
err = s3c2410_nand_inithw(info, pdev);
--
1.5.6.5
--8t9RHnE3ZwKMSgU+--
More information about the openmoko-kernel
mailing list