1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/bits.h> 3 #include <linux/clk-provider.h> 4 #include <linux/io.h> 5 #include <linux/slab.h> 6 #include <linux/kernel.h> 7 #include <linux/err.h> 8 9 #include "clk.h" 10 11 /** 12 * pll v1 13 * 14 * @clk_hw clock source 15 * @parent the parent clock name 16 * @base base address of pll registers 17 * 18 * PLL clock version 1, found on i.MX1/21/25/27/31/35 19 */ 20 21 #define MFN_BITS (10) 22 #define MFN_SIGN (BIT(MFN_BITS - 1)) 23 #define MFN_MASK (MFN_SIGN - 1) 24 25 struct clk_pllv1 { 26 struct clk_hw hw; 27 void __iomem *base; 28 enum imx_pllv1_type type; 29 }; 30 31 #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk)) 32 33 static inline bool is_imx1_pllv1(struct clk_pllv1 *pll) 34 { 35 return pll->type == IMX_PLLV1_IMX1; 36 } 37 38 static inline bool is_imx21_pllv1(struct clk_pllv1 *pll) 39 { 40 return pll->type == IMX_PLLV1_IMX21; 41 } 42 43 static inline bool is_imx27_pllv1(struct clk_pllv1 *pll) 44 { 45 return pll->type == IMX_PLLV1_IMX27; 46 } 47 48 static inline bool mfn_is_negative(struct clk_pllv1 *pll, unsigned int mfn) 49 { 50 return !is_imx1_pllv1(pll) && !is_imx21_pllv1(pll) && (mfn & MFN_SIGN); 51 } 52 53 static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, 54 unsigned long parent_rate) 55 { 56 struct clk_pllv1 *pll = to_clk_pllv1(hw); 57 unsigned long long ull; 58 int mfn_abs; 59 unsigned int mfi, mfn, mfd, pd; 60 u32 reg; 61 unsigned long rate; 62 63 reg = readl(pll->base); 64 65 /* 66 * Get the resulting clock rate from a PLL register value and the input 67 * frequency. PLLs with this register layout can be found on i.MX1, 68 * i.MX21, i.MX27 and i,MX31 69 * 70 * mfi + mfn / (mfd + 1) 71 * f = 2 * f_ref * -------------------- 72 * pd + 1 73 */ 74 75 mfi = (reg >> 10) & 0xf; 76 mfn = reg & 0x3ff; 77 mfd = (reg >> 16) & 0x3ff; 78 pd = (reg >> 26) & 0xf; 79 80 mfi = mfi <= 5 ? 5 : mfi; 81 82 mfn_abs = mfn; 83 84 /* 85 * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit 86 * 2's complements number. 87 * On i.MX27 the bit 9 is the sign bit. 88 */ 89 if (mfn_is_negative(pll, mfn)) { 90 if (is_imx27_pllv1(pll)) 91 mfn_abs = mfn & MFN_MASK; 92 else 93 mfn_abs = BIT(MFN_BITS) - mfn; 94 } 95 96 rate = parent_rate * 2; 97 rate /= pd + 1; 98 99 ull = (unsigned long long)rate * mfn_abs; 100 101 do_div(ull, mfd + 1); 102 103 if (mfn_is_negative(pll, mfn)) 104 ull = (rate * mfi) - ull; 105 else 106 ull = (rate * mfi) + ull; 107 108 return ull; 109 } 110 111 static const struct clk_ops clk_pllv1_ops = { 112 .recalc_rate = clk_pllv1_recalc_rate, 113 }; 114 115 struct clk_hw *imx_clk_hw_pllv1(enum imx_pllv1_type type, const char *name, 116 const char *parent, void __iomem *base) 117 { 118 struct clk_pllv1 *pll; 119 struct clk_hw *hw; 120 struct clk_init_data init; 121 int ret; 122 123 pll = kmalloc(sizeof(*pll), GFP_KERNEL); 124 if (!pll) 125 return ERR_PTR(-ENOMEM); 126 127 pll->base = base; 128 pll->type = type; 129 130 init.name = name; 131 init.ops = &clk_pllv1_ops; 132 init.flags = 0; 133 init.parent_names = &parent; 134 init.num_parents = 1; 135 136 pll->hw.init = &init; 137 hw = &pll->hw; 138 139 ret = clk_hw_register(NULL, hw); 140 if (ret) { 141 kfree(pll); 142 return ERR_PTR(ret); 143 } 144 145 return hw; 146 } 147