Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
On Tue, May 25, 2010 at 8:07 PM, Ghorai, Sukumar wrote: [...] >> > c. And how to know that ECC engine is in used other driver should not >> use it? Any bit to know that ecc engine is busy, as we check for prefetch? >> Do not really remember config registers. Perhaps there is no way. >> But I guess you should check into register GPMC_ECC_CONFIG at bit 1. >> This is the bit we are setting to enable ECC calculation, IIRC. > [Ghorai] there are two functions - > info->nand.ecc.calculate = omap_calculate_ecc; > info->nand.ecc.hwctl = omap_enable_hwecc; > And GPMC_ECC_CONFIG register.. > 3:1 ECCCS Selects the CS where ECC is computed > 0 ECCENABLE Enables the ECC feature > Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its > get disabled (automatically) when ecc_size data transfer over. > But say still it did not read the ecc value yet (omap_calculate_ecc). > So how to protect following omap_enable_hwecc() before omap_calculate_ecc() > without additional flag? Any input is welcome. Oh yes, that's is a problem. Perhaps in that case you have to protect it in very much same way you already did. -- Regards, Vimal Singh -- 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 v3 1/3] omap3 gpmc: functionality enhancement
Vimal, > -Original Message- > From: Vimal Singh [mailto:vimal.neww...@gmail.com] > Sent: Thursday, May 20, 2010 12:01 AM > To: Ghorai, Sukumar > Cc: linux-omap@vger.kernel.org; linux-...@lists.infradead.org; > t...@atomide.com; sako...@gmail.com; m...@compulab.co.il; > artem.bityuts...@nokia.com; peter.bar...@gmail.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: > >> > > + > >> > > + 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; > >> > > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not > connected). > >> > >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the > >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the > >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND > >> accesses > > [Ghorai] So better keep this feature, > > Yes, looks like there are some boards which can still take advantage of > this. > > >> > [...] > >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > >> > > /** > >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine > >> > > */ > >> > > -void gpmc_prefetch_reset(void) > >> > > +int gpmc_prefetch_reset(int cs) > >> > > { > >> > > + if (gpmc_pref_used == cs) > >> > > + gpmc_pref_used = -EINVAL; > >> > > + else > >> > > + return -EINVAL; > >> > > + > >> > > >> > This is also not required. As, this function will be called only if > >> > prefetch was used. > > [Ghorai] Agree. Can you see this input too? > > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html > > Exactly, this is what I am telling here. Enable prefetch engine call > is already being check for *busy* or not. [Ghorai] Agree. > > > > [...] > >> > > +int gpmc_ecc_init(int cs, int ecc_size) > >> > > +{ > >> > > + unsigned int val = 0x0; > >> > > + > >> > > + /* check if ecc engine already by another cs */ > >> > > + if (gpmc_ecc_used == -EINVAL) > >> > > + gpmc_ecc_used = cs; > >> > > + else > >> > > + return -EBUSY; > >> > Here few things need be to consider: > >> > 1. 'init' is supposed to done once for every instance of driver > during > >> probe > >> > 2. But ECC engine, too, have only one instance at a time, So > >> > 3. As long as all NAND chip are supposed to use same ECC machenism, > we > >> > can go for only one time 'init' for all drivers, perhaps in > >> > gpmc_nand.c. > >> > 4. But in case, different instances of driver (or NAND chip) requires > >> > different ECC machenism (for ex. Hamming or BCH, or even with > >> > different capabilities of error correction), > >> > this will no longer vailid. Then rather we should have something like > >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > >> > needs it (something like as it is done for prefetch engine). > > [Ghorai] > > a. do you think it will reduce the throughput? > No. But in current implementation it will be called for each instance > driver. (see my 3rd point) > > > b. Moreover I think we will take this as 5th patch as cleanup/ > improvemnt. > > c. And how to know that ECC engine is in used other driver should not > use it? Any bit to know that ecc engine is busy, as we check for prefetch? > Do not really remember config registers. Perhaps there is no way. > But I guess you should check into register GPMC_ECC_CONFIG at bit 1. > This is the bit we are setting to enable ECC calculation, IIRC. [Ghorai] there are two functions - info->nand.ecc.calculate= omap_calculate_ecc; info->nand.ecc.hwctl= omap_enable_hwecc; And GPMC_ECC_CONFIG register.. 3:1 ECCCS Selects the CS where ECC is computed 0 ECCENABLE Enables the ECC feature Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its get disabled (aut
Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
On Thu, May 20, 2010 at 11:08 AM, Ghorai, Sukumar wrote: > Vimal, > >> -Original Message- >> From: Vimal Singh [mailto:vimal.neww...@gmail.com] >> Sent: 2010-05-20 00:01 >> To: Ghorai, Sukumar >> Cc: linux-omap@vger.kernel.org; linux-...@lists.infradead.org; >> t...@atomide.com; sako...@gmail.com; m...@compulab.co.il; >> artem.bityuts...@nokia.com; peter.bar...@gmail.com >> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement >> >> On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: >> >> > > + >> >> > > + 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; >> >> > >> >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not >> connected). >> >> >> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the >> >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the >> >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND >> >> accesses >> > [Ghorai] So better keep this feature, >> >> Yes, looks like there are some boards which can still take advantage of >> this. >> >> >> >> [...] >> >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); >> >> > > /** >> >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine >> >> > > */ >> >> > > -void gpmc_prefetch_reset(void) >> >> > > +int gpmc_prefetch_reset(int cs) >> >> > > { >> >> > > + if (gpmc_pref_used == cs) >> >> > > + gpmc_pref_used = -EINVAL; >> >> > > + else >> >> > > + return -EINVAL; >> >> > > + >> >> > >> >> > This is also not required. As, this function will be called only if >> >> > prefetch was used. >> > [Ghorai] Agree. Can you see this input too? >> > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html >> >> Exactly, this is what I am telling here. Enable prefetch engine call >> is already being check for *busy* or not. >> >> > >> [...] >> >> > > +int gpmc_ecc_init(int cs, int ecc_size) >> >> > > +{ >> >> > > + unsigned int val = 0x0; >> >> > > + >> >> > > + /* check if ecc engine already by another cs */ >> >> > > + if (gpmc_ecc_used == -EINVAL) >> >> > > + gpmc_ecc_used = cs; >> >> > > + else >> >> > > + return -EBUSY; >> >> > Here few things need be to consider: >> >> > 1. 'init' is supposed to done once for every instance of driver >> during >> >> probe >> >> > 2. But ECC engine, too, have only one instance at a time, So >> >> > 3. As long as all NAND chip are supposed to use same ECC machenism, >> we >> >> > can go for only one time 'init' for all drivers, perhaps in >> >> > gpmc_nand.c. >> >> > 4. But in case, different instances of driver (or NAND chip) requires >> >> > different ECC machenism (for ex. Hamming or BCH, or even with >> >> > different capabilities of error correction), >> >> > this will no longer vailid. Then rather we should have something like >> >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver >> >> > needs it (something like as it is done for prefetch engine). >> > [Ghorai] >> > a. do you think it will reduce the throughput? >> No. But in current implementation it will be called for each instance >> driver. (see my 3rd point) >> >> > b. Moreover I think we will take this as 5th patch as cleanup/ >> improvemnt. >> > c. And how to know that ECC engine is in used other driver should not >> use it? Any bit to know that ecc engine is busy, as we check for prefetch? >> Do not really remember config registers. Perhaps there is no way. >> But I guess you should check into register GPMC_ECC_CONFIG at bit 1. >> This is the bit we are setting to enable ECC calculation, IIRC. >> >> > d. any further input on http://www.mail-archive.com/linux- >> o...@vger.kernel.org/msg28520.html >> And this what I was suggesting in my point 4. In my example >> 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. >> I said *config*, since in such scenario you need to configer HW >> ECCconfig register everytime as well, rather just checking >> availability and enabling. > [Ghorai] still I feel we should not mix this patch with cleanup. And yes if > possible this will be the 5th one as cleanup. > 4th one - prefetch cleanup > 5th one - ecc cleanup. > Do you think still missing anything for this patch? As long as you take care of current comments, I do not have any further comment for now. -- Regards, Vimal Singh -- 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 v3 1/3] omap3 gpmc: functionality enhancement
Vimal, > -Original Message- > From: Vimal Singh [mailto:vimal.neww...@gmail.com] > Sent: 2010-05-20 00:01 > To: Ghorai, Sukumar > Cc: linux-omap@vger.kernel.org; linux-...@lists.infradead.org; > t...@atomide.com; sako...@gmail.com; m...@compulab.co.il; > artem.bityuts...@nokia.com; peter.bar...@gmail.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: > >> > > + > >> > > + 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; > >> > > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not > connected). > >> > >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the > >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the > >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND > >> accesses > > [Ghorai] So better keep this feature, > > Yes, looks like there are some boards which can still take advantage of > this. > > >> > [...] > >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > >> > > /** > >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine > >> > > */ > >> > > -void gpmc_prefetch_reset(void) > >> > > +int gpmc_prefetch_reset(int cs) > >> > > { > >> > > + if (gpmc_pref_used == cs) > >> > > + gpmc_pref_used = -EINVAL; > >> > > + else > >> > > + return -EINVAL; > >> > > + > >> > > >> > This is also not required. As, this function will be called only if > >> > prefetch was used. > > [Ghorai] Agree. Can you see this input too? > > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html > > Exactly, this is what I am telling here. Enable prefetch engine call > is already being check for *busy* or not. > > > > [...] > >> > > +int gpmc_ecc_init(int cs, int ecc_size) > >> > > +{ > >> > > + unsigned int val = 0x0; > >> > > + > >> > > + /* check if ecc engine already by another cs */ > >> > > + if (gpmc_ecc_used == -EINVAL) > >> > > + gpmc_ecc_used = cs; > >> > > + else > >> > > + return -EBUSY; > >> > Here few things need be to consider: > >> > 1. 'init' is supposed to done once for every instance of driver > during > >> probe > >> > 2. But ECC engine, too, have only one instance at a time, So > >> > 3. As long as all NAND chip are supposed to use same ECC machenism, > we > >> > can go for only one time 'init' for all drivers, perhaps in > >> > gpmc_nand.c. > >> > 4. But in case, different instances of driver (or NAND chip) requires > >> > different ECC machenism (for ex. Hamming or BCH, or even with > >> > different capabilities of error correction), > >> > this will no longer vailid. Then rather we should have something like > >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > >> > needs it (something like as it is done for prefetch engine). > > [Ghorai] > > a. do you think it will reduce the throughput? > No. But in current implementation it will be called for each instance > driver. (see my 3rd point) > > > b. Moreover I think we will take this as 5th patch as cleanup/ > improvemnt. > > c. And how to know that ECC engine is in used other driver should not > use it? Any bit to know that ecc engine is busy, as we check for prefetch? > Do not really remember config registers. Perhaps there is no way. > But I guess you should check into register GPMC_ECC_CONFIG at bit 1. > This is the bit we are setting to enable ECC calculation, IIRC. > > > d. any further input on http://www.mail-archive.com/linux- > o...@vger.kernel.org/msg28520.html > And this what I was suggesting in my point 4. In my example > 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. > I said *config*, since in such scenario you need to configer HW > ECCconfig register everytime as well, rather just checking > availability and enabling. [Ghorai] still I feel we should not mix this patch with cleanup. And yes if possible this will be the 5th one as cleanup. 4th one - prefetch cleanup 5th one - ecc cleanup. Do you think still missing anything for this patch? > > > > [...] > >> > > +int gpmc_ecc_reset(int cs) > >> > > +{ > >> > > + if (gpmc_ecc_used == cs) > >> > > + gpmc_ecc_used = -EINVAL; > >> > > + else > >> > > + return -EINVAL; > >> > > + > >> > > + return 0; > >> > > +} > > I guess in this function you should also clear gpmc ecc config > register explicitly. > > > -- > Regards, > Vimal Singh -- 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 v3 1/3] omap3 gpmc: functionality enhancement
On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: >> > > + >> > > + 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; >> > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). >> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND >> accesses > [Ghorai] So better keep this feature, Yes, looks like there are some boards which can still take advantage of this. >> [...] >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); >> > > /** >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine >> > > */ >> > > -void gpmc_prefetch_reset(void) >> > > +int gpmc_prefetch_reset(int cs) >> > > { >> > > + if (gpmc_pref_used == cs) >> > > + gpmc_pref_used = -EINVAL; >> > > + else >> > > + return -EINVAL; >> > > + >> > >> > This is also not required. As, this function will be called only if >> > prefetch was used. > [Ghorai] Agree. Can you see this input too? > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html Exactly, this is what I am telling here. Enable prefetch engine call is already being check for *busy* or not. > [...] >> > > +int gpmc_ecc_init(int cs, int ecc_size) >> > > +{ >> > > + unsigned int val = 0x0; >> > > + >> > > + /* check if ecc engine already by another cs */ >> > > + if (gpmc_ecc_used == -EINVAL) >> > > + gpmc_ecc_used = cs; >> > > + else >> > > + return -EBUSY; >> > Here few things need be to consider: >> > 1. 'init' is supposed to done once for every instance of driver during >> probe >> > 2. But ECC engine, too, have only one instance at a time, So >> > 3. As long as all NAND chip are supposed to use same ECC machenism, we >> > can go for only one time 'init' for all drivers, perhaps in >> > gpmc_nand.c. >> > 4. But in case, different instances of driver (or NAND chip) requires >> > different ECC machenism (for ex. Hamming or BCH, or even with >> > different capabilities of error correction), >> > this will no longer vailid. Then rather we should have something like >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver >> > needs it (something like as it is done for prefetch engine). > [Ghorai] > a. do you think it will reduce the throughput? No. But in current implementation it will be called for each instance driver. (see my 3rd point) > b. Moreover I think we will take this as 5th patch as cleanup/ improvemnt. > c. And how to know that ECC engine is in used other driver should not use it? > Any bit to know that ecc engine is busy, as we check for prefetch? Do not really remember config registers. Perhaps there is no way. But I guess you should check into register GPMC_ECC_CONFIG at bit 1. This is the bit we are setting to enable ECC calculation, IIRC. > d. any further input on > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html And this what I was suggesting in my point 4. In my example 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. I said *config*, since in such scenario you need to configer HW ECCconfig register everytime as well, rather just checking availability and enabling. > [...] >> > > +int gpmc_ecc_reset(int cs) >> > > +{ >> > > + if (gpmc_ecc_used == cs) >> > > + gpmc_ecc_used = -EINVAL; >> > > + else >> > > + return -EINVAL; >> > > + >> > > + return 0; >> > > +} I guess in this function you should also clear gpmc ecc config register explicitly. -- Regards, Vimal Singh -- 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 v3 1/3] omap3 gpmc: functionality enhancement
Vimal, > -Original Message- > From: Peter Barada [mailto:peter.bar...@gmail.com] > Sent: 2010-05-19 21:18 > To: Vimal Singh > Cc: Ghorai, Sukumar; linux-omap@vger.kernel.org; linux- > m...@lists.infradead.org; t...@atomide.com; sako...@gmail.com; > m...@compulab.co.il; artem.bityuts...@nokia.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote: > > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > > 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 | 246 > +++- > > > arch/arm/plat-omap/include/plat/gpmc.h | 35 - > > > drivers/mtd/nand/omap2.c |4 +- > > > 3 files changed, 274 insertions(+), 11 deletions(-) > > > > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > > index 5bc3ca0..7e6d821 > > > --- 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,9 @@ 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 unsignedint gpmc_cs_map;/* flag for cs which > are initialized */ > > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > > > +static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ > > > > > > static void __iomem *gpmc_base; > > > > > > @@ -108,11 +111,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 +139,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 +438,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); &
Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote: > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > 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 | 246 > > +++- > > arch/arm/plat-omap/include/plat/gpmc.h | 35 - > > drivers/mtd/nand/omap2.c |4 +- > > 3 files changed, 274 insertions(+), 11 deletions(-) > > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > index 5bc3ca0..7e6d821 > > --- 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,9 @@ 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 unsignedint gpmc_cs_map;/* flag for cs which are > > initialized */ > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > > +static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ > > > > static void __iomem *gpmc_base; > > > > @@ -108,11 +111,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 +139,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 +438,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; > > IIRC, at least in OMAP2/3, ready
Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > 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 | 246 > +++- > arch/arm/plat-omap/include/plat/gpmc.h | 35 - > drivers/mtd/nand/omap2.c | 4 +- > 3 files changed, 274 insertions(+), 11 deletions(-) > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > index 5bc3ca0..7e6d821 > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -46,8 +46,9 @@ > #define GPMC_ECC_CONFIG 0x1f4 > #define GPMC_ECC_CONTROL 0x1f8 > #define GPMC_ECC_SIZE_CONFIG 0x1fc > +#define GPMC_ECC1_RESULT 0x200 > > -#define GPMC_CS0 0x60 > +#define GPMC_CS0_BASE 0x60 > #define GPMC_CS_SIZE 0x30 > > #define GPMC_MEM_START 0x > @@ -92,7 +93,9 @@ 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 unsigned gpmc_cs_map; > +static unsigned int gpmc_cs_map; /* flag for cs which are > initialized */ > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ > > static void __iomem *gpmc_base; > > @@ -108,11 +111,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 +139,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 +438,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; IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). > + > + 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_
[PATCH v3 1/3] omap3 gpmc: functionality enhancement
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 | 246 +++- arch/arm/plat-omap/include/plat/gpmc.h | 35 - drivers/mtd/nand/omap2.c |4 +- 3 files changed, 274 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5bc3ca0..7e6d821 --- 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,9 @@ 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 unsignedint gpmc_cs_map;/* flag for cs which are initialized */ +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ +static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ static void __iomem *gpmc_base; @@ -108,11 +111,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 +139,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 +438,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_w