From: Varshini Rajendran <varshini.rajend...@microchip.com>

Add support for hardware dividers for PLL IDs.In sam9x7 SoC,
PLL_ID_PLLA and PLL_ID_PLLA_DIV2 has /2 hardware dividers
each.

fcorepllack -----> HW Div = 2 -+--> fpllack
                               |
                               +--> HW Div = 2 ---> fplladiv2ck

Signed-off-by: Varshini Rajendran <varshini.rajend...@microchip.com>
---
 drivers/clk/at91/clk-sam9x60-pll.c | 38 +++++++++++++++++++++++++++++-
 drivers/clk/at91/pmc.h             |  1 +
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/at91/clk-sam9x60-pll.c 
b/drivers/clk/at91/clk-sam9x60-pll.c
index 676ad8294a6..df8172bccac 100644
--- a/drivers/clk/at91/clk-sam9x60-pll.c
+++ b/drivers/clk/at91/clk-sam9x60-pll.c
@@ -22,6 +22,7 @@
 
 #define UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL      "at91-sam9x60-div-pll-clk"
 #define UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL     "at91-sam9x60-frac-pll-clk"
+#define UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL        
"at91-sam9x60-fixed-div-pll-clk"
 
 #define        PMC_PLL_CTRL0_DIV_MSK   GENMASK(7, 0)
 #define        PMC_PLL_CTRL1_MUL_MSK   GENMASK(31, 24)
@@ -140,6 +141,7 @@ static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
        void __iomem *base = pll->base;
        ulong parent_rate = clk_get_parent_rate(clk);
        u32 mul, frac, val;
+       ulong pll_rate;
 
        if (!parent_rate)
                return 0;
@@ -149,8 +151,12 @@ static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
        pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
        mul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
        frac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
+       pll_rate = (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
 
-       return (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
+       if (pll->layout->div2)
+               pll_rate >>= 1;
+
+       return pll_rate;
 }
 
 static int sam9x60_frac_pll_enable(struct clk *clk)
@@ -359,6 +365,16 @@ static ulong sam9x60_div_pll_get_rate(struct clk *clk)
        return parent_rate / (div + 1);
 }
 
+static ulong sam9x60_fixed_div_pll_get_rate(struct clk *clk)
+{
+       ulong parent_rate = clk_get_parent_rate(clk);
+
+       if (!parent_rate)
+               return 0;
+
+       return parent_rate >> 1;
+}
+
 static const struct clk_ops sam9x60_div_pll_ops = {
        .enable = sam9x60_div_pll_enable,
        .disable = sam9x60_div_pll_disable,
@@ -366,6 +382,12 @@ static const struct clk_ops sam9x60_div_pll_ops = {
        .get_rate = sam9x60_div_pll_get_rate,
 };
 
+static const struct clk_ops sam9x60_fixed_div_pll_ops = {
+       .enable = sam9x60_div_pll_enable,
+       .disable = sam9x60_div_pll_disable,
+       .get_rate = sam9x60_fixed_div_pll_get_rate,
+};
+
 static struct clk *
 sam9x60_clk_register_pll(void __iomem *base, const char *type,
                         const char *name, const char *parent_name, u8 id,
@@ -406,6 +428,13 @@ sam9x60_clk_register_div_pll(void __iomem *base, const 
char *name,
                             const struct clk_pll_characteristics 
*characteristics,
                             const struct clk_pll_layout *layout, bool critical)
 {
+       if (layout->div2) {
+               return sam9x60_clk_register_pll(base,
+                       UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL, name, 
parent_name,
+                       id, characteristics, layout,
+                       CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 
0));
+       }
+
        return sam9x60_clk_register_pll(base,
                UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL, name, parent_name, id,
                characteristics, layout,
@@ -431,6 +460,13 @@ U_BOOT_DRIVER(at91_sam9x60_div_pll_clk) = {
        .flags = DM_FLAG_PRE_RELOC,
 };
 
+U_BOOT_DRIVER(at91_sam9x60_fixed_div_pll_clk) = {
+       .name = UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL,
+       .id = UCLASS_CLK,
+       .ops = &sam9x60_fixed_div_pll_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
+
 U_BOOT_DRIVER(at91_sam9x60_frac_pll_clk) = {
        .name = UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL,
        .id = UCLASS_CLK,
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 49134531564..580c9964ff4 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -54,6 +54,7 @@ struct clk_pll_layout {
        u8 frac_shift;
        u8 div_shift;
        u8 endiv_shift;
+       u8 div2;
 };
 
 struct clk_programmable_layout {
-- 
2.25.1

Reply via email to