soc: Remove copyright notices
[coreboot.git] / src / soc / qualcomm / qcs405 / clock.c
blobe2e03c3e3280b56586e7d4c56798411db34a5acf
1 /* This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <console/console.h>
15 #include <device/mmio.h>
16 #include <types.h>
17 #include <commonlib/helpers.h>
18 #include <soc/clock.h>
20 #define DIV(div) (div ? (2*div - 1) : 0)
21 #define HALF_DIVIDER(div2x) (div2x ? (div2x - 1) : 0)
23 struct clock_config uart_cfg[] = {
25 .hz = 1843200,
26 .hw_ctl = 0x0,
27 .src = SRC_GPLL0_MAIN_800MHZ,
28 .div = DIV(0),
29 .m = 36,
30 .n = 15625,
31 .d_2 = 15625,
34 .hz = 3686400,
35 .hw_ctl = 0x0,
36 .src = SRC_GPLL0_MAIN_800MHZ,
37 .div = DIV(0),
38 .m = 72,
39 .n = 15625,
40 .d_2 = 15625,
44 struct clock_config i2c_cfg[] = {
46 .hz = 19200000,
47 .hw_ctl = 0x0,
48 .src = SRC_XO_19_2MHZ,
49 .div = DIV(0),
52 .hz = 50000000,
53 .hw_ctl = 0x0,
54 .src = SRC_GPLL0_MAIN_800MHZ,
55 .div = DIV(32),
59 struct clock_config spi_cfg[] = {
61 .hz = 1000000,
62 .hw_ctl = 0x0,
63 .src = SRC_XO_19_2MHZ,
64 .div = DIV(48),
67 .hz = 7372800,
68 .src = SRC_GPLL0_MAIN_800MHZ,
69 .div = DIV(1),
70 .m = 144,
71 .n = 15625,
72 .d_2 = 15625,
75 .hz = 19200000,
76 .hw_ctl = 0x0,
77 .src = SRC_XO_19_2MHZ,
78 .div = DIV(0),
81 .hz = 30000000,
82 .hw_ctl = 0x0,
83 .src = SRC_XO_19_2MHZ,
84 .div = DIV(0),
87 .hz = 50000000,
88 .hw_ctl = 0x0,
89 .src = SRC_GPLL0_MAIN_800MHZ,
90 .div = DIV(32),
94 static int clock_configure_gpll0(void)
96 /* Keep existing GPLL0 configuration, in RUN mode @800Mhz. */
97 setbits32(&gcc->gpll0.user_ctl,
98 1 << CLK_CTL_GPLL_PLLOUT_LV_EARLY_SHFT |
99 1 << CLK_CTL_GPLL_PLLOUT_AUX2_SHFT |
100 1 << CLK_CTL_GPLL_PLLOUT_AUX_SHFT |
101 1 << CLK_CTL_GPLL_PLLOUT_MAIN_SHFT);
102 return 0;
105 static int clock_configure_mnd(struct qcs405_clock *clk, uint32_t m, uint32_t n,
106 uint32_t d_2)
108 uint32_t reg_val;
110 /* Configure Root Clock Generator(RCG) for Dual Edge Mode */
111 reg_val = read32(&clk->rcg.cfg);
112 reg_val |= (2 << CLK_CTL_CFG_MODE_SHFT);
113 write32(&clk->rcg.cfg, reg_val);
115 /* Set M/N/D config */
116 write32(&clk->m, m & CLK_CTL_RCG_MND_BMSK);
117 write32(&clk->n, ~(n-m) & CLK_CTL_RCG_MND_BMSK);
118 write32(&clk->d_2, ~(d_2) & CLK_CTL_RCG_MND_BMSK);
120 return 0;
123 static int clock_configure(struct qcs405_clock *clk,
124 struct clock_config *clk_cfg,
125 uint32_t hz, uint32_t num_perfs)
127 uint32_t reg_val;
128 uint32_t idx;
130 for (idx = 0; idx < num_perfs; idx++)
131 if (hz <= clk_cfg[idx].hz)
132 break;
134 reg_val = (clk_cfg[idx].src << CLK_CTL_CFG_SRC_SEL_SHFT) |
135 (clk_cfg[idx].div << CLK_CTL_CFG_SRC_DIV_SHFT);
137 /* Set clock config */
138 write32(&clk->rcg.cfg, reg_val);
140 if (clk_cfg[idx].m != 0)
141 clock_configure_mnd(clk, clk_cfg[idx].m, clk_cfg[idx].n,
142 clk_cfg[idx].d_2);
144 /* Commit config to RCG*/
145 setbits32(&clk->rcg.cmd, BIT(CLK_CTL_CMD_UPDATE_SHFT));
147 return 0;
150 static bool clock_is_off(void *cbcr_addr)
152 return (read32(cbcr_addr) & CLK_CTL_CBC_CLK_OFF_BMSK);
155 static int clock_enable_vote(void *cbcr_addr, void *vote_addr,
156 uint32_t vote_bit)
159 /* Set clock vote bit */
160 setbits32(vote_addr, BIT(vote_bit));
162 /* Ensure clock is enabled */
163 while (clock_is_off(cbcr_addr));
165 return 0;
168 static int clock_enable(void *cbcr_addr)
171 /* Set clock enable bit */
172 setbits32(cbcr_addr, BIT(CLK_CTL_CBC_CLK_EN_SHFT));
174 /* Ensure clock is enabled */
175 while (clock_is_off(cbcr_addr))
178 return 0;
181 static int clock_disable(void *cbcr_addr)
184 /* Set clock enable bit */
185 clrbits32(cbcr_addr, BIT(CLK_CTL_CBC_CLK_EN_SHFT));
186 return 0;
189 int clock_reset_bcr(void *bcr_addr, bool reset)
191 struct qcs405_bcr *bcr = bcr_addr;
193 if (reset)
194 setbits32(&bcr->bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT));
195 else
196 clrbits32(&bcr->bcr, BIT(CLK_CTL_BCR_BLK_ARES_SHFT));
198 return 0;
201 void clock_configure_uart(uint32_t hz)
203 struct qcs405_clock *uart_clk = (struct qcs405_clock *)
204 &gcc->blsp1_uart2_apps_clk;
206 clock_configure(uart_clk, uart_cfg, hz, ARRAY_SIZE(uart_cfg));
209 void clock_configure_spi(int blsp, int qup, uint32_t hz)
211 struct qcs405_clock *spi_clk = 0;
213 if (blsp == 1) {
214 switch (qup) {
215 case 0:
216 spi_clk = (struct qcs405_clock *)
217 &gcc->blsp1_qup0_spi_clk;
218 break;
219 case 1:
220 spi_clk = (struct qcs405_clock *)
221 &gcc->blsp1_qup1_spi_clk;
222 break;
223 case 2:
224 spi_clk = (struct qcs405_clock *)
225 &gcc->blsp1_qup2_spi_clk;
226 break;
227 case 3:
228 spi_clk = (struct qcs405_clock *)
229 &gcc->blsp1_qup3_spi_clk;
230 break;
231 case 4:
232 spi_clk = (struct qcs405_clock *)
233 &gcc->blsp1_qup4_spi_clk;
234 break;
235 default:
236 printk(BIOS_ERR, "Invalid QUP %d\n", qup);
237 return;
239 } else if (blsp == 2) {
240 spi_clk = (struct qcs405_clock *)&gcc->blsp2_qup0_spi_clk;
241 } else {
242 printk(BIOS_ERR, "BLSP %d not supported\n", blsp);
243 return;
246 clock_configure(spi_clk, spi_cfg, hz, ARRAY_SIZE(spi_cfg));
249 void clock_configure_i2c(uint32_t hz)
251 struct qcs405_clock *i2c_clk =
252 (struct qcs405_clock *)&gcc->blsp1_qup1_i2c_clk;
254 clock_configure(i2c_clk, i2c_cfg, hz, ARRAY_SIZE(i2c_cfg));
257 void clock_enable_uart(void)
259 clock_enable(&gcc->blsp1_uart2_apps_cbcr);
262 void clock_disable_uart(void)
264 clock_disable(&gcc->blsp1_uart2_apps_cbcr);
267 void clock_enable_spi(int blsp, int qup)
269 if (blsp == 1) {
270 switch (qup) {
271 case 0:
272 clock_enable(&gcc->blsp1_qup0_spi_apps_cbcr);
273 break;
274 case 1:
275 clock_enable(&gcc->blsp1_qup1_spi_apps_cbcr);
276 break;
277 case 2:
278 clock_enable(&gcc->blsp1_qup2_spi_apps_cbcr);
279 break;
280 case 3:
281 clock_enable(&gcc->blsp1_qup3_spi_apps_cbcr);
282 break;
283 case 4:
284 clock_enable(&gcc->blsp1_qup4_spi_apps_cbcr);
285 break;
287 } else if (blsp == 2)
288 clock_enable(&gcc->blsp2_qup0_spi_apps_cbcr);
289 else
290 printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
293 void clock_disable_spi(int blsp, int qup)
295 if (blsp == 1) {
296 switch (qup) {
297 case 0:
298 clock_enable(&gcc->blsp1_qup0_spi_apps_cbcr);
299 break;
300 case 1:
301 clock_enable(&gcc->blsp1_qup1_spi_apps_cbcr);
302 break;
303 case 2:
304 clock_enable(&gcc->blsp1_qup2_spi_apps_cbcr);
305 break;
306 case 3:
307 clock_enable(&gcc->blsp1_qup3_spi_apps_cbcr);
308 break;
309 case 4:
310 clock_enable(&gcc->blsp1_qup4_spi_apps_cbcr);
311 break;
313 } else if (blsp == 2)
314 clock_enable(&gcc->blsp2_qup0_spi_apps_cbcr);
315 else
316 printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
320 void clock_enable_i2c(void)
322 clock_enable(&gcc->blsp1_qup1_i2c_apps_cbcr);
325 void clock_disable_i2c(void)
327 clock_disable(&gcc->blsp1_qup1_i2c_apps_cbcr);
330 void clock_init(void)
332 clock_configure_gpll0();
333 clock_enable_vote(&gcc->blsp1_ahb_cbcr,
334 &gcc->gcc_apcs_clock_branch_en_vote,
335 BLSP1_AHB_CLK_ENA);
337 clock_enable_vote(&gcc->blsp2_ahb_cbcr,
338 &gcc->gcc_apcs_clock_branch_en_vote,
339 BLSP2_AHB_CLK_ENA);