]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arm/cpu/armv7/am33xx/clock_am33xx.c
arm, am335x: Enable Spread Spectrum for the MPU
[people/ms/u-boot.git] / arch / arm / cpu / armv7 / am33xx / clock_am33xx.c
index 92142c893444bc63ad7e1b811172c5996d6005a0..7b841b2d556da3492cfc1ce58e19149cbb237f1c 100644 (file)
@@ -159,3 +159,76 @@ void enable_basic_clocks(void)
        /* Select the Master osc 24 MHZ as Timer2 clock source */
        writel(0x1, &cmdpll->clktimer2clk);
 }
+
+/*
+ * Enable Spread Spectrum for the MPU by calculating the required
+ * values and setting the registers accordingly.
+ * @param permille The spreading in permille (10th of a percent)
+ */
+void set_mpu_spreadspectrum(int permille)
+{
+       u32 multiplier_m;
+       u32 predivider_n;
+       u32 cm_clksel_dpll_mpu;
+       u32 cm_clkmode_dpll_mpu;
+       u32 ref_clock;
+       u32 pll_bandwidth;
+       u32 mod_freq_divider;
+       u32 exponent;
+       u32 mantissa;
+       u32 delta_m_step;
+
+       printf("Enabling Spread Spectrum of %d permille for MPU\n",
+              permille);
+
+       /* Read PLL parameter m and n */
+       cm_clksel_dpll_mpu = readl(&cmwkup->clkseldpllmpu);
+       multiplier_m = (cm_clksel_dpll_mpu >> 8) & 0x3FF;
+       predivider_n = cm_clksel_dpll_mpu & 0x7F;
+
+       /*
+        * Calculate reference clock (clock after pre-divider),
+        * its max. PLL bandwidth,
+        * and resulting mod_freq_divider
+        */
+       ref_clock = V_OSCK / (predivider_n + 1);
+       pll_bandwidth = ref_clock / 70;
+       mod_freq_divider = ref_clock / (4 * pll_bandwidth);
+
+       /* Calculate Mantissa/Exponent */
+       exponent = 0;
+       mantissa = mod_freq_divider;
+       while ((mantissa > 127) && (exponent < 7)) {
+               exponent++;
+               mantissa /= 2;
+       }
+       if (mantissa > 127)
+               mantissa = 127;
+
+       mod_freq_divider = mantissa << exponent;
+
+       /*
+        * Calculate Modulation steps
+        * As we use Downspread only, the spread is twice the value of
+        * permille, so Div2!
+        * As it takes the value in percent, divide by ten!
+        */
+       delta_m_step = ((u32)((multiplier_m * permille) / 10 / 2)) << 18;
+       delta_m_step /= 100;
+       delta_m_step /= mod_freq_divider;
+       if (delta_m_step > 0xFFFFF)
+               delta_m_step = 0xFFFFF;
+
+       /* Setup Spread Spectrum */
+       writel(delta_m_step, &cmwkup->sscdeltamstepdllmpu);
+       writel((exponent << 8) | mantissa, &cmwkup->sscmodfreqdivdpllmpu);
+       cm_clkmode_dpll_mpu = readl(&cmwkup->clkmoddpllmpu);
+       /* clear all SSC flags */
+       cm_clkmode_dpll_mpu &= ~(0xF << CM_CLKMODE_DPLL_SSC_EN_SHIFT);
+       /* enable SSC with Downspread only */
+       cm_clkmode_dpll_mpu |=  CM_CLKMODE_DPLL_SSC_EN_MASK |
+                               CM_CLKMODE_DPLL_SSC_DOWNSPREAD_MASK;
+       writel(cm_clkmode_dpll_mpu, &cmwkup->clkmoddpllmpu);
+       while (!(readl(&cmwkup->clkmoddpllmpu) & 0x2000))
+               ;
+}