From 5d8e701238c30a8b2df8bc5b116fad8a41a3e89c Mon Sep 17 00:00:00 2001 From: Quinn Jensen Date: Thu, 24 May 2007 18:23:44 -0600 Subject: Bugzilla 563: MX31 register swizzle work-around A problem has been discovered with MX31-TO2 silicon where a general register is loaded with an address constant from a PC-relative location. Upon going indirect through this register, the address value contained in the register will have been rotated right by 8 bits, causing a memory fault. At present the cause of the rotation is not known. This patch implements a work around to this problem, although why it works is still unknown. http://www.bitshrine.org/gpp/linux-2.6.19.2-mx31_TO2_reg_swizzle_workaround.patch --- arch/arm/plat-mxc/Kconfig | 14 ++++++++++++++ drivers/mxc/pm/dvfs_dptc.c | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index d6f061142717..fd4f53228a38 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -11,6 +11,20 @@ config ARCH_MX3 help This enables support for systems based on Freescale i.MX31 +config MX31_TO2_REG_SWIZZLE_WORKAROUND + bool "MX31-TO2 Register Swizzle Workaround" + depends on ARCH_MX3 + help + This option attempts to work around a problem discovered with + MX31-TO2 silicon where a general register is loaded with an + address constant from a PC-relative location. Upon going + indirect through this register, the address value contained + in the register will have been rotated right by 8 bits, causing + a memory fault. The cause of the rotation is not known, nor is + the reason why this work around seems to make the problem go + away. If you are using MX31-TO2 silicon and are faulting on + rotated addresses, enable this option. + config ARCH_MX27 bool "MX27-based" select MXC_EMMA diff --git a/drivers/mxc/pm/dvfs_dptc.c b/drivers/mxc/pm/dvfs_dptc.c index 40c5a79d7b59..cbbd9b51ef46 100644 --- a/drivers/mxc/pm/dvfs_dptc.c +++ b/drivers/mxc/pm/dvfs_dptc.c @@ -422,7 +422,11 @@ static int __init dvfs_dptc_init_default_table(void) return -ENOMEM; } +#ifdef CONFIG_MX31_TO2_REG_SWIZZLE_WORKAROUND + table_str = default_table_str_rev2; +#else table_str = default_table_str; +#endif if (cpu_is_mx31()) { if (system_rev < CHIP_REV_2_0) { clk = clk_get(NULL, "ckih"); @@ -435,7 +439,9 @@ static int __init dvfs_dptc_init_default_table(void) } } else { #ifdef CONFIG_ARCH_MX3 +#ifndef CONFIG_MX31_TO2_REG_SWIZZLE_WORKAROUND table_str = default_table_str_rev2; +#endif #endif } clk_put(clk); -- cgit v1.2.3