MIPS: CM: Provide a function to map from CPU to VP ID.
authorPaul Burton <paul.burton@imgtec.com>
Tue, 22 Sep 2015 18:29:09 +0000 (11:29 -0700)
committerRalf Baechle <ralf@linux-mips.org>
Sun, 27 Sep 2015 12:11:17 +0000 (14:11 +0200)
The VP ID of a given CPU may not match up with the CPU number used by
Linux. For example, if the width of the VP part of the VP ID is wider
than log2(number of VPs per core) and the system has multiple cores then
this will be the case. Alternatively, if a pre-r6 system implements the
MT ASE with multiple VPEs per core and Linux is built without support
for the MT ASE then the numbers won't match up either. Provide a
function to convert from CPU number to VP ID.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Patchwork: https://patchwork.linux-mips.org/patch/11211/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/mips-cm.h

index d75b75e..1f1927a 100644 (file)
@@ -194,6 +194,7 @@ BUILD_CM_RW(reg3_mask,              MIPS_CM_GCB_OFS + 0xc8)
 BUILD_CM_R_(gic_status,                MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,                MIPS_CM_GCB_OFS + 0xf0)
 BUILD_CM_RW(l2_config,         MIPS_CM_GCB_OFS + 0x130)
+BUILD_CM_RW(sys_config2,       MIPS_CM_GCB_OFS + 0x150)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -316,6 +317,10 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_L2_CONFIG_ASSOC_SHF             0
 #define CM_GCR_L2_CONFIG_ASSOC_MSK             (_ULCAST_(0xff) << 0)
 
+/* GCR_SYS_CONFIG2 register fields */
+#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF          0
+#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK          (_ULCAST_(0xf) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF    0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK    (_ULCAST_(0xff) << 0)
@@ -405,4 +410,38 @@ static inline int mips_cm_revision(void)
        return read_gcr_rev();
 }
 
+/**
+ * mips_cm_max_vp_width() - return the width in bits of VP indices
+ *
+ * Return: the width, in bits, of VP indices in fields that combine core & VP
+ * indices.
+ */
+static inline unsigned int mips_cm_max_vp_width(void)
+{
+       extern int smp_num_siblings;
+
+       if (mips_cm_revision() >= CM_REV_CM3)
+               return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
+
+       return smp_num_siblings;
+}
+
+/**
+ * mips_cm_vp_id() - calculate the hardware VP ID for a CPU
+ * @cpu: the CPU whose VP ID to calculate
+ *
+ * Hardware such as the GIC uses identifiers for VPs which may not match the
+ * CPU numbers used by Linux. This function calculates the hardware VP
+ * identifier corresponding to a given CPU.
+ *
+ * Return: the VP ID for the CPU.
+ */
+static inline unsigned int mips_cm_vp_id(unsigned int cpu)
+{
+       unsigned int core = cpu_data[cpu].core;
+       unsigned int vp = cpu_vpe_id(&cpu_data[cpu]);
+
+       return (core * mips_cm_max_vp_width()) + vp;
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */