* [PATCH v4 1/4] omap3: nand: prefetch in irq mode support
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
@ 2010-08-02 15:49 ` Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 2/4] omap3: nand: configurable fifo threshold to gain the throughput Sukumar Ghorai
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sukumar Ghorai @ 2010-08-02 15:49 UTC (permalink / raw)
To: linux-arm-kernel
This patch enable prefetch-irq mode for NAND.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-flash.c | 2 +
arch/arm/mach-omap2/gpmc.c | 4 +
arch/arm/plat-omap/include/plat/gpmc.h | 4 +
arch/arm/plat-omap/include/plat/irqs.h | 1 +
arch/arm/plat-omap/include/plat/nand.h | 1 +
drivers/mtd/nand/Kconfig | 14 ++-
drivers/mtd/nand/omap2.c | 196 +++++++++++++++++++++++++++++++-
7 files changed, 216 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index ac834aa..4871d71 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -17,6 +17,7 @@
#include <linux/mtd/physmap.h>
#include <linux/io.h>
+#include <plat/irqs.h>
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/onenand.h>
@@ -133,6 +134,7 @@ static struct omap_nand_platform_data board_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .gpmc_irq = INT_34XX_GPMC_IRQ,
.dev_ready = NULL,
.devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
};
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index f46933b..86a6f78 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -487,6 +487,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
u32 regval = 0;
switch (cmd) {
+ case GPMC_ENABLE_IRQ:
+ gpmc_write_reg(GPMC_IRQENABLE, wval);
+ break;
+
case GPMC_SET_IRQ_STATUS:
gpmc_write_reg(GPMC_IRQSTATUS, wval);
break;
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 9fd99b9..054e704 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -41,6 +41,8 @@
#define GPMC_NAND_ADDRESS 0x0000000b
#define GPMC_NAND_DATA 0x0000000c
+#define GPMC_ENABLE_IRQ 0x0000000d
+
/* ECC commands */
#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
@@ -78,6 +80,8 @@
#define WR_RD_PIN_MONITORING 0x00600000
#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+#define GPMC_IRQ_FIFOEVENTENABLE 0x01
+#define GPMC_IRQ_COUNT_EVENT 0x02
/*
* Note that all values in this struct are in nanoseconds, while
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index c01d9f0..fd6d677 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -318,6 +318,7 @@
#define INT_34XX_PRCM_MPU_IRQ 11
#define INT_34XX_MCBSP1_IRQ 16
#define INT_34XX_MCBSP2_IRQ 17
+#define INT_34XX_GPMC_IRQ 20
#define INT_34XX_MCBSP3_IRQ 22
#define INT_34XX_MCBSP4_IRQ 23
#define INT_34XX_CAM_IRQ 24
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 6562cd0..5e69463 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -20,6 +20,7 @@ struct omap_nand_platform_data {
int (*nand_setup)(void);
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
+ int gpmc_irq;
unsigned long phys_base;
int devsize;
};
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..46361ef 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -112,6 +112,9 @@ config MTD_NAND_OMAP_PREFETCH
help
The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
to improve the performance.
+ GPMC PREFETCH can be configured eigther in MPU interrupt mode or in DMA
+ interrupt mode. If not selected any of them prefetch will be used in
+ polling mode.
config MTD_NAND_OMAP_PREFETCH_DMA
depends on MTD_NAND_OMAP_PREFETCH
@@ -120,7 +123,16 @@ config MTD_NAND_OMAP_PREFETCH_DMA
help
The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
or in DMA interrupt mode.
- Say y for DMA mode or MPU mode will be used
+ Say y for DMA mode
+
+config MTD_NAND_OMAP_PREFETCH_IRQ
+ depends on MTD_NAND_OMAP_PREFETCH && !MTD_NAND_OMAP_PREFETCH_DMA
+ bool "IRQ mode"
+ default n
+ help
+ The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
+ or in DMA interrupt mode.
+ Say y for IRQ mode
config MTD_NAND_IDS
tristate
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 133d515..9dc5ff9 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/mtd/mtd.h>
@@ -105,17 +106,27 @@ module_param(use_prefetch, bool, 0);
MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
+const int use_interrupt;
static int use_dma = 1;
/* "modprobe ... use_dma=0" etc */
module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
+MODULE_PARM_DESC(use_dma, "enable/disable use of DMA mode");
+#elif defined(CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ)
+const int use_dma;
+static int use_interrupt = 1;
+
+/* "modprobe ... use_dma=0" etc */
+module_param(use_interrupt, bool, 0);
+MODULE_PARM_DESC(use_interrupt, "enable/disable use of IRQ mode");
#else
const int use_dma;
+const int use_interrupt;
#endif
#else
const int use_prefetch;
const int use_dma;
+const int use_interrupt;
#endif
struct omap_nand_info {
@@ -130,6 +141,13 @@ struct omap_nand_info {
unsigned long phys_base;
struct completion comp;
int dma_ch;
+ int gpmc_irq;
+ enum {
+ OMAP_NAND_IO_READ = 0, /* read */
+ OMAP_NAND_IO_WRITE, /* write */
+ } iomode;
+ u_char *buf;
+ int buf_len;
};
/**
@@ -467,6 +485,152 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
}
+/*
+ * omap_nand_irq - GMPC irq handler
+ * @this_irq: gpmc irq number
+ * @dev: omap_nand_info structure pointer is passed here
+ */
+static irqreturn_t omap_nand_irq(int this_irq, void *dev)
+{
+ struct omap_nand_info *info = (struct omap_nand_info *) dev;
+ u32 bytes;
+ u32 irq_stat;
+
+ irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+ bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+ bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
+ if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
+ if (irq_stat & 0x2)
+ goto done;
+
+ if (info->buf_len & (info->buf_len < bytes))
+ bytes = info->buf_len;
+ else if (!info->buf_len)
+ bytes = 0;
+ iowrite32_rep(info->nand.IO_ADDR_W,
+ (u32 *)info->buf, bytes >> 2);
+ info->buf = info->buf + bytes;
+ info->buf_len -= bytes;
+
+ } else {
+ ioread32_rep(info->nand.IO_ADDR_R,
+ (u32 *)info->buf, bytes >> 2);
+ info->buf = info->buf + bytes;
+
+ if (irq_stat & 0x2)
+ goto done;
+ }
+ gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+ irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+
+ return IRQ_HANDLED;
+
+done:
+ complete(&info->comp);
+ /* disable irq */
+ gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
+
+ /* clear status */
+ gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+ irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * omap_read_buf_irq_pref - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ int ret = 0;
+
+ if (len <= mtd->oobsize) {
+ omap_read_buf_pref(mtd, buf, len);
+ return;
+ }
+ info->iomode = OMAP_NAND_IO_READ;
+ info->buf = buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ info->buf_len = len;
+ /* enable irq */
+ gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+ (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+
+ /* waiting for read to complete */
+ wait_for_completion(&info->comp);
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset(info->gpmc_cs);
+ return;
+
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_read_buf16(mtd, buf, len);
+ else
+ omap_read_buf8(mtd, buf, len);
+}
+
+/*
+ * omap_write_buf_irq_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_irq_pref(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ int ret = 0;
+ if (len <= mtd->oobsize) {
+ omap_write_buf_pref(mtd, buf, len);
+ return;
+ }
+
+ info->iomode = OMAP_NAND_IO_WRITE;
+ info->buf = (u_char *) buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ info->buf_len = len;
+ /* enable irq */
+ gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+ (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+ /* waiting for write to complete */
+ wait_for_completion(&info->comp);
+ /* wait for data to flushed-out before reset the prefetch */
+ do {
+ ret = gpmc_read_status(GPMC_PREFETCH_COUNT);
+ } while (ret);
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset(info->gpmc_cs);
+ return;
+
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_write_buf16(mtd, buf, len);
+ else
+ omap_write_buf8(mtd, buf, len);
+}
+
/**
* omap_verify_buf - Verify chip data against buffer
* @mtd: MTD device structure
@@ -800,6 +964,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->gpmc_cs = pdata->cs;
info->phys_base = pdata->phys_base;
+ info->gpmc_irq = pdata->gpmc_irq;
info->mtd.priv = &info->nand;
info->mtd.name = dev_name(&pdev->dev);
@@ -863,7 +1028,20 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.read_buf = omap_read_buf_dma_pref;
info->nand.write_buf = omap_write_buf_dma_pref;
}
+ } else if (use_interrupt) {
+ err = request_irq(info->gpmc_irq, omap_nand_irq,
+ IRQF_SHARED, info->mtd.name, info);
+ if (err) {
+ printk(KERN_INFO"failure requesting irq %i."
+ " Prefetch will work in mpu"
+ " poling mode.\n",
+ info->gpmc_irq);
+ } else {
+ info->nand.read_buf = omap_read_buf_irq_pref;
+ info->nand.write_buf = omap_write_buf_irq_pref;
+ }
}
+
} else {
if (info->nand.options & NAND_BUSWIDTH_16) {
info->nand.read_buf = omap_read_buf16;
@@ -953,11 +1131,19 @@ static int __init omap_nand_init(void)
/* This check is required if driver is being
* loaded run time as a module
*/
- if ((1 == use_dma) && (0 == use_prefetch)) {
- printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
- "without use_prefetch'. Prefetch will not be"
- " used in either mode (mpu or dma)\n");
+
+ if ((0 == use_prefetch) && (1 == (use_dma | use_interrupt))) {
+ printk(KERN_INFO "Wrong parameters: Neither 'dma' nor 'irq' "
+ "can used without 'use_prefetch' selected.\n");
+ printk(KERN_INFO "Prefetch will not be used in any mode: "
+ "poll, mpu or dma\n");
+ } else if ((1 == use_prefetch) && (1 == (use_interrupt & use_dma))) {
+ printk(KERN_INFO "Wrong parameters: Both DMA and IRQ"
+ " modes can not be used together.\n");
+ printk(KERN_INFO "It has to be selected at compile "
+ "time and same will be used.\n");
}
+
return platform_driver_register(&omap_nand_driver);
}
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 2/4] omap3: nand: configurable fifo threshold to gain the throughput
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 1/4] omap3: nand: prefetch in irq mode support Sukumar Ghorai
@ 2010-08-02 15:49 ` Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 3/4] omap: nand: ecc layout select from board file Sukumar Ghorai
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sukumar Ghorai @ 2010-08-02 15:49 UTC (permalink / raw)
To: linux-arm-kernel
Configure the FIFO THREASHOLD value different for read and write to keep busy
both filling and to drain out of FIFO at reading and writing.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 11 +++++++----
arch/arm/plat-omap/include/plat/gpmc.h | 5 ++++-
drivers/mtd/nand/omap2.c | 24 +++++++++++++++---------
3 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 86a6f78..8871a91 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -58,7 +58,6 @@
#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
#define GPMC_SECTION_SHIFT 28 /* 128 MB */
-#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
#define CS_NUM_SHIFT 24
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE 2
@@ -592,15 +591,19 @@ EXPORT_SYMBOL(gpmc_nand_write);
/**
* gpmc_prefetch_enable - configures and starts prefetch transfer
* @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
* @dma_mode: dma mode enable (1) or disable (0)
* @u32_count: number of bytes to be transferred
* @is_write: prefetch read(0) or write post(1) mode
*/
-int gpmc_prefetch_enable(int cs, int dma_mode,
+int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
unsigned int u32_count, int is_write)
{
- if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+ if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+ printk(KERN_ERR "PREFETCH Fifo Threshold is not supported\n");
+ return -1;
+ } else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
/* Set the amount of bytes to be prefetched */
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
@@ -608,7 +611,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
* enable the engine. Set which cs is has requested for.
*/
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
- PREFETCH_FIFOTHRESHOLD |
+ PREFETCH_FIFOTHRESHOLD(fifo_th) |
ENABLE_PREFETCH |
(dma_mode << DMA_MPU_MODE) |
(0x1 & is_write)));
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 054e704..fb82335 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -83,6 +83,9 @@
#define GPMC_IRQ_FIFOEVENTENABLE 0x01
#define GPMC_IRQ_COUNT_EVENT 0x02
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val) (val << 8)
+
/*
* Note that all values in this struct are in nanoseconds, while
* the register values are in gpmc_fck cycles.
@@ -133,7 +136,7 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
extern void gpmc_cs_free(int cs);
extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int dma_mode,
+extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
unsigned int u32_count, int is_write);
extern int gpmc_prefetch_reset(int cs);
extern void omap3_gpmc_save_context(void);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 9dc5ff9..20e73bf 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -275,7 +275,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info->nand.options & NAND_BUSWIDTH_16)
@@ -319,7 +320,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info->nand.options & NAND_BUSWIDTH_16)
@@ -373,10 +375,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
dma_addr_t dma_addr;
int ret;
- /* The fifo depth is 64 bytes. We have a sync at each frame and frame
- * length is 64 bytes.
+ /* The fifo depth is 64 bytes max.
+ * But configure the FIFO-threahold to 32 to get a sync at each frame
+ * and frame length is 32 bytes.
*/
- int buf_len = len >> 6;
+ int buf_len = len >> 5;
if (addr >= high_memory) {
struct page *p1;
@@ -415,7 +418,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_MAX/2, 0x1, len, is_write);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
@@ -558,7 +562,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
init_completion(&info->comp);
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
@@ -603,8 +608,9 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
info->buf = (u_char *) buf;
init_completion(&info->comp);
- /* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ /* configure and start prefetch transfer : size=24 */
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ (PREFETCH_FIFOTHRESHOLD_MAX*3)/8, 0x0, len, 0x1);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 3/4] omap: nand: ecc layout select from board file
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 1/4] omap3: nand: prefetch in irq mode support Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 2/4] omap3: nand: configurable fifo threshold to gain the throughput Sukumar Ghorai
@ 2010-08-02 15:49 ` Sukumar Ghorai
2010-08-02 15:49 ` [PATCH v4 4/4] omap: nand: making ecc layout as compatible with romcode ecc Sukumar Ghorai
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sukumar Ghorai @ 2010-08-02 15:49 UTC (permalink / raw)
To: linux-arm-kernel
This patch makes it possible to select sw or hw (different layout options)
ecc scheme supported by omap nand driver. And hw ecc layout selected for
sdp and zoom boards, by default.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/board-flash.c | 3 ++-
arch/arm/plat-omap/include/plat/nand.h | 6 ++++++
drivers/mtd/nand/omap2.c | 29 +++++++++++++----------------
3 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 4871d71..5f74c8f 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -144,7 +144,8 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
{
board_nand_data.cs = cs;
board_nand_data.parts = nand_parts;
- board_nand_data.nr_parts = nr_parts;
+ board_nand_data.nr_parts = nr_parts;
+ board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DIFF_LAYOUT;
gpmc_nand_init(&board_nand_data);
}
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 5e69463..2e026e4 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -23,6 +23,12 @@ struct omap_nand_platform_data {
int gpmc_irq;
unsigned long phys_base;
int devsize;
+ enum {
+ OMAP_ECC_HAMMING_CODE_DIFF_LAYOUT = 0,
+ /* 1-bit s/w ecc and layout different from romcode */
+ OMAP_ECC_HAMMING_CODE_HW,/* 1-bit ecc, romcode layout */
+ OMAP_ECC_HAMMING_CODE_SW,/* 1-bit ecc, romcode layout */
+ } ecc_opt;
};
/* minimum size for IO mapping */
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 20e73bf..63682c0 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -7,7 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define CONFIG_MTD_NAND_OMAP_HWECC
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -658,8 +657,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
return 0;
}
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-
/**
* gen_true_ecc - This function will generate true ECC value
* @ecc_buf: buffer to store ecc code
@@ -879,8 +876,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
}
-#endif
-
/**
* omap_wait - wait until the command is done
* @mtd: MTD device structure
@@ -1059,17 +1054,19 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
info->nand.verify_buf = omap_verify_buf;
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
- info->nand.ecc.bytes = 3;
- info->nand.ecc.size = 512;
- info->nand.ecc.calculate = omap_calculate_ecc;
- info->nand.ecc.hwctl = omap_enable_hwecc;
- info->nand.ecc.correct = omap_correct_data;
- info->nand.ecc.mode = NAND_ECC_HW;
-
-#else
- info->nand.ecc.mode = NAND_ECC_SOFT;
-#endif
+ /* selsect the ecc type */
+ if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DIFF_LAYOUT) ||
+ (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW)) {
+ info->nand.ecc.bytes = 3;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.calculate = omap_calculate_ecc;
+ info->nand.ecc.hwctl = omap_enable_hwecc;
+ info->nand.ecc.correct = omap_correct_data;
+ info->nand.ecc.mode = NAND_ECC_HW;
+
+ } else if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_SW) {
+ info->nand.ecc.mode = NAND_ECC_SOFT;
+ }
/* DIP switches on some boards change between 8 and 16 bit
* bus widths for flash. Try the other width if the first try fails.
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 4/4] omap: nand: making ecc layout as compatible with romcode ecc
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
` (2 preceding siblings ...)
2010-08-02 15:49 ` [PATCH v4 3/4] omap: nand: ecc layout select from board file Sukumar Ghorai
@ 2010-08-02 15:49 ` Sukumar Ghorai
2010-08-04 3:58 ` [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Ghorai, Sukumar
2010-08-06 9:03 ` Ghorai, Sukumar
5 siblings, 0 replies; 8+ messages in thread
From: Sukumar Ghorai @ 2010-08-02 15:49 UTC (permalink / raw)
To: linux-arm-kernel
This patch overrides nand ecc layout and bad block descriptor (for 8-bit
device) to support hw ecc in romcode layout. So as to have in sync with ecc
layout throughout; i.e. x-loader, u-boot and kernel.
This patch also enables to use romcode ecc for spd and zoom, by default.
This enables to flash x-loader, u-boot, kernel, FS images from kernel itself
and compatiable with other tools.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/board-flash.c | 2 +-
drivers/mtd/nand/omap2.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 5f74c8f..d71c511 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -145,7 +145,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
board_nand_data.cs = cs;
board_nand_data.parts = nand_parts;
board_nand_data.nr_parts = nr_parts;
- board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DIFF_LAYOUT;
+ board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_HW;
gpmc_nand_init(&board_nand_data);
}
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 63682c0..1041783 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -128,6 +128,20 @@ const int use_dma;
const int use_interrupt;
#endif
+/* oob info generated runtime depending on ecc algorithm and layout selected */
+static struct nand_ecclayout omap_oobinfo;
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+ .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+ .offs = 0,
+ .len = 1,
+ .pattern = scan_ff_pattern,
+};
+
+
struct omap_nand_info {
struct nand_hw_control controller;
struct omap_nand_platform_data *pdata;
@@ -945,6 +959,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
struct omap_nand_info *info;
struct omap_nand_platform_data *pdata;
int err;
+ int i, offset;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
@@ -1079,6 +1094,25 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
}
+ /* rom code layout */
+ if (pdata->ecc_opt != OMAP_ECC_HAMMING_CODE_DIFF_LAYOUT) {
+ offset = (info->nand.options & NAND_BUSWIDTH_16) ? 2 : 1;
+ if (info->mtd.oobsize == 16) {
+ info->nand.badblock_pattern = &bb_descrip_flashbased;
+ omap_oobinfo.eccbytes = 3;
+ } else
+ omap_oobinfo.eccbytes = 3 * 4;
+
+ for (i = 0; i < omap_oobinfo.eccbytes; i++)
+ omap_oobinfo.eccpos[i] = i+offset;
+
+ omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
+ omap_oobinfo.oobfree->length = info->mtd.oobsize -
+ (offset + omap_oobinfo.eccbytes);
+
+ info->nand.ecc.layout = &omap_oobinfo;
+ }
+
#ifdef CONFIG_MTD_PARTITIONS
err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
if (err > 0)
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
` (3 preceding siblings ...)
2010-08-02 15:49 ` [PATCH v4 4/4] omap: nand: making ecc layout as compatible with romcode ecc Sukumar Ghorai
@ 2010-08-04 3:58 ` Ghorai, Sukumar
2010-08-06 9:03 ` Ghorai, Sukumar
5 siblings, 0 replies; 8+ messages in thread
From: Ghorai, Sukumar @ 2010-08-04 3:58 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Monday, August 02, 2010 9:20 PM
> To: linux-omap at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org;
> Ghorai, Sukumar
> Subject: [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage
>
> The following set of patches applies on top of omap-for-linus.
>
> v4: Comments incorporated
>
> v3: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg32071.html
> Rebase on latest codebase and previous patch(posted).
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg31963.html
>
> v2: Rebase on latest codebase and previous patch(posted).
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg31471.html
>
> v1: http://www.mail-archive.com/linux-
> omap at vger.kernel.org/msg26666.html
>
> Sukumar Ghorai (4):
> omap3: nand: prefetch in irq mode support
> omap: nand: configurable fifo threshold to gain the throughput
> omap: nand: ecc layout select from board file
> omap: nand: making ecc layout as compatible with romcode ecc
>
> arch/arm/mach-omap2/board-flash.c | 5 +-
> arch/arm/mach-omap2/gpmc.c | 15 ++-
> arch/arm/plat-omap/include/plat/gpmc.h | 9 +-
> arch/arm/plat-omap/include/plat/irqs.h | 1 +
> arch/arm/plat-omap/include/plat/nand.h | 7 +
> drivers/mtd/nand/Kconfig | 14 ++-
> drivers/mtd/nand/omap2.c | 277
> ++++++++++++++++++++++++++++---
> 7 files changed, 294 insertions(+), 34 deletions(-)
[Ghorai]
Tony,
Would you please check if you have any input further?
Regards,
Ghorai
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage
2010-08-02 15:49 [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
` (4 preceding siblings ...)
2010-08-04 3:58 ` [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage Ghorai, Sukumar
@ 2010-08-06 9:03 ` Ghorai, Sukumar
2010-08-06 9:10 ` Tony Lindgren
5 siblings, 1 reply; 8+ messages in thread
From: Ghorai, Sukumar @ 2010-08-06 9:03 UTC (permalink / raw)
To: linux-arm-kernel
Tony,
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Wednesday, August 04, 2010 9:29 AM
> To: linux-omap at vger.kernel.org; 'Tony Lindgren'
> Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org
> Subject: RE: [PATCH v4 0/4] nand prefetch-irq support and ecc layout
> chanage
>
> > -----Original Message-----
> > From: Ghorai, Sukumar
> > Sent: Monday, August 02, 2010 9:20 PM
> > To: linux-omap at vger.kernel.org
> > Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org;
> > Ghorai, Sukumar
> > Subject: [PATCH v4 0/4] nand prefetch-irq support and ecc layout chanage
> >
> > The following set of patches applies on top of omap-for-linus.
> >
> > v4: Comments incorporated
> >
> > v3: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg32071.html
> > Rebase on latest codebase and previous patch(posted).
> > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg31963.html
> >
> > v2: Rebase on latest codebase and previous patch(posted).
> > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg31471.html
> >
> > v1: http://www.mail-archive.com/linux-
> > omap at vger.kernel.org/msg26666.html
> >
> > Sukumar Ghorai (4):
> > omap3: nand: prefetch in irq mode support
> > omap: nand: configurable fifo threshold to gain the throughput
> > omap: nand: ecc layout select from board file
> > omap: nand: making ecc layout as compatible with romcode ecc
> >
> > arch/arm/mach-omap2/board-flash.c | 5 +-
> > arch/arm/mach-omap2/gpmc.c | 15 ++-
> > arch/arm/plat-omap/include/plat/gpmc.h | 9 +-
> > arch/arm/plat-omap/include/plat/irqs.h | 1 +
> > arch/arm/plat-omap/include/plat/nand.h | 7 +
> > drivers/mtd/nand/Kconfig | 14 ++-
> > drivers/mtd/nand/omap2.c | 277
> > ++++++++++++++++++++++++++++---
> > 7 files changed, 294 insertions(+), 34 deletions(-)
> [Ghorai]
> Tony,
> Would you please check if you have any input further?
[Ghorai]
Tony,
Would you please check the status of these patch(s).
Regards,
Ghorai
^ permalink raw reply [flat|nested] 8+ messages in thread