All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kyungmin Park <kyungmin.park@samsung.com>
To: linux-mtd@lists.infradead.org
Subject: OneNAND: interrupt based wait support (for reference)
Date: Fri, 03 Nov 2006 09:29:22 +0000 (GMT)	[thread overview]
Message-ID: <8759205.60761162546191576.JavaMail.weblogic@ep_ml21> (raw)

Hi,

The previous mail has some problem. So I send it again.

Here's full referenece code against mtd tree.

Just reference to apollon source. Apollon patch will be sent to omap mailing list.

Please apply the previous patch. :)

Thank you,
Kyungmin Park

--


diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 03d6905..e181945 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -24,6 +24,7 @@ #include <linux/mtd/partitions.h>
 #include <linux/mtd/onenand.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -45,6 +46,8 @@ #define SW_ENTER_GPIO16		16
 #define SW_UP_GPIO17		17
 #define SW_DOWN_GPIO58		58
 
+#define APOLLON_FLASH_GPIO_IRQ	72
+
 static struct mtd_partition apollon_partitions[] = {
 	{
 		.name		= "X-Loader + U-Boot",
@@ -84,10 +87,17 @@ static struct flash_platform_data apollo
 	.nr_parts	= ARRAY_SIZE(apollon_partitions),
 };
 
-static struct resource apollon_flash_resource = {
-	.start		= APOLLON_CS0_BASE,
-	.end		= APOLLON_CS0_BASE + SZ_128K,
-	.flags		= IORESOURCE_MEM,
+static struct resource apollon_flash_resource[] = {
+	[0] = {
+		.start	= APOLLON_CS0_BASE,
+		.end	= APOLLON_CS0_BASE + SZ_128K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= OMAP_GPIO_IRQ(APOLLON_FLASH_GPIO_IRQ),
+		.end	= OMAP_GPIO_IRQ(APOLLON_FLASH_GPIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device apollon_onenand_device = {
@@ -96,8 +106,8 @@ static struct platform_device apollon_on
 	.dev		= {
 		.platform_data	= &apollon_flash_data,
 	},
-	.num_resources	= ARRAY_SIZE(&apollon_flash_resource),
-	.resource	= &apollon_flash_resource,
+	.num_resources	= ARRAY_SIZE(apollon_flash_resource),
+	.resource	= apollon_flash_resource,
 };
 
 static struct resource apollon_smc91x_resources[] = {
@@ -152,12 +162,24 @@ static inline void __init apollon_init_s
 	omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
 }
 
+static inline void __init apollon_init_flash(void)
+{
+	if (omap_request_gpio(APOLLON_FLASH_GPIO_IRQ) < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for onenand IRQ\n",
+			APOLLON_FLASH_GPIO_IRQ);
+		return;
+	}
+	omap_set_gpio_direction(APOLLON_FLASH_GPIO_IRQ, 1);
+	set_irq_type(OMAP_GPIO_IRQ(APOLLON_FLASH_GPIO_IRQ), IRQT_RISING);
+}
+
 static void __init omap_apollon_init_irq(void)
 {
 	omap2_init_common_hw();
 	omap_init_irq();
 	omap_gpio_init();
 	apollon_init_smc91x();
+	apollon_init_flash();
 }
 
 static struct omap_uart_config apollon_uart_config __initdata = {
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index af06a80..cdf80c6 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -63,6 +63,7 @@ static int __devinit generic_onenand_pro
 	}
 
 	info->onenand.mmcontrol = pdata->mmcontrol;
+	info->onenand.irq = platform_get_irq(pdev, 0);
 
 	info->mtd.name = pdev->dev.bus_id;
 	info->mtd.priv = &info->onenand;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8ed68b2..aea13a3 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -13,6 +13,7 @@ #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
@@ -339,6 +340,111 @@ static int onenand_wait(struct mtd_info 
 	return 0;
 }
 
+/*
+ * onenand_interrupt - [DEFAULT] onenand interrupt handler
+ * @param irq		onenand interrupt number
+ * @param dev_id	interrupt data
+ *
+ * complete the work
+ */
+static irqreturn_t onenand_interrupt(int irq, void *data)
+{
+	struct onenand_chip *this = (struct onenand_chip *) data;
+
+	/* To handle shared interrupt */
+	if (!this->complete.done)
+		complete(&this->complete);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * onenand_interrupt_wait - [DEFAULT] wait until the command is done
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_interrupt_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	/* To prevent soft lockup */
+	touch_softlockup_watchdog();
+
+	wait_for_completion(&this->complete);
+
+	return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_try_interrupt_wait - [DEFAULT] try interrupt wait
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Try interrupt based wait (It is used one-time)
+ */
+static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned long remain, timeout;
+
+	/* We use interrupt wait first */
+	this->wait = onenand_interrupt_wait;
+
+	/* To prevent soft lockup */
+	touch_softlockup_watchdog();
+
+	timeout = msecs_to_jiffies(100);
+	remain = wait_for_completion_timeout(&this->complete, timeout);
+	if (!remain) {
+		printk(KERN_INFO "OneNAND: There's no interrupt. "
+				"We use the normal wait\n");
+
+		/* Release the irq */
+		free_irq(this->irq, this);
+		
+		this->wait = onenand_wait;
+	}
+
+	return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_setup_wait - [OneNAND Interface] setup onenand wait method
+ * @param mtd		MTD device structure
+ *
+ * There's two method to wait onenand work
+ * 1. polling - read interrupt status register
+ * 2. interrupt - use the kernel interrupt method
+ */
+static void onenand_setup_wait(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int syscfg;
+
+	init_completion(&this->complete);
+
+	if (this->irq <= 0) {
+		this->wait = onenand_wait;
+		return;
+	}
+
+	if (request_irq(this->irq, &onenand_interrupt,
+				IRQF_SHARED, "onenand", this)) {
+		/* If we can't get irq, use the normal wait */
+		this->wait = onenand_wait;
+		return;
+	}
+
+	/* Enable interrupt */
+	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+	syscfg |= ONENAND_SYS_CFG1_IOBE;
+	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
+
+	this->wait = onenand_try_interrupt_wait;
+}
+
 /**
  * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
  * @param mtd		MTD data structure
@@ -1129,7 +1235,6 @@ static void onenand_sync(struct mtd_info
 	onenand_release_device(mtd);
 }
 
-
 /**
  * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
  * @param mtd		MTD device structure
@@ -1846,7 +1951,7 @@ int onenand_scan(struct mtd_info *mtd, i
 	if (!this->command)
 		this->command = onenand_command;
 	if (!this->wait)
-		this->wait = onenand_wait;
+		onenand_setup_wait(mtd);
 
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
index 6e59805..a497dcc 100644
--- a/include/asm-arm/arch-omap/omap24xx.h
+++ b/include/asm-arm/arch-omap/omap24xx.h
@@ -16,6 +16,8 @@ #define VA_IC_BASE		IO_ADDRESS(OMAP24XX_
 #define OMAP24XX_IVA_INTC_BASE	0x40000000
 #define IRQ_SIR_IRQ		0x0040
 
+#define OMAP242X_CONTROL_STATUS	(L4_24XX_BASE + 0x2f8)
+
 #define OMAP24XX_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
 #define OMAP24XX_PRCM_BASE	(L4_24XX_BASE + 0x8000)
 #define OMAP24XX_SDRC_BASE	(L3_24XX_BASE + 0x9000)
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 6f045b5..df963f1 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -13,6 +13,7 @@ #ifndef __LINUX_MTD_ONENAND_H
 #define __LINUX_MTD_ONENAND_H
 
 #include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/mtd/bbm.h>
 
@@ -120,6 +121,9 @@ struct onenand_chip {
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	int (*scan_bbt)(struct mtd_info *mtd);
 
+	struct completion	complete;
+	int			irq;
+
 	spinlock_t		chip_lock;
 	wait_queue_head_t	wq;
 	onenand_state_t		state;

             reply	other threads:[~2006-11-03  9:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-03  9:29 Kyungmin Park [this message]
2006-11-03  9:36 ` OneNAND: interrupt based wait support (for reference) Artem Bityutskiy
     [not found] <9737167.495191163379347461.JavaMail.weblogic@ep_ml28>
2006-11-13  7:43 ` Artem Bityutskiy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8759205.60761162546191576.JavaMail.weblogic@ep_ml21 \
    --to=kyungmin.park@samsung.com \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.