Prepare for GPMC driver conversion (w.r.t MTD)
Subsystems (7)
v2 cover Prepare for GPMC driver conversion (w.r.t MTD)
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of arch/arm/*omap*/
This series,
1. provides the ability for OMAP NAND driver to configure GPMC-NAND registers by NAND driver itself instead of using exported GPMC symbols
2. modifies GPMC to provide OMAP ONENAND & NAND drivers with GPMC allocated address space as resource
3. creates a fictitious GPMC interrupt chip and provide the clients with interrupts that could be handled using standard APIs (helps in removing the requirement for driver of peripheral connected to GPMC having the knowledge about GPMC interrupt handling). The only user is OMAP NAND driver, it has also been modified to take advantage of this
This series has been made over 3.5-rc1
Regards
Afzal
v2:
[mtd: nand: omap2: handle nand on gpmc] simplify omap_prefetch_enable()
Afzal Mohammed (10):
ARM: OMAP2+: gpmc: update nand register helper
ARM: OMAP2+: gpmc-nand: update gpmc-nand regs
mtd: nand: omap2: handle nand on gpmc
ARM: OMAP2+: gpmc-nand: update resource with memory
ARM: OMAP2+: gpmc-onenand: provide memory as resource
mtd: nand: omap2: obtain memory from resource
mtd: onenand: omap2: obtain memory from resource
ARM: OMAP2+: gpmc: Modify interrupt handling
ARM: OMAP2+: gpmc-nand: Modify Interrupt handling
mtd: nand: omap2: use gpmc provided irqs
arch/arm/mach-omap2/gpmc-nand.c | 28 ++- arch/arm/mach-omap2/gpmc-onenand.c | 23 ++- arch/arm/mach-omap2/gpmc.c | 156 +++++++++++++++-- arch/arm/plat-omap/include/plat/gpmc.h | 19 +++ arch/arm/plat-omap/include/plat/nand.h | 2 +- drivers/mtd/nand/omap2.c | 291 ++++++++++++++++++++++++-------- drivers/mtd/onenand/omap2.c | 29 ++-- 7 files changed, 436 insertions(+), 112 deletions(-)
Signature · 1 line
1.7.10.2
PATCH v2 1/10 ARM: OMAP2+: gpmc: update nand register helper
Provide helper function for updating NAND register details for the necessary chip select. NAND drivers platform data can be updated with this information so that NAND driver can handle GPMC NAND operations by itself.
--- arch/arm/mach-omap2/gpmc.c | 20 ++++++++++++++++++++ arch/arm/plat-omap/include/plat/gpmc.h | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+)
arch/arm/mach-omap2/gpmc.c +20 -0
@@ -682,6 +682,26 @@ int gpmc_prefetch_reset(int cs) }EXPORT_SYMBOL (gpmc_prefetch_reset); +void gpmc_update_nand_reg (struct gpmc_nand_regs *reg,int cs) +{ + reg->gpmc_status = gpmc_base +GPMC_STATUS ; + reg->gpmc_nand_command = gpmc_base +GPMC_CS0_OFFSET + +GPMC_CS_NAND_COMMAND +GPMC_CS_SIZE * cs; + reg->gpmc_nand_address = gpmc_base +GPMC_CS0_OFFSET + +GPMC_CS_NAND_ADDRESS +GPMC_CS_SIZE * cs; + reg->gpmc_nand_data = gpmc_base +GPMC_CS0_OFFSET + +GPMC_CS_NAND_DATA +GPMC_CS_SIZE * cs; + reg->gpmc_prefetch_config1 = gpmc_base +GPMC_PREFETCH_CONFIG1 ; + reg->gpmc_prefetch_config2 = gpmc_base +GPMC_PREFETCH_CONFIG2 ; + reg->gpmc_prefetch_control = gpmc_base +GPMC_PREFETCH_CONTROL ; + reg->gpmc_prefetch_status = gpmc_base +GPMC_PREFETCH_STATUS ; + reg->gpmc_ecc_config = gpmc_base +GPMC_ECC_CONFIG ; + reg->gpmc_ecc_control = gpmc_base +GPMC_ECC_CONTROL ; + reg->gpmc_ecc_size_config = gpmc_base +GPMC_ECC_SIZE_CONFIG ; + reg->gpmc_ecc1_result = gpmc_base +GPMC_ECC1_RESULT ; + reg->gpmc_bch_result0 = gpmc_base +GPMC_ECC_BCH_RESULT_0 ; +} +static void __init gpmc_mem_init (void ) {int cs;
arch/arm/plat-omap/include/plat/gpmc.h +18 -0
@@ -133,6 +133,24 @@ struct gpmc_timings {u16 wr_data_mux_bus;/* WRDATAONADMUXBUS */ }; +struct gpmc_nand_regs { +void __iomem *gpmc_status; +void __iomem *gpmc_nand_command; +void __iomem *gpmc_nand_address; +void __iomem *gpmc_nand_data; +void __iomem *gpmc_prefetch_config1; +void __iomem *gpmc_prefetch_config2; +void __iomem *gpmc_prefetch_control; +void __iomem *gpmc_prefetch_status; +void __iomem *gpmc_ecc_config; +void __iomem *gpmc_ecc_control; +void __iomem *gpmc_ecc_size_config; +void __iomem *gpmc_ecc1_result; +void __iomem *gpmc_bch_result0; +}; + +extern void gpmc_update_nand_reg (struct gpmc_nand_regs *reg,int cs); +extern unsigned int gpmc_ns_to_ticks (unsigned int time_ns);extern unsigned int gpmc_ps_to_ticks (unsigned int time_ps);extern unsigned int gpmc_ticks_to_ns (unsigned int ticks);
Signature · 1 line
1.7.10.2
PATCH v2 2/10 ARM: OMAP2+: gpmc-nand: update gpmc-nand regs
In reply to Afzal MohammedGPMC has NAND registers, update nand platform data with those details so that NAND driver can configure those by itself instead of using exported symbols.
--- arch/arm/mach-omap2/gpmc-nand.c | 2 ++ arch/arm/plat-omap/include/plat/nand.h | 1 + 2 files changed, 3 insertions(+)
arch/arm/mach-omap2/gpmc-nand.c +2 -0
@@ -108,6 +108,8 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)gpmc_cs_configure (gpmc_nand_data->cs,GPMC_CONFIG_RDY_BSY ,1 ); } +gpmc_update_nand_reg (&gpmc_nand_data->reg, gpmc_nand_data->cs); + err =platform_device_register (&gpmc_nand_device);if (err <0 ) {dev_err (dev,"Unable to register NAND device\n" );
arch/arm/plat-omap/include/plat/nand.h +1 -0
@@ -29,6 +29,7 @@ struct omap_nand_platform_data {unsigned long phys_base;int devsize;enum omap_ecc ecc_opt; +struct gpmc_nand_regs reg; };/* minimum size for IO mapping */
Signature · 1 line
1.7.10.2
PATCH v2 3/10 mtd: nand: omap2: handle nand on gpmc
In reply to Afzal MohammedGPMC platform initialization has been modified to fill NAND platform data with GPMC NAND register details. As these registers are accessible in NAND driver itself, configure NAND in GPMC by itself.
Modified prefetch and ecc functions are logically same as the corresponding exported symbols from GPMC code.
Note: Verfying that other CS have not yet enabled for prefetch & ecc has to be incorporated. Currently this causes no issues as there are no boards that use NAND on multiple CS. With ongoing GPMC driver migration, perhaps it would be better to consider NAND connected on multiple CS as a single peripheral using multiple CS. This would make handling multiple CS issues easier.
---
v2: simplify omap_prefetch_enable function
drivers/mtd/nand/omap2.c | 204 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 44 deletions(-)
drivers/mtd/nand/omap2.c +160 -44
@@ -99,6 +99,16 @@#define P4e_s (a) (TF(a & NAND_Ecc_P4e) << 0)#define P4o_s (a) (TF(a & NAND_Ecc_P4o) << 1) +#define PREFETCH_CONFIG1_CS_SHIFT 24 +#define ECC_CONFIG_CS_SHIFT 1 +#define CS_MASK 0x7 +#define ENABLE_PREFETCH (0x1 << 7) +#define DMA_MPU_MODE_SHIFT 2 +#define ECCSIZE1_SHIFT 22 +#define ECC1RESULTSIZE 0x1 +#define ECCCLEAR 0x100 +#define ECC1 0x1 +/* oob info generated runtime depending on ecc algorithm and layout selected */ static struct nand_ecclayout omap_oobinfo;/* Define some generic bad / good block scan pattern which are used
@@ -131,6 +141,7 @@ struct omap_nand_info { } iomode;u_char *buf;int buf_len; +struct gpmc_nand_regs reg;#ifdef CONFIG_MTD_NAND_OMAP_BCH struct bch_control *bch;
@@ -139,6 +150,63 @@ struct omap_nand_info { };/** +* omap_prefetch_enable - configures and starts prefetch transfer +* @cs: cs (chip select) number +* @fifo_th: fifo threshold to be used for read/ write +* @dma_mode: dma mode enable (1) or disable (0) +* @u32_count: number of bytes to be transferred +* @is_write: prefetch read(0) or write post(1) mode +*/ +static int omap_prefetch_enable (int cs,int fifo_th,int dma_mode, +unsigned int u32_count,int is_write,struct omap_nand_info *info) +{ +u32 val; + +if (fifo_th >PREFETCH_FIFOTHRESHOLD_MAX ) +return -1 ; + +if (readl (info->reg.gpmc_prefetch_control)) +return -EBUSY ; + +/* Set the amount of bytes to be prefetched */ +writel (u32_count, info->reg.gpmc_prefetch_config2); + +/* Set dma/mpu mode, the prefetch read / post write and +* enable the engine. Set which cs is has requested for. +*/ + val = ((cs <<PREFETCH_CONFIG1_CS_SHIFT ) | +PREFETCH_FIFOTHRESHOLD (fifo_th) |ENABLE_PREFETCH | + (dma_mode <<DMA_MPU_MODE_SHIFT ) | (0x1 & is_write)); +writel (val, info->reg.gpmc_prefetch_config1); + +/* Start the prefetch engine */ +writel (0x1 , info->reg.gpmc_prefetch_control); + +return 0 ; +} + +/** +* omap_prefetch_reset - disables and stops the prefetch engine +*/ +static int omap_prefetch_reset (int cs,struct omap_nand_info *info) +{ +u32 config1; + +/* check if the same module/cs is trying to reset */ + config1 =readl (info->reg.gpmc_prefetch_config1); +if (((config1 >>PREFETCH_CONFIG1_CS_SHIFT ) &CS_MASK ) != cs) +return -EINVAL ; + +/* Stop the PFPW engine */ +writel (0x0 , info->reg.gpmc_prefetch_control); + +/* Reset/disable the PFPW engine */ +writel (0x0 , info->reg.gpmc_prefetch_config1); + +return 0 ; +} + +/** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure * @cmd: command to device
@@ -156,13 +224,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)if (cmd !=NAND_CMD_NONE ) {if (ctrl &NAND_CLE ) -gpmc_nand_write (info->gpmc_cs,GPMC_NAND_COMMAND , cmd); +writeb (cmd, info->reg.gpmc_nand_command);else if (ctrl &NAND_ALE ) -gpmc_nand_write (info->gpmc_cs,GPMC_NAND_ADDRESS , cmd); +writeb (cmd, info->reg.gpmc_nand_address);else /* NAND_NCE */ -gpmc_nand_write (info->gpmc_cs,GPMC_NAND_DATA , cmd); +writeb (cmd, info->reg.gpmc_nand_data); } }
@@ -196,7 +264,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)iowrite8 (*p++, info->nand.IO_ADDR_W);/* wait until buffer is available for write */ do { - status =gpmc_read_status (GPMC_STATUS_BUFFER ); + status =readl (info->reg.gpmc_status) & +GPMC_STATUS_BUFF_EMPTY ; }while (!status); } }
@@ -233,7 +302,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)iowrite16 (*p++, info->nand.IO_ADDR_W);/* wait until buffer is available for write */ do { - status =gpmc_read_status (GPMC_STATUS_BUFFER ); + status =readl (info->reg.gpmc_status) & +GPMC_STATUS_BUFF_EMPTY ; }while (!status); } }
@@ -263,8 +333,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) }/* configure and start prefetch transfer */ - ret =gpmc_prefetch_enable (info->gpmc_cs, -PREFETCH_FIFOTHRESHOLD_MAX ,0x0 , len,0x0 ); + ret =omap_prefetch_enable (info->gpmc_cs, +PREFETCH_FIFOTHRESHOLD_MAX ,0x0 , len,0x0 , info);if (ret) {/* PFPW engine is busy, use cpu copy method */ if (info->nand.options &NAND_BUSWIDTH_16 )
@@ -273,14 +343,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)omap_read_buf8 (mtd, (u_char *)p, len); }else {do { - r_count =gpmc_read_status (GPMC_PREFETCH_FIFO_CNT ); + r_count =readl (info->reg.gpmc_prefetch_status); + r_count =GPMC_PREFETCH_STATUS_FIFO_CNT (r_count); r_count = r_count >>2 ;ioread32_rep (info->nand.IO_ADDR_R, p, r_count); p += r_count; len -= r_count <<2 ; }while (len);/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (info->gpmc_cs); +omap_prefetch_reset (info->gpmc_cs, info); } }
@@ -299,6 +370,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,int i =0 , ret =0 ;u16 *p = (u16 *)buf;unsigned long tim, limit; +u32 val;/* take care of subpage writes */ if (len %2 !=0 ) {
@@ -308,8 +380,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd, }/* configure and start prefetch transfer */ - ret =gpmc_prefetch_enable (info->gpmc_cs, -PREFETCH_FIFOTHRESHOLD_MAX ,0x0 , len,0x1 ); + ret =omap_prefetch_enable (info->gpmc_cs, +PREFETCH_FIFOTHRESHOLD_MAX ,0x0 , len,0x1 , info);if (ret) {/* PFPW engine is busy, use cpu copy method */ if (info->nand.options &NAND_BUSWIDTH_16 )
@@ -318,7 +390,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,omap_write_buf8 (mtd, (u_char *)p, len); }else {while (len) { - w_count =gpmc_read_status (GPMC_PREFETCH_FIFO_CNT ); + w_count =readl (info->reg.gpmc_prefetch_status); + w_count =GPMC_PREFETCH_STATUS_FIFO_CNT (w_count); w_count = w_count >>1 ;for (i =0 ; (i < w_count) && len; i++, len -=2 )iowrite16 (*p++, info->nand.IO_ADDR_W);
@@ -327,11 +400,14 @@ static void omap_write_buf_pref(struct mtd_info *mtd, tim =0 ; limit = (loops_per_jiffy *msecs_to_jiffies (OMAP_NAND_TIMEOUT_MS )); -while (gpmc_read_status (GPMC_PREFETCH_COUNT ) && (tim++ < limit)) +do {cpu_relax (); + val =readl (info->reg.gpmc_prefetch_status); + val =GPMC_PREFETCH_STATUS_COUNT (val); + }while (val && (tim++ < limit));/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (info->gpmc_cs); +omap_prefetch_reset (info->gpmc_cs, info); } }
@@ -363,6 +439,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,dma_addr_t dma_addr;int ret;unsigned long tim, limit; +u32 val;/* The fifo depth is 64 bytes max. * But configure the FIFO-threahold to 32 to get a sync at each frame
@@ -407,8 +484,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC); }/* configure and start prefetch transfer */ - ret =gpmc_prefetch_enable (info->gpmc_cs, -PREFETCH_FIFOTHRESHOLD_MAX ,0x1 , len, is_write); + ret =omap_prefetch_enable (info->gpmc_cs, +PREFETCH_FIFOTHRESHOLD_MAX ,0x1 , len, is_write, info);if (ret)/* PFPW engine is busy, use cpu copy method */ goto out_copy_unmap;
@@ -421,11 +498,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,wait_for_completion (&info->comp); tim =0 ; limit = (loops_per_jiffy *msecs_to_jiffies (OMAP_NAND_TIMEOUT_MS )); -while (gpmc_read_status (GPMC_PREFETCH_COUNT ) && (tim++ < limit)) + +do {cpu_relax (); + val =readl (info->reg.gpmc_prefetch_status); + val =GPMC_PREFETCH_STATUS_COUNT (val); + }while (val && (tim++ < limit));/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (info->gpmc_cs); +omap_prefetch_reset (info->gpmc_cs, info);dma_unmap_single (&info->pdev->dev, dma_addr, len, dir);return 0 ;
@@ -485,7 +566,8 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)u32 irq_stat; irq_stat =gpmc_read_status (GPMC_GET_IRQ_STATUS ); - bytes =gpmc_read_status (GPMC_PREFETCH_FIFO_CNT ); + bytes =readl (info->reg.gpmc_prefetch_status); + bytes =GPMC_PREFETCH_STATUS_FIFO_CNT (bytes); bytes = bytes &0xFFFC ;/* io in multiple of 4 bytes */ if (info->iomode ==OMAP_NAND_IO_WRITE ) {/* checks for write io */ if (irq_stat &0x2 )
@@ -545,8 +627,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, -PREFETCH_FIFOTHRESHOLD_MAX /2 ,0x0 , len,0x0 ); + ret =omap_prefetch_enable (info->gpmc_cs, +PREFETCH_FIFOTHRESHOLD_MAX /2 ,0x0 , len,0x0 , info);if (ret)/* PFPW engine is busy, use cpu copy method */ goto out_copy;
@@ -560,7 +642,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)wait_for_completion (&info->comp);/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (info->gpmc_cs); +omap_prefetch_reset (info->gpmc_cs, info);return ; out_copy:
@@ -583,6 +665,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, struct omap_nand_info, mtd);int ret =0 ;unsigned long tim, limit; +u32 val;if (len <= mtd->oobsize) {omap_write_buf_pref (mtd, buf, len);
@@ -594,8 +677,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,init_completion (&info->comp);/* configure and start prefetch transfer : size=24 */ - ret =gpmc_prefetch_enable (info->gpmc_cs, - (PREFETCH_FIFOTHRESHOLD_MAX *3 ) /8 ,0x0 , len,0x1 ); + ret =omap_prefetch_enable (info->gpmc_cs, + (PREFETCH_FIFOTHRESHOLD_MAX *3 ) /8 ,0x0 , len,0x1 , info);if (ret)/* PFPW engine is busy, use cpu copy method */ goto out_copy;
@@ -610,11 +693,14 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,/* wait for data to flushed-out before reset the prefetch */ tim =0 ; limit = (loops_per_jiffy *msecs_to_jiffies (OMAP_NAND_TIMEOUT_MS )); -while (gpmc_read_status (GPMC_PREFETCH_COUNT ) && (tim++ < limit)) +do { + val =readl (info->reg.gpmc_prefetch_status); + val =GPMC_PREFETCH_STATUS_COUNT (val);cpu_relax (); + }while (val && (tim++ < limit));/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (info->gpmc_cs); +omap_prefetch_reset (info->gpmc_cs, info);return ; out_copy:
@@ -854,7 +940,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); -return gpmc_calculate_ecc (info->gpmc_cs, dat, ecc_code); +u32 val; + + val =readl (info->reg.gpmc_ecc_config); +if (((val >>ECC_CONFIG_CS_SHIFT ) & ~CS_MASK ) != info->gpmc_cs) +return -EINVAL ; + +/* read ecc result */ + val =readl (info->reg.gpmc_ecc1_result); + *ecc_code++ = val;/* P128e, ..., P1e */ + *ecc_code++ = val >>16 ;/* P128o, ..., P1o */ +/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ + *ecc_code++ = ((val >>8 ) &0x0f ) | ((val >>20 ) &0xf0 ); + +return 0 ; }/**
@@ -868,8 +967,34 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) mtd);struct nand_chip *chip = mtd->priv;unsigned int dev_width = (chip->options &NAND_BUSWIDTH_16 ) ?1 :0 ; +u32 val; + +/* clear ecc and enable bits */ + val =ECCCLEAR |ECC1 ; +writel (val, info->reg.gpmc_ecc_control); + +/* program ecc and result sizes */ + val = ((((info->nand.ecc.size >>1 ) -1 ) <<ECCSIZE1_SHIFT ) | +ECC1RESULTSIZE ); +writel (val, info->reg.gpmc_ecc_size_config); + +switch (mode) { +case NAND_ECC_READ : +case NAND_ECC_WRITE : +writel (ECCCLEAR |ECC1 , info->reg.gpmc_ecc_control); +break ; +case NAND_ECC_READSYN : +writel (ECCCLEAR , info->reg.gpmc_ecc_control); +break ; +default : +dev_info (&info->pdev->dev, +"error: unrecognized Mode[%d]!\n" , mode); +break ; + } -gpmc_enable_hwecc (info->gpmc_cs, mode, dev_width, info->nand.ecc.size); +/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width <<7 ) | (info->gpmc_cs <<1 ) | (0x1 ); +writel (val, info->reg.gpmc_ecc_config); }/**
@@ -897,10 +1022,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)else timeo += (HZ *20 ) /1000 ; -gpmc_nand_write (info->gpmc_cs, -GPMC_NAND_COMMAND , (NAND_CMD_STATUS &0xFF )); +writeb (NAND_CMD_STATUS &0xFF , info->reg.gpmc_nand_command);while (time_before (jiffies, timeo)) { - status =gpmc_nand_read (info->gpmc_cs,GPMC_NAND_DATA ); + status =readb (info->reg.gpmc_nand_data);if (status &NAND_STATUS_READY )break ;cond_resched ();
@@ -920,22 +1044,13 @@ static int omap_dev_ready(struct mtd_info *mtd) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - val =gpmc_read_status (GPMC_GET_IRQ_STATUS ); + val =readl (info->reg.gpmc_status); +if ((val &0x100 ) ==0x100 ) { -/* Clear IRQ Interrupt */ - val |=0x100 ; - val &= ~(0x0 ); -gpmc_cs_configure (info->gpmc_cs,GPMC_SET_IRQ_STATUS , val); +return 1 ; }else { -unsigned int cnt =0 ; -while (cnt++ <0x1FF ) { -if ((val &0x100 ) ==0x100 ) -return 0 ; - val =gpmc_read_status (GPMC_GET_IRQ_STATUS ); - } +return 0 ; } - -return 1 ; }#ifdef CONFIG_MTD_NAND_OMAP_BCH
@@ -1184,6 +1299,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->gpmc_cs = pdata->cs; info->phys_base = pdata->phys_base; + info->reg = pdata->reg; info->mtd.priv = &info->nand; info->mtd.name =dev_name (&pdev->dev);
Signature · 1 line
1.7.10.2
PATCH v2 4/10 ARM: OMAP2+: gpmc-nand: update resource with memory
In reply to Afzal MohammedCurrently omap nand driver uses a field in platform data - phys_base for passing the address space allocated by gpmc for nand. Use struct resource instead. With this change omap nand driver has to get address space from memory resource.
This helps in smooth migration of gpmc to driver.
--- arch/arm/mach-omap2/gpmc-nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/gpmc-nand.c +3 -1
@@ -90,12 +90,14 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_nand_device.dev.platform_data = gpmc_nand_data; err =gpmc_cs_request (gpmc_nand_data->cs,NAND_IO_SIZE , - &gpmc_nand_data->phys_base); + (unsigned long *)&gpmc_nand_resource.start);if (err <0 ) {dev_err (dev,"Cannot request GPMC CS\n" );return err; } + gpmc_nand_resource.end = gpmc_nand_resource.start +NAND_IO_SIZE -1 ; +/* Set timings in GPMC */ err =omap2_nand_gpmc_retime (gpmc_nand_data);if (err <0 ) {
Signature · 1 line
1.7.10.2
PATCH v2 5/10 ARM: OMAP2+: gpmc-onenand: provide memory as resource
In reply to Afzal MohammedCurrently omap onenand driver invokes gpmc_cs_request, obtains address space allocated by gpmc to onenand. Remove this, instead use resource structure; this is now updated with address space for onenand by gpmc initialization with the help of gpmc_cs_request. And remove usage of gpmc_cs_request in onenand driver.
This helps in smooth migration of gpmc to driver.
--- arch/arm/mach-omap2/gpmc-onenand.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/gpmc-onenand.c +22 -1
@@ -23,11 +23,19 @@#include <plat/board.h> #include <plat/gpmc.h> +#define ONENAND_IO_SIZE SZ_128K +static struct omap_onenand_platform_data *gpmc_onenand_data; +static struct resource gpmc_onenand_resource = { + .flags =IORESOURCE_MEM , +}; +static struct platform_device gpmc_onenand_device = { .name ="omap2-onenand" , .id =-1 , + .num_resources =1 , + .resource = &gpmc_onenand_resource, };static int omap2_onenand_set_async_mode (int cs,void __iomem *onenand_base)
@@ -390,6 +398,8 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)void __init gpmc_onenand_init (struct omap_onenand_platform_data *_onenand_data) { +int err; + gpmc_onenand_data = _onenand_data; gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
@@ -401,8 +411,19 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) gpmc_onenand_data->flags |=ONENAND_SYNC_READ ; } + err =gpmc_cs_request (gpmc_onenand_data->cs,ONENAND_IO_SIZE , + (unsigned long *)&gpmc_onenand_resource.start); +if (err <0 ) { +pr_err ("%s: Cannot request GPMC CS\n" , __func__); +return ; + } + + gpmc_onenand_resource.end = gpmc_onenand_resource.start + +ONENAND_IO_SIZE -1 ; +if (platform_device_register (&gpmc_onenand_device) <0 ) { -printk (KERN_ERR "Unable to register OneNAND device\n" ); +pr_err ("%s: Unable to register OneNAND device\n" , __func__); +gpmc_cs_free (gpmc_onenand_data->cs);return ; } }
Signature · 1 line
1.7.10.2
PATCH v2 6/10 mtd: nand: omap2: obtain memory from resource
In reply to Afzal Mohammedgpmc initialization done by platform code now updates struct resource with the address space alloted for nand. Use this interface to obtain memory rather than relying on platform data field - phys_base.
--- arch/arm/plat-omap/include/plat/nand.h | 1 - drivers/mtd/nand/omap2.c | 19 +++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-)
arch/arm/plat-omap/include/plat/nand.h +0 -1
@@ -26,7 +26,6 @@ struct omap_nand_platform_data {bool dev_ready;int gpmc_irq;enum nand_io xfer_type; -unsigned long phys_base;int devsize;enum omap_ecc ecc_opt;struct gpmc_nand_regs reg;
drivers/mtd/nand/omap2.c +15 -4
@@ -132,6 +132,7 @@ struct omap_nand_info {int gpmc_cs;unsigned long phys_base; +unsigned long mem_size;struct completion comp;int dma_ch;int gpmc_irq;
@@ -1279,6 +1280,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)struct omap_nand_platform_data *pdata;int err;int i, offset; +struct resource *res; pdata = pdev->dev.platform_data;if (pdata ==NULL ) {
@@ -1298,7 +1300,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->phys_base = pdata->phys_base; info->reg = pdata->reg; info->mtd.priv = &info->nand;
@@ -1311,13 +1312,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)/* NAND write protect off */ gpmc_cs_configure (info->gpmc_cs,GPMC_CONFIG_WP ,0 ); -if (!request_mem_region (info->phys_base,NAND_IO_SIZE , + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (res ==NULL ) { + err = -EINVAL ; +dev_err (&pdev->dev,"error getting memory resource\n" ); + goto out_free_info; + } + + info->phys_base = res->start; + info->mem_size =resource_size (res); + +if (!request_mem_region (info->phys_base, info->mem_size, pdev->dev.driver->name)) { err = -EBUSY ; goto out_free_info; } - info->nand.IO_ADDR_R =ioremap (info->phys_base,NAND_IO_SIZE ); + info->nand.IO_ADDR_R =ioremap (info->phys_base, info->mem_size);if (!info->nand.IO_ADDR_R) { err = -ENOMEM ; goto out_release_mem_region;
@@ -1474,7 +1485,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)return 0 ; out_release_mem_region: -release_mem_region (info->phys_base,NAND_IO_SIZE ); +release_mem_region (info->phys_base, info->mem_size); out_free_info:kfree (info);
Signature · 1 line
1.7.10.2
PATCH v2 7/10 mtd: onenand: omap2: obtain memory from resource
In reply to Afzal Mohammedgpmc initialization for onenand done by platform code now provides onenand address space as memory resource. Hence remove usage of gpmc_cs_request in onenand driver and obtain memory details from resource structure.
--- drivers/mtd/onenand/omap2.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/mtd/onenand/omap2.c +16 -13
@@ -48,13 +48,13 @@#define DRIVER_NAME "omap2-onenand" -#define ONENAND_IO_SIZE SZ_128K#define ONENAND_BUFRAM_SIZE (1024 * 5)struct omap2_onenand {struct platform_device *pdev;int gpmc_cs;unsigned long phys_base; +unsigned int mem_size;int gpio_irq;struct mtd_info mtd;struct onenand_chip onenand;
@@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)struct omap2_onenand *c;struct onenand_chip *this;int r; +struct resource *res; pdata = pdev->dev.platform_data;if (pdata ==NULL ) {
@@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c->gpio_irq =0 ; } - r =gpmc_cs_request (c->gpmc_cs,ONENAND_IO_SIZE , &c->phys_base); -if (r <0 ) { -dev_err (&pdev->dev,"Cannot request GPMC CS\n" ); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (res ==NULL ) { + r = -EINVAL ; +dev_err (&pdev->dev,"error getting memory resource\n" ); goto err_kfree; } -if (request_mem_region (c->phys_base,ONENAND_IO_SIZE , + c->phys_base = res->start; + c->mem_size =resource_size (res); + +if (request_mem_region (c->phys_base, c->mem_size, pdev->dev.driver->name) ==NULL ) { -dev_err (&pdev->dev,"Cannot reserve memory region at 0x%08lx, " -"size: 0x%x\n" , c->phys_base,ONENAND_IO_SIZE ); +dev_err (&pdev->dev,"Cannot reserve memory region at 0x%08lx, size: 0x%x\n" , + c->phys_base, c->mem_size); r = -EBUSY ; - goto err_free_cs; + goto err_kfree; } - c->onenand.base =ioremap (c->phys_base,ONENAND_IO_SIZE ); + c->onenand.base =ioremap (c->phys_base, c->mem_size);if (c->onenand.base ==NULL ) { r = -ENOMEM ; goto err_release_mem_region;
@@ -776,9 +781,7 @@ err_release_gpio: err_iounmap:iounmap (c->onenand.base); err_release_mem_region: -release_mem_region (c->phys_base,ONENAND_IO_SIZE ); -err_free_cs: -gpmc_cs_free (c->gpmc_cs); +release_mem_region (c->phys_base, c->mem_size); err_kfree:kfree (c);
@@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)gpio_free (c->gpio_irq); }iounmap (c->onenand.base); -release_mem_region (c->phys_base,ONENAND_IO_SIZE ); +release_mem_region (c->phys_base, c->mem_size);gpmc_cs_free (c->gpmc_cs);kfree (c);
Signature · 1 line
1.7.10.2
PATCH v2 8/10 ARM: OMAP2+: gpmc: Modify interrupt handling
In reply to Afzal MohammedModify interrupt handling such that interrupts can be handled by GPMC client drivers using standard interrupt APIs rather than requiring the drivers to have knowledge about GPMC interrupt handling. Currently only NAND related interrupts has been considered (which is the case even without this change) as the only user of GPMC interrupt is NAND.
--- arch/arm/mach-omap2/gpmc.c | 136 ++++++++++++++++++++++++++++---- arch/arm/plat-omap/include/plat/gpmc.h | 1 + 2 files changed, 120 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/gpmc.c +119 -17
@@ -78,6 +78,15 @@#define ENABLE_PREFETCH (0x1 << 7)#define DMA_MPU_MODE 2 +/* XXX: Only NAND irq has been considered,currently these are the only ones used +*/ +#define GPMC_NR_IRQ 2 + +struct gpmc_client_irq { +unsigned irq; +u32 bitmask; +}; +/* Structure to save gpmc cs context */ struct gpmc_cs_config {u32 config1;
@@ -105,6 +114,10 @@ struct omap3_gpmc_regs {struct gpmc_cs_config cs_context[GPMC_CS_NUM ]; }; +static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ ]; +static struct irq_chip gpmc_irq_chip; +static unsigned gpmc_irq_start; +static struct resource gpmc_mem_root;static struct resource gpmc_cs_mem[GPMC_CS_NUM ];static DEFINE_SPINLOCK (gpmc_mem_lock);
@@ -702,6 +715,97 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) reg->gpmc_bch_result0 = gpmc_base +GPMC_ECC_BCH_RESULT_0 ; } +int gpmc_get_client_irq (unsigned irq_config) +{ +int i; + +if (hweight32 (irq_config) >1 ) +return 0 ; + +for (i =0 ; i <GPMC_NR_IRQ ; i++) +if (gpmc_client_irq[i].bitmask & irq_config) +return gpmc_client_irq[i].irq; + +return 0 ; +} + +static int gpmc_irq_endis (unsigned irq,bool endis) +{ +int i; +u32 regval; + +for (i =0 ; i <GPMC_NR_IRQ ; i++) +if (irq == gpmc_client_irq[i].irq) { + regval =gpmc_read_reg (GPMC_IRQENABLE ); +if (endis) + regval |= gpmc_client_irq[i].bitmask; +else + regval &= ~gpmc_client_irq[i].bitmask; +gpmc_write_reg (GPMC_IRQENABLE , regval); +break ; + } + +return 0 ; +} + +static void gpmc_irq_disable (struct irq_data *p) +{ +gpmc_irq_endis (p->irq, false); +} + +static void gpmc_irq_enable (struct irq_data *p) +{ +gpmc_irq_endis (p->irq, true); +} + +static void gpmc_irq_noop (struct irq_data *data) { } + +static unsigned int gpmc_irq_noop_ret (struct irq_data *data) {return 0 ; } + +static int gpmc_setup_irq (int gpmc_irq) +{ +int i; +u32 regval; + +if (!gpmc_irq) +return -EINVAL ; + + gpmc_irq_start =irq_alloc_descs (-1 ,0 ,GPMC_NR_IRQ ,0 ); +if (IS_ERR_VALUE (gpmc_irq_start)) { +pr_err ("irq_alloc_descs failed\n" ); +return gpmc_irq_start; + } + + gpmc_irq_chip.name ="gpmc" ; + gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; + gpmc_irq_chip.irq_enable = gpmc_irq_enable; + gpmc_irq_chip.irq_disable = gpmc_irq_disable; + gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; + gpmc_irq_chip.irq_ack = gpmc_irq_noop; + gpmc_irq_chip.irq_mask = gpmc_irq_noop; + gpmc_irq_chip.irq_unmask = gpmc_irq_noop; + + gpmc_client_irq[0 ].bitmask =GPMC_IRQ_FIFOEVENTENABLE ; + gpmc_client_irq[1 ].bitmask =GPMC_IRQ_COUNT_EVENT ; + +for (i =0 ; i <GPMC_NR_IRQ ; i++) { + gpmc_client_irq[i].irq = gpmc_irq_start + i; +irq_set_chip_and_handler (gpmc_client_irq[i].irq, + &gpmc_irq_chip, handle_simple_irq); +set_irq_flags (gpmc_client_irq[i].irq, +IRQF_VALID |IRQF_NOAUTOEN ); + } + +/* Disable interrupts */ +gpmc_write_reg (GPMC_IRQENABLE ,0 ); + +/* clear interrupts */ + regval =gpmc_read_reg (GPMC_IRQSTATUS ); +gpmc_write_reg (GPMC_IRQSTATUS , regval); + +return request_irq (gpmc_irq, gpmc_handle_irq,0 ,"gpmc" ,NULL ); +} +static void __init gpmc_mem_init (void ) {int cs;
@@ -731,8 +835,8 @@ static void __init gpmc_mem_init(void)static int __init gpmc_init (void ) { -u32 l, irq; -int cs, ret = -EINVAL ; +u32 l; +int ret = -EINVAL ;int gpmc_irq;char *ck =NULL ;
@@ -780,16 +884,7 @@ static int __init gpmc_init(void)gpmc_write_reg (GPMC_SYSCONFIG , l);gpmc_mem_init (); -/* initalize the irq_chained */ - irq =OMAP_GPMC_IRQ_BASE ; -for (cs =0 ; cs <GPMC_CS_NUM ; cs++) { -irq_set_chip_and_handler (irq, &dummy_irq_chip, - handle_simple_irq); -set_irq_flags (irq,IRQF_VALID ); - irq++; - } - - ret =request_irq (gpmc_irq, gpmc_handle_irq,IRQF_SHARED ,"gpmc" ,NULL ); + ret =gpmc_setup_irq (gpmc_irq);if (ret)pr_err ("gpmc: irq-%d could not claim: err %d\n" , gpmc_irq, ret);
@@ -799,12 +894,19 @@ postcore_initcall(gpmc_init);static irqreturn_t gpmc_handle_irq (int irq,void *dev) { -u8 cs; +int i; +u32 regval; + + regval =gpmc_read_reg (GPMC_IRQSTATUS ); + +if (!regval) +return IRQ_NONE ; + +for (i =0 ; i <GPMC_NR_IRQ ; i++) +if (regval & gpmc_client_irq[i].bitmask) +generic_handle_irq (gpmc_client_irq[i].irq); -/* check cs to invoke the irq */ - cs = ((gpmc_read_reg (GPMC_PREFETCH_CONFIG1 )) >>CS_NUM_SHIFT ) &0x7 ; -if (OMAP_GPMC_IRQ_BASE +cs <=OMAP_GPMC_IRQ_END ) -generic_handle_irq (OMAP_GPMC_IRQ_BASE +cs); +gpmc_write_reg (GPMC_IRQSTATUS , regval);return IRQ_HANDLED ; }
arch/arm/plat-omap/include/plat/gpmc.h +1 -0
@@ -150,6 +150,7 @@ struct gpmc_nand_regs { };extern void gpmc_update_nand_reg (struct gpmc_nand_regs *reg,int cs); +extern int gpmc_get_client_irq (unsigned irq_config);extern unsigned int gpmc_ns_to_ticks (unsigned int time_ns);extern unsigned int gpmc_ps_to_ticks (unsigned int time_ps);
Signature · 1 line
1.7.10.2
Re: [PATCH v2 08/10] ARM: OMAP2+: gpmc: Modify interrupt handling
arch/arm/mach-omap2/gpmc.c line 83
Quoted 3 lines · Afzal Mohammed
arch/arm/mach-omap2/gpmc.c +3
-0+/* XXX: Only NAND irq has been considered,currently these are the only ones used +*/ +#define GPMC_NR_IRQ 2
I guess "XXX" means "Warning"? Why not to use plain English? :-)
Signature · 2 lines
Best Regards, Artem Bityutskiy
RE: [PATCH v2 08/10] ARM: OMAP2+: gpmc: Modify interrupt handling
Hi Artem,
Quoted 6 lines · Artem Bityutskiy
arch/arm/mach-omap2/gpmc.c line 83
Quoted 3 lines · Afzal Mohammed
arch/arm/mach-omap2/gpmc.c +3
-0+/* XXX: Only NAND irq has been considered,currently these are the only ones used +*/ +#define GPMC_NR_IRQ 2I guess "XXX" means "Warning"? Why not to use plain English? :-)
It was made so that in editor (vim, maybe got biased towards it as I use it) it gets highlighted, do you want me to send an updated series ?
Regards
Afzal
RE: [PATCH v2 08/10] ARM: OMAP2+: gpmc: Modify interrupt handling
Quoted 4 lines · Afzal
Quoted 1 line
I guess "XXX" means "Warning"? Why not to use plain English? :-)
It was made so that in editor (vim, maybe got biased towards it as I use it) it gets highlighted, do you want me to send an updated series ?
No, thanks.
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH v2 9/10 ARM: OMAP2+: gpmc-nand: Modify Interrupt handling
In reply to Afzal MohammedNow GPMC provides its client with interrupts that can be handled using the standard interrupt API. Modify GPMC NAND setup to work with it.
Also disable write protect in GPMC code, so that NAND driver can be ignorant of GPMC configuration.
--- arch/arm/mach-omap2/gpmc-nand.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/gpmc-nand.c +20 -6
@@ -21,15 +21,23 @@#include <plat/board.h> #include <plat/gpmc.h> -static struct resource gpmc_nand_resource = { - .flags =IORESOURCE_MEM , +static struct resource gpmc_nand_resource[] = { + { + .flags =IORESOURCE_MEM , + }, + { + .flags =IORESOURCE_IRQ , + }, + { + .flags =IORESOURCE_IRQ , + }, };static struct platform_device gpmc_nand_device = { .name ="omap2-nand" , .id =0 , - .num_resources =1 , - .resource = &gpmc_nand_resource, + .num_resources =ARRAY_SIZE (gpmc_nand_resource), + .resource = gpmc_nand_resource, };static int omap2_nand_gpmc_retime (struct omap_nand_platform_data *gpmc_nand_data)
@@ -75,6 +83,7 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_datagpmc_cs_configure (gpmc_nand_data->cs,GPMC_CONFIG_DEV_SIZE ,0 );gpmc_cs_configure (gpmc_nand_data->cs,GPMC_CONFIG_DEV_TYPE ,GPMC_DEVICETYPE_NAND ); +gpmc_cs_configure (gpmc_nand_data->cs,GPMC_CONFIG_WP ,0 ); err =gpmc_cs_set_timings (gpmc_nand_data->cs, &t);if (err)return err;
@@ -90,14 +99,19 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_nand_device.dev.platform_data = gpmc_nand_data; err =gpmc_cs_request (gpmc_nand_data->cs,NAND_IO_SIZE , - (unsigned long *)&gpmc_nand_resource.start); + (unsigned long *)&gpmc_nand_resource[0 ].start);if (err <0 ) {dev_err (dev,"Cannot request GPMC CS\n" );return err; } - gpmc_nand_resource.end = gpmc_nand_resource.start +NAND_IO_SIZE -1 ; + gpmc_nand_resource[0 ].end = gpmc_nand_resource[0 ].start + +NAND_IO_SIZE -1 ; + gpmc_nand_resource[1 ].start = +gpmc_get_client_irq (GPMC_IRQ_FIFOEVENTENABLE ); + gpmc_nand_resource[2 ].start = +gpmc_get_client_irq (GPMC_IRQ_COUNT_EVENT );/* Set timings in GPMC */ err =omap2_nand_gpmc_retime (gpmc_nand_data);if (err <0 ) {
Signature · 1 line
1.7.10.2
PATCH v2 10/10 mtd: nand: omap2: use gpmc provided irqs
In reply to Afzal MohammedGPMC platform initialization provides it's clients with interrupts that can be used through struct resource. Make use of it for irq mode functionality.
Also now write protect disable is done by GPMC,
hence remove it.
--- drivers/mtd/nand/omap2.c | 70 +++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 28 deletions(-)
drivers/mtd/nand/omap2.c +42 -28
@@ -135,7 +135,8 @@ struct omap_nand_info {unsigned long mem_size;struct completion comp;int dma_ch; -int gpmc_irq; +int gpmc_irq_fifo; +int gpmc_irq_count;enum {OMAP_NAND_IO_READ =0 ,/* read */ OMAP_NAND_IO_WRITE ,/* write */
@@ -564,14 +565,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) {struct omap_nand_info *info = (struct omap_nand_info *) dev;u32 bytes; -u32 irq_stat; - irq_stat =gpmc_read_status (GPMC_GET_IRQ_STATUS ); bytes =readl (info->reg.gpmc_prefetch_status); bytes =GPMC_PREFETCH_STATUS_FIFO_CNT (bytes); bytes = bytes &0xFFFC ;/* io in multiple of 4 bytes */ if (info->iomode ==OMAP_NAND_IO_WRITE ) {/* checks for write io */ -if (irq_stat &0x2 ) +if (this_irq == info->gpmc_irq_count) goto done;if (info->buf_len && (info->buf_len < bytes))
@@ -588,20 +587,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) (u32 *)info->buf, bytes >> 2); info->buf = info->buf + bytes; -if (irq_stat &0x2 ) +if (this_irq == info->gpmc_irq_count) goto done; } -gpmc_cs_configure (info->gpmc_cs,GPMC_SET_IRQ_STATUS , irq_stat);return IRQ_HANDLED ; done:complete (&info->comp); -/* disable irq */ -gpmc_cs_configure (info->gpmc_cs,GPMC_ENABLE_IRQ ,0 ); -/* clear status */ -gpmc_cs_configure (info->gpmc_cs,GPMC_SET_IRQ_STATUS , irq_stat); +disable_irq_nosync (info->gpmc_irq_fifo); +disable_irq_nosync (info->gpmc_irq_count);return IRQ_HANDLED ; }
@@ -635,9 +631,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) goto out_copy; info->buf_len = len; -/* enable irq */ -gpmc_cs_configure (info->gpmc_cs,GPMC_ENABLE_IRQ , - (GPMC_IRQ_FIFOEVENTENABLE |GPMC_IRQ_COUNT_EVENT )); + +enable_irq (info->gpmc_irq_count); +enable_irq (info->gpmc_irq_fifo);/* waiting for read to complete */ wait_for_completion (&info->comp);
@@ -685,12 +681,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, goto out_copy; info->buf_len = len; -/* enable irq */ -gpmc_cs_configure (info->gpmc_cs,GPMC_ENABLE_IRQ , - (GPMC_IRQ_FIFOEVENTENABLE |GPMC_IRQ_COUNT_EVENT )); + +enable_irq (info->gpmc_irq_count); +enable_irq (info->gpmc_irq_fifo);/* waiting for write to complete */ wait_for_completion (&info->comp); +/* wait for data to flushed-out before reset the prefetch */ tim =0 ; limit = (loops_per_jiffy *msecs_to_jiffies (OMAP_NAND_TIMEOUT_MS ));
@@ -1309,9 +1306,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.options = pdata->devsize; info->nand.options |=NAND_SKIP_BBTSCAN ; -/* NAND write protect off */ -gpmc_cs_configure (info->gpmc_cs,GPMC_CONFIG_WP ,0 ); - res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (res ==NULL ) { err = -EINVAL ;
@@ -1334,6 +1328,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } + info->gpmc_irq_fifo =platform_get_irq (pdev,0 ); +if (info->gpmc_irq_fifo == -ENXIO ) +dev_warn (&pdev->dev,"error getting FIFO IRQ\n" ); + + info->gpmc_irq_count =platform_get_irq (pdev,1 ); +if (info->gpmc_irq_count == -ENXIO ) +dev_warn (&pdev->dev,"error getting TERMINALCOUNT IRQ\n" ); + info->nand.controller = &info->controller; info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
@@ -1389,17 +1391,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)break ;case NAND_OMAP_PREFETCH_IRQ : - err =request_irq (pdata->gpmc_irq, - omap_nand_irq,IRQF_SHARED ,"gpmc-nand" , info); + err =request_irq (info->gpmc_irq_fifo, omap_nand_irq, +IRQF_SHARED ,"gpmc-nand-fifo" , info);if (err) {dev_err (&pdev->dev,"requesting irq(%d) error:%d" , - pdata->gpmc_irq, err); + info->gpmc_irq_fifo, err); goto out_release_mem_region; - }else { - info->gpmc_irq = pdata->gpmc_irq; - info->nand.read_buf = omap_read_buf_irq_pref; - info->nand.write_buf = omap_write_buf_irq_pref; } + err =request_irq (info->gpmc_irq_count, omap_nand_irq, +IRQF_SHARED ,"gpmc-nand-count" , info); +if (err) { +dev_err (&pdev->dev,"requesting irq(%d) error:%d" , + info->gpmc_irq_count, err); + goto out_free_irq_gpmc_fifo; + } + + info->nand.read_buf = omap_read_buf_irq_pref; + info->nand.write_buf = omap_write_buf_irq_pref; +break ;default :
@@ -1484,6 +1493,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)return 0 ; +out_free_irq_gpmc_fifo: +free_irq (info->gpmc_irq_fifo, info); out_release_mem_region:release_mem_region (info->phys_base, info->mem_size); out_free_info:
@@ -1503,8 +1514,11 @@ static int omap_nand_remove(struct platform_device *pdev)if (info->dma_ch !=-1 )omap_free_dma (info->dma_ch); -if (info->gpmc_irq) -free_irq (info->gpmc_irq, info); +if (info->gpmc_irq_fifo >0 ) +free_irq (info->gpmc_irq_fifo, info); + +if (info->gpmc_irq_count >0 ) +free_irq (info->gpmc_irq_count, info);/* Release NAND device, its internal structures and partitions */ nand_release (&info->mtd);
Signature · 1 line
1.7.10.2
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/
Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
Hi Artem,
Quoted 11 lines · Artem Bityutskiy
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Acked-by Artem Bityutskiy <[email protected]>
Thanks
Afzal
Tony Lindgren
maintainerQuoted 11 lines · Artem Bityutskiy
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Acked-by Artem Bityutskiy <[email protected]>
Thanks will add to the drivers/mtd touching patches in this series.
Tony
Hi Tony,
Quoted 7 lines · Tony Lindgren
Quoted 6 lines · Artem Bityutskiy
Quoted 3 lines · Afzal Mohammed
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/
Quoted 6 lines
Quoted 4 lines
Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Acked-by Artem Bityutskiy <[email protected]>Thanks will add to the
drivers/mtdtouching patches in this series.
Can you please consider this series for inclusion in the coming merge window. This series can live by itself and is not dependent on any other patches.
Regards
Afzal
Tony Lindgren
maintainerQuoted 13 lines · Mohammed, Afzal
Hi Tony,
Quoted 10 lines · Tony Lindgren
Quoted 9 lines · Artem Bityutskiy
Quoted 3 lines · Afzal Mohammed
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Acked-by Artem Bityutskiy <[email protected]>Thanks will add to the
drivers/mtdtouching patches in this series.Can you please consider this series for inclusion in the coming merge window. This series can live by itself and is not dependent on any other patches.
Yes I have some of the gpmc patches applied locally on top of the dmaengine changes from Russell. Will update and push out once we have an immutable commit for the dmaengine changes available.
Regards,
Tony
I've requested several times to remove my e-mail from that list. I'll report it to legal authorities on this issue if no action is taken.
William.
Quoted 29 lines · Mohammed, Afzal
Quoted 8 lines
Hi Tony,
Quoted 5 lines · Tony Lindgren
Quoted 4 lines · Artem Bityutskiy
Quoted 3 lines · Afzal Mohammed
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/Quoted 8 lines
Quoted 5 lines
Quoted 4 lines
Dunno if Tony picked this, but the MTD changes look good an the quick glance. Feel free to add
Acked-by Artem Bityutskiy<[email protected]>Thanks will add to the
drivers/mtdtouching patches in this series.Can you please consider this series for inclusion in the coming merge window. This series can live by itself and is not dependent on any other patches.
Yes I have some of the gpmc patches applied locally on top of the dmaengine changes from Russell. Will update and push out once we have an immutable commit for the dmaengine changes available.
Regards,
Tony
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
Quoted 2 lines · William F.
I've requested several times to remove my e-mail from that list. I'll report it to legal authorities on this issue if no action is taken.
Have you tried following the link at the bottom of every mail you receive from the list, and following the 'To unsubscribe from linux-mtd' instructions you find there?
I'll report it to stupidity authorities on this issue if no such action is taken :)
Signature · 1 line
dwmw2
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/
BTW, be aware that Russel King patched the omap2.c file in patch series which switches to the DMA engine, so I expect conflicts. You can check his tree, I guess. The subjects were:
[CFT 09/11] mtd: omap2: add DMA engine support
[CFT 10/11] mtd: omap2: remove private DMA API implementation
Signature · 2 lines
Best Regards, Artem Bityutskiy
Hi Artem,
Quoted 7 lines · Artem Bityutskiy
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/
Quoted 6 lines
BTW, be aware that Russel King patched the
omap2.cfile in patch series which switches to the DMA engine, so I expect conflicts. You can check his tree, I guess. The subjects were:[CFT 09/11] mtd: omap2: add DMA engine support
[CFT 10/11] mtd: omap2: remove private DMA API implementation
Thanks for the information.
Hi Tony,
We have Artem's ack on MTD changes in this series, please let me know whether I need to do anything more to get this series picked up in your tree.
Regards
Afzal
Tony Lindgren
maintainerQuoted 18 lines · Mohammed, Afzal
Hi Artem,
Quoted 7 lines · Artem Bityutskiy
Quoted 5 lines · Afzal Mohammed
Hi,
This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of
arch/arm/*omap*/Quoted 6 lines
BTW, be aware that Russel King patched the
omap2.cfile in patch series which switches to the DMA engine, so I expect conflicts. You can check his tree, I guess. The subjects were:[CFT 09/11] mtd: omap2: add DMA engine support
[CFT 10/11] mtd: omap2: remove private DMA API implementation
Quoted 6 lines
Thanks for the information.
Hi Tony,
We have Artem's ack on MTD changes in this series, please let me know whether I need to do anything more to get this series picked up in your tree.
This series looks OK to me. As the second series still has at least one issue, let's wait a little bit on applying these so we have an immutable commit from Russell on the DMA changes.
Regards,
Tony