|
@@ -0,0 +1,106 @@
|
|
|
|
+/*
|
|
|
|
+ * linux/arch/arm/mach-omap2/gpmc-onenand.c
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2006 - 2009 Nokia Corporation
|
|
|
|
+ * Contacts: Juha Yrjola
|
|
|
|
+ * Tony Lindgren
|
|
|
|
+ *
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU General Public License version 2 as
|
|
|
|
+ * published by the Free Software Foundation.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include <linux/string.h>
|
|
|
|
+#include <linux/kernel.h>
|
|
|
|
+#include <linux/platform_device.h>
|
|
|
|
+#include <linux/mtd/onenand_regs.h>
|
|
|
|
+#include <linux/io.h>
|
|
|
|
+#include <linux/platform_data/mtd-onenand-omap2.h>
|
|
|
|
+#include <linux/err.h>
|
|
|
|
+
|
|
|
|
+#include <asm/mach/flash.h>
|
|
|
|
+
|
|
|
|
+#include "gpmc.h"
|
|
|
|
+#include "soc.h"
|
|
|
|
+#include "gpmc-onenand.h"
|
|
|
|
+
|
|
|
|
+#define ONENAND_IO_SIZE SZ_128K
|
|
|
|
+
|
|
|
|
+#define ONENAND_FLAG_SYNCREAD (1 << 0)
|
|
|
|
+#define ONENAND_FLAG_SYNCWRITE (1 << 1)
|
|
|
|
+#define ONENAND_FLAG_HF (1 << 2)
|
|
|
|
+#define ONENAND_FLAG_VHF (1 << 3)
|
|
|
|
+
|
|
|
|
+static unsigned onenand_flags;
|
|
|
|
+static unsigned latency;
|
|
|
|
+
|
|
|
|
+static struct omap_onenand_platform_data *gpmc_onenand_data;
|
|
|
|
+
|
|
|
|
+static struct resource gpmc_onenand_resource = {
|
|
|
|
+ .flags = IORESOURCE_MEM,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct platform_device gpmc_onenand_device = {
|
|
|
|
+ .name = "omap2-onenand",
|
|
|
|
+ .id = -1,
|
|
|
|
+ .num_resources = 1,
|
|
|
|
+ .resource = &gpmc_onenand_resource,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct gpmc_timings omap2_onenand_calc_async_timings(void)
|
|
|
|
+{
|
|
|
|
+ struct gpmc_device_timings dev_t;
|
|
|
|
+ struct gpmc_timings t;
|
|
|
|
+
|
|
|
|
+ const int t_cer = 15;
|
|
|
|
+ const int t_avdp = 12;
|
|
|
|
+ const int t_aavdh = 7;
|
|
|
|
+ const int t_ce = 76;
|
|
|
|
+ const int t_aa = 76;
|
|
|
|
+ const int t_oe = 20;
|
|
|
|
+ const int t_cez = 20; /* max of t_cez, t_oez */
|
|
|
|
+ const int t_wpl = 40;
|
|
|
|
+ const int t_wph = 30;
|
|
|
|
+
|
|
|
|
+ memset(&dev_t, 0, sizeof(dev_t));
|
|
|
|
+
|
|
|
|
+ dev_t.mux = true;
|
|
|
|
+ dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
|
|
|
|
+ dev_t.t_avdp_w = dev_t.t_avdp_r;
|
|
|
|
+ dev_t.t_aavdh = t_aavdh * 1000;
|
|
|
|
+ dev_t.t_aa = t_aa * 1000;
|
|
|
|
+ dev_t.t_ce = t_ce * 1000;
|
|
|
|
+ dev_t.t_oe = t_oe * 1000;
|
|
|
|
+ dev_t.t_cez_r = t_cez * 1000;
|
|
|
|
+ dev_t.t_cez_w = dev_t.t_cez_r;
|
|
|
|
+ dev_t.t_wpl = t_wpl * 1000;
|
|
|
|
+ dev_t.t_wph = t_wph * 1000;
|
|
|
|
+
|
|
|
|
+ gpmc_calc_timings(&t, &dev_t);
|
|
|
|
+
|
|
|
|
+ return t;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
|
|
|
|
+{
|
|
|
|
+ /* Configure GPMC for asynchronous read */
|
|
|
|
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
|
|
|
|
+ GPMC_CONFIG1_DEVICESIZE_16 |
|
|
|
|
+ GPMC_CONFIG1_MUXADDDATA);
|
|
|
|
+
|
|
|
|
+ return gpmc_cs_set_timings(cs, t);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
|
|
|
|
+{
|
|
|
|
+ u32 reg;
|
|
|
|
+
|
|
|
|
+ /* Ensure sync read and sync write are disabled */
|
|
|
|
+ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
|
|
|
|
+ reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
|
|
|
|
+ writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void set_onenand_cfg(void __iomem *onenand_base)
|
|
|
|
+{
|
|
|
|
+ u32 reg;
|