RE: [PATCH v5 1/3] omap3 gpmc: functionality enhancement

2010-07-07 Thread Ghorai, Sukumar


> -Original Message-
> From: Tony Lindgren [mailto:t...@atomide.com]
> Sent: Wednesday, July 07, 2010 6:32 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-...@lists.infradead.org;
> m...@compulab.co.il
> Subject: Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
> 
> * Ghorai, Sukumar  [100707 15:26]:
> > > From: Tony Lindgren [mailto:t...@atomide.com]
> > >
> > > You should just replace this function with simple functions like we
> > > already
> > > have in gpmc.c rather than trying to pack everything into one function.
> > > Just add various gpmc_xxx_get/set functions rather than pass int *rval.
> >
> > [Ghorai] So I was having the same query very 1st time.
> > So we need to implement 15 separate functions to do the same as you
> suggested. And in my approach it's very easy to enhance the functionally
> in future, say to add new set/get. E.g. we need the similar cleanup for
> OneNAND code too.
> > So, would you please confirm once again with one is the best and should
> follow?
> 
> In general, we should have separate read and write functions.
> 
> Maybe you can group them a little bit? Some of them need the chip
> select, and some of them are generic. Then some of them are NAND
> specific.
[Ghorai] ok. And let me re-work this for next version.
> 
> Regards,
> 
> Tony
--
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


Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement

2010-07-07 Thread Tony Lindgren
* Ghorai, Sukumar  [100707 15:26]:
> > From: Tony Lindgren [mailto:t...@atomide.com]
> > 
> > You should just replace this function with simple functions like we
> > already
> > have in gpmc.c rather than trying to pack everything into one function.
> > Just add various gpmc_xxx_get/set functions rather than pass int *rval.
> 
> [Ghorai] So I was having the same query very 1st time. 
> So we need to implement 15 separate functions to do the same as you 
> suggested. And in my approach it's very easy to enhance the functionally in 
> future, say to add new set/get. E.g. we need the similar cleanup for OneNAND 
> code too. 
> So, would you please confirm once again with one is the best and should 
> follow? 

In general, we should have separate read and write functions.

Maybe you can group them a little bit? Some of them need the chip
select, and some of them are generic. Then some of them are NAND
specific.

Regards,

Tony
--
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


RE: [PATCH v5 1/3] omap3 gpmc: functionality enhancement

2010-07-07 Thread Ghorai, Sukumar
Tony,

