Commit 5714b7ed authored by Adrian Hunter's avatar Adrian Hunter Committed by Tony Lindgren

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: default avatarAdrian Hunter <adrian.hunter@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 3ad2d861
...@@ -121,6 +121,47 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, ...@@ -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, ...@@ -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, ...@@ -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); freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
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;
}
first_time = 1; first_time = 1;
} }
...@@ -232,6 +254,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, ...@@ -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);
......
...@@ -15,12 +15,20 @@ ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment