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/kernel.h> 14#include <linux/platform_device.h> 15#include <linux/mtd/onenand_regs.h> 16#include <linux/io.h> 17 18#include <asm/mach/flash.h> 19 20#include <plat/onenand.h> 21#include <plat/board.h> 22#include <plat/gpmc.h> 23 24static struct omap_onenand_platform_data *gpmc_onenand_data; 25 26static struct platform_device gpmc_onenand_device = { 27 .name = "omap2-onenand", 28 .id = -1, 29}; 30 31static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) 32{ 33 struct gpmc_timings t; 34 u32 reg; 35 int err; 36 37 const int t_cer = 15; 38 const int t_avdp = 12; 39 const int t_aavdh = 7; 40 const int t_ce = 76; 41 const int t_aa = 76; 42 const int t_oe = 20; 43 const int t_cez = 20; /* max of t_cez, t_oez */ 44 const int t_ds = 30; 45 const int t_wpl = 40; 46 const int t_wph = 30; 47 48 /* Ensure sync read and sync write are disabled */ 49 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 50 reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; 51 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 52 53 memset(&t, 0, sizeof(t)); 54 t.sync_clk = 0; 55 t.cs_on = 0; 56 t.adv_on = 0; 57 58 /* Read */ 59 t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); 60 t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); 61 t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); 62 t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); 63 t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); 64 t.oe_off = t.access + gpmc_round_ns_to_ticks(1); 65 t.cs_rd_off = t.oe_off; 66 t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); 67 68 /* Write */ 69 t.adv_wr_off = t.adv_rd_off; 70 t.we_on = t.oe_on; 71 if (cpu_is_omap34xx()) { 72 t.wr_data_mux_bus = t.we_on; 73 t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); 74 } 75 t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); 76 t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); 77 t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); 78 79 /* Configure GPMC for asynchronous read */ 80 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 81 GPMC_CONFIG1_DEVICESIZE_16 | 82 GPMC_CONFIG1_MUXADDDATA); 83 84 err = gpmc_cs_set_timings(cs, &t); 85 if (err) 86 return err; 87 88 /* Ensure sync read and sync write are disabled */ 89 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 90 reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; 91 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 92 93 return 0; 94} 95 96static void set_onenand_cfg(void __iomem *onenand_base, int latency, 97 int sync_read, int sync_write, int hf) 98{ 99 u32 reg; 100 101 reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); 102 reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); 103 reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | 104 ONENAND_SYS_CFG1_BL_16; 105 if (sync_read) 106 reg |= ONENAND_SYS_CFG1_SYNC_READ; 107 else 108 reg &= ~ONENAND_SYS_CFG1_SYNC_READ; 109 if (sync_write) 110 reg |= ONENAND_SYS_CFG1_SYNC_WRITE; 111 else 112 reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE; 113 if (hf) 114 reg |= ONENAND_SYS_CFG1_HF; 115 else 116 reg &= ~ONENAND_SYS_CFG1_HF; 117 writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); 118} 119 120static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, 121 void __iomem *onenand_base, 122 int freq) 123{ 124 struct gpmc_timings t; 125 const int t_cer = 15; 126 const int t_avdp = 12; 127 const int t_cez = 20; /* max of t_cez, t_oez */ 128 const int t_ds = 30; 129 const int t_wpl = 40; 130 const int t_wph = 30; 131 int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; 132 int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; 133 int first_time = 0, hf = 0, sync_read = 0, sync_write = 0; 134 int err, ticks_cez; 135 int cs = cfg->cs; 136 u32 reg; 137 138 if (cfg->flags & ONENAND_SYNC_READ) { 139 sync_read = 1; 140 } else if (cfg->flags & ONENAND_SYNC_READWRITE) { 141 sync_read = 1; 142 sync_write = 1; 143 } else 144 return omap2_onenand_set_async_mode(cs, onenand_base); 145 146 if (!freq) { 147 /* Very first call freq is not known */ 148 err = omap2_onenand_set_async_mode(cs, onenand_base); 149 if (err) 150 return err; 151 reg = readw(onenand_base + ONENAND_REG_VERSION_ID); 152 switch ((reg >> 4) & 0xf) { 153 case 0: 154 freq = 40; 155 break; 156 case 1: 157 freq = 54; 158 break; 159 case 2: 160 freq = 66; 161 break; 162 case 3: 163 freq = 83; 164 break; 165 case 4: 166 freq = 104; 167 break; 168 default: 169 freq = 54; 170 break; 171 } 172 first_time = 1; 173 } 174 175 switch (freq) { 176 case 83: 177 min_gpmc_clk_period = 12; /* 83 MHz */ 178 t_ces = 5; 179 t_avds = 4; 180 t_avdh = 2; 181 t_ach = 6; 182 t_aavdh = 6; 183 t_rdyo = 9; 184 break; 185 case 66: 186 min_gpmc_clk_period = 15; /* 66 MHz */ 187 t_ces = 6; 188 t_avds = 5; 189 t_avdh = 2; 190 t_ach = 6; 191 t_aavdh = 6; 192 t_rdyo = 11; 193 break; 194 default: 195 min_gpmc_clk_period = 18; /* 54 MHz */ 196 t_ces = 7; 197 t_avds = 7; 198 t_avdh = 7; 199 t_ach = 9; 200 t_aavdh = 7; 201 t_rdyo = 15; 202 sync_write = 0; 203 break; 204 } 205 206 tick_ns = gpmc_ticks_to_ns(1); 207 div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); 208 gpmc_clk_ns = gpmc_ticks_to_ns(div); 209 if (gpmc_clk_ns < 15) /* >66Mhz */ 210 hf = 1; 211 if (hf) 212 latency = 6; 213 else if (gpmc_clk_ns >= 25) /* 40 MHz*/ 214 latency = 3; 215 else 216 latency = 4; 217 218 if (first_time) 219 set_onenand_cfg(onenand_base, latency, 220 sync_read, sync_write, hf); 221 222 if (div == 1) { 223 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 224 reg |= (1 << 7); 225 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 226 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 227 reg |= (1 << 7); 228 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 229 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 230 reg |= (1 << 7); 231 reg |= (1 << 23); 232 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 233 } else { 234 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 235 reg &= ~(1 << 7); 236 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 237 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 238 reg &= ~(1 << 7); 239 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 240 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 241 reg &= ~(1 << 7); 242 reg &= ~(1 << 23); 243 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 244 } 245 246 /* Set synchronous read timings */ 247 memset(&t, 0, sizeof(t)); 248 t.sync_clk = min_gpmc_clk_period; 249 t.cs_on = 0; 250 t.adv_on = 0; 251 fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); 252 fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); 253 t.page_burst_access = gpmc_clk_ns; 254 255 /* Read */ 256 t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); 257 t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); 258 t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); 259 t.oe_off = t.access + gpmc_round_ns_to_ticks(1); 260 t.cs_rd_off = t.oe_off; 261 ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; 262 t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + 263 ticks_cez); 264 265 /* Write */ 266 if (sync_write) { 267 t.adv_wr_off = t.adv_rd_off; 268 t.we_on = 0; 269 t.we_off = t.cs_rd_off; 270 t.cs_wr_off = t.cs_rd_off; 271 t.wr_cycle = t.rd_cycle; 272 if (cpu_is_omap34xx()) { 273 t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset + 274 gpmc_ns_to_ticks(min_gpmc_clk_period + 275 t_rdyo)); 276 t.wr_access = t.access; 277 } 278 } else { 279 t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, 280 t_avdp, t_cer)); 281 t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh); 282 t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); 283 t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); 284 t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); 285 if (cpu_is_omap34xx()) { 286 t.wr_data_mux_bus = t.we_on; 287 t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); 288 } 289 } 290 291 /* Configure GPMC for synchronous read */ 292 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 293 GPMC_CONFIG1_WRAPBURST_SUPP | 294 GPMC_CONFIG1_READMULTIPLE_SUPP | 295 (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | 296 (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | 297 (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | 298 GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | 299 GPMC_CONFIG1_PAGE_LEN(2) | 300 (cpu_is_omap34xx() ? 0 : 301 (GPMC_CONFIG1_WAIT_READ_MON | 302 GPMC_CONFIG1_WAIT_PIN_SEL(0))) | 303 GPMC_CONFIG1_DEVICESIZE_16 | 304 GPMC_CONFIG1_DEVICETYPE_NOR | 305 GPMC_CONFIG1_MUXADDDATA); 306 307 err = gpmc_cs_set_timings(cs, &t); 308 if (err) 309 return err; 310 311 set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf); 312 313 return 0; 314} 315 316static int gpmc_onenand_setup(void __iomem *onenand_base, int freq) 317{ 318 struct device *dev = &gpmc_onenand_device.dev; 319 320 /* Set sync timings in GPMC */ 321 if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, 322 freq) < 0) { 323 dev_err(dev, "Unable to set synchronous mode\n"); 324 return -EINVAL; 325 } 326 327 return 0; 328} 329 330void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) 331{ 332 gpmc_onenand_data = _onenand_data; 333 gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; 334 gpmc_onenand_device.dev.platform_data = gpmc_onenand_data; 335 336 if (cpu_is_omap24xx() && 337 (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) { 338 printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n"); 339 gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE; 340 gpmc_onenand_data->flags |= ONENAND_SYNC_READ; 341 } 342 343 if (platform_device_register(&gpmc_onenand_device) < 0) { 344 printk(KERN_ERR "Unable to register OneNAND device\n"); 345 return; 346 } 347} 348