Commit 841bcd2e authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'omap-for-v4.4/onenand-corruption' of...

Merge tag 'omap-for-v4.4/onenand-corruption' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes

Pull "urgent onenand file system corruption fix for n900" from Tony Lindgren:

Last minute urgent pull request to prevent file system corruption
on Nokia N900.

Looks like we have a GPMC bus timing bug that has gone unnoticed
because of bootloader configured registers until few days ago. We
are not detecting the onenand clock rate properly unless we have
CONFIG_OMAP_GPMC_DEBUG set and this causes onenand corruption
that can be easily be reproduced.

There seems to be also an additional bug still lurking around for
onenand corruption. But that is still being investigated and
it does not seem to be GPMC timings related.

Meanwhile, it would be good to get this fix into v4.4 to prevent
wrong timings from corrupting onenand.

* tag 'omap-for-v4.4/onenand-corruption' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
  ARM: OMAP2+: Fix onenand rate detection to avoid filesystem corruption
parents 0f090bf1 e7b11dc7
...@@ -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