* [PATCH-v2 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
[not found] <61339.192.168.10.89.1247226725.squirrel@dbdmail.itg.ti.com>
@ 2009-07-10 13:32 ` vimal singh
[not found] ` <48097.192.168.10.89.1247232736.squirrel@dbdmail.itg.ti.com>
1 sibling, 0 replies; 10+ messages in thread
From: vimal singh @ 2009-07-10 13:32 UTC (permalink / raw)
To: linux-mtd
Cc: Tony Lindgren, dwmw2, dedekind, david-b, linux-kernel, linux-omap
Please ignore previous patch, it had some problem.
Fixing and re-submitting the patch this time.
-vimal
This patch adds prefetch support to access nand flash in mpu mode.
This patch also adds 8-bit nand support (omap_read/write_buf8).
Prefetch can be used for both 8- and 16-bit devices.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 63 ++++++++++++-
arch/arm/plat-omap/include/mach/gpmc.h | 4
drivers/mtd/nand/Kconfig | 8 +
drivers/mtd/nand/omap2.c | 159 +++++++++++++++++++++++++++++++--
4 files changed, 226 insertions(+), 8 deletions(-)
Index: mtd-2.6/arch/arm/mach-omap2/gpmc.c
===================================================================
--- mtd-2.6.orig/arch/arm/mach-omap2/gpmc.c
+++ mtd-2.6/arch/arm/mach-omap2/gpmc.c
@@ -57,6 +57,11 @@
#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
+
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -386,6 +391,63 @@ void gpmc_cs_free(int cs)
}
EXPORT_SYMBOL(gpmc_cs_free);
+/**
+ * gpmc_prefetch_enable - configures and starts prefetch transfer
+ * @cs: nand cs (chip select) number
+ * @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,
+ unsigned int u32_count, int is_write)
+{
+ uint32_t prefetch_config1;
+
+ if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+ /* Set the amount of bytes to be prefetched */
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
+
+ /* Set dma/mpu mode, the prefetch read / post write and
+ * enable the engine. Set which cs is has requested for.
+ */
+ prefetch_config1 = ((cs << CS_NUM_SHIFT) |
+ PREFETCH_FIFOTHRESHOLD |
+ ENABLE_PREFETCH |
+ (dma_mode << DMA_MPU_MODE) |
+ (0x1 & is_write));
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
+ } else {
+ return -EBUSY;
+ }
+ /* Start the prefetch engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_prefetch_enable);
+
+/**
+ * gpmc_prefetch_reset - disables and stops the prefetch engine
+ */
+void gpmc_prefetch_reset(void)
+{
+ /* Stop the PFPW engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
+
+ /* Reset/disable the PFPW engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+}
+EXPORT_SYMBOL(gpmc_prefetch_reset);
+
+/**
+ * gpmc_prefetch_status - reads prefetch status of engine
+ */
+int gpmc_prefetch_status(void)
+{
+ return gpmc_read_reg(GPMC_PREFETCH_STATUS);
+}
+EXPORT_SYMBOL(gpmc_prefetch_status);
+
static void __init gpmc_mem_init(void)
{
int cs;
@@ -452,6 +514,5 @@ void __init gpmc_init(void)
l &= 0x03 << 3;
l |= (0x02 << 3) | (1 << 0);
gpmc_write_reg(GPMC_SYSCONFIG, l);
-
gpmc_mem_init();
}
Index: mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
===================================================================
--- mtd-2.6.orig/arch/arm/plat-omap/include/mach/gpmc.h
+++ mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
@@ -103,6 +103,10 @@ extern int gpmc_cs_request(int cs, unsig
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,
+ unsigned int u32_count, int is_write);
+extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_status(void);
extern void __init gpmc_init(void);
#endif
Index: mtd-2.6/drivers/mtd/nand/Kconfig
===================================================================
--- mtd-2.6.orig/drivers/mtd/nand/Kconfig
+++ mtd-2.6/drivers/mtd/nand/Kconfig
@@ -80,6 +80,14 @@ config MTD_NAND_OMAP2
help
Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
+config MTD_NAND_OMAP_PREFETCH
+ bool "GPMC prefetch support for NAND Flash device"
+ depends on MTD_NAND && MTD_NAND_OMAP2
+ default y
+ help
+ The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
+ to improve the performance.
+
config MTD_NAND_TS7250
tristate "NAND Flash device on TS-7250 board"
depends on MACH_TS72XX
Index: mtd-2.6/drivers/mtd/nand/omap2.c
===================================================================
--- mtd-2.6.orig/drivers/mtd/nand/omap2.c
+++ mtd-2.6/drivers/mtd/nand/omap2.c
@@ -112,6 +112,16 @@
static const char *part_probes[] = { "cmdlinepart", NULL };
#endif
+#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
+static int use_prefetch = 1;
+
+/* "modprobe ... use_prefetch=0" etc */
+module_param(use_prefetch, bool, 0);
+MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
+#else
+const int use_prefetch;
+#endif
+
struct omap_nand_info {
struct nand_hw_control controller;
struct omap_nand_platform_data *pdata;
@@ -124,6 +134,7 @@ struct omap_nand_info {
unsigned long phys_base;
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
+ void __iomem *nand_pref_fifo_add;
};
/**
@@ -189,6 +200,40 @@ static void omap_hwcontrol(struct mtd_in
}
/**
+ * omap_read_buf8 - 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_buf8(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *nand = mtd->priv;
+ u_char *p = (u_char *)buf;
+
+ while (len--)
+ *p++ = __raw_readb(nand->IO_ADDR_R);
+}
+
+/**
+ * omap_write_buf8 - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u_char *p = (u_char *)buf;
+
+ while (len--) {
+ writeb(*p++, info->nand.IO_ADDR_W);
+ while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
+ GPMC_STATUS) & GPMC_BUF_FULL));
+ }
+}
+
+/**
* omap_read_buf16 - read data from NAND controller into buffer
* @mtd: MTD device structure
* @buf: buffer to store date
@@ -224,6 +269,94 @@ static void omap_write_buf16(struct mtd_
;
}
}
+
+/**
+ * omap_read_buf_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_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ uint32_t pfpw_status = 0, r_count = 0;
+ int ret = 0;
+ u32 *p = (u32 *)buf;
+
+ /* take care of subpage reads */
+ for (; len % 4 != 0; ) {
+ *buf++ = __raw_readb(info->nand.IO_ADDR_R);
+ len--;
+ }
+ p = (u32 *) buf;
+
+ /* 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 */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_read_buf16(mtd, buf, len);
+ else
+ omap_read_buf8(mtd, buf, len);
+ } else {
+ do {
+ pfpw_status = gpmc_prefetch_status();
+ r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
+ __raw_readsl(info->nand_pref_fifo_add, p, r_count);
+ p += r_count;
+ len -= r_count << 2;
+ } while (len);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+ }
+}
+
+/**
+ * omap_write_buf_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_pref(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ uint32_t pfpw_status = 0, w_count = 0;
+ int i = 0, ret = 0;
+ u16 *p = (u16 *) buf;
+
+ /* take care of subpage writes */
+ if (len % 2 != 0) {
+ writeb(*buf, info->nand.IO_ADDR_R);
+ p = (u16 *)(buf + 1);
+ len--;
+ }
+
+ /* 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 */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_write_buf16(mtd, buf, len);
+ else
+ omap_write_buf8(mtd, buf, len);
+ } else {
+ pfpw_status = gpmc_prefetch_status();
+ while (pfpw_status & 0x3FFF) {
+ w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+ for (i = 0; (i < w_count) && len; i++, len -= 2)
+ __raw_writew(*p++, info->nand_pref_fifo_add);
+ pfpw_status = gpmc_prefetch_status();
+ }
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+ }
+}
+
/**
* omap_verify_buf - Verify chip data against buffer
* @mtd: MTD device structure
@@ -658,17 +791,12 @@ static int __devinit omap_nand_probe(str
err = -ENOMEM;
goto out_release_mem_region;
}
+
info->nand.controller = &info->controller;
info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
info->nand.cmd_ctrl = omap_hwcontrol;
- /* REVISIT: only supports 16-bit NAND flash */
-
- info->nand.read_buf = omap_read_buf16;
- info->nand.write_buf = omap_write_buf16;
- info->nand.verify_buf = omap_verify_buf;
-
/*
* If RDY/BSY line is connected to OMAP then use the omap ready
* funcrtion and the generic nand_wait function which reads the status
@@ -689,6 +817,23 @@ static int __devinit omap_nand_probe(str
== 0x1000)
info->nand.options |= NAND_BUSWIDTH_16;
+ if (use_prefetch) {
+ /* copy the virtual address of nand base for fifo access */
+ info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
+
+ info->nand.read_buf = omap_read_buf_pref;
+ info->nand.write_buf = omap_write_buf_pref;
+ } else {
+ if (info->nand.options & NAND_BUSWIDTH_16) {
+ info->nand.read_buf = omap_read_buf16;
+ info->nand.write_buf = omap_write_buf16;
+ } else {
+ info->nand.read_buf = omap_read_buf8;
+ info->nand.write_buf = omap_write_buf8;
+ }
+ }
+ info->nand.verify_buf = omap_verify_buf;
+
#ifdef CONFIG_MTD_NAND_OMAP_HWECC
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
@@ -746,7 +891,7 @@ static int omap_nand_remove(struct platf
platform_set_drvdata(pdev, NULL);
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand.IO_ADDR_R);
+ iounmap(info->nand_pref_fifo_add);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
[not found] ` <48097.192.168.10.89.1247232736.squirrel@dbdmail.itg.ti.com>
@ 2009-07-13 10:56 ` vimal singh
2009-08-10 16:27 ` Tony Lindgren
0 siblings, 1 reply; 10+ messages in thread
From: vimal singh @ 2009-07-13 10:56 UTC (permalink / raw)
To: vimal singh
Cc: linux-mtd, Tony Lindgren, dwmw2, dedekind, david-b, linux-kernel,
linux-omap
Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep' as per
David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions also
for this.
-vimal
This patch adds prefetch support to access nand flash in mpu mode.
This patch also adds 8-bit nand support (omap_read/write_buf8).
Prefetch can be used for both 8- and 16-bit devices.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
---
arch/arm/mach-omap2/gpmc.c | 63 ++++++++++++
arch/arm/plat-omap/include/mach/gpmc.h | 4
drivers/mtd/nand/Kconfig | 8 +
drivers/mtd/nand/omap2.c | 161 +++++++++++++++++++++++++++++++--
4 files changed, 226 insertions(+), 10 deletions(-)
Index: mtd-2.6/arch/arm/mach-omap2/gpmc.c
===================================================================
--- mtd-2.6.orig/arch/arm/mach-omap2/gpmc.c
+++ mtd-2.6/arch/arm/mach-omap2/gpmc.c
@@ -57,6 +57,11 @@
#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
+
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -386,6 +391,63 @@ void gpmc_cs_free(int cs)
}
EXPORT_SYMBOL(gpmc_cs_free);
+/**
+ * gpmc_prefetch_enable - configures and starts prefetch transfer
+ * @cs: nand cs (chip select) number
+ * @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,
+ unsigned int u32_count, int is_write)
+{
+ uint32_t prefetch_config1;
+
+ if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+ /* Set the amount of bytes to be prefetched */
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
+
+ /* Set dma/mpu mode, the prefetch read / post write and
+ * enable the engine. Set which cs is has requested for.
+ */
+ prefetch_config1 = ((cs << CS_NUM_SHIFT) |
+ PREFETCH_FIFOTHRESHOLD |
+ ENABLE_PREFETCH |
+ (dma_mode << DMA_MPU_MODE) |
+ (0x1 & is_write));
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
+ } else {
+ return -EBUSY;
+ }
+ /* Start the prefetch engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_prefetch_enable);
+
+/**
+ * gpmc_prefetch_reset - disables and stops the prefetch engine
+ */
+void gpmc_prefetch_reset(void)
+{
+ /* Stop the PFPW engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
+
+ /* Reset/disable the PFPW engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+}
+EXPORT_SYMBOL(gpmc_prefetch_reset);
+
+/**
+ * gpmc_prefetch_status - reads prefetch status of engine
+ */
+int gpmc_prefetch_status(void)
+{
+ return gpmc_read_reg(GPMC_PREFETCH_STATUS);
+}
+EXPORT_SYMBOL(gpmc_prefetch_status);
+
static void __init gpmc_mem_init(void)
{
int cs;
@@ -452,6 +514,5 @@ void __init gpmc_init(void)
l &= 0x03 << 3;
l |= (0x02 << 3) | (1 << 0);
gpmc_write_reg(GPMC_SYSCONFIG, l);
-
gpmc_mem_init();
}
Index: mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
===================================================================
--- mtd-2.6.orig/arch/arm/plat-omap/include/mach/gpmc.h
+++ mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
@@ -103,6 +103,10 @@ extern int gpmc_cs_request(int cs, unsig
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,
+ unsigned int u32_count, int is_write);
+extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_status(void);
extern void __init gpmc_init(void);
#endif
Index: mtd-2.6/drivers/mtd/nand/Kconfig
===================================================================
--- mtd-2.6.orig/drivers/mtd/nand/Kconfig
+++ mtd-2.6/drivers/mtd/nand/Kconfig
@@ -80,6 +80,14 @@ config MTD_NAND_OMAP2
help
Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
+config MTD_NAND_OMAP_PREFETCH
+ bool "GPMC prefetch support for NAND Flash device"
+ depends on MTD_NAND && MTD_NAND_OMAP2
+ default y
+ help
+ The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
+ to improve the performance.
+
config MTD_NAND_TS7250
tristate "NAND Flash device on TS-7250 board"
depends on MACH_TS72XX
Index: mtd-2.6/drivers/mtd/nand/omap2.c
===================================================================
--- mtd-2.6.orig/drivers/mtd/nand/omap2.c
+++ mtd-2.6/drivers/mtd/nand/omap2.c
@@ -112,6 +112,16 @@
static const char *part_probes[] = { "cmdlinepart", NULL };
#endif
+#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
+static int use_prefetch = 1;
+
+/* "modprobe ... use_prefetch=0" etc */
+module_param(use_prefetch, bool, 0);
+MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
+#else
+const int use_prefetch;
+#endif
+
struct omap_nand_info {
struct nand_hw_control controller;
struct omap_nand_platform_data *pdata;
@@ -124,6 +134,7 @@ struct omap_nand_info {
unsigned long phys_base;
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
+ void __iomem *nand_pref_fifo_add;
};
/**
@@ -189,6 +200,38 @@ static void omap_hwcontrol(struct mtd_in
}
/**
+ * omap_read_buf8 - 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_buf8(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *nand = mtd->priv;
+
+ ioread8_rep(nand->IO_ADDR_R, buf, len);
+}
+
+/**
+ * omap_write_buf8 - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u_char *p = (u_char *)buf;
+
+ while (len--) {
+ iowrite8(*p++, info->nand.IO_ADDR_W);
+ while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
+ GPMC_STATUS) & GPMC_BUF_FULL));
+ }
+}
+
+/**
* omap_read_buf16 - read data from NAND controller into buffer
* @mtd: MTD device structure
* @buf: buffer to store date
@@ -198,7 +241,7 @@ static void omap_read_buf16(struct mtd_i
{
struct nand_chip *nand = mtd->priv;
- __raw_readsw(nand->IO_ADDR_R, buf, len / 2);
+ ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
}
/**
@@ -217,13 +260,101 @@ static void omap_write_buf16(struct mtd_
len >>= 1;
while (len--) {
- writew(*p++, info->nand.IO_ADDR_W);
+ iowrite16(*p++, info->nand.IO_ADDR_W);
while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
GPMC_STATUS) & GPMC_BUF_FULL))
;
}
}
+
+/**
+ * omap_read_buf_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_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ uint32_t pfpw_status = 0, r_count = 0;
+ int ret = 0;
+ u32 *p = (u32 *)buf;
+
+ /* take care of subpage reads */
+ for (; len % 4 != 0; ) {
+ *buf++ = __raw_readb(info->nand.IO_ADDR_R);
+ len--;
+ }
+ p = (u32 *) buf;
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_read_buf16(mtd, buf, len);
+ else
+ omap_read_buf8(mtd, buf, len);
+ } else {
+ do {
+ pfpw_status = gpmc_prefetch_status();
+ r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
+ ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ p += r_count;
+ len -= r_count << 2;
+ } while (len);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+ }
+}
+
+/**
+ * omap_write_buf_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_pref(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ uint32_t pfpw_status = 0, w_count = 0;
+ int i = 0, ret = 0;
+ u16 *p = (u16 *) buf;
+
+ /* take care of subpage writes */
+ if (len % 2 != 0) {
+ writeb(*buf, info->nand.IO_ADDR_R);
+ p = (u16 *)(buf + 1);
+ len--;
+ }
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_write_buf16(mtd, buf, len);
+ else
+ omap_write_buf8(mtd, buf, len);
+ } else {
+ pfpw_status = gpmc_prefetch_status();
+ while (pfpw_status & 0x3FFF) {
+ w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+ for (i = 0; (i < w_count) && len; i++, len -= 2)
+ iowrite16(*p++, info->nand_pref_fifo_add);
+ pfpw_status = gpmc_prefetch_status();
+ }
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+ }
+}
+
/**
* omap_verify_buf - Verify chip data against buffer
* @mtd: MTD device structure
@@ -658,17 +789,12 @@ static int __devinit omap_nand_probe(str
err = -ENOMEM;
goto out_release_mem_region;
}
+
info->nand.controller = &info->controller;
info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
info->nand.cmd_ctrl = omap_hwcontrol;
- /* REVISIT: only supports 16-bit NAND flash */
-
- info->nand.read_buf = omap_read_buf16;
- info->nand.write_buf = omap_write_buf16;
- info->nand.verify_buf = omap_verify_buf;
-
/*
* If RDY/BSY line is connected to OMAP then use the omap ready
* funcrtion and the generic nand_wait function which reads the status
@@ -689,6 +815,23 @@ static int __devinit omap_nand_probe(str
== 0x1000)
info->nand.options |= NAND_BUSWIDTH_16;
+ if (use_prefetch) {
+ /* copy the virtual address of nand base for fifo access */
+ info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
+
+ info->nand.read_buf = omap_read_buf_pref;
+ info->nand.write_buf = omap_write_buf_pref;
+ } else {
+ if (info->nand.options & NAND_BUSWIDTH_16) {
+ info->nand.read_buf = omap_read_buf16;
+ info->nand.write_buf = omap_write_buf16;
+ } else {
+ info->nand.read_buf = omap_read_buf8;
+ info->nand.write_buf = omap_write_buf8;
+ }
+ }
+ info->nand.verify_buf = omap_verify_buf;
+
#ifdef CONFIG_MTD_NAND_OMAP_HWECC
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
@@ -746,7 +889,7 @@ static int omap_nand_remove(struct platf
platform_set_drvdata(pdev, NULL);
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand.IO_ADDR_R);
+ iounmap(info->nand_pref_fifo_add);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
2009-07-13 10:56 ` [PATCH-v3 " vimal singh
@ 2009-08-10 16:27 ` Tony Lindgren
2009-08-11 5:45 ` vimal singh
0 siblings, 1 reply; 10+ messages in thread
From: Tony Lindgren @ 2009-08-10 16:27 UTC (permalink / raw)
To: vimal singh; +Cc: linux-mtd, dwmw2, dedekind, david-b, linux-kernel, linux-omap
* vimal singh <vimalsingh@ti.com> [090713 13:56]:
> Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep' as per
> David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions also
> for this.
>
> -vimal
>
> This patch adds prefetch support to access nand flash in mpu mode.
> This patch also adds 8-bit nand support (omap_read/write_buf8).
> Prefetch can be used for both 8- and 16-bit devices.
>
> Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Sorry for the delay. I've looked at the GPMC part, and that now looks OK
to me. So I'm OK for this to get integrated via the MTD list.
Acked-by: Tony Lindgren <tony@atomide.com>
> ---
>
> ---
> arch/arm/mach-omap2/gpmc.c | 63 ++++++++++++
> arch/arm/plat-omap/include/mach/gpmc.h | 4
> drivers/mtd/nand/Kconfig | 8 +
> drivers/mtd/nand/omap2.c | 161 +++++++++++++++++++++++++++++++--
> 4 files changed, 226 insertions(+), 10 deletions(-)
>
> Index: mtd-2.6/arch/arm/mach-omap2/gpmc.c
> ===================================================================
> --- mtd-2.6.orig/arch/arm/mach-omap2/gpmc.c
> +++ mtd-2.6/arch/arm/mach-omap2/gpmc.c
> @@ -57,6 +57,11 @@
> #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
> +
> static struct resource gpmc_mem_root;
> static struct resource gpmc_cs_mem[GPMC_CS_NUM];
> static DEFINE_SPINLOCK(gpmc_mem_lock);
> @@ -386,6 +391,63 @@ void gpmc_cs_free(int cs)
> }
> EXPORT_SYMBOL(gpmc_cs_free);
>
> +/**
> + * gpmc_prefetch_enable - configures and starts prefetch transfer
> + * @cs: nand cs (chip select) number
> + * @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,
> + unsigned int u32_count, int is_write)
> +{
> + uint32_t prefetch_config1;
> +
> + if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
> + /* Set the amount of bytes to be prefetched */
> + gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> +
> + /* Set dma/mpu mode, the prefetch read / post write and
> + * enable the engine. Set which cs is has requested for.
> + */
> + prefetch_config1 = ((cs << CS_NUM_SHIFT) |
> + PREFETCH_FIFOTHRESHOLD |
> + ENABLE_PREFETCH |
> + (dma_mode << DMA_MPU_MODE) |
> + (0x1 & is_write));
> + gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
> + } else {
> + return -EBUSY;
> + }
> + /* Start the prefetch engine */
> + gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_enable);
> +
> +/**
> + * gpmc_prefetch_reset - disables and stops the prefetch engine
> + */
> +void gpmc_prefetch_reset(void)
> +{
> + /* Stop the PFPW engine */
> + gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> +
> + /* Reset/disable the PFPW engine */
> + gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_reset);
> +
> +/**
> + * gpmc_prefetch_status - reads prefetch status of engine
> + */
> +int gpmc_prefetch_status(void)
> +{
> + return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_status);
> +
> static void __init gpmc_mem_init(void)
> {
> int cs;
> @@ -452,6 +514,5 @@ void __init gpmc_init(void)
> l &= 0x03 << 3;
> l |= (0x02 << 3) | (1 << 0);
> gpmc_write_reg(GPMC_SYSCONFIG, l);
> -
> gpmc_mem_init();
> }
> Index: mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
> ===================================================================
> --- mtd-2.6.orig/arch/arm/plat-omap/include/mach/gpmc.h
> +++ mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
> @@ -103,6 +103,10 @@ extern int gpmc_cs_request(int cs, unsig
> 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,
> + unsigned int u32_count, int is_write);
> +extern void gpmc_prefetch_reset(void);
> +extern int gpmc_prefetch_status(void);
> extern void __init gpmc_init(void);
>
> #endif
> Index: mtd-2.6/drivers/mtd/nand/Kconfig
> ===================================================================
> --- mtd-2.6.orig/drivers/mtd/nand/Kconfig
> +++ mtd-2.6/drivers/mtd/nand/Kconfig
> @@ -80,6 +80,14 @@ config MTD_NAND_OMAP2
> help
> Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
>
> +config MTD_NAND_OMAP_PREFETCH
> + bool "GPMC prefetch support for NAND Flash device"
> + depends on MTD_NAND && MTD_NAND_OMAP2
> + default y
> + help
> + The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
> + to improve the performance.
> +
> config MTD_NAND_TS7250
> tristate "NAND Flash device on TS-7250 board"
> depends on MACH_TS72XX
> Index: mtd-2.6/drivers/mtd/nand/omap2.c
> ===================================================================
> --- mtd-2.6.orig/drivers/mtd/nand/omap2.c
> +++ mtd-2.6/drivers/mtd/nand/omap2.c
> @@ -112,6 +112,16 @@
> static const char *part_probes[] = { "cmdlinepart", NULL };
> #endif
>
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
> +static int use_prefetch = 1;
> +
> +/* "modprobe ... use_prefetch=0" etc */
> +module_param(use_prefetch, bool, 0);
> +MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
> +#else
> +const int use_prefetch;
> +#endif
> +
> struct omap_nand_info {
> struct nand_hw_control controller;
> struct omap_nand_platform_data *pdata;
> @@ -124,6 +134,7 @@ struct omap_nand_info {
> unsigned long phys_base;
> void __iomem *gpmc_cs_baseaddr;
> void __iomem *gpmc_baseaddr;
> + void __iomem *nand_pref_fifo_add;
> };
>
> /**
> @@ -189,6 +200,38 @@ static void omap_hwcontrol(struct mtd_in
> }
>
> /**
> + * omap_read_buf8 - 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_buf8(struct mtd_info *mtd, u_char *buf, int len)
> +{
> + struct nand_chip *nand = mtd->priv;
> +
> + ioread8_rep(nand->IO_ADDR_R, buf, len);
> +}
> +
> +/**
> + * omap_write_buf8 - write buffer to NAND controller
> + * @mtd: MTD device structure
> + * @buf: data buffer
> + * @len: number of bytes to write
> + */
> +static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
> +{
> + struct omap_nand_info *info = container_of(mtd,
> + struct omap_nand_info, mtd);
> + u_char *p = (u_char *)buf;
> +
> + while (len--) {
> + iowrite8(*p++, info->nand.IO_ADDR_W);
> + while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> + GPMC_STATUS) & GPMC_BUF_FULL));
> + }
> +}
> +
> +/**
> * omap_read_buf16 - read data from NAND controller into buffer
> * @mtd: MTD device structure
> * @buf: buffer to store date
> @@ -198,7 +241,7 @@ static void omap_read_buf16(struct mtd_i
> {
> struct nand_chip *nand = mtd->priv;
>
> - __raw_readsw(nand->IO_ADDR_R, buf, len / 2);
> + ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
> }
>
> /**
> @@ -217,13 +260,101 @@ static void omap_write_buf16(struct mtd_
> len >>= 1;
>
> while (len--) {
> - writew(*p++, info->nand.IO_ADDR_W);
> + iowrite16(*p++, info->nand.IO_ADDR_W);
>
> while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> GPMC_STATUS) & GPMC_BUF_FULL))
> ;
> }
> }
> +
> +/**
> + * omap_read_buf_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_pref(struct mtd_info *mtd, u_char *buf, int len)
> +{
> + struct omap_nand_info *info = container_of(mtd,
> + struct omap_nand_info, mtd);
> + uint32_t pfpw_status = 0, r_count = 0;
> + int ret = 0;
> + u32 *p = (u32 *)buf;
> +
> + /* take care of subpage reads */
> + for (; len % 4 != 0; ) {
> + *buf++ = __raw_readb(info->nand.IO_ADDR_R);
> + len--;
> + }
> + p = (u32 *) buf;
> +
> + /* configure and start prefetch transfer */
> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
> + if (ret) {
> + /* PFPW engine is busy, use cpu copy method */
> + if (info->nand.options & NAND_BUSWIDTH_16)
> + omap_read_buf16(mtd, buf, len);
> + else
> + omap_read_buf8(mtd, buf, len);
> + } else {
> + do {
> + pfpw_status = gpmc_prefetch_status();
> + r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
> + ioread32_rep(info->nand_pref_fifo_add, p, r_count);
> + p += r_count;
> + len -= r_count << 2;
> + } while (len);
> +
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset();
> + }
> +}
> +
> +/**
> + * omap_write_buf_pref - write buffer to NAND controller
> + * @mtd: MTD device structure
> + * @buf: data buffer
> + * @len: number of bytes to write
> + */
> +static void omap_write_buf_pref(struct mtd_info *mtd,
> + const u_char *buf, int len)
> +{
> + struct omap_nand_info *info = container_of(mtd,
> + struct omap_nand_info, mtd);
> + uint32_t pfpw_status = 0, w_count = 0;
> + int i = 0, ret = 0;
> + u16 *p = (u16 *) buf;
> +
> + /* take care of subpage writes */
> + if (len % 2 != 0) {
> + writeb(*buf, info->nand.IO_ADDR_R);
> + p = (u16 *)(buf + 1);
> + len--;
> + }
> +
> + /* configure and start prefetch transfer */
> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
> + if (ret) {
> + /* PFPW engine is busy, use cpu copy method */
> + if (info->nand.options & NAND_BUSWIDTH_16)
> + omap_write_buf16(mtd, buf, len);
> + else
> + omap_write_buf8(mtd, buf, len);
> + } else {
> + pfpw_status = gpmc_prefetch_status();
> + while (pfpw_status & 0x3FFF) {
> + w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
> + for (i = 0; (i < w_count) && len; i++, len -= 2)
> + iowrite16(*p++, info->nand_pref_fifo_add);
> + pfpw_status = gpmc_prefetch_status();
> + }
> +
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset();
> + }
> +}
> +
> /**
> * omap_verify_buf - Verify chip data against buffer
> * @mtd: MTD device structure
> @@ -658,17 +789,12 @@ static int __devinit omap_nand_probe(str
> err = -ENOMEM;
> goto out_release_mem_region;
> }
> +
> info->nand.controller = &info->controller;
>
> info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
> info->nand.cmd_ctrl = omap_hwcontrol;
>
> - /* REVISIT: only supports 16-bit NAND flash */
> -
> - info->nand.read_buf = omap_read_buf16;
> - info->nand.write_buf = omap_write_buf16;
> - info->nand.verify_buf = omap_verify_buf;
> -
> /*
> * If RDY/BSY line is connected to OMAP then use the omap ready
> * funcrtion and the generic nand_wait function which reads the status
> @@ -689,6 +815,23 @@ static int __devinit omap_nand_probe(str
> == 0x1000)
> info->nand.options |= NAND_BUSWIDTH_16;
>
> + if (use_prefetch) {
> + /* copy the virtual address of nand base for fifo access */
> + info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
> +
> + info->nand.read_buf = omap_read_buf_pref;
> + info->nand.write_buf = omap_write_buf_pref;
> + } else {
> + if (info->nand.options & NAND_BUSWIDTH_16) {
> + info->nand.read_buf = omap_read_buf16;
> + info->nand.write_buf = omap_write_buf16;
> + } else {
> + info->nand.read_buf = omap_read_buf8;
> + info->nand.write_buf = omap_write_buf8;
> + }
> + }
> + info->nand.verify_buf = omap_verify_buf;
> +
> #ifdef CONFIG_MTD_NAND_OMAP_HWECC
> info->nand.ecc.bytes = 3;
> info->nand.ecc.size = 512;
> @@ -746,7 +889,7 @@ static int omap_nand_remove(struct platf
> platform_set_drvdata(pdev, NULL);
> /* Release NAND device, its internal structures and partitions */
> nand_release(&info->mtd);
> - iounmap(info->nand.IO_ADDR_R);
> + iounmap(info->nand_pref_fifo_add);
> kfree(&info->mtd);
> return 0;
> }
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
2009-08-10 16:27 ` Tony Lindgren
@ 2009-08-11 5:45 ` vimal singh
2009-08-11 6:21 ` Artem Bityutskiy
0 siblings, 1 reply; 10+ messages in thread
From: vimal singh @ 2009-08-11 5:45 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap, dedekind, linux-kernel, david-b, linux-mtd,
vimal singh, dwmw2
On Mon, Aug 10, 2009 at 9:57 PM, Tony Lindgren<tony@atomide.com> wrote:
> * vimal singh <vimalsingh@ti.com> [090713 13:56]:
>> Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep' as per
>> David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions also
>> for this.
>>
>> -vimal
>>
>> This patch adds prefetch support to access nand flash in mpu mode.
>> This patch also adds 8-bit nand support (omap_read/write_buf8).
>> Prefetch can be used for both 8- and 16-bit devices.
>>
>> Signed-off-by: Vimal Singh <vimalsingh@ti.com>
>
> Sorry for the delay. I've looked at the GPMC part, and that now looks OK
> to me. So I'm OK for this to get integrated via the MTD list.
>
> Acked-by: Tony Lindgren <tony@atomide.com>
>
Can you give your ack to below patch too?
http://lists.infradead.org/pipermail/linux-mtd/2009-July/026373.html
>
>> ---
>>
>> ---
>> arch/arm/mach-omap2/gpmc.c | 63 ++++++++++++
>> arch/arm/plat-omap/include/mach/gpmc.h | 4
>> drivers/mtd/nand/Kconfig | 8 +
>> drivers/mtd/nand/omap2.c | 161 +++++++++++++++++++++++++++++++--
>> 4 files changed, 226 insertions(+), 10 deletions(-)
>>
>> Index: mtd-2.6/arch/arm/mach-omap2/gpmc.c
>> ===================================================================
>> --- mtd-2.6.orig/arch/arm/mach-omap2/gpmc.c
>> +++ mtd-2.6/arch/arm/mach-omap2/gpmc.c
>> @@ -57,6 +57,11 @@
>> #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
>> +
>> static struct resource gpmc_mem_root;
>> static struct resource gpmc_cs_mem[GPMC_CS_NUM];
>> static DEFINE_SPINLOCK(gpmc_mem_lock);
>> @@ -386,6 +391,63 @@ void gpmc_cs_free(int cs)
>> }
>> EXPORT_SYMBOL(gpmc_cs_free);
>>
>> +/**
>> + * gpmc_prefetch_enable - configures and starts prefetch transfer
>> + * @cs: nand cs (chip select) number
>> + * @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,
>> + unsigned int u32_count, int is_write)
>> +{
>> + uint32_t prefetch_config1;
>> +
>> + if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
>> + /* Set the amount of bytes to be prefetched */
>> + gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
>> +
>> + /* Set dma/mpu mode, the prefetch read / post write and
>> + * enable the engine. Set which cs is has requested for.
>> + */
>> + prefetch_config1 = ((cs << CS_NUM_SHIFT) |
>> + PREFETCH_FIFOTHRESHOLD |
>> + ENABLE_PREFETCH |
>> + (dma_mode << DMA_MPU_MODE) |
>> + (0x1 & is_write));
>> + gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
>> + } else {
>> + return -EBUSY;
>> + }
>> + /* Start the prefetch engine */
>> + gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(gpmc_prefetch_enable);
>> +
>> +/**
>> + * gpmc_prefetch_reset - disables and stops the prefetch engine
>> + */
>> +void gpmc_prefetch_reset(void)
>> +{
>> + /* Stop the PFPW engine */
>> + gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
>> +
>> + /* Reset/disable the PFPW engine */
>> + gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
>> +}
>> +EXPORT_SYMBOL(gpmc_prefetch_reset);
>> +
>> +/**
>> + * gpmc_prefetch_status - reads prefetch status of engine
>> + */
>> +int gpmc_prefetch_status(void)
>> +{
>> + return gpmc_read_reg(GPMC_PREFETCH_STATUS);
>> +}
>> +EXPORT_SYMBOL(gpmc_prefetch_status);
>> +
>> static void __init gpmc_mem_init(void)
>> {
>> int cs;
>> @@ -452,6 +514,5 @@ void __init gpmc_init(void)
>> l &= 0x03 << 3;
>> l |= (0x02 << 3) | (1 << 0);
>> gpmc_write_reg(GPMC_SYSCONFIG, l);
>> -
>> gpmc_mem_init();
>> }
>> Index: mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
>> ===================================================================
>> --- mtd-2.6.orig/arch/arm/plat-omap/include/mach/gpmc.h
>> +++ mtd-2.6/arch/arm/plat-omap/include/mach/gpmc.h
>> @@ -103,6 +103,10 @@ extern int gpmc_cs_request(int cs, unsig
>> 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,
>> + unsigned int u32_count, int is_write);
>> +extern void gpmc_prefetch_reset(void);
>> +extern int gpmc_prefetch_status(void);
>> extern void __init gpmc_init(void);
>>
>> #endif
>> Index: mtd-2.6/drivers/mtd/nand/Kconfig
>> ===================================================================
>> --- mtd-2.6.orig/drivers/mtd/nand/Kconfig
>> +++ mtd-2.6/drivers/mtd/nand/Kconfig
>> @@ -80,6 +80,14 @@ config MTD_NAND_OMAP2
>> help
>> Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
>>
>> +config MTD_NAND_OMAP_PREFETCH
>> + bool "GPMC prefetch support for NAND Flash device"
>> + depends on MTD_NAND && MTD_NAND_OMAP2
>> + default y
>> + help
>> + The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
>> + to improve the performance.
>> +
>> config MTD_NAND_TS7250
>> tristate "NAND Flash device on TS-7250 board"
>> depends on MACH_TS72XX
>> Index: mtd-2.6/drivers/mtd/nand/omap2.c
>> ===================================================================
>> --- mtd-2.6.orig/drivers/mtd/nand/omap2.c
>> +++ mtd-2.6/drivers/mtd/nand/omap2.c
>> @@ -112,6 +112,16 @@
>> static const char *part_probes[] = { "cmdlinepart", NULL };
>> #endif
>>
>> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
>> +static int use_prefetch = 1;
>> +
>> +/* "modprobe ... use_prefetch=0" etc */
>> +module_param(use_prefetch, bool, 0);
>> +MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
>> +#else
>> +const int use_prefetch;
>> +#endif
>> +
>> struct omap_nand_info {
>> struct nand_hw_control controller;
>> struct omap_nand_platform_data *pdata;
>> @@ -124,6 +134,7 @@ struct omap_nand_info {
>> unsigned long phys_base;
>> void __iomem *gpmc_cs_baseaddr;
>> void __iomem *gpmc_baseaddr;
>> + void __iomem *nand_pref_fifo_add;
>> };
>>
>> /**
>> @@ -189,6 +200,38 @@ static void omap_hwcontrol(struct mtd_in
>> }
>>
>> /**
>> + * omap_read_buf8 - 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_buf8(struct mtd_info *mtd, u_char *buf, int len)
>> +{
>> + struct nand_chip *nand = mtd->priv;
>> +
>> + ioread8_rep(nand->IO_ADDR_R, buf, len);
>> +}
>> +
>> +/**
>> + * omap_write_buf8 - write buffer to NAND controller
>> + * @mtd: MTD device structure
>> + * @buf: data buffer
>> + * @len: number of bytes to write
>> + */
>> +static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
>> +{
>> + struct omap_nand_info *info = container_of(mtd,
>> + struct omap_nand_info, mtd);
>> + u_char *p = (u_char *)buf;
>> +
>> + while (len--) {
>> + iowrite8(*p++, info->nand.IO_ADDR_W);
>> + while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
>> + GPMC_STATUS) & GPMC_BUF_FULL));
>> + }
>> +}
>> +
>> +/**
>> * omap_read_buf16 - read data from NAND controller into buffer
>> * @mtd: MTD device structure
>> * @buf: buffer to store date
>> @@ -198,7 +241,7 @@ static void omap_read_buf16(struct mtd_i
>> {
>> struct nand_chip *nand = mtd->priv;
>>
>> - __raw_readsw(nand->IO_ADDR_R, buf, len / 2);
>> + ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
>> }
>>
>> /**
>> @@ -217,13 +260,101 @@ static void omap_write_buf16(struct mtd_
>> len >>= 1;
>>
>> while (len--) {
>> - writew(*p++, info->nand.IO_ADDR_W);
>> + iowrite16(*p++, info->nand.IO_ADDR_W);
>>
>> while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
>> GPMC_STATUS) & GPMC_BUF_FULL))
>> ;
>> }
>> }
>> +
>> +/**
>> + * omap_read_buf_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_pref(struct mtd_info *mtd, u_char *buf, int len)
>> +{
>> + struct omap_nand_info *info = container_of(mtd,
>> + struct omap_nand_info, mtd);
>> + uint32_t pfpw_status = 0, r_count = 0;
>> + int ret = 0;
>> + u32 *p = (u32 *)buf;
>> +
>> + /* take care of subpage reads */
>> + for (; len % 4 != 0; ) {
>> + *buf++ = __raw_readb(info->nand.IO_ADDR_R);
>> + len--;
>> + }
>> + p = (u32 *) buf;
>> +
>> + /* configure and start prefetch transfer */
>> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
>> + if (ret) {
>> + /* PFPW engine is busy, use cpu copy method */
>> + if (info->nand.options & NAND_BUSWIDTH_16)
>> + omap_read_buf16(mtd, buf, len);
>> + else
>> + omap_read_buf8(mtd, buf, len);
>> + } else {
>> + do {
>> + pfpw_status = gpmc_prefetch_status();
>> + r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
>> + ioread32_rep(info->nand_pref_fifo_add, p, r_count);
>> + p += r_count;
>> + len -= r_count << 2;
>> + } while (len);
>> +
>> + /* disable and stop the PFPW engine */
>> + gpmc_prefetch_reset();
>> + }
>> +}
>> +
>> +/**
>> + * omap_write_buf_pref - write buffer to NAND controller
>> + * @mtd: MTD device structure
>> + * @buf: data buffer
>> + * @len: number of bytes to write
>> + */
>> +static void omap_write_buf_pref(struct mtd_info *mtd,
>> + const u_char *buf, int len)
>> +{
>> + struct omap_nand_info *info = container_of(mtd,
>> + struct omap_nand_info, mtd);
>> + uint32_t pfpw_status = 0, w_count = 0;
>> + int i = 0, ret = 0;
>> + u16 *p = (u16 *) buf;
>> +
>> + /* take care of subpage writes */
>> + if (len % 2 != 0) {
>> + writeb(*buf, info->nand.IO_ADDR_R);
>> + p = (u16 *)(buf + 1);
>> + len--;
>> + }
>> +
>> + /* configure and start prefetch transfer */
>> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
>> + if (ret) {
>> + /* PFPW engine is busy, use cpu copy method */
>> + if (info->nand.options & NAND_BUSWIDTH_16)
>> + omap_write_buf16(mtd, buf, len);
>> + else
>> + omap_write_buf8(mtd, buf, len);
>> + } else {
>> + pfpw_status = gpmc_prefetch_status();
>> + while (pfpw_status & 0x3FFF) {
>> + w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
>> + for (i = 0; (i < w_count) && len; i++, len -= 2)
>> + iowrite16(*p++, info->nand_pref_fifo_add);
>> + pfpw_status = gpmc_prefetch_status();
>> + }
>> +
>> + /* disable and stop the PFPW engine */
>> + gpmc_prefetch_reset();
>> + }
>> +}
>> +
>> /**
>> * omap_verify_buf - Verify chip data against buffer
>> * @mtd: MTD device structure
>> @@ -658,17 +789,12 @@ static int __devinit omap_nand_probe(str
>> err = -ENOMEM;
>> goto out_release_mem_region;
>> }
>> +
>> info->nand.controller = &info->controller;
>>
>> info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
>> info->nand.cmd_ctrl = omap_hwcontrol;
>>
>> - /* REVISIT: only supports 16-bit NAND flash */
>> -
>> - info->nand.read_buf = omap_read_buf16;
>> - info->nand.write_buf = omap_write_buf16;
>> - info->nand.verify_buf = omap_verify_buf;
>> -
>> /*
>> * If RDY/BSY line is connected to OMAP then use the omap ready
>> * funcrtion and the generic nand_wait function which reads the status
>> @@ -689,6 +815,23 @@ static int __devinit omap_nand_probe(str
>> == 0x1000)
>> info->nand.options |= NAND_BUSWIDTH_16;
>>
>> + if (use_prefetch) {
>> + /* copy the virtual address of nand base for fifo access */
>> + info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
>> +
>> + info->nand.read_buf = omap_read_buf_pref;
>> + info->nand.write_buf = omap_write_buf_pref;
>> + } else {
>> + if (info->nand.options & NAND_BUSWIDTH_16) {
>> + info->nand.read_buf = omap_read_buf16;
>> + info->nand.write_buf = omap_write_buf16;
>> + } else {
>> + info->nand.read_buf = omap_read_buf8;
>> + info->nand.write_buf = omap_write_buf8;
>> + }
>> + }
>> + info->nand.verify_buf = omap_verify_buf;
>> +
>> #ifdef CONFIG_MTD_NAND_OMAP_HWECC
>> info->nand.ecc.bytes = 3;
>> info->nand.ecc.size = 512;
>> @@ -746,7 +889,7 @@ static int omap_nand_remove(struct platf
>> platform_set_drvdata(pdev, NULL);
>> /* Release NAND device, its internal structures and partitions */
>> nand_release(&info->mtd);
>> - iounmap(info->nand.IO_ADDR_R);
>> + iounmap(info->nand_pref_fifo_add);
>> kfree(&info->mtd);
>> return 0;
>> }
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
---
Regards,
\/ | |\/| /-\ |_
____ __o
------ -\<,
----- ( )/ ( )
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
2009-08-11 5:45 ` vimal singh
@ 2009-08-11 6:21 ` Artem Bityutskiy
2009-08-11 6:29 ` vimal singh
0 siblings, 1 reply; 10+ messages in thread
From: Artem Bityutskiy @ 2009-08-11 6:21 UTC (permalink / raw)
To: vimal singh
Cc: vimal singh, Tony Lindgren, linux-kernel, david-b, dedekind,
linux-mtd, linux-omap, dwmw2
On 08/11/2009 08:45 AM, vimal singh wrote:
> On Mon, Aug 10, 2009 at 9:57 PM, Tony Lindgren<tony@atomide.com> wrote:
>> * vimal singh<vimalsingh@ti.com> [090713 13:56]:
>>> Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep' as per
>>> David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions also
>>> for this.
>>>
>>> -vimal
>>>
>>> This patch adds prefetch support to access nand flash in mpu mode.
>>> This patch also adds 8-bit nand support (omap_read/write_buf8).
>>> Prefetch can be used for both 8- and 16-bit devices.
>>>
>>> Signed-off-by: Vimal Singh<vimalsingh@ti.com>
>> Sorry for the delay. I've looked at the GPMC part, and that now looks OK
>> to me. So I'm OK for this to get integrated via the MTD list.
>>
>> Acked-by: Tony Lindgren<tony@atomide.com>
>>
>
> Can you give your ack to below patch too?
>
> http://lists.infradead.org/pipermail/linux-mtd/2009-July/026373.html
I've picked up both of your patches, please, check:
http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/33f48f597315842f39427ee4261cbf82a9afeaf3
http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/b67d52c91b26e97f981f2c292619d31667d5b272
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
2009-08-11 6:21 ` Artem Bityutskiy
@ 2009-08-11 6:29 ` vimal singh
2009-09-05 10:06 ` vimal singh
0 siblings, 1 reply; 10+ messages in thread
From: vimal singh @ 2009-08-11 6:29 UTC (permalink / raw)
To: Artem Bityutskiy
Cc: vimal singh, Tony Lindgren, linux-kernel, david-b, dedekind,
linux-mtd, linux-omap, dwmw2
On Tue, Aug 11, 2009 at 11:51 AM, Artem Bityutskiy<dedekind1@gmail.com> wrote:
> On 08/11/2009 08:45 AM, vimal singh wrote:
>>
>> On Mon, Aug 10, 2009 at 9:57 PM, Tony Lindgren<tony@atomide.com> wrote:
>>>
>>> * vimal singh<vimalsingh@ti.com> [090713 13:56]:
>>>>
>>>> Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep'
>>>> as per
>>>> David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions
>>>> also
>>>> for this.
>>>>
>>>> -vimal
>>>>
>>>> This patch adds prefetch support to access nand flash in mpu mode.
>>>> This patch also adds 8-bit nand support (omap_read/write_buf8).
>>>> Prefetch can be used for both 8- and 16-bit devices.
>>>>
>>>> Signed-off-by: Vimal Singh<vimalsingh@ti.com>
>>>
>>> Sorry for the delay. I've looked at the GPMC part, and that now looks OK
>>> to me. So I'm OK for this to get integrated via the MTD list.
>>>
>>> Acked-by: Tony Lindgren<tony@atomide.com>
>>>
>>
>> Can you give your ack to below patch too?
>>
>> http://lists.infradead.org/pipermail/linux-mtd/2009-July/026373.html
>
> I've picked up both of your patches, please, check:
> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/33f48f597315842f39427ee4261cbf82a9afeaf3
> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/b67d52c91b26e97f981f2c292619d31667d5b272
>
Thanks Artem.
> --
> Best Regards,
> Artem Bityutskiy (Артём Битюцкий)
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH-v3 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode.
2009-08-11 6:29 ` vimal singh
@ 2009-09-05 10:06 ` vimal singh
2009-09-05 17:02 ` FYI - Frankencamera is open source, runs on Linux Pandita, Vikram
0 siblings, 1 reply; 10+ messages in thread
From: vimal singh @ 2009-09-05 10:06 UTC (permalink / raw)
To: Artem Bityutskiy
Cc: Tony Lindgren, linux-omap, dedekind, linux-kernel, david-b,
linux-mtd, vimal singh, dwmw2
Hi David,
On Tue, Aug 11, 2009 at 11:59 AM, vimal singh<vimal.newwork@gmail.com> wrote:
> On Tue, Aug 11, 2009 at 11:51 AM, Artem Bityutskiy<dedekind1@gmail.com> wrote:
>> On 08/11/2009 08:45 AM, vimal singh wrote:
>>>
>>> On Mon, Aug 10, 2009 at 9:57 PM, Tony Lindgren<tony@atomide.com> wrote:
>>>>
>>>> * vimal singh<vimalsingh@ti.com> [090713 13:56]:
>>>>>
>>>>> Patch updated for ' ioreadX / iowriteX and ioreadX_rep / iowriteX_rep'
>>>>> as per
>>>>> David Brownell's comment. I updated 'omap_(read/write)_buf16' fucntions
>>>>> also
>>>>> for this.
>>>>>
>>>>> -vimal
>>>>>
>>>>> This patch adds prefetch support to access nand flash in mpu mode.
>>>>> This patch also adds 8-bit nand support (omap_read/write_buf8).
>>>>> Prefetch can be used for both 8- and 16-bit devices.
>>>>>
>>>>> Signed-off-by: Vimal Singh<vimalsingh@ti.com>
>>>>
>>>> Sorry for the delay. I've looked at the GPMC part, and that now looks OK
>>>> to me. So I'm OK for this to get integrated via the MTD list.
>>>>
>>>> Acked-by: Tony Lindgren<tony@atomide.com>
>>>>
>>>
>>> Can you give your ack to below patch too?
>>>
>>> http://lists.infradead.org/pipermail/linux-mtd/2009-July/026373.html
>>
>> I've picked up both of your patches, please, check:
>> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/33f48f597315842f39427ee4261cbf82a9afeaf3
>> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/b67d52c91b26e97f981f2c292619d31667d5b272
>>
>
Is there any chance for these patches to get merged in this merge
window? These have been waiting for long time.
-Vimal
> Thanks Artem.
>
>> --
>> Best Regards,
>> Artem Bityutskiy (Артём Битюцкий)
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* FYI - Frankencamera is open source, runs on Linux
2009-09-05 10:06 ` vimal singh
@ 2009-09-05 17:02 ` Pandita, Vikram
2009-09-05 17:46 ` Koen Kooi
0 siblings, 1 reply; 10+ messages in thread
From: Pandita, Vikram @ 2009-09-05 17:02 UTC (permalink / raw)
To: linux-omap@vger.kernel.org
Have you seen this post on N95 camera using linux by Stanford Team -
http://news.cnet.com/8301-17938_105-10345557-1.html
Is this running on OMAP?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FYI - Frankencamera is open source, runs on Linux
2009-09-05 17:02 ` FYI - Frankencamera is open source, runs on Linux Pandita, Vikram
@ 2009-09-05 17:46 ` Koen Kooi
2009-09-06 7:51 ` Eino-Ville Talvala
0 siblings, 1 reply; 10+ messages in thread
From: Koen Kooi @ 2009-09-05 17:46 UTC (permalink / raw)
To: Linux OMAP Users
Op 5 sep 2009, om 19:02 heeft Pandita, Vikram het volgende geschreven:
>
> Have you seen this post on N95 camera using linux by Stanford Team -
> http://news.cnet.com/8301-17938_105-10345557-1.html
>
> Is this running on OMAP?--
The board in the youtube video looks a lot like the omap3evm, so I
guess it's safe to say it's omap3 based.
regards,
Koen
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FYI - Frankencamera is open source, runs on Linux
2009-09-05 17:46 ` Koen Kooi
@ 2009-09-06 7:51 ` Eino-Ville Talvala
0 siblings, 0 replies; 10+ messages in thread
From: Eino-Ville Talvala @ 2009-09-06 7:51 UTC (permalink / raw)
To: linux-omap
>> Have you seen this post on N95 camera using linux by Stanford Team -
>> http://news.cnet.com/8301-17938_105-10345557-1.html
>>
>> Is this running on OMAP?--
>
>
> The board in the youtube video looks a lot like the omap3evm, so I
> guess it's safe to say it's omap3 based.
>
> regards,
>
> Koen
I'm one of the graduate students at Stanford working on this project.
Yes, we're using an OMAP3 EVM (needed the camera interface pins)
connected to a small custom daughtercard that interfaces to an Elphel
10338 camera tile, with an Aptina MT9P031 on it. Plus a bunch of other
off-the-shelf hardware, but the OMAP3 is at the heart of it.
Eino-Ville (Eddy) Talvala
Graduate Research Assistant
Stanford University
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-09-06 7:58 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <61339.192.168.10.89.1247226725.squirrel@dbdmail.itg.ti.com>
2009-07-10 13:32 ` [PATCH-v2 1:2] [MTD][NAND]omap: Adding support for nand prefetch-read and post-write, in MPU mode vimal singh
[not found] ` <48097.192.168.10.89.1247232736.squirrel@dbdmail.itg.ti.com>
2009-07-13 10:56 ` [PATCH-v3 " vimal singh
2009-08-10 16:27 ` Tony Lindgren
2009-08-11 5:45 ` vimal singh
2009-08-11 6:21 ` Artem Bityutskiy
2009-08-11 6:29 ` vimal singh
2009-09-05 10:06 ` vimal singh
2009-09-05 17:02 ` FYI - Frankencamera is open source, runs on Linux Pandita, Vikram
2009-09-05 17:46 ` Koen Kooi
2009-09-06 7:51 ` Eino-Ville Talvala
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox