Detect the MIPS R2 vectored interrupt, external interrupt controller
options and the precense of the MT ASE.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 53e4496..844126b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -501,6 +501,12 @@
 		c->ases |= MIPS_ASE_SMARTMIPS;
 	if (config3 & MIPS_CONF3_DSP)
 		c->ases |= MIPS_ASE_DSP;
+	if (config3 & MIPS_CONF3_VINT)
+		c->options |= MIPS_CPU_VINT;
+	if (config3 & MIPS_CONF3_VEIC)
+		c->options |= MIPS_CPU_VEIC;
+	if (config3 & MIPS_CONF3_MT)
+                c->ases |= MIPS_ASE_MIPSMT;
 
 	return config3 & MIPS_CONF_M;
 }
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index bb2212c..698c2112 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -109,6 +109,14 @@
 #define cpu_has_dsp		(cpu_data[0].ases & MIPS_ASE_DSP)
 #endif
 
+#ifdef CONFIG_MIPS_MT
+#ifndef cpu_has_mipsmt
+# define cpu_has_mipsmt		(cpu_data[0].ases & MIPS_ASE_MIPSMT)
+#endif
+#else
+# define cpu_has_mipsmt		0
+#endif
+
 #ifdef CONFIG_32BIT
 # ifndef cpu_has_nofpuex
 # define cpu_has_nofpuex	(cpu_data[0].options & MIPS_CPU_NOFPUEX)
@@ -145,6 +153,22 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_MIPSR2
+# if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint)
+#  define cpu_has_vint		(cpu_data[0].options & MIPS_CPU_VINT)
+# else
+#  define cpu_has_vint			0
+# endif
+# if defined(CONFIG_CPU_MIPSR2_IRQ_EI) && !defined(cpu_has_veic)
+#  define cpu_has_veic		(cpu_data[0].options & MIPS_CPU_VEIC)
+# else
+#  define cpu_has_veic			0
+# endif
+#else
+# define cpu_has_vint			0
+# define cpu_has_veic			0
+#endif
+
 #ifndef cpu_has_subset_pcaches
 #define cpu_has_subset_pcaches	(cpu_data[0].options & MIPS_CPU_SUBSET_CACHES)
 #endif
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index e692744..3bbb643 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -227,6 +227,8 @@
 #define MIPS_CPU_LLSC		0x00010000 /* CPU has ll/sc instructions */
 #define MIPS_CPU_SUBSET_CACHES	0x00020000 /* P-cache subset enforced */
 #define MIPS_CPU_PREFETCH	0x00040000 /* CPU has usable prefetch */
+#define MIPS_CPU_VINT		0x00080000 /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC		0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */
 
 /*
  * CPU ASE encodings
@@ -236,5 +238,7 @@
 #define MIPS_ASE_MIPS3D		0x00000004 /* MIPS-3D */
 #define MIPS_ASE_SMARTMIPS	0x00000008 /* SmartMIPS */
 #define MIPS_ASE_DSP		0x00000010 /* Signal Processing ASE */
+#define MIPS_ASE_MIPSMT		0x00000020 /* CPU supports MIPS MT */
+
 
 #endif /* _ASM_CPU_H */
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
index 9aaefc1..eda24c2 100644
--- a/include/asm-mips/mipsmtregs.h
+++ b/include/asm-mips/mipsmtregs.h
@@ -175,8 +175,8 @@
 	"	.set	noreorder					\n"
 	"	.set	noat						\n"
 	"	.set	mips32r2					\n"
-	"	move	$1, %0						\n"
 	"	.word	0x41610001		# dvpe $1		\n"
+	"	move	%0, $1						\n"
 	"	ehb							\n"
 	"	.set	pop						\n"
 	: "=r" (res));
@@ -214,12 +214,13 @@
 	int res;
 
 	__asm__ __volatile__(
-	"	.set	noreorder					\n"
+	"	.set	push						\n"
 	"	.set	mips32r2					\n"
-	"	dmt	%0						\n"
+	"	.set	noat						\n"
+	"	.word	0x41610BC1			# dmt $1	\n"
 	"	ehb							\n"
-	"	.set mips0						\n"
-	"	.set reorder						\n"
+	"	move	%0, $1						\n"
+	"	.set	pop						\n"
 	: "=r" (res));
 
 	instruction_hazard();
@@ -251,7 +252,10 @@
 
 static inline void ehb(void)
 {
-	__asm__ __volatile__("ehb");
+	__asm__ __volatile__(
+	"	.set	mips32r2				\n"
+	"	ehb						\n"
+	"	.set	mips0					\n");
 }
 
 #define mftc0(rt,sel)							\
@@ -259,10 +263,14 @@
 	 unsigned long  __res;						\
 									\
 	__asm__ __volatile__(						\
-	 "	.set noat\n\t"						\
-	 "	mftc0\t%0," #rt ", " #sel "\n\t"			\
-	 "	.set at\n\t"						\
-	 : "=r" (__res));						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	# mftc0	$1, $" #rt ", " #sel "			\n"	\
+	"	.word	0x41000800 | (" #rt " << 16) | " #sel "	\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
 									\
 	__res;								\
 })
@@ -272,9 +280,10 @@
 	unsigned long __res;						\
 									\
 	__asm__ __volatile__(						\
-	"	.set	noat					\n"	\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
 	"	mftgpr	%0," #rt "				\n"	\
-	"	.set	at					\n"	\
+	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 									\
 	__res;								\
@@ -294,17 +303,30 @@
 })
 
 #define mttgpr(rd,v)							\
-({									\
+do {									\
 	__asm__ __volatile__(						\
-	"mttgpr	%0," #rd						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttgpr $1, " #rd "				\n"	\
+	"	.word	0x41810020 | (" #rd " << 11)		\n"	\
+	"	.set	pop					\n"	\
 	: : "r" (v));							\
-})
+} while (0)
 
 #define mttc0(rd,sel,v)							\
 ({									\
 	__asm__ __volatile__(						\
-	"mttc0\t %0," #rd ", " #sel					\
-	: : "r" (v));							\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttc0 %0," #rd ", " #sel "			\n"	\
+	"	.word	0x41810000 | (" #rd " << 11) | " #sel "	\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (v));							\
 })
 
 
@@ -324,42 +346,42 @@
 
 
 /* you *must* set the target tc (settc) before trying to use these */
-#define read_vpe_c0_vpecontrol()	mftc0($1, 1)
-#define write_vpe_c0_vpecontrol(val)	mttc0($1, 1, val)
-#define read_vpe_c0_vpeconf0()		mftc0($1, 2)
-#define write_vpe_c0_vpeconf0(val)	mttc0($1, 2, val)
-#define read_vpe_c0_status()		mftc0($12, 0)
-#define write_vpe_c0_status(val)	mttc0($12, 0, val)
-#define read_vpe_c0_cause()		mftc0($13, 0)
-#define write_vpe_c0_cause(val)		mttc0($13, 0, val)
-#define read_vpe_c0_config()		mftc0($16, 0)
-#define write_vpe_c0_config(val)	mttc0($16, 0, val)
-#define read_vpe_c0_config1()		mftc0($16, 1)
-#define write_vpe_c0_config1(val)	mttc0($16, 1, val)
-#define read_vpe_c0_config7()		mftc0($16, 7)
-#define write_vpe_c0_config7(val)	mttc0($16, 7, val)
-#define read_vpe_c0_ebase()		mftc0($15,1)
-#define write_vpe_c0_ebase(val)		mttc0($15, 1, val)
-#define write_vpe_c0_compare(val)	mttc0($11, 0, val)
+#define read_vpe_c0_vpecontrol()	mftc0(1, 1)
+#define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
+#define read_vpe_c0_vpeconf0()		mftc0(1, 2)
+#define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
+#define read_vpe_c0_status()		mftc0(12, 0)
+#define write_vpe_c0_status(val)	mttc0(12, 0, val)
+#define read_vpe_c0_cause()		mftc0(13, 0)
+#define write_vpe_c0_cause(val)		mttc0(13, 0, val)
+#define read_vpe_c0_config()		mftc0(16, 0)
+#define write_vpe_c0_config(val)	mttc0(16, 0, val)
+#define read_vpe_c0_config1()		mftc0(16, 1)
+#define write_vpe_c0_config1(val)	mttc0(16, 1, val)
+#define read_vpe_c0_config7()		mftc0(16, 7)
+#define write_vpe_c0_config7(val)	mttc0(16, 7, val)
+#define read_vpe_c0_ebase()		mftc0(15,1)
+#define write_vpe_c0_ebase(val)		mttc0(15, 1, val)
+#define write_vpe_c0_compare(val)	mttc0(11, 0, val)
 
 
 /* TC */
-#define read_tc_c0_tcstatus()		mftc0($2, 1)
-#define write_tc_c0_tcstatus(val)	mttc0($2,1,val)
-#define read_tc_c0_tcbind()		mftc0($2, 2)
-#define write_tc_c0_tcbind(val)		mttc0($2,2,val)
-#define read_tc_c0_tcrestart()		mftc0($2, 3)
-#define write_tc_c0_tcrestart(val)	mttc0($2,3,val)
-#define read_tc_c0_tchalt()		mftc0($2, 4)
-#define write_tc_c0_tchalt(val)		mttc0($2,4,val)
-#define read_tc_c0_tccontext()		mftc0($2, 5)
-#define write_tc_c0_tccontext(val)	mttc0($2,5,val)
+#define read_tc_c0_tcstatus()		mftc0(2, 1)
+#define write_tc_c0_tcstatus(val)	mttc0(2,1,val)
+#define read_tc_c0_tcbind()		mftc0(2, 2)
+#define write_tc_c0_tcbind(val)		mttc0(2,2,val)
+#define read_tc_c0_tcrestart()		mftc0(2, 3)
+#define write_tc_c0_tcrestart(val)	mttc0(2,3,val)
+#define read_tc_c0_tchalt()		mftc0(2, 4)
+#define write_tc_c0_tchalt(val)		mttc0(2,4,val)
+#define read_tc_c0_tccontext()		mftc0(2, 5)
+#define write_tc_c0_tccontext(val)	mttc0(2,5,val)
 
 /* GPR */
-#define read_tc_gpr_sp()		mftgpr($29)
-#define write_tc_gpr_sp(val)		mttgpr($29, val)
-#define read_tc_gpr_gp()		mftgpr($28)
-#define write_tc_gpr_gp(val)		mttgpr($28, val)
+#define read_tc_gpr_sp()		mftgpr(29)
+#define write_tc_gpr_sp(val)		mttgpr(29, val)
+#define read_tc_gpr_gp()		mftgpr(28)
+#define write_tc_gpr_gp(val)		mttgpr(28, val)
 
 
 #endif /* Not __ASSEMBLY__ */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 89aac1e..a7a43ff 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -528,6 +528,7 @@
 
 #define MIPS_CONF3_TL		(_ULCAST_(1) <<  0)
 #define MIPS_CONF3_SM		(_ULCAST_(1) <<  1)
+#define MIPS_CONF3_MT		(_ULCAST_(1) <<  2)
 #define MIPS_CONF3_SP		(_ULCAST_(1) <<  4)
 #define MIPS_CONF3_VINT		(_ULCAST_(1) <<  5)
 #define MIPS_CONF3_VEIC		(_ULCAST_(1) <<  6)