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