coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
lcc.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 
3 #include <stdint.h>
4 #include <delay.h>
5 #include <console/console.h>
6 #include <soc/clock.h>
7 #include <soc/lcc-reg.h>
8 #include <device/mmio.h>
9 
10 typedef struct {
15  void *lcc_pll_regs;
16 } IpqLccClocks;
17 
18 typedef struct __packed {
21 
22 typedef struct __packed {
31 
32 typedef struct __packed {
38 
39 typedef struct __packed {
40  uint32_t ns;
41  uint32_t md;
44 
45 typedef struct __packed {
49 
50 struct lcc_freq_tbl {
51  unsigned int freq;
52  unsigned int pd;
53  unsigned int m;
54  unsigned int n;
55  unsigned int d;
56 };
57 
58 static const struct lcc_freq_tbl lcc_mi2s_freq_tbl[] = {
59  { 1024000, 4, 1, 96, 8 },
60  { 1411200, 4, 2, 139, 8 },
61  { 1536000, 4, 1, 64, 8 },
62  { 2048000, 4, 1, 48, 8 },
63  { 2116800, 4, 2, 93, 8 },
64  { 2304000, 4, 2, 85, 8 },
65  { 2822400, 4, 6, 209, 8 },
66  { 3072000, 4, 1, 32, 8 },
67  { 3175200, 4, 1, 31, 8 },
68  { 4096000, 4, 1, 24, 8 },
69  { 4233600, 4, 9, 209, 8 },
70  { 4608000, 4, 3, 64, 8 },
71  { 5644800, 4, 12, 209, 8 },
72  { 6144000, 4, 1, 16, 8 },
73  { 6350400, 4, 2, 31, 8 },
74  { 8192000, 4, 1, 12, 8 },
75  { 8467200, 4, 18, 209, 8 },
76  { 9216000, 4, 3, 32, 8 },
77  { 11289600, 4, 24, 209, 8 },
78  { 12288000, 4, 1, 8, 8 },
79  { 12700800, 4, 27, 209, 8 },
80  { 13824000, 4, 9, 64, 8 },
81  { 16384000, 4, 1, 6, 8 },
82  { 16934400, 4, 41, 238, 8 },
83  { 18432000, 4, 3, 16, 8 },
84  { 22579200, 2, 24, 209, 8 },
85  { 24576000, 4, 1, 4, 8 },
86  { 27648000, 4, 9, 32, 8 },
87  { 33868800, 4, 41, 119, 8 },
88  { 36864000, 4, 3, 8, 8 },
89  { 45158400, 1, 24, 209, 8 },
90  { 49152000, 4, 1, 2, 8 },
91  { 50803200, 1, 27, 209, 8 },
92  { }
93 };
94 
96 {
97  IpqLccGccRegs *gcc_regs = bus->gcc_apcs_regs;
98  IpqLccPll0Regs *pll0_regs = bus->lcc_pll0_regs;
99  IpqLccPllRegs *pll_regs = bus->lcc_pll_regs;
100  uint32_t regval;
101 
102  regval = 0;
103  regval = 15 << LCC_PLL0_L_SHIFT & LCC_PLL0_L_MASK;
104  write32(&pll0_regs->l_val, regval);
105 
106  regval = 0;
107  regval = 145 << LCC_PLL0_M_SHIFT & LCC_PLL0_M_MASK;
108  write32(&pll0_regs->m_val, regval);
109 
110  regval = 0;
111  regval = 199 << LCC_PLL0_N_SHIFT & LCC_PLL0_N_MASK;
112  write32(&pll0_regs->n_val, regval);
113 
114  regval = 0;
115  regval |= LCC_PLL0_CFG_LV_MAIN_ENABLE;
116  regval |= LCC_PLL0_CFG_FRAC_ENABLE;
117  write32(&pll0_regs->config, regval);
118 
119  regval = 0;
120  regval |= LCC_PLL_PCLK_SRC_PRI;
121  write32(&pll_regs->pri, regval);
122 
123  regval = 0;
124  regval |= 1 << LCC_PLL0_MODE_BIAS_CNT_SHIFT &
126  regval |= 8 << LCC_PLL0_MODE_LOCK_CNT_SHIFT &
128  write32(&pll0_regs->mode, regval);
129 
130  regval = read32(&gcc_regs->apcs);
131  regval |= GCC_PLL_APCS_PLL4_ENABLE;
132  write32(&gcc_regs->apcs, regval);
133 
134  regval = read32(&pll0_regs->mode);
136  write32(&pll0_regs->mode, regval);
137 
138  mdelay(1);
139 
140  regval = read32(&pll0_regs->status);
141  if (regval & LCC_PLL0_STAT_ACTIVE_MASK)
142  return 0;
143 
144  printk(BIOS_ERR, "%s: error enabling PLL4 clock\n", __func__);
145  return 1;
146 }
147 
149 {
150  IpqLccAhbixRegs *ahbix_regs = bus->lcc_ahbix_regs;
151  uint32_t regval;
152 
153  regval = 0;
155  regval |= 252 << LCC_AHBIX_MD_NOT_2D_VAL_SHIFT &
157  write32(&ahbix_regs->md, regval);
158 
159  regval = 0;
161  regval |= LCC_AHBIX_NS_CRC_ENABLE;
162  regval |= LCC_AHBIX_NS_GFM_SEL_MNC;
163  regval |= LCC_AHBIX_NS_MNC_CLK_ENABLE;
164  regval |= LCC_AHBIX_NS_MNC_ENABLE;
165  regval |= LCC_AHBIX_NS_MNC_MODE_DUAL;
166  regval |= LCC_AHBIX_NS_PREDIV_BYPASS;
167  regval |= LCC_AHBIX_NS_MN_SRC_LPA;
168  write32(&ahbix_regs->ns, regval);
169 
170  mdelay(1);
171 
172  regval = read32(&ahbix_regs->status);
173  if (regval & LCC_AHBIX_STAT_AIF_CLK_MASK)
174  return 0;
175 
176  printk(BIOS_ERR, "%s: error enabling AHBIX clock\n", __func__);
177  return 1;
178 }
179 
180 static int lcc_init_mi2s(IpqLccClocks *bus, unsigned int freq)
181 {
182  IpqLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
183  uint32_t regval;
184  uint8_t pd, m, n, d;
185  unsigned int i;
186 
187  i = 0;
188  while (lcc_mi2s_freq_tbl[i].freq != 0) {
189  if (lcc_mi2s_freq_tbl[i].freq == freq)
190  break;
191  ++i;
192  }
193  if (lcc_mi2s_freq_tbl[i].freq == 0) {
194  printk(BIOS_ERR, "%s: invalid frequency given: %u\n",
195  __func__, freq);
196  return 1;
197  }
198 
199  switch (lcc_mi2s_freq_tbl[i].pd) {
200  case 1:
202  break;
203  case 2:
205  break;
206  case 4:
208  break;
209  default:
210  printk(BIOS_ERR, "%s: invalid prediv found: %u\n", __func__,
211  lcc_mi2s_freq_tbl[i].pd);
212  return 1;
213  }
214 
215  m = lcc_mi2s_freq_tbl[i].m;
216  n = ~(lcc_mi2s_freq_tbl[i].n - m);
217  d = ~(lcc_mi2s_freq_tbl[i].d * 2);
218 
219  regval = 0;
221  regval |= d << LCC_MI2S_MD_NOT_2D_VAL_SHIFT &
223  write32(&mi2s_regs->md, regval);
224 
225  regval = 0;
227  regval |= LCC_MI2S_NS_BIT_DIV_DIV4;
228  regval |= LCC_MI2S_NS_MNC_CLK_ENABLE;
229  regval |= LCC_MI2S_NS_MNC_ENABLE;
230  regval |= LCC_MI2S_NS_MNC_MODE_DUAL;
231  regval |= pd;
232  regval |= LCC_MI2S_NS_MN_SRC_LPA;
233  write32(&mi2s_regs->ns, regval);
234 
235  return 0;
236 }
237 
239 {
240  IpqLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
241  uint32_t regval;
242 
243  regval = read32(&mi2s_regs->ns);
244  regval |= LCC_MI2S_NS_OSR_CXC_ENABLE;
245  regval |= LCC_MI2S_NS_BIT_CXC_ENABLE;
246  write32(&mi2s_regs->ns, regval);
247 
248  udelay(10);
249 
250  regval = read32(&mi2s_regs->status);
251  if (regval & LCC_MI2S_STAT_OSR_CLK_MASK)
252  if (regval & LCC_MI2S_STAT_BIT_CLK_MASK)
253  return 0;
254 
255  printk(BIOS_ERR, "%s: error enabling MI2S clocks: %u\n",
256  __func__, regval);
257  return 1;
258 }
259 
260 int audio_clock_config(unsigned int frequency)
261 {
262  IpqLccClocks bus = {
263  .gcc_apcs_regs = (void *)(MSM_GCC_BASE + GCC_PLL_APCS_REG),
264  .lcc_pll0_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL0_MODE_REG),
265  .lcc_ahbix_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_AHBIX_NS_REG),
266  .lcc_mi2s_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_MI2S_NS_REG),
267  .lcc_pll_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL_PCLK_REG),
268  };
269 
271  return 1;
273  return 1;
274  if (lcc_init_mi2s(&bus, frequency))
275  return 1;
276  if (lcc_enable_mi2s(&bus))
277  return 1;
278 
279  return 0;
280 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
#define LCC_PLL_PCLK_SRC_PRI
Definition: lcc-reg.h:291
#define MSM_GCC_BASE
Definition: lcc-reg.h:6
#define LCC_AHBIX_MD_NOT_2D_VAL_MASK
Definition: lcc-reg.h:159
#define LCC_AHBIX_NS_MNC_CLK_ENABLE
Definition: lcc-reg.h:124
#define LCC_AHBIX_NS_REG
Definition: lcc-reg.h:106
#define LCC_PLL0_L_SHIFT
Definition: lcc-reg.h:63
#define LCC_PLL0_L_MASK
Definition: lcc-reg.h:62
#define LCC_AHBIX_MD_M_VAL_SHIFT
Definition: lcc-reg.h:157
#define LCC_PLL0_CFG_LV_MAIN_ENABLE
Definition: lcc-reg.h:73
#define LCC_AHBIX_NS_MNC_MODE_DUAL
Definition: lcc-reg.h:138
#define LCC_MI2S_NS_PREDIV_DIV4
Definition: lcc-reg.h:254
#define LCC_AHBIX_NS_PREDIV_BYPASS
Definition: lcc-reg.h:143
#define LCC_MI2S_NS_MNC_ENABLE
Definition: lcc-reg.h:237
#define LCC_MI2S_NS_MNC_MODE_DUAL
Definition: lcc-reg.h:247
#define LCC_PLL0_N_SHIFT
Definition: lcc-reg.h:69
#define LCC_MI2S_STAT_OSR_CLK_MASK
Definition: lcc-reg.h:271
#define LCC_PLL_PCLK_REG
Definition: lcc-reg.h:281
#define LCC_AHBIX_STAT_AIF_CLK_MASK
Definition: lcc-reg.h:166
#define LCC_PLL0_STAT_ACTIVE_MASK
Definition: lcc-reg.h:96
#define LCC_MI2S_MD_M_VAL_SHIFT
Definition: lcc-reg.h:266
#define LCC_MI2S_NS_OSR_CXC_ENABLE
Definition: lcc-reg.h:197
#define LCC_MI2S_NS_N_VAL_SHIFT
Definition: lcc-reg.h:185
#define GCC_PLL_APCS_REG
Definition: lcc-reg.h:11
#define MSM_LPASS_LCC_BASE
Definition: lcc-reg.h:7
#define LCC_AHBIX_MD_M_VAL_MASK
Definition: lcc-reg.h:156
#define LCC_MI2S_MD_NOT_2D_VAL_SHIFT
Definition: lcc-reg.h:269
#define LCC_MI2S_MD_M_VAL_MASK
Definition: lcc-reg.h:265
#define LCC_PLL0_M_SHIFT
Definition: lcc-reg.h:66
#define LCC_PLL0_MODE_LOCK_CNT_MASK
Definition: lcc-reg.h:37
#define LCC_PLL0_MODE_BIAS_CNT_SHIFT
Definition: lcc-reg.h:35
#define LCC_PLL0_MODE_REG
Definition: lcc-reg.h:19
#define LCC_AHBIX_NS_MN_SRC_LPA
Definition: lcc-reg.h:151
#define LCC_MI2S_NS_MNC_CLK_ENABLE
Definition: lcc-reg.h:233
#define LCC_PLL0_CFG_FRAC_ENABLE
Definition: lcc-reg.h:77
#define LCC_MI2S_NS_PREDIV_BYPASS
Definition: lcc-reg.h:252
#define LCC_MI2S_MD_NOT_2D_VAL_MASK
Definition: lcc-reg.h:268
#define LCC_MI2S_NS_REG
Definition: lcc-reg.h:180
#define LCC_MI2S_NS_PREDIV_DIV2
Definition: lcc-reg.h:253
#define LCC_PLL0_M_MASK
Definition: lcc-reg.h:65
#define LCC_MI2S_NS_BIT_DIV_DIV4
Definition: lcc-reg.h:217
#define LCC_AHBIX_NS_CRC_ENABLE
Definition: lcc-reg.h:115
#define LCC_MI2S_STAT_BIT_CLK_MASK
Definition: lcc-reg.h:275
#define LCC_AHBIX_NS_GFM_SEL_MNC
Definition: lcc-reg.h:120
#define LCC_PLL0_MODE_FSM_VOTE_ENABLE
Definition: lcc-reg.h:32
#define LCC_AHBIX_NS_MNC_ENABLE
Definition: lcc-reg.h:128
#define GCC_PLL_APCS_PLL4_ENABLE
Definition: lcc-reg.h:15
#define LCC_PLL0_MODE_LOCK_CNT_SHIFT
Definition: lcc-reg.h:38
#define LCC_MI2S_NS_MN_SRC_LPA
Definition: lcc-reg.h:260
#define LCC_AHBIX_NS_N_VAL_MASK
Definition: lcc-reg.h:110
#define LCC_PLL0_MODE_BIAS_CNT_MASK
Definition: lcc-reg.h:34
#define LCC_PLL0_N_MASK
Definition: lcc-reg.h:68
#define LCC_AHBIX_NS_N_VAL_SHIFT
Definition: lcc-reg.h:111
#define LCC_MI2S_NS_N_VAL_MASK
Definition: lcc-reg.h:184
#define LCC_AHBIX_MD_NOT_2D_VAL_SHIFT
Definition: lcc-reg.h:160
#define LCC_MI2S_NS_BIT_CXC_ENABLE
Definition: lcc-reg.h:205
struct __packed IpqLccPll0Regs
static int lcc_init_enable_ahbix(IpqLccClocks *bus)
Definition: lcc.c:148
static int lcc_init_mi2s(IpqLccClocks *bus, unsigned int freq)
Definition: lcc.c:180
static const struct lcc_freq_tbl lcc_mi2s_freq_tbl[]
Definition: lcc.c:58
static int lcc_enable_mi2s(IpqLccClocks *bus)
Definition: lcc.c:238
static int lcc_init_enable_pll0(IpqLccClocks *bus)
Definition: lcc.c:95
int audio_clock_config(unsigned int frequency)
Definition: lcc.c:260
struct __packed IpqLccAhbixRegs
struct __packed IpqLccMi2sRegs
struct __packed IpqLccPllRegs
struct __packed IpqLccGccRegs
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
void * lcc_mi2s_regs
Definition: lcc.c:14
void * lcc_pll0_regs
Definition: lcc.c:12
void * gcc_apcs_regs
Definition: lcc.c:11
void * lcc_pll_regs
Definition: lcc.c:15
void * lcc_ahbix_regs
Definition: lcc.c:13
Definition: x86.c:23
uint32_t md
Definition: lcc.c:34
uint32_t sec
Definition: lcc.c:47
uint32_t apcs
Definition: lcc.c:19
uint32_t UNUSED
Definition: lcc.c:27
uint32_t ns
Definition: lcc.c:33
uint32_t config
Definition: lcc.c:28
uint32_t mode
Definition: lcc.c:23
uint32_t l_val
Definition: lcc.c:24
uint32_t pri
Definition: lcc.c:46
uint32_t n_val
Definition: lcc.c:26
uint32_t m_val
Definition: lcc.c:25
uint32_t status
Definition: lcc.c:29
Definition: device.h:76
Definition: dw_i2c.c:39
unsigned int d
Definition: lcc.c:55
unsigned int pd
Definition: lcc.c:52
unsigned int freq
Definition: lcc.c:51
unsigned int m
Definition: lcc.c:53
unsigned int n
Definition: lcc.c:54
#define m(clkreg, src_bits, pmcreg, dst_bits)
void udelay(uint32_t us)
Definition: udelay.c:15