[PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput

2010-04-16 Thread Sukumar Ghorai
  Configure the FIFO THREASHOLD value to 50% (32 bytes) to keep busy both
  filling and to drain out of FIFO at reading and writing.

Signed-off-by: Sukumar Ghorai s-gho...@ti.com
Signed-off-by: Vimal Singh vimalsi...@ti.com
---
 arch/arm/mach-omap2/gpmc.c |9 ++---
 arch/arm/plat-omap/include/plat/gpmc.h |7 +--
 drivers/mtd/nand/omap2.c   |   25 +
 3 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9c77af0..1380886 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -391,12 +391,15 @@ EXPORT_SYMBOL(gpmc_cs_free);
  * @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)
 {
uint32_t prefetch_config1;
 
-   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);
 
@@ -404,7 +407,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
 * enable the engine. Set which cs is has requested for.
 */
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 347d212..a36a046 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -55,10 +55,13 @@
 #define GPMC_CHUNK_SHIFT24  /* 16 MB */
 #define GPMC_SECTION_SHIFT  28  /* 128 MB */
 
-#define PREFETCH_FIFOTHRESHOLD  (0x40  8)
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val)(val  8)
 #define CS_NUM_SHIFT24
 #define ENABLE_PREFETCH (0x1  7)
 #define DMA_MPU_MODE2
+#define PREFETCH_FIFOTHRESHOLD_READ32 /* threashold size for read */
+#define PREFETCH_FIFOTHRESHOLD_WRITE   32 /* threashold size for write */
 
 #define GPMC_CONFIG1_WRAPBURST_SUPP (1  31)
 #define GPMC_CONFIG1_READMULTIPLE_SUPP  (1  30)
@@ -136,7 +139,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 void gpmc_prefetch_reset(void);
 extern int gpmc_prefetch_status(void);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index de9b058..61c0c01
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -310,7 +310,7 @@ 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, 0x40, 0x0, len, 0x0);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info-nand.options  NAND_BUSWIDTH_16)
@@ -354,7 +354,7 @@ 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, 0x40, 0x0, len, 0x1);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info-nand.options  NAND_BUSWIDTH_16)
@@ -405,10 +405,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;
@@ -447,7 +448,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info 
*mtd, void *addr,
  

Re: [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput

2010-04-16 Thread Vimal Singh
Hi Ghorai,

On Fri, Apr 16, 2010 at 5:05 PM, Sukumar Ghorai s-gho...@ti.com wrote:
[...]
 -   ret = gpmc_prefetch_enable(info-gpmc_cs, 0x0, len, 0x0);
 +   ret = gpmc_prefetch_enable(info-gpmc_cs, 0x40, 0x0, len, 0x0);

Use macros here too then.

if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info-nand.options  NAND_BUSWIDTH_16)
 @@ -354,7 +354,7 @@ 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, 0x40, 0x0, len, 0x1);

here too

if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info-nand.options  NAND_BUSWIDTH_16)
 @@ -405,10 +405,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;
 @@ -447,7 +448,7 @@ 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, 0x20, 0x1, len, is_write);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
 @@ -524,6 +525,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
  static irqreturn_t omap_nand_irq(int this_irq, void *dev)
  {
struct omap_nand_info *info = (struct omap_nand_info *) dev;
 +   u32 *p = (u32 *) info-buf;
u32 irq_enb = 0, pref_status = 0, bytes = 0;
u32 irq_stats = __raw_readl(info-gpmc_baseaddr + GPMC_IRQSTATUS);
u32 pref_config = __raw_readl(info-gpmc_baseaddr +
 @@ -533,14 +535,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void 
 *dev)
if (irq_stats  0x2)
goto done;

 -   u32 *p = (u32 *) info-buf;
 -   pref_status = gpmc_prefetch_status();
 -   bytes = ((pref_status  24)  0x7F);
 +   bytes = PREFETCH_FIFOTHRESHOLD_WRITE;

By this, you are not really keeping prefetch the busyest.
you are filling only 'PREFETCH_FIFOTHRESHOLD_WRITE' bytes, while there
could be more free spaces.
Previous way of doing it was more efficent.

iowrite32_rep(info-nand_pref_fifo_add, p, bytes  2);
info-buf = info-buf + bytes;

} else {
 -   u32 *p = (u32 *) info-buf;
pref_status = gpmc_prefetch_status();
bytes = ((pref_status  24)  0x7F);
ioread32_rep(info-nand_pref_fifo_add, p, bytes  2);
 @@ -586,7 +585,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_READ, 0x0, len, 0x0);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
 @@ -630,7 +630,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
init_completion(info-comp);

/*  configure and start prefetch transfer */
 -   ret = gpmc_prefetch_enable(info-gpmc_cs, 0x0, len, 0x1);
 +   ret = gpmc_prefetch_enable(info-gpmc_cs,
 +   PREFETCH_FIFOTHRESHOLD_WRITE, 0x0, len, 0x1);

In case of write, in my experiments, fifo thresholed '24' was the best
compromise for throughput and cpu load.


Regards,
Vimal
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html