Example #1
0
static int gpmc_config(void)
{
    // first reg gpmc_init() already called; io pinmux already configed
    // ti8168evm board_nand_init -> gpmc_nand_init
    u32 val = 0;
    int err = 0;
/*-
EXPORT_SYMBOL(gpmc_cs_write_reg);
EXPORT_SYMBOL(gpmc_cs_read_reg);
EXPORT_SYMBOL(gpmc_cs_set_timings);
-*/
    // gpmc cs disable memory
    val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7);
    val &= ~GPMC_CONFIG7_CSVALID;
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7, val);

    // disable cs3 irq
    gpmc_cs_configure(GPMC_FPGA_CS, GPMC_SET_IRQ_STATUS, 0);
    gpmc_cs_configure(GPMC_FPGA_CS, GPMC_ENABLE_IRQ, 0);

    // set config1
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, GPMC_CONFIG1_READTYPE_ASYNC|  // set read type async
        GPMC_CONFIG1_WRITETYPE_ASYNC| // set write type async
        GPMC_CONFIG1_DEVICESIZE_16|   // set device size 16bit
        GPMC_CONFIG1_DEVICETYPE_NOR   // set device type nor
    );
    val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1);
    val &= ~GPMC_CONFIG1_MUXADDDATA;
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, val);
 
    // set gpmc timings
    err = gpmc_cs_set_timings(GPMC_FPGA_CS, &fpga_timings);
    if(err < 0){
        printk(KERN_ERR "Unable to set gpmc timings\n");
    }

    // apply gpmc select memory
    err = gpmc_cs_request(GPMC_FPGA_CS, GPMC_FIFO_SIZE, &gpmc_membase);
    if(err < 0){
        printk(KERN_ERR "Cannot request GPMC CS\n");
        return err;
    }

 //   request_mem_region(gpmc_membase, GPMC_FIFO_SIZE, DRIVERNAME);

 //   fpga_membase = ioremap(gpmc_membase, GPMC_FIFO_SIZE);

    return err;
}
Example #2
0
static void __init omap3beagle_flash_init(void)
{
	u8 cs = 0;
	u8 nandcs = GPMC_CS_NUM + 1;

	/* find out the chip-select on which NAND exists */
	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);
			if (nandcs > GPMC_CS_NUM)
				nandcs = cs;
		}
		cs++;
	}

	if (nandcs > GPMC_CS_NUM) {
		printk(KERN_INFO "NAND: Unable to find configuration "
				 "in GPMC\n ");
		return;
	}

	if (nandcs < GPMC_CS_NUM) {
		omap3beagle_nand_data.cs = nandcs;

		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
		if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
			printk(KERN_ERR "Unable to register NAND device\n");
	}
}
Example #3
0
void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
				 int nr_parts)
{
	u8 cs = 0;
	u8 nandcs = GPMC_CS_NUM + 1;

	/* find out the chip-select on which NAND exists */
	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);
			if (nandcs > GPMC_CS_NUM)
				nandcs = cs;
		}
		cs++;
	}

	if (nandcs > GPMC_CS_NUM) {
		pr_info("NAND: Unable to find configuration in GPMC\n");
		return;
	}

	if (nandcs < GPMC_CS_NUM) {
		nand_data.cs = nandcs;
		nand_data.parts = parts;
		nand_data.nr_parts = nr_parts;
		nand_data.devsize = options;

		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
		if (gpmc_nand_init(&nand_data) < 0)
			printk(KERN_ERR "Unable to register NAND device\n");
	}
}
static void __init omap3beagle_flash_init(void)
{
	u8 cs = 0;
	u8 nandcs = GPMC_CS_NUM + 1;

	/* find out the chip-select on which NAND exists */
	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);
			if (nandcs > GPMC_CS_NUM)
				nandcs = cs;
		}
		cs++;
	}

	if (nandcs > GPMC_CS_NUM) {
		printk(KERN_INFO "NAND: Unable to find configuration "
				 "in GPMC\n ");
		return;
	}

	if (nandcs < GPMC_CS_NUM) {
		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
		board_nand_init(omap3beagle_nand_partitions,
			ARRAY_SIZE(omap3beagle_nand_partitions),
			nandcs, NAND_BUSWIDTH_16);
	}
}
static void __init board_init(void)
{
	omap_board_config = board_config;
	omap_board_config_size = ARRAY_SIZE(board_config);

	archos_accel_init(&board_mma7456l_pdata);
	omap_i2c_init();

#ifdef CONFIG_OMAP3_PM
	prcm_init();
#endif

	init_buffer_pbias();

	if (archos_lcd_panel_init(&board_dss_data) < 0)
		pr_err("archos_lcd_panel_init failed!\n");
	if (archos_tvout_venc_init(&board_dss_data) < 0)
		pr_err("archos_tvout_venc_init failed\n");
	if (archos_tvout_hdmi_init(&board_dss_data) < 0)
		pr_err("archos_tvout_hdmi_init failed\n");
	if (archos_tvout_extdac_init(&board_dss_data) < 0)
		pr_err("archos_tvout_extdac_init failed\n");
	
	platform_device_register(&board_dss_device);

	platform_device_register(&omap_tvp_isp_device);

#ifdef CONFIG_ARCHOS_NAND_MOD
	{
	/* fixup for nand support of hw version 1.1 */
	u32 ret = gpmc_cs_read_reg(0, GPMC_CS_CONFIG1);
	if (hardware_rev == 1 && (ret & 0xC00) == GPMC_CONFIG1_DEVICETYPE_NAND) {
		usb_config.rev[1].enable_usb_musb.nb = 161;
		usb_config.rev[1].enable_usb_musb.mux_cfg = K26_3430_GPIO161;
		usb_config.rev[1].enable_usb_ehci.nb = 167;
		usb_config.rev[1].enable_usb_ehci.mux_cfg = B23_3430_GPIO167;
	}
	}
#endif
	
	archosg7_init();
	archos_flash_init();
	archos_atmega_init();
	ads7846_dev_init();
	omap_serial_init();
	usb_musb_init();
	usb_ehci_init();
	archos_usb2sata_init();
	archos_audio_gpio_init();
	archos_keys_init();
	archos_wifi_bt_init();

	omap_cfg_reg(AH26_3430_GPIO2);
	
	pm_power_off = archos_power_off;
}
void __init VAR_SOM_OM3X_flash_init(void)
{
	u8 cs = 0;
	u8 nandcs = GPMC_CS_NUM + 1;

	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;

	while (cs < GPMC_CS_NUM) {
		u32 ret = 0;
		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);

		if ((ret & 0xC00) == 0x800) {

			/* Found it!! */
			if (nandcs > GPMC_CS_NUM)
				nandcs = cs;
		} else {
			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
		}
		cs++;
	}

	if (nandcs > GPMC_CS_NUM) {
		printk(KERN_INFO "NAND/OneNAND: Unable to find configuration "
			" in GPMC\n ");
		return;
	}

	if (nandcs < GPMC_CS_NUM) {
		VAR_SOM_OM3X_nand_data.cs   = nandcs;
		VAR_SOM_OM3X_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
					GPMC_CS0_BASE + nandcs*GPMC_CS_SIZE);
		VAR_SOM_OM3X_nand_data.gpmc_baseaddr   = (void *) (gpmc_base_add);

		if (platform_device_register(&VAR_SOM_OM3X_nand_device) < 0) {
			printk(KERN_ERR "Unable to register NAND device\n");
		}
	}
}
int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
{
	unsigned int val;
	int err	= 0;
	struct device *dev = &gpmc_nand_device.dev;

	gpmc_nand_data = _nand_data;
	gpmc_nand_data->nand_setup = gpmc_nand_setup;
	gpmc_nand_device.dev.platform_data = gpmc_nand_data;

	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;
	}

	err = gpmc_nand_setup();
	if (err < 0) {
		dev_err(dev, "NAND platform setup failed: %d\n", err);
		return err;
	}

	/* Enable RD PIN Monitoring Reg */
	if (gpmc_nand_data->dev_ready) {
		val  = gpmc_cs_read_reg(gpmc_nand_data->cs,
						 GPMC_CS_CONFIG1);
		val |= WR_RD_PIN_MONITORING;
		gpmc_cs_write_reg(gpmc_nand_data->cs,
						GPMC_CS_CONFIG1, val);
	}

	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;
}
static void __init omap3touchbook_flash_init(void)
{
	u8 cs = 0;
	u8 nandcs = GPMC_CS_NUM + 1;

	u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;

	/* find out the chip-select on which NAND exists */
	while (cs < GPMC_CS_NUM) {
		u32 ret = 0;
		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);

		if ((ret & 0xC00) == 0x800) {
			printk(KERN_INFO "Found NAND on CS%d\n", cs);
			if (nandcs > GPMC_CS_NUM)
				nandcs = cs;
		}
		cs++;
	}

	if (nandcs > GPMC_CS_NUM) {
		printk(KERN_INFO "NAND: Unable to find configuration "
				 "in GPMC\n ");
		return;
	}

	if (nandcs < GPMC_CS_NUM) {
		omap3touchbook_nand_data.cs = nandcs;
		omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
			(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
		omap3touchbook_nand_data.gpmc_baseaddr =
						(void *) (gpmc_base_add);

		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
		if (platform_device_register(&omap3touchbook_nand_device) < 0)
			printk(KERN_ERR "Unable to register NAND device\n");
	}
}
Example #9
0
static int __init fpga_perh_init(void)
{
    unsigned int cnt;
    u32 val = 0;
    int ret = 0;
    int chk = 0;

    gpio_store();     // GPIO初始化
    gpio_config();
    gpmc_config();    // GPMC配置
    edma_config();    // EDMA配置

    for(cnt=0; cnt<7; cnt++){
        val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1 + cnt*0x04);
        printk("GPMC_CS3_CONFIG_%d : [%08X]\n", cnt+1, val);
    }

    printk("Gpmc now start reading...\n");

    FPGA_RRST_L;
    _delay_ns(1);   // 1us
    FPGA_RRST_H;


    ret = edma_start(dma_ch);
    
    if (ret != 0) {
        printk ("dm8168_start_dma failed, error:%d", ret);
        return ret;
    }

    // wait for completion ISR
    while(irqraised1 == 0u){
        _delay_ms(10);
 //       break;
    }


    if (ret == 0) {
        for (cnt=0; cnt<FPGA_FIFO_SIZE; cnt++) {
//            fpga_buf[cnt] = readw(fpga_membase);
            if (fpga_buf[cnt] != cnt+1) {            // 进行数据校验
                chk = cnt+1;
                break;
            }
        }
        edma_stop(dma_ch);
        edma_free_channel(dma_ch);
    }

    if (chk == 0){
        printk ("Gpmc&edma reading sequence data check successful!\n");
    }else{
        printk ("Gpmc&edma reading data check error at: %d\n", chk);
    }

    for(cnt=0; cnt<8; cnt++){
        printk("[%04X] [%04X] [%04X] [%04X]\n", fpga_buf[cnt*4], fpga_buf[cnt*4+1], fpga_buf[cnt*4+2], fpga_buf[cnt*4+3]);
    }