> -Original Message-
> From: Tony Lindgren [mailto:t...@atomide.com]
> Sent: Wednesday, July 07, 2010 3:49 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-...@lists.infradead.org;
> m...@compulab.co.il
> Subject: Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
> 
> * Sukumar Ghorai  [100604 10:34]:
> > few functions added in gpmc module and to be used by other drivers like
> NAND.
> > E.g.: - ioctl function
> >   - ecc functions
> 
> Uhh, let's leave out ioctl from the description.. Otherwise people
> think you're adding new ioctls in this patch.
[Ghorai] I am agree.
> 
> > @@ -46,8 +46,9 @@
> >  #define GPMC_ECC_CONFIG0x1f4
> >  #define GPMC_ECC_CONTROL   0x1f8
> >  #define GPMC_ECC_SIZE_CONFIG   0x1fc
> > +#define GPMC_ECC1_RESULT0x200
> >
> > -#define GPMC_CS0   0x60
> > +#define GPMC_CS0_BASE  0x60
> >  #define GPMC_CS_SIZE   0x30
> >
> >  #define GPMC_MEM_START 0x
> 
> Why changing GPMC_CS0 to GPMC_CS0_BASE? Should it rather be
> GPMC_CS0_OFFSET?
[Ghorai] I am agree with your input.
> 
> > @@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
> >  EXPORT_SYMBOL(gpmc_cs_free);
> >
> >  /**
> > + * gpmc_hwcontrol - hardware specific access (read/ write) control
> > + * @cs: chip select number
> > + * @cmd: command type
> > + * @write: 1 for write; 0 for read
> > + * @wval: value to write
> > + * @rval: read pointer
> > + */
> > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> > +{
> > +   u32 regval = 0;
> > +
> > +   if (!write && !rval)
> > +   return -EINVAL;
> 
> You pass int write, then return immediately if it's not set?
[Ghorai] This is just to check if argument passed correctly either for read or 
write functionally to do. We can remove this checking.
  
> 
> > +   switch (cmd) {
> > +   case GPMC_STATUS_BUFFER:
> > +   regval = gpmc_read_reg(GPMC_STATUS);
> > +   /* 1 : buffer is available to write */
> > +   *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> > +   break;
> > +
> > +   case GPMC_GET_SET_IRQ_STATUS:
> > +   if (write)
> > +   gpmc_write_reg(GPMC_IRQSTATUS, wval);
> > +   else
> > +   *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> > +   break;
> > +
> > +   case GPMC_PREFETCH_FIFO_CNT:
> > +   regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > +   *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> > +   break;
> > +
> > +   case GPMC_PREFETCH_COUNT:
> > +   regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > +   *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> > +   break;
> > +
> > +   case GPMC_CONFIG_WP:
> > +   regval = gpmc_read_reg(GPMC_CONFIG);
> > +   if (wval)
> > +   regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> > +   else
> > +   regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
> > +   gpmc_write_reg(GPMC_CONFIG, regval);
> > +   break;
> > +
> > +   case GPMC_CONFIG_RDY_BSY:
> > +   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > +   regval |= WR_RD_PIN_MONITORING;
> > +   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > +   break;
> > +
> > +   case GPMC_CONFIG_DEV_SIZE:
> > +   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > +   regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > +   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > +   break;
> > +
> > +   case GPMC_CONFIG_DEV_TYPE:
> > +   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > +   regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > +   if (wval == GPMC_DEVICETYPE_NOR)
> > +   regval |= GPMC_CONFIG1_MUXADDDATA;
> > +   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > +   break;
> > +
> > +   case GPMC_NAND_COMMAND:
> > +   gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > +   break;
> > +
> > +   case GPMC_NAND_ADDRESS:
> > +   gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > +   break;
> > +
> > +   case GPMC_NAND_DATA:
> > +   if (write)
> > +   gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> > +   els

Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement

2010-07-07 Thread Tony Lindgren
* Sukumar Ghorai  [100604 10:34]:
> few functions added in gpmc module and to be used by other drivers like NAND.
> E.g.: - ioctl function
>   - ecc functions

Uhh, let's leave out ioctl from the description.. Otherwise people
think you're adding new ioctls in this patch.
 
> @@ -46,8 +46,9 @@
>  #define GPMC_ECC_CONFIG  0x1f4
>  #define GPMC_ECC_CONTROL 0x1f8
>  #define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT0x200
>  
> -#define GPMC_CS0 0x60
> +#define GPMC_CS0_BASE0x60
>  #define GPMC_CS_SIZE 0x30
>  
>  #define GPMC_MEM_START   0x

Why changing GPMC_CS0 to GPMC_CS0_BASE? Should it rather be
GPMC_CS0_OFFSET?

> @@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
>  EXPORT_SYMBOL(gpmc_cs_free);
>  
>  /**
> + * gpmc_hwcontrol - hardware specific access (read/ write) control
> + * @cs: chip select number
> + * @cmd: command type
> + * @write: 1 for write; 0 for read
> + * @wval: value to write
> + * @rval: read pointer
> + */
> +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> +{
> + u32 regval = 0;
> +
> + if (!write && !rval)
> + return -EINVAL;

You pass int write, then return immediately if it's not set?

> + switch (cmd) {
> + case GPMC_STATUS_BUFFER:
> + regval = gpmc_read_reg(GPMC_STATUS);
> + /* 1 : buffer is available to write */
> + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> + break;
> +
> + case GPMC_GET_SET_IRQ_STATUS:
> + if (write)
> + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> + else
> + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> + break;
> +
> + case GPMC_PREFETCH_FIFO_CNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> + break;
> +
> + case GPMC_PREFETCH_COUNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> + break;
> +
> + case GPMC_CONFIG_WP:
> + regval = gpmc_read_reg(GPMC_CONFIG);
> + if (wval)
> + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> + else
> + regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
> + gpmc_write_reg(GPMC_CONFIG, regval);
> + break;
> +
> + case GPMC_CONFIG_RDY_BSY:
> + regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= WR_RD_PIN_MONITORING;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_SIZE:
> + regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_TYPE:
> + regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> + if (wval == GPMC_DEVICETYPE_NOR)
> + regval |= GPMC_CONFIG1_MUXADDDATA;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_NAND_COMMAND:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> + break;
> +
> + case GPMC_NAND_ADDRESS:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> + break;
> +
> + case GPMC_NAND_DATA:
> + if (write)
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> + else
> + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> + break;
> +
> + default:
> + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_hwcontrol);

You should just replace this function with simple functions like we already
have in gpmc.c rather than trying to pack everything into one function.
Just add various gpmc_xxx_get/set functions rather than pass int *rval.

Regards,

Tony
--
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


[PATCH v5 1/3] omap3 gpmc: functionality enhancement

2010-06-04 Thread Sukumar Ghorai
few functions added in gpmc module and to be used by other drivers like NAND.
E.g.: - ioctl function
  - ecc functions

Signed-off-by: Sukumar Ghorai 
---
 arch/arm/mach-omap2/gpmc.c |  219 ++--
 arch/arm/plat-omap/include/plat/gpmc.h |   33 +-
 drivers/mtd/nand/omap2.c   |4 +-
 3 files changed, 239 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..48b5af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -46,8 +46,9 @@
 #define GPMC_ECC_CONFIG0x1f4
 #define GPMC_ECC_CONTROL   0x1f8
 #define GPMC_ECC_SIZE_CONFIG   0x1fc
+#define GPMC_ECC1_RESULT0x200
 
-#define GPMC_CS0   0x60
+#define GPMC_CS0_BASE  0x60
 #define GPMC_CS_SIZE   0x30
 
 #define GPMC_MEM_START 0x
@@ -92,7 +93,8 @@ struct omap3_gpmc_regs {
 static struct resource gpmc_mem_root;
 static struct resource gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsignedgpmc_cs_map;
+static unsigned int gpmc_cs_map;   /* flag for cs which are initialized */
+static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */
 
 static void __iomem *gpmc_base;
 
@@ -108,11 +110,27 @@ static u32 gpmc_read_reg(int idx)
return __raw_readl(gpmc_base + idx);
 }
 
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+   void __iomem *reg_addr;
+
+   reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+   __raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+   void __iomem *reg_addr;
+
+   reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+   return __raw_readb(reg_addr);
+}
+
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
void __iomem *reg_addr;
 
-   reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+   reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
 }
 
@@ -120,7 +138,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
 {
void __iomem *reg_addr;
 
-   reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+   reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
 }
 
@@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
+ * gpmc_hwcontrol - hardware specific access (read/ write) control
+ * @cs: chip select number
+ * @cmd: command type
+ * @write: 1 for write; 0 for read
+ * @wval: value to write
+ * @rval: read pointer
+ */
+int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
+{
+   u32 regval = 0;
+
+   if (!write && !rval)
+   return -EINVAL;
+
+   switch (cmd) {
+   case GPMC_STATUS_BUFFER:
+   regval = gpmc_read_reg(GPMC_STATUS);
+   /* 1 : buffer is available to write */
+   *rval = regval & GPMC_STATUS_BUFF_EMPTY;
+   break;
+
+   case GPMC_GET_SET_IRQ_STATUS:
+   if (write)
+   gpmc_write_reg(GPMC_IRQSTATUS, wval);
+   else
+   *rval = gpmc_read_reg(GPMC_IRQSTATUS);
+   break;
+
+   case GPMC_PREFETCH_FIFO_CNT:
+   regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+   *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
+   break;
+
+   case GPMC_PREFETCH_COUNT:
+   regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+   *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
+   break;
+
+   case GPMC_CONFIG_WP:
+   regval = gpmc_read_reg(GPMC_CONFIG);
+   if (wval)
+   regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+   else
+   regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
+   gpmc_write_reg(GPMC_CONFIG, regval);
+   break;
+
+   case GPMC_CONFIG_RDY_BSY:
+   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+   regval |= WR_RD_PIN_MONITORING;
+   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+   break;
+
+   case GPMC_CONFIG_DEV_SIZE:
+   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+   regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+   break;
+
+   case GPMC_CONFIG_DEV_TYPE:
+   regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+   regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+   if (wval == GPMC_DEVICETYPE_NOR)
+   regval |= GPMC_CONFIG1_MUXADDDATA;
+   gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+   break;
+
+   case GPMC_NAND_COMMAND:
+   gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+   break;
+
+   cas