Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);