[PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
Vimal Singh
vimal.newwork at gmail.com
Fri May 14 14:02:33 EDT 2010
On Fri, May 14, 2010 at 8:53 PM, Sukumar Ghorai <s-ghorai at ti.com> wrote:
[...]
> diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
> index 7bb6922..5d66817
> --- a/arch/arm/mach-omap2/gpmc-onenand.c
> +++ b/arch/arm/mach-omap2/gpmc-onenand.c
> @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
> (GPMC_CONFIG1_WAIT_READ_MON |
> GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
> GPMC_CONFIG1_DEVICESIZE_16 |
> - GPMC_CONFIG1_DEVICETYPE_NOR |
> + GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) |
> GPMC_CONFIG1_MUXADDDATA);
Please do not dp OneNAND changes in NAND patch.
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 5bc3ca0..a3fd1ed
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -29,27 +29,27 @@
> #include <plat/sdrc.h>
>
> /* GPMC register offsets */
> -#define GPMC_REVISION 0x00
> -#define GPMC_SYSCONFIG 0x10
> -#define GPMC_SYSSTATUS 0x14
> -#define GPMC_IRQSTATUS 0x18
> -#define GPMC_IRQENABLE 0x1c
> -#define GPMC_TIMEOUT_CONTROL 0x40
> -#define GPMC_ERR_ADDRESS 0x44
> -#define GPMC_ERR_TYPE 0x48
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_PREFETCH_CONFIG1 0x1e0
> -#define GPMC_PREFETCH_CONFIG2 0x1e4
> -#define GPMC_PREFETCH_CONTROL 0x1ec
> -#define GPMC_PREFETCH_STATUS 0x1f0
> -#define GPMC_ECC_CONFIG 0x1f4
> -#define GPMC_ECC_CONTROL 0x1f8
> -#define GPMC_ECC_SIZE_CONFIG 0x1fc
> -
> -#define GPMC_CS0 0x60
> -#define GPMC_CS_SIZE 0x30
> -
> +#define GPMC_REVISION 0x00
> +#define GPMC_SYSCONFIG 0x10
> +#define GPMC_SYSSTATUS 0x14
> +#define GPMC_IRQSTATUS 0x18
> +#define GPMC_IRQENABLE 0x1c
> +#define GPMC_TIMEOUT_CONTROL 0x40
> +#define GPMC_ERR_ADDRESS 0x44
> +#define GPMC_ERR_TYPE 0x48
> +#define GPMC_CONFIG 0x50
> +#define GPMC_STATUS 0x54
> +#define GPMC_PREFETCH_CONFIG1 0x1e0
> +#define GPMC_PREFETCH_CONFIG2 0x1e4
> +#define GPMC_PREFETCH_CONTROL 0x1ec
> +#define GPMC_PREFETCH_STATUS 0x1f0
> +#define GPMC_ECC_CONFIG 0x1f4
> +#define GPMC_ECC_CONTROL 0x1f8
> +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
> +
> +#define GPMC_CS0_BASE 0x60
> +#define GPMC_CS_SIZE 0x30
> #define GPMC_MEM_START 0x00000000
> #define GPMC_MEM_END 0x3FFFFFFF
> #define BOOT_ROM_SPACE 0x100000 /* 1MB */
> @@ -108,11 +108,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);
> +}
> +
I do not think we need these functions.
> 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 +136,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,6 +435,96 @@ void gpmc_cs_free(int cs)
> EXPORT_SYMBOL(gpmc_cs_free);
>
> /**
> + * gpmc_hwcontrol - hardware specific access (read/ write) to control
> + * @write: need 1 for configure; 0 for reading the complete register
> + * @cs: chip select number
> + * @cmd: Command type
> + * @wval: value/information to write
> + * @rval: pointer to get the value back
> + */
> +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval)
> +{
> + u32 reg = 0;
> + u32 regval = 0;
> +
> + switch (cmd) {
> +
> + case GPMC_GET_SET_STATUS:
> + reg = GPMC_STATUS;
> + if (write)
> + gpmc_write_reg(GPMC_STATUS, regval);
> + break;
> +
> + case GPMC_GET_SET_IRQ_STATUS:
> + reg = GPMC_IRQSTATUS;
> + if (write)
> + gpmc_write_reg(GPMC_IRQSTATUS, regval);
> + break;
> +
> + case GPMC_GET_PREF_STATUS:
> + reg = GPMC_PREFETCH_STATUS;
> + break;
> +
> + case GPMC_CONFIG_WP:
> + reg = GPMC_CONFIG;
> + 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(reg, regval);
> + break;
> +
> + case GPMC_CONFIG_RDY_BSY:
> + #define WR_RD_PIN_MONITORING 0x00600000
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= WR_RD_PIN_MONITORING;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_SIZE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_TYPE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> + if (wval == GPMC_DEVICETYPE_NOR)
> + regval |= GPMC_CONFIG1_MUXADDDATA;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_NAND_COMMAND:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> + break;
> +
> + case GPMC_NAND_ADDRESS:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> + break;
> +
> + case GPMC_NAND_DATA:
> + if (write)
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> + else
> + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> + break;
> +
> + default:
> + dump_stack();
> + printk(KERN_ERR "not supported\n");
> + return -1;
> + }
> +
> + if (!write && reg)
> + *rval = gpmc_read_reg(reg);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_hwcontrol);
> +
> +/**
> * gpmc_prefetch_enable - configures and starts prefetch transfer
> * @cs: nand cs (chip select) number
> * @dma_mode: dma mode enable (1) or disable (0)
> @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void)
> }
> 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;
> @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void)
> }
> }
> #endif /* CONFIG_ARCH_OMAP3 */
> +
> +/**
> + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller
> + * @cs: Chip select number
> + * @ecc_size: bytes for which ECC will be generated
> + */
> +void gpmc_ecc_init(int cs, int ecc_size)
> +{
> + unsigned int val = 0x0;
> +
> + /* Read from ECC Control Register */
> + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> +
> + /* Clear all ECC | Enable Reg1 */
> + val = ((0x00000001<<8) | 0x00000001);
> + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> +
> + /* Read from ECC Size Config Register */
> + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> + /* ECCSIZE1=512 | Select eccResultsize[0-3] */
> + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> +}
> +
> +/**
> + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes.
> + * @cs: Chip select number
> + * @dat: The pointer to data on which ecc is computed
> + * @ecc_code: The ecc_code buffer
> + *
> + * Using noninverted ECC can be considered ugly since writing a blank
> + * page ie. padding will clear the ECC bytes. This is no problem as long
> + * nobody 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;
> +
> + /* Start Reading from HW ECC1_Result = 0x200 */
> + 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);
> +
> + return 0;
> +}
> +
> +/**
> + * gpmc_enable_hwecc - This function enables the hardware ecc functionality
> + * @cs: Chip select number
> + * @mode: Read/Write mode
> + * @dev_width: device bus width
> + */
> +void gpmc_enable_hwecc(int cs, int mode, int dev_width)
> +{
> + unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG);
> +
> + switch (mode) {
> + case GPMC_ECC_READ:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case GPMC_ECC_READSYN:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case GPMC_ECC_WRITE:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + default:
> + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
> + break;
> + }
> +
> + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> +}
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 145838a..56e1407
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -25,10 +25,22 @@
> #define GPMC_CS_NAND_ADDRESS 0x20
> #define GPMC_CS_NAND_DATA 0x24
>
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_CS0_BASE 0x60
> -#define GPMC_CS_SIZE 0x30
> +/* Control Commands */
> +#define GPMC_GET_SET_STATUS 0x00000001
> +#define GPMC_CONFIG_WP 0x00000002
> +#define GPMC_CONFIG_RDY_BSY 0x00000003
> +#define GPMC_CONFIG_DEV_SIZE 0x00000004
> +#define GPMC_CONFIG_DEV_TYPE 0x00000005
> +#define GPMC_NAND_COMMAND 0x00000006
> +#define GPMC_NAND_ADDRESS 0x00000007
> +#define GPMC_NAND_DATA 0x00000008
> +#define GPMC_GET_PREF_STATUS 0x00000009
> +#define GPMC_GET_SET_IRQ_STATUS 0x0000000a
> +
> +/* 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)
> @@ -44,10 +56,7 @@
> #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
> #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16)
> #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12)
> -#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)
> @@ -56,6 +65,12 @@
> #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_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> +
> +
> /*
> * Note that all values in this struct are in nanoseconds, while
> * the register values are in gpmc_fck cycles.
> @@ -109,9 +124,14 @@ 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_status(void);
> extern void omap3_gpmc_save_context(void);
> extern void omap3_gpmc_restore_context(void);
> extern void gpmc_init(void);
> +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval);
> +
> +void gpmc_ecc_init(int cs, int ecc_size);
> +void gpmc_enable_hwecc(int cs, int mode, int dev_width);
> +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> +
>
> #endif
> diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
> index f8efd54..6562cd0
> --- a/arch/arm/plat-omap/include/plat/nand.h
> +++ b/arch/arm/plat-omap/include/plat/nand.h
> @@ -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);
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 7545568..1858c42
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -23,12 +23,6 @@
> #include <plat/gpmc.h>
> #include <plat/nand.h>
>
> -#define GPMC_IRQ_STATUS 0x18
> -#define GPMC_ECC_CONFIG 0x1F4
> -#define GPMC_ECC_CONTROL 0x1F8
> -#define GPMC_ECC_SIZE_CONFIG 0x1FC
> -#define GPMC_ECC1_RESULT 0x200
> -
> #define DRIVER_NAME "omap2-nand"
>
> #define NAND_WP_OFF 0
> @@ -37,6 +31,7 @@
> #define GPMC_BUF_FULL 0x00000001
> #define GPMC_BUF_EMPTY 0x00000000
>
> +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
> #define NAND_Ecc_P1e (1 << 0)
> #define NAND_Ecc_P2e (1 << 1)
> #define NAND_Ecc_P4e (1 << 2)
> @@ -103,6 +98,7 @@
>
> #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
> #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
> +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
Why this ifdef macro?
>
> #ifdef CONFIG_MTD_PARTITIONS
> static const char *part_probes[] = { "cmdlinepart", NULL };
> @@ -139,34 +135,11 @@ struct omap_nand_info {
>
> int gpmc_cs;
> unsigned long phys_base;
> - void __iomem *gpmc_cs_baseaddr;
> - void __iomem *gpmc_baseaddr;
> - void __iomem *nand_pref_fifo_add;
> struct completion comp;
> int dma_ch;
> };
>
> /**
> - * omap_nand_wp - This function enable or disable the Write Protect feature
> - * @mtd: MTD device structure
> - * @mode: WP ON/OFF
> - */
> -static void omap_nand_wp(struct mtd_info *mtd, int mode)
> -{
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> -
> - unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
> -
> - if (mode)
> - config &= ~(NAND_WP_BIT); /* WP is ON */
> - else
> - config |= (NAND_WP_BIT); /* WP is OFF */
> -
> - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
> -}
> -
> -/**
> * omap_hwcontrol - hardware specific access to control-lines
> * @mtd: MTD device structure
> * @cmd: command to device
> @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
> {
> struct omap_nand_info *info = container_of(mtd,
> struct omap_nand_info, mtd);
> - switch (ctrl) {
> - case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_COMMAND;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> -
> - case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_ADDRESS;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> -
> - case NAND_CTRL_CHANGE | NAND_NCE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> - }
>
> - if (cmd != NAND_CMD_NONE)
> - __raw_writeb(cmd, info->nand.IO_ADDR_W);
> + if (cmd != NAND_CMD_NONE) {
> + if (ctrl & NAND_CLE) {
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_COMMAND, cmd, NULL);
> +
> + } else if (ctrl & NAND_ALE) {
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_ADDRESS, cmd, NULL);
> +
> + } else /* NAND_NCE */
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_DATA, cmd, NULL);
> + }
> }
>
> /**
> @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
> */
> static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
> {
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> + u32 status;
> + struct nand_chip *nand = mtd->priv;
> u_char *p = (u_char *)buf;
>
> while (len--) {
> - iowrite8(*p++, info->nand.IO_ADDR_W);
> - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> - GPMC_STATUS) & GPMC_BUF_FULL));
> + iowrite8(*p++, nand->IO_ADDR_W);
> + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
If I am not mistaking, 2nd argument is 'cs', correct? And then, why
are you hard coding this?
Different boards will have NAND chip present at different 'cs'.
Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this.
Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then:
> + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
> + ;
You got in an infinite loop here?
> }
> }
>
> @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
> */
> static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
> {
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> + u32 status;
> + struct nand_chip *nand = mtd->priv;
> u16 *p = (u16 *) buf;
>
> /* FIXME try bursts of writesw() or DMA ... */
> len >>= 1;
>
> while (len--) {
> - iowrite16(*p++, info->nand.IO_ADDR_W);
> -
> - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> - GPMC_STATUS) & GPMC_BUF_FULL))
> + iowrite16(*p++, nand->IO_ADDR_W);
> + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
> + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
same as above.
--
Regards,
Vimal Singh
More information about the linux-mtd
mailing list