blob: f1ea9a9f03588046933164540f4dcba54a54b804 [file] [log] [blame]
James Liaof9fad122015-07-31 17:10:53 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2015 MediaTek Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <arch/io.h>
21#include <assert.h>
22#include <console/console.h>
23#include <delay.h>
24#include <stddef.h>
25
26#include <soc/addressmap.h>
27#include <soc/infracfg.h>
28#include <soc/pll.h>
29
30#define GENMASK(h, l) (((1U << ((h) - (l) + 1)) - 1) << (l))
31
32enum mux_id {
33 TOP_AXI_SEL,
34 TOP_MEM_SEL,
35 TOP_DDRPHYCFG_SEL,
36 TOP_MM_SEL,
37 TOP_PWM_SEL,
38 TOP_VDEC_SEL,
39 TOP_VENC_SEL,
40 TOP_MFG_SEL,
41 TOP_CAMTG_SEL,
42 TOP_UART_SEL,
43 TOP_SPI_SEL,
44 TOP_USB20_SEL,
45 TOP_USB30_SEL,
46 TOP_MSDC50_0_H_SEL,
47 TOP_MSDC50_0_SEL,
48 TOP_MSDC30_1_SEL,
49 TOP_MSDC30_2_SEL,
50 TOP_MSDC30_3_SEL,
51 TOP_AUDIO_SEL,
52 TOP_AUD_INTBUS_SEL,
53 TOP_PMICSPI_SEL,
54 TOP_SCP_SEL,
55 TOP_ATB_SEL,
56 TOP_VENC_LT_SEL,
57 TOP_DPI0_SEL,
58 TOP_IRDA_SEL,
59 TOP_CCI400_SEL,
60 TOP_AUD_1_SEL,
61 TOP_AUD_2_SEL,
62 TOP_MEM_MFG_IN_SEL,
63 TOP_AXI_MFG_IN_SEL,
64 TOP_SCAM_SEL,
65 TOP_SPINFI_IFR_SEL,
66 TOP_HDMI_SEL,
67 TOP_DPILVDS_SEL,
68 TOP_MSDC50_2_H_SEL,
69 TOP_HDCP_SEL,
70 TOP_HDCP_24M_SEL,
71 TOP_RTC_SEL,
72 TOP_NR_MUX
73};
74
75#define TOPCKGEN_REG(x) (CKSYS_BASE + offsetof(struct mt8173_topckgen_regs, x))
76#define APMIXED_REG(x) (APMIXED_BASE + offsetof(struct mt8173_apmixed_regs, x))
77
78struct mux {
79 void *reg;
80 u8 mux_shift;
81 u8 mux_width;
82};
83
84#define MUX(_id, _reg, _mux_shift, _mux_width) \
85 [_id] = { \
86 .reg = (void *)TOPCKGEN_REG(_reg), \
87 .mux_shift = _mux_shift, \
88 .mux_width = _mux_width, \
89 }
90
91static const struct mux muxes[] = {
92 /* CLK_CFG_0 */
93 MUX(TOP_AXI_SEL, clk_cfg_0, 0, 3),
94 MUX(TOP_MEM_SEL, clk_cfg_0, 8, 1),
95 MUX(TOP_DDRPHYCFG_SEL, clk_cfg_0, 16, 1),
96 MUX(TOP_MM_SEL, clk_cfg_0, 24, 4),
97 /* CLK_CFG_1 */
98 MUX(TOP_PWM_SEL, clk_cfg_1, 0, 2),
99 MUX(TOP_VDEC_SEL, clk_cfg_1, 8, 4),
100 MUX(TOP_VENC_SEL, clk_cfg_1, 16, 4),
101 MUX(TOP_MFG_SEL, clk_cfg_1, 24, 4),
102 /* CLK_CFG_2 */
103 MUX(TOP_CAMTG_SEL, clk_cfg_2, 0, 3),
104 MUX(TOP_UART_SEL, clk_cfg_2, 8, 1),
105 MUX(TOP_SPI_SEL, clk_cfg_2, 16, 3),
106 MUX(TOP_USB20_SEL, clk_cfg_2, 24, 2),
107 /* CLK_CFG_3 */
108 MUX(TOP_USB30_SEL, clk_cfg_3, 0, 2),
109 MUX(TOP_MSDC50_0_H_SEL, clk_cfg_3, 8, 3),
110 MUX(TOP_MSDC50_0_SEL, clk_cfg_3, 16, 4),
111 MUX(TOP_MSDC30_1_SEL, clk_cfg_3, 24, 3),
112 /* CLK_CFG_4 */
113 MUX(TOP_MSDC30_2_SEL, clk_cfg_4, 0, 3),
114 MUX(TOP_MSDC30_3_SEL, clk_cfg_4, 8, 4),
115 MUX(TOP_AUDIO_SEL, clk_cfg_4, 16, 2),
116 MUX(TOP_AUD_INTBUS_SEL, clk_cfg_4, 24, 3),
117 /* CLK_CFG_5 */
118 MUX(TOP_PMICSPI_SEL, clk_cfg_5, 0, 3),
119 MUX(TOP_SCP_SEL, clk_cfg_5, 8, 3),
120 MUX(TOP_ATB_SEL, clk_cfg_5, 16, 2),
121 MUX(TOP_VENC_LT_SEL, clk_cfg_5, 24, 4),
122 /* CLK_CFG_6 */
123 MUX(TOP_DPI0_SEL, clk_cfg_6, 0, 3),
124 MUX(TOP_IRDA_SEL, clk_cfg_6, 8, 2),
125 MUX(TOP_CCI400_SEL, clk_cfg_6, 16, 3),
126 MUX(TOP_AUD_1_SEL, clk_cfg_6, 24, 2),
127 /* CLK_CFG_7 */
128 MUX(TOP_AUD_2_SEL, clk_cfg_7, 0, 2),
129 MUX(TOP_MEM_MFG_IN_SEL, clk_cfg_7, 8, 2),
130 MUX(TOP_AXI_MFG_IN_SEL, clk_cfg_7, 16, 2),
131 MUX(TOP_SCAM_SEL, clk_cfg_7, 24, 2),
132 /* CLK_CFG_12 */
133 MUX(TOP_SPINFI_IFR_SEL, clk_cfg_12, 0, 3),
134 MUX(TOP_HDMI_SEL, clk_cfg_12, 8, 2),
135 MUX(TOP_DPILVDS_SEL, clk_cfg_12, 24, 3),
136 /* CLK_CFG_13 */
137 MUX(TOP_MSDC50_2_H_SEL, clk_cfg_13, 0, 3),
138 MUX(TOP_HDCP_SEL, clk_cfg_13, 8, 2),
139 MUX(TOP_HDCP_24M_SEL, clk_cfg_13, 16, 2),
140 MUX(TOP_RTC_SEL, clk_cfg_13, 24, 2),
141};
142
143static void mux_set_sel(const struct mux *mux, u32 sel)
144{
145 u32 mask = GENMASK(mux->mux_width - 1, 0);
146 u32 val = read32(mux->reg);
147
148 val &= ~(mask << mux->mux_shift);
149 val |= (sel & mask) << mux->mux_shift;
150 write32(mux->reg, val);
151}
152
153#define PLL_PWR_ON (1 << 0)
154#define PLL_EN (1 << 0)
155#define PLL_ISO (1 << 1)
156#define PLL_RSTB (1 << 24)
157#define PLL_PCW_CHG (1 << 31)
158#define PLL_POSTDIV_MASK 0x7
159#define PCW_INTEGER_BITS 7
160
161enum pll_id {
162 APMIXED_ARMCA15PLL,
163 APMIXED_ARMCA7PLL,
164 APMIXED_MAINPLL,
165 APMIXED_UNIVPLL,
166 APMIXED_MMPLL,
167 APMIXED_MSDCPLL,
168 APMIXED_VENCPLL,
169 APMIXED_TVDPLL,
170 APMIXED_MPLL,
171 APMIXED_VCODECPLL,
172 APMIXED_APLL1,
173 APMIXED_APLL2,
174 APMIXED_LVDSPLL,
175 APMIXED_MSDCPLL2,
176 APMIXED_NR_PLL
177};
178
179const u32 pll_div_rate[] = {
180 3UL * GHz,
181 1 * GHz,
182 500 * MHz,
183 250 * MHz,
184 125 * MHz,
185 0,
186};
187
188const u32 univpll_div_rate[] = {
189 3UL * GHz,
190 1500 * MHz,
191 750 * MHz,
192 375 * MHz,
193 187500 * KHz,
194 0,
195};
196
197const u32 mmpll_div_rate[] = {
198 3UL * GHz,
199 1 * GHz,
200 702 * MHz,
201 253500 * KHz,
202 126750 * KHz,
203 0,
204};
205
206struct pll {
207 void *reg;
208 void *pwr_reg;
209 u32 rstb;
210 u8 pcwbits;
211 void *div_reg;
212 u8 div_shift;
213 void *pcw_reg;
214 u8 pcw_shift;
215 const u32 *div_rate;
216};
217
218#define PLL(_id, _reg, _pwr_reg, _rstb, _pcwbits, _div_reg, _div_shift, \
219 _pcw_reg, _pcw_shift, _div_rate) \
220 [_id] = { \
221 .reg = (void *)APMIXED_REG(_reg), \
222 .pwr_reg = (void *)APMIXED_REG(_pwr_reg), \
223 .rstb = _rstb, \
224 .pcwbits = _pcwbits, \
225 .div_reg = (void *)APMIXED_REG(_div_reg), \
226 .div_shift = _div_shift, \
227 .pcw_reg = (void *)APMIXED_REG(_pcw_reg), \
228 .pcw_shift = _pcw_shift, \
229 .div_rate = _div_rate, \
230 }
231
232static const struct pll plls[] = {
233 PLL(APMIXED_ARMCA15PLL, armca15pll_con0, armca15pll_pwr_con0, 0, 21,
234 armca15pll_con1, 24, armca15pll_con1, 0, pll_div_rate),
235 PLL(APMIXED_ARMCA7PLL, armca7pll_con0, armca7pll_pwr_con0, PLL_RSTB, 21,
236 armca7pll_con1, 24, armca7pll_con1, 0, pll_div_rate),
237 PLL(APMIXED_MAINPLL, mainpll_con0, mainpll_pwr_con0, PLL_RSTB, 21,
238 mainpll_con0, 4, mainpll_con1, 0, pll_div_rate),
239 PLL(APMIXED_UNIVPLL, univpll_con0, univpll_pwr_con0, PLL_RSTB, 7,
240 univpll_con0, 4, univpll_con1, 14, univpll_div_rate),
241 PLL(APMIXED_MMPLL, mmpll_con0, mmpll_pwr_con0, 0, 21,
242 mmpll_con1, 24, mmpll_con1, 0, mmpll_div_rate),
243 PLL(APMIXED_MSDCPLL, msdcpll_con0, msdcpll_pwr_con0, 0, 21,
244 msdcpll_con0, 4, msdcpll_con1, 0, pll_div_rate),
245 PLL(APMIXED_VENCPLL, vencpll_con0, vencpll_pwr_con0, 0, 21,
246 vencpll_con0, 4, vencpll_con1, 0, pll_div_rate),
247 PLL(APMIXED_TVDPLL, tvdpll_con0, tvdpll_pwr_con0, 0, 21,
248 tvdpll_con0, 4, tvdpll_con1, 0, pll_div_rate),
249 PLL(APMIXED_MPLL, mpll_con0, mpll_pwr_con0, 0, 21,
250 mpll_con0, 4, mpll_con1, 0, pll_div_rate),
251 PLL(APMIXED_VCODECPLL, vcodecpll_con0, vcodecpll_pwr_con0, 0, 21,
252 vcodecpll_con0, 4, vcodecpll_con1, 0, pll_div_rate),
253 PLL(APMIXED_APLL1, apll1_con0, apll1_pwr_con0, 0, 31,
254 apll1_con0, 4, apll1_con1, 0, pll_div_rate),
255 PLL(APMIXED_APLL2, apll2_con0, apll2_pwr_con0, 0, 31,
256 apll2_con0, 4, apll2_con1, 0, pll_div_rate),
257 PLL(APMIXED_LVDSPLL, lvdspll_con0, lvdspll_pwr_con0, 0, 21,
258 lvdspll_con0, 4, lvdspll_con1, 0, pll_div_rate),
259 PLL(APMIXED_MSDCPLL2, msdcpll2_con0, msdcpll2_pwr_con0, 0, 21,
260 msdcpll2_con0, 4, msdcpll2_con1, 0, pll_div_rate),
261};
262
263static void pll_set_rate_regs(const struct pll *pll, u32 pcw, u32 postdiv)
264{
265 u32 val;
266
267 /* set postdiv */
268 val = read32(pll->div_reg);
269 val &= ~(PLL_POSTDIV_MASK << pll->div_shift);
270 val |= postdiv << pll->div_shift;
271
272 /* postdiv and pcw need to set at the same time if on same register */
273 if (pll->div_reg != pll->pcw_reg) {
274 write32(pll->div_reg, val);
275 val = read32(pll->pcw_reg);
276 }
277
278 /* set pcw */
279 val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift);
280 val |= pcw << pll->pcw_shift;
281 val |= PLL_PCW_CHG;
282 write32(pll->pcw_reg, val);
283}
284
285static void pll_calc_values(const struct pll *pll, u32 *pcw, u32 *postdiv,
286 u32 freq)
287{
288 const u32 fin_hz = CLK26M_HZ;
289 const u32 *div_rate = pll->div_rate;
290 u32 val;
291
292 assert(freq <= div_rate[0]);
293 assert(freq >= 1 * GHz / 16);
294
295 for (val = 1; div_rate[val] != 0; val++) {
296 if (freq > div_rate[val])
297 break;
298 }
299 val--;
300 *postdiv = val;
301
302 /* _pcw = freq * 2^postdiv / fin * 2^pcwbits_fractional */
303 val += pll->pcwbits - PCW_INTEGER_BITS;
304
305 *pcw = ((u64)freq << val) / fin_hz;
306}
307
308static int pll_set_rate(const struct pll *pll, u32 rate)
309{
310 u32 pcw = 0;
311 u32 postdiv;
312
313 pll_calc_values(pll, &pcw, &postdiv, rate);
314 pll_set_rate_regs(pll, pcw, postdiv);
315
316 return 0;
317}
318
319void mt_pll_init(void)
320{
321 int i;
322
323 /* reduce CLKSQ disable time */
324 write32(&mt8173_apmixed->clksq_stb_con0, (0x05 << 8) | (0x01 << 0));
325 /* extend PWR/ISO control timing to 1us */
326 write32(&mt8173_apmixed->pll_iso_con0, (0x8 << 16) | (0x8 << 0));
327 write32(&mt8173_apmixed->ap_pll_con6, 0x00000000);
328
329 /*************
330 * xPLL PWR ON
331 **************/
332 for (i = 0; i < APMIXED_NR_PLL; i++)
333 setbits_le32(plls[i].pwr_reg, PLL_PWR_ON);
334
335 udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us) */
336
337 /******************
338 * xPLL ISO Disable
339 *******************/
340 for (i = 0; i < APMIXED_NR_PLL; i++)
341 clrbits_le32(plls[i].pwr_reg, PLL_ISO);
342
343 /********************
344 * xPLL Frequency Set
345 *********************/
346
347 pll_set_rate(&plls[APMIXED_ARMCA15PLL], ARMCA15PLL_HZ);
348 pll_set_rate(&plls[APMIXED_ARMCA7PLL], ARMCA7PLL_HZ);
349 pll_set_rate(&plls[APMIXED_MAINPLL], MAINPLL_HZ);
350 pll_set_rate(&plls[APMIXED_UNIVPLL], UNIVPLL_HZ);
351 pll_set_rate(&plls[APMIXED_MMPLL], MMPLL_HZ);
352 pll_set_rate(&plls[APMIXED_MSDCPLL], MSDCPLL_HZ);
353 pll_set_rate(&plls[APMIXED_VENCPLL], VENCPLL_HZ);
354 pll_set_rate(&plls[APMIXED_TVDPLL], TVDPLL_HZ);
355 pll_set_rate(&plls[APMIXED_MPLL], MPLL_HZ);
356 pll_set_rate(&plls[APMIXED_VCODECPLL], VCODECPLL_HZ);
357 pll_set_rate(&plls[APMIXED_LVDSPLL], LVDSPLL_HZ);
358 pll_set_rate(&plls[APMIXED_MSDCPLL2], MSDCPLL2_HZ);
359 pll_set_rate(&plls[APMIXED_APLL1], APLL1_HZ);
360 pll_set_rate(&plls[APMIXED_APLL2], APLL2_HZ);
361
362 /***********************
363 * xPLL Frequency Enable
364 ************************/
365 for (i = 0; i < APMIXED_NR_PLL; i++)
366 setbits_le32(plls[i].reg, PLL_EN);
367
368 udelay(40); /* wait for PLL stable (min delay is 20us) */
369
370 /***************
371 * xPLL DIV RSTB
372 ****************/
373 for (i = 0; i < APMIXED_NR_PLL; i++) {
374 if (plls[i].rstb)
375 setbits_le32(plls[i].reg, plls[i].rstb);
376 }
377
378 /**************
379 * INFRA CLKMUX
380 ***************/
381
382 /* enable infrasys DCM */
383 setbits_le32(&mt8173_infracfg->top_dcmctl, 0x1);
384
385 write32(&mt8173_topckgen->clk_mode, 0x1);
386 write32(&mt8173_topckgen->clk_mode, 0x0); /* enable TOPCKGEN */
387
388 /************
389 * TOP CLKMUX -- DO NOT CHANGE WITHOUT ADJUSTING <soc/pll.h> CONSTANTS!
390 *************/
391
392 /* CLK_CFG_0 */
393 mux_set_sel(&muxes[TOP_AXI_SEL], 5); /* 5: univpll2_d2 */
394 mux_set_sel(&muxes[TOP_MEM_SEL], 0); /* 0: clk26m */
395 mux_set_sel(&muxes[TOP_DDRPHYCFG_SEL], 0); /* 0: clk26m */
396 mux_set_sel(&muxes[TOP_MM_SEL], 1); /* 1: vencpll_d2 */
397 /* CLK_CFG_1 */
398 mux_set_sel(&muxes[TOP_PWM_SEL], 0); /* 0: clk26m */
399 mux_set_sel(&muxes[TOP_VDEC_SEL], 1); /* 1: vcodecpll_ck */
400 mux_set_sel(&muxes[TOP_VENC_SEL], 1); /* 1: vcodecpll_ck */
401 mux_set_sel(&muxes[TOP_MFG_SEL], 1); /* 1: mmpll_ck */
402 /* CLK_CFG_2 */
403 mux_set_sel(&muxes[TOP_CAMTG_SEL], 0); /* 0: clk26m */
404 mux_set_sel(&muxes[TOP_UART_SEL], 0); /* 0: clk26m */
405 mux_set_sel(&muxes[TOP_SPI_SEL], 1); /* 1: syspll3_d2 */
406 mux_set_sel(&muxes[TOP_USB20_SEL], 1); /* 1: univpll1_d8 */
407 /* CLK_CFG_4 */
408 mux_set_sel(&muxes[TOP_MSDC30_2_SEL], 2); /* 2: msdcpll_d4 */
409 mux_set_sel(&muxes[TOP_MSDC30_3_SEL], 5); /* 5: msdcpll_d4 */
410 mux_set_sel(&muxes[TOP_AUDIO_SEL], 0); /* 0: clk26m */
411 mux_set_sel(&muxes[TOP_AUD_INTBUS_SEL], 1); /* 1: syspll1_d4 */
412 /* CLK_CFG_5 */
413 mux_set_sel(&muxes[TOP_PMICSPI_SEL], 0); /* 0: clk26m */
414 mux_set_sel(&muxes[TOP_SCP_SEL], 1); /* 1: syspll1_d2 */
415 mux_set_sel(&muxes[TOP_ATB_SEL], 0); /* 0: clk26m */
416 mux_set_sel(&muxes[TOP_VENC_LT_SEL], 6); /* 6: univpll1_d2 */
417 /* CLK_CFG_6 */
418 mux_set_sel(&muxes[TOP_DPI0_SEL], 1); /* 1: tvdpll_d2 */
419 mux_set_sel(&muxes[TOP_IRDA_SEL], 1); /* 1: univpll2_d4 */
420 mux_set_sel(&muxes[TOP_CCI400_SEL], 5); /* 5: syspll_d2 */
421 mux_set_sel(&muxes[TOP_AUD_1_SEL], 1); /* 1: apll1_ck */
422 /* CLK_CFG_7 */
423 mux_set_sel(&muxes[TOP_AUD_2_SEL], 1); /* 1: apll2_ck */
424 mux_set_sel(&muxes[TOP_MEM_MFG_IN_SEL], 1); /* 1: mmpll_ck */
425 mux_set_sel(&muxes[TOP_AXI_MFG_IN_SEL], 1); /* 1: hd_faxi_ck */
426 mux_set_sel(&muxes[TOP_SCAM_SEL], 1); /* 1: syspll3_d2 */
427 /* CLK_CFG_12 */
428 mux_set_sel(&muxes[TOP_SPINFI_IFR_SEL], 0); /* 0: clk26m */
429 mux_set_sel(&muxes[TOP_HDMI_SEL], 1); /* 1: AD_HDMITX_CLK */
430 mux_set_sel(&muxes[TOP_DPILVDS_SEL], 1); /* 1: AD_LVDSPLL_CK */
431 /* CLK_CFG_13 */
432 mux_set_sel(&muxes[TOP_MSDC50_2_H_SEL], 2); /* 2: syspll2_d2 */
433 mux_set_sel(&muxes[TOP_HDCP_SEL], 2); /* 2: syspll3_d4 */
434 mux_set_sel(&muxes[TOP_HDCP_24M_SEL], 2); /* 2: univpll_d52 */
435 mux_set_sel(&muxes[TOP_RTC_SEL], 1); /* 1: clkrtc_ext */
436 /* CLK_CFG_3 */
437 mux_set_sel(&muxes[TOP_USB30_SEL], 1); /* 1: univpll3_d2 */
438 mux_set_sel(&muxes[TOP_MSDC50_0_H_SEL], 2); /* 2: syspll2_d2 */
439 mux_set_sel(&muxes[TOP_MSDC50_0_SEL], 6); /* 6: msdcpll_d4 */
440 mux_set_sel(&muxes[TOP_MSDC30_1_SEL], 2); /* 2: msdcpll_d4 */
441
442 /* enable scpsys clock off control */
443 write32(&mt8173_topckgen->clk_scp_cfg_0,
444 (1 << 10) | (1 << 9) | (1 << 5) | (1 << 4) | (1 << 2) |
445 (1 << 1) | (1 << 0));
446 write32(&mt8173_topckgen->clk_scp_cfg_1,
447 (1 << 4) | (1 << 2) | (1 << 0));
448}
449
450/* after pmic_init */
451void mt_pll_post_init(void)
452{
453 /* CPU clock divide by 1 */
454 clrbits_le32(&mt8173_infracfg->top_ckdiv1, 0x3ff);
455
456 /* select ARMPLL */
457 /* TODO: possibly raise ARMPLL frequency here */
458 /* NOTICE: raise Vproc voltage before raise ARMPLL frequency */
459 write32(&mt8173_infracfg->top_ckmuxsel, (1 << 2) | 1);
460}