root/drivers/clk/socfpga/clk-pll-s10.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clk_pll_recalc_rate
  2. clk_boot_clk_recalc_rate
  3. clk_pll_get_parent
  4. clk_boot_get_parent
  5. clk_pll_prepare
  6. s10_register_pll

   1 // SPDX-License-Identifier:     GPL-2.0
   2 /*
   3  * Copyright (C) 2017, Intel Corporation
   4  */
   5 #include <linux/slab.h>
   6 #include <linux/clk-provider.h>
   7 #include <linux/io.h>
   8 
   9 #include "stratix10-clk.h"
  10 #include "clk.h"
  11 
  12 /* Clock Manager offsets */
  13 #define CLK_MGR_PLL_CLK_SRC_SHIFT       16
  14 #define CLK_MGR_PLL_CLK_SRC_MASK        0x3
  15 
  16 /* PLL Clock enable bits */
  17 #define SOCFPGA_PLL_POWER               0
  18 #define SOCFPGA_PLL_RESET_MASK          0x2
  19 #define SOCFPGA_PLL_REFDIV_MASK         0x00003F00
  20 #define SOCFPGA_PLL_REFDIV_SHIFT        8
  21 #define SOCFPGA_PLL_MDIV_MASK           0xFF000000
  22 #define SOCFPGA_PLL_MDIV_SHIFT          24
  23 #define SWCTRLBTCLKSEL_MASK             0x200
  24 #define SWCTRLBTCLKSEL_SHIFT            9
  25 
  26 #define SOCFPGA_BOOT_CLK                "boot_clk"
  27 
  28 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
  29 
  30 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
  31                                          unsigned long parent_rate)
  32 {
  33         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
  34         unsigned long mdiv;
  35         unsigned long refdiv;
  36         unsigned long reg;
  37         unsigned long long vco_freq;
  38 
  39         /* read VCO1 reg for numerator and denominator */
  40         reg = readl(socfpgaclk->hw.reg);
  41         refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
  42         vco_freq = (unsigned long long)parent_rate / refdiv;
  43 
  44         /* Read mdiv and fdiv from the fdbck register */
  45         reg = readl(socfpgaclk->hw.reg + 0x4);
  46         mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
  47         vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
  48 
  49         return (unsigned long)vco_freq;
  50 }
  51 
  52 static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
  53                                          unsigned long parent_rate)
  54 {
  55         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
  56         u32 div = 1;
  57 
  58         div = ((readl(socfpgaclk->hw.reg) &
  59                 SWCTRLBTCLKSEL_MASK) >>
  60                 SWCTRLBTCLKSEL_SHIFT);
  61         div += 1;
  62         return parent_rate /= div;
  63 }
  64 
  65 
  66 static u8 clk_pll_get_parent(struct clk_hw *hwclk)
  67 {
  68         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
  69         u32 pll_src;
  70 
  71         pll_src = readl(socfpgaclk->hw.reg);
  72         return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
  73                 CLK_MGR_PLL_CLK_SRC_MASK;
  74 }
  75 
  76 static u8 clk_boot_get_parent(struct clk_hw *hwclk)
  77 {
  78         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
  79         u32 pll_src;
  80 
  81         pll_src = readl(socfpgaclk->hw.reg);
  82         return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
  83                 SWCTRLBTCLKSEL_MASK;
  84 }
  85 
  86 static int clk_pll_prepare(struct clk_hw *hwclk)
  87 {
  88         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
  89         u32 reg;
  90 
  91         /* Bring PLL out of reset */
  92         reg = readl(socfpgaclk->hw.reg);
  93         reg |= SOCFPGA_PLL_RESET_MASK;
  94         writel(reg, socfpgaclk->hw.reg);
  95 
  96         return 0;
  97 }
  98 
  99 static struct clk_ops clk_pll_ops = {
 100         .recalc_rate = clk_pll_recalc_rate,
 101         .get_parent = clk_pll_get_parent,
 102         .prepare = clk_pll_prepare,
 103 };
 104 
 105 static struct clk_ops clk_boot_ops = {
 106         .recalc_rate = clk_boot_clk_recalc_rate,
 107         .get_parent = clk_boot_get_parent,
 108         .prepare = clk_pll_prepare,
 109 };
 110 
 111 struct clk *s10_register_pll(const char *name, const char * const *parent_names,
 112                                     u8 num_parents, unsigned long flags,
 113                                     void __iomem *reg, unsigned long offset)
 114 {
 115         struct clk *clk;
 116         struct socfpga_pll *pll_clk;
 117         struct clk_init_data init;
 118 
 119         pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
 120         if (WARN_ON(!pll_clk))
 121                 return NULL;
 122 
 123         pll_clk->hw.reg = reg + offset;
 124 
 125         if (streq(name, SOCFPGA_BOOT_CLK))
 126                 init.ops = &clk_boot_ops;
 127         else
 128                 init.ops = &clk_pll_ops;
 129 
 130         init.name = name;
 131         init.flags = flags;
 132 
 133         init.num_parents = num_parents;
 134         init.parent_names = parent_names;
 135         pll_clk->hw.hw.init = &init;
 136 
 137         pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
 138         clk_pll_ops.enable = clk_gate_ops.enable;
 139         clk_pll_ops.disable = clk_gate_ops.disable;
 140 
 141         clk = clk_register(NULL, &pll_clk->hw.hw);
 142         if (WARN_ON(IS_ERR(clk))) {
 143                 kfree(pll_clk);
 144                 return NULL;
 145         }
 146         return clk;
 147 }

/* [<][>][^][v][top][bottom][index][help] */