diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2005-10-29 11:28:26 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-10-29 11:28:26 -0400 |
commit | 931db7d6880027bb2b6b0cb78a488ab1486e28b7 (patch) | |
tree | fd85ee0a0d4fc217b59b639307af76bfd65504e0 | |
parent | 13bfb34c10fae6016710f5f070043c8b94b40583 (diff) |
[ARM] 3050/1: remove ixp2000_reg_write erratum #66 workaround
Patch from Lennert Buytenhek
The workaround that we do for avoiding triggering ixp2400 erratum #66
involves mapping I/O pages using XCB=101 instead of XCB=000 so that we
prevent the I/O signal to the gasket from being asserted (which can
cause data corruption.) But XCB=101 mappings are write-buffered while
mappings using XCB=000 are not, which is why if we use XCB=101 mappings
we do a readback for every CSR store in an attempt to make sure that
the store has been pushed out of the xscale core and the gasket.
Unfortunately, there are two issues with this:
- we do a readback for every CSR store, which is wrong, because the
register we are writing to might have unwanted side-effects on read,
for example, in the case of the scratchpad ring enqueue/dequeue
registers; and
- the readback is totally ineffective in the way we currently do it,
because we just issue a load but do not issue any instruction that
depends on the return value of that load, so the xscale core does
not wait for the load to complete before continuing.
See this linux-arm-kernel mailing list post for further information:
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2005-September/031314.html
This means that my ixp2400 boxes have been running for many months
without a working readback in ixp2000_reg_write, without any apparent
adverse effects. Two of them have been running for a week now with
the actual readback deleted from ixp2000_reg_write, also without any
apparent ill effects.
So, because in its current form it does more harm than good, the
readback in ixp2000_reg_write should simply be killed, as the patch
below does.
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | include/asm-arm/arch-ixp2000/platform.h | 29 |
1 files changed, 0 insertions, 29 deletions
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index abdcf51bd283..aabeef2454dd 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h | |||
@@ -15,39 +15,10 @@ | |||
15 | 15 | ||
16 | #ifndef __ASSEMBLY__ | 16 | #ifndef __ASSEMBLY__ |
17 | 17 | ||
18 | /* | ||
19 | * The IXP2400 B0 silicon contains an erratum (#66) that causes writes | ||
20 | * to on-chip I/O register to not complete fully. What this means is | ||
21 | * that if you have a write to on-chip I/O followed by a back-to-back | ||
22 | * read or write, the first write will happen twice. OR...if it's | ||
23 | * not a back-to-back transaction, the read or write will generate | ||
24 | * incorrect data. | ||
25 | * | ||
26 | * The official work around for this is to set the on-chip I/O regions | ||
27 | * as XCB=101 and then force a read-back from the register. | ||
28 | * | ||
29 | */ | ||
30 | #if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401) | ||
31 | |||
32 | #include <asm/system.h> /* Pickup local_irq_ functions */ | ||
33 | |||
34 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) | ||
35 | { | ||
36 | unsigned long dummy; | ||
37 | unsigned long flags; | ||
38 | |||
39 | local_irq_save(flags); | ||
40 | *((volatile unsigned long *)reg) = val; | ||
41 | barrier(); | ||
42 | dummy = *((volatile unsigned long *)reg); | ||
43 | local_irq_restore(flags); | ||
44 | } | ||
45 | #else | ||
46 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) | 18 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) |
47 | { | 19 | { |
48 | *((volatile unsigned long *)reg) = val; | 20 | *((volatile unsigned long *)reg) = val; |
49 | } | 21 | } |
50 | #endif /* IXDP2400 || IXDP2401 */ | ||
51 | #define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) | 22 | #define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) |
52 | 23 | ||
53 | /* | 24 | /* |