Commit e7b11dc7 authored by Tony Lindgren's avatar Tony Lindgren

ARM: OMAP2+: Fix onenand rate detection to avoid filesystem corruption

Commit 63aa945b ("memory: omap-gpmc: Add Kconfig option for debug")
unified the GPMC debug for the SoCs with GPMC. The commit also left out
the option for HWMOD_INIT_NO_RESET as we now require proper timings for
GPMC to be able to remap GPMC devices out of address 0.

Unfortunately on Nokia N900, onenand now only partially works with the
device tree provided timings. It works enough to get detected but the
clock rate supported by the onenand chip gets misdetected. This in turn
causes the GPMC timings to be miscalculated and this leads into file
system corruption on N900.

Looks like onenand needs CS_CONFIG1 bit 27 WRITETYPE set for for sync
write. This is needed also for async timings when we write to onenand
with omap2_onenand_set_async_mode(). Without sync write bit set, the
async read for the onenand ONENAND_REG_VERSION_ID will return 0xfff.

Let's exit with an error if onenand rate is not detected. And let's
remove the extra call to omap2_onenand_set_async_mode() as we only need
to do this once at the end of omap2_onenand_setup_async().

Fixes: 63aa945b ("memory: omap-gpmc: Add Kconfig option for debug")
Cc: stable@vger.kernel.org # v4.2+
Reported-by: default avatarIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Tested-by: default avatarIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Tested-by: default avatarAaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 0b4d6972
...@@ -149,8 +149,8 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, ...@@ -149,8 +149,8 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
freq = 104; freq = 104;
break; break;
default: default:
freq = 54; pr_err("onenand rate not detected, bad GPMC async timings?\n");
break; freq = 0;
} }
return freq; return freq;
...@@ -271,6 +271,11 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base) ...@@ -271,6 +271,11 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
struct gpmc_timings t; struct gpmc_timings t;
int ret; int ret;
/*
* Note that we need to keep sync_write set for the call to
* omap2_onenand_set_async_mode() to work to detect the onenand
* supported clock rate for the sync timings.
*/
if (gpmc_onenand_data->of_node) { if (gpmc_onenand_data->of_node) {
gpmc_read_settings_dt(gpmc_onenand_data->of_node, gpmc_read_settings_dt(gpmc_onenand_data->of_node,
&onenand_async); &onenand_async);
...@@ -281,12 +286,9 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base) ...@@ -281,12 +286,9 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
else else
gpmc_onenand_data->flags |= ONENAND_SYNC_READ; gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
onenand_async.sync_read = false; onenand_async.sync_read = false;
onenand_async.sync_write = false;
} }
} }
omap2_onenand_set_async_mode(onenand_base);
omap2_onenand_calc_async_timings(&t); omap2_onenand_calc_async_timings(&t);
ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async); ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
...@@ -310,6 +312,8 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr) ...@@ -310,6 +312,8 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
if (!freq) { if (!freq) {
/* Very first call freq is not known */ /* Very first call freq is not known */
freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base); freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base);
if (!freq)
return -ENODEV;
set_onenand_cfg(onenand_base); set_onenand_cfg(onenand_base);
} }
......
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