coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
clock.c
Go to the documentation of this file.
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 
83 static int clock_configure_gpll0(void)
84 {
85  /* Keep existing GPLL0 configuration, in RUN mode @800Mhz. */
91  return 0;
92 }
93 
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 
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*/
135 
136  return 0;
137 }
138 
139 static bool clock_is_off(void *cbcr_addr)
140 {
141  return (read32(cbcr_addr) & CLK_CTL_CBC_CLK_OFF_BMSK);
142 }
143 
144 static int clock_enable_vote(void *cbcr_addr, void *vote_addr,
145  uint32_t vote_bit)
146 {
147 
148  /* Set clock vote bit */
149  setbits32(vote_addr, BIT(vote_bit));
150 
151  /* Ensure clock is enabled */
152  while (clock_is_off(cbcr_addr));
153 
154  return 0;
155 }
156 
157 static int clock_enable(void *cbcr_addr)
158 {
159 
160  /* Set clock enable bit */
162 
163  /* Ensure clock is enabled */
164  while (clock_is_off(cbcr_addr))
165  ;
166 
167  return 0;
168 }
169 
170 static int clock_disable(void *cbcr_addr)
171 {
172 
173  /* Set clock enable bit */
175  return 0;
176 }
177 
178 int clock_reset_bcr(void *bcr_addr, bool reset)
179 {
180  struct qcs405_bcr *bcr = bcr_addr;
181 
182  if (reset)
184  else
186 
187  return 0;
188 }
189 
191 {
192  struct qcs405_clock *uart_clk = (struct qcs405_clock *)
194 
195  clock_configure(uart_clk, uart_cfg, hz, ARRAY_SIZE(uart_cfg));
196 }
197 
198 void clock_configure_spi(int blsp, int qup, uint32_t hz)
199 {
200  struct qcs405_clock *spi_clk = 0;
201 
202  if (blsp == 1) {
203  switch (qup) {
204  case 0:
205  spi_clk = (struct qcs405_clock *)
207  break;
208  case 1:
209  spi_clk = (struct qcs405_clock *)
211  break;
212  case 2:
213  spi_clk = (struct qcs405_clock *)
215  break;
216  case 3:
217  spi_clk = (struct qcs405_clock *)
219  break;
220  case 4:
221  spi_clk = (struct qcs405_clock *)
223  break;
224  default:
225  printk(BIOS_ERR, "Invalid QUP %d\n", qup);
226  return;
227  }
228  } else if (blsp == 2) {
229  spi_clk = (struct qcs405_clock *)&gcc->blsp2_qup0_spi_clk;
230  } else {
231  printk(BIOS_ERR, "BLSP %d not supported\n", blsp);
232  return;
233  }
234 
235  clock_configure(spi_clk, spi_cfg, hz, ARRAY_SIZE(spi_cfg));
236 }
237 
239 {
240  struct qcs405_clock *i2c_clk =
241  (struct qcs405_clock *)&gcc->blsp1_qup1_i2c_clk;
242 
243  clock_configure(i2c_clk, i2c_cfg, hz, ARRAY_SIZE(i2c_cfg));
244 }
245 
247 {
249 }
250 
252 {
254 }
255 
256 void clock_enable_spi(int blsp, int qup)
257 {
258  if (blsp == 1) {
259  switch (qup) {
260  case 0:
262  break;
263  case 1:
265  break;
266  case 2:
268  break;
269  case 3:
271  break;
272  case 4:
274  break;
275  }
276  } else if (blsp == 2)
278  else
279  printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
280 }
281 
282 void clock_disable_spi(int blsp, int qup)
283 {
284  if (blsp == 1) {
285  switch (qup) {
286  case 0:
288  break;
289  case 1:
291  break;
292  case 2:
294  break;
295  case 3:
297  break;
298  case 4:
300  break;
301  }
302  } else if (blsp == 2)
304  else
305  printk(BIOS_ERR, "BLSP%d not supported\n", blsp);
306 
307 }
308 
310 {
312 }
313 
315 {
317 }
318 
319 void clock_init(void)
320 {
325 
329 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
@ CLK_CTL_RCG_MND_BMSK
Definition: clock_common.h:123
@ CLK_CTL_CFG_SRC_DIV_SHFT
Definition: clock_common.h:104
@ CLK_CTL_CFG_MODE_SHFT
Definition: clock_common.h:106
@ CLK_CTL_CFG_SRC_SEL_SHFT
Definition: clock_common.h:105
@ CLK_CTL_CMD_UPDATE_SHFT
Definition: clock_common.h:110
#define printk(level,...)
Definition: stdlib.h:16
#define BIT(nr)
Definition: ec_commands.h:45
#define setbits32(addr, set)
Definition: mmio.h:21
#define clrbits32(addr, clear)
Definition: mmio.h:26
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
void clock_init(void)
Definition: clock.c:539
enum cb_err clock_enable(void *cbcr_addr)
Definition: clock.c:35
enum cb_err clock_configure(struct clock_rcg *clk, struct clock_freq_config *clk_cfg, uint32_t hz, uint32_t num_perfs)
Definition: clock.c:92
void clock_reset_bcr(void *bcr_addr, bool assert)
Definition: clock.c:54
enum cb_err clock_enable_vote(void *cbcr_addr, void *vote_addr, uint32_t vote_bit)
Definition: clock.c:17
void clock_enable_i2c(void)
Definition: clock.c:309
void clock_disable_spi(int blsp, int qup)
Definition: clock.c:282
#define DIV(div)
Definition: clock.c:9
static int clock_disable(void *cbcr_addr)
Definition: clock.c:170
void clock_configure_spi(int blsp, int qup, uint32_t hz)
Definition: clock.c:198
void clock_enable_spi(int blsp, int qup)
Definition: clock.c:256
void clock_disable_uart(void)
Definition: clock.c:251
static int clock_configure_mnd(struct qcs405_clock *clk, uint32_t m, uint32_t n, uint32_t d_2)
Definition: clock.c:94
void clock_disable_i2c(void)
Definition: clock.c:314
void clock_configure_i2c(uint32_t hz)
Definition: clock.c:238
void clock_enable_uart(void)
Definition: clock.c:246
struct clock_config uart_cfg[]
Definition: clock.c:12
void clock_configure_uart(uint32_t hz)
Definition: clock.c:190
static int clock_configure_gpll0(void)
Definition: clock.c:83
struct clock_config i2c_cfg[]
Definition: clock.c:33
static bool clock_is_off(void *cbcr_addr)
Definition: clock.c:139
#define BLSP1_AHB_CLK_ENA
Definition: clock.h:8
@ CLK_CTL_GPLL_PLLOUT_MAIN_SHFT
Definition: clock.h:117
@ CLK_CTL_GPLL_PLLOUT_LV_EARLY_SHFT
Definition: clock.h:114
@ CLK_CTL_GPLL_PLLOUT_AUX_SHFT
Definition: clock.h:116
@ CLK_CTL_GPLL_PLLOUT_AUX2_SHFT
Definition: clock.h:115
@ CLK_CTL_BCR_BLK_ARES_SHFT
Definition: clock.h:152
@ CLK_CTL_CBC_CLK_EN_SHFT
Definition: clock.h:142
@ CLK_CTL_CBC_CLK_OFF_BMSK
Definition: clock.h:139
#define SRC_XO_19_2MHZ
Definition: clock.h:10
#define SRC_GPLL0_MAIN_800MHZ
Definition: clock.h:11
#define BLSP2_AHB_CLK_ENA
Definition: clock.h:9
static struct qcs405_gcc *const gcc
Definition: clock.h:165
unsigned int uint32_t
Definition: stdint.h:14
uint32_t hz
Definition: clock.h:156
uint32_t div
Definition: clock.h:159
uint32_t src
Definition: clock.h:158
uint32_t n
Definition: clock.h:161
uint32_t d_2
Definition: clock.h:162
uint32_t bcr
Definition: clock.h:36
uint32_t m
Definition: clock.h:30
struct qcs405_rcg rcg
Definition: clock.h:29
uint32_t n
Definition: clock.h:31
uint32_t d_2
Definition: clock.h:32
u32 blsp1_ahb_cbcr
Definition: clock.h:55
u32 blsp1_qup1_spi_apps_cbcr
Definition: clock.h:59
struct qcs405_clock blsp1_uart2_apps_clk
Definition: clock.h:72
u32 gcc_apcs_clock_branch_en_vote
Definition: clock.h:100
u32 blsp1_qup4_spi_apps_cbcr
Definition: clock.h:80
struct qcs405_clock blsp1_qup3_spi_clk
Definition: clock.h:77
u32 blsp2_qup0_spi_apps_cbcr
Definition: clock.h:94
struct qcs405_clock blsp2_qup0_spi_clk
Definition: clock.h:96
struct qcs405_clock blsp1_qup2_spi_clk
Definition: clock.h:68
u32 blsp1_qup1_i2c_apps_cbcr
Definition: clock.h:60
struct qcs405_clock blsp1_qup1_spi_clk
Definition: clock.h:63
struct qcs405_clock blsp1_qup4_spi_clk
Definition: clock.h:82
struct qcs405_gpll gpll0
Definition: clock.h:98
u32 blsp1_qup0_spi_apps_cbcr
Definition: clock.h:85
struct qcs405_clock blsp1_qup0_spi_clk
Definition: clock.h:87
struct qcs405_clock blsp1_qup1_i2c_clk
Definition: clock.h:61
u32 blsp1_qup3_spi_apps_cbcr
Definition: clock.h:75
u32 blsp2_ahb_cbcr
Definition: clock.h:91
u32 blsp1_qup2_spi_apps_cbcr
Definition: clock.h:66
u32 blsp1_uart2_apps_cbcr
Definition: clock.h:70
u32 user_ctl
Definition: clock.h:44
u32 cfg
Definition: clock.h:25
u32 cmd
Definition: clock.h:24
static void __noreturn reset(void)
#define m(clkreg, src_bits, pmcreg, dst_bits)