• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <types.h>
6 #include <commonlib/helpers.h>
7 #include <soc/clock.h>
8 
9 #define DIV(div) (div ? (2*div - 1) : 0)
10 #define HALF_DIVIDER(div2x)  (div2x ? (div2x - 1) : 0)
11 
12 struct clock_config uart_cfg[] = {
13 	{
14 		.hz = 1843200,
15 		.hw_ctl = 0x0,
16 		.src = SRC_GPLL0_MAIN_800MHZ,
17 		.div = DIV(0),
18 		.m = 36,
19 		.n = 15625,
20 		.d_2 = 15625,
21 	},
22 	{
23 		.hz = 3686400,
24 		.hw_ctl = 0x0,
25 		.src = SRC_GPLL0_MAIN_800MHZ,
26 		.div = DIV(0),
27 		.m = 72,
28 		.n = 15625,
29 		.d_2 = 15625,
30 	}
31 };
32 
33 struct clock_config i2c_cfg[] = {
34 	{
35 		.hz = 19200000,
36 		.hw_ctl = 0x0,
37 		.src = SRC_XO_19_2MHZ,
38 		.div = DIV(0),
39 	},
40 	{
41 		.hz = 50000000,
42 		.hw_ctl = 0x0,
43 		.src = SRC_GPLL0_MAIN_800MHZ,
44 		.div = DIV(32),
45 	}
46 };
47 
48 struct clock_config spi_cfg[] = {
49 	{
50 		.hz = 1000000,
51 		.hw_ctl = 0x0,
52 		.src = SRC_XO_19_2MHZ,
53 		.div = DIV(48),
54 	},
55 	{
56 		.hz = 7372800,
57 		.src = SRC_GPLL0_MAIN_800MHZ,
58 		.div = DIV(1),
59 		.m = 144,
60 		.n = 15625,
61 		.d_2 = 15625,
62 	},
63 	{
64 		.hz = 19200000,
65 		.hw_ctl = 0x0,
66 		.src = SRC_XO_19_2MHZ,
67 		.div = DIV(0),
68 	},
69 	{
70 		.hz = 30000000,
71 		.hw_ctl = 0x0,
72 		.src = SRC_XO_19_2MHZ,
73 		.div = DIV(0),
74 	},
75 	{
76 		.hz = 50000000,
77 		.hw_ctl = 0x0,
78 		.src = SRC_GPLL0_MAIN_800MHZ,
79 		.div = DIV(32),
80 	}
81 };
82 
clock_configure_gpll0(void)83 static int clock_configure_gpll0(void)
84 {
85 	/* Keep existing GPLL0 configuration, in RUN mode @800Mhz. */
86 	setbits32(&gcc->gpll0.user_ctl,
87 			1 << CLK_CTL_GPLL_PLLOUT_LV_EARLY_SHFT |
88 			1 << CLK_CTL_GPLL_PLLOUT_AUX2_SHFT |
89 			1 << CLK_CTL_GPLL_PLLOUT_AUX_SHFT |
90 			1 << CLK_CTL_GPLL_PLLOUT_MAIN_SHFT);
91 	return 0;
92 }
93 
clock_configure_mnd(struct qcs405_clock * clk,uint32_t m,uint32_t n,uint32_t d_2)94 static int clock_configure_mnd(struct qcs405_clock *clk, uint32_t m, uint32_t n,
95 				uint32_t d_2)
96 {
97 	uint32_t reg_val;
98 
99 	/* Configure Root Clock Generator(RCG) for Dual Edge Mode */
100 	reg_val = read32(&clk->rcg.cfg);
101 	reg_val |= (2 << CLK_CTL_CFG_MODE_SHFT);
102 	write32(&clk->rcg.cfg, reg_val);
103 
104 	/* Set M/N/D config */
105 	write32(&clk->m, m & CLK_CTL_RCG_MND_BMSK);
106 	write32(&clk->n, ~(n-m) & CLK_CTL_RCG_MND_BMSK);
107 	write32(&clk->d_2, ~(d_2) & CLK_CTL_RCG_MND_BMSK);
108 
109 	return 0;
110 }
111 
clock_configure(struct qcs405_clock * clk,struct clock_config * clk_cfg,uint32_t hz,uint32_t num_perfs)112 static int clock_configure(struct qcs405_clock *clk,
113 				struct clock_config *clk_cfg,
114 				uint32_t hz, uint32_t num_perfs)
115 {
116 	uint32_t reg_val;
117 	uint32_t idx;
118 
119 	for (idx = 0; idx < num_perfs; idx++)
120 		if (hz <= clk_cfg[idx].hz)
121 			break;
122 
123 	reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) |
124 			(clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT);
125 
126 	/* Set clock config */
127 	write32(&clk->rcg.cfg, reg_val);
128 
129 	if (clk_cfg[idx].m != 0)
130 		clock_configure_mnd(clk, clk_cfg[idx].m, clk_cfg[idx].n,
131 				clk_cfg[idx].d_2);
132 
133 	/* Commit config to RCG*/
134 	setbits32(&clk->rcg.cmd, BIT(CLK_CTL_CMD_UPDATE_SHFT));
135 
136 	return 0;
137 }
138 
clock_is_off(void * cbcr_addr)139 static bool clock_is_off(void *cbcr_addr)
140 {
141 	return (read32(cbcr_addr) & CLK_CTL_CBC_CLK_OFF_BMSK);
142 }
143 
clock_enable_vote(void * cbcr_addr,void * vote_addr,uint32_t vote_bit)144 static int clock_enable_vote(void *cbcr_addr, void *vote_addr,
145 				uint32_t vote_bit)
146 {
147 	/* Set clock vote bit */
148 	setbits32(vote_addr, BIT(vote_bit));
149 
150 	/* Ensure clock is enabled */
151 	while (clock_is_off(cbcr_addr));
152 
153 	return 0;
154 }
155 
clock_enable(void * cbcr_addr)156 static int clock_enable(void *cbcr_addr)
157 {
158 	/* Set clock enable bit */
159 	setbits32(cbcr_addr, BIT(CLK_CTL_CBC_CLK_EN_SHFT));
160 
161 	/* Ensure clock is enabled */
162 	while (clock_is_off(cbcr_addr))
163 		;
164 
165 	return 0;
166 }
167 
clock_disable(void * cbcr_addr)168 static int clock_disable(void *cbcr_addr)
169 {
170 	/* Set clock enable bit */
171 	clrbits32(cbcr_addr, BIT(CLK_CTL_CBC_CLK_EN_SHFT));
172 	return 0;
173 }
174 
clock_reset_bcr(void * bcr_addr,bool reset)175 int clock_reset_bcr(void *bcr_addr, bool reset)
176 {
177 	struct qcs405_bcr *bcr = bcr_addr;
178 
179 	if (reset)
180 		setbits32(&bcr->bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT));
181 	else
182 		clrbits32(&bcr->bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT));
183 
184 	return 0;
185 }
186 
clock_configure_uart(uint32_t hz)187 void clock_configure_uart(uint32_t hz)
188 {
189 	struct qcs405_clock *uart_clk = (struct qcs405_clock *)
190 					&gcc->blsp1_uart2_apps_clk;
191 
192 	clock_configure(uart_clk, uart_cfg, hz, ARRAY_SIZE(uart_cfg));
193 }
194 
clock_configure_spi(int blsp,int qup,uint32_t hz)195 void clock_configure_spi(int blsp, int qup, uint32_t hz)
196 {
197 	struct qcs405_clock *spi_clk = 0;
198 
199 	if (blsp == 1) {
200 		switch (qup) {
201 		case 0:
202 			spi_clk = (struct qcs405_clock *)
203 					&gcc->blsp1_qup0_spi_clk;
204 			break;
205 		case 1:
206 			spi_clk = (struct qcs405_clock *)
207 					&gcc->blsp1_qup1_spi_clk;
208 			break;
209 		case 2:
210 			spi_clk = (struct qcs405_clock *)
211 					&gcc->blsp1_qup2_spi_clk;
212 			break;
213 		case 3:
214 			spi_clk = (struct qcs405_clock *)
215 					&gcc->blsp1_qup3_spi_clk;
216 			break;
217 		case 4:
218 			spi_clk = (struct qcs405_clock *)
219 					&gcc->blsp1_qup4_spi_clk;
220 			break;
221 		default:
222 			printk(BIOS_ERR, "Invalid QUP %d\n", qup);
223 			return;
224 		}
225 	} else if (blsp == 2) {
226 		spi_clk = (struct qcs405_clock *)&gcc->blsp2_qup0_spi_clk;
227 	} else {
228 		printk(BIOS_ERR, "BLSP %d not supported\n", blsp);
229 		return;
230 	}
231 
232 	clock_configure(spi_clk, spi_cfg, hz, ARRAY_SIZE(spi_cfg));
233 }
234 
clock_configure_i2c(uint32_t hz)235 void clock_configure_i2c(uint32_t hz)
236 {
237 	struct qcs405_clock *i2c_clk =
238 			(struct qcs405_clock *)&gcc->blsp1_qup1_i2c_clk;
239 
240 	clock_configure(i2c_clk, i2c_cfg, hz, ARRAY_SIZE(i2c_cfg));
241 }
242 
clock_enable_uart(void)243 void clock_enable_uart(void)
244 {
245 	clock_enable(&gcc->blsp1_uart2_apps_cbcr);
246 }
247 
clock_disable_uart(void)248 void clock_disable_uart(void)
249 {
250 	clock_disable(&gcc->blsp1_uart2_apps_cbcr);
251 }
252 
clock_enable_spi(int blsp,int qup)253 void clock_enable_spi(int blsp, int qup)
254 {
255 	if (blsp == 1) {
256 		switch (qup) {
257 		case 0:
258 			clock_enable(&gcc->blsp1_qup0_spi_apps_cbcr);
259 			break;
260 		case 1:
261 			clock_enable(&gcc->blsp1_qup1_spi_apps_cbcr);
262 			break;
263 		case 2:
264 			clock_enable(&gcc->blsp1_qup2_spi_apps_cbcr);
265 			break;
266 		case 3:
267 			clock_enable(&gcc->blsp1_qup3_spi_apps_cbcr);
268 			break;
269 		case 4:
270 			clock_enable(&gcc->blsp1_qup4_spi_apps_cbcr);
271 			break;
272 		}
273 	} else if (blsp == 2)
274 		clock_enable(&gcc->blsp2_qup0_spi_apps_cbcr);
275 	else
276 		printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
277 }
278 
clock_disable_spi(int blsp,int qup)279 void clock_disable_spi(int blsp, int qup)
280 {
281 	if (blsp == 1) {
282 		switch (qup) {
283 		case 0:
284 			clock_enable(&gcc->blsp1_qup0_spi_apps_cbcr);
285 			break;
286 		case 1:
287 			clock_enable(&gcc->blsp1_qup1_spi_apps_cbcr);
288 			break;
289 		case 2:
290 			clock_enable(&gcc->blsp1_qup2_spi_apps_cbcr);
291 			break;
292 		case 3:
293 			clock_enable(&gcc->blsp1_qup3_spi_apps_cbcr);
294 			break;
295 		case 4:
296 			clock_enable(&gcc->blsp1_qup4_spi_apps_cbcr);
297 			break;
298 		}
299 	} else if (blsp == 2)
300 		clock_enable(&gcc->blsp2_qup0_spi_apps_cbcr);
301 	else
302 		printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
303 }
304 
clock_enable_i2c(void)305 void clock_enable_i2c(void)
306 {
307 	clock_enable(&gcc->blsp1_qup1_i2c_apps_cbcr);
308 }
309 
clock_disable_i2c(void)310 void clock_disable_i2c(void)
311 {
312 	clock_disable(&gcc->blsp1_qup1_i2c_apps_cbcr);
313 }
314 
clock_init(void)315 void clock_init(void)
316 {
317 	clock_configure_gpll0();
318 	clock_enable_vote(&gcc->blsp1_ahb_cbcr,
319 				&gcc->gcc_apcs_clock_branch_en_vote,
320 				BLSP1_AHB_CLK_ENA);
321 
322 	clock_enable_vote(&gcc->blsp2_ahb_cbcr,
323 				&gcc->gcc_apcs_clock_branch_en_vote,
324 				BLSP2_AHB_CLK_ENA);
325 }
326