summaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/netlogic
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/include/asm/netlogic')
-rw-r--r--arch/mips/include/asm/netlogic/mips-extns.h79
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h2
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pic.h12
-rw-r--r--arch/mips/include/asm/netlogic/xlr/pic.h48
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 */