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