Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jayachandran C and committed by
Ralf Baechle
1ad4af85 3c0553e7

+49 -5
+49 -5
arch/mips/include/asm/netlogic/haldefs.h
··· 35 35 #ifndef __NLM_HAL_HALDEFS_H__ 36 36 #define __NLM_HAL_HALDEFS_H__ 37 37 38 + #include <linux/irqflags.h> /* for local_irq_disable */ 39 + 38 40 /* 39 41 * This file contains platform specific memory mapped IO implementation 40 42 * and will provide a way to read 32/64 bit memory mapped registers in 41 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 46 * For o32 compilation, we have to disable interrupts and enable KX bit to 48 47 * access 64 bit addresses or data. ··· 86 87 *addr = val; 87 88 } 88 89 90 + /* 91 + * For o32 compilation, we have to disable interrupts to access 64 bit 92 + * registers 93 + * 94 + * We need to disable interrupts because we save just the lower 32 bits of 95 + * registers in interrupt handling. So if we get hit by an interrupt while 96 + * using the upper 32 bits of a register, we lose. 97 + */ 98 + 89 99 static inline uint64_t 90 100 nlm_read_reg64(uint64_t base, uint32_t reg) 91 101 { 92 102 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 93 103 volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; 104 + uint64_t val; 94 105 95 - return *ptr; 106 + if (sizeof(unsigned long) == 4) { 107 + unsigned long flags; 108 + 109 + local_irq_save(flags); 110 + __asm__ __volatile__( 111 + ".set push" "\n\t" 112 + ".set mips64" "\n\t" 113 + "ld %L0, %1" "\n\t" 114 + "dsra32 %M0, %L0, 0" "\n\t" 115 + "sll %L0, %L0, 0" "\n\t" 116 + ".set pop" "\n" 117 + : "=r" (val) 118 + : "m" (*ptr)); 119 + local_irq_restore(flags); 120 + } else 121 + val = *ptr; 122 + 123 + return val; 96 124 } 97 125 98 126 static inline void ··· 128 102 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); 129 103 volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; 130 104 131 - *ptr = val; 105 + if (sizeof(unsigned long) == 4) { 106 + unsigned long flags; 107 + uint64_t tmp; 108 + 109 + local_irq_save(flags); 110 + __asm__ __volatile__( 111 + ".set push" "\n\t" 112 + ".set mips64" "\n\t" 113 + "dsll32 %L0, %L0, 0" "\n\t" 114 + "dsrl32 %L0, %L0, 0" "\n\t" 115 + "dsll32 %M0, %M0, 0" "\n\t" 116 + "or %L0, %L0, %M0" "\n\t" 117 + "sd %L0, %2" "\n\t" 118 + ".set pop" "\n" 119 + : "=r" (tmp) 120 + : "0" (val), "m" (*ptr)); 121 + local_irq_restore(flags); 122 + } else 123 + *ptr = val; 132 124 } 133 125 134 126 /*