blob: 758447d8056aa05acb593d11257639c5a6e9115e [file] [log] [blame]
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -08001/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080030#include <stdint.h>
31#include <delay.h>
32#include <console/console.h>
33#include <soc/clock.h>
34#include <soc/lcc-reg.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020035#include <device/mmio.h>
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080036
37typedef struct {
38 void *gcc_apcs_regs;
39 void *lcc_pll0_regs;
40 void *lcc_ahbix_regs;
41 void *lcc_mi2s_regs;
42 void *lcc_pll_regs;
43} Ipq806xLccClocks;
44
Stefan Reinauer6a001132017-07-13 02:20:27 +020045typedef struct __packed {
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080046 uint32_t apcs;
47} Ipq806xLccGccRegs;
48
Stefan Reinauer6a001132017-07-13 02:20:27 +020049typedef struct __packed {
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080050 uint32_t mode;
51 uint32_t l_val;
52 uint32_t m_val;
53 uint32_t n_val;
54 uint32_t UNUSED;
55 uint32_t config;
56 uint32_t status;
57} Ipq806xLccPll0Regs;
58
Stefan Reinauer6a001132017-07-13 02:20:27 +020059typedef struct __packed {
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080060 uint32_t ns;
61 uint32_t md;
62 uint32_t UNUSED;
63 uint32_t status;
64} Ipq806xLccAhbixRegs;
65
Stefan Reinauer6a001132017-07-13 02:20:27 +020066typedef struct __packed {
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080067 uint32_t ns;
68 uint32_t md;
69 uint32_t status;
70} Ipq806xLccMi2sRegs;
71
Stefan Reinauer6a001132017-07-13 02:20:27 +020072typedef struct __packed {
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080073 uint32_t pri;
74 uint32_t sec;
75} Ipq806xLccPllRegs;
76
77struct lcc_freq_tbl {
Martin Roth57e89092019-10-23 21:45:23 -060078 unsigned int freq;
79 unsigned int pd;
80 unsigned int m;
81 unsigned int n;
82 unsigned int d;
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -080083};
84
85static const struct lcc_freq_tbl lcc_mi2s_freq_tbl[] = {
86 { 1024000, 4, 1, 96, 8 },
87 { 1411200, 4, 2, 139, 8 },
88 { 1536000, 4, 1, 64, 8 },
89 { 2048000, 4, 1, 48, 8 },
90 { 2116800, 4, 2, 93, 8 },
91 { 2304000, 4, 2, 85, 8 },
92 { 2822400, 4, 6, 209, 8 },
93 { 3072000, 4, 1, 32, 8 },
94 { 3175200, 4, 1, 31, 8 },
95 { 4096000, 4, 1, 24, 8 },
96 { 4233600, 4, 9, 209, 8 },
97 { 4608000, 4, 3, 64, 8 },
98 { 5644800, 4, 12, 209, 8 },
99 { 6144000, 4, 1, 16, 8 },
100 { 6350400, 4, 2, 31, 8 },
101 { 8192000, 4, 1, 12, 8 },
102 { 8467200, 4, 18, 209, 8 },
103 { 9216000, 4, 3, 32, 8 },
104 { 11289600, 4, 24, 209, 8 },
105 { 12288000, 4, 1, 8, 8 },
106 { 12700800, 4, 27, 209, 8 },
107 { 13824000, 4, 9, 64, 8 },
108 { 16384000, 4, 1, 6, 8 },
109 { 16934400, 4, 41, 238, 8 },
110 { 18432000, 4, 3, 16, 8 },
111 { 22579200, 2, 24, 209, 8 },
112 { 24576000, 4, 1, 4, 8 },
113 { 27648000, 4, 9, 32, 8 },
114 { 33868800, 4, 41, 119, 8 },
115 { 36864000, 4, 3, 8, 8 },
116 { 45158400, 1, 24, 209, 8 },
117 { 49152000, 4, 1, 2, 8 },
118 { 50803200, 1, 27, 209, 8 },
119 { }
120};
121
122static int lcc_init_enable_pll0(Ipq806xLccClocks *bus)
123{
124 Ipq806xLccGccRegs *gcc_regs = bus->gcc_apcs_regs;
125 Ipq806xLccPll0Regs *pll0_regs = bus->lcc_pll0_regs;
126 Ipq806xLccPllRegs *pll_regs = bus->lcc_pll_regs;
127 uint32_t regval;
128
129 regval = 0;
130 regval = 15 << LCC_PLL0_L_SHIFT & LCC_PLL0_L_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800131 write32(&pll0_regs->l_val, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800132
133 regval = 0;
134 regval = 145 << LCC_PLL0_M_SHIFT & LCC_PLL0_M_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800135 write32(&pll0_regs->m_val, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800136
137 regval = 0;
138 regval = 199 << LCC_PLL0_N_SHIFT & LCC_PLL0_N_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800139 write32(&pll0_regs->n_val, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800140
141 regval = 0;
142 regval |= LCC_PLL0_CFG_LV_MAIN_ENABLE;
143 regval |= LCC_PLL0_CFG_FRAC_ENABLE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800144 write32(&pll0_regs->config, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800145
146 regval = 0;
147 regval |= LCC_PLL_PCLK_SRC_PRI;
Julius Werner2f37bd62015-02-19 14:51:15 -0800148 write32(&pll_regs->pri, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800149
150 regval = 0;
151 regval |= 1 << LCC_PLL0_MODE_BIAS_CNT_SHIFT &
152 LCC_PLL0_MODE_BIAS_CNT_MASK;
153 regval |= 8 << LCC_PLL0_MODE_LOCK_CNT_SHIFT &
154 LCC_PLL0_MODE_LOCK_CNT_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800155 write32(&pll0_regs->mode, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800156
Julius Werner2f37bd62015-02-19 14:51:15 -0800157 regval = read32(&gcc_regs->apcs);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800158 regval |= GCC_PLL_APCS_PLL4_ENABLE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800159 write32(&gcc_regs->apcs, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800160
Julius Werner2f37bd62015-02-19 14:51:15 -0800161 regval = read32(&pll0_regs->mode);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800162 regval |= LCC_PLL0_MODE_FSM_VOTE_ENABLE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800163 write32(&pll0_regs->mode, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800164
165 mdelay(1);
166
Julius Werner2f37bd62015-02-19 14:51:15 -0800167 regval = read32(&pll0_regs->status);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800168 if (regval & LCC_PLL0_STAT_ACTIVE_MASK)
169 return 0;
170
171 printk(BIOS_ERR, "%s: error enabling PLL4 clock\n", __func__);
172 return 1;
173}
174
175static int lcc_init_enable_ahbix(Ipq806xLccClocks *bus)
176{
177 Ipq806xLccAhbixRegs *ahbix_regs = bus->lcc_ahbix_regs;
178 uint32_t regval;
179
180 regval = 0;
181 regval |= 1 << LCC_AHBIX_MD_M_VAL_SHIFT & LCC_AHBIX_MD_M_VAL_MASK;
182 regval |= 252 << LCC_AHBIX_MD_NOT_2D_VAL_SHIFT &
183 LCC_AHBIX_MD_NOT_2D_VAL_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800184 write32(&ahbix_regs->md, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800185
186 regval = 0;
187 regval |= 253 << LCC_AHBIX_NS_N_VAL_SHIFT & LCC_AHBIX_NS_N_VAL_MASK;
188 regval |= LCC_AHBIX_NS_CRC_ENABLE;
189 regval |= LCC_AHBIX_NS_GFM_SEL_MNC;
190 regval |= LCC_AHBIX_NS_MNC_CLK_ENABLE;
191 regval |= LCC_AHBIX_NS_MNC_ENABLE;
192 regval |= LCC_AHBIX_NS_MNC_MODE_DUAL;
193 regval |= LCC_AHBIX_NS_PREDIV_BYPASS;
194 regval |= LCC_AHBIX_NS_MN_SRC_LPA;
Julius Werner2f37bd62015-02-19 14:51:15 -0800195 write32(&ahbix_regs->ns, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800196
197 mdelay(1);
198
Julius Werner2f37bd62015-02-19 14:51:15 -0800199 regval = read32(&ahbix_regs->status);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800200 if (regval & LCC_AHBIX_STAT_AIF_CLK_MASK)
201 return 0;
202
203 printk(BIOS_ERR, "%s: error enabling AHBIX clock\n", __func__);
204 return 1;
205}
206
Martin Roth57e89092019-10-23 21:45:23 -0600207static int lcc_init_mi2s(Ipq806xLccClocks *bus, unsigned int freq)
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800208{
209 Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
210 uint32_t regval;
211 uint8_t pd, m, n, d;
Martin Roth57e89092019-10-23 21:45:23 -0600212 unsigned int i;
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800213
214 i = 0;
215 while (lcc_mi2s_freq_tbl[i].freq != 0) {
216 if (lcc_mi2s_freq_tbl[i].freq == freq)
217 break;
218 ++i;
219 }
220 if (lcc_mi2s_freq_tbl[i].freq == 0) {
221 printk(BIOS_ERR, "%s: invalid frequency given: %u\n",
222 __func__, freq);
223 return 1;
224 }
225
226 switch (lcc_mi2s_freq_tbl[i].pd) {
227 case 1:
228 pd = LCC_MI2S_NS_PREDIV_BYPASS;
229 break;
230 case 2:
231 pd = LCC_MI2S_NS_PREDIV_DIV2;
232 break;
233 case 4:
234 pd = LCC_MI2S_NS_PREDIV_DIV4;
235 break;
236 default:
237 printk(BIOS_ERR, "%s: invalid prediv found: %u\n", __func__,
238 lcc_mi2s_freq_tbl[i].pd);
239 return 1;
240 }
241
242 m = lcc_mi2s_freq_tbl[i].m;
243 n = ~(lcc_mi2s_freq_tbl[i].n - m);
244 d = ~(lcc_mi2s_freq_tbl[i].d * 2);
245
246 regval = 0;
247 regval |= m << LCC_MI2S_MD_M_VAL_SHIFT & LCC_MI2S_MD_M_VAL_MASK;
248 regval |= d << LCC_MI2S_MD_NOT_2D_VAL_SHIFT &
249 LCC_MI2S_MD_NOT_2D_VAL_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800250 write32(&mi2s_regs->md, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800251
252 regval = 0;
253 regval |= n << LCC_MI2S_NS_N_VAL_SHIFT & LCC_MI2S_NS_N_VAL_MASK;
254 regval |= LCC_MI2S_NS_BIT_DIV_DIV4;
255 regval |= LCC_MI2S_NS_MNC_CLK_ENABLE;
256 regval |= LCC_MI2S_NS_MNC_ENABLE;
257 regval |= LCC_MI2S_NS_MNC_MODE_DUAL;
258 regval |= pd;
259 regval |= LCC_MI2S_NS_MN_SRC_LPA;
Julius Werner2f37bd62015-02-19 14:51:15 -0800260 write32(&mi2s_regs->ns, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800261
262 return 0;
263}
264
265static int lcc_enable_mi2s(Ipq806xLccClocks *bus)
266{
267 Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
268 uint32_t regval;
269
Julius Werner2f37bd62015-02-19 14:51:15 -0800270 regval = read32(&mi2s_regs->ns);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800271 regval |= LCC_MI2S_NS_OSR_CXC_ENABLE;
272 regval |= LCC_MI2S_NS_BIT_CXC_ENABLE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800273 write32(&mi2s_regs->ns, regval);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800274
275 udelay(10);
276
Julius Werner2f37bd62015-02-19 14:51:15 -0800277 regval = read32(&mi2s_regs->status);
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800278 if (regval & LCC_MI2S_STAT_OSR_CLK_MASK)
279 if (regval & LCC_MI2S_STAT_BIT_CLK_MASK)
280 return 0;
281
282 printk(BIOS_ERR, "%s: error enabling MI2S clocks: %u\n",
283 __func__, regval);
284 return 1;
285}
286
Martin Roth57e89092019-10-23 21:45:23 -0600287int audio_clock_config(unsigned int frequency)
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800288{
Jacob Garber0f33d8c2019-07-22 16:20:36 -0600289 Ipq806xLccClocks bus = {
290 .gcc_apcs_regs = (void *)(MSM_GCC_BASE + GCC_PLL_APCS_REG),
291 .lcc_pll0_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL0_MODE_REG),
292 .lcc_ahbix_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_AHBIX_NS_REG),
293 .lcc_mi2s_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_MI2S_NS_REG),
294 .lcc_pll_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL_PCLK_REG),
295 };
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800296
Jacob Garber0f33d8c2019-07-22 16:20:36 -0600297 if (lcc_init_enable_pll0(&bus))
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800298 return 1;
Jacob Garber0f33d8c2019-07-22 16:20:36 -0600299 if (lcc_init_enable_ahbix(&bus))
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800300 return 1;
Jacob Garber0f33d8c2019-07-22 16:20:36 -0600301 if (lcc_init_mi2s(&bus, frequency))
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800302 return 1;
Jacob Garber0f33d8c2019-07-22 16:20:36 -0600303 if (lcc_enable_mi2s(&bus))
Vadim Bendebury3cfb6a02015-02-11 15:13:04 -0800304 return 1;
305
306 return 0;
307}