1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * clock_am43xx.c
4  *
5  * clocks for AM43XX based boards
6  * Derived from AM33XX based boards
7  *
8  * Copyright (C) 2013, Texas Instruments, Incorporated - https://www.ti.com/
9  */
10 
11 #include <asm/arch/cpu.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/hardware.h>
14 #include <asm/arch/sys_proto.h>
15 #include <asm/io.h>
16 
17 struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
18 struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
19 struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
20 
21 const struct dpll_regs dpll_mpu_regs = {
22 	.cm_clkmode_dpll	= CM_WKUP + 0x560,
23 	.cm_idlest_dpll		= CM_WKUP + 0x564,
24 	.cm_clksel_dpll		= CM_WKUP + 0x56c,
25 	.cm_div_m2_dpll		= CM_WKUP + 0x570,
26 };
27 
28 const struct dpll_regs dpll_core_regs = {
29 	.cm_clkmode_dpll	= CM_WKUP + 0x520,
30 	.cm_idlest_dpll		= CM_WKUP + 0x524,
31 	.cm_clksel_dpll		= CM_WKUP + 0x52C,
32 	.cm_div_m4_dpll		= CM_WKUP + 0x538,
33 	.cm_div_m5_dpll		= CM_WKUP + 0x53C,
34 	.cm_div_m6_dpll		= CM_WKUP + 0x540,
35 };
36 
37 const struct dpll_regs dpll_per_regs = {
38 	.cm_clkmode_dpll	= CM_WKUP + 0x5E0,
39 	.cm_idlest_dpll		= CM_WKUP + 0x5E4,
40 	.cm_clksel_dpll		= CM_WKUP + 0x5EC,
41 	.cm_div_m2_dpll		= CM_WKUP + 0x5F0,
42 };
43 
44 const struct dpll_regs dpll_ddr_regs = {
45 	.cm_clkmode_dpll	= CM_WKUP + 0x5A0,
46 	.cm_idlest_dpll		= CM_WKUP + 0x5A4,
47 	.cm_clksel_dpll		= CM_WKUP + 0x5AC,
48 	.cm_div_m2_dpll		= CM_WKUP + 0x5B0,
49 	.cm_div_m4_dpll		= CM_WKUP + 0x5B8,
50 };
51 
setup_clocks_for_console(void)52 void setup_clocks_for_console(void)
53 {
54 	u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
55 
56 	/* Do not add any spl_debug prints in this function */
57 	clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
58 			CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
59 			CD_CLKCTRL_CLKTRCTRL_SHIFT);
60 
61 	/* Enable UART0 */
62 	clrsetbits_le32(&cmwkup->wkup_uart0ctrl,
63 			MODULE_CLKCTRL_MODULEMODE_MASK,
64 			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
65 			MODULE_CLKCTRL_MODULEMODE_SHIFT);
66 
67 	while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
68 		(idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
69 		clkctrl = readl(&cmwkup->wkup_uart0ctrl);
70 		idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
71 			 MODULE_CLKCTRL_IDLEST_SHIFT;
72 	}
73 }
74 
enable_basic_clocks(void)75 void enable_basic_clocks(void)
76 {
77 	u32 *const clk_domains[] = {
78 		&cmper->l3clkstctrl,
79 		&cmper->l3sclkstctrl,
80 		&cmper->l4lsclkstctrl,
81 		&cmwkup->wkclkstctrl,
82 		&cmper->emifclkstctrl,
83 		0
84 	};
85 
86 	u32 *const clk_modules_explicit_en[] = {
87 		&cmper->l3clkctrl,
88 		&cmper->l4lsclkctrl,
89 		&cmper->l4fwclkctrl,
90 		&cmwkup->wkl4wkclkctrl,
91 		&cmper->l3instrclkctrl,
92 		&cmper->l4hsclkctrl,
93 		&cmwkup->wkgpio0clkctrl,
94 		&cmwkup->wkctrlclkctrl,
95 		&cmper->timer2clkctrl,
96 		&cmper->gpmcclkctrl,
97 		&cmper->elmclkctrl,
98 		&cmper->mmc0clkctrl,
99 		&cmper->mmc1clkctrl,
100 		&cmwkup->wkup_i2c0ctrl,
101 		&cmper->gpio1clkctrl,
102 		&cmper->gpio2clkctrl,
103 		&cmper->gpio3clkctrl,
104 		&cmper->gpio4clkctrl,
105 		&cmper->gpio5clkctrl,
106 		&cmper->i2c1clkctrl,
107 		&cmper->cpgmac0clkctrl,
108 		&cmper->emiffwclkctrl,
109 		&cmper->emifclkctrl,
110 		&cmper->otfaemifclkctrl,
111 		&cmper->qspiclkctrl,
112 		&cmper->spi0clkctrl,
113 		0
114 	};
115 
116 	do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
117 
118 	/* Select the Master osc clk as Timer2 clock source */
119 	writel(0x1, &cmdpll->clktimer2clk);
120 
121 	/* For OPP100 the mac clock should be /5. */
122 	writel(0x4, &cmdpll->clkselmacclk);
123 }
124 
rtc_only_enable_basic_clocks(void)125 void rtc_only_enable_basic_clocks(void)
126 {
127 	u32 *const clk_domains[] = {
128 		&cmper->emifclkstctrl,
129 		0
130 	};
131 
132 	u32 *const clk_modules_explicit_en[] = {
133 		&cmper->gpio5clkctrl,
134 		&cmper->emiffwclkctrl,
135 		&cmper->emifclkctrl,
136 		&cmper->otfaemifclkctrl,
137 		0
138 	};
139 
140 	do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
141 
142 	/* Select the Master osc clk as Timer2 clock source */
143 	writel(0x1, &cmdpll->clktimer2clk);
144 }
145 
146 #ifdef CONFIG_TI_EDMA3
enable_edma3_clocks(void)147 void enable_edma3_clocks(void)
148 {
149 	u32 *const clk_domains_edma3[] = {
150 		0
151 	};
152 
153 	u32 *const clk_modules_explicit_en_edma3[] = {
154 		&cmper->tpccclkctrl,
155 		&cmper->tptc0clkctrl,
156 		0
157 	};
158 
159 	do_enable_clocks(clk_domains_edma3,
160 			 clk_modules_explicit_en_edma3,
161 			 1);
162 }
163 
disable_edma3_clocks(void)164 void disable_edma3_clocks(void)
165 {
166 	u32 *const clk_domains_edma3[] = {
167 		0
168 	};
169 
170 	u32 *const clk_modules_disable_edma3[] = {
171 		&cmper->tpccclkctrl,
172 		&cmper->tptc0clkctrl,
173 		0
174 	};
175 
176 	do_disable_clocks(clk_domains_edma3,
177 			  clk_modules_disable_edma3,
178 			  1);
179 }
180 #endif
181 
182 #if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP)
enable_usb_clocks(int index)183 void enable_usb_clocks(int index)
184 {
185 	u32 *usbclkctrl = 0;
186 	u32 *usbphyocp2scpclkctrl = 0;
187 
188 	if (index == 0) {
189 		usbclkctrl = &cmper->usb0clkctrl;
190 		usbphyocp2scpclkctrl = &cmper->usbphyocp2scp0clkctrl;
191 		setbits_le32(&cmper->usb0clkctrl,
192 			     USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
193 		setbits_le32(&cmwkup->usbphy0clkctrl,
194 			     USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
195 	} else if (index == 1) {
196 		usbclkctrl = &cmper->usb1clkctrl;
197 		usbphyocp2scpclkctrl = &cmper->usbphyocp2scp1clkctrl;
198 		setbits_le32(&cmper->usb1clkctrl,
199 			     USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
200 		setbits_le32(&cmwkup->usbphy1clkctrl,
201 			     USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
202 	}
203 
204 	u32 *const clk_domains_usb[] = {
205 		0
206 	};
207 
208 	u32 *const clk_modules_explicit_en_usb[] = {
209 		usbclkctrl,
210 		usbphyocp2scpclkctrl,
211 		0
212 	};
213 
214 	do_enable_clocks(clk_domains_usb, clk_modules_explicit_en_usb, 1);
215 }
216 
disable_usb_clocks(int index)217 void disable_usb_clocks(int index)
218 {
219 	u32 *usbclkctrl = 0;
220 	u32 *usbphyocp2scpclkctrl = 0;
221 
222 	if (index == 0) {
223 		usbclkctrl = &cmper->usb0clkctrl;
224 		usbphyocp2scpclkctrl = &cmper->usbphyocp2scp0clkctrl;
225 		clrbits_le32(&cmper->usb0clkctrl,
226 			     USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
227 		clrbits_le32(&cmwkup->usbphy0clkctrl,
228 			     USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
229 	} else if (index == 1) {
230 		usbclkctrl = &cmper->usb1clkctrl;
231 		usbphyocp2scpclkctrl = &cmper->usbphyocp2scp1clkctrl;
232 		clrbits_le32(&cmper->usb1clkctrl,
233 			     USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
234 		clrbits_le32(&cmwkup->usbphy1clkctrl,
235 			     USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
236 	}
237 
238 	u32 *const clk_domains_usb[] = {
239 		0
240 	};
241 
242 	u32 *const clk_modules_disable_usb[] = {
243 		usbclkctrl,
244 		usbphyocp2scpclkctrl,
245 		0
246 	};
247 
248 	do_disable_clocks(clk_domains_usb, clk_modules_disable_usb, 1);
249 }
250 #endif
251