omap3 nand: cleanup exiting platform related code
Subsystems (7)
v7 cover omap3 nand: cleanup exiting platform related code
The following set of patches applies on top of for-next branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly.
Discussion: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg27630.html
No code change from previous version.
Looping linux-arm-kernel mailing list with new version.
Changes in this series -
gpmc_hwcontrol() function in gpmc.c, break into various small function.
v6: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg31936.html
Unused function removed.
v5: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg30305.html
Functions related to ecc and prefetch engine are optimized.
v4: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg29458.html
Few functionality was missing like - There should be some locking as only
one chipselect can use the ECC or prefetch engine at a time. If you have NAND in two chipselects, bad things would happen.
v3: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28715.html
Additionally, it was needed to implement more functions for the platform init code to use.
v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28467.html
v1: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28164.html
Sukumar Ghorai (3):
omap3 gpmc: functionality enhancement omap3 nand: cleanup virtual address usages omap3 nand: fix issue in board file to detect nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +-- arch/arm/mach-omap2/board-devkit8000.c | 25 +--- arch/arm/mach-omap2/board-omap3beagle.c | 24 +--- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +--- arch/arm/mach-omap2/board-overo.c | 24 +--- arch/arm/mach-omap2/board-sdp-flash.c | 5 - arch/arm/mach-omap2/gpmc-nand.c | 38 +--- arch/arm/mach-omap2/gpmc.c | 285 ++++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/gpmc.h | 42 ++++- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 218 ++++++---------------- 11 files changed, 371 insertions(+), 341 deletions(-)
PATCH v7 1/3 omap3 gpmc: functionality enhancement
few functions added in gpmc module and to be used by other drivers like NAND.
--- arch/arm/mach-omap2/gpmc.c | 276 ++++++++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/gpmc.h | 39 ++++- drivers/mtd/nand/omap2.c | 4 +- 3 files changed, 302 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/gpmc.c +264 -12
@@ -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_OFFSET 0x60#define GPMC_CS_SIZE 0x30#define GPMC_MEM_START 0x00000000
@@ -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 unsigned gpmc_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_OFFSET + (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_OFFSET + (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_OFFSET + (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_OFFSET + (cs *GPMC_CS_SIZE ) + idx;return __raw_readl (reg_addr); }
@@ -419,8 +437,157 @@ void gpmc_cs_free(int cs)EXPORT_SYMBOL (gpmc_cs_free);/** +* gpmc_read_status - read access request to get the different gpmc status +* @cmd: command type +* @return status +*/ +int gpmc_read_status (int cmd) +{ +int status = -EINVAL ; +u32 regval =0 ; + +switch (cmd) { +case GPMC_GET_IRQ_STATUS : + status =gpmc_read_reg (GPMC_IRQSTATUS ); +break ; + +case GPMC_PREFETCH_FIFO_CNT : + regval =gpmc_read_reg (GPMC_PREFETCH_STATUS ); + status =GPMC_PREFETCH_STATUS_FIFO_CNT (regval); +break ; + +case GPMC_PREFETCH_COUNT : + regval =gpmc_read_reg (GPMC_PREFETCH_STATUS ); + status =GPMC_PREFETCH_STATUS_COUNT (regval); +break ; + +case GPMC_STATUS_BUFFER : + regval =gpmc_read_reg (GPMC_STATUS ); +/* 1 : buffer is available to write */ + status = regval &GPMC_STATUS_BUFF_EMPTY ; +break ; + +default : +printk (KERN_ERR "gpmc_read_status: Not supported\n" ); + } +return status; +} +EXPORT_SYMBOL (gpmc_read_status); + +/** +* gpmc_cs_configure - write request to configure gpmc +* @cs: chip select number +* @cmd: command type +* @wval: value to write +* @return status of the operation +*/ +int gpmc_cs_configure (int cs,int cmd,int wval) +{ +int err =0 ; +u32 regval =0 ; + +switch (cmd) { +case GPMC_SET_IRQ_STATUS : +gpmc_write_reg (GPMC_IRQSTATUS , wval); +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 ); +if (wval) + regval |=WR_RD_PIN_MONITORING ; +else + 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 ; + +default : +printk (KERN_ERR "gpmc_configure_cs: Not supported\n" ); + err = -EINVAL ; + } + +return err; +} +EXPORT_SYMBOL (gpmc_cs_configure); + +/** +* gpmc_nand_read - nand specific read access request +* @cs: chip select number +* @cmd: command type +*/ +int gpmc_nand_read (int cs,int cmd) +{ +int rval = -EINVAL ; + +switch (cmd) { +case GPMC_NAND_DATA : + rval =gpmc_cs_read_byte (cs,GPMC_CS_NAND_DATA ); +break ; + +default : +printk (KERN_ERR "gpmc_read_nand_ctrl: Not supported\n" ); + } +return rval; +} +EXPORT_SYMBOL (gpmc_nand_read); + +/** +* gpmc_nand_write - nand specific write request +* @cs: chip select number +* @cmd: command type +* @wval: value to write +*/ +int gpmc_nand_write (int cs,int cmd,int wval) +{ +int err =0 ; + +switch (cmd) { +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 : +gpmc_cs_write_byte (cs,GPMC_CS_NAND_DATA , wval); + +default : +printk (KERN_ERR "gpmc_write_nand_ctrl: Not supported\n" ); + err = -EINVAL ; + } +return err; +} +EXPORT_SYMBOL (gpmc_nand_write); + + + +/** * gpmc_prefetch_enable - configures and starts prefetch transfer -* @cs: nand cs (chip select) number +* @cs: cs (chip select) number * @dma_mode: dma mode enable (1) or disable (0) * @u32_count: number of bytes to be transferred * @is_write: prefetch read(0) or write post(1) mode
@@ -428,7 +595,6 @@ EXPORT_SYMBOL(gpmc_cs_free);int gpmc_prefetch_enable (int cs,int dma_mode,unsigned int u32_count,int is_write) { -uint32_t prefetch_config1;if (!(gpmc_read_reg (GPMC_PREFETCH_CONTROL ))) {/* Set the amount of bytes to be prefetched */
@@ -437,17 +603,17 @@ int gpmc_prefetch_enable(int cs, int dma_mode,/* Set dma/mpu mode, the prefetch read / post write and * enable the engine. Set which cs is has requested for. */ - prefetch_config1 = ((cs <<CS_NUM_SHIFT ) | +gpmc_write_reg (GPMC_PREFETCH_CONFIG1 , ((cs <<CS_NUM_SHIFT ) |PREFETCH_FIFOTHRESHOLD |ENABLE_PREFETCH | (dma_mode <<DMA_MPU_MODE ) | - (0x1 & is_write)); -gpmc_write_reg (GPMC_PREFETCH_CONFIG1 , prefetch_config1); + (0x1 & is_write))); + +/* Start the prefetch engine */ +gpmc_write_reg (GPMC_PREFETCH_CONTROL ,0x1 ); }else {return -EBUSY ; } -/* Start the prefetch engine */ -gpmc_write_reg (GPMC_PREFETCH_CONTROL ,0x1 );return 0 ; }
@@ -456,13 +622,22 @@ 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) { +u32 config1; + +/* check if the same module/cs is trying to reset */ + config1 =gpmc_read_reg (GPMC_PREFETCH_CONFIG1 ); +if (((config1 >>CS_NUM_SHIFT ) &0x7 ) != cs) +return -EINVAL ; +/* Stop the PFPW engine */ gpmc_write_reg (GPMC_PREFETCH_CONTROL ,0x0 );/* Reset/disable the PFPW engine */ gpmc_write_reg (GPMC_PREFETCH_CONFIG1 ,0x0 ); + +return 0 ; }EXPORT_SYMBOL (gpmc_prefetch_reset);
@@ -615,3 +790,80 @@ void omap3_gpmc_restore_context(void) } }#endif /* CONFIG_ARCH_OMAP3 */ + +/** +* gpmc_enable_hwecc - enable hardware ecc functionality +* @cs: chip select number +* @mode: read/write mode +* @dev_width: device bus width(1 for x16, 0 for x8) +* @ecc_size: bytes for which ECC will be generated +*/ +int gpmc_enable_hwecc (int cs,int mode,int dev_width,int ecc_size) +{ +unsigned int val; + +/* check if ecc module is in used */ +if (gpmc_ecc_used != -EINVAL ) +return -EINVAL ; + + gpmc_ecc_used = cs; + +/* clear ecc and enable bits */ + val = ((0x00000001 <<8 ) |0x00000001 ); +gpmc_write_reg (GPMC_ECC_CONTROL , val); + +/* program ecc and result sizes */ + val = ((((ecc_size >>1 ) -1 ) <<22 ) | (0x0000000F )); +gpmc_write_reg (GPMC_ECC_SIZE_CONFIG , val); + +switch (mode) { +case GPMC_ECC_READ : +gpmc_write_reg (GPMC_ECC_CONTROL ,0x101 ); +break ; +case GPMC_ECC_READSYN : +gpmc_write_reg (GPMC_ECC_CONTROL ,0x100 ); +break ; +case GPMC_ECC_WRITE : +gpmc_write_reg (GPMC_ECC_CONTROL ,0x101 ); +break ; +default : +printk (KERN_INFO "Error: Unrecognized Mode[%d]!\n" , mode); +break ; + } + +/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width <<7 ) | (cs <<1 ) | (0x1 ); +gpmc_write_reg (GPMC_ECC_CONFIG , val); +return 0 ; +} + +/** +* gpmc_calculate_ecc - generate non-inverted ecc bytes +* @cs: chip select number +* @dat: data pointer over which ecc is computed +* @ecc_code: ecc code buffer +* +* Using non-inverted ECC is considered ugly since writing a blank +* page (padding) will clear the ECC bytes. This is not a problem as long +* no one is trying to write data on the seemingly unused page. Reading +* an erased page will produce an ECC mismatch between generated and read +* ECC bytes that has to be dealt with separately. +*/ +int gpmc_calculate_ecc (int cs,const u_char *dat,u_char *ecc_code) +{ +unsigned int val =0x0 ; + +if (gpmc_ecc_used != cs) +return -EINVAL ; + +/* read ecc result */ + val =gpmc_read_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 ); + + gpmc_ecc_used = -EINVAL ; +return 0 ; +} +
arch/arm/plat-omap/include/plat/gpmc.h +36 -3
@@ -27,8 +27,27 @@#define GPMC_CONFIG 0x50#define GPMC_STATUS 0x54 -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 + +/* Control Commands */ +#define GPMC_CONFIG_RDY_BSY 0x00000001 +#define GPMC_CONFIG_DEV_SIZE 0x00000002 +#define GPMC_CONFIG_DEV_TYPE 0x00000003 +#define GPMC_SET_IRQ_STATUS 0x00000004 +#define GPMC_CONFIG_WP 0x00000005 + +#define GPMC_GET_IRQ_STATUS 0x00000006 +#define GPMC_PREFETCH_FIFO_CNT 0x00000007/* bytes available in FIFO for r/w */ +#define GPMC_PREFETCH_COUNT 0x00000008/* remaining bytes to be read/write*/ +#define GPMC_STATUS_BUFFER 0x00000009/* 1: buffer is available to write */ + +#define GPMC_NAND_COMMAND 0x0000000a +#define GPMC_NAND_ADDRESS 0x0000000b +#define GPMC_NAND_DATA 0x0000000c + +/* ECC commands */ +#define GPMC_ECC_READ 0/* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1/* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2/* Reset before syndrom is read back */ #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -56,6 +75,14 @@#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))#define GPMC_CONFIG7_CSVALID (1 << 6) +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 +#define WR_RD_PIN_MONITORING 0x00600000 +#define GPMC_PREFETCH_STATUS_FIFO_CNT (val) ((val >> 24) & 0x7F) +#define GPMC_PREFETCH_STATUS_COUNT (val) (val & 0x00003fff) +/* * Note that all values in this struct are in nanoseconds, while * the register values are in gpmc_fck cycles.
@@ -108,10 +135,16 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);extern int gpmc_cs_reserved (int cs);extern int gpmc_prefetch_enable (int cs,int dma_mode,unsigned int u32_count,int is_write); -extern void gpmc_prefetch_reset (void ); +extern int gpmc_prefetch_reset (int cs);extern int gpmc_prefetch_status (void );extern void omap3_gpmc_save_context (void );extern void omap3_gpmc_restore_context (void );extern void gpmc_init (void ); +extern int gpmc_read_status (int cmd); +extern int gpmc_cs_configure (int cs,int cmd,int wval); +extern int gpmc_nand_read (int cs,int cmd); +extern int gpmc_nand_write (int cs,int cmd,int wval); +int gpmc_enable_hwecc (int cs,int mode,int dev_width,int ecc_size); +int gpmc_calculate_ecc (int cs,const u_char *dat,u_char *ecc_code);#endif
drivers/mtd/nand/omap2.c +2 -2
@@ -319,7 +319,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) }while (len);/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (); +gpmc_prefetch_reset (info->gpmc_cs); } }
@@ -363,7 +363,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, }/* disable and stop the PFPW engine */ -gpmc_prefetch_reset (); +gpmc_prefetch_reset (info->gpmc_cs); } }
PATCH v7 2/3 omap3 nand: cleanup virtual address usages
This patch removes direct reference of gpmc address from generic nand platform code. Nand platform code now uses wrapper functions which are implemented in gpmc module.
--- arch/arm/mach-omap2/gpmc-nand.c | 38 ++---- arch/arm/mach-omap2/gpmc.c | 9 -- arch/arm/plat-omap/include/plat/gpmc.h | 5 - arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 214 ++++++++------------------------ 5 files changed, 65 insertions(+), 207 deletions(-)
arch/arm/mach-omap2/gpmc-nand.c +10 -28
@@ -19,8 +19,6 @@#include <plat/board.h> #include <plat/gpmc.h> -#define WR_RD_PIN_MONITORING 0x00600000 -static struct omap_nand_platform_data *gpmc_nand_data;static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void) t.wr_cycle =gpmc_round_ns_to_ticks (gpmc_nand_data->gpmc_t->wr_cycle);/* Configure GPMC */ -gpmc_cs_write_reg (gpmc_nand_data->cs,GPMC_CS_CONFIG1 , -GPMC_CONFIG1_DEVICESIZE (gpmc_nand_data->devsize) | -GPMC_CONFIG1_DEVICETYPE_NAND ); - +gpmc_cs_configure (gpmc_nand_data->cs, +GPMC_CONFIG_DEV_SIZE , gpmc_nand_data->devsize); +gpmc_cs_configure (gpmc_nand_data->cs, +GPMC_CONFIG_DEV_TYPE ,GPMC_DEVICETYPE_NAND ); err =gpmc_cs_set_timings (gpmc_nand_data->cs, &t);if (err)return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)return 0 ; } -static int gpmc_nand_setup (void ) -{ -struct device *dev = &gpmc_nand_device.dev; - -/* Set timings in GPMC */ -if (omap2_nand_gpmc_retime () <0 ) { -dev_err (dev,"Unable to set gpmc timings\n" ); -return -EINVAL ; - } - -return 0 ; -} -int __init gpmc_nand_init (struct omap_nand_platform_data *_nand_data) { -unsigned int val;int err =0 ;struct device *dev = &gpmc_nand_device.dev; gpmc_nand_data = _nand_data; - gpmc_nand_data->nand_setup = gpmc_nand_setup; + gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime; gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,16 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)return err; } - err =gpmc_nand_setup (); +/* Set timings in GPMC */ + err =omap2_nand_gpmc_retime ();if (err <0 ) { -dev_err (dev,"NAND platform setup failed: %d\n" , err); +dev_err (dev,"Unable to set gpmc timings: %d\n" , err);return err; }/* Enable RD PIN Monitoring Reg */ if (gpmc_nand_data->dev_ready) { - val =gpmc_cs_read_reg (gpmc_nand_data->cs, -GPMC_CS_CONFIG1 ); - val |=WR_RD_PIN_MONITORING ; -gpmc_cs_write_reg (gpmc_nand_data->cs, -GPMC_CS_CONFIG1 , val); +gpmc_cs_configure (gpmc_nand_data->cs,GPMC_CONFIG_RDY_BSY ,1 ); } err =platform_device_register (&gpmc_nand_device);
@@ -140,3 +121,4 @@ out_free_cs:return err; } +
arch/arm/mach-omap2/gpmc.c +0 -9
@@ -641,15 +641,6 @@ int gpmc_prefetch_reset(int cs) }EXPORT_SYMBOL (gpmc_prefetch_reset); -/** -* gpmc_prefetch_status - reads prefetch status of engine -*/ -int gpmc_prefetch_status (void ) -{ -return gpmc_read_reg (GPMC_PREFETCH_STATUS ); -} -EXPORT_SYMBOL (gpmc_prefetch_status); -static void __init gpmc_mem_init (void ) {int cs;
arch/arm/plat-omap/include/plat/gpmc.h +0 -5
@@ -25,9 +25,6 @@#define GPMC_CS_NAND_ADDRESS 0x20#define GPMC_CS_NAND_DATA 0x24 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 -/* Control Commands */ #define GPMC_CONFIG_RDY_BSY 0x00000001#define GPMC_CONFIG_DEV_SIZE 0x00000002
@@ -66,7 +63,6 @@#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)#define GPMC_CONFIG1_DEVICETYPE (val) ((val & 3) << 10)#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)#define GPMC_CONFIG1_MUXADDDATA (1 << 9)#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)#define GPMC_CONFIG1_FCLK_DIV (val) (val & 3)
@@ -136,7 +132,6 @@ extern int gpmc_cs_reserved(int cs);extern int gpmc_prefetch_enable (int cs,int dma_mode,unsigned int u32_count,int is_write);extern int gpmc_prefetch_reset (int cs); -extern int gpmc_prefetch_status (void );extern void omap3_gpmc_save_context (void );extern void omap3_gpmc_restore_context (void );extern void gpmc_init (void );
arch/arm/plat-omap/include/plat/nand.h +2 -4
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {int (*dev_ready)(struct omap_nand_platform_data *);int dma_channel;unsigned long phys_base; -void __iomem *gpmc_cs_baseaddr; -void __iomem *gpmc_baseaddr;int devsize; }; -/* size (4 KiB) for IO mapping */ -#define NAND_IO_SIZE SZ_4K +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4#if defined(CONFIG_MTD_NAND_OMAP2 ) || defined(CONFIG_MTD_NAND_OMAP2_MODULE )extern int gpmc_nand_init (struct omap_nand_platform_data *d);
drivers/mtd/nand/omap2.c +53 -161
381 lines not on this page · raw message
PATCH v7 3/3 omap3 nand: fix issue in board file to detect nand
Board file modified for not to provide gpmc phys_base address to nand driver. The gpmc_nand_init funciton is now used to detect the nand and required to adopt _prob function as in nand/omap2.c
--- arch/arm/mach-omap2/board-cm-t35.c | 20 +------------------- arch/arm/mach-omap2/board-devkit8000.c | 25 +------------------------ arch/arm/mach-omap2/board-omap3beagle.c | 24 +----------------------- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------------------------ arch/arm/mach-omap2/board-overo.c | 24 +----------------------- arch/arm/mach-omap2/board-sdp-flash.c | 5 ----- 6 files changed, 5 insertions(+), 118 deletions(-)
arch/arm/mach-omap2/board-cm-t35.c +1 -19
@@ -61,8 +61,6 @@#define SB_T35_SMSC911X_GPIO 65#define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)#if defined(CONFIG_SMSC911X ) || defined(CONFIG_SMSC911X_MODULE )#include <linux/smsc911x.h>
@@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = { .nr_parts = ARRAY_SIZE(cm_t35_nand_partitions), .dma_channel = -1, /* disable DMA in OMAP NAND driver */ .cs = 0, - .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR, - .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT, }; -static struct resource cm_t35_nand_resource = { - .flags =IORESOURCE_MEM , -}; - -static struct platform_device cm_t35_nand_device = { - .name ="omap2-nand" , - .id =-1 , - .num_resources =1 , - .resource = &cm_t35_nand_resource, - .dev = { - .platform_data = &cm_t35_nand_data, - }, -}; -static void __init cm_t35_init_nand (void ) { -if (platform_device_register (&cm_t35_nand_device) <0 ) +if (gpmc_nand_init (&cm_t35_nand_data) <0 )pr_err ("CM-T35: Unable to register NAND device\n" ); }#else
arch/arm/mach-omap2/board-devkit8000.c +1 -24
@@ -59,9 +59,6 @@#include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 -#define NAND_BLOCK_SIZE SZ_128K#define OMAP_DM9000_GPIO_IRQ 25
@@ -105,20 +102,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource devkit8000_nand_resource = { - .flags =IORESOURCE_MEM , -}; - -static struct platform_device devkit8000_nand_device = { - .name ="omap2-nand" , - .id =-1 , - .dev = { - .platform_data = &devkit8000_nand_data, - }, - .num_resources =1 , - .resource = &devkit8000_nand_resource, -}; -static struct omap2_hsmmc_info mmc[] = { { .mmc =1 ,
@@ -591,8 +574,6 @@ static void __init devkit8000_flash_init(void)u8 cs =0 ;u8 nandcs =GPMC_CS_NUM +1 ; -u32 gpmc_base_add =OMAP34XX_GPMC_VIRT ; -/* find out the chip-select on which NAND exists */ while (cs <GPMC_CS_NUM ) {u32 ret =0 ;
@@ -614,13 +595,9 @@ static void __init devkit8000_flash_init(void)if (nandcs <GPMC_CS_NUM ) { devkit8000_nand_data.cs = nandcs; - devkit8000_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add +GPMC_CS0_BASE + nandcs *GPMC_CS_SIZE ); - devkit8000_nand_data.gpmc_baseaddr = (void *) - (gpmc_base_add);printk (KERN_INFO "Registering NAND on CS%d\n" , nandcs); -if (platform_device_register (&devkit8000_nand_device) <0 ) +if (gpmc_nand_init (&devkit8000_nand_data) <0 )printk (KERN_ERR "Unable to register NAND device\n" ); } }
arch/arm/mach-omap2/board-omap3beagle.c +1 -23
@@ -48,9 +48,6 @@#include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 -#define NAND_BLOCK_SIZE SZ_128Kstatic struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -93,20 +90,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = { .dev_ready = NULL, }; -static struct resource omap3beagle_nand_resource = { - .flags =IORESOURCE_MEM , -}; - -static struct platform_device omap3beagle_nand_device = { - .name ="omap2-nand" , - .id =-1 , - .dev = { - .platform_data = &omap3beagle_nand_data, - }, - .num_resources =1 , - .resource = &omap3beagle_nand_resource, -}; -/* DSS */ static int beagle_enable_dvi (struct omap_dss_device *dssdev)
@@ -424,8 +407,6 @@ static void __init omap3beagle_flash_init(void)u8 cs =0 ;u8 nandcs =GPMC_CS_NUM +1 ; -u32 gpmc_base_add =OMAP34XX_GPMC_VIRT ; -/* find out the chip-select on which NAND exists */ while (cs <GPMC_CS_NUM ) {u32 ret =0 ;
@@ -447,12 +428,9 @@ static void __init omap3beagle_flash_init(void)if (nandcs <GPMC_CS_NUM ) { omap3beagle_nand_data.cs = nandcs; - omap3beagle_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add +GPMC_CS0_BASE + nandcs *GPMC_CS_SIZE ); - omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);printk (KERN_INFO "Registering NAND on CS%d\n" , nandcs); -if (platform_device_register (&omap3beagle_nand_device) <0 ) +if (gpmc_nand_init (&omap3beagle_nand_data) <0 )printk (KERN_ERR "Unable to register NAND device\n" ); } }
arch/arm/mach-omap2/board-omap3touchbook.c +1 -24
@@ -54,9 +54,6 @@#include <asm/setup.h> -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 -#define NAND_BLOCK_SIZE SZ_128K#define OMAP3_AC_GPIO 136
@@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = { .dev_ready = NULL, }; -static struct resource omap3touchbook_nand_resource = { - .flags =IORESOURCE_MEM , -}; - -static struct platform_device omap3touchbook_nand_device = { - .name ="omap2-nand" , - .id =-1 , - .dev = { - .platform_data = &omap3touchbook_nand_data, - }, - .num_resources =1 , - .resource = &omap3touchbook_nand_resource, -}; -#include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = {
@@ -458,8 +441,6 @@ static void __init omap3touchbook_flash_init(void)u8 cs =0 ;u8 nandcs =GPMC_CS_NUM +1 ; -u32 gpmc_base_add =OMAP34XX_GPMC_VIRT ; -/* find out the chip-select on which NAND exists */ while (cs <GPMC_CS_NUM ) {u32 ret =0 ;
@@ -481,13 +462,9 @@ static void __init omap3touchbook_flash_init(void)if (nandcs <GPMC_CS_NUM ) { omap3touchbook_nand_data.cs = nandcs; - omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add +GPMC_CS0_BASE + nandcs *GPMC_CS_SIZE ); - omap3touchbook_nand_data.gpmc_baseaddr = - (void *) (gpmc_base_add);printk (KERN_INFO "Registering NAND on CS%d\n" , nandcs); -if (platform_device_register (&omap3touchbook_nand_device) <0 ) +if (gpmc_nand_init (&omap3touchbook_nand_data) <0 )printk (KERN_ERR "Unable to register NAND device\n" ); } }
arch/arm/mach-omap2/board-overo.c +1 -23
@@ -58,8 +58,6 @@#define OVERO_GPIO_USBH_NRESET 183#define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30#define OVERO_SMSC911X_CS 5#define OVERO_SMSC911X_GPIO 176
@@ -269,28 +267,11 @@ static struct omap_nand_platform_data overo_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource overo_nand_resource = { - .flags =IORESOURCE_MEM , -}; - -static struct platform_device overo_nand_device = { - .name ="omap2-nand" , - .id =-1 , - .dev = { - .platform_data = &overo_nand_data, - }, - .num_resources =1 , - .resource = &overo_nand_resource, -}; - -static void __init overo_flash_init (void ) {u8 cs =0 ;u8 nandcs =GPMC_CS_NUM +1 ; -u32 gpmc_base_add =OMAP34XX_GPMC_VIRT ; -/* find out the chip-select on which NAND exists */ while (cs <GPMC_CS_NUM ) {u32 ret =0 ;
@@ -312,12 +293,9 @@ static void __init overo_flash_init(void)if (nandcs <GPMC_CS_NUM ) { overo_nand_data.cs = nandcs; - overo_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add +GPMC_CS0_BASE + nandcs *GPMC_CS_SIZE ); - overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);printk (KERN_INFO "Registering NAND on CS%d\n" , nandcs); -if (platform_device_register (&overo_nand_device) <0 ) +if (gpmc_nand_init (&overo_nand_data) <0 )printk (KERN_ERR "Unable to register NAND device\n" ); } }
arch/arm/mach-omap2/board-sdp-flash.c +0 -5
@@ -162,11 +162,6 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs) sdp_nand_data.parts = sdp_nand_parts.parts; sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts; - sdp_nand_data.gpmc_cs_baseaddr = (void *)(OMAP34XX_GPMC_VIRT + -GPMC_CS0_BASE + - cs *GPMC_CS_SIZE ); - sdp_nand_data.gpmc_baseaddr = (void *) (OMAP34XX_GPMC_VIRT ); - gpmc_nand_init(&sdp_nand_data); }#else
Tony Lindgren
maintainerv7 cover omap3 nand: cleanup exiting platform related code
In reply to Sukumar GhoraiQuoted 10 lines · Sukumar Ghorai
The following set of patches applies on top of for-next branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.gitPatches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC.
Quoted 4 lines
2. Passing hardcoded
GPMC_CS0_BASEneeds to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly.
Thanks, I'll add this series into omap-for-linus.
Regards,
Tony
Quoted 47 lines
Discussion: http://www.mail-archive.com/[email protected]/msg27630.html
No code change from previous version.
Looping linux-arm-kernel mailing list with new version.Changes in this series -
gpmc_hwcontrol()function ingpmc.c, break into various small function.
v6: http://www.mail-archive.com/[email protected]/msg31936.htmlUnused function removed.
v5: http://www.mail-archive.com/[email protected]/msg30305.htmlFunctions related to ecc and prefetch engine are optimized.
v4: http://www.mail-archive.com/[email protected]/msg29458.htmlFew functionality was missing like - There should be some locking as only
one chipselect can use the ECC or prefetch engine at a time. If you have NAND in two chipselects, bad things would happen.
v3: http://www.mail-archive.com/[email protected]/msg28715.htmlAdditionally, it was needed to implement more functions for the platform init code to use.
v2: http://www.mail-archive.com/[email protected]/msg28467.htmlv1: http://www.mail-archive.com/[email protected]/msg28164.html
Sukumar Ghorai (3):
omap3 gpmc: functionality enhancement omap3 nand: cleanup virtual address usages omap3 nand: fix issue in board file to detect nandarch/arm/mach-omap2/board-cm-t35.c | 20 +-- arch/arm/mach-omap2/board-devkit8000.c | 25 +--- arch/arm/mach-omap2/board-omap3beagle.c | 24 +--- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +--- arch/arm/mach-omap2/board-overo.c | 24 +--- arch/arm/mach-omap2/board-sdp-flash.c | 5 - arch/arm/mach-omap2/gpmc-nand.c | 38 +--- arch/arm/mach-omap2/gpmc.c | 285 ++++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/gpmc.h | 42 ++++- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 218 ++++++---------------- 11 files changed, 371 insertions(+), 341 deletions(-)--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html