diff options
Diffstat (limited to 'include/asm-arm/arch-ixp2000/platform.h')
-rw-r--r-- | include/asm-arm/arch-ixp2000/platform.h | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index abdcf51bd283..a66317ab2071 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h | |||
@@ -15,40 +15,40 @@ | |||
15 | 15 | ||
16 | #ifndef __ASSEMBLY__ | 16 | #ifndef __ASSEMBLY__ |
17 | 17 | ||
18 | static inline unsigned long ixp2000_reg_read(volatile void *reg) | ||
19 | { | ||
20 | return *((volatile unsigned long *)reg); | ||
21 | } | ||
22 | |||
23 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) | ||
24 | { | ||
25 | *((volatile unsigned long *)reg) = val; | ||
26 | } | ||
27 | |||
18 | /* | 28 | /* |
19 | * The IXP2400 B0 silicon contains an erratum (#66) that causes writes | 29 | * On the IXP2400, we can't use XCB=000 due to chip bugs. We use |
20 | * to on-chip I/O register to not complete fully. What this means is | 30 | * XCB=101 instead, but that makes all I/O accesses bufferable. This |
21 | * that if you have a write to on-chip I/O followed by a back-to-back | 31 | * is not a problem in general, but we do have to be slightly more |
22 | * read or write, the first write will happen twice. OR...if it's | 32 | * careful because I/O writes are no longer automatically flushed out |
23 | * not a back-to-back transaction, the read or write will generate | 33 | * of the write buffer. |
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 | * | 34 | * |
35 | * In cases where we want to make sure that a write has been flushed | ||
36 | * out of the write buffer before we proceed, for example when masking | ||
37 | * a device interrupt before re-enabling IRQs in CPSR, we can use this | ||
38 | * function, ixp2000_reg_wrb, which performs a write, a readback, and | ||
39 | * issues a dummy instruction dependent on the value of the readback | ||
40 | * (mov rX, rX) to make sure that the readback has completed before we | ||
41 | * continue. | ||
29 | */ | 42 | */ |
30 | #if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401) | 43 | static inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val) |
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 | { | 44 | { |
36 | unsigned long dummy; | 45 | unsigned long dummy; |
37 | unsigned long flags; | ||
38 | 46 | ||
39 | local_irq_save(flags); | ||
40 | *((volatile unsigned long *)reg) = val; | 47 | *((volatile unsigned long *)reg) = val; |
41 | barrier(); | 48 | |
42 | dummy = *((volatile unsigned long *)reg); | 49 | dummy = *((volatile unsigned long *)reg); |
43 | local_irq_restore(flags); | 50 | __asm__ __volatile__("mov %0, %0" : "+r" (dummy)); |
44 | } | ||
45 | #else | ||
46 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) | ||
47 | { | ||
48 | *((volatile unsigned long *)reg) = val; | ||
49 | } | 51 | } |
50 | #endif /* IXDP2400 || IXDP2401 */ | ||
51 | #define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) | ||
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Boards may multiplex different devices on the 2nd channel of | 54 | * Boards may multiplex different devices on the 2nd channel of |