1 /* SPDX-License-Identifier: BSD-3-Clause */
5 #include <console/console.h>
7 #include <soc/lcc-reg.h>
8 #include <device/mmio.h>
18 typedef struct __packed
{
22 typedef struct __packed
{
32 typedef struct __packed
{
37 } Ipq806xLccAhbixRegs
;
39 typedef struct __packed
{
45 typedef struct __packed
{
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 },
95 static int lcc_init_enable_pll0(Ipq806xLccClocks
*bus
)
97 Ipq806xLccGccRegs
*gcc_regs
= bus
->gcc_apcs_regs
;
98 Ipq806xLccPll0Regs
*pll0_regs
= bus
->lcc_pll0_regs
;
99 Ipq806xLccPllRegs
*pll_regs
= bus
->lcc_pll_regs
;
103 regval
= 15 << LCC_PLL0_L_SHIFT
& LCC_PLL0_L_MASK
;
104 write32(&pll0_regs
->l_val
, regval
);
107 regval
= 145 << LCC_PLL0_M_SHIFT
& LCC_PLL0_M_MASK
;
108 write32(&pll0_regs
->m_val
, regval
);
111 regval
= 199 << LCC_PLL0_N_SHIFT
& LCC_PLL0_N_MASK
;
112 write32(&pll0_regs
->n_val
, regval
);
115 regval
|= LCC_PLL0_CFG_LV_MAIN_ENABLE
;
116 regval
|= LCC_PLL0_CFG_FRAC_ENABLE
;
117 write32(&pll0_regs
->config
, regval
);
120 regval
|= LCC_PLL_PCLK_SRC_PRI
;
121 write32(&pll_regs
->pri
, regval
);
124 regval
|= 1 << LCC_PLL0_MODE_BIAS_CNT_SHIFT
&
125 LCC_PLL0_MODE_BIAS_CNT_MASK
;
126 regval
|= 8 << LCC_PLL0_MODE_LOCK_CNT_SHIFT
&
127 LCC_PLL0_MODE_LOCK_CNT_MASK
;
128 write32(&pll0_regs
->mode
, regval
);
130 regval
= read32(&gcc_regs
->apcs
);
131 regval
|= GCC_PLL_APCS_PLL4_ENABLE
;
132 write32(&gcc_regs
->apcs
, regval
);
134 regval
= read32(&pll0_regs
->mode
);
135 regval
|= LCC_PLL0_MODE_FSM_VOTE_ENABLE
;
136 write32(&pll0_regs
->mode
, regval
);
140 regval
= read32(&pll0_regs
->status
);
141 if (regval
& LCC_PLL0_STAT_ACTIVE_MASK
)
144 printk(BIOS_ERR
, "%s: error enabling PLL4 clock\n", __func__
);
148 static int lcc_init_enable_ahbix(Ipq806xLccClocks
*bus
)
150 Ipq806xLccAhbixRegs
*ahbix_regs
= bus
->lcc_ahbix_regs
;
154 regval
|= 1 << LCC_AHBIX_MD_M_VAL_SHIFT
& LCC_AHBIX_MD_M_VAL_MASK
;
155 regval
|= 252 << LCC_AHBIX_MD_NOT_2D_VAL_SHIFT
&
156 LCC_AHBIX_MD_NOT_2D_VAL_MASK
;
157 write32(&ahbix_regs
->md
, regval
);
160 regval
|= 253 << LCC_AHBIX_NS_N_VAL_SHIFT
& LCC_AHBIX_NS_N_VAL_MASK
;
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
);
172 regval
= read32(&ahbix_regs
->status
);
173 if (regval
& LCC_AHBIX_STAT_AIF_CLK_MASK
)
176 printk(BIOS_ERR
, "%s: error enabling AHBIX clock\n", __func__
);
180 static int lcc_init_mi2s(Ipq806xLccClocks
*bus
, unsigned int freq
)
182 Ipq806xLccMi2sRegs
*mi2s_regs
= bus
->lcc_mi2s_regs
;
188 while (lcc_mi2s_freq_tbl
[i
].freq
!= 0) {
189 if (lcc_mi2s_freq_tbl
[i
].freq
== freq
)
193 if (lcc_mi2s_freq_tbl
[i
].freq
== 0) {
194 printk(BIOS_ERR
, "%s: invalid frequency given: %u\n",
199 switch (lcc_mi2s_freq_tbl
[i
].pd
) {
201 pd
= LCC_MI2S_NS_PREDIV_BYPASS
;
204 pd
= LCC_MI2S_NS_PREDIV_DIV2
;
207 pd
= LCC_MI2S_NS_PREDIV_DIV4
;
210 printk(BIOS_ERR
, "%s: invalid prediv found: %u\n", __func__
,
211 lcc_mi2s_freq_tbl
[i
].pd
);
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);
220 regval
|= m
<< LCC_MI2S_MD_M_VAL_SHIFT
& LCC_MI2S_MD_M_VAL_MASK
;
221 regval
|= d
<< LCC_MI2S_MD_NOT_2D_VAL_SHIFT
&
222 LCC_MI2S_MD_NOT_2D_VAL_MASK
;
223 write32(&mi2s_regs
->md
, regval
);
226 regval
|= n
<< LCC_MI2S_NS_N_VAL_SHIFT
& LCC_MI2S_NS_N_VAL_MASK
;
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
;
232 regval
|= LCC_MI2S_NS_MN_SRC_LPA
;
233 write32(&mi2s_regs
->ns
, regval
);
238 static int lcc_enable_mi2s(Ipq806xLccClocks
*bus
)
240 Ipq806xLccMi2sRegs
*mi2s_regs
= bus
->lcc_mi2s_regs
;
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
);
250 regval
= read32(&mi2s_regs
->status
);
251 if (regval
& LCC_MI2S_STAT_OSR_CLK_MASK
)
252 if (regval
& LCC_MI2S_STAT_BIT_CLK_MASK
)
255 printk(BIOS_ERR
, "%s: error enabling MI2S clocks: %u\n",
260 int audio_clock_config(unsigned int frequency
)
262 Ipq806xLccClocks 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
),
270 if (lcc_init_enable_pll0(&bus
))
272 if (lcc_init_enable_ahbix(&bus
))
274 if (lcc_init_mi2s(&bus
, frequency
))
276 if (lcc_enable_mi2s(&bus
))