This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

two piece of nand problem(am3352)

Other Parts Discussed in Thread: AM3352

I have a custom board based on AM3352.

it's has two piece of  nand ( k9f2g08 )

has chip select cs0 and cs1

i'm kernel that is pin mux config and function (evm_nand_init) add omap_nand_init(CS1) 

but congnition only cs1 and cs0 pass

it's boot log

[ 0.168947] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.169203] NET: Registered protocol family 1
[ 0.169479] RPC: Registered named UNIX socket transport module.
[ 0.169494] RPC: Registered udp transport module.
[ 0.169503] RPC: Registered tcp transport module.
[ 0.169513] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.169742] NetWinder Floating Point Emulator V0.97 (double precision)
[ 0.169957] omap-gpmc omap-gpmc: GPMC revision 6.0
[ 0.169985] Registering NAND on CS1
[ 0.170506] Registering NAND on CS1
[ 0.170519] platform omap2-nand.0: Cannot request GPMC CS

 ......

[ 0.861171] omap2-nand driver initializing
[ 0.865823] NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
[ 0.875052] Creating 1 MTD partitions on "omap2-nand.0":
[ 0.880621] 0x000000000000-0x000010000000 : "data"

it's kernel code function's evm_nand_init 

static void evm_nand_init(int evm_id, int profile)
{
struct omap_nand_platform_data *pdata , *pdata2;
struct gpmc_devices_info gpmc_device[2] = {
{ NULL, 0 },
{ NULL, 0 },
};


setup_pin_mux(nand_pin_mux);
pdata = omap_nan d_init(am335x_nand_partitions,
ARRAY_SIZE(am335x_nand_partitions), 0, 0,
&am335x_nand_timings);
if (!pdata)
return;
pdata->ecc_opt =OMAP_ECC_BCH8_CODE_HW;
pdata->elm_used = true;
gpmc_device[0].pdata = pdata;
gpmc_device[0].flag = GPMC_DEVICE_NAND;

#if 1
pdata2 = omap_nand_init(am335x_nand2_partitions,
ARRAY_SIZE(am335x_nand2_partitions), 1, 0,
&am335x_nand_timings);
if (!pdata2)
return;
pdata2->ecc_opt =OMAP_ECC_BCH8_CODE_HW;
pdata2->elm_used = true;
gpmc_device[1].pdata = pdata2;
gpmc_device[1].flag = GPMC_DEVICE_NAND;
#endif

omap_init_gpmc(gpmc_device, sizeof(gpmc_device));

omap_init_elm();

}

it's configuration same timing  and different mtd config

it 's wrong .

Thank you

