^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "clk-regmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define PLLCON_OFFSET(x) (x * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PLL_BYPASS(x) HIWORD_UPDATE(x, 15, 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define PLL_BYPASS_MASK BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define PLL_BYPASS_SHIFT 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PLL_POSTDIV1(x) HIWORD_UPDATE(x, 14, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PLL_POSTDIV1_MASK GENMASK(14, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PLL_POSTDIV1_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PLL_FBDIV(x) HIWORD_UPDATE(x, 11, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PLL_FBDIV_MASK GENMASK(11, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PLL_FBDIV_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PLL_POSTDIV2(x) HIWORD_UPDATE(x, 8, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PLL_POSTDIV2_MASK GENMASK(8, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PLL_POSTDIV2_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PLL_REFDIV(x) HIWORD_UPDATE(x, 5, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PLL_REFDIV_MASK GENMASK(5, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PLL_REFDIV_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PLL_FOUT_4PHASE_CLK_POWER_DOWN BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PLL_FOUT_VCO_CLK_POWER_DOWN BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PLL_FOUT_POST_DIV_POWER_DOWN BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define PLL_DAC_POWER_DOWN BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define PLL_FRAC(x) UPDATE(x, 23, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define PLL_FRAC_MASK GENMASK(23, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define PLL_FRAC_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MIN_FREF_RATE 10000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MAX_FREF_RATE 800000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MIN_FREFDIV_RATE 1000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MAX_FREFDIV_RATE 40000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MIN_FVCO_RATE 400000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MAX_FVCO_RATE 1600000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MIN_FOUTPOSTDIV_RATE 8000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MAX_FOUTPOSTDIV_RATE 1600000000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct clk_regmap_pll {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 pd_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 dsmpd_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 lock_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define to_clk_regmap_pll(_hw) container_of(_hw, struct clk_regmap_pll, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) clk_regmap_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned int postdiv1, fbdiv, dsmpd, postdiv2, refdiv, frac, bypass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int con0, con1, con2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u64 foutvco, foutpostdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) regmap_read(pll->regmap, pll->reg + PLLCON_OFFSET(0), &con0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) regmap_read(pll->regmap, pll->reg + PLLCON_OFFSET(1), &con1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) regmap_read(pll->regmap, pll->reg + PLLCON_OFFSET(2), &con2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bypass = (con0 & PLL_BYPASS_MASK) >> PLL_BYPASS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) postdiv1 = (con0 & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fbdiv = (con0 & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dsmpd = (con1 & BIT(pll->dsmpd_shift)) >> pll->dsmpd_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) postdiv2 = (con1 & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) refdiv = (con1 & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) frac = (con2 & PLL_FRAC_MASK) >> PLL_FRAC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return prate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) foutvco = prate * fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) do_div(foutvco, refdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!dsmpd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u64 frac_rate = (u64)prate * frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) do_div(frac_rate, refdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) foutvco += frac_rate >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) foutpostdiv = foutvco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) do_div(foutpostdiv, postdiv1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) do_div(foutpostdiv, postdiv2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return foutpostdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static long clk_pll_round_rate(unsigned long fin, unsigned long fout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 *refdiv, u16 *fbdiv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u8 *postdiv1, u8 *postdiv2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 *frac, u8 *dsmpd, u8 *bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u8 min_refdiv, max_refdiv, postdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u8 _dsmpd = 1, _postdiv1 = 0, _postdiv2 = 0, _refdiv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u16 _fbdiv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 _frac = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u64 foutvco, foutpostdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * FREF : 10MHz ~ 800MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * FREFDIV : 1MHz ~ 40MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * FOUTVCO : 400MHz ~ 1.6GHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * FOUTPOSTDIV : 8MHz ~ 1.6GHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (fin < MIN_FREF_RATE || fin > MAX_FREF_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (fout < MIN_FOUTPOSTDIV_RATE || fout > MAX_FOUTPOSTDIV_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (fin == fout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *bypass = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return fin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) min_refdiv = DIV_ROUND_UP(fin, MAX_FREFDIV_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) max_refdiv = fin / MIN_FREFDIV_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (max_refdiv > 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) max_refdiv = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (fout < MIN_FVCO_RATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) postdiv = DIV_ROUND_UP_ULL(MIN_FVCO_RATE, fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) for (_postdiv2 = 1; _postdiv2 < 8; _postdiv2++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (postdiv % _postdiv2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) _postdiv1 = postdiv / _postdiv2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (_postdiv1 > 0 && _postdiv1 < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (_postdiv2 > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fout *= _postdiv1 * _postdiv2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) _postdiv1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) _postdiv2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) for (_refdiv = min_refdiv; _refdiv <= max_refdiv; _refdiv++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u64 tmp, frac_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (fin % _refdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) tmp = (u64)fout * _refdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) do_div(tmp, fin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) _fbdiv = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (_fbdiv < 10 || _fbdiv > 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) tmp = (u64)_fbdiv * fin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) do_div(tmp, _refdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (fout < MIN_FVCO_RATE || fout > MAX_FVCO_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) frac_rate = fout - tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (frac_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) tmp = (u64)frac_rate * _refdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) tmp <<= 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) do_div(tmp, fin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) _frac = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) _dsmpd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * If DSMPD = 1 (DSM is disabled, "integer mode")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * FOUTVCO = FREF / REFDIV * FBDIV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * If DSMPD = 0 (DSM is enabled, "fractional mode")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 2^24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) foutvco = fin * _fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) do_div(foutvco, _refdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!_dsmpd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u64 frac_rate = (u64)fin * _frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) do_div(frac_rate, _refdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) foutvco += frac_rate >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) foutpostdiv = foutvco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) do_div(foutpostdiv, _postdiv1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) do_div(foutpostdiv, _postdiv2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (refdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) *refdiv = _refdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (fbdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *fbdiv = _fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (postdiv1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *postdiv1 = _postdiv1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (postdiv2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) *postdiv2 = _postdiv2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (frac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *frac = _frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (dsmpd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *dsmpd = _dsmpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *bypass = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return (unsigned long)foutpostdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) clk_regmap_pll_round_rate(struct clk_hw *hw, unsigned long drate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rate = clk_pll_round_rate(*prate, drate, NULL, NULL, NULL, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dev_dbg(pll->dev, "%s: prate=%ld, drate=%ld, rate=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) clk_hw_get_name(hw), *prate, drate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) clk_regmap_pll_set_rate(struct clk_hw *hw, unsigned long drate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u8 refdiv, postdiv1, postdiv2, dsmpd, bypass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u16 fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) u32 frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rate = clk_pll_round_rate(prate, drate, &refdiv, &fbdiv, &postdiv1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) &postdiv2, &frac, &dsmpd, &bypass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (rate < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dev_dbg(pll->dev, "%s: rate=%ld, bypass=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) clk_hw_get_name(hw), drate, bypass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (bypass) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) PLL_BYPASS(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) PLL_BYPASS(0) | PLL_POSTDIV1(postdiv1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) PLL_FBDIV(fbdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) HIWORD_UPDATE(dsmpd, pll->dsmpd_shift, pll->dsmpd_shift) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) PLL_POSTDIV2(postdiv2) | PLL_REFDIV(refdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) PLL_FRAC(frac));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dev_dbg(pll->dev, "refdiv=%d, fbdiv=%d, frac=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) refdiv, fbdiv, frac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dev_dbg(pll->dev, "postdiv1=%d, postdiv2=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) postdiv1, postdiv2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int clk_regmap_pll_prepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) HIWORD_UPDATE(0, pll->pd_shift, pll->pd_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = regmap_read_poll_timeout(pll->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) pll->reg + PLLCON_OFFSET(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) v, v & BIT(pll->lock_shift), 50, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(pll->dev, "%s is not lock\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static void clk_regmap_pll_unprepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) regmap_write(pll->regmap, pll->reg + PLLCON_OFFSET(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) HIWORD_UPDATE(1, pll->pd_shift, pll->pd_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int clk_regmap_pll_is_prepared(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct clk_regmap_pll *pll = to_clk_regmap_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) unsigned int con1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) regmap_read(pll->regmap, pll->reg + PLLCON_OFFSET(1), &con1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return !(con1 & BIT(pll->pd_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static const struct clk_ops clk_regmap_pll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .recalc_rate = clk_regmap_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .round_rate = clk_regmap_pll_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .set_rate = clk_regmap_pll_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .prepare = clk_regmap_pll_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .unprepare = clk_regmap_pll_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .is_prepared = clk_regmap_pll_is_prepared,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct clk *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) devm_clk_regmap_register_pll(struct device *dev, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct regmap *regmap, u32 reg, u8 pd_shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u8 dsmpd_shift, u8 lock_shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct clk_regmap_pll *pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct clk_init_data init = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!pll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) init.ops = &clk_regmap_pll_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) init.parent_names = (parent_name ? &parent_name : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) init.num_parents = (parent_name ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) pll->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) pll->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pll->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) pll->pd_shift = pd_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) pll->dsmpd_shift = dsmpd_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) pll->lock_shift = lock_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pll->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return devm_clk_register(dev, &pll->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) EXPORT_SYMBOL_GPL(devm_clk_regmap_register_pll);