diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2013-02-21 15:51:33 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-02-21 15:51:33 +0400 |
commit | 8bfc245f9ad7bd4e461179e4e7852ef99b8b6144 (patch) | |
tree | 0ad091f645fbc8318634599d278966a53d3922ee /arch/mips/include/asm/netlogic | |
parent | 612663a974065c3445e641d046769fe4c55a6438 (diff) | |
parent | 535237cecab2b078114be712c67e89a0db61965f (diff) | |
download | linux-8bfc245f9ad7bd4e461179e4e7852ef99b8b6144.tar.xz |
Merge branch 'mips-next-3.9' of git://git.linux-mips.org/pub/scm/john/linux-john into mips-for-linux-next
Diffstat (limited to 'arch/mips/include/asm/netlogic')
-rw-r--r-- | arch/mips/include/asm/netlogic/mips-extns.h | 79 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/pic.h | 12 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlr/pic.h | 48 |
4 files changed, 136 insertions, 5 deletions
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index 8ffae43107e6..8ad2e0f81719 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -68,6 +68,85 @@ do { \ __write_64bit_c0_register($9, 7, (val)); \ } while (0) +/* + * Handling the 64 bit EIMR and EIRR registers in 32-bit mode with + * standard functions will be very inefficient. This provides + * optimized functions for the normal operations on the registers. + * + * Call with interrupts disabled. + */ +static inline void ack_c0_eirr(int irq) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set mips64\n\t" + ".set noat\n\t" + "li $1, 1\n\t" + "dsllv $1, $1, %0\n\t" + "dmtc0 $1, $9, 6\n\t" + ".set pop" + : : "r" (irq)); +} + +static inline void set_c0_eimr(int irq) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set mips64\n\t" + ".set noat\n\t" + "li $1, 1\n\t" + "dsllv %0, $1, %0\n\t" + "dmfc0 $1, $9, 7\n\t" + "or $1, %0\n\t" + "dmtc0 $1, $9, 7\n\t" + ".set pop" + : "+r" (irq)); +} + +static inline void clear_c0_eimr(int irq) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set mips64\n\t" + ".set noat\n\t" + "li $1, 1\n\t" + "dsllv %0, $1, %0\n\t" + "dmfc0 $1, $9, 7\n\t" + "or $1, %0\n\t" + "xor $1, %0\n\t" + "dmtc0 $1, $9, 7\n\t" + ".set pop" + : "+r" (irq)); +} + +/* + * Read c0 eimr and c0 eirr, do AND of the two values, the result is + * the interrupts which are raised and are not masked. + */ +static inline uint64_t read_c0_eirr_and_eimr(void) +{ + uint64_t val; + +#ifdef CONFIG_64BIT + val = read_c0_eimr() & read_c0_eirr(); +#else + __asm__ __volatile__( + ".set push\n\t" + ".set mips64\n\t" + ".set noat\n\t" + "dmfc0 %M0, $9, 6\n\t" + "dmfc0 %L0, $9, 7\n\t" + "and %M0, %L0\n\t" + "dsll %L0, %M0, 32\n\t" + "dsra %M0, %M0, 32\n\t" + "dsra %L0, %L0, 32\n\t" + ".set pop" + : "=r" (val)); +#endif + + return val; +} + static inline int hard_smp_processor_id(void) { return __read_32bit_c0_register($15, 1) & 0x3ff; diff --git a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h index 7b63a6b722a0..6d2e58a9a542 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h @@ -46,6 +46,8 @@ #define CPU_BLOCKID_FPU 9 #define CPU_BLOCKID_MAP 10 +#define ICU_DEFEATURE 0x100 + #define LSU_DEFEATURE 0x304 #define LSU_DEBUG_ADDR 0x305 #define LSU_DEBUG_DATA0 0x306 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index 46ace0ca26d8..3df53017fe51 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -261,6 +261,8 @@ #define PIC_LOCAL_SCHEDULING 1 #define PIC_GLOBAL_SCHEDULING 0 +#define PIC_CLK_HZ 133333333 + #define nlm_read_pic_reg(b, r) nlm_read_reg64(b, r) #define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v) #define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node)) @@ -315,6 +317,12 @@ nlm_pic_read_timer(uint64_t base, int timer) return nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer)); } +static inline uint32_t +nlm_pic_read_timer32(uint64_t base, int timer) +{ + return (uint32_t)nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer)); +} + static inline void nlm_pic_write_timer(uint64_t base, int timer, uint64_t value) { @@ -376,9 +384,9 @@ nlm_pic_ack(uint64_t base, int irt_num) } static inline void -nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) +nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en) { - nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt); + nlm_pic_write_irt_direct(base, irt, en, 0, 0, irq, hwt); } int nlm_irq_to_irt(int irq); diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h index 2f549453585e..63c99176dffe 100644 --- a/arch/mips/include/asm/netlogic/xlr/pic.h +++ b/arch/mips/include/asm/netlogic/xlr/pic.h @@ -35,10 +35,11 @@ #ifndef _ASM_NLM_XLR_PIC_H #define _ASM_NLM_XLR_PIC_H -#define PIC_CLKS_PER_SEC 66666666ULL +#define PIC_CLK_HZ 66666666 /* PIC hardware interrupt numbers */ #define PIC_IRT_WD_INDEX 0 #define PIC_IRT_TIMER_0_INDEX 1 +#define PIC_IRT_TIMER_INDEX(i) ((i) + PIC_IRT_TIMER_0_INDEX) #define PIC_IRT_TIMER_1_INDEX 2 #define PIC_IRT_TIMER_2_INDEX 3 #define PIC_IRT_TIMER_3_INDEX 4 @@ -99,6 +100,7 @@ /* PIC Registers */ #define PIC_CTRL 0x00 +#define PIC_CTRL_STE 8 /* timer enable start bit */ #define PIC_IPI 0x04 #define PIC_INT_ACK 0x06 @@ -251,12 +253,52 @@ nlm_pic_ack(uint64_t base, int irt) } static inline void -nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) +nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en) { nlm_write_reg(base, PIC_IRT_0(irt), (1u << hwt)); /* local scheduling, invalid, level by default */ nlm_write_reg(base, PIC_IRT_1(irt), - (1 << 30) | (1 << 6) | irq); + (en << 30) | (1 << 6) | irq); +} + +static inline uint64_t +nlm_pic_read_timer(uint64_t base, int timer) +{ + uint32_t up1, up2, low; + + up1 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer)); + low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); + up2 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer)); + + if (up1 != up2) /* wrapped, get the new low */ + low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); + return ((uint64_t)up2 << 32) | low; + +} + +static inline uint32_t +nlm_pic_read_timer32(uint64_t base, int timer) +{ + return nlm_read_reg(base, PIC_TIMER_COUNT_0(timer)); +} + +static inline void +nlm_pic_set_timer(uint64_t base, int timer, uint64_t value, int irq, int cpu) +{ + uint32_t up, low; + uint64_t pic_ctrl = nlm_read_reg(base, PIC_CTRL); + int en; + + en = (irq > 0); + up = value >> 32; + low = value & 0xFFFFFFFF; + nlm_write_reg(base, PIC_TIMER_MAXVAL_0(timer), low); + nlm_write_reg(base, PIC_TIMER_MAXVAL_1(timer), up); + nlm_pic_init_irt(base, PIC_IRT_TIMER_INDEX(timer), irq, cpu, 0); + + /* enable the timer */ + pic_ctrl |= (1 << (PIC_CTRL_STE + timer)); + nlm_write_reg(base, PIC_CTRL, pic_ctrl); } #endif #endif /* _ASM_NLM_XLR_PIC_H */ |