coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pll.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <assert.h>
5 #include <soc/pll.h>
6 #include <types.h>
7 
8 void mux_set_sel(const struct mux *mux, u32 sel)
9 {
10  u32 mask = GENMASK(mux->mux_width - 1, 0);
11  u32 val = read32(mux->reg);
12 
13  if (mux->set_reg && mux->clr_reg) {
15  write32(mux->set_reg, sel << mux->mux_shift);
16  } else {
17  val &= ~(mask << mux->mux_shift);
18  val |= (sel & mask) << mux->mux_shift;
19  write32(mux->reg, val);
20  }
21 
22  if (mux->upd_reg)
23  write32(mux->upd_reg, 1 << mux->upd_shift);
24 }
25 
26 static void pll_calc_values(const struct pll *pll, u32 *pcw, u32 *postdiv,
27  u32 freq)
28 {
29  const u32 fin_hz = CLK26M_HZ;
30  const u32 *div_rate = pll->div_rate;
31  u32 val;
32 
33  assert(freq <= div_rate[0]);
34  assert(freq >= 1 * GHz / 16);
35 
36  for (val = 1; div_rate[val] != 0; val++) {
37  if (freq > div_rate[val])
38  break;
39  }
40  val--;
41  *postdiv = val;
42 
43  /* _pcw = freq * 2^postdiv / fin * 2^pcwbits_fractional */
45 
46  *pcw = ((u64)freq << val) / fin_hz;
47 }
48 
49 static void pll_set_rate_regs(const struct pll *pll, u32 pcw, u32 postdiv)
50 {
51  u32 val;
52 
53  /* set postdiv */
54  val = read32(pll->div_reg);
56  val |= postdiv << pll->div_shift;
57 
58  /* set postdiv and pcw at the same time if on the same register */
59  if (pll->div_reg != pll->pcw_reg) {
61  val = read32(pll->pcw_reg);
62  }
63 
64  /* set pcw */
66  val |= pcw << pll->pcw_shift;
68 
70 }
71 
72 int pll_set_rate(const struct pll *pll, u32 rate)
73 {
74  u32 pcw, postdiv;
75 
76  pll_calc_values(pll, &pcw, &postdiv, rate);
77  pll_set_rate_regs(pll, pcw, postdiv);
78 
79  return 0;
80 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define assert(statement)
Definition: assert.h:74
#define GHz
Definition: helpers.h:81
#define GENMASK(high, low)
Definition: helpers.h:58
void mux_set_sel(const struct mux *mux, u32 sel)
Definition: pll.c:8
int pll_set_rate(const struct pll *pll, u32 rate)
Definition: pll.c:72
static void pll_set_rate_regs(const struct pll *pll, u32 pcw, u32 postdiv)
Definition: pll.c:49
static void pll_calc_values(const struct pll *pll, u32 *pcw, u32 *postdiv, u32 freq)
Definition: pll.c:26
@ CLK26M_HZ
Definition: pll.h:215
@ PCW_INTEGER_BITS
Definition: pll.h:188
void pll_set_pcw_change(const struct pll *pll)
Definition: pll.c:284
#define PLL_POSTDIV_MASK
Definition: pll_common.h:20
static const int mask[4]
Definition: gpio.c:308
uint64_t u64
Definition: stdint.h:54
uint32_t u32
Definition: stdint.h:51
Definition: dw_i2c.c:39
Definition: pll_common.h:22
u8 mux_width
Definition: pll_common.h:28
void * reg
Definition: pll_common.h:23
void * clr_reg
Definition: pll_common.h:25
void * set_reg
Definition: pll_common.h:24
void * upd_reg
Definition: pll_common.h:26
u8 mux_shift
Definition: pll_common.h:27
u8 upd_shift
Definition: pll_common.h:29
Definition: pll_common.h:32
u8 div_shift
Definition: pll_common.h:40
u8 pcw_shift
Definition: pll_common.h:41
const u32 * div_rate
Definition: pll_common.h:37
u8 pcwbits
Definition: pll_common.h:39
void * div_reg
Definition: pll_common.h:35
void * pcw_reg
Definition: pll_common.h:36
Definition: pll.c:262
u8 val
Definition: sys.c:300