+static inline unsigned int mfspr(unsigned int reg)
+{
+ unsigned int val;
+
+ asm volatile("mfspr %0,%1": "=r" (val) : "K" (reg));
+ return val;
+}
+
+#define SPRN_TBRL 0x10C /* Time Base Register Lower */
+#define SPRN_TBRU 0x10D /* Time Base Register Upper */
+#define SPRN_ATBL 0x20E /* Alternate Time Base Lower */
+#define SPRN_ATBU 0x20F /* Alternate Time Base Upper */
+
+#ifdef __powerpc64__
+static inline unsigned long long get_cpu_clock(void)
+{
+ unsigned long long rval;
+
+ asm volatile(
+ "90: mfspr %0, %1;\n"
+ " cmpwi %0,0;\n"
+ " beq- 90b;\n"
+ : "=r" (rval)
+ : "i" (SPRN_TBRL));
+
+ return rval;
+}
+#else
+static inline unsigned long long get_cpu_clock(void)
+{
+ unsigned int tbl, tbu0, tbu1;
+ unsigned long long ret;
+
+ do {
+ if (arch_flags & ARCH_FLAG_1) {
+ tbu0 = mfspr(SPRN_ATBU);
+ tbl = mfspr(SPRN_ATBL);
+ tbu1 = mfspr(SPRN_ATBU);
+ } else {
+ tbu0 = mfspr(SPRN_TBRU);
+ tbl = mfspr(SPRN_TBRL);
+ tbu1 = mfspr(SPRN_TBRU);
+ }
+ } while (tbu0 != tbu1);
+
+ ret = (((unsigned long long)tbu0) << 32) | tbl;
+ return ret;
+}
+#endif