Retain the write-only OD from being clobbered
PATCH 1/1 Retain the write-only OD from being clobbered
First of several patches forwarded to me by Sergei Shtylyov. Ralf, these should be good to go for the tree.
Retain the write-only OD bit from being clobbered by coherency_setup()
---
arch/mips/mm/c-r4k.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-)
arch/mips/mm/c-r4k.c +14 -0
@@ -29,6 +29,10 @@#include <asm/war.h> #include <asm/cacheflush.h> /* for run_uncached() */ +#ifdef CONFIG_SOC_AU1X00 +#include <au1000.h> +#endif +/* * Must die. */
@@ -1203,6 +1207,16 @@ static inline void coherency_setup(void) {change_c0_config (CONF_CM_CMASK ,CONF_CM_DEFAULT ); +#ifdef CONFIG_SOC_AU1X00 +/* +* c0_config.od (bit 19) is write only (and reads as 0) on many early +* revs of AMD Au1x00 SOCs. It disables the bus transaction overlapping +* and needs to be set to correct the various errata. So if it has been +* set by the board setup code we must leave it set... +*/ +if (cur_cpu_spec[0 ]->cpu_od) +set_c0_config (1 <<19 ); +#endif /* * c0_status.cu=0 specifies that updates by the sc instruction use * the coherency mode specified by the TLB; 1 means cachable
Hello.
Quoted 7 lines · Jordan Crouse
First of several patches forwarded to me by Sergei Shtylyov. Ralf, these should be good to go for the tree.
Retain the write-only OD bit from being clobbered by
coherency_setup()Signed-off-by Sergei Shtylyov <[email protected]>Acked-by Jordan Crouse <[email protected]>
A long story of a long standing bug follows...
AMD Au1x00 board setup code in au1x00_setup() sets CONFIG.OD bit for the
early steppings of the Au1x00 SOCs, consulting the PRID table in arch/mips/au1000/common/cputable.c. This bit disables the bus transaction overlapping which causes a number of errata in those early SOC steppings (including the one that I think we've run into with USB host--at least setting the bit back to 1 fixed it, although disabling USB host DMA coherency also seemd to help). The problem is that this bit is write-only and reads as 0 on almost all SOCs that need it set. So, when the arch/mm/c-r4k.c code
does RMW to the CONFIG reg. in coherency_setup(), its value is lost, and the
chip again becomes prone to all the nasty errata that it has just been saved
from... :-)
There's couple more places in the assembly code where the CP0 CONFIG
reg. is written without care of OD bit:
1) In the cache parity error handler (arch/mips/mm/cex-gen.S) -- as thepanic() call follows shortly, probably CACHE.OD=0 doesn't matter much at this point;
2) In arch/mips/au1000/common/sleeper.S, when the CPU regs are being
restored on wakeup; Au1x00 PM code in 2.6 seem to have fallen out of
maintenance, and the stack frame set up there seemed just erratic (2.4
situation in this module is much better).
I didn't touch both those places. And of course, this CONFIG.OD bug is
present in 2.4 kernels as well...
WBR, Sergei
Hello
Quoted 19 lines · Sergei Shtylylov
Quoted 7 lines · Jordan Crouse
First of several patches forwarded to me by Sergei Shtylyov. Ralf, these should be good to go for the tree.
Retain the write-only OD bit from being clobbered by
coherency_setup()Signed-off-by Sergei Shtylyov <[email protected]>Acked-by Jordan Crouse <[email protected]>A long story of a long standing bug follows...
AMD Au1x00 board setup code inau1x00_setup()sets CONFIG.OD bit for
the early steppings of the Au1x00 SOCs, consulting the PRID table inarch/mips/au1000/common/cputable.c. This bit disables the bus transaction overlapping which causes a number of errata in those early SOC steppings (including the one that I think we've run into with USB host--at least setting the bit back to 1 fixed it, although disabling USB host DMA coherency also seemd to help). The problem is that this bit is write-only and reads as 0 on almost all SOCs that need it set. So, when thearch/mm/c-r4k.ccode
does RMW to the CONFIG reg. incoherency_setup(), its value is lost, and the
chip again becomes prone to all the nasty errata that it has just been saved
from... :-)
There's couple more places in the assembly code where the CP0
CONFIG reg. is written without care of OD bit:
Quoted 8 lines
1) In the cache parity error handler (
arch/mips/mm/cex-gen.S) -- as
thepanic()call follows shortly, probably CACHE.OD=0 doesn't matter much at this point;
2) Inarch/mips/au1000/common/sleeper.S, when the CPU regs are being
restored on wakeup; Au1x00 PM code in 2.6 seem to have fallen out of maintenance, and the stack frame set up there seemed just erratic (2.4 situation in this module is much better).
I didn't touch both those places. And of course, this CONFIG.OD bug is
present in 2.4 kernels as well...
Posting the reworked patch at last -- this variant doesn't include
machine-specific header into arch/mips/c-r4k.c...
WBR, Sergei
arch/mips/au1000/common/setup.c +11 -0
@@ -143,6 +143,17 @@ void __init plat_setup(void)au_writel (0 ,SYS_TOYTRIM ); } +/* +* Fix up write-only Config[OD] bit after a write to that register. Since the +* bit always reads as 0 on those SOC revs that require it to be set to fight +* the various errata, we need to set it back to 1... +*/ +void au1x00_fixup_config_od (void ) +{ +if (cur_cpu_spec[0 ]->cpu_od) +set_c0_config (1 <<19 ); +} +#if defined(CONFIG_64BIT_PHYS_ADDR )/* This routine should be valid for all Au1x based boards */ phys_t __fixup_bigphys_addr (phys_t phys_addr,phys_t size)
arch/mips/mm/c-r4k.c +12 -0
@@ -1201,8 +1201,20 @@ static void __init setup_scache(void)static inline void coherency_setup (void ) { +extern void au1x00_fixup_config_od (void ); +change_c0_config (CONF_CM_CMASK ,CONF_CM_DEFAULT ); +#ifdef CONFIG_SOC_AU1X00 +/* +* c0_config.od (bit 19) is write only (and reads as 0) on many early +* revs of AMD Au1x00 SOCs. It disables the bus transaction overlapping +* and needs to be set to correct the various errata. So if it has been +* set by the board setup code we must leave it set... +*/ +au1x00_fixup_config_od (); +#endif +/* * c0_status.cu=0 specifies that updates by the sc instruction use * the coherency mode specified by the TLB; 1 means cachable
Hello.
Retain the write-only OD bit from being clobbered by coherency_setup().
WBR, Sergei
PS: Looks like this patch is stuck uncommitted since December, while it's a serious issue causing the kernel lockups.
arch/mips/au1000/common/setup.c +11 -0
@@ -143,6 +143,17 @@ void __init plat_setup(void)au_writel (0 ,SYS_TOYTRIM ); } +/* +* Fix up write-only Config[OD] bit after a write to that register. Since the +* bit always reads as 0 on those SOC revs that require it to be set to fight +* the various errata, we need to set it back to 1... +*/ +void au1x00_fixup_config_od (void ) +{ +if (cur_cpu_spec[0 ]->cpu_od) +set_c0_config (1 <<19 ); +} +#if defined(CONFIG_64BIT_PHYS_ADDR )/* This routine should be valid for all Au1x based boards */ phys_t __fixup_bigphys_addr (phys_t phys_addr,phys_t size)
arch/mips/mm/c-r4k.c +12 -0
@@ -1201,8 +1201,20 @@ static void __init setup_scache(void)static inline void coherency_setup (void ) { +extern void au1x00_fixup_config_od (void ); +change_c0_config (CONF_CM_CMASK ,CONF_CM_DEFAULT ); +#ifdef CONFIG_SOC_AU1X00 +/* +* c0_config.od (bit 19) is write only (and reads as 0) on many early +* revs of AMD Au1x00 SOCs. It disables the bus transaction overlapping +* and needs to be set to correct the various errata. So if it has been +* set by the board setup code we must leave it set... +*/ +au1x00_fixup_config_od (); +#endif +/* * c0_status.cu=0 specifies that updates by the sc instruction use * the coherency mode specified by the TLB; 1 means cachable
Re: [PATCH] Save write-only Config.OD from being clobbered
Hello.
Save the Config.OD bit from being clobbered by coherency_setup(). This
bit, when set, fixes various errata in the early steppings of Au1x00 SOCs. Unfortunately, the bit was write-only on the most early of them. In addition, also restore the bit after a wakeup from sleep.
WBR, Sergei
arch/mips/au1000/common/sleeper.S +5 -0
@@ -112,6 +112,11 @@ sdsleep: mtc0 k0, CP0_PAGEMASK lw k0, 0x14(sp) mtc0 k0, CP0_CONFIG + + /* We need to catch the ealry Alchemy SOCs with + * the write-only Config[OD] bit and set it back to one... + */ + jal au1x00_fixup_config_od lw $1, PT_R1(sp) lw $2, PT_R2(sp) lw $3, PT_R3(sp)
arch/mips/mm/c-r4k.c +27 -0
@@ -1136,6 +1136,26 @@ static void __init setup_scache(void) c->options |=MIPS_CPU_SUBSET_CACHES ; } +void au1x00_fixup_config_od (void ) +{ +/* +* c0_config.od (bit 19) was write only (and read as 0) +* on the early revisions of Alchemy SOCs. It disables the bus +* transaction overlapping and needs to be set to fix various errata. +*/ +switch (current_cpu_data.cputype) { +case CPU_AU1000 :/* rev. DA, HA, HB */ +case CPU_AU1100 :/* rev. AB, BA, BC ?? */ +if ((read_c0_prid () &0xff ) <3 ) +set_c0_config (1 <<19 ); +break ; +case CPU_AU1500 :/* rev. AB */ +if ((read_c0_prid () &0xff ) <1 ) +set_c0_config (1 <<19 ); +break ; + } +} +static inline void coherency_setup (void ) {change_c0_config (CONF_CM_CMASK ,CONF_CM_DEFAULT );
@@ -1156,6 +1176,13 @@ static inline void coherency_setup(void)case CPU_R4400MC :clear_c0_config (CONF_CU );break ; +default : +/* +* We need to catch the ealry Alchemy SOCs with +* the write-only co_config.od bit and set it back to one... +*/ +au1x00_fixup_config_od (); +break ; } }
PATCH 1/1 Save write-only Config.OD from being clobbered (take 4)
Save the Config.OD bit from being clobbered by coherency_setup(). This
bit, when set, fixes various errata in the early steppings of Au1x00 SOCs. Unfortunately, the bit was write-only on the most early of them. In addition, also restore the bit after a wakeup from sleep.
WBR, Sergei
arch/mips/au1000/common/sleeper.S +5 -0
@@ -112,6 +112,11 @@ sdsleep: mtc0 k0, CP0_PAGEMASK lw k0, 0x14(sp) mtc0 k0, CP0_CONFIG + + /* We need to catch the ealry Alchemy SOCs with + * the write-only Config[OD] bit and set it back to one... + */ + jal au1x00_fixup_config_od lw $1, PT_R1(sp) lw $2, PT_R2(sp) lw $3, PT_R3(sp)
arch/mips/mm/c-r4k.c +34 -0
@@ -1136,6 +1136,31 @@ static void __init setup_scache(void) c->options |=MIPS_CPU_SUBSET_CACHES ; } +void au1x00_fixup_config_od (void ) +{ +/* +* c0_config.od (bit 19) was write only (and read as 0) +* on the early revisions of Alchemy SOCs. It disables the bus +* transaction overlapping and needs to be set to fix various errata. +*/ +switch (read_c0_prid ()) { +case 0x00030100 :/* Au1000 DA */ +case 0x00030201 :/* Au1000 HA */ +case 0x00030202 :/* Au1000 HB */ +case 0x01030200 :/* Au1500 AB */ +/* +* Au1100 errata actually keeps silence about this bit, so we set it +* just in case for those revisions that require it to be set according +* to arch/mips/au1000/common/cputable.c +*/ +case 0x02030200 :/* Au1100 AB */ +case 0x02030201 :/* Au1100 BA */ +case 0x02030202 :/* Au1100 BC */ +set_c0_config (1 <<19 ); +break ; + } +} +static inline void coherency_setup (void ) {change_c0_config (CONF_CM_CMASK ,CONF_CM_DEFAULT );
@@ -1156,6 +1181,15 @@ static inline void coherency_setup(void)case CPU_R4400MC :clear_c0_config (CONF_CU );break ; +/* +* We need to catch the ealry Alchemy SOCs with +* the write-only co_config.od bit and set it back to one... +*/ +case CPU_AU1000 :/* rev. DA, HA, HB */ +case CPU_AU1100 :/* rev. AB, BA, BC ?? */ +case CPU_AU1500 :/* rev. AB */ +au1x00_fixup_config_od (); +break ; } }
Re: [PATCH] Save write-only Config.OD from being clobbered (take 4)
arch/mips/au1000/common/sleeper.S sdsleep: · line 116
Quoted 1 line · Sergei Shtylyov
arch/mips/au1000/common/sleeper.S +1
-0+ /* We need to catch the ealry Alchemy SOCs with
^^^^^
typo
arch/mips/mm/c-r4k.c static inline void coherency_setup(void) · line 1185
Quoted 1 line
arch/mips/mm/c-r4k.c +1
-0+* We need to catch the ealry Alchemy SOCs with
likewise.
Signature · 2 lines
Martin Michlmayr http://www.cyrius.com/
Re: [PATCH] Save write-only Config.OD from being clobbered (take 4)
Hello.
Quoted 3 lines · Martin Michlmayr
arch/mips/au1000/common/sleeper.S sdsleep: · line 116
Quoted 1 line · Sergei Shtylyov
arch/mips/au1000/common/sleeper.S +1
-0+ /* We need to catch the ealry Alchemy SOCs with
^^^^^
Quoted 5 lines
typo
arch/mips/mm/c-r4k.c static inline void coherency_setup(void) · line 1185
Quoted 1 line
arch/mips/mm/c-r4k.c +1
-0+* We need to catch the ealry Alchemy SOCs with likewise.
Too late, after 6 or so months, it's in. :-)
WBR, Sergei