xref: /aosp_15_r20/external/coreboot/src/soc/qualcomm/common/clock.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <commonlib/helpers.h>
5 #include <delay.h>
6 #include <device/mmio.h>
7 #include <soc/clock.h>
8 #include <timer.h>
9 #include <types.h>
10 
11 /* Clock Branch Operations */
clock_is_off(u32 * cbcr_addr)12 static bool clock_is_off(u32 *cbcr_addr)
13 {
14 	return (read32(cbcr_addr) & CLK_CTL_OFF_BMSK);
15 }
16 
clock_enable_vote(void * cbcr_addr,void * vote_addr,uint32_t vote_bit)17 enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr,
18 				uint32_t vote_bit)
19 {
20 	int count = 100;
21 
22 	setbits32(vote_addr, BIT(vote_bit));
23 
24 	/* Ensure clock is enabled */
25 	while (count-- > 0) {
26 		if (!clock_is_off(cbcr_addr))
27 			return CB_SUCCESS;
28 		udelay(1);
29 	}
30 	printk(BIOS_ERR, "Failed to enable clock, register val: 0x%x\n",
31 			read32(cbcr_addr));
32 	return CB_ERR;
33 }
34 
clock_enable(void * cbcr_addr)35 enum cb_err clock_enable(void *cbcr_addr)
36 {
37 	int count = 100;
38 
39 	/* Set clock enable bit */
40 	setbits32(cbcr_addr, BIT(CLK_CTL_EN_SHFT));
41 
42 	/* Ensure clock is enabled */
43 	while (count-- > 0) {
44 		if (!clock_is_off(cbcr_addr))
45 			return CB_SUCCESS;
46 		udelay(1);
47 	}
48 	printk(BIOS_ERR, "Failed to enable clock, register val: 0x%x\n",
49 			read32(cbcr_addr));
50 	return CB_ERR;
51 }
52 
53 /* Clock Block Reset Operations */
clock_reset_bcr(void * bcr_addr,bool assert)54 void clock_reset_bcr(void *bcr_addr, bool assert)
55 {
56 	if (assert)
57 		setbits32(bcr_addr, BIT(CLK_CTL_BCR_BLK_SHFT));
58 	else
59 		clrbits32(bcr_addr, BIT(CLK_CTL_BCR_BLK_SHFT));
60 }
61 
62 /* Clock GDSC Operations */
enable_and_poll_gdsc_status(void * gdscr_addr)63 enum cb_err enable_and_poll_gdsc_status(void *gdscr_addr)
64 {
65 	if (read32(gdscr_addr) & CLK_CTL_OFF_BMSK)
66 		return CB_SUCCESS;
67 
68 	clrbits32(gdscr_addr, BIT(GDSC_ENABLE_BIT));
69 
70 	/* Ensure gdsc is enabled */
71 	if (!wait_us(100, (read32(gdscr_addr) & CLK_CTL_OFF_BMSK)))
72 		return CB_ERR;
73 
74 	return CB_SUCCESS;
75 }
76 
77 /* Clock Root clock Generator with MND Operations */
clock_configure_mnd(struct clock_rcg * clk,uint32_t m,uint32_t n,uint32_t d_2)78 static void clock_configure_mnd(struct clock_rcg *clk, uint32_t m, uint32_t n,
79 				uint32_t d_2)
80 {
81 	struct clock_rcg_mnd *mnd = (struct clock_rcg_mnd *)clk;
82 
83 	setbits32(&clk->rcg_cfg,
84 			RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT);
85 
86 	write32(&mnd->m, m & CLK_CTL_RCG_MND_BMSK);
87 	write32(&mnd->n, ~(n-m) & CLK_CTL_RCG_MND_BMSK);
88 	write32(&mnd->d_2, ~(d_2) & CLK_CTL_RCG_MND_BMSK);
89 }
90 
91 /* Clock Root clock Generator Operations */
clock_configure(struct clock_rcg * clk,struct clock_freq_config * clk_cfg,uint32_t hz,uint32_t num_perfs)92 enum cb_err clock_configure(struct clock_rcg *clk,
93 			    struct clock_freq_config *clk_cfg, uint32_t hz,
94 			    uint32_t num_perfs)
95 {
96 	uint32_t reg_val, idx;
97 
98 	for (idx = 0; idx < num_perfs; idx++)
99 		if (hz == clk_cfg[idx].hz)
100 			break;
101 
102 	/* Verify we matched an entry.  If not, throw error. */
103 	if (idx >= num_perfs)
104 		die("Failed to find a matching clock frequency (%d hz) for %p!\n",
105 		    hz, clk);
106 
107 	reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) |
108 			(clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT);
109 
110 	/* Set clock config */
111 	write32(&clk->rcg_cfg, reg_val);
112 
113 	if (clk_cfg[idx].m != 0)
114 		clock_configure_mnd(clk, clk_cfg[idx].m, clk_cfg[idx].n,
115 				clk_cfg[idx].d_2);
116 
117 	/* Commit config to RCG */
118 	setbits32(&clk->rcg_cmd, BIT(CLK_CTL_CMD_UPDATE_SHFT));
119 
120 	return CB_SUCCESS;
121 }
122 
123 /* Clock Root clock Generator with DFS Operations */
clock_configure_dfsr_table(int qup,struct clock_freq_config * clk_cfg,uint32_t num_perfs)124 void clock_configure_dfsr_table(int qup, struct clock_freq_config *clk_cfg,
125 		uint32_t num_perfs)
126 {
127 	struct qupv3_clock *qup_clk;
128 	unsigned int idx, s = qup % QUP_WRAP1_S0;
129 	uint32_t reg_val;
130 
131 	qup_clk = qup < QUP_WRAP1_S0 ?
132 				&gcc->qup_wrap0_s[s] : &gcc->qup_wrap1_s[s];
133 
134 	clrsetbits32(&qup_clk->dfsr_clk.cmd_dfsr,
135 			BIT(CLK_CTL_CMD_RCG_SW_CTL_SHFT),
136 			BIT(CLK_CTL_CMD_DFSR_SHFT));
137 
138 	for (idx = 0; idx < num_perfs; idx++) {
139 		reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) |
140 			(clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT);
141 
142 		write32(&qup_clk->dfsr_clk.perf_dfsr[idx], reg_val);
143 
144 		if (clk_cfg[idx].m == 0)
145 			continue;
146 
147 		setbits32(&qup_clk->dfsr_clk.perf_dfsr[idx],
148 				RCG_MODE_DUAL_EDGE << CLK_CTL_CFG_MODE_SHFT);
149 
150 		reg_val = clk_cfg[idx].m & CLK_CTL_RCG_MND_BMSK;
151 		write32(&qup_clk->dfsr_clk.perf_m_dfsr[idx], reg_val);
152 
153 		reg_val = ~(clk_cfg[idx].n - clk_cfg[idx].m)
154 				& CLK_CTL_RCG_MND_BMSK;
155 		write32(&qup_clk->dfsr_clk.perf_n_dfsr[idx], reg_val);
156 
157 		reg_val = ~(clk_cfg[idx].d_2) & CLK_CTL_RCG_MND_BMSK;
158 		write32(&qup_clk->dfsr_clk.perf_d_dfsr[idx], reg_val);
159 	}
160 }
161 
162 /* General Purpose PLL configuration and enable Operations */
clock_configure_enable_gpll(struct alpha_pll_reg_val_config * cfg,bool enable,int br_enable)163 enum cb_err clock_configure_enable_gpll(struct alpha_pll_reg_val_config *cfg,
164 					bool enable, int br_enable)
165 {
166 	if (cfg->l_val)
167 		write32(cfg->reg_l, cfg->l_val);
168 
169 	if (cfg->cal_l_val)
170 		write32(cfg->reg_cal_l, cfg->cal_l_val);
171 
172 	if (cfg->alpha_val)
173 		write32(cfg->reg_alpha, cfg->alpha_val);
174 
175 	if (cfg->user_ctl_val)
176 		write32(cfg->reg_user_ctl, cfg->user_ctl_val);
177 
178 	if (cfg->user_ctl_hi_val)
179 		write32(cfg->reg_user_ctl_hi, cfg->user_ctl_hi_val);
180 
181 	if (cfg->user_ctl_hi1_val)
182 		write32(cfg->reg_user_ctl_hi1, cfg->user_ctl_hi1_val);
183 
184 	if (cfg->config_ctl_val)
185 		write32(cfg->reg_config_ctl, cfg->config_ctl_val);
186 
187 	if (cfg->config_ctl_hi_val)
188 		write32(cfg->reg_config_ctl_hi, cfg->config_ctl_hi_val);
189 
190 	if (cfg->config_ctl_hi1_val)
191 		write32(cfg->reg_config_ctl_hi1, cfg->config_ctl_hi1_val);
192 
193 	if (cfg->fsm_enable)
194 		setbits32(cfg->reg_mode, BIT(PLL_FSM_EN_SHFT));
195 
196 	if (enable) {
197 		setbits32(cfg->reg_opmode, BIT(PLL_STANDBY_MODE));
198 
199 		/*
200 		* H/W requires a 1us delay between placing PLL in STANDBY and
201 		* de-asserting the reset.
202 		*/
203 		udelay(1);
204 		setbits32(cfg->reg_mode, BIT(PLL_RESET_N_SHFT));
205 
206 		/*
207 		* H/W requires a 10us delay between de-asserting the reset and
208 		* enabling the PLL branch bit.
209 		*/
210 		udelay(10);
211 		setbits32(cfg->reg_apcs_pll_br_en, BIT(br_enable));
212 
213 		/* Wait for Lock Detection */
214 		if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) {
215 			printk(BIOS_ERR, "PLL did not lock!\n");
216 			return CB_ERR;
217 		}
218 	}
219 
220 	return CB_SUCCESS;
221 }
222 
agera_pll_enable(struct alpha_pll_reg_val_config * cfg)223 enum cb_err agera_pll_enable(struct alpha_pll_reg_val_config *cfg)
224 {
225 	setbits32(cfg->reg_mode, BIT(PLL_BYPASSNL_SHFT));
226 
227 	/*
228 	* H/W requires a 5us delay between disabling the bypass and
229 	* de-asserting the reset.
230 	*/
231 	udelay(5);
232 	setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT));
233 
234 	if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) {
235 		printk(BIOS_ERR, "CPU PLL did not lock!\n");
236 		return CB_ERR;
237 	}
238 
239 	setbits32(cfg->reg_mode, BIT(PLL_OUTCTRL_SHFT));
240 
241 	return CB_SUCCESS;
242 }
243 
zonda_pll_enable(struct alpha_pll_reg_val_config * cfg)244 enum cb_err zonda_pll_enable(struct alpha_pll_reg_val_config *cfg)
245 {
246 	setbits32(cfg->reg_mode, BIT(PLL_BYPASSNL_SHFT));
247 
248 	/*
249 	* H/W requires a 1us delay between disabling the bypass and
250 	* de-asserting the reset.
251 	*/
252 	udelay(1);
253 	setbits32(cfg->reg_mode, BIT(PLL_RESET_SHFT));
254 	setbits32(cfg->reg_opmode, PLL_RUN_MODE);
255 
256 	if (!wait_us(100, read32(cfg->reg_mode) & PLL_LOCK_DET_BMSK)) {
257 		printk(BIOS_ERR, "CPU PLL did not lock!\n");
258 		return CB_ERR;
259 	}
260 
261 	setbits32(cfg->reg_user_ctl, PLL_USERCTL_BMSK);
262 	setbits32(cfg->reg_mode, BIT(PLL_OUTCTRL_SHFT));
263 
264 	return CB_SUCCESS;
265 }
266 
267 /* Bring subsystem out of RESET */
clock_reset_subsystem(u32 * misc,u32 shft)268 void clock_reset_subsystem(u32 *misc, u32 shft)
269 {
270 	clrbits32(misc, BIT(shft));
271 }
272