浏览代码

OMAP: OneNAND: let boards determine OneNAND frequency

OneNAND version ID may not give the highest frequency
supported and some OneNAND's have setup times that are
clock dependent.  Let the board provide that information.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Adrian Hunter 14 年之前
父节点
当前提交
5714b7ed6b
共有 2 个文件被更改,包括 67 次插入21 次删除
  1. 59 21
      arch/arm/mach-omap2/gpmc-onenand.c
  2. 8 0
      arch/arm/plat-omap/include/plat/onenand.h

+ 59 - 21
arch/arm/mach-omap2/gpmc-onenand.c

@@ -121,6 +121,47 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency,
 	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 }
 }
 
 
+static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
+				  void __iomem *onenand_base, bool *clk_dep)
+{
+	u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
+	int freq = 0;
+
+	if (cfg->get_freq) {
+		struct onenand_freq_info fi;
+
+		fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID);
+		fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID);
+		fi.ver_id = ver;
+		freq = cfg->get_freq(&fi, clk_dep);
+		if (freq)
+			return freq;
+	}
+
+	switch ((ver >> 4) & 0xf) {
+	case 0:
+		freq = 40;
+		break;
+	case 1:
+		freq = 54;
+		break;
+	case 2:
+		freq = 66;
+		break;
+	case 3:
+		freq = 83;
+		break;
+	case 4:
+		freq = 104;
+		break;
+	default:
+		freq = 54;
+		break;
+	}
+
+	return freq;
+}
+
 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					void __iomem *onenand_base,
 					void __iomem *onenand_base,
 					int *freq_ptr)
 					int *freq_ptr)
@@ -138,6 +179,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int err, ticks_cez;
 	int err, ticks_cez;
 	int cs = cfg->cs, freq = *freq_ptr;
 	int cs = cfg->cs, freq = *freq_ptr;
 	u32 reg;
 	u32 reg;
+	bool clk_dep = false;
 
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
 	if (cfg->flags & ONENAND_SYNC_READ) {
 		sync_read = 1;
 		sync_read = 1;
@@ -152,27 +194,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 		err = omap2_onenand_set_async_mode(cs, onenand_base);
 		err = omap2_onenand_set_async_mode(cs, onenand_base);
 		if (err)
 		if (err)
 			return err;
 			return err;
-		reg = readw(onenand_base + ONENAND_REG_VERSION_ID);
-		switch ((reg >> 4) & 0xf) {
-		case 0:
-			freq = 40;
-			break;
-		case 1:
-			freq = 54;
-			break;
-		case 2:
-			freq = 66;
-			break;
-		case 3:
-			freq = 83;
-			break;
-		case 4:
-			freq = 104;
-			break;
-		default:
-			freq = 54;
-			break;
-		}
+		freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
 		first_time = 1;
 		first_time = 1;
 	}
 	}
 
 
@@ -232,6 +254,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	else
 	else
 		latency = 4;
 		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)
 	if (first_time)
 		set_onenand_cfg(onenand_base, latency,
 		set_onenand_cfg(onenand_base, latency,
 					sync_read, sync_write, hf, vhf);
 					sync_read, sync_write, hf, vhf);

+ 8 - 0
arch/arm/plat-omap/include/plat/onenand.h

@@ -15,12 +15,20 @@
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
 
 
+struct onenand_freq_info {
+	u16			maf_id;
+	u16			dev_id;
+	u16			ver_id;
+};
+
 struct omap_onenand_platform_data {
 struct omap_onenand_platform_data {
 	int			cs;
 	int			cs;
 	int			gpio_irq;
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	struct mtd_partition	*parts;
 	int			nr_parts;
 	int			nr_parts;
 	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
 	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
+	int		(*get_freq)(const struct onenand_freq_info *freq_info,
+				    bool *clk_dep);
 	int			dma_channel;
 	int			dma_channel;
 	u8			flags;
 	u8			flags;
 	u8			regulator_can_sleep;
 	u8			regulator_can_sleep;