Kind Regards,

  • Hi,

    It seems the resource address not initialized for GPMC chip select 2.

    So can you add some debug prints in gpmc_cs_request() and give some further inputs.

    I interested in following debug. may be you can addsome other also.

    int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
    {

    ---

          if (gpmc_cs_mem_enabled(cs))
                   r = adjust_resource(res, res->start & ~(size - 1), size);
           if (r < 0)
                   r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
                                         size, NULL, NULL);
           if (r < 0) {

                   pr_emerg("allocate_resource return %d\n", r);
                   goto out;

           }

    ---

    Thanks Avinash

  • Thank you Avinash..

    I'm Add your debug... and kernel downloading , so kernel loading

    but didn't print "allocate_resource return"

    Now i'm debugging ..  find it any stranger point...

    function's  evm_nand_init  is print cs(chip select)

     that is printk("evm_nand_init %d\n" , pdata->cs );

     so print it 

    [ 0.103248] evm_nand_init 0
    [ 0.103262] evm_nand_init 1

    pdata-> cs is correct setting cs ( 0 , 1 )

    but 

    function's gpmc_probe (gpmc.c)  is print cs(chip select)

      at code ...

    p = gpmc_device->pdata ;
    printk("gpmc_probe cs %d \n" , ((struct omap_nand_platform_data *) p)->cs );
    gpmc_device++; ;
    printk("gpmc_probe cs %d \n" , ((struct omap_nand_platform_data *) p)->cs );

    so print it 

    [ 0.151765] gpmc_probe cs 1
    [ 0.151774] gpmc_probe cs 1

    only cs 1 print

    it's wrong 

    Thank you

    Kind Regards,

  • Hi,

    struct gpmc_devices_info gpmc_device[2] = {
    { NULL, 0 },
    { NULL, 0 },

    { NULL, 0 },

    };

    please modify as above in evm_nand_init().

    Also please use attached (gpmc*.c) file & update.

    /*
     * GPMC support functions
     *
     * Copyright (C) 2005-2006 Nokia Corporation
     *
     * Author: Juha Yrjola
     *
     * Copyright (C) 2009 Texas Instruments
     * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    #undef DEBUG
    
    #include <linux/platform_device.h>
    
    #include <linux/irq.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/err.h>
    #include <linux/clk.h>
    #include <linux/ioport.h>
    #include <linux/spinlock.h>
    #include <linux/io.h>
    #include <linux/module.h>
    #include <linux/interrupt.h>
    #include <linux/pm_runtime.h>
    
    #include <asm/mach-types.h>
    #include <plat/gpmc.h>
    #include <plat/nand.h>
    
    #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_ECC1_RESULT        0x200
    #define GPMC_ECC_BCH_RESULT_0	0x240
    
    #define GPMC_CS0_OFFSET		0x60
    #define GPMC_CS_SIZE		0x30
    
    #define GPMC_MEM_START		0x00000000
    #define GPMC_MEM_END		0x3FFFFFFF
    #define BOOT_ROM_SPACE		0x100000	/* 1MB */
    
    #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
    #define GPMC_SECTION_SHIFT	28		/* 128 MB */
    
    #define CS_NUM_SHIFT		24
    #define ENABLE_PREFETCH		(0x1 << 7)
    #define DMA_MPU_MODE		2
    
    /* Structure to save gpmc cs context */
    struct gpmc_cs_config {
    	u32 config1;
    	u32 config2;
    	u32 config3;
    	u32 config4;
    	u32 config5;
    	u32 config6;
    	u32 config7;
    	int is_valid;
    };
    
    /*
     * Structure to save/restore gpmc context
     * to support core off on OMAP3
     */
    struct omap3_gpmc_regs {
    	u32 sysconfig;
    	u32 irqenable;
    	u32 timeout_ctrl;
    	u32 config;
    	u32 prefetch_config1;
    	u32 prefetch_config2;
    	u32 prefetch_control;
    	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
    };
    
    
    #define	DRIVER_NAME	"omap-gpmc"
    
    struct gpmc {
    	struct device	*dev;
    	void __iomem	*io_base;
    	unsigned long	phys_base;
    	u32		memsize;
    	unsigned int	cs_map;
    	int		ecc_used;
    	spinlock_t	mem_lock;
    	struct resource	mem_root;
    	struct resource	cs_mem[GPMC_CS_NUM];
    };
    
    static struct gpmc *gpmc;
    
    static void gpmc_write_reg(int idx, u32 val)
    {
    	writel(val, gpmc->io_base + idx);
    }
    
    static u32 gpmc_read_reg(int idx)
    {
    	return readl(gpmc->io_base + idx);
    }
    
    static void gpmc_cs_write_byte(int cs, int idx, u8 val)
    {
    	void __iomem *reg_addr;
    
    	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
    	writeb(val, reg_addr);
    }
    
    static u8 gpmc_cs_read_byte(int cs, int idx)
    {
    	void __iomem *reg_addr;
    
    	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
    	return readb(reg_addr);
    }
    
    void gpmc_cs_write_reg(int cs, int idx, u32 val)
    {
    	void __iomem *reg_addr;
    
    	if (!gpmc) {
    		pr_err("%s invoked without initializing GPMC\n", __func__);
    		return;
    	}
    
    	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
    	writel(val, reg_addr);
    }
    
    u32 gpmc_cs_read_reg(int cs, int idx)
    {
    	void __iomem *reg_addr;
    
    	if (!gpmc) {
    		pr_err("%s invoked without initializing GPMC\n", __func__);
    		return 0;
    	}
    
    	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
    	return readl(reg_addr);
    }
    
    static struct clk *gpmc_l3_clk;
    
    static void __devinit gpmc_clk_init(struct device *dev)
    {
    	char *ck = NULL;
    
    	if (cpu_is_omap24xx())
    		ck = "core_l3_ck";
    	else if (cpu_is_omap34xx())
    		ck = "gpmc_fck";
    	else if (cpu_is_omap44xx())
    		ck = "gpmc_ck";
    
    	if (WARN_ON(!ck))
    		return;
    
    	gpmc_l3_clk = clk_get(NULL, ck);
    	if (IS_ERR(gpmc_l3_clk)) {
    		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
    		BUG();
    	}
    
    	pm_runtime_enable(dev);
    	pm_runtime_get_sync(dev);
    }
    
    /* TODO: Add support for gpmc_fck to clock framework and use it */
    unsigned long gpmc_get_fclk_period(void)
    {
    	unsigned long rate = clk_get_rate(gpmc_l3_clk);
    
    	if (rate == 0) {
    		printk(KERN_WARNING "gpmc_l3_clk not enabled\n");
    		return 0;
    	}
    
    	rate /= 1000;
    	rate = 1000000000 / rate;	/* In picoseconds */
    
    	return rate;
    }
    
    unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
    {
    	unsigned long tick_ps;
    
    	/* Calculate in picosecs to yield more exact results */
    	tick_ps = gpmc_get_fclk_period();
    
    	return (time_ns * 1000 + tick_ps - 1) / tick_ps;
    }
    
    unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
    {
    	unsigned long tick_ps;
    
    	/* Calculate in picosecs to yield more exact results */
    	tick_ps = gpmc_get_fclk_period();
    
    	return (time_ps + tick_ps - 1) / tick_ps;
    }
    
    unsigned int gpmc_ticks_to_ns(unsigned int ticks)
    {
    	return ticks * gpmc_get_fclk_period() / 1000;
    }
    
    unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
    {
    	unsigned long ticks = gpmc_ns_to_ticks(time_ns);
    
    	return ticks * gpmc_get_fclk_period() / 1000;
    }
    
    #ifdef DEBUG
    static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
    			       int time, const char *name)
    #else
    static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
    			       int time)
    #endif
    {
    	u32 l;
    	int ticks, mask, nr_bits;
    
    	if (time == 0)
    		ticks = 0;
    	else
    		ticks = gpmc_ns_to_ticks(time);
    	nr_bits = end_bit - st_bit + 1;
    	if (ticks >= 1 << nr_bits) {
    #ifdef DEBUG
    		printk(KERN_INFO "GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n",
    				cs, name, time, ticks, 1 << nr_bits);
    #endif
    		return -1;
    	}
    
    	mask = (1 << nr_bits) - 1;
    	l = gpmc_cs_read_reg(cs, reg);
    #ifdef DEBUG
    	printk(KERN_INFO
    		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
    	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
    			(l >> st_bit) & mask, time);
    #endif
    	l &= ~(mask << st_bit);
    	l |= ticks << st_bit;
    	gpmc_cs_write_reg(cs, reg, l);
    
    	return 0;
    }
    
    #ifdef DEBUG
    #define GPMC_SET_ONE(reg, st, end, field) \
    	if (set_gpmc_timing_reg(cs, (reg), (st), (end),		\
    			t->field, #field) < 0)			\
    		return -1
    #else
    #define GPMC_SET_ONE(reg, st, end, field) \
    	if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
    		return -1
    #endif
    
    int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
    {
    	int div;
    	u32 l;
    
    	l = sync_clk + (gpmc_get_fclk_period() - 1);
    	div = l / gpmc_get_fclk_period();
    	if (div > 4)
    		return -1;
    	if (div <= 0)
    		div = 1;
    
    	return div;
    }
    
    int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
    {
    	int div;
    	u32 l;
    
    	div = gpmc_cs_calc_divider(cs, t->sync_clk);
    	if (div < 0)
    		return -1;
    
    	GPMC_SET_ONE(GPMC_CS_CONFIG2,  0,  3, cs_on);
    	GPMC_SET_ONE(GPMC_CS_CONFIG2,  8, 12, cs_rd_off);
    	GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off);
    
    	GPMC_SET_ONE(GPMC_CS_CONFIG3,  0,  3, adv_on);
    	GPMC_SET_ONE(GPMC_CS_CONFIG3,  8, 12, adv_rd_off);
    	GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
    
    	GPMC_SET_ONE(GPMC_CS_CONFIG4,  0,  3, oe_on);
    	GPMC_SET_ONE(GPMC_CS_CONFIG4,  8, 12, oe_off);
    	GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
    	GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
    
    	GPMC_SET_ONE(GPMC_CS_CONFIG5,  0,  4, rd_cycle);
    	GPMC_SET_ONE(GPMC_CS_CONFIG5,  8, 12, wr_cycle);
    	GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
    
    	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
    
    	if (cpu_is_omap34xx()) {
    		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
    		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
    	}
    
    	/* caller is expected to have initialized CONFIG1 to cover
    	 * at least sync vs async
    	 */
    	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
    	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
    #ifdef DEBUG
    		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
    				cs, (div * gpmc_get_fclk_period()) / 1000, div);
    #endif
    		l &= ~0x03;
    		l |= (div - 1);
    		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
    	}
    
    	return 0;
    }
    
    static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
    {
    	u32 l;
    	u32 mask;
    
    	mask = (1 << GPMC_SECTION_SHIFT) - size;
    	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
    	l &= ~0x3f;
    	l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
    	l &= ~(0x0f << 8);
    	l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
    	l |= GPMC_CONFIG7_CSVALID;
    	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
    }
    
    static void gpmc_cs_disable_mem(int cs)
    {
    	u32 l;
    
    	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
    	l &= ~GPMC_CONFIG7_CSVALID;
    	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
    }
    
    static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
    {
    	u32 l;
    	u32 mask;
    
    	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
    	*base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
    	mask = (l >> 8) & 0x0f;
    	*size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
    
    	if (cpu_is_am33xx()) {
    		*base = 0x8000000;
    		*size = 0x10000000;
    	}
    }
    
    static int gpmc_cs_mem_enabled(int cs)
    {
    	u32 l;
    
    	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
    	return l & GPMC_CONFIG7_CSVALID;
    }
    
    int gpmc_cs_set_reserved(int cs, int reserved)
    {
    	if (cs > GPMC_CS_NUM)
    		return -ENODEV;
    
    	gpmc->cs_map &= ~(1 << cs);
    	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
    
    	return 0;
    }
    
    int gpmc_cs_reserved(int cs)
    {
    	if (cs > GPMC_CS_NUM)
    		return -ENODEV;
    
    	return gpmc->cs_map & (1 << cs);
    }
    
    static unsigned long gpmc_mem_align(unsigned long size)
    {
    	int order;
    
    	size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
    	order = GPMC_CHUNK_SHIFT - 1;
    	do {
    		size >>= 1;
    		order++;
    	} while (size);
    	size = 1 << order;
    	return size;
    }
    
    static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
    {
    	struct resource	*res = &gpmc->cs_mem[cs];
    	int r;
    
    	size = gpmc_mem_align(size);
    	spin_lock(&gpmc->mem_lock);
    	res->start = base;
    	res->end = base + size - 1;
    	r = request_resource(&gpmc->mem_root, res);
    	spin_unlock(&gpmc->mem_lock);
    
    	return r;
    }
    
    int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
    {
    	struct resource *res = &gpmc->cs_mem[cs];
    	int r = -1;
    
    	pr_emerg("%s() %d\n", __func__, __LINE__);
    	if (cs > GPMC_CS_NUM)
    		return -ENODEV;
    
    	pr_emerg("%s() %d\n", __func__, __LINE__);
    	size = gpmc_mem_align(size);
    	if (size > (1 << GPMC_SECTION_SHIFT))
    		return -ENOMEM;
    
    	pr_emerg("%s() %d\n", __func__, __LINE__);
    	spin_lock(&gpmc->mem_lock);
    	if (gpmc_cs_reserved(cs)) {
    		r = -EBUSY;
    		goto out;
    	}
    	pr_emerg("%s() %d\n", __func__, __LINE__);
    	if (gpmc_cs_mem_enabled(cs))
    		r = adjust_resource(res, res->start & ~(size - 1), size);
    	if (r < 0)
    		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
    				      size, NULL, NULL);
    	pr_emerg("%s() %d\n", __func__, __LINE__);
    	if (r < 0) {
    		pr_emerg("%s() return value%d\n", __func__, r);
    		goto out;
    	}
    
    	gpmc_cs_enable_mem(cs, res->start, resource_size(res));
    	*base = res->start;
    	gpmc_cs_set_reserved(cs, 1);
    out:
    	spin_unlock(&gpmc->mem_lock);
    	return r;
    }
    EXPORT_SYMBOL(gpmc_cs_request);
    
    void gpmc_cs_free(int cs)
    {
    	spin_lock(&gpmc->mem_lock);
    	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
    		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
    		BUG();
    		spin_unlock(&gpmc->mem_lock);
    		return;
    	}
    	gpmc_cs_disable_mem(cs);
    	release_resource(&gpmc->cs_mem[cs]);
    	gpmc_cs_set_reserved(cs, 0);
    	spin_unlock(&gpmc->mem_lock);
    }
    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_ENABLE_IRQ:
    		gpmc_write_reg(GPMC_IRQENABLE, wval);
    		break;
    
    	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: 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
     */
    int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
    				unsigned int u32_count, int is_write)
    {
    
    	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
    		pr_err("gpmc: fifo threshold is not supported\n");
    		return -1;
    	} else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
    		/* Set the amount of bytes to be prefetched */
    		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
    
    		/* Set dma/mpu mode, the prefetch read / post write and
    		 * enable the engine. Set which cs is has requested for.
    		 */
    		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
    					PREFETCH_FIFOTHRESHOLD(fifo_th) |
    					ENABLE_PREFETCH |
    					(dma_mode << DMA_MPU_MODE) |
    					(0x1 & is_write)));
    
    		/*  Start the prefetch engine */
    		gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
    	} else {
    		return -EBUSY;
    	}
    
    	return 0;
    }
    EXPORT_SYMBOL(gpmc_prefetch_enable);
    
    /**
     * gpmc_prefetch_reset - disables and stops the prefetch engine
     */
    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);
    
    static void __devinit gpmc_mem_init(void)
    {
    	int cs;
    	unsigned long boot_rom_space = 0;
    
    	/* never allocate the first page, to facilitate bug detection;
    	 * even if we didn't boot from ROM.
    	 */
    	boot_rom_space = BOOT_ROM_SPACE;
    	/* In apollon the CS0 is mapped as 0x0000 0000 */
    	if (machine_is_omap_apollon())
    		boot_rom_space = 0;
    	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
    	gpmc->mem_root.end = GPMC_MEM_END;
    
    	/* Reserve all regions that has been set up by bootloader */
    	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
    		u32 base, size;
    
    		if (!gpmc_cs_mem_enabled(cs))
    			continue;
    		gpmc_cs_get_memconf(cs, &base, &size);
    		if (gpmc_cs_insert_mem(cs, base, size) < 0)
    			BUG();
    	}
    }
    
    struct device *gpmc_dev;
    
    static int __devinit gpmc_probe(struct platform_device *pdev)
    {
    	u32 l;
    	int ret = -EINVAL;
    	struct resource *res = NULL;
    	struct gpmc_devices_info *gpmc_device = pdev->dev.platform_data;
    	void *p;
    
    	/* XXX: This should go away with HWMOD & runtime PM adaptation */
    	gpmc_clk_init(&pdev->dev);
    
    	gpmc_dev = &pdev->dev;
    
    	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
    	if (!gpmc)
    		return -ENOMEM;
    
    	gpmc->dev = &pdev->dev;
    
    	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    	if (!res) {
    		ret = -ENOENT;
    		dev_err(gpmc->dev, "Failed to get resource: memory\n");
    		goto err_res;
    	}
    	gpmc->phys_base = res->start;
    	gpmc->memsize = resource_size(res);
    
    	if (request_mem_region(gpmc->phys_base,
    		gpmc->memsize, DRIVER_NAME) == NULL) {
    		ret = -ENOMEM;
    		dev_err(gpmc->dev, "Failed to request memory region\n");
    		goto err_mem;
    	}
    
    	gpmc->io_base = ioremap(gpmc->phys_base, gpmc->memsize);
    	if (!gpmc->io_base) {
    		ret = -ENOMEM;
    		dev_err(gpmc->dev, "Failed to ioremap memory\n");
    		goto err_remap;
    	}
    
    	gpmc->ecc_used = -EINVAL;
    	spin_lock_init(&gpmc->mem_lock);
    	platform_set_drvdata(pdev, gpmc);
    
    	l = gpmc_read_reg(GPMC_REVISION);
    	dev_info(gpmc->dev, "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
    
    	gpmc_mem_init();
    
    	for (p = gpmc_device->pdata; p; gpmc_device++, p = gpmc_device->pdata)
    		if (gpmc_device->flag & GPMC_DEVICE_NAND)
    			gpmc_nand_init((struct omap_nand_platform_data *) p);
    	return 0;
    
    err_remap:
    	release_mem_region(gpmc->phys_base, gpmc->memsize);
    err_mem:
    err_res:
    	devm_kfree(&pdev->dev, gpmc);
    	return ret;
    }
    
    static int __devexit gpmc_remove(struct platform_device *pdev)
    {
    	struct gpmc *gpmc = platform_get_drvdata(pdev);
    
    	platform_set_drvdata(pdev, NULL);
    	iounmap(gpmc->io_base);
    	release_mem_region(gpmc->phys_base, gpmc->memsize);
    	devm_kfree(&pdev->dev, gpmc);
    
    	return 0;
    }
    
    static struct platform_driver gpmc_driver = {
    	.probe		= gpmc_probe,
    	.remove		= __devexit_p(gpmc_remove),
    	.driver		= {
    		.name	= DRIVER_NAME,
    		.owner	= THIS_MODULE,
    	},
    };
    
    module_platform_driver(gpmc_driver);
    
    int gpmc_suspend(void)
    {
    	omap3_gpmc_save_context();
    	pm_runtime_put_sync(gpmc_dev);
    	return 0;
    }
    
    int gpmc_resume(void)
    {
    	pm_runtime_get_sync(gpmc_dev);
    	omap3_gpmc_restore_context();
    	return 0;
    }
    
    #ifdef CONFIG_ARCH_OMAP3
    static struct omap3_gpmc_regs gpmc_context;
    
    void omap3_gpmc_save_context(void)
    {
    	int i;
    
    	gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
    	gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
    	gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
    	gpmc_context.config = gpmc_read_reg(GPMC_CONFIG);
    	gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
    	gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
    	gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
    	for (i = 0; i < GPMC_CS_NUM; i++) {
    		gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
    		if (gpmc_context.cs_context[i].is_valid) {
    			gpmc_context.cs_context[i].config1 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
    			gpmc_context.cs_context[i].config2 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
    			gpmc_context.cs_context[i].config3 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
    			gpmc_context.cs_context[i].config4 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
    			gpmc_context.cs_context[i].config5 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
    			gpmc_context.cs_context[i].config6 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
    			gpmc_context.cs_context[i].config7 =
    				gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
    		}
    	}
    }
    
    void omap3_gpmc_restore_context(void)
    {
    	int i;
    
    	gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
    	gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
    	gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
    	gpmc_write_reg(GPMC_CONFIG, gpmc_context.config);
    	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
    	gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
    	gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
    	for (i = 0; i < GPMC_CS_NUM; i++) {
    		if (gpmc_context.cs_context[i].is_valid) {
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
    				gpmc_context.cs_context[i].config1);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
    				gpmc_context.cs_context[i].config2);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
    				gpmc_context.cs_context[i].config3);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
    				gpmc_context.cs_context[i].config4);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
    				gpmc_context.cs_context[i].config5);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
    				gpmc_context.cs_context[i].config6);
    			gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
    				gpmc_context.cs_context[i].config7);
    		}
    	}
    }
    #endif /* CONFIG_ARCH_OMAP3 */
    
    /**
     * gpmc_enable_hwecc - enable hardware ecc functionality
     * @ecc_type: ecc type e.g. Hamming, BCH
     * @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 ecc_type, int cs, int mode,
    			int dev_width, int ecc_size)
    {
    	unsigned int bch_mod = 0, bch_wrapmode = 0, eccsize1 = 0, eccsize0 = 0;
    	unsigned int ecc_conf_val = 0, ecc_size_conf_val = 0;
    
    	switch (mode) {
    	case GPMC_ECC_READ:
    		if (ecc_type == OMAP_ECC_BCH4_CODE_HW) {
    			eccsize1 = 0xD; eccsize0 = 0x48;
    			bch_mod = 0;
    			bch_wrapmode = 0x09;
    		} else if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
    			eccsize1 = 0x2; eccsize0 = 0x1A;
    			bch_mod = 1;
    			bch_wrapmode = 0x01;
    		} else
    			eccsize1 = ((ecc_size >> 1) - 1);
    		break;
    	case GPMC_ECC_READSYN:
    		break;
    	case GPMC_ECC_WRITE:
    		if (ecc_type == OMAP_ECC_BCH4_CODE_HW) {
    			eccsize1 = 0x20; eccsize0 = 0x00;
    			bch_mod = 0;
    			bch_wrapmode = 0x06;
    		} else if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
    			eccsize1 = 0x00; eccsize0 = 0x00;
    			bch_mod = 1;
    			bch_wrapmode = 0x01;
    		} else
    			eccsize1 = ((ecc_size >> 1) - 1);
    		break;
    	default:
    		printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
    		break;
    	}
    
    	/* clear ecc and enable bits */
    	if ((ecc_type == OMAP_ECC_BCH4_CODE_HW) ||
    		(ecc_type == OMAP_ECC_BCH8_CODE_HW)) {
    		gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000001);
    		ecc_size_conf_val = (eccsize1 << 22) | (eccsize0 << 12);
    		ecc_conf_val = ((0x01 << 16) | (bch_mod << 12)
    			| (bch_wrapmode << 8) | (dev_width << 7)
    			| (0x00 << 4) | (cs << 1) | (0x1));
    	} else {
    		gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000101);
    		ecc_size_conf_val = (eccsize1 << 22) | 0x0000000F;
    		ecc_conf_val = (dev_width << 7) | (cs << 1) | (0x1);
    	}
    
    	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, ecc_size_conf_val);
    	gpmc_write_reg(GPMC_ECC_CONFIG, ecc_conf_val);
    	gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000101);
    	return 0;
    }
    EXPORT_SYMBOL(gpmc_enable_hwecc);
    
    /**
     * gpmc_calculate_ecc - generate non-inverted ecc bytes
     * @ecc_type: ecc type e.g. Hamming, BCH
     * @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 ecc_type, int cs,
    		const u_char *dat, u_char *ecc_code)
    {
    	unsigned int reg;
    	unsigned int val1 = 0x0, val2 = 0x0;
    	unsigned int val3 = 0x0, val4 = 0x0;
    	int i;
    
    	if ((ecc_type == OMAP_ECC_BCH4_CODE_HW) ||
    		(ecc_type == OMAP_ECC_BCH8_CODE_HW)) {
    		for (i = 0; i < 1; i++) {
    			/*
    			 * Reading HW ECC_BCH_Results
    			 * 0x240-0x24C, 0x250-0x25C, 0x260-0x26C, 0x270-0x27C
    			 */
    			reg =  GPMC_ECC_BCH_RESULT_0 + (0x10 * i);
    			val1 = gpmc_read_reg(reg);
    			val2 = gpmc_read_reg(reg + 4);
    			if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
    				val3 = gpmc_read_reg(reg + 8);
    				val4 = gpmc_read_reg(reg + 12);
    
    				*ecc_code++ = (val4 & 0xFF);
    				*ecc_code++ = ((val3 >> 24) & 0xFF);
    				*ecc_code++ = ((val3 >> 16) & 0xFF);
    				*ecc_code++ = ((val3 >> 8) & 0xFF);
    				*ecc_code++ = (val3 & 0xFF);
    				*ecc_code++ = ((val2 >> 24) & 0xFF);
    			}
    			*ecc_code++ = ((val2 >> 16) & 0xFF);
    			*ecc_code++ = ((val2 >> 8) & 0xFF);
    			*ecc_code++ = (val2 & 0xFF);
    			*ecc_code++ = ((val1 >> 24) & 0xFF);
    			*ecc_code++ = ((val1 >> 16) & 0xFF);
    			*ecc_code++ = ((val1 >> 8) & 0xFF);
    			*ecc_code++ = (val1 & 0xFF);
    		}
    	} else {
    		/* read ecc result */
    		val1 = gpmc_read_reg(GPMC_ECC1_RESULT);
    		*ecc_code++ = val1;          /* P128e, ..., P1e */
    		*ecc_code++ = val1 >> 16;    /* P128o, ..., P1o */
    		/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
    		*ecc_code++ = ((val1 >> 8) & 0x0f) | ((val1 >> 20) & 0xf0);
    	}
    	return 0;
    }
    EXPORT_SYMBOL(gpmc_calculate_ecc);
    

    /*
     * gpmc-nand.c
     *
     * Copyright (C) 2009 Texas Instruments
     * Vimal Singh <vimalsingh@ti.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/io.h>
    #include <linux/mtd/nand.h>
    
    #include <asm/mach/flash.h>
    
    #include <plat/nand.h>
    #include <plat/board.h>
    #include <plat/gpmc.h>
    
    static struct resource gpmc_nand_resource = {
    	.flags		= IORESOURCE_MEM,
    };
    
    static struct platform_device gpmc_nand_device = {
    	.name		= "omap2-nand",
    	.id		= 0,
    	.num_resources	= 1,
    	.resource	= &gpmc_nand_resource,
    };
    
    static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	struct gpmc_timings t;
    	int err;
    
    	if (!gpmc_nand_data->gpmc_t)
    		return 0;
    
    	memset(&t, 0, sizeof(t));
    	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
    	t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
    	t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
    
    	/* Read */
    	t.adv_rd_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_rd_off);
    	t.oe_on  = t.adv_on;
    	t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access);
    	t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off);
    	t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off);
    	t.rd_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle);
    
    	/* Write */
    	t.adv_wr_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_wr_off);
    	t.we_on  = t.oe_on;
    	if (cpu_is_omap34xx()) {
    	    t.wr_data_mux_bus =	gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_data_mux_bus);
    	    t.wr_access = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_access);
    	}
    	t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off);
    	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
    	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
    
    	/* Configure GPMC */
    	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
    	else
    		gpmc_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);
    	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
    	if (err)
    		return err;
    
    	return 0;
    }
    
    int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	int err	= 0;
    	u8 cs = 0;
    	struct device *dev = &gpmc_nand_device.dev;
    
    	pr_emerg("%s() %d\n", __func__, gpmc_nand_data->cs);
    	/* if cs not provided, find out the chip-select on which NAND exist */
    	if (gpmc_nand_data->cs > GPMC_CS_NUM)
    		while (cs < GPMC_CS_NUM) {
    			u32 ret = 0;
    			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
    
    			if ((ret & 0xC00) == 0x800) {
    				printk(KERN_INFO "Found NAND on CS%d\n", cs);
    				gpmc_nand_data->cs = cs;
    				break;
    			}
    			cs++;
    		}
    
    	if (gpmc_nand_data->cs > GPMC_CS_NUM) {
    		printk(KERN_INFO "NAND: Unable to find configuration "
    				 "in GPMC\n ");
    		return -ENODEV;
    	}
    
    	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
    	gpmc_nand_data->ctrlr_suspend	= gpmc_suspend;
    	gpmc_nand_data->ctrlr_resume	= gpmc_resume;
    
    	printk(KERN_INFO "Registering NAND on CS%d\n", gpmc_nand_data->cs);
    
    	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
    				&gpmc_nand_data->phys_base);
    	if (err < 0) {
    		dev_err(dev, "Cannot request GPMC CS\n");
    		return err;
    	}
    
    	 /* Set timings in GPMC */
    	err = omap2_nand_gpmc_retime(gpmc_nand_data);
    	if (err < 0) {
    		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
    		return err;
    	}
    
    	/* Enable RD PIN Monitoring Reg */
    	if (gpmc_nand_data->dev_ready) {
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
    	}
    
    	err = platform_device_register(&gpmc_nand_device);
    	if (err < 0) {
    		dev_err(dev, "Unable to register NAND device\n");
    		goto out_free_cs;
    	}
    
    	return 0;
    
    out_free_cs:
    	gpmc_cs_free(gpmc_nand_data->cs);
    
    	return err;
    }
    

    Try using above files and please update.

    Thanks Avinash

  • Thank you Avinash advice

    I'm try your modify code update all gpmc*.c  and gpmc_device[2] = { ....{NULL,0)}

    and kernel loding log...blew

    ++++++++++++++

    [ 0.095844] NET: Registered protocol family 16
    [ 0.098001] OMAP GPIO hardware version 0.1
    [ 0.100387] omap_mux_init: Add partition: #1: core, flags: 0
    [ 0.102180] am335x_evm_i2c_init .new kernel
    [ 0.102238] omap_i2c.1: alias fck already exists
    [ 0.102438] setup_general_purpose_evm diggo change
    [ 0.103192] omap_nand_init 0 ++ i'm log...CS0
    [ 0.103200] evm_nand_init 0
    [ 0.103207] omap_nand_init 1
    [ 0.103214] evm_nand_init 1 ++ i'm log ...CS1

    ......

    [ 0.151604] NetWinder Floating Point Emulator V0.97 (double precision)
    [ 0.151820] omap-gpmc omap-gpmc: GPMC revision 6.0
    [ 0.151838] gpmc_nand_init() 1
    [ 0.151847] Registering NAND on CS1
    [ 0.151856] gpmc_cs_request() 458
    [ 0.151864] gpmc_cs_request() 462
    [ 0.151872] gpmc_cs_request() 467
    [ 0.151880] gpmc_cs_request() 473
    [ 0.151892] gpmc_cs_request() 479
    [ 0.152396] gpmc_nand_init() 1
    [ 0.152407] Registering NAND on CS1
    [ 0.152416] gpmc_cs_request() 458
    [ 0.152424] gpmc_cs_request() 462
    [ 0.152432] gpmc_cs_request() 467
    [ 0.152443] platform omap2-nand.0: Cannot request GPMC CS
    [ 0.159793] VFS: Disk quotas dquot_6.5.2
    [ 0.159862] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
    [ 0.160425] msgmni has been set to 243
    [ 0.163682] alg: No test for stdrng (krng)
    [ 0.164399] io scheduler noop registered
    [ 0.164413] io scheduler deadline registered
    [ 0.164477] io scheduler cfq registered (default)
    [ 0.165127] omap_uart.0: ttyO0 at MMIO 0x44e09000 (irq = 72) is a OMAP UART0
    [ 0.801828] console [ttyO0] enabled
    [ 0.806137] omap_uart.1: ttyO1 at MMIO 0x48022000 (irq = 73) is a OMAP UART1
    [ 0.813981] omap_uart.2: ttyO2 at MMIO 0x48024000 (irq = 74) is a OMAP UART2
    [ 0.821773] omap_uart.3: ttyO3 at MMIO 0x481a6000 (irq = 44) is a OMAP UART3
    [ 0.829545] omap_uart.4: ttyO4 at MMIO 0x481a8000 (irq = 45) is a OMAP UART4
    [ 0.837329] omap_uart.5: ttyO5 at MMIO 0x481aa000 (irq = 46) is a OMAP UART5
    [ 0.854370] brd: module loaded
    [ 0.862450] loop: module loaded
    [ 0.867962] mtdoops: mtd device (mtddev=name/number) must be supplied
    [ 0.875248] omap2-nand driver initializing
    [ 0.879584] omap_nand_probe 1
    [ 0.883018] NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
    [ 0.892236] Creating 1 MTD partitions on "omap2-nand.0":
    [ 0.897784] 0x000000000000-0x000010000000 : "data"
    [ 1.061088] davinci_mdio davinci_mdio.0: davinci mdio revision 1.6
    [ 1.067540] davinci_mdio davinci_mdio.0: detected phy mask fffffff9
    [ 1.075294] davinci_mdio.0: probed
    [ 1.078848] davinci_mdio davinci_mdio.0: phy[1]: device 0:01, driver unknown
    [ 1.086226] davinci_mdio davinci_mdio.0: phy[2]: device 0:02, driver unknown
    [ 1.093946] usbcore: registered new interface driver cdc_ether
    [ 1.100169] usbcore: registered new interface driver cdc_eem
    [ 1.106236] usbcore: registered new interface driver dm9601

    --- 

    print your update debug code ...

    same problem ....CS0 is disable ...and CS1 is able ...ONLY ONE 

    NOW if select only one... of CS0 or CS1 , and detect ...

    Add print log..

    if is enable gpmc.c 's DEBUG blew  print log

    [ 0.170245] GPMC CS1: cs_on : 0 ticks, 0 ns (was 1 ticks) 0 ns
    [ 0.170262] GPMC CS1: cs_rd_off : 5 ticks, 50 ns (was 16 ticks) 50 ns
    [ 0.170277] GPMC CS1: cs_wr_off : 5 ticks, 50 ns (was 16 ticks) 50 ns
    [ 0.170292] GPMC CS1: adv_on : 1 ticks, 10 ns (was 4 ticks) 10 ns
    [ 0.170308] GPMC CS1: adv_rd_off: 4 ticks, 40 ns (was 5 ticks) 40 ns
    [ 0.170323] GPMC CS1: adv_wr_off: 5 ticks, 50 ns (was 6 ticks) 50 ns
    [ 0.170338] GPMC CS1: oe_on : 1 ticks, 10 ns (was 6 ticks) 10 ns
    [ 0.170353] GPMC CS1: oe_off : 6 ticks, 60 ns (was 16 ticks) 60 ns
    [ 0.170368] GPMC CS1: we_on : 1 ticks, 10 ns (was 5 ticks) 10 ns
    [ 0.170384] GPMC CS1: we_off : 4 ticks, 40 ns (was 16 ticks) 40 ns
    [ 0.170399] GPMC CS1: rd_cycle : 9 ticks, 90 ns (was 17 ticks) 90 ns
    [ 0.170414] GPMC CS1: wr_cycle : 9 ticks, 90 ns (was 17 ticks) 90 ns
    [ 0.170429] GPMC CS1: access : 7 ticks, 70 ns (was 15 ticks) 70 ns
    [ 0.170444] GPMC CS1: page_burst_access: 0 ticks, 0 ns (was 1 ticks) 0 ns
    [ 0.170459] GPMC CS1: wr_data_mux_bus: 0 ticks, 0 ns (was 7 ticks) 0 ns
    [ 0.170475] GPMC CS1: wr_access : 4 ticks, 40 ns (was 15 ticks) 40 ns

    Please What's problem ?

    Thank you

    Kind Regards,

  • Hi,

    In omap_nand_init, modifying static structure and by the time,

    you requested for GPMC chip select 1,

    pdata->cs= pdata2->cs =1 as pdata = pdata2.

    so can you consider following modification in your board-am335x file and try.

    @@ -1296,9 +1296,11 @@ static void evm_nand_init(int evm_id, int profile)
                    return;                                                   
            pdata->ecc_opt =OMAP_ECC_BCH8_CODE_HW;                            
            pdata->elm_used = true;                                           
    -       gpmc_device[0].pdata = pdata;                                     
    +       gpmc_device[0].pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);       
    +       memcpy(gpmc_device[0].pdata, pdata, sizeof(*pdata));

    ---

    -       gpmc_device[1].pdata = pdata2;                                     
    +       gpmc_device[1].pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);       
    +       memcpy(gpmc_device[1].pdata, pdata2, sizeof(*pdata2));

    Thanks Avinash

  • Thank you Avinash advice

    your's advice correct . i'm modify your code.- allocte memery it

    CS0 ,CS1 Registered but kernel panic generate it.

    [ 0.103244] omap_nand_init 0
    [ 0.103254] evm_nand_init 0
    [ 0.103261] omap_nand_init 1
    [ 0.103269] evm_nand_init 1

    [ 0.151843] omap-gpmc omap-gpmc: GPMC revision 6.0
    [ 0.151862] gpmc_nand_init() 0
    [ 0.151871] Registering NAND on CS0
    [ 0.152386] gpmc_nand_init() 1
    [ 0.152397] Registering NAND on CS1
    [ 0.152435] kobject (c04fbf90): tried to init an initialized object, something is seriously wrong.
    [ 0.152450] Backtrace:
    [ 0.152499] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f630>] (dump_stack+0x18/0x1c)
    [ 0.152514] r6:00000000 r5:c051b710 r4:c04fbf90 r3:c04fcbc8
    [ 0.152551] [<c036f618>] (dump_stack+0x0/0x1c) from [<c01cbdd8>] (kobject_init+0x8c/0x9c)
    [ 0.152579] [<c01cbd4c>] (kobject_init+0x0/0x9c) from [<c0211d9c>] (device_initialize+0x30/0x68)
    [ 0.152592] r5:c0553bd0 r4:c04fbf88
    [ 0.152614] [<c0211d6c>] (device_initialize+0x0/0x68) from [<c0217158>] (platform_device_register+0x18/0x2c)
    [ 0.152629] r5:c04fbf80 r4:c04fbf80
    [ 0.152650] [<c0217140>] (platform_device_register+0x0/0x2c) from [<c0369ec0>] (gpmc_nand_init+0x280/0x2b4)
    [ 0.152665] r4:c7861440 r3:00000000
    [ 0.152684] [<c0369c40>] (gpmc_nand_init+0x0/0x2b4) from [<c0369b18>] (gpmc_probe+0x298/0x2d4)
    [ 0.152697] r6:00000008 r5:c0533cec r4:0000001c
    [ 0.152728] [<c0369880>] (gpmc_probe+0x0/0x2d4) from [<c0216844>] (platform_drv_probe+0x20/0x24)
    [ 0.152742] r8:00000000 r7:c04e53f0 r6:c052ec88 r5:c0553bf0 r4:c7868e08
    [ 0.152774] [<c0216824>] (platform_drv_probe+0x0/0x24) from [<c021525c>] (driver_probe_device+0xc0/0x2dc)
    [ 0.152798] [<c021519c>] (driver_probe_device+0x0/0x2dc) from [<c021550c>] (__driver_attach+0x94/0x98)
    [ 0.152812] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.152842] [<c0215478>] (__driver_attach+0x0/0x98) from [<c02141c0>] (bus_for_each_dev+0x58/0x84)
    [ 0.152856] r6:00000000 r5:c0215478 r4:c04e53f0 r3:c0215478
    [ 0.152883] [<c0214168>] (bus_for_each_dev+0x0/0x84) from [<c0214e54>] (driver_attach+0x24/0x28)
    [ 0.152896] r6:c790c840 r5:c051b850 r4:c04e53f0
    [ 0.152920] [<c0214e30>] (driver_attach+0x0/0x28) from [<c0214ac0>] (bus_add_driver+0x19c/0x26c)
    [ 0.152943] [<c0214924>] (bus_add_driver+0x0/0x26c) from [<c0215ab0>] (driver_register+0x80/0x138)
    [ 0.152965] [<c0215a30>] (driver_register+0x0/0x138) from [<c0216d14>] (platform_driver_register+0x5c/0x60)
    [ 0.152979] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf24 r4:c0533780
    [ 0.152999] r3:00000000
    [ 0.153021] [<c0216cb8>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.153045] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.153074] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.153106] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.153118] r5:c04a87e8 r4:00000000
    [ 0.153139] ------------[ cut here ]------------
    [ 0.153159] WARNING: at kernel/resource.c:597 __insert_resource+0x148/0x14c()
    [ 0.153170] Modules linked in:
    [ 0.153178] Backtrace:
    [ 0.153197] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f630>] (dump_stack+0x18/0x1c)
    [ 0.153210] r6:c04360d4 r5:00000255 r4:00000000 r3:c04fcbc8
    [ 0.153237] [<c036f618>] (dump_stack+0x0/0x1c) from [<c003c708>] (warn_slowpath_common+0x5c/0x6c)
    [ 0.153260] [<c003c6ac>] (warn_slowpath_common+0x0/0x6c) from [<c003c73c>] (warn_slowpath_null+0x24/0x2c)
    [ 0.153273] r8:00000001 r7:c7865888 r6:c04fcc7c r5:c04fc0d0 r4:c04fc0d0
    [ 0.153293] r3:00000009
    [ 0.153311] [<c003c718>] (warn_slowpath_null+0x0/0x2c) from [<c00426bc>] (__insert_resource+0x148/0x14c)
    [ 0.153335] [<c0042574>] (__insert_resource+0x0/0x14c) from [<c004304c>] (insert_resource+0x10/0x1c)
    [ 0.153348] r6:c04fbf88 r5:c04fbf80 r4:00000000 r3:c790fc40
    [ 0.153373] [<c004303c>] (insert_resource+0x0/0x1c) from [<c0216e84>] (platform_device_add+0x80/0x204)
    [ 0.153395] [<c0216e04>] (platform_device_add+0x0/0x204) from [<c0217168>] (platform_device_register+0x28/0x2c)
    [ 0.153409] r7:c7865888 r6:00000000 r5:c04fbf80 r4:c04fbf80
    [ 0.153435] [<c0217140>] (platform_device_register+0x0/0x2c) from [<c0369ec0>] (gpmc_nand_init+0x280/0x2b4)
    [ 0.153449] r4:c7861440 r3:00000000
    [ 0.153468] [<c0369c40>] (gpmc_nand_init+0x0/0x2b4) from [<c0369b18>] (gpmc_probe+0x298/0x2d4)
    [ 0.153481] r6:00000008 r5:c0533cec r4:0000001c
    [ 0.153506] [<c0369880>] (gpmc_probe+0x0/0x2d4) from [<c0216844>] (platform_drv_probe+0x20/0x24)
    [ 0.153519] r8:00000000 r7:c04e53f0 r6:c052ec88 r5:c0553bf0 r4:c7868e08
    [ 0.153550] [<c0216824>] (platform_drv_probe+0x0/0x24) from [<c021525c>] (driver_probe_device+0xc0/0x2dc)
    [ 0.153574] [<c021519c>] (driver_probe_device+0x0/0x2dc) from [<c021550c>] (__driver_attach+0x94/0x98)
    [ 0.153587] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.153618] [<c0215478>] (__driver_attach+0x0/0x98) from [<c02141c0>] (bus_for_each_dev+0x58/0x84)
    [ 0.153631] r6:00000000 r5:c0215478 r4:c04e53f0 r3:c0215478
    [ 0.153658] [<c0214168>] (bus_for_each_dev+0x0/0x84) from [<c0214e54>] (driver_attach+0x24/0x28)
    [ 0.153672] r6:c790c840 r5:c051b850 r4:c04e53f0
    [ 0.153696] [<c0214e30>] (driver_attach+0x0/0x28) from [<c0214ac0>] (bus_add_driver+0x19c/0x26c)
    [ 0.153718] [<c0214924>] (bus_add_driver+0x0/0x26c) from [<c0215ab0>] (driver_register+0x80/0x138)
    [ 0.153740] [<c0215a30>] (driver_register+0x0/0x138) from [<c0216d14>] (platform_driver_register+0x5c/0x60)
    [ 0.153754] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf24 r4:c0533780
    [ 0.153773] r3:00000000
    [ 0.153789] [<c0216cb8>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.153811] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.153832] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.153853] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.153866] r5:c04a87e8 r4:00000000
    [ 0.153909] ---[ end trace 65f8ea860415c04f ]---
    [ 0.153921] omap2-nand.0: failed to claim resource 0
    [ 0.153933] platform omap2-nand.0: Unable to register NAND device
    [ 0.161435] VFS: Disk quotas dquot_6.5.2
    [ 0.161503] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
    [ 0.162060] msgmni has been set to 243
    [ 0.165239] alg: No test for stdrng (krng)
    [ 0.165941] io scheduler noop registered
    [ 0.165957] io scheduler deadline registered
    [ 0.166022] io scheduler cfq registered (default)
    [ 0.166671] omap_uart.0: ttyO0 at MMIO 0x44e09000 (irq = 72) is a OMAP UART0
    [ 1.317243] console [ttyO0] enabled
    [ 1.321701] omap_uart.1: ttyO1 at MMIO 0x48022000 (irq = 73) is a OMAP UART1
    [ 1.329526] omap_uart.2: ttyO2 at MMIO 0x48024000 (irq = 74) is a OMAP UART2
    [ 1.337348] omap_uart.3: ttyO3 at MMIO 0x481a6000 (irq = 44) is a OMAP UART3
    [ 1.345139] omap_uart.4: ttyO4 at MMIO 0x481a8000 (irq = 45) is a OMAP UART4
    [ 1.352911] omap_uart.5: ttyO5 at MMIO 0x481aa000 (irq = 46) is a OMAP UART5
    [ 1.369857] brd: module loaded
    [ 1.377987] loop: module loaded
    [ 1.383524] mtdoops: mtd device (mtddev=name/number) must be supplied
    [ 1.390742] omap2-nand driver initializing

    BUT IF is select only one 's nand cs0 or cs1 

    kernel panic not print..

    Please i'm wait your good advice.

    Thank you

    Kind Regards,



  • Hi,

    Thanks for the patience and support shown on testing.

    I don't have board with multiple NAND sitting on chip select.

    can you please add following patch also

    diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
    index 0207a66..7c66870 100644
    --- a/arch/arm/mach-omap2/gpmc-nand.c
    +++ b/arch/arm/mach-omap2/gpmc-nand.c
    @@ -24,13 +24,6 @@ static struct resource gpmc_nand_resource = {
            .flags          = IORESOURCE_MEM,
     };

    -static struct platform_device gpmc_nand_device = {
    -       .name           = "omap2-nand",
    -       .id             = 0,
    -       .num_resources  = 1,
    -       .resource       = &gpmc_nand_resource,
    -};
    -
     static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
     {
            struct gpmc_timings t;
    @@ -85,8 +78,16 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
     {
            int err = 0;
            u8 cs = 0;
    -       struct device *dev = &gpmc_nand_device.dev;
    +       struct device *dev;
    +       static struct platform_device *gpmc_nand_device;
    +
    +       gpmc_nand_device = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
    +       dev = &gpmc_nand_device.dev;
    +
    +       gpmc_nand_device->resource = &gpmc_nand_resource;
    +       gpmc_nand_device->num_resources = 1,

    @@ -107,7 +108,7 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
                    return -ENODEV;
            }

    -       gpmc_nand_device.dev.platform_data = gpmc_nand_data;
    +       gpmc_nand_device->dev.platform_data = gpmc_nand_data;
            gpmc_nand_data->ctrlr_suspend   = gpmc_suspend;
            gpmc_nand_data->ctrlr_resume    = gpmc_resume;

    @@ -132,7 +133,7 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
                    gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
            }

    -       err = platform_device_register(&gpmc_nand_device);
    +       err = platform_device_register(gpmc_nand_device);

    Thanks Avinash

  • Thank you Avinash advice

    your's advice it .

    so increasingly solve problem .

    i'm modify your code.- allocte memery it

    some edit your code it below

      function's gpmc_nand_init

         struct device *dev;

        static struct platform_device *gpmc_nand_device;
       gpmc_nand_device = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
        dev = &gpmc_nand_device->dev;
        gpmc_nand_device->resource = &gpmc_nand_resource;
        gpmc_nand_device->num_resources = 1;

         ......

         dev->platform_data = gpmc_nand_data;

        ......

         err = platform_device_register(gpmc_nand_device);

       ... 

    then...kernel loading and print it

         *******************

    [ 0.103230] omap_nand_init 0

    [ 0.103241] omap_nand_init 1

    .....

    [ 0.151855] omap-gpmc omap-gpmc: GPMC revision 6.0

    [ 0.151881] gpmc_nand_init() 0
    [ 0.151889] Registering NAND on CS0
    [ 0.151934] kobject (c78fc410): tried to init an initialized object, something is seriously wrong.
    [ 0.151948] Backtrace:
    [ 0.151997] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f660>] (dump_stack+0x18/0x1c)
    [ 0.152012] r6:00000000 r5:c051b5d0 r4:c78fc410 r3:c04fca88
    [ 0.152048] [<c036f648>] (dump_stack+0x0/0x1c) from [<c01cbdd8>] (kobject_init+0x8c/0x9c)
    [ 0.152077] [<c01cbd4c>] (kobject_init+0x0/0x9c) from [<c0211d9c>] (device_initialize+0x30/0x68)
    [ 0.152090] r5:c0553a90 r4:c78fc408
    [ 0.152113] [<c0211d6c>] (device_initialize+0x0/0x68) from [<c0217158>] (platform_device_register+0x18/0x2c)
    [ 0.152127] r5:c78fc408 r4:c78fc400
    [ 0.152147] [<c0217140>] (platform_device_register+0x0/0x2c) from [<c0369ef4>] (gpmc_nand_init+0x2b4/0x2e4)
    [ 0.152162] r4:c78614c0 r3:c0534408
    [ 0.152182] [<c0369c40>] (gpmc_nand_init+0x0/0x2e4) from [<c0369b18>] (gpmc_probe+0x298/0x2d4)
    [ 0.152195] r6:00000008 r5:c0533bac r4:0000001c
    [ 0.152225] [<c0369880>] (gpmc_probe+0x0/0x2d4) from [<c0216844>] (platform_drv_probe+0x20/0x24)
    [ 0.152239] r8:00000000 r7:c04e53f0 r6:c052eb48 r5:c0553ab0 r4:c7868e08
    [ 0.152271] [<c0216824>] (platform_drv_probe+0x0/0x24) from [<c021525c>] (driver_probe_device+0xc0/0x2dc)
    [ 0.152295] [<c021519c>] (driver_probe_device+0x0/0x2dc) from [<c021550c>] (__driver_attach+0x94/0x98)
    [ 0.152309] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.152339] [<c0215478>] (__driver_attach+0x0/0x98) from [<c02141c0>] (bus_for_each_dev+0x58/0x84)
    [ 0.152352] r6:00000000 r5:c0215478 r4:c04e53f0 r3:c0215478
    [ 0.152379] [<c0214168>] (bus_for_each_dev+0x0/0x84) from [<c0214e54>] (driver_attach+0x24/0x28)
    [ 0.152392] r6:c790c840 r5:c051b710 r4:c04e53f0
    [ 0.152416] [<c0214e30>] (driver_attach+0x0/0x28) from [<c0214ac0>] (bus_add_driver+0x19c/0x26c)
    [ 0.152439] [<c0214924>] (bus_add_driver+0x0/0x26c) from [<c0215ab0>] (driver_register+0x80/0x138)
    [ 0.152462] [<c0215a30>] (driver_register+0x0/0x138) from [<c0216d14>] (platform_driver_register+0x5c/0x60)
    [ 0.152476] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf04 r4:c0533640
    [ 0.152495] r3:00000000
    [ 0.152517] [<c0216cb8>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.152541] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.152570] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.152601] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.152613] r5:c04a87e8 r4:00000000
    [ 0.153107] gpmc_nand_init() 1
    [ 0.153120] Registering NAND on CS1
    [ 0.153159] kobject (c78fc210): tried to init an initialized object, something is seriously wrong.
    [ 0.153171] Backtrace:
    [ 0.153198] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f660>] (dump_stack+0x18/0x1c)
    [ 0.153212] r6:00000000 r5:c051b5d0 r4:c78fc210 r3:c04fca88
    [ 0.153242] [<c036f648>] (dump_stack+0x0/0x1c) from [<c01cbdd8>] (kobject_init+0x8c/0x9c)
    [ 0.153266] [<c01cbd4c>] (kobject_init+0x0/0x9c) from [<c0211d9c>] (device_initialize+0x30/0x68)
    [ 0.153279] r5:c0553a90 r4:c78fc208
    [ 0.153300] [<c0211d6c>] (device_initialize+0x0/0x68) from [<c0217158>] (platform_device_register+0x18/0x2c)
    [ 0.153314] r5:c78fc208 r4:c78fc200
    [ 0.153334] [<c0217140>] (platform_device_register+0x0/0x2c) from [<c0369ef4>] (gpmc_nand_init+0x2b4/0x2e4)
    [ 0.153348] r4:c7861440 r3:c0534408
    [ 0.153367] [<c0369c40>] (gpmc_nand_init+0x0/0x2e4) from [<c0369b18>] (gpmc_probe+0x298/0x2d4)
    [ 0.153380] r6:00000008 r5:c0533bac r4:0000001c
    [ 0.153408] [<c0369880>] (gpmc_probe+0x0/0x2d4) from [<c0216844>] (platform_drv_probe+0x20/0x24)
    [ 0.153421] r8:00000000 r7:c04e53f0 r6:c052eb48 r5:c0553ab0 r4:c7868e08
    [ 0.153453] [<c0216824>] (platform_drv_probe+0x0/0x24) from [<c021525c>] (driver_probe_device+0xc0/0x2dc)
    [ 0.153477] [<c021519c>] (driver_probe_device+0x0/0x2dc) from [<c021550c>] (__driver_attach+0x94/0x98)
    [ 0.153490] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.153521] [<c0215478>] (__driver_attach+0x0/0x98) from [<c02141c0>] (bus_for_each_dev+0x58/0x84)
    [ 0.153534] r6:00000000 r5:c0215478 r4:c04e53f0 r3:c0215478
    [ 0.153561] [<c0214168>] (bus_for_each_dev+0x0/0x84) from [<c0214e54>] (driver_attach+0x24/0x28)
    [ 0.153575] r6:c790c840 r5:c051b710 r4:c04e53f0
    [ 0.153599] [<c0214e30>] (driver_attach+0x0/0x28) from [<c0214ac0>] (bus_add_driver+0x19c/0x26c)
    [ 0.153621] [<c0214924>] (bus_add_driver+0x0/0x26c) from [<c0215ab0>] (driver_register+0x80/0x138)
    [ 0.153643] [<c0215a30>] (driver_register+0x0/0x138) from [<c0216d14>] (platform_driver_register+0x5c/0x60)
    [ 0.153657] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf04 r4:c0533640
    [ 0.153677] r3:00000000
    [ 0.153694] [<c0216cb8>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.153717] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.153741] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.153765] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.153778] r5:c04a87e8 r4:00000000
    [ 0.153797] ------------[ cut here ]------------
    [ 0.153817] WARNING: at kernel/resource.c:597 __insert_resource+0x148/0x14c() -- different it
    [ 0.153829] Modules linked in:
    [ 0.153837] Backtrace:
    [ 0.153855] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f660>] (dump_stack+0x18/0x1c)
    [ 0.153868] r6:c04360c0 r5:00000255 r4:00000000 r3:c04fca88
    [ 0.153895] [<c036f648>] (dump_stack+0x0/0x1c) from [<c003c708>] (warn_slowpath_common+0x5c/0x6c)
    [ 0.153917] [<c003c6ac>] (warn_slowpath_common+0x0/0x6c) from [<c003c73c>] (warn_slowpath_null+0x24/0x2c)
    [ 0.153931] r8:00000001 r7:c7865888 r6:c04fcb3c r5:c04fbf80 r4:c04fbf80
    [ 0.153951] r3:00000009
    [ 0.153968] [<c003c718>] (warn_slowpath_null+0x0/0x2c) from [<c00426bc>] (__insert_resource+0x148/0x14c)
    [ 0.153992] [<c0042574>] (__insert_resource+0x0/0x14c) from [<c004304c>] (insert_resource+0x10/0x1c)
    [ 0.154006] r6:c78fc208 r5:c78fc200 r4:00000000 r3:c790fc40
    [ 0.154031] [<c004303c>] (insert_resource+0x0/0x1c) from [<c0216e84>] (platform_device_add+0x80/0x204)
    [ 0.154052] [<c0216e04>] (platform_device_add+0x0/0x204) from [<c0217168>] (platform_device_register+0x28/0x2c)
    [ 0.154067] r7:c7865888 r6:00000000 r5:c78fc208 r4:c78fc200
    [ 0.154093] [<c0217140>] (platform_device_register+0x0/0x2c) from [<c0369ef4>] (gpmc_nand_init+0x2b4/0x2e4)
    [ 0.154107] r4:c7861440 r3:c0534408
    [ 0.154126] [<c0369c40>] (gpmc_nand_init+0x0/0x2e4) from [<c0369b18>] (gpmc_probe+0x298/0x2d4)
    [ 0.154139] r6:00000008 r5:c0533bac r4:0000001c
    [ 0.154163] [<c0369880>] (gpmc_probe+0x0/0x2d4) from [<c0216844>] (platform_drv_probe+0x20/0x24)
    [ 0.154176] r8:00000000 r7:c04e53f0 r6:c052eb48 r5:c0553ab0 r4:c7868e08
    [ 0.154207] [<c0216824>] (platform_drv_probe+0x0/0x24) from [<c021525c>] (driver_probe_device+0xc0/0x2dc)
    [ 0.154231] [<c021519c>] (driver_probe_device+0x0/0x2dc) from [<c021550c>] (__driver_attach+0x94/0x98)
    [ 0.154245] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.154275] [<c0215478>] (__driver_attach+0x0/0x98) from [<c02141c0>] (bus_for_each_dev+0x58/0x84)
    [ 0.154289] r6:00000000 r5:c0215478 r4:c04e53f0 r3:c0215478
    [ 0.154316] [<c0214168>] (bus_for_each_dev+0x0/0x84) from [<c0214e54>] (driver_attach+0x24/0x28)
    [ 0.154329] r6:c790c840 r5:c051b710 r4:c04e53f0
    [ 0.154353] [<c0214e30>] (driver_attach+0x0/0x28) from [<c0214ac0>] (bus_add_driver+0x19c/0x26c)
    [ 0.154376] [<c0214924>] (bus_add_driver+0x0/0x26c) from [<c0215ab0>] (driver_register+0x80/0x138)
    [ 0.154398] [<c0215a30>] (driver_register+0x0/0x138) from [<c0216d14>] (platform_driver_register+0x5c/0x60)
    [ 0.154412] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf04 r4:c0533640
    [ 0.154431] r3:00000000
    [ 0.154447] [<c0216cb8>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.154469] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.154491] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.154512] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.154525] r5:c04a87e8 r4:00000000
    [ 0.154568] ---[ end trace 65f8ea860415c04f ]---
    [ 0.154580] omap2-nand.1: failed to claim resource 0
    [ 0.154592] platform omap2-nand.1: Unable to register NAND device   -- different it 

    ...............

    [ 1.613025] loop: module loaded
    [ 1.618491] mtdoops: mtd device (mtddev=name/number) must be supplied
    [ 1.625802] omap2-nand driver initializing
    [ 1.630138] omap_nand_probe 0
    [ 1.633577] NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)   --- but it is CS0 , get it
    [ 1.642803] Creating 8 MTD partitions on "omap2-nand.0":
    [ 1.648352] 0x000000000000-0x000000020000 : "SPL"
    [ 1.654757] 0x000000020000-0x000000040000 : "SPL.backup1"
    [ 1.661721] 0x000000040000-0x000000060000 : "SPL.backup2"
    [ 1.668547] 0x000000060000-0x000000080000 : "SPL.backup3"
    [ 1.675462] 0x000000080000-0x000000260000 : "U-Boot"
    [ 1.682650] 0x000000260000-0x000000280000 : "U-Boot Env"
    [ 1.689427] 0x000000280000-0x000000780000 : "Kernel"
    [ 1.697945] 0x000000780000-0x000010000000 : "File System"

    *******************

    some different before modify your code it.

    1. omap2-nand 0 , omap2-nand1 generated 

    2. kernel panic step diffenernet ...

    3. detect it cs0 - add attach omap2-nand.0 

    but kernel panic same it 

    Please i'm wait Avinash's good advice.

    Thank you

    Kind Regards,

     

  • Hi,

    can you use attached gpmc-nand.c

    /*
     * gpmc-nand.c
     *
     * Copyright (C) 2009 Texas Instruments
     * Vimal Singh <vimalsingh@ti.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/io.h>
    #include <linux/mtd/nand.h>
    
    #include <asm/mach/flash.h>
    
    #include <plat/nand.h>
    #include <plat/board.h>
    #include <plat/gpmc.h>
    
    static struct resource gpmc_nand_resource = {
    	.flags		= IORESOURCE_MEM,
    };
    
    static struct resource gpmc_nand_resource1 = {
    	.start		= 4,
    	.end		= 8,
    	.flags		= IORESOURCE_MEM,
    };
    
    static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	struct gpmc_timings t;
    	int err;
    
    	if (!gpmc_nand_data->gpmc_t)
    		return 0;
    
    	memset(&t, 0, sizeof(t));
    	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
    	t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
    	t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
    
    	/* Read */
    	t.adv_rd_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_rd_off);
    	t.oe_on  = t.adv_on;
    	t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access);
    	t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off);
    	t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off);
    	t.rd_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle);
    
    	/* Write */
    	t.adv_wr_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_wr_off);
    	t.we_on  = t.oe_on;
    	if (cpu_is_omap34xx()) {
    	    t.wr_data_mux_bus =	gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_data_mux_bus);
    	    t.wr_access = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_access);
    	}
    	t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off);
    	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
    	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
    
    	/* Configure GPMC */
    	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
    	else
    		gpmc_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);
    	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
    	if (err)
    		return err;
    
    	return 0;
    }
    
    int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	int err	= 0;
    	u8 cs = 0;
    	struct device *dev;
    	static struct platform_device *gpmc_nand_device;
    
    	gpmc_nand_device = platform_device_alloc("omap2-nand",
    			gpmc_nand_data->cs);
    	dev = &gpmc_nand_device->dev;
    
    	gpmc_nand_device->resource = &gpmc_nand_resource;
    	gpmc_nand_device->num_resources	= 1;
    
    	if (gpmc_nand_data->cs == 1)
    		gpmc_nand_device->resource = &gpmc_nand_resource1;
    
    	/* if cs not provided, find out the chip-select on which NAND exist */
    	if (gpmc_nand_data->cs > GPMC_CS_NUM)
    		while (cs < GPMC_CS_NUM) {
    			u32 ret = 0;
    			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
    
    			if ((ret & 0xC00) == 0x800) {
    				printk(KERN_INFO "Found NAND on CS%d\n", cs);
    				gpmc_nand_data->cs = cs;
    				break;
    			}
    			cs++;
    		}
    
    	if (gpmc_nand_data->cs > GPMC_CS_NUM) {
    		printk(KERN_INFO "NAND: Unable to find configuration "
    				 "in GPMC\n ");
    		return -ENODEV;
    	}
    
    	gpmc_nand_device->dev.platform_data = gpmc_nand_data;
    	gpmc_nand_data->ctrlr_suspend	= gpmc_suspend;
    	gpmc_nand_data->ctrlr_resume	= gpmc_resume;
    
    	printk(KERN_INFO "Registering NAND on CS%d\n", gpmc_nand_data->cs);
    
    	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
    				&gpmc_nand_data->phys_base);
    	if (err < 0) {
    		dev_err(dev, "Cannot request GPMC CS\n");
    		return err;
    	}
    
    	 /* Set timings in GPMC */
    	err = omap2_nand_gpmc_retime(gpmc_nand_data);
    	if (err < 0) {
    		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
    		return err;
    	}
    
    	/* Enable RD PIN Monitoring Reg */
    	if (gpmc_nand_data->dev_ready) {
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
    	}
    
    	err = platform_device_add(gpmc_nand_device);
    	if (err < 0) {
    		dev_err(dev, "Unable to register NAND device\n");
    		goto out_free_cs;
    	}
    
    	return 0;
    
    out_free_cs:
    	gpmc_cs_free(gpmc_nand_data->cs);
    
    	return err;
    }
    

    Thanks Avinash

  • Thank you Avinash advice

    your's right

    i'm solve problem it

    [ 1.311573] mtdoops: mtd device (mtddev=name/number) must be supplied
    [ 1.318817] omap2-nand driver initializing
    [ 1.323196] omap_nand_probe 0
    [ 1.326610] NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
    [ 1.335832] Creating 8 MTD partitions on "omap2-nand.0":
    [ 1.341402] 0x000000000000-0x000000020000 : "SPL"
    [ 1.347795] 0x000000020000-0x000000040000 : "SPL.backup1"
    [ 1.354729] 0x000000040000-0x000000060000 : "SPL.backup2"
    [ 1.361615] 0x000000060000-0x000000080000 : "SPL.backup3"
    [ 1.368485] 0x000000080000-0x000000260000 : "U-Boot"
    [ 1.375684] 0x000000260000-0x000000280000 : "U-Boot Env"
    [ 1.382513] 0x000000280000-0x000000780000 : "Kernel"
    [ 1.390991] 0x000000780000-0x000010000000 : "File System"
    [ 1.500868] omap_nand_probe 1
    [ 1.504306] NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
    [ 1.513510] Creating 1 MTD partitions on "omap2-nand.1":
    [ 1.519055] 0x000000000000-0x000010000000 : "data"


    nand CS0 , CS1 detect .. good solution...

    kernel net boot and ls /dev

    mtdblock0   --> cs0
    mtdblock1 
    mtdblock2
    mtdblock3 
    mtdblock4
    mtdblock5
    mtdblock6
    mtdblock7 
    mtdblock8  --> cs1

    thand you Avinash

    and resource wrong disable but kobject wrong ...log print 

    [ 0.152083] Registering NAND on CS0
    [ 0.152127] kobject (c78fc410): tried to init an initialized object, something is seriously wrong.
    [ 0.152141] Backtrace:
    [ 0.152189] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f688>] (dump_stack+0x18/0x1c)
    [ 0.152205] r6:00000000 r5:c051b5d0 r4:c78fc410 r3:c04fca88
    [ 0.152241] [<c036f670>] (dump_stack+0x0/0x1c) from [<c01cbdd8>] (kobject_init+0x8c/0x9c)
    [ 0.152270] [<c01cbd4c>] (kobject_init+0x0/0x9c) from [<c0211da8>] (device_initialize+0x30/0x68)
    [ 0.152283] r5:c0553a90 r4:c78fc408
    [ 0.152306] [<c0211d78>] (device_initialize+0x0/0x68) from [<c0217164>] (platform_device_register+0x18/0x2c)
    [ 0.152320] r5:c78fc408 r4:c78fc400
    [ 0.152340] [<c021714c>] (platform_device_register+0x0/0x2c) from [<c0369f1c>] (gpmc_nand_init+0x2d0/0x300)
    [ 0.152354] r4:c78614c0 r3:c0534408
    [ 0.152375] [<c0369c4c>] (gpmc_nand_init+0x0/0x300) from [<c0369b24>] (gpmc_probe+0x298/0x2d4)
    [ 0.152388] r6:00000008 r5:c0533bac r4:0000001c
    [ 0.152419] [<c036988c>] (gpmc_probe+0x0/0x2d4) from [<c0216850>] (platform_drv_probe+0x20/0x24)
    [ 0.152432] r8:00000000 r7:c04e53f0 r6:c052eb48 r5:c0553ab0 r4:c7868e08
    [ 0.152465] [<c0216830>] (platform_drv_probe+0x0/0x24) from [<c0215268>] (driver_probe_device+0xc0/0x2dc)
    [ 0.152489] [<c02151a8>] (driver_probe_device+0x0/0x2dc) from [<c0215518>] (__driver_attach+0x94/0x98)
    [ 0.152503] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.152533] [<c0215484>] (__driver_attach+0x0/0x98) from [<c02141cc>] (bus_for_each_dev+0x58/0x84)
    [ 0.152547] r6:00000000 r5:c0215484 r4:c04e53f0 r3:c0215484
    [ 0.152574] [<c0214174>] (bus_for_each_dev+0x0/0x84) from [<c0214e60>] (driver_attach+0x24/0x28)
    [ 0.152587] r6:c790c840 r5:c051b710 r4:c04e53f0
    [ 0.152611] [<c0214e3c>] (driver_attach+0x0/0x28) from [<c0214acc>] (bus_add_driver+0x19c/0x26c)
    [ 0.152635] [<c0214930>] (bus_add_driver+0x0/0x26c) from [<c0215abc>] (driver_register+0x80/0x138)
    [ 0.152656] [<c0215a3c>] (driver_register+0x0/0x138) from [<c0216d20>] (platform_driver_register+0x5c/0x60)
    [ 0.152671] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf04 r4:c0533640
    [ 0.152690] r3:00000000
    [ 0.152712] [<c0216cc4>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.152736] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.152765] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.152796] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.152808] r5:c04a87e8 r4:00000000
    [ 0.153319] gpmc_nand_init() 1
    [ 0.153332] Registering NAND on CS1
    [ 0.153371] kobject (c78fc210): tried to init an initialized object, something is seriously wrong.
    [ 0.153384] Backtrace:
    [ 0.153411] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c036f688>] (dump_stack+0x18/0x1c)
    [ 0.153425] r6:00000000 r5:c051b5d0 r4:c78fc210 r3:c04fca88
    [ 0.153455] [<c036f670>] (dump_stack+0x0/0x1c) from [<c01cbdd8>] (kobject_init+0x8c/0x9c)
    [ 0.153480] [<c01cbd4c>] (kobject_init+0x0/0x9c) from [<c0211da8>] (device_initialize+0x30/0x68)
    [ 0.153493] r5:c0553a90 r4:c78fc208
    [ 0.153513] [<c0211d78>] (device_initialize+0x0/0x68) from [<c0217164>] (platform_device_register+0x18/0x2c)
    [ 0.153527] r5:c78fc208 r4:c78fc200
    [ 0.153547] [<c021714c>] (platform_device_register+0x0/0x2c) from [<c0369f1c>] (gpmc_nand_init+0x2d0/0x300)
    [ 0.153561] r4:c7861440 r3:c0534408
    [ 0.153581] [<c0369c4c>] (gpmc_nand_init+0x0/0x300) from [<c0369b24>] (gpmc_probe+0x298/0x2d4)
    [ 0.153594] r6:00000008 r5:c0533bac r4:0000001c
    [ 0.153620] [<c036988c>] (gpmc_probe+0x0/0x2d4) from [<c0216850>] (platform_drv_probe+0x20/0x24)
    [ 0.153633] r8:00000000 r7:c04e53f0 r6:c052eb48 r5:c0553ab0 r4:c7868e08
    [ 0.153665] [<c0216830>] (platform_drv_probe+0x0/0x24) from [<c0215268>] (driver_probe_device+0xc0/0x2dc)
    [ 0.153689] [<c02151a8>] (driver_probe_device+0x0/0x2dc) from [<c0215518>] (__driver_attach+0x94/0x98)
    [ 0.153703] r8:00000000 r7:00000000 r6:c7868e3c r5:c04e53f0 r4:c7868e08
    [ 0.153734] [<c0215484>] (__driver_attach+0x0/0x98) from [<c02141cc>] (bus_for_each_dev+0x58/0x84)
    [ 0.153747] r6:00000000 r5:c0215484 r4:c04e53f0 r3:c0215484
    [ 0.153775] [<c0214174>] (bus_for_each_dev+0x0/0x84) from [<c0214e60>] (driver_attach+0x24/0x28)
    [ 0.153788] r6:c790c840 r5:c051b710 r4:c04e53f0
    [ 0.153812] [<c0214e3c>] (driver_attach+0x0/0x28) from [<c0214acc>] (bus_add_driver+0x19c/0x26c)
    [ 0.153835] [<c0214930>] (bus_add_driver+0x0/0x26c) from [<c0215abc>] (driver_register+0x80/0x138)
    [ 0.153857] [<c0215a3c>] (driver_register+0x0/0x138) from [<c0216d20>] (platform_driver_register+0x5c/0x60)
    [ 0.153871] r8:00000000 r7:00000000 r6:c781c000 r5:c04dcf04 r4:c0533640
    [ 0.153891] r3:00000000
    [ 0.153908] [<c0216cc4>] (platform_driver_register+0x0/0x60) from [<c04b12a8>] (gpmc_driver_init+0x18/0x1c)
    [ 0.153931] [<c04b1290>] (gpmc_driver_init+0x0/0x1c) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 0.153957] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c04a8884>] (kernel_init+0x9c/0x130)
    [ 0.153981] [<c04a87e8>] (kernel_init+0x0/0x130) from [<c003f788>] (do_exit+0x0/0x67c)
    [ 0.153993] r5:c04a87e8 r4:00000000

    it's problem... same...

    Let's help a few more...

    final....

    Thank you

    Kind Regards,

  • Hi,

    Did you replaced the gpmc-nand.c file

    or use platform_device_add at

    err = platform_device_register(gpmc_nand_device);

    arch/arm/mach-omap2/gpmc-nand.c

    -             err = platform_device_register(gpmc_nand_device);
    +            err = platform_device_add(gpmc_nand_device);

    Thanks Avinash

  • Thank you Avinash advice

    your's solution very good...

    solve problem it PERFECT and CLEAN

    I"M Happy

    Sincerely  your advice Thank you

    God bless you...Avinash

  • Hi,

    Please apply the attached patch on gpmc-nand.c after resetting all the changes.

    From 6678ffcbc66613a57051f83f2b4e540ef2adbf18 Mon Sep 17 00:00:00 2001
    From: Philip Avinash <avinashphilip@ti.com>
    Date: Fri, 22 Feb 2013 13:00:17 +0530
    Subject: [PATCH] gpmc mult nand support
    
    Signed-off-by: Philip Avinash <avinashphilip@ti.com>
    ---
     arch/arm/mach-omap2/gpmc-nand.c |   21 +++++++++++----------
     1 file changed, 11 insertions(+), 10 deletions(-)
    
    diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
    index 0207a66..9fd7557 100644
    --- a/arch/arm/mach-omap2/gpmc-nand.c
    +++ b/arch/arm/mach-omap2/gpmc-nand.c
    @@ -24,13 +24,6 @@ static struct resource gpmc_nand_resource = {
     	.flags		= IORESOURCE_MEM,
     };
     
    -static struct platform_device gpmc_nand_device = {
    -	.name		= "omap2-nand",
    -	.id		= 0,
    -	.num_resources	= 1,
    -	.resource	= &gpmc_nand_resource,
    -};
    -
     static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
     {
     	struct gpmc_timings t;
    @@ -85,7 +78,15 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
     {
     	int err	= 0;
     	u8 cs = 0;
    -	struct device *dev = &gpmc_nand_device.dev;
    +	struct device *dev;
    +	static struct platform_device *gpmc_nand_device;
    +
    +	gpmc_nand_device = platform_device_alloc("omap2-nand",
    +			gpmc_nand_data->cs);
    +	dev = &gpmc_nand_device->dev;
    +
    +	gpmc_nand_device->resource = &gpmc_nand_resource;
    +	gpmc_nand_device->num_resources	= 1;
     
     	/* if cs not provided, find out the chip-select on which NAND exist */
     	if (gpmc_nand_data->cs > GPMC_CS_NUM)
    @@ -107,7 +108,7 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
     		return -ENODEV;
     	}
     
    -	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
    +	gpmc_nand_device->dev.platform_data = gpmc_nand_data;
     	gpmc_nand_data->ctrlr_suspend	= gpmc_suspend;
     	gpmc_nand_data->ctrlr_resume	= gpmc_resume;
     
    @@ -132,7 +133,7 @@ int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
     		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
     	}
     
    -	err = platform_device_register(&gpmc_nand_device);
    +	err = platform_device_add(gpmc_nand_device);
     	if (err < 0) {
     		dev_err(dev, "Unable to register NAND device\n");
     		goto out_free_cs;
    -- 
    1.7.9.5
    
    

    Also for your convenience I had attached gpmc-nand.c file also.

    /*
     * gpmc-nand.c
     *
     * Copyright (C) 2009 Texas Instruments
     * Vimal Singh <vimalsingh@ti.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/io.h>
    #include <linux/mtd/nand.h>
    
    #include <asm/mach/flash.h>
    
    #include <plat/nand.h>
    #include <plat/board.h>
    #include <plat/gpmc.h>
    
    static struct resource gpmc_nand_resource = {
    	.flags		= IORESOURCE_MEM,
    };
    
    static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	struct gpmc_timings t;
    	int err;
    
    	if (!gpmc_nand_data->gpmc_t)
    		return 0;
    
    	memset(&t, 0, sizeof(t));
    	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
    	t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
    	t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
    
    	/* Read */
    	t.adv_rd_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_rd_off);
    	t.oe_on  = t.adv_on;
    	t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access);
    	t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off);
    	t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off);
    	t.rd_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle);
    
    	/* Write */
    	t.adv_wr_off = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->adv_wr_off);
    	t.we_on  = t.oe_on;
    	if (cpu_is_omap34xx()) {
    	    t.wr_data_mux_bus =	gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_data_mux_bus);
    	    t.wr_access = gpmc_round_ns_to_ticks(
    				gpmc_nand_data->gpmc_t->wr_access);
    	}
    	t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off);
    	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
    	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
    
    	/* Configure GPMC */
    	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
    	else
    		gpmc_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);
    	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
    	if (err)
    		return err;
    
    	return 0;
    }
    
    int __devinit gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
    {
    	int err	= 0;
    	u8 cs = 0;
    	struct device *dev;
    	static struct platform_device *gpmc_nand_device;
    
    	gpmc_nand_device = platform_device_alloc("omap2-nand",
    			gpmc_nand_data->cs);
    	dev = &gpmc_nand_device->dev;
    
    	gpmc_nand_device->resource = &gpmc_nand_resource;
    	gpmc_nand_device->num_resources	= 1;
    
    	/* if cs not provided, find out the chip-select on which NAND exist */
    	if (gpmc_nand_data->cs > GPMC_CS_NUM)
    		while (cs < GPMC_CS_NUM) {
    			u32 ret = 0;
    			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
    
    			if ((ret & 0xC00) == 0x800) {
    				printk(KERN_INFO "Found NAND on CS%d\n", cs);
    				gpmc_nand_data->cs = cs;
    				break;
    			}
    			cs++;
    		}
    
    	if (gpmc_nand_data->cs > GPMC_CS_NUM) {
    		printk(KERN_INFO "NAND: Unable to find configuration "
    				 "in GPMC\n ");
    		return -ENODEV;
    	}
    
    	gpmc_nand_device->dev.platform_data = gpmc_nand_data;
    	gpmc_nand_data->ctrlr_suspend	= gpmc_suspend;
    	gpmc_nand_data->ctrlr_resume	= gpmc_resume;
    
    	printk(KERN_INFO "Registering NAND on CS%d\n", gpmc_nand_data->cs);
    
    	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
    				&gpmc_nand_data->phys_base);
    	if (err < 0) {
    		dev_err(dev, "Cannot request GPMC CS\n");
    		return err;
    	}
    
    	 /* Set timings in GPMC */
    	err = omap2_nand_gpmc_retime(gpmc_nand_data);
    	if (err < 0) {
    		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
    		return err;
    	}
    
    	/* Enable RD PIN Monitoring Reg */
    	if (gpmc_nand_data->dev_ready) {
    		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
    	}
    
    	err = platform_device_add(gpmc_nand_device);
    	if (err < 0) {
    		dev_err(dev, "Unable to register NAND device\n");
    		goto out_free_cs;
    	}
    
    	return 0;
    
    out_free_cs:
    	gpmc_cs_free(gpmc_nand_data->cs);
    
    	return err;
    }
    

    But I prefer apply of the patch.

    Remember you can keep your board file change as such (board-am335xevm.c).

    Thanks avinash