|
@@ -1488,3 +1488,191 @@ static inline void tlb_write_indexed(void)
|
|
".set noreorder\n\t"
|
|
".set noreorder\n\t"
|
|
"tlbwi\n\t"
|
|
"tlbwi\n\t"
|
|
".set reorder");
|
|
".set reorder");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void tlb_write_random(void)
|
|
|
|
+{
|
|
|
|
+ __asm__ __volatile__(
|
|
|
|
+ ".set noreorder\n\t"
|
|
|
|
+ "tlbwr\n\t"
|
|
|
|
+ ".set reorder");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Manipulate bits in a c0 register.
|
|
|
|
+ */
|
|
|
|
+#ifndef CONFIG_MIPS_MT_SMTC
|
|
|
|
+/*
|
|
|
|
+ * SMTC Linux requires shutting-down microthread scheduling
|
|
|
|
+ * during CP0 register read-modify-write sequences.
|
|
|
|
+ */
|
|
|
|
+#define __BUILD_SET_C0(name) \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+set_c0_##name(unsigned int set) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res, new; \
|
|
|
|
+ \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res | set; \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+} \
|
|
|
|
+ \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+clear_c0_##name(unsigned int clear) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res, new; \
|
|
|
|
+ \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res & ~clear; \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+} \
|
|
|
|
+ \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+change_c0_##name(unsigned int change, unsigned int val) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res, new; \
|
|
|
|
+ \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res & ~change; \
|
|
|
|
+ new |= (val & change); \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#else /* SMTC versions that manage MT scheduling */
|
|
|
|
+
|
|
|
|
+#include <linux/irqflags.h>
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
|
|
|
|
+ * header file recursion.
|
|
|
|
+ */
|
|
|
|
+static inline unsigned int __dmt(void)
|
|
|
|
+{
|
|
|
|
+ int res;
|
|
|
|
+
|
|
|
|
+ __asm__ __volatile__(
|
|
|
|
+ " .set push \n"
|
|
|
|
+ " .set mips32r2 \n"
|
|
|
|
+ " .set noat \n"
|
|
|
|
+ " .word 0x41610BC1 # dmt $1 \n"
|
|
|
|
+ " ehb \n"
|
|
|
|
+ " move %0, $1 \n"
|
|
|
|
+ " .set pop \n"
|
|
|
|
+ : "=r" (res));
|
|
|
|
+
|
|
|
|
+ instruction_hazard();
|
|
|
|
+
|
|
|
|
+ return res;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define __VPECONTROL_TE_SHIFT 15
|
|
|
|
+#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT)
|
|
|
|
+
|
|
|
|
+#define __EMT_ENABLE __VPECONTROL_TE
|
|
|
|
+
|
|
|
|
+static inline void __emt(unsigned int previous)
|
|
|
|
+{
|
|
|
|
+ if ((previous & __EMT_ENABLE))
|
|
|
|
+ __asm__ __volatile__(
|
|
|
|
+ " .set mips32r2 \n"
|
|
|
|
+ " .word 0x41600be1 # emt \n"
|
|
|
|
+ " ehb \n"
|
|
|
|
+ " .set mips0 \n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void __ehb(void)
|
|
|
|
+{
|
|
|
|
+ __asm__ __volatile__(
|
|
|
|
+ " .set mips32r2 \n"
|
|
|
|
+ " ehb \n" " .set mips0 \n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
|
|
|
|
+ * not Status.IE as in non-SMTC kernel.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#define __BUILD_SET_C0(name) \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+set_c0_##name(unsigned int set) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res; \
|
|
|
|
+ unsigned int new; \
|
|
|
|
+ unsigned int omt; \
|
|
|
|
+ unsigned long flags; \
|
|
|
|
+ \
|
|
|
|
+ local_irq_save(flags); \
|
|
|
|
+ omt = __dmt(); \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res | set; \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ __emt(omt); \
|
|
|
|
+ local_irq_restore(flags); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+} \
|
|
|
|
+ \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+clear_c0_##name(unsigned int clear) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res; \
|
|
|
|
+ unsigned int new; \
|
|
|
|
+ unsigned int omt; \
|
|
|
|
+ unsigned long flags; \
|
|
|
|
+ \
|
|
|
|
+ local_irq_save(flags); \
|
|
|
|
+ omt = __dmt(); \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res & ~clear; \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ __emt(omt); \
|
|
|
|
+ local_irq_restore(flags); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+} \
|
|
|
|
+ \
|
|
|
|
+static inline unsigned int \
|
|
|
|
+change_c0_##name(unsigned int change, unsigned int newbits) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned int res; \
|
|
|
|
+ unsigned int new; \
|
|
|
|
+ unsigned int omt; \
|
|
|
|
+ unsigned long flags; \
|
|
|
|
+ \
|
|
|
|
+ local_irq_save(flags); \
|
|
|
|
+ \
|
|
|
|
+ omt = __dmt(); \
|
|
|
|
+ res = read_c0_##name(); \
|
|
|
|
+ new = res & ~change; \
|
|
|
|
+ new |= (newbits & change); \
|
|
|
|
+ write_c0_##name(new); \
|
|
|
|
+ __emt(omt); \
|
|
|
|
+ local_irq_restore(flags); \
|
|
|
|
+ \
|
|
|
|
+ return res; \
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+__BUILD_SET_C0(status)
|
|
|
|
+__BUILD_SET_C0(cause)
|
|
|
|
+__BUILD_SET_C0(config)
|
|
|
|
+__BUILD_SET_C0(intcontrol)
|
|
|
|
+__BUILD_SET_C0(intctl)
|
|
|
|
+__BUILD_SET_C0(srsmap)
|
|
|
|
+__BUILD_SET_C0(brcm_config_0)
|
|
|
|
+__BUILD_SET_C0(brcm_bus_pll)
|
|
|
|
+__BUILD_SET_C0(brcm_reset)
|
|
|
|
+__BUILD_SET_C0(brcm_cmt_intr)
|
|
|
|
+__BUILD_SET_C0(brcm_cmt_ctrl)
|
|
|
|
+__BUILD_SET_C0(brcm_config)
|
|
|
|
+__BUILD_SET_C0(brcm_mode)
|
|
|
|
+
|
|
|
|
+#endif /* !__ASSEMBLY__ */
|
|
|
|
+
|
|
|
|
+#endif /* _ASM_MIPSREGS_H */
|