From: SangeethaRao <sangeetha....@lsi.com>

Added calibrate_delay_is_known() such that only the first core
calculates delay calibration and rest of the cores use
the calculated value by the axxia_calibrate_delay_converge().

Set LPS_PREC - number of bits of precision for the loops_per_jiffy.
Each time we refine our estimate after the first takes 1.5/HZ seconds,
so try to start with a good estimate.
For the boot cpu we can skip the delay calibration and assign it a
value calculated based on the timer frequency.
For the rest of the CPUs we cannot assume that the timer frequency
is same as the cpu frequency, hence do the calibration for those.

Signed-off-by: SangeethaRao <sangeetha....@lsi.com>
Signed-off-by: Bruce Ashfield <bruce.ashfi...@windriver.com>
---
 arch/arm/mach-axxia/axxia.c |   85 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/arch/arm/mach-axxia/axxia.c b/arch/arm/mach-axxia/axxia.c
index 81d39d1..8872898 100644
--- a/arch/arm/mach-axxia/axxia.c
+++ b/arch/arm/mach-axxia/axxia.c
@@ -283,6 +283,91 @@ static void axxia_restart(char str, const char *cmd)
        writel(0x00080802, base + 0x31008); /* Chip Reset */
 }
 
+/*
+ * This is the number of bits of precision for the loops_per_jiffy.  Each
+ * time we refine our estimate after the first takes 1.5/HZ seconds, so try
+ * to start with a good estimate.
+ * For the boot cpu we can skip the delay calibration and assign it a value
+ * calculated based on the timer frequency.
+ * For the rest of the CPUs we cannot assume that the timer frequency is same 
as
+ * the cpu frequency, hence do the calibration for those.
+ */
+#define LPS_PREC 8
+
+static unsigned long __cpuinit axxia_calibrate_delay_converge(void)
+{
+       /* First stage - slowly accelerate to find initial bounds */
+       unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
+       int trials = 0, band = 0, trial_in_band = 0;
+
+       lpj = (1<<12);
+
+       /* wait for "start of" clock tick */
+       ticks = jiffies;
+       while (ticks == jiffies)
+               ; /* nothing */
+       /* Go .. */
+       ticks = jiffies;
+       do {
+               if (++trial_in_band == (1<<band)) {
+                       ++band;
+                       trial_in_band = 0;
+               }
+               __delay(lpj * band);
+               trials += band;
+       } while (ticks == jiffies);
+       /*
+        * We overshot, so retreat to a clear underestimate. Then estimate
+        * the largest likely undershoot. This defines our chop bounds.
+        */
+       trials -= band;
+       loopadd_base = lpj * band;
+       lpj_base = lpj * trials;
+
+recalibrate:
+       lpj = lpj_base;
+       loopadd = loopadd_base;
+
+       /*
+        * Do a binary approximation to get lpj set to
+        * equal one clock (up to LPS_PREC bits)
+        */
+       chop_limit = lpj >> LPS_PREC;
+       while (loopadd > chop_limit) {
+               lpj += loopadd;
+               ticks = jiffies;
+               while (ticks == jiffies)
+                       ; /* nothing */
+               ticks = jiffies;
+               __delay(lpj);
+               if (jiffies != ticks)   /* longer than 1 tick */
+                       lpj -= loopadd;
+               loopadd >>= 1;
+       }
+       /*
+        * If we incremented every single time possible, presume we've
+        * massively underestimated initially, and retry with a higher
+        * start, and larger range. (Only seen on x86_64, due to SMIs)
+        */
+       if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
+               lpj_base = lpj;
+               loopadd_base <<= 2;
+               goto recalibrate;
+       }
+
+       return lpj;
+}
+
+
+unsigned long calibrate_delay_is_known(void)
+{
+       static unsigned long lpj_val;
+
+       if (lpj_val == 0)
+               lpj_val = axxia_calibrate_delay_converge();
+       return lpj_val;
+}
+
 DT_MACHINE_START(AXXIA_DT, "LSI Axxia")
        .dt_compat      = axxia_dt_match,
        .map_io         = axxia_dt_map_io,
-- 
1.7.9.5

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to