//    gpmc_cs_free(GPMC_FPGA_CS);  
    return 0;
}
static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
					void __iomem *onenand_base,
					int *freq_ptr)
{
	struct gpmc_timings t;
	const int t_cer  = 15;
	const int t_avdp = 12;
	const int t_cez  = 20; /* max of t_cez, t_oez */
	const int t_ds   = 30;
	const int t_wpl  = 40;
	const int t_wph  = 30;
	int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
	int err, ticks_cez;
	int cs = cfg->cs, freq = *freq_ptr;
	u32 reg;
	bool clk_dep = false;

	if (cfg->flags & ONENAND_SYNC_READ) {
		sync_read = 1;
	} else if (cfg->flags & ONENAND_SYNC_READWRITE) {
		sync_read = 1;
		sync_write = 1;
	} else
		return omap2_onenand_set_async_mode(cs, onenand_base);

	if (!freq) {
		/* Very first call freq is not known */
		err = omap2_onenand_set_async_mode(cs, onenand_base);
		if (err)
			return err;
		freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
		first_time = 1;
	}

	switch (freq) {
	case 104:
		min_gpmc_clk_period = 9600; /* 104 MHz */
		t_ces   = 3;
		t_avds  = 4;
		t_avdh  = 2;
		t_ach   = 3;
		t_aavdh = 6;
		t_rdyo  = 6;
		break;
	case 83:
		min_gpmc_clk_period = 12000; /* 83 MHz */
		t_ces   = 5;
		t_avds  = 4;
		t_avdh  = 2;
		t_ach   = 6;
		t_aavdh = 6;
		t_rdyo  = 9;
		break;
	case 66:
		min_gpmc_clk_period = 15000; /* 66 MHz */
		t_ces   = 6;
		t_avds  = 5;
		t_avdh  = 2;
		t_ach   = 6;
		t_aavdh = 6;
		t_rdyo  = 11;
		break;
	default:
		min_gpmc_clk_period = 18500; /* 54 MHz */
		t_ces   = 7;
		t_avds  = 7;
		t_avdh  = 7;
		t_ach   = 9;
		t_aavdh = 7;
		t_rdyo  = 15;
		sync_write = 0;
		break;
	}

	tick_ns = gpmc_ticks_to_ns(1);
	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
	gpmc_clk_ns = gpmc_ticks_to_ns(div);
	if (gpmc_clk_ns < 15) /* >66Mhz */
		hf = 1;
	if (gpmc_clk_ns < 12) /* >83Mhz */
		vhf = 1;
	if (vhf)
		latency = 8;
	else if (hf)
		latency = 6;
	else if (gpmc_clk_ns >= 25) /* 40 MHz*/
		latency = 3;
	else
		latency = 4;

	if (clk_dep) {
		if (gpmc_clk_ns < 12) { /* >83Mhz */
			t_ces   = 3;
			t_avds  = 4;
		} else if (gpmc_clk_ns < 15) { /* >66Mhz */
			t_ces   = 5;
			t_avds  = 4;
		} else if (gpmc_clk_ns < 25) { /* >40Mhz */
			t_ces   = 6;
			t_avds  = 5;
		} else {
			t_ces   = 7;
			t_avds  = 7;
		}
	}

	if (first_time)
		set_onenand_cfg(onenand_base, latency,
					sync_read, sync_write, hf, vhf);

	if (div == 1) {
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
		reg |= (1 << 7);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
		reg |= (1 << 7);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
		reg |= (1 << 7);
		reg |= (1 << 23);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
	} else {
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
		reg &= ~(1 << 7);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
		reg &= ~(1 << 7);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
		reg &= ~(1 << 7);
		reg &= ~(1 << 23);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
	}

	/* Set synchronous read timings */
	memset(&t, 0, sizeof(t));
	t.sync_clk = min_gpmc_clk_period;
	t.cs_on = 0;
	t.adv_on = 0;
	fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
	fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
	t.page_burst_access = gpmc_clk_ns;

	/* Read */
	t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
	t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
	/* Force at least 1 clk between AVD High to OE Low */
	if (t.oe_on <= t.adv_rd_off)
		t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
	t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
	t.cs_rd_off = t.oe_off;
	ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
	t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
		     ticks_cez);

	/* Write */
	if (sync_write) {
		t.adv_wr_off = t.adv_rd_off;
		t.we_on  = 0;
		t.we_off = t.cs_rd_off;
		t.cs_wr_off = t.cs_rd_off;
		t.wr_cycle  = t.rd_cycle;
		if (cpu_is_omap34xx()) {
			t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
					gpmc_ps_to_ticks(min_gpmc_clk_period +
					t_rdyo * 1000));
			t.wr_access = t.access;
		}
	} else {
		t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
							t_avdp, t_cer));
		t.we_on  = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
		t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
		t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
		t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
		if (cpu_is_omap34xx()) {
			t.wr_data_mux_bus = t.we_on;
			t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
		}
	}

	/* Configure GPMC for synchronous read */
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
			  GPMC_CONFIG1_WRAPBURST_SUPP |
			  GPMC_CONFIG1_READMULTIPLE_SUPP |
			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
			  GPMC_CONFIG1_PAGE_LEN(2) |
			  (cpu_is_omap34xx() ? 0 :
				(GPMC_CONFIG1_WAIT_READ_MON |
				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
			  GPMC_CONFIG1_DEVICESIZE_16 |
			  GPMC_CONFIG1_DEVICETYPE_NOR |
			  GPMC_CONFIG1_MUXADDDATA);

	err = gpmc_cs_set_timings(cs, &t);
	if (err)
		return err;

	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);

	*freq_ptr = freq;

	return 0;
}
static void __init apollon_cs_init(void)
{
	unsigned long base;
	unsigned int rate;
	struct clk *l3ck;
	u32 value;
	int cs, sync = 0;

	l3ck = clk_get(NULL, "core_l3_ck");
	if (IS_ERR(l3ck))
		rate = 100000000;
	else
		rate = clk_get_rate(l3ck);

	/* CS2: OneNAND */
	cs = 2;
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG1);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, value);
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG2);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, value);
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG3);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, value);
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG4);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, value);
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG5);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, value);
	value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG6);
	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, value);

	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_ONENAND_CS2_ADDRESS);

	/* CS3: External NOR */
	cs = APOLLON_NOR_CS;
	if (rate >= 160000000) {
		sync = 1;
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe5011211);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00090b01);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00020201);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x09030b03);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x010a0a0c);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
	} else if (rate >= 130000000) {
		/* Not yet know ... Use the async values */
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0x00021201);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00121601);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00040401);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x12061605);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01151317);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
	} else {/* rate = 100000000 */
		sync = 1;
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe1001202);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00151501);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00050501);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x0e070e07);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01131F1F);
		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
	}

	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_EXT_CS3_ADDRESS);

	if (gpmc_cs_request(cs, SZ_32M, &base) < 0) {
		printk(KERN_ERR "Failed to request GPMC CS for external\n");
		return;
	}

	/* Synchronous mode */
	if (sync) {
		void __iomem *addr = ioremap(base, SZ_32M);
		writew(0xaa, addr + 0xaaa);
		writew(0x55, addr + 0x554);
		writew(0xc0, addr + 0x24aaa);
		iounmap(addr);
	}

	gpmc_cs_free(cs);
}
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;

	/* 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;
}