linux/arch/arm/mach-omap2/gpmc-onenand.c
<<
>>
Prefs
   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#include <linux/omap-gpmc.h>
  19#include <linux/platform_data/mtd-onenand-omap2.h>
  20#include <linux/err.h>
  21
  22#include <asm/mach/flash.h>
  23
  24#include "soc.h"
  25
  26#define ONENAND_IO_SIZE SZ_128K
  27
  28#define ONENAND_FLAG_SYNCREAD   (1 << 0)
  29#define ONENAND_FLAG_SYNCWRITE  (1 << 1)
  30#define ONENAND_FLAG_HF         (1 << 2)
  31#define ONENAND_FLAG_VHF        (1 << 3)
  32
  33static unsigned onenand_flags;
  34static unsigned latency;
  35
  36static struct omap_onenand_platform_data *gpmc_onenand_data;
  37
  38static struct resource gpmc_onenand_resource = {
  39        .flags          = IORESOURCE_MEM,
  40};
  41
  42static struct platform_device gpmc_onenand_device = {
  43        .name           = "omap2-onenand",
  44        .id             = -1,
  45        .num_resources  = 1,
  46        .resource       = &gpmc_onenand_resource,
  47};
  48
  49static struct gpmc_settings onenand_async = {
  50        .device_width   = GPMC_DEVWIDTH_16BIT,
  51        .mux_add_data   = GPMC_MUX_AD,
  52};
  53
  54static struct gpmc_settings onenand_sync = {
  55        .burst_read     = true,
  56        .burst_wrap     = true,
  57        .burst_len      = GPMC_BURST_16,
  58        .device_width   = GPMC_DEVWIDTH_16BIT,
  59        .mux_add_data   = GPMC_MUX_AD,
  60        .wait_pin       = 0,
  61};
  62
  63static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
  64{
  65        struct gpmc_device_timings dev_t;
  66        const int t_cer = 15;
  67        const int t_avdp = 12;
  68        const int t_aavdh = 7;
  69        const int t_ce = 76;
  70        const int t_aa = 76;
  71        const int t_oe = 20;
  72        const int t_cez = 20; /* max of t_cez, t_oez */
  73        const int t_wpl = 40;
  74        const int t_wph = 30;
  75
  76        memset(&dev_t, 0, sizeof(dev_t));
  77
  78        dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
  79        dev_t.t_avdp_w = dev_t.t_avdp_r;
  80        dev_t.t_aavdh = t_aavdh * 1000;
  81        dev_t.t_aa = t_aa * 1000;
  82        dev_t.t_ce = t_ce * 1000;
  83        dev_t.t_oe = t_oe * 1000;
  84        dev_t.t_cez_r = t_cez * 1000;
  85        dev_t.t_cez_w = dev_t.t_cez_r;
  86        dev_t.t_wpl = t_wpl * 1000;
  87        dev_t.t_wph = t_wph * 1000;
  88
  89        gpmc_calc_timings(t, &onenand_async, &dev_t);
  90}
  91
  92static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
  93{
  94        u32 reg;
  95
  96        /* Ensure sync read and sync write are disabled */
  97        reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
  98        reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
  99        writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 100}
 101
 102static void set_onenand_cfg(void __iomem *onenand_base)
 103{
 104        u32 reg;
 105
 106        reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
 107        reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
 108        reg |=  (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
 109                ONENAND_SYS_CFG1_BL_16;
 110        if (onenand_flags & ONENAND_FLAG_SYNCREAD)
 111                reg |= ONENAND_SYS_CFG1_SYNC_READ;
 112        else
 113                reg &= ~ONENAND_SYS_CFG1_SYNC_READ;
 114        if (onenand_flags & ONENAND_FLAG_SYNCWRITE)
 115                reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
 116        else
 117                reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
 118        if (onenand_flags & ONENAND_FLAG_HF)
 119                reg |= ONENAND_SYS_CFG1_HF;
 120        else
 121                reg &= ~ONENAND_SYS_CFG1_HF;
 122        if (onenand_flags & ONENAND_FLAG_VHF)
 123                reg |= ONENAND_SYS_CFG1_VHF;
 124        else
 125                reg &= ~ONENAND_SYS_CFG1_VHF;
 126        writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 127}
 128
 129static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
 130                                  void __iomem *onenand_base)
 131{
 132        u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
 133        int freq;
 134
 135        switch ((ver >> 4) & 0xf) {
 136        case 0:
 137                freq = 40;
 138                break;
 139        case 1:
 140                freq = 54;
 141                break;
 142        case 2:
 143                freq = 66;
 144                break;
 145        case 3:
 146                freq = 83;
 147                break;
 148        case 4:
 149                freq = 104;
 150                break;
 151        default:
 152                freq = 54;
 153                break;
 154        }
 155
 156        return freq;
 157}
 158
 159static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
 160                                            unsigned int flags,
 161                                            int freq)
 162{
 163        struct gpmc_device_timings dev_t;
 164        const int t_cer  = 15;
 165        const int t_avdp = 12;
 166        const int t_cez  = 20; /* max of t_cez, t_oez */
 167        const int t_wpl  = 40;
 168        const int t_wph  = 30;
 169        int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
 170        int div, gpmc_clk_ns;
 171
 172        if (flags & ONENAND_SYNC_READ)
 173                onenand_flags = ONENAND_FLAG_SYNCREAD;
 174        else if (flags & ONENAND_SYNC_READWRITE)
 175                onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
 176
 177        switch (freq) {
 178        case 104:
 179                min_gpmc_clk_period = 9600; /* 104 MHz */
 180                t_ces   = 3;
 181                t_avds  = 4;
 182                t_avdh  = 2;
 183                t_ach   = 3;
 184                t_aavdh = 6;
 185                t_rdyo  = 6;
 186                break;
 187        case 83:
 188                min_gpmc_clk_period = 12000; /* 83 MHz */
 189                t_ces   = 5;
 190                t_avds  = 4;
 191                t_avdh  = 2;
 192                t_ach   = 6;
 193                t_aavdh = 6;
 194                t_rdyo  = 9;
 195                break;
 196        case 66:
 197                min_gpmc_clk_period = 15000; /* 66 MHz */
 198                t_ces   = 6;
 199                t_avds  = 5;
 200                t_avdh  = 2;
 201                t_ach   = 6;
 202                t_aavdh = 6;
 203                t_rdyo  = 11;
 204                break;
 205        default:
 206                min_gpmc_clk_period = 18500; /* 54 MHz */
 207                t_ces   = 7;
 208                t_avds  = 7;
 209                t_avdh  = 7;
 210                t_ach   = 9;
 211                t_aavdh = 7;
 212                t_rdyo  = 15;
 213                onenand_flags &= ~ONENAND_FLAG_SYNCWRITE;
 214                break;
 215        }
 216
 217        div = gpmc_calc_divider(min_gpmc_clk_period);
 218        gpmc_clk_ns = gpmc_ticks_to_ns(div);
 219        if (gpmc_clk_ns < 15) /* >66Mhz */
 220                onenand_flags |= ONENAND_FLAG_HF;
 221        else
 222                onenand_flags &= ~ONENAND_FLAG_HF;
 223        if (gpmc_clk_ns < 12) /* >83Mhz */
 224                onenand_flags |= ONENAND_FLAG_VHF;
 225        else
 226                onenand_flags &= ~ONENAND_FLAG_VHF;
 227        if (onenand_flags & ONENAND_FLAG_VHF)
 228                latency = 8;
 229        else if (onenand_flags & ONENAND_FLAG_HF)
 230                latency = 6;
 231        else if (gpmc_clk_ns >= 25) /* 40 MHz*/
 232                latency = 3;
 233        else
 234                latency = 4;
 235
 236        /* Set synchronous read timings */
 237        memset(&dev_t, 0, sizeof(dev_t));
 238
 239        if (onenand_flags & ONENAND_FLAG_SYNCREAD)
 240                onenand_sync.sync_read = true;
 241        if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
 242                onenand_sync.sync_write = true;
 243                onenand_sync.burst_write = true;
 244        } else {
 245                dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
 246                dev_t.t_wpl = t_wpl * 1000;
 247                dev_t.t_wph = t_wph * 1000;
 248                dev_t.t_aavdh = t_aavdh * 1000;
 249        }
 250        dev_t.ce_xdelay = true;
 251        dev_t.avd_xdelay = true;
 252        dev_t.oe_xdelay = true;
 253        dev_t.we_xdelay = true;
 254        dev_t.clk = min_gpmc_clk_period;
 255        dev_t.t_bacc = dev_t.clk;
 256        dev_t.t_ces = t_ces * 1000;
 257        dev_t.t_avds = t_avds * 1000;
 258        dev_t.t_avdh = t_avdh * 1000;
 259        dev_t.t_ach = t_ach * 1000;
 260        dev_t.cyc_iaa = (latency + 1);
 261        dev_t.t_cez_r = t_cez * 1000;
 262        dev_t.t_cez_w = dev_t.t_cez_r;
 263        dev_t.cyc_aavdh_oe = 1;
 264        dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
 265
 266        gpmc_calc_timings(t, &onenand_sync, &dev_t);
 267}
 268
 269static int omap2_onenand_setup_async(void __iomem *onenand_base)
 270{
 271        struct gpmc_timings t;
 272        int ret;
 273
 274        if (gpmc_onenand_data->of_node) {
 275                gpmc_read_settings_dt(gpmc_onenand_data->of_node,
 276                                      &onenand_async);
 277                if (onenand_async.sync_read || onenand_async.sync_write) {
 278                        if (onenand_async.sync_write)
 279                                gpmc_onenand_data->flags |=
 280                                        ONENAND_SYNC_READWRITE;
 281                        else
 282                                gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 283                        onenand_async.sync_read = false;
 284                        onenand_async.sync_write = false;
 285                }
 286        }
 287
 288        omap2_onenand_set_async_mode(onenand_base);
 289
 290        omap2_onenand_calc_async_timings(&t);
 291
 292        ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
 293        if (ret < 0)
 294                return ret;
 295
 296        ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
 297        if (ret < 0)
 298                return ret;
 299
 300        omap2_onenand_set_async_mode(onenand_base);
 301
 302        return 0;
 303}
 304
 305static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
 306{
 307        int ret, freq = *freq_ptr;
 308        struct gpmc_timings t;
 309
 310        if (!freq) {
 311                /* Very first call freq is not known */
 312                freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base);
 313                set_onenand_cfg(onenand_base);
 314        }
 315
 316        if (gpmc_onenand_data->of_node) {
 317                gpmc_read_settings_dt(gpmc_onenand_data->of_node,
 318                                      &onenand_sync);
 319        } else {
 320                /*
 321                 * FIXME: Appears to be legacy code from initial ONENAND commit.
 322                 * Unclear what boards this is for and if this can be removed.
 323                 */
 324                if (!cpu_is_omap34xx())
 325                        onenand_sync.wait_on_read = true;
 326        }
 327
 328        omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
 329
 330        ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
 331        if (ret < 0)
 332                return ret;
 333
 334        ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
 335        if (ret < 0)
 336                return ret;
 337
 338        set_onenand_cfg(onenand_base);
 339
 340        *freq_ptr = freq;
 341
 342        return 0;
 343}
 344
 345static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 346{
 347        struct device *dev = &gpmc_onenand_device.dev;
 348        unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
 349        int ret;
 350
 351        ret = omap2_onenand_setup_async(onenand_base);
 352        if (ret) {
 353                dev_err(dev, "unable to set to async mode\n");
 354                return ret;
 355        }
 356
 357        if (!(gpmc_onenand_data->flags & l))
 358                return 0;
 359
 360        ret = omap2_onenand_setup_sync(onenand_base, freq_ptr);
 361        if (ret)
 362                dev_err(dev, "unable to set to sync mode\n");
 363        return ret;
 364}
 365
 366void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 367{
 368        int err;
 369        struct device *dev = &gpmc_onenand_device.dev;
 370
 371        gpmc_onenand_data = _onenand_data;
 372        gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
 373        gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
 374
 375        if (cpu_is_omap24xx() &&
 376                        (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
 377                dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
 378                gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
 379                gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 380        }
 381
 382        if (cpu_is_omap34xx())
 383                gpmc_onenand_data->flags |= ONENAND_IN_OMAP34XX;
 384        else
 385                gpmc_onenand_data->flags &= ~ONENAND_IN_OMAP34XX;
 386
 387        err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
 388                                (unsigned long *)&gpmc_onenand_resource.start);
 389        if (err < 0) {
 390                dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
 391                        gpmc_onenand_data->cs, err);
 392                return;
 393        }
 394
 395        gpmc_onenand_resource.end = gpmc_onenand_resource.start +
 396                                                        ONENAND_IO_SIZE - 1;
 397
 398        if (platform_device_register(&gpmc_onenand_device) < 0) {
 399                dev_err(dev, "Unable to register OneNAND device\n");
 400                gpmc_cs_free(gpmc_onenand_data->cs);
 401                return;
 402        }
 403}
 404