1/* 2 * linux/arch/arm/mach-omap2/gpmc-onenand.c 3 * 4 * Copyright (C) 2006 - 2009 Nokia Corporation 5 * Contacts: Juha Yrjola 6 * Tony Lindgren 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/string.h> 14#include <linux/kernel.h> 15#include <linux/platform_device.h> 16#include <linux/mtd/onenand_regs.h> 17#include <linux/io.h> 18 19#include <asm/mach/flash.h> 20 21#include <plat/cpu.h> 22#include <plat/onenand.h> 23#include <plat/board.h> 24#include <plat/gpmc.h> 25 26static struct omap_onenand_platform_data *gpmc_onenand_data; 27 28static struct platform_device gpmc_onenand_device = { 29 .name = "omap2-onenand", 30 .id = -1, 31}; 32 33static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) 34{ 35 struct gpmc_timings t; 36 u32 reg; 37 int err; 38 39 const int t_cer = 15; 40 const int t_avdp = 12; 41 const int t_aavdh = 7; 42 const int t_ce = 76; 43 const int t_aa = 76; 44 const int t_oe = 20; 45 const int t_cez = 20; /* max of t_cez, t_oez */ 46 const int t_ds = 30; 47 const int t_wpl = 40; 48 const int t_wph = 30; 49 50 /* Ensure sync read and sync write are disabled */ 51 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 52 reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; 53 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 54 55 memset(&t, 0, sizeof(t)); 56 t.sync_clk = 0; 57 t.cs_on = 0; 58 t.adv_on = 0; 59 60 /* Read */ 61 t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); 62 t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); 63 t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); 64 t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); 65 t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); 66 t.oe_off = t.access + gpmc_round_ns_to_ticks(1); 67 t.cs_rd_off = t.oe_off; 68 t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); 69 70 /* Write */ 71 t.adv_wr_off = t.adv_rd_off; 72 t.we_on = t.oe_on; 73 if (cpu_is_omap34xx()) { 74 t.wr_data_mux_bus = t.we_on; 75 t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); 76 } 77 t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); 78 t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); 79 t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); 80 81 /* Configure GPMC for asynchronous read */ 82 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 83 GPMC_CONFIG1_DEVICESIZE_16 | 84 GPMC_CONFIG1_MUXADDDATA); 85 86 err = gpmc_cs_set_timings(cs, &t); 87 if (err) 88 return err; 89 90 /* Ensure sync read and sync write are disabled */ 91 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 92 reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; 93 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 94 95 return 0; 96} 97 98static void set_onenand_cfg(void __iomem *onenand_base, int latency, 99 int sync_read, int sync_write, int hf, int vhf) 100{ 101 u32 reg; 102 103 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 104 reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); 105 reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | 106 ONENAND_SYS_CFG1_BL_16; 107 if (sync_read) 108 reg |= ONENAND_SYS_CFG1_SYNC_READ; 109 else 110 reg &= ~ONENAND_SYS_CFG1_SYNC_READ; 111 if (sync_write) 112 reg |= ONENAND_SYS_CFG1_SYNC_WRITE; 113 else 114 reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE; 115 if (hf) 116 reg |= ONENAND_SYS_CFG1_HF; 117 else 118 reg &= ~ONENAND_SYS_CFG1_HF; 119 if (vhf) 120 reg |= ONENAND_SYS_CFG1_VHF; 121 else 122 reg &= ~ONENAND_SYS_CFG1_VHF; 123 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 124} 125 126static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, 127 void __iomem *onenand_base, bool *clk_dep) 128{ 129 u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID); 130 int freq = 0; 131 132 if (cfg->get_freq) { 133 struct onenand_freq_info fi; 134 135 fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID); 136 fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID); 137 fi.ver_id = ver; 138 freq = cfg->get_freq(&fi, clk_dep); 139 if (freq) 140 return freq; 141 } 142 143 switch ((ver >> 4) & 0xf) { 144 case 0: 145 freq = 40; 146 break; 147 case 1: 148 freq = 54; 149 break; 150 case 2: 151 freq = 66; 152 break; 153 case 3: 154 freq = 83; 155 break; 156 case 4: 157 freq = 104; 158 break; 159 default: 160 freq = 54; 161 break; 162 } 163 164 return freq; 165} 166 167static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, 168 void __iomem *onenand_base, 169 int *freq_ptr) 170{ 171 struct gpmc_timings t; 172 const int t_cer = 15; 173 const int t_avdp = 12; 174 const int t_cez = 20; /* max of t_cez, t_oez */ 175 const int t_ds = 30; 176 const int t_wpl = 40; 177 const int t_wph = 30; 178 int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; 179 int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; 180 int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; 181 int err, ticks_cez; 182 int cs = cfg->cs, freq = *freq_ptr; 183 u32 reg; 184 bool clk_dep = false; 185 186 if (cfg->flags & ONENAND_SYNC_READ) { 187 sync_read = 1; 188 } else if (cfg->flags & ONENAND_SYNC_READWRITE) { 189 sync_read = 1; 190 sync_write = 1; 191 } else 192 return omap2_onenand_set_async_mode(cs, onenand_base); 193 194 if (!freq) { 195 /* Very first call freq is not known */ 196 err = omap2_onenand_set_async_mode(cs, onenand_base); 197 if (err) 198 return err; 199 freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep); 200 first_time = 1; 201 } 202 203 switch (freq) { 204 case 104: 205 min_gpmc_clk_period = 9600; /* 104 MHz */ 206 t_ces = 3; 207 t_avds = 4; 208 t_avdh = 2; 209 t_ach = 3; 210 t_aavdh = 6; 211 t_rdyo = 6; 212 break; 213 case 83: 214 min_gpmc_clk_period = 12000; /* 83 MHz */ 215 t_ces = 5; 216 t_avds = 4; 217 t_avdh = 2; 218 t_ach = 6; 219 t_aavdh = 6; 220 t_rdyo = 9; 221 break; 222 case 66: 223 min_gpmc_clk_period = 15000; /* 66 MHz */ 224 t_ces = 6; 225 t_avds = 5; 226 t_avdh = 2; 227 t_ach = 6; 228 t_aavdh = 6; 229 t_rdyo = 11; 230 break; 231 default: 232 min_gpmc_clk_period = 18500; /* 54 MHz */ 233 t_ces = 7; 234 t_avds = 7; 235 t_avdh = 7; 236 t_ach = 9; 237 t_aavdh = 7; 238 t_rdyo = 15; 239 sync_write = 0; 240 break; 241 } 242 243 tick_ns = gpmc_ticks_to_ns(1); 244 div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); 245 gpmc_clk_ns = gpmc_ticks_to_ns(div); 246 if (gpmc_clk_ns < 15) /* >66Mhz */ 247 hf = 1; 248 if (gpmc_clk_ns < 12) /* >83Mhz */ 249 vhf = 1; 250 if (vhf) 251 latency = 8; 252 else if (hf) 253 latency = 6; 254 else if (gpmc_clk_ns >= 25) /* 40 MHz*/ 255 latency = 3; 256 else 257 latency = 4; 258 259 if (clk_dep) { 260 if (gpmc_clk_ns < 12) { /* >83Mhz */ 261 t_ces = 3; 262 t_avds = 4; 263 } else if (gpmc_clk_ns < 15) { /* >66Mhz */ 264 t_ces = 5; 265 t_avds = 4; 266 } else if (gpmc_clk_ns < 25) { /* >40Mhz */ 267 t_ces = 6; 268 t_avds = 5; 269 } else { 270 t_ces = 7; 271 t_avds = 7; 272 } 273 } 274 275 if (first_time) 276 set_onenand_cfg(onenand_base, latency, 277 sync_read, sync_write, hf, vhf); 278 279 if (div == 1) { 280 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 281 reg |= (1 << 7); 282 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 283 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 284 reg |= (1 << 7); 285 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 286 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 287 reg |= (1 << 7); 288 reg |= (1 << 23); 289 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 290 } else { 291 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 292 reg &= ~(1 << 7); 293 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 294 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 295 reg &= ~(1 << 7); 296 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 297 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 298 reg &= ~(1 << 7); 299 reg &= ~(1 << 23); 300 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 301 } 302 303 /* Set synchronous read timings */ 304 memset(&t, 0, sizeof(t)); 305 t.sync_clk = min_gpmc_clk_period; 306 t.cs_on = 0; 307 t.adv_on = 0; 308 fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); 309 fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); 310 t.page_burst_access = gpmc_clk_ns; 311 312 /* Read */ 313 t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); 314 t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); 315 /* Force at least 1 clk between AVD High to OE Low */ 316 if (t.oe_on <= t.adv_rd_off) 317 t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1); 318 t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); 319 t.oe_off = t.access + gpmc_round_ns_to_ticks(1); 320 t.cs_rd_off = t.oe_off; 321 ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; 322 t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + 323 ticks_cez); 324 325 /* Write */ 326 if (sync_write) { 327 t.adv_wr_off = t.adv_rd_off; 328 t.we_on = 0; 329 t.we_off = t.cs_rd_off; 330 t.cs_wr_off = t.cs_rd_off; 331 t.wr_cycle = t.rd_cycle; 332 if (cpu_is_omap34xx()) { 333 t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset + 334 gpmc_ps_to_ticks(min_gpmc_clk_period + 335 t_rdyo * 1000)); 336 t.wr_access = t.access; 337 } 338 } else { 339 t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, 340 t_avdp, t_cer)); 341 t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh); 342 t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); 343 t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); 344 t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); 345 if (cpu_is_omap34xx()) { 346 t.wr_data_mux_bus = t.we_on; 347 t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); 348 } 349 } 350 351 /* Configure GPMC for synchronous read */ 352 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 353 GPMC_CONFIG1_WRAPBURST_SUPP | 354 GPMC_CONFIG1_READMULTIPLE_SUPP | 355 (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | 356 (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | 357 (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | 358 GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | 359 GPMC_CONFIG1_PAGE_LEN(2) | 360 (cpu_is_omap34xx() ? 0 : 361 (GPMC_CONFIG1_WAIT_READ_MON | 362 GPMC_CONFIG1_WAIT_PIN_SEL(0))) | 363 GPMC_CONFIG1_DEVICESIZE_16 | 364 GPMC_CONFIG1_DEVICETYPE_NOR | 365 GPMC_CONFIG1_MUXADDDATA); 366 367 err = gpmc_cs_set_timings(cs, &t); 368 if (err) 369 return err; 370 371 set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf); 372 373 *freq_ptr = freq; 374 375 return 0; 376} 377 378static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) 379{ 380 struct device *dev = &gpmc_onenand_device.dev; 381 382 /* Set sync timings in GPMC */ 383 if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, 384 freq_ptr) < 0) { 385 dev_err(dev, "Unable to set synchronous mode\n"); 386 return -EINVAL; 387 } 388 389 return 0; 390} 391 392void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) 393{ 394 gpmc_onenand_data = _onenand_data; 395 gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; 396 gpmc_onenand_device.dev.platform_data = gpmc_onenand_data; 397 398 if (cpu_is_omap24xx() && 399 (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) { 400 printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n"); 401 gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE; 402 gpmc_onenand_data->flags |= ONENAND_SYNC_READ; 403 } 404 405 if (platform_device_register(&gpmc_onenand_device) < 0) { 406 printk(KERN_ERR "Unable to register OneNAND device\n"); 407 return; 408 } 409} 410