xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-keystone/clock.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Keystone2: pll initialization
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * (C) Copyright 2012-2014
5*4882a593Smuzhiyun  *     Texas Instruments Incorporated, <www.ti.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <asm/arch/clock.h>
12*4882a593Smuzhiyun #include <asm/arch/clock_defs.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun /* DEV and ARM speed definitions as specified in DEVSPEED register */
15*4882a593Smuzhiyun int __weak speeds[DEVSPEED_NUMSPDS] = {
16*4882a593Smuzhiyun 	SPD1000,
17*4882a593Smuzhiyun 	SPD1200,
18*4882a593Smuzhiyun 	SPD1350,
19*4882a593Smuzhiyun 	SPD1400,
20*4882a593Smuzhiyun 	SPD1500,
21*4882a593Smuzhiyun 	SPD1400,
22*4882a593Smuzhiyun 	SPD1350,
23*4882a593Smuzhiyun 	SPD1200,
24*4882a593Smuzhiyun 	SPD1000,
25*4882a593Smuzhiyun 	SPD800,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun const struct keystone_pll_regs keystone_pll_regs[] = {
29*4882a593Smuzhiyun 	[CORE_PLL]	= {KS2_MAINPLLCTL0, KS2_MAINPLLCTL1},
30*4882a593Smuzhiyun 	[PASS_PLL]	= {KS2_PASSPLLCTL0, KS2_PASSPLLCTL1},
31*4882a593Smuzhiyun 	[TETRIS_PLL]	= {KS2_ARMPLLCTL0, KS2_ARMPLLCTL1},
32*4882a593Smuzhiyun 	[DDR3A_PLL]	= {KS2_DDR3APLLCTL0, KS2_DDR3APLLCTL1},
33*4882a593Smuzhiyun 	[DDR3B_PLL]	= {KS2_DDR3BPLLCTL0, KS2_DDR3BPLLCTL1},
34*4882a593Smuzhiyun 	[UART_PLL]	= {KS2_UARTPLLCTL0, KS2_UARTPLLCTL1},
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
pll_pa_clk_sel(void)37*4882a593Smuzhiyun inline void pll_pa_clk_sel(void)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	setbits_le32(keystone_pll_regs[PASS_PLL].reg1, CFG_PLLCTL1_PAPLL_MASK);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
wait_for_completion(const struct pll_init_data * data)42*4882a593Smuzhiyun static void wait_for_completion(const struct pll_init_data *data)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	int i;
45*4882a593Smuzhiyun 	for (i = 0; i < 100; i++) {
46*4882a593Smuzhiyun 		sdelay(450);
47*4882a593Smuzhiyun 		if (!(pllctl_reg_read(data->pll, stat) & PLLSTAT_GOSTAT_MASK))
48*4882a593Smuzhiyun 			break;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
bypass_main_pll(const struct pll_init_data * data)52*4882a593Smuzhiyun static inline void bypass_main_pll(const struct pll_init_data *data)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLENSRC_MASK |
55*4882a593Smuzhiyun 			   PLLCTL_PLLEN_MASK);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	/* 4 cycles of reference clock CLKIN*/
58*4882a593Smuzhiyun 	sdelay(340);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
configure_mult_div(const struct pll_init_data * data)61*4882a593Smuzhiyun static void configure_mult_div(const struct pll_init_data *data)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	u32 pllm, plld, bwadj;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	pllm = data->pll_m - 1;
66*4882a593Smuzhiyun 	plld = (data->pll_d - 1) & CFG_PLLCTL0_PLLD_MASK;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	/* Program Multiplier */
69*4882a593Smuzhiyun 	if (data->pll == MAIN_PLL)
70*4882a593Smuzhiyun 		pllctl_reg_write(data->pll, mult, pllm & PLLM_MULT_LO_MASK);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	clrsetbits_le32(keystone_pll_regs[data->pll].reg0,
73*4882a593Smuzhiyun 			CFG_PLLCTL0_PLLM_MASK,
74*4882a593Smuzhiyun 			pllm << CFG_PLLCTL0_PLLM_SHIFT);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	/* Program BWADJ */
77*4882a593Smuzhiyun 	bwadj = (data->pll_m - 1) >> 1; /* Divide pllm by 2 */
78*4882a593Smuzhiyun 	clrsetbits_le32(keystone_pll_regs[data->pll].reg0,
79*4882a593Smuzhiyun 			CFG_PLLCTL0_BWADJ_MASK,
80*4882a593Smuzhiyun 			(bwadj << CFG_PLLCTL0_BWADJ_SHIFT) &
81*4882a593Smuzhiyun 			CFG_PLLCTL0_BWADJ_MASK);
82*4882a593Smuzhiyun 	bwadj = bwadj >> CFG_PLLCTL0_BWADJ_BITS;
83*4882a593Smuzhiyun 	clrsetbits_le32(keystone_pll_regs[data->pll].reg1,
84*4882a593Smuzhiyun 			CFG_PLLCTL1_BWADJ_MASK, bwadj);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	/* Program Divider */
87*4882a593Smuzhiyun 	clrsetbits_le32(keystone_pll_regs[data->pll].reg0,
88*4882a593Smuzhiyun 			CFG_PLLCTL0_PLLD_MASK, plld);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
configure_main_pll(const struct pll_init_data * data)91*4882a593Smuzhiyun void configure_main_pll(const struct pll_init_data *data)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	u32 tmp, pllod, i, alnctl_val = 0;
94*4882a593Smuzhiyun 	u32 *offset;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	pllod = data->pll_od - 1;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* 100 micro sec for stabilization */
99*4882a593Smuzhiyun 	sdelay(210000);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	tmp = pllctl_reg_read(data->pll, secctl);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	/* Check for Bypass */
104*4882a593Smuzhiyun 	if (tmp & SECCTL_BYPASS_MASK) {
105*4882a593Smuzhiyun 		setbits_le32(keystone_pll_regs[data->pll].reg1,
106*4882a593Smuzhiyun 			     CFG_PLLCTL1_ENSAT_MASK);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 		bypass_main_pll(data);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 		/* Powerdown and powerup Main Pll */
111*4882a593Smuzhiyun 		pllctl_reg_setbits(data->pll, secctl, SECCTL_BYPASS_MASK);
112*4882a593Smuzhiyun 		pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLPWRDN_MASK);
113*4882a593Smuzhiyun 		/* 5 micro sec */
114*4882a593Smuzhiyun 		sdelay(21000);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 		pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN_MASK);
117*4882a593Smuzhiyun 	} else {
118*4882a593Smuzhiyun 		bypass_main_pll(data);
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	configure_mult_div(data);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	/* Program Output Divider */
124*4882a593Smuzhiyun 	pllctl_reg_rmw(data->pll, secctl, SECCTL_OP_DIV_MASK,
125*4882a593Smuzhiyun 		       ((pllod << SECCTL_OP_DIV_SHIFT) & SECCTL_OP_DIV_MASK));
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	/* Program PLLDIVn */
128*4882a593Smuzhiyun 	wait_for_completion(data);
129*4882a593Smuzhiyun 	for (i = 0; i < PLLDIV_MAX; i++) {
130*4882a593Smuzhiyun 		if (i < 3)
131*4882a593Smuzhiyun 			offset = pllctl_reg(data->pll, div1) + i;
132*4882a593Smuzhiyun 		else
133*4882a593Smuzhiyun 			offset = pllctl_reg(data->pll, div4) + (i - 3);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 		if (divn_val[i] != -1) {
136*4882a593Smuzhiyun 			__raw_writel(divn_val[i] | PLLDIV_ENABLE_MASK, offset);
137*4882a593Smuzhiyun 			alnctl_val |= BIT(i);
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	if (alnctl_val) {
142*4882a593Smuzhiyun 		pllctl_reg_setbits(data->pll, alnctl, alnctl_val);
143*4882a593Smuzhiyun 		/*
144*4882a593Smuzhiyun 		 * Set GOSET bit in PLLCMD to initiate the GO operation
145*4882a593Smuzhiyun 		 * to change the divide
146*4882a593Smuzhiyun 		 */
147*4882a593Smuzhiyun 		pllctl_reg_setbits(data->pll, cmd, PLLSTAT_GOSTAT_MASK);
148*4882a593Smuzhiyun 		wait_for_completion(data);
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	/* Reset PLL */
152*4882a593Smuzhiyun 	pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST_MASK);
153*4882a593Smuzhiyun 	sdelay(21000);	/* Wait for a minimum of 7 us*/
154*4882a593Smuzhiyun 	pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST_MASK);
155*4882a593Smuzhiyun 	sdelay(105000);	/* Wait for PLL Lock time (min 50 us) */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	/* Enable PLL */
158*4882a593Smuzhiyun 	pllctl_reg_clrbits(data->pll, secctl, SECCTL_BYPASS_MASK);
159*4882a593Smuzhiyun 	pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN_MASK);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
configure_secondary_pll(const struct pll_init_data * data)162*4882a593Smuzhiyun void configure_secondary_pll(const struct pll_init_data *data)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	int pllod = data->pll_od - 1;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	/* Enable Glitch free bypass for ARM PLL */
167*4882a593Smuzhiyun 	if (cpu_is_k2hk() && data->pll == TETRIS_PLL)
168*4882a593Smuzhiyun 		clrbits_le32(KS2_MISC_CTRL, MISC_CTL1_ARM_PLL_EN);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* Enable Bypass mode */
171*4882a593Smuzhiyun 	setbits_le32(keystone_pll_regs[data->pll].reg1, CFG_PLLCTL1_ENSAT_MASK);
172*4882a593Smuzhiyun 	setbits_le32(keystone_pll_regs[data->pll].reg0,
173*4882a593Smuzhiyun 		     CFG_PLLCTL0_BYPASS_MASK);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	configure_mult_div(data);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	/* Program Output Divider */
178*4882a593Smuzhiyun 	clrsetbits_le32(keystone_pll_regs[data->pll].reg0,
179*4882a593Smuzhiyun 			CFG_PLLCTL0_CLKOD_MASK,
180*4882a593Smuzhiyun 			(pllod << CFG_PLLCTL0_CLKOD_SHIFT) &
181*4882a593Smuzhiyun 			CFG_PLLCTL0_CLKOD_MASK);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	/* Reset PLL */
184*4882a593Smuzhiyun 	setbits_le32(keystone_pll_regs[data->pll].reg1, CFG_PLLCTL1_RST_MASK);
185*4882a593Smuzhiyun 	/* Wait for 5 micro seconds */
186*4882a593Smuzhiyun 	sdelay(21000);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* Select the Output of PASS PLL as input to PASS */
189*4882a593Smuzhiyun 	if (data->pll == PASS_PLL && cpu_is_k2hk())
190*4882a593Smuzhiyun 		pll_pa_clk_sel();
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	clrbits_le32(keystone_pll_regs[data->pll].reg1, CFG_PLLCTL1_RST_MASK);
193*4882a593Smuzhiyun 	/* Wait for 500 * REFCLK cucles * (PLLD + 1) */
194*4882a593Smuzhiyun 	sdelay(105000);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	/* Switch to PLL mode */
197*4882a593Smuzhiyun 	clrbits_le32(keystone_pll_regs[data->pll].reg0,
198*4882a593Smuzhiyun 		     CFG_PLLCTL0_BYPASS_MASK);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* Select the Output of ARM PLL as input to ARM */
201*4882a593Smuzhiyun 	if (cpu_is_k2hk() && data->pll == TETRIS_PLL)
202*4882a593Smuzhiyun 		setbits_le32(KS2_MISC_CTRL, MISC_CTL1_ARM_PLL_EN);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
init_pll(const struct pll_init_data * data)205*4882a593Smuzhiyun void init_pll(const struct pll_init_data *data)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	if (data->pll == MAIN_PLL)
208*4882a593Smuzhiyun 		configure_main_pll(data);
209*4882a593Smuzhiyun 	else
210*4882a593Smuzhiyun 		configure_secondary_pll(data);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	/*
213*4882a593Smuzhiyun 	 * This is required to provide a delay between multiple
214*4882a593Smuzhiyun 	 * consequent PPL configurations
215*4882a593Smuzhiyun 	 */
216*4882a593Smuzhiyun 	sdelay(210000);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
init_plls(void)219*4882a593Smuzhiyun void init_plls(void)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	struct pll_init_data *data;
222*4882a593Smuzhiyun 	int pll;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	for (pll = MAIN_PLL; pll < MAX_PLL_COUNT; pll++) {
225*4882a593Smuzhiyun 		data = get_pll_init_data(pll);
226*4882a593Smuzhiyun 		if (data)
227*4882a593Smuzhiyun 			init_pll(data);
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
get_max_speed(u32 val,u32 speed_supported,int * spds)231*4882a593Smuzhiyun static int get_max_speed(u32 val, u32 speed_supported, int *spds)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	int speed;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	/* Left most setbit gives the speed */
236*4882a593Smuzhiyun 	for (speed = DEVSPEED_NUMSPDS; speed >= 0; speed--) {
237*4882a593Smuzhiyun 		if ((val & BIT(speed)) & speed_supported)
238*4882a593Smuzhiyun 			return spds[speed];
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	/* If no bit is set, return minimum speed */
242*4882a593Smuzhiyun 	if (cpu_is_k2g())
243*4882a593Smuzhiyun 		return SPD200;
244*4882a593Smuzhiyun 	else
245*4882a593Smuzhiyun 		return SPD800;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
read_efuse_bootrom(void)248*4882a593Smuzhiyun static inline u32 read_efuse_bootrom(void)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	if (cpu_is_k2hk() && (cpu_revision() <= 1))
251*4882a593Smuzhiyun 		return __raw_readl(KS2_REV1_DEVSPEED);
252*4882a593Smuzhiyun 	else
253*4882a593Smuzhiyun 		return __raw_readl(KS2_EFUSE_BOOTROM);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
get_max_arm_speed(int * spds)256*4882a593Smuzhiyun int get_max_arm_speed(int *spds)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	u32 armspeed = read_efuse_bootrom();
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	armspeed = (armspeed & DEVSPEED_ARMSPEED_MASK) >>
261*4882a593Smuzhiyun 		    DEVSPEED_ARMSPEED_SHIFT;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return get_max_speed(armspeed, ARM_SUPPORTED_SPEEDS, spds);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
get_max_dev_speed(int * spds)266*4882a593Smuzhiyun int get_max_dev_speed(int *spds)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	u32 devspeed = read_efuse_bootrom();
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	devspeed = (devspeed & DEVSPEED_DEVSPEED_MASK) >>
271*4882a593Smuzhiyun 		    DEVSPEED_DEVSPEED_SHIFT;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return get_max_speed(devspeed, DEV_SUPPORTED_SPEEDS, spds);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun /**
277*4882a593Smuzhiyun  * pll_freq_get - get pll frequency
278*4882a593Smuzhiyun  * @pll:	pll identifier
279*4882a593Smuzhiyun  */
pll_freq_get(int pll)280*4882a593Smuzhiyun static unsigned long pll_freq_get(int pll)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	unsigned long mult = 1, prediv = 1, output_div = 2;
283*4882a593Smuzhiyun 	unsigned long ret;
284*4882a593Smuzhiyun 	u32 tmp, reg;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (pll == MAIN_PLL) {
287*4882a593Smuzhiyun 		ret = get_external_clk(sys_clk);
288*4882a593Smuzhiyun 		if (pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN_MASK) {
289*4882a593Smuzhiyun 			/* PLL mode */
290*4882a593Smuzhiyun 			tmp = __raw_readl(KS2_MAINPLLCTL0);
291*4882a593Smuzhiyun 			prediv = (tmp & CFG_PLLCTL0_PLLD_MASK) + 1;
292*4882a593Smuzhiyun 			mult = ((tmp & CFG_PLLCTL0_PLLM_HI_MASK) >>
293*4882a593Smuzhiyun 				CFG_PLLCTL0_PLLM_SHIFT |
294*4882a593Smuzhiyun 				(pllctl_reg_read(pll, mult) &
295*4882a593Smuzhiyun 				 PLLM_MULT_LO_MASK)) + 1;
296*4882a593Smuzhiyun 			output_div = ((pllctl_reg_read(pll, secctl) &
297*4882a593Smuzhiyun 				       SECCTL_OP_DIV_MASK) >>
298*4882a593Smuzhiyun 				       SECCTL_OP_DIV_SHIFT) + 1;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 			ret = ret / prediv / output_div * mult;
301*4882a593Smuzhiyun 		}
302*4882a593Smuzhiyun 	} else {
303*4882a593Smuzhiyun 		switch (pll) {
304*4882a593Smuzhiyun 		case PASS_PLL:
305*4882a593Smuzhiyun 			ret = get_external_clk(pa_clk);
306*4882a593Smuzhiyun 			reg = KS2_PASSPLLCTL0;
307*4882a593Smuzhiyun 			break;
308*4882a593Smuzhiyun 		case TETRIS_PLL:
309*4882a593Smuzhiyun 			ret = get_external_clk(tetris_clk);
310*4882a593Smuzhiyun 			reg = KS2_ARMPLLCTL0;
311*4882a593Smuzhiyun 			break;
312*4882a593Smuzhiyun 		case DDR3A_PLL:
313*4882a593Smuzhiyun 			ret = get_external_clk(ddr3a_clk);
314*4882a593Smuzhiyun 			reg = KS2_DDR3APLLCTL0;
315*4882a593Smuzhiyun 			break;
316*4882a593Smuzhiyun 		case DDR3B_PLL:
317*4882a593Smuzhiyun 			ret = get_external_clk(ddr3b_clk);
318*4882a593Smuzhiyun 			reg = KS2_DDR3BPLLCTL0;
319*4882a593Smuzhiyun 			break;
320*4882a593Smuzhiyun 		case UART_PLL:
321*4882a593Smuzhiyun 			ret = get_external_clk(uart_clk);
322*4882a593Smuzhiyun 			reg = KS2_UARTPLLCTL0;
323*4882a593Smuzhiyun 			break;
324*4882a593Smuzhiyun 		default:
325*4882a593Smuzhiyun 			return 0;
326*4882a593Smuzhiyun 		}
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		tmp = __raw_readl(reg);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 		if (!(tmp & CFG_PLLCTL0_BYPASS_MASK)) {
331*4882a593Smuzhiyun 			/* Bypass disabled */
332*4882a593Smuzhiyun 			prediv = (tmp & CFG_PLLCTL0_PLLD_MASK) + 1;
333*4882a593Smuzhiyun 			mult = ((tmp & CFG_PLLCTL0_PLLM_MASK) >>
334*4882a593Smuzhiyun 				CFG_PLLCTL0_PLLM_SHIFT) + 1;
335*4882a593Smuzhiyun 			output_div = ((tmp & CFG_PLLCTL0_CLKOD_MASK) >>
336*4882a593Smuzhiyun 				      CFG_PLLCTL0_CLKOD_SHIFT) + 1;
337*4882a593Smuzhiyun 			ret = ((ret / prediv) * mult) / output_div;
338*4882a593Smuzhiyun 		}
339*4882a593Smuzhiyun 	}
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	return ret;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
ks_clk_get_rate(unsigned int clk)344*4882a593Smuzhiyun unsigned long ks_clk_get_rate(unsigned int clk)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	unsigned long freq = 0;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	switch (clk) {
349*4882a593Smuzhiyun 	case core_pll_clk:
350*4882a593Smuzhiyun 		freq = pll_freq_get(CORE_PLL);
351*4882a593Smuzhiyun 		break;
352*4882a593Smuzhiyun 	case pass_pll_clk:
353*4882a593Smuzhiyun 		freq = pll_freq_get(PASS_PLL);
354*4882a593Smuzhiyun 		break;
355*4882a593Smuzhiyun 	case tetris_pll_clk:
356*4882a593Smuzhiyun 		if (!cpu_is_k2e())
357*4882a593Smuzhiyun 			freq = pll_freq_get(TETRIS_PLL);
358*4882a593Smuzhiyun 		break;
359*4882a593Smuzhiyun 	case ddr3a_pll_clk:
360*4882a593Smuzhiyun 		freq = pll_freq_get(DDR3A_PLL);
361*4882a593Smuzhiyun 		break;
362*4882a593Smuzhiyun 	case ddr3b_pll_clk:
363*4882a593Smuzhiyun 		if (cpu_is_k2hk())
364*4882a593Smuzhiyun 			freq = pll_freq_get(DDR3B_PLL);
365*4882a593Smuzhiyun 		break;
366*4882a593Smuzhiyun 	case uart_pll_clk:
367*4882a593Smuzhiyun 		if (cpu_is_k2g())
368*4882a593Smuzhiyun 			freq = pll_freq_get(UART_PLL);
369*4882a593Smuzhiyun 		break;
370*4882a593Smuzhiyun 	case sys_clk0_1_clk:
371*4882a593Smuzhiyun 	case sys_clk0_clk:
372*4882a593Smuzhiyun 		freq = pll_freq_get(CORE_PLL) / pll0div_read(1);
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 	case sys_clk1_clk:
375*4882a593Smuzhiyun 	return pll_freq_get(CORE_PLL) / pll0div_read(2);
376*4882a593Smuzhiyun 		break;
377*4882a593Smuzhiyun 	case sys_clk2_clk:
378*4882a593Smuzhiyun 		freq = pll_freq_get(CORE_PLL) / pll0div_read(3);
379*4882a593Smuzhiyun 		break;
380*4882a593Smuzhiyun 	case sys_clk3_clk:
381*4882a593Smuzhiyun 		freq = pll_freq_get(CORE_PLL) / pll0div_read(4);
382*4882a593Smuzhiyun 		break;
383*4882a593Smuzhiyun 	case sys_clk0_2_clk:
384*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 2;
385*4882a593Smuzhiyun 		break;
386*4882a593Smuzhiyun 	case sys_clk0_3_clk:
387*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 3;
388*4882a593Smuzhiyun 		break;
389*4882a593Smuzhiyun 	case sys_clk0_4_clk:
390*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 4;
391*4882a593Smuzhiyun 		break;
392*4882a593Smuzhiyun 	case sys_clk0_6_clk:
393*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 6;
394*4882a593Smuzhiyun 		break;
395*4882a593Smuzhiyun 	case sys_clk0_8_clk:
396*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 8;
397*4882a593Smuzhiyun 		break;
398*4882a593Smuzhiyun 	case sys_clk0_12_clk:
399*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 12;
400*4882a593Smuzhiyun 		break;
401*4882a593Smuzhiyun 	case sys_clk0_24_clk:
402*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk0_clk) / 24;
403*4882a593Smuzhiyun 		break;
404*4882a593Smuzhiyun 	case sys_clk1_3_clk:
405*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk1_clk) / 3;
406*4882a593Smuzhiyun 		break;
407*4882a593Smuzhiyun 	case sys_clk1_4_clk:
408*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk1_clk) / 4;
409*4882a593Smuzhiyun 		break;
410*4882a593Smuzhiyun 	case sys_clk1_6_clk:
411*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk1_clk) / 6;
412*4882a593Smuzhiyun 		break;
413*4882a593Smuzhiyun 	case sys_clk1_12_clk:
414*4882a593Smuzhiyun 		freq = ks_clk_get_rate(sys_clk1_clk) / 12;
415*4882a593Smuzhiyun 		break;
416*4882a593Smuzhiyun 	default:
417*4882a593Smuzhiyun 		break;
418*4882a593Smuzhiyun 	}
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	return freq;
421*4882a593Smuzhiyun }
422