1 /*
2  * clock.c
3  *
4  * Clock initialization for AM33XX boards.
5  * Derived from OMAP4 boards
6  *
7  * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 #include <common.h>
12 #include <asm/arch/cpu.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/arch/sys_proto.h>
16 #include <asm/io.h>
17 
18 static void setup_post_dividers(const struct dpll_regs *dpll_regs,
19 			 const struct dpll_params *params)
20 {
21 	/* Setup post-dividers */
22 	if (params->m2 >= 0)
23 		writel(params->m2, dpll_regs->cm_div_m2_dpll);
24 	if (params->m3 >= 0)
25 		writel(params->m3, dpll_regs->cm_div_m3_dpll);
26 	if (params->m4 >= 0)
27 		writel(params->m4, dpll_regs->cm_div_m4_dpll);
28 	if (params->m5 >= 0)
29 		writel(params->m5, dpll_regs->cm_div_m5_dpll);
30 	if (params->m6 >= 0)
31 		writel(params->m6, dpll_regs->cm_div_m6_dpll);
32 }
33 
34 static inline void do_lock_dpll(const struct dpll_regs *dpll_regs)
35 {
36 	clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
37 			CM_CLKMODE_DPLL_DPLL_EN_MASK,
38 			DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT);
39 }
40 
41 static inline void wait_for_lock(const struct dpll_regs *dpll_regs)
42 {
43 	if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK,
44 			   (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
45 		printf("DPLL locking failed for 0x%x\n",
46 		       dpll_regs->cm_clkmode_dpll);
47 		hang();
48 	}
49 }
50 
51 static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs)
52 {
53 	clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
54 			CM_CLKMODE_DPLL_DPLL_EN_MASK,
55 			DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT);
56 }
57 
58 static inline void wait_for_bypass(const struct dpll_regs *dpll_regs)
59 {
60 	if (!wait_on_value(ST_DPLL_CLK_MASK, 0,
61 			   (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
62 		printf("Bypassing DPLL failed 0x%x\n",
63 		       dpll_regs->cm_clkmode_dpll);
64 	}
65 }
66 
67 static void bypass_dpll(const struct dpll_regs *dpll_regs)
68 {
69 	do_bypass_dpll(dpll_regs);
70 	wait_for_bypass(dpll_regs);
71 }
72 
73 void do_setup_dpll(const struct dpll_regs *dpll_regs,
74 		   const struct dpll_params *params)
75 {
76 	u32 temp;
77 
78 	if (!params)
79 		return;
80 
81 	temp = readl(dpll_regs->cm_clksel_dpll);
82 
83 	bypass_dpll(dpll_regs);
84 
85 	/* Set M & N */
86 	temp &= ~CM_CLKSEL_DPLL_M_MASK;
87 	temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
88 
89 	temp &= ~CM_CLKSEL_DPLL_N_MASK;
90 	temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK;
91 
92 	writel(temp, dpll_regs->cm_clksel_dpll);
93 
94 	setup_post_dividers(dpll_regs, params);
95 
96 	/* Wait till the DPLL locks */
97 	do_lock_dpll(dpll_regs);
98 	wait_for_lock(dpll_regs);
99 }
100 
101 static void setup_dplls(void)
102 {
103 	const struct dpll_params *params;
104 
105 	params = get_dpll_core_params();
106 	do_setup_dpll(&dpll_core_regs, params);
107 
108 	params = get_dpll_mpu_params();
109 	do_setup_dpll(&dpll_mpu_regs, params);
110 
111 	params = get_dpll_per_params();
112 	do_setup_dpll(&dpll_per_regs, params);
113 	writel(0x300, &cmwkup->clkdcoldodpllper);
114 
115 	params = get_dpll_ddr_params();
116 	do_setup_dpll(&dpll_ddr_regs, params);
117 }
118 
119 static inline void wait_for_clk_enable(u32 *clkctrl_addr)
120 {
121 	u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
122 	u32 bound = LDELAY;
123 
124 	while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
125 		(idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
126 		clkctrl = readl(clkctrl_addr);
127 		idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
128 			 MODULE_CLKCTRL_IDLEST_SHIFT;
129 		if (--bound == 0) {
130 			printf("Clock enable failed for 0x%p idlest 0x%x\n",
131 			       clkctrl_addr, clkctrl);
132 			return;
133 		}
134 	}
135 }
136 
137 static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode,
138 				       u32 wait_for_enable)
139 {
140 	clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
141 			enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
142 	debug("Enable clock module - %p\n", clkctrl_addr);
143 	if (wait_for_enable)
144 		wait_for_clk_enable(clkctrl_addr);
145 }
146 
147 static inline void wait_for_clk_disable(u32 *clkctrl_addr)
148 {
149 	u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_FULLY_FUNCTIONAL;
150 	u32 bound = LDELAY;
151 
152 	while ((idlest != MODULE_CLKCTRL_IDLEST_DISABLED)) {
153 		clkctrl = readl(clkctrl_addr);
154 		idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
155 			  MODULE_CLKCTRL_IDLEST_SHIFT;
156 		if (--bound == 0) {
157 			printf("Clock disable failed for 0x%p idlest 0x%x\n",
158 			       clkctrl_addr, clkctrl);
159 			 return;
160 		}
161 	}
162 }
163 static inline void disable_clock_module(u32 *const clkctrl_addr,
164 					u32 wait_for_disable)
165 {
166 	clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
167 			MODULE_CLKCTRL_MODULEMODE_SW_DISABLE <<
168 			MODULE_CLKCTRL_MODULEMODE_SHIFT);
169 	debug("Disable clock module - %p\n", clkctrl_addr);
170 	if (wait_for_disable)
171 		wait_for_clk_disable(clkctrl_addr);
172 }
173 
174 static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
175 {
176 	clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
177 			enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
178 	debug("Enable clock domain - %p\n", clkctrl_reg);
179 }
180 
181 static inline void disable_clock_domain(u32 *const clkctrl_reg)
182 {
183 	clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
184 			CD_CLKCTRL_CLKTRCTRL_SW_SLEEP <<
185 			CD_CLKCTRL_CLKTRCTRL_SHIFT);
186 	debug("Disable clock domain - %p\n", clkctrl_reg);
187 }
188 
189 void do_enable_clocks(u32 *const *clk_domains,
190 		      u32 *const *clk_modules_explicit_en, u8 wait_for_enable)
191 {
192 	u32 i, max = 100;
193 
194 	/* Put the clock domains in SW_WKUP mode */
195 	for (i = 0; (i < max) && clk_domains[i]; i++) {
196 		enable_clock_domain(clk_domains[i],
197 				    CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
198 	}
199 
200 	/* Clock modules that need to be put in SW_EXPLICIT_EN mode */
201 	for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
202 		enable_clock_module(clk_modules_explicit_en[i],
203 				    MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
204 				    wait_for_enable);
205 	};
206 }
207 
208 void do_disable_clocks(u32 *const *clk_domains,
209 			u32 *const *clk_modules_disable,
210 			u8 wait_for_disable)
211 {
212 	u32 i, max = 100;
213 
214 
215 	/* Clock modules that need to be put in SW_DISABLE */
216 	for (i = 0; (i < max) && clk_modules_disable[i]; i++)
217 		disable_clock_module(clk_modules_disable[i],
218 				     wait_for_disable);
219 
220 	/* Put the clock domains in SW_SLEEP mode */
221 	for (i = 0; (i < max) && clk_domains[i]; i++)
222 		disable_clock_domain(clk_domains[i]);
223 }
224 
225 /*
226  * Before scaling up the clocks we need to have the PMIC scale up the
227  * voltages first.  This will be dependent on which PMIC is in use
228  * and in some cases we may not be scaling things up at all and thus not
229  * need to do anything here.
230  */
231 __weak void scale_vcores(void)
232 {
233 }
234 
235 void setup_early_clocks(void)
236 {
237 	setup_clocks_for_console();
238 	enable_basic_clocks();
239 	timer_init();
240 }
241 
242 void prcm_init(void)
243 {
244 	scale_vcores();
245 	setup_dplls();
246 }
247