1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
5 #include <device/mmio.h>
7 #include <commonlib/helpers.h>
10 #define DIV(div) (div ? (2*div - 1) : 0)
11 #define HALF_DIVIDER(div2x) (div2x ? (div2x - 1) : 0)
13 struct clock_config uart_cfg
[] = {
17 .src
= SRC_GPLL0_MAIN_800MHZ
,
26 .src
= SRC_GPLL0_MAIN_800MHZ
,
34 struct clock_config i2c_cfg
[] = {
38 .src
= SRC_XO_19_2MHZ
,
44 .src
= SRC_GPLL0_MAIN_800MHZ
,
49 struct clock_config spi_cfg
[] = {
53 .src
= SRC_XO_19_2MHZ
,
58 .src
= SRC_GPLL0_MAIN_800MHZ
,
67 .src
= SRC_XO_19_2MHZ
,
73 .src
= SRC_XO_19_2MHZ
,
79 .src
= SRC_GPLL0_MAIN_800MHZ
,
84 static int clock_configure_gpll0(void)
86 /* Keep existing GPLL0 configuration, in RUN mode @800Mhz. */
87 setbits32(&gcc
->gpll0
.user_ctl
,
88 1 << CLK_CTL_GPLL_PLLOUT_LV_EARLY_SHFT
|
89 1 << CLK_CTL_GPLL_PLLOUT_AUX2_SHFT
|
90 1 << CLK_CTL_GPLL_PLLOUT_AUX_SHFT
|
91 1 << CLK_CTL_GPLL_PLLOUT_MAIN_SHFT
);
95 static int clock_configure_mnd(struct qcs405_clock
*clk
, uint32_t m
, uint32_t n
,
100 /* Configure Root Clock Generator(RCG) for Dual Edge Mode */
101 reg_val
= read32(&clk
->rcg
.cfg
);
102 reg_val
|= (2 << CLK_CTL_CFG_MODE_SHFT
);
103 write32(&clk
->rcg
.cfg
, reg_val
);
105 /* Set M/N/D config */
106 write32(&clk
->m
, m
& CLK_CTL_RCG_MND_BMSK
);
107 write32(&clk
->n
, ~(n
-m
) & CLK_CTL_RCG_MND_BMSK
);
108 write32(&clk
->d_2
, ~(d_2
) & CLK_CTL_RCG_MND_BMSK
);
113 static int clock_configure(struct qcs405_clock
*clk
,
114 struct clock_config
*clk_cfg
,
115 uint32_t hz
, uint32_t num_perfs
)
120 for (idx
= 0; idx
< num_perfs
; idx
++)
121 if (hz
<= clk_cfg
[idx
].hz
)
124 reg_val
= (clk_cfg
[idx
].src
<< CLK_CTL_CFG_SRC_SEL_SHFT
) |
125 (clk_cfg
[idx
].div
<< CLK_CTL_CFG_SRC_DIV_SHFT
);
127 /* Set clock config */
128 write32(&clk
->rcg
.cfg
, reg_val
);
130 if (clk_cfg
[idx
].m
!= 0)
131 clock_configure_mnd(clk
, clk_cfg
[idx
].m
, clk_cfg
[idx
].n
,
134 /* Commit config to RCG*/
135 setbits32(&clk
->rcg
.cmd
, BIT(CLK_CTL_CMD_UPDATE_SHFT
));
140 static bool clock_is_off(void *cbcr_addr
)
142 return (read32(cbcr_addr
) & CLK_CTL_CBC_CLK_OFF_BMSK
);
145 static int clock_enable_vote(void *cbcr_addr
, void *vote_addr
,
149 /* Set clock vote bit */
150 setbits32(vote_addr
, BIT(vote_bit
));
152 /* Ensure clock is enabled */
153 while (clock_is_off(cbcr_addr
));
158 static int clock_enable(void *cbcr_addr
)
161 /* Set clock enable bit */
162 setbits32(cbcr_addr
, BIT(CLK_CTL_CBC_CLK_EN_SHFT
));
164 /* Ensure clock is enabled */
165 while (clock_is_off(cbcr_addr
))
171 static int clock_disable(void *cbcr_addr
)
174 /* Set clock enable bit */
175 clrbits32(cbcr_addr
, BIT(CLK_CTL_CBC_CLK_EN_SHFT
));
179 int clock_reset_bcr(void *bcr_addr
, bool reset
)
181 struct qcs405_bcr
*bcr
= bcr_addr
;
184 setbits32(&bcr
->bcr
, BIT(CLK_CTL_BCR_BLK_ARES_SHFT
));
186 clrbits32(&bcr
->bcr
, BIT(CLK_CTL_BCR_BLK_ARES_SHFT
));
191 void clock_configure_uart(uint32_t hz
)
193 struct qcs405_clock
*uart_clk
= (struct qcs405_clock
*)
194 &gcc
->blsp1_uart2_apps_clk
;
196 clock_configure(uart_clk
, uart_cfg
, hz
, ARRAY_SIZE(uart_cfg
));
199 void clock_configure_spi(int blsp
, int qup
, uint32_t hz
)
201 struct qcs405_clock
*spi_clk
= 0;
206 spi_clk
= (struct qcs405_clock
*)
207 &gcc
->blsp1_qup0_spi_clk
;
210 spi_clk
= (struct qcs405_clock
*)
211 &gcc
->blsp1_qup1_spi_clk
;
214 spi_clk
= (struct qcs405_clock
*)
215 &gcc
->blsp1_qup2_spi_clk
;
218 spi_clk
= (struct qcs405_clock
*)
219 &gcc
->blsp1_qup3_spi_clk
;
222 spi_clk
= (struct qcs405_clock
*)
223 &gcc
->blsp1_qup4_spi_clk
;
226 printk(BIOS_ERR
, "Invalid QUP %d\n", qup
);
229 } else if (blsp
== 2) {
230 spi_clk
= (struct qcs405_clock
*)&gcc
->blsp2_qup0_spi_clk
;
232 printk(BIOS_ERR
, "BLSP %d not supported\n", blsp
);
236 clock_configure(spi_clk
, spi_cfg
, hz
, ARRAY_SIZE(spi_cfg
));
239 void clock_configure_i2c(uint32_t hz
)
241 struct qcs405_clock
*i2c_clk
=
242 (struct qcs405_clock
*)&gcc
->blsp1_qup1_i2c_clk
;
244 clock_configure(i2c_clk
, i2c_cfg
, hz
, ARRAY_SIZE(i2c_cfg
));
247 void clock_enable_uart(void)
249 clock_enable(&gcc
->blsp1_uart2_apps_cbcr
);
252 void clock_disable_uart(void)
254 clock_disable(&gcc
->blsp1_uart2_apps_cbcr
);
257 void clock_enable_spi(int blsp
, int qup
)
262 clock_enable(&gcc
->blsp1_qup0_spi_apps_cbcr
);
265 clock_enable(&gcc
->blsp1_qup1_spi_apps_cbcr
);
268 clock_enable(&gcc
->blsp1_qup2_spi_apps_cbcr
);
271 clock_enable(&gcc
->blsp1_qup3_spi_apps_cbcr
);
274 clock_enable(&gcc
->blsp1_qup4_spi_apps_cbcr
);
277 } else if (blsp
== 2)
278 clock_enable(&gcc
->blsp2_qup0_spi_apps_cbcr
);
280 printk(BIOS_ERR
, "BLSP%d not supported\n", blsp
);
283 void clock_disable_spi(int blsp
, int qup
)
288 clock_enable(&gcc
->blsp1_qup0_spi_apps_cbcr
);
291 clock_enable(&gcc
->blsp1_qup1_spi_apps_cbcr
);
294 clock_enable(&gcc
->blsp1_qup2_spi_apps_cbcr
);
297 clock_enable(&gcc
->blsp1_qup3_spi_apps_cbcr
);
300 clock_enable(&gcc
->blsp1_qup4_spi_apps_cbcr
);
303 } else if (blsp
== 2)
304 clock_enable(&gcc
->blsp2_qup0_spi_apps_cbcr
);
306 printk(BIOS_ERR
, "BLSP%d not supported\n", blsp
);
310 void clock_enable_i2c(void)
312 clock_enable(&gcc
->blsp1_qup1_i2c_apps_cbcr
);
315 void clock_disable_i2c(void)
317 clock_disable(&gcc
->blsp1_qup1_i2c_apps_cbcr
);
320 void clock_init(void)
322 clock_configure_gpll0();
323 clock_enable_vote(&gcc
->blsp1_ahb_cbcr
,
324 &gcc
->gcc_apcs_clock_branch_en_vote
,
327 clock_enable_vote(&gcc
->blsp2_ahb_cbcr
,
328 &gcc
->gcc_apcs_clock_branch_en_vote
,