MIPS: mips-cm: Extend CM accessors for 64-bit CPUs
authorMarkos Chandras <markos.chandras@imgtec.com>
Tue, 14 Jul 2015 08:14:12 +0000 (09:14 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 26 Aug 2015 13:23:12 +0000 (15:23 +0200)
Previously, the CM accessors were only accessing CM registers as u32
types instead of using the native CM register with. However, newer CMs
may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
(CM3) hold all the useful configuration bits in the lower half of the
64-bit registers (at least most of them) so they can still be accessed
using the current 32-bit accessors.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/10707/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/mips-cm.h
arch/mips/kernel/mips-cm.c

index ca3f2c963fbd5200b26a111f08e3ebfcea1f4c5b..46cc0c69b77c006c4e94b2ee6017939398d36f59 100644 (file)
@@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)                                 \
-static inline u32 __iomem *addr_gcr_##name(void)               \
+static inline unsigned long __iomem *addr_gcr_##name(void)     \
 {                                                              \
-       return (u32 __iomem *)(mips_cm_base + (off));           \
+       return (unsigned long __iomem *)(mips_cm_base + (off)); \
 }                                                              \
                                                                \
-static inline u32 read_gcr_##name(void)                                \
+static inline u32 read32_gcr_##name(void)                      \
 {                                                              \
        return __raw_readl(addr_gcr_##name());                  \
+}                                                              \
+                                                               \
+static inline u64 read64_gcr_##name(void)                      \
+{                                                              \
+       return __raw_readq(addr_gcr_##name());                  \
+}                                                              \
+                                                               \
+static inline unsigned long read_gcr_##name(void)              \
+{                                                              \
+       if (mips_cm_is64)                                       \
+               return read64_gcr_##name();                     \
+       else                                                    \
+               return read32_gcr_##name();                     \
 }
 
 #define BUILD_CM__W(name, off)                                 \
-static inline void write_gcr_##name(u32 value)                 \
+static inline void write32_gcr_##name(u32 value)               \
 {                                                              \
        __raw_writel(value, addr_gcr_##name());                 \
+}                                                              \
+                                                               \
+static inline void write64_gcr_##name(u64 value)               \
+{                                                              \
+       __raw_writeq(value, addr_gcr_##name());                 \
+}                                                              \
+                                                               \
+static inline void write_gcr_##name(unsigned long value)       \
+{                                                              \
+       if (mips_cm_is64)                                       \
+               write64_gcr_##name(value);                      \
+       else                                                    \
+               write32_gcr_##name(value);                      \
 }
 
 #define BUILD_CM_RW(name, off)                                 \
index 42602f30949fe6428c643e18c8fd688c8132808d..3d2cb6f47898136672bf52f269cb56e8d858d0be 100644 (file)
@@ -15,6 +15,7 @@
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
 
 phys_addr_t __mips_cm_phys_base(void)
 {
@@ -124,5 +125,8 @@ int mips_cm_probe(void)
        /* probe for an L2-only sync region */
        mips_cm_probe_l2sync();
 
+       /* determine register width for this CM */
+       mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+
        return 0;
 }