1 /*
2  * Copyright (c) 2022-2024, Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 #include <zephyr/arch/cpu.h>
10 #include <socfpga_system_manager.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include "clock_control_agilex5_ll.h"
14 
15 LOG_MODULE_REGISTER(clock_control_agilex5_ll, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
16 
17 /* Extract reference clock from platform clock source */
get_ref_clk(mm_reg_t pllglob_reg,mm_reg_t pllm_reg)18 static uint32_t get_ref_clk(mm_reg_t pllglob_reg, mm_reg_t pllm_reg)
19 {
20 	uint32_t arefclkdiv = 0U;
21 	uint32_t ref_clk = 0U;
22 	uint32_t mdiv = 0U;
23 	uint32_t pllglob_val = 0U;
24 	uint32_t pllm_val = 0U;
25 
26 	/* Read pllglob and pllm registers */
27 	pllglob_val = sys_read32(pllglob_reg);
28 	pllm_val = sys_read32(pllm_reg);
29 
30 	/*
31 	 * Based on the clock source, read the values from System Manager boot
32 	 * scratch registers. These values are filled by boot loader based on
33 	 * hand-off data.
34 	 */
35 	switch (CLKCTRL_PSRC(pllglob_val)) {
36 	case CLKCTRL_PLLGLOB_PSRC_EOSC1:
37 		ref_clk = sys_read32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
38 		break;
39 
40 	case CLKCTRL_PLLGLOB_PSRC_INTOSC:
41 		ref_clk = CLKCTRL_INTOSC_HZ;
42 		break;
43 
44 	case CLKCTRL_PLLGLOB_PSRC_F2S:
45 		ref_clk = sys_read32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
46 		break;
47 
48 	default:
49 		ref_clk = 0;
50 		__ASSERT(0, "Invalid input clock source");
51 		break;
52 	}
53 
54 	/* Get reference clock divider */
55 	arefclkdiv = CLKCTRL_PLLGLOB_AREFCLKDIV(pllglob_val);
56 	__ASSERT(arefclkdiv != 0, "Reference clock divider is zero");
57 	ref_clk /= arefclkdiv;
58 
59 	/* Feedback clock divider */
60 	mdiv = CLKCTRL_PLLM_MDIV(pllm_val);
61 	ref_clk *= mdiv;
62 
63 	LOG_DBG("%s: ref_clk %u\n", __func__, ref_clk);
64 
65 	return ref_clk;
66 }
67 
68 /* Calculate clock frequency based on parameter */
get_clk_freq(mm_reg_t psrc_reg,mm_reg_t mainpllc_reg,mm_reg_t perpllc_reg)69 static uint32_t get_clk_freq(mm_reg_t psrc_reg, mm_reg_t mainpllc_reg,
70 			     mm_reg_t perpllc_reg)
71 {
72 	uint32_t clock_val = 0U;
73 	uint32_t clk_psrc = 0U;
74 	uint32_t pllcx_div = 0U;
75 
76 	/*
77 	 * Select source for the active 5:1 clock selection when the PLL
78 	 * is not bypassed
79 	 */
80 	clk_psrc = sys_read32(psrc_reg);
81 	switch (GET_CLKCTRL_CLKSRC(clk_psrc)) {
82 	case CLKCTRL_CLKSRC_MAIN:
83 		clock_val = get_ref_clk(CLKCTRL_MAINPLL(PLLGLOB), CLKCTRL_MAINPLL(PLLM));
84 		pllcx_div = (sys_read32(mainpllc_reg) & CLKCTRL_PLLCX_DIV_MSK);
85 		__ASSERT(pllcx_div != 0, "Main PLLC clock divider is zero");
86 		clock_val /= pllcx_div;
87 		break;
88 
89 	case CLKCTRL_CLKSRC_PER:
90 		clock_val = get_ref_clk(CLKCTRL_PERPLL(PLLGLOB), CLKCTRL_PERPLL(PLLM));
91 		pllcx_div = (sys_read32(perpllc_reg) & CLKCTRL_PLLCX_DIV_MSK);
92 		__ASSERT(pllcx_div != 0, "Peripheral PLLC clock divider is zero");
93 		clock_val /= pllcx_div;
94 		break;
95 
96 	case CLKCTRL_CLKSRC_OSC1:
97 		clock_val = sys_read32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
98 		break;
99 
100 	case CLKCTRL_CLKSRC_INTOSC:
101 		clock_val = CLKCTRL_INTOSC_HZ;
102 		break;
103 
104 	case CLKCTRL_CLKSRC_FPGA:
105 		clock_val = sys_read32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
106 		break;
107 
108 	default:
109 		__ASSERT(0, "Invalid clock source select");
110 		break;
111 	}
112 
113 	LOG_DBG("%s: clock source %lu and its value %u\n",
114 		__func__, GET_CLKCTRL_CLKSRC(clk_psrc), clock_val);
115 
116 	return clock_val;
117 }
118 
119 /* Get L3 free clock */
get_l3_main_free_clk(void)120 static uint32_t get_l3_main_free_clk(void)
121 {
122 	return get_clk_freq(CLKCTRL_MAINPLL(NOCCLK),
123 			    CLKCTRL_MAINPLL(PLLC3),
124 			    CLKCTRL_PERPLL(PLLC1));
125 }
126 
127 /* Get L4 mp clock */
get_l4_mp_clk(void)128 static uint32_t get_l4_mp_clk(void)
129 {
130 	uint32_t l3_main_free_clk = get_l3_main_free_clk();
131 	uint32_t mainpll_nocdiv_l4mp = BIT(GET_CLKCTRL_MAINPLL_NOCDIV_L4MP(
132 					sys_read32(CLKCTRL_MAINPLL(NOCDIV))));
133 
134 	uint32_t l4_mp_clk = (l3_main_free_clk / mainpll_nocdiv_l4mp);
135 
136 	return l4_mp_clk;
137 }
138 
139 /*
140  * Get L4 sp clock.
141  * "l4_sp_clk" (100MHz) will be used for slow peripherals like UART, I2C,
142  * Timers ...etc.
143  */
get_l4_sp_clk(void)144 static uint32_t get_l4_sp_clk(void)
145 {
146 	uint32_t l3_main_free_clk = get_l3_main_free_clk();
147 	uint32_t mainpll_nocdiv_l4sp = BIT(GET_CLKCTRL_MAINPLL_NOCDIV_L4SP(
148 					sys_read32(CLKCTRL_MAINPLL(NOCDIV))));
149 
150 	uint32_t l4_sp_clk = (l3_main_free_clk / mainpll_nocdiv_l4sp);
151 
152 	return l4_sp_clk;
153 }
154 
155 /* Get MPU clock */
get_mpu_clk(void)156 uint32_t get_mpu_clk(void)
157 {
158 	uint8_t cpu_id = arch_curr_cpu()->id;
159 	uint32_t ctr_reg = 0U;
160 	uint32_t clock_val = 0U;
161 
162 	if (cpu_id > CLKCTRL_CPU_ID_CORE1) {
163 		clock_val = get_clk_freq(CLKCTRL_CTLGRP(CORE23CTR),
164 				     CLKCTRL_MAINPLL(PLLC0),
165 				     CLKCTRL_PERPLL(PLLC0));
166 	} else {
167 		clock_val = get_clk_freq(CLKCTRL_CTLGRP(CORE01CTR),
168 				     CLKCTRL_MAINPLL(PLLC1),
169 				     CLKCTRL_PERPLL(PLLC0));
170 	}
171 
172 	switch (cpu_id) {
173 	case CLKCTRL_CPU_ID_CORE0:
174 	case CLKCTRL_CPU_ID_CORE1:
175 		ctr_reg = CLKCTRL_CTLGRP(CORE01CTR);
176 		break;
177 
178 	case CLKCTRL_CPU_ID_CORE2:
179 		ctr_reg = CLKCTRL_CTLGRP(CORE2CTR);
180 		break;
181 
182 	case CLKCTRL_CPU_ID_CORE3:
183 		ctr_reg = CLKCTRL_CTLGRP(CORE3CTR);
184 		break;
185 
186 	default:
187 		break;
188 	}
189 
190 	/* Division setting for ping pong counter in clock slice */
191 	clock_val /= 1 + (sys_read32(ctr_reg) & CLKCTRL_PLLCX_DIV_MSK);
192 
193 	return clock_val;
194 }
195 
196 /* Calculate clock frequency to be used for watchdog timer */
get_wdt_clk(void)197 uint32_t get_wdt_clk(void)
198 {
199 	uint32_t l3_main_free_clk = get_l3_main_free_clk();
200 	uint32_t mainpll_nocdiv_l4sysfreeclk = BIT(GET_CLKCTRL_MAINPLL_NOCDIV_L4SYSFREE(
201 						sys_read32(CLKCTRL_MAINPLL(NOCDIV))));
202 	uint32_t l4_sys_free_clk = (l3_main_free_clk / mainpll_nocdiv_l4sysfreeclk);
203 
204 	return l4_sys_free_clk;
205 }
206 
207 /* Get clock frequency to be used for UART driver */
get_uart_clk(void)208 uint32_t get_uart_clk(void)
209 {
210 	return get_l4_sp_clk();
211 }
212 
213 /* Calculate clock frequency to be used for SDMMC driver */
get_sdmmc_clk(void)214 uint32_t get_sdmmc_clk(void)
215 {
216 	uint32_t l4_mp_clk = get_l4_mp_clk();
217 	uint32_t mainpll_nocdiv = sys_read32(CLKCTRL_MAINPLL(NOCDIV));
218 	uint32_t sdmmc_clk = l4_mp_clk / BIT(GET_CLKCTRL_MAINPLL_NOCDIV_SPHY(mainpll_nocdiv));
219 
220 	return sdmmc_clk;
221 }
222 
223 /* Calculate clock frequency to be used for Timer driver */
get_timer_clk(void)224 uint32_t get_timer_clk(void)
225 {
226 	return get_l4_sp_clk();
227 }
228 
229 /* Calculate clock frequency to be used for QSPI driver */
get_qspi_clk(void)230 uint32_t get_qspi_clk(void)
231 {
232 	uint32_t scr_reg, ref_clk;
233 
234 	scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0);
235 	ref_clk = sys_read32(scr_reg);
236 
237 	/*
238 	 * In ATF, the qspi clock is divided by 1000 and loaded in scratch cold register 0
239 	 * So in Zephyr, reverting back the clock frequency by multiplying by 1000.
240 	 */
241 	return (ref_clk * 1000);
242 }
243 
244 /* Calculate clock frequency to be used for I2C driver */
get_i2c_clk(void)245 uint32_t get_i2c_clk(void)
246 {
247 	return get_l4_sp_clk();
248 }
249 
250 /* Calculate clock frequency to be used for I3C driver */
get_i3c_clk(void)251 uint32_t get_i3c_clk(void)
252 {
253 	return get_l4_mp_clk();
254 }
255