diff options
author | Jayachandran C <jchandra@broadcom.com> | 2013-03-23 13:27:57 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-05-07 19:19:05 -0400 |
commit | 1ad4af852bc3b352ac36ceffd2e30dbba413bc1a (patch) | |
tree | 0b5791f08708f54b14bee1be76a089d75e13bfab | |
parent | 3c0553e7347a96519ea232a9235dfb0eb1c6d3ec (diff) |
MIPS: Netlogic: Add 32-bit support for XLP
Update asm/netlogic/haldefs.h to extend register access functions
nlm_{read,write}_reg64() for 32-bit compilation. When compiled for 32-bit
the functions will read 64 IO registers with interrupts disabled.
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/5026/
Acked-by: John Crispin <blogic@openwrt.org>
-rw-r--r-- | arch/mips/include/asm/netlogic/haldefs.h | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/arch/mips/include/asm/netlogic/haldefs.h b/arch/mips/include/asm/netlogic/haldefs.h index 419d8aef8569..61fecb85e66f 100644 --- a/arch/mips/include/asm/netlogic/haldefs.h +++ b/arch/mips/include/asm/netlogic/haldefs.h | |||
@@ -35,14 +35,13 @@ | |||
35 | #ifndef __NLM_HAL_HALDEFS_H__ | 35 | #ifndef __NLM_HAL_HALDEFS_H__ |
36 | #define __NLM_HAL_HALDEFS_H__ | 36 | #define __NLM_HAL_HALDEFS_H__ |
37 | 37 | ||
38 | #include <linux/irqflags.h> /* for local_irq_disable */ | ||
39 | |||
38 | /* | 40 | /* |
39 | * This file contains platform specific memory mapped IO implementation | 41 | * This file contains platform specific memory mapped IO implementation |
40 | * and will provide a way to read 32/64 bit memory mapped registers in | 42 | * and will provide a way to read 32/64 bit memory mapped registers in |
41 | * all ABIs | 43 | * all ABIs |
42 | */ | 44 | */ |
43 | #if !defined(CONFIG_64BIT) && defined(CONFIG_CPU_XLP) | ||
44 | #error "o32 compile not supported on XLP yet" | ||
45 | #endif | ||
46 | /* | 45 | /* |
47 | * For o32 compilation, we have to disable interrupts and enable KX bit to | 46 | * For o32 compilation, we have to disable interrupts and enable KX bit to |
48 | * access 64 bit addresses or data. | 47 | * access 64 bit addresses or data. |
@@ -87,13 +86,40 @@ nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val) | |||
87 | *addr = val; | 86 | *addr = val; |
88 | } | 87 | } |
89 | 88 | ||
89 | /* | ||
90 | * For o32 compilation, we have to disable interrupts to access 64 bit | ||
91 | * registers | ||
92 | * | ||
93 | * We need to disable interrupts because we save just the lower 32 bits of | ||
94 | * registers in interrupt handling. So if we get hit by an interrupt while | ||
95 | * using the upper 32 bits of a register, we lose. | ||
96 | */ | ||
97 | |||
90 | static inline uint64_t | 98 | static inline uint64_t |
91 | nlm_read_reg64(uint64_t base, uint32_t reg) | 99 | nlm_read_reg64(uint64_t base, uint32_t reg) |
92 | { | 100 | { |
93 | uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); | 101 | uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); |
94 | volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; | 102 | volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; |
95 | 103 | uint64_t val; | |
96 | return *ptr; | 104 | |
105 | if (sizeof(unsigned long) == 4) { | ||
106 | unsigned long flags; | ||
107 | |||
108 | local_irq_save(flags); | ||
109 | __asm__ __volatile__( | ||
110 | ".set push" "\n\t" | ||
111 | ".set mips64" "\n\t" | ||
112 | "ld %L0, %1" "\n\t" | ||
113 | "dsra32 %M0, %L0, 0" "\n\t" | ||
114 | "sll %L0, %L0, 0" "\n\t" | ||
115 | ".set pop" "\n" | ||
116 | : "=r" (val) | ||
117 | : "m" (*ptr)); | ||
118 | local_irq_restore(flags); | ||
119 | } else | ||
120 | val = *ptr; | ||
121 | |||
122 | return val; | ||
97 | } | 123 | } |
98 | 124 | ||
99 | static inline void | 125 | static inline void |
@@ -102,7 +128,25 @@ nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val) | |||
102 | uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); | 128 | uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); |
103 | volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; | 129 | volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; |
104 | 130 | ||
105 | *ptr = val; | 131 | if (sizeof(unsigned long) == 4) { |
132 | unsigned long flags; | ||
133 | uint64_t tmp; | ||
134 | |||
135 | local_irq_save(flags); | ||
136 | __asm__ __volatile__( | ||
137 | ".set push" "\n\t" | ||
138 | ".set mips64" "\n\t" | ||
139 | "dsll32 %L0, %L0, 0" "\n\t" | ||
140 | "dsrl32 %L0, %L0, 0" "\n\t" | ||
141 | "dsll32 %M0, %M0, 0" "\n\t" | ||
142 | "or %L0, %L0, %M0" "\n\t" | ||
143 | "sd %L0, %2" "\n\t" | ||
144 | ".set pop" "\n" | ||
145 | : "=r" (tmp) | ||
146 | : "0" (val), "m" (*ptr)); | ||
147 | local_irq_restore(flags); | ||
148 | } else | ||
149 | *ptr = val; | ||
106 | } | 150 | } |
107 | 151 | ||
108 | /* | 152 | /* |