summaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8173/pll.c
diff options
context:
space:
mode:
authorJames Liao <jamesjj.liao@mediatek.com>2015-07-31 17:10:53 +0800
committerPatrick Georgi <pgeorgi@google.com>2015-12-03 14:17:12 +0100
commitf9fad12875d2ecbf47a3af5788f672eed406a9c5 (patch)
treedc1e6c1e78220be7577eb05094beeb7019f4c601 /src/soc/mediatek/mt8173/pll.c
parent3d7b6069e1c8e4e2054fd4648e8089f20a1990ff (diff)
downloadcoreboot-f9fad12875d2ecbf47a3af5788f672eed406a9c5.tar.xz
mediatek/mt8173: Add PLL driver
Add PLL init code. BRANCH=none BUG=none TEST=none Change-Id: I2dcea8cdea1a3812bd8b84b7e8d961e7f8d4d953 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: e6e2eecb2fad30db018685b61912103f5e2cd524 Original-Change-Id: Id67d8033f3b2a267a140d7d73daa5727bc032272 Original-Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Original-Reviewed-on: https://chromium-review.googlesource.com/292670 Original-Commit-Ready: Yidi Lin <yidi.lin@mediatek.com> Original-Tested-by: Yidi Lin <yidi.lin@mediatek.com> Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/12588 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/mediatek/mt8173/pll.c')
-rw-r--r--src/soc/mediatek/mt8173/pll.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8173/pll.c b/src/soc/mediatek/mt8173/pll.c
new file mode 100644
index 0000000000..f1ea9a9f03
--- /dev/null
+++ b/src/soc/mediatek/mt8173/pll.c
@@ -0,0 +1,460 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <assert.h>
+#include <console/console.h>
+#include <delay.h>
+#include <stddef.h>
+
+#include <soc/addressmap.h>
+#include <soc/infracfg.h>
+#include <soc/pll.h>
+
+#define GENMASK(h, l) (((1U << ((h) - (l) + 1)) - 1) << (l))
+
+enum mux_id {
+ TOP_AXI_SEL,
+ TOP_MEM_SEL,
+ TOP_DDRPHYCFG_SEL,
+ TOP_MM_SEL,
+ TOP_PWM_SEL,
+ TOP_VDEC_SEL,
+ TOP_VENC_SEL,
+ TOP_MFG_SEL,
+ TOP_CAMTG_SEL,
+ TOP_UART_SEL,
+ TOP_SPI_SEL,
+ TOP_USB20_SEL,
+ TOP_USB30_SEL,
+ TOP_MSDC50_0_H_SEL,
+ TOP_MSDC50_0_SEL,
+ TOP_MSDC30_1_SEL,
+ TOP_MSDC30_2_SEL,
+ TOP_MSDC30_3_SEL,
+ TOP_AUDIO_SEL,
+ TOP_AUD_INTBUS_SEL,
+ TOP_PMICSPI_SEL,
+ TOP_SCP_SEL,
+ TOP_ATB_SEL,
+ TOP_VENC_LT_SEL,
+ TOP_DPI0_SEL,
+ TOP_IRDA_SEL,
+ TOP_CCI400_SEL,
+ TOP_AUD_1_SEL,
+ TOP_AUD_2_SEL,
+ TOP_MEM_MFG_IN_SEL,
+ TOP_AXI_MFG_IN_SEL,
+ TOP_SCAM_SEL,
+ TOP_SPINFI_IFR_SEL,
+ TOP_HDMI_SEL,
+ TOP_DPILVDS_SEL,
+ TOP_MSDC50_2_H_SEL,
+ TOP_HDCP_SEL,
+ TOP_HDCP_24M_SEL,
+ TOP_RTC_SEL,
+ TOP_NR_MUX
+};
+
+#define TOPCKGEN_REG(x) (CKSYS_BASE + offsetof(struct mt8173_topckgen_regs, x))
+#define APMIXED_REG(x) (APMIXED_BASE + offsetof(struct mt8173_apmixed_regs, x))
+
+struct mux {
+ void *reg;
+ u8 mux_shift;
+ u8 mux_width;
+};
+
+#define MUX(_id, _reg, _mux_shift, _mux_width) \
+ [_id] = { \
+ .reg = (void *)TOPCKGEN_REG(_reg), \
+ .mux_shift = _mux_shift, \
+ .mux_width = _mux_width, \
+ }
+
+static const struct mux muxes[] = {
+ /* CLK_CFG_0 */
+ MUX(TOP_AXI_SEL, clk_cfg_0, 0, 3),
+ MUX(TOP_MEM_SEL, clk_cfg_0, 8, 1),
+ MUX(TOP_DDRPHYCFG_SEL, clk_cfg_0, 16, 1),
+ MUX(TOP_MM_SEL, clk_cfg_0, 24, 4),
+ /* CLK_CFG_1 */
+ MUX(TOP_PWM_SEL, clk_cfg_1, 0, 2),
+ MUX(TOP_VDEC_SEL, clk_cfg_1, 8, 4),
+ MUX(TOP_VENC_SEL, clk_cfg_1, 16, 4),
+ MUX(TOP_MFG_SEL, clk_cfg_1, 24, 4),
+ /* CLK_CFG_2 */
+ MUX(TOP_CAMTG_SEL, clk_cfg_2, 0, 3),
+ MUX(TOP_UART_SEL, clk_cfg_2, 8, 1),
+ MUX(TOP_SPI_SEL, clk_cfg_2, 16, 3),
+ MUX(TOP_USB20_SEL, clk_cfg_2, 24, 2),
+ /* CLK_CFG_3 */
+ MUX(TOP_USB30_SEL, clk_cfg_3, 0, 2),
+ MUX(TOP_MSDC50_0_H_SEL, clk_cfg_3, 8, 3),
+ MUX(TOP_MSDC50_0_SEL, clk_cfg_3, 16, 4),
+ MUX(TOP_MSDC30_1_SEL, clk_cfg_3, 24, 3),
+ /* CLK_CFG_4 */
+ MUX(TOP_MSDC30_2_SEL, clk_cfg_4, 0, 3),
+ MUX(TOP_MSDC30_3_SEL, clk_cfg_4, 8, 4),
+ MUX(TOP_AUDIO_SEL, clk_cfg_4, 16, 2),
+ MUX(TOP_AUD_INTBUS_SEL, clk_cfg_4, 24, 3),
+ /* CLK_CFG_5 */
+ MUX(TOP_PMICSPI_SEL, clk_cfg_5, 0, 3),
+ MUX(TOP_SCP_SEL, clk_cfg_5, 8, 3),
+ MUX(TOP_ATB_SEL, clk_cfg_5, 16, 2),
+ MUX(TOP_VENC_LT_SEL, clk_cfg_5, 24, 4),
+ /* CLK_CFG_6 */
+ MUX(TOP_DPI0_SEL, clk_cfg_6, 0, 3),
+ MUX(TOP_IRDA_SEL, clk_cfg_6, 8, 2),
+ MUX(TOP_CCI400_SEL, clk_cfg_6, 16, 3),
+ MUX(TOP_AUD_1_SEL, clk_cfg_6, 24, 2),
+ /* CLK_CFG_7 */
+ MUX(TOP_AUD_2_SEL, clk_cfg_7, 0, 2),
+ MUX(TOP_MEM_MFG_IN_SEL, clk_cfg_7, 8, 2),
+ MUX(TOP_AXI_MFG_IN_SEL, clk_cfg_7, 16, 2),
+ MUX(TOP_SCAM_SEL, clk_cfg_7, 24, 2),
+ /* CLK_CFG_12 */
+ MUX(TOP_SPINFI_IFR_SEL, clk_cfg_12, 0, 3),
+ MUX(TOP_HDMI_SEL, clk_cfg_12, 8, 2),
+ MUX(TOP_DPILVDS_SEL, clk_cfg_12, 24, 3),
+ /* CLK_CFG_13 */
+ MUX(TOP_MSDC50_2_H_SEL, clk_cfg_13, 0, 3),
+ MUX(TOP_HDCP_SEL, clk_cfg_13, 8, 2),
+ MUX(TOP_HDCP_24M_SEL, clk_cfg_13, 16, 2),
+ MUX(TOP_RTC_SEL, clk_cfg_13, 24, 2),
+};
+
+static void mux_set_sel(const struct mux *mux, u32 sel)
+{
+ u32 mask = GENMASK(mux->mux_width - 1, 0);
+ u32 val = read32(mux->reg);
+
+ val &= ~(mask << mux->mux_shift);
+ val |= (sel & mask) << mux->mux_shift;
+ write32(mux->reg, val);
+}
+
+#define PLL_PWR_ON (1 << 0)
+#define PLL_EN (1 << 0)
+#define PLL_ISO (1 << 1)
+#define PLL_RSTB (1 << 24)
+#define PLL_PCW_CHG (1 << 31)
+#define PLL_POSTDIV_MASK 0x7
+#define PCW_INTEGER_BITS 7
+
+enum pll_id {
+ APMIXED_ARMCA15PLL,
+ APMIXED_ARMCA7PLL,
+ APMIXED_MAINPLL,
+ APMIXED_UNIVPLL,
+ APMIXED_MMPLL,
+ APMIXED_MSDCPLL,
+ APMIXED_VENCPLL,
+ APMIXED_TVDPLL,
+ APMIXED_MPLL,
+ APMIXED_VCODECPLL,
+ APMIXED_APLL1,
+ APMIXED_APLL2,
+ APMIXED_LVDSPLL,
+ APMIXED_MSDCPLL2,
+ APMIXED_NR_PLL
+};
+
+const u32 pll_div_rate[] = {
+ 3UL * GHz,
+ 1 * GHz,
+ 500 * MHz,
+ 250 * MHz,
+ 125 * MHz,
+ 0,
+};
+
+const u32 univpll_div_rate[] = {
+ 3UL * GHz,
+ 1500 * MHz,
+ 750 * MHz,
+ 375 * MHz,
+ 187500 * KHz,
+ 0,
+};
+
+const u32 mmpll_div_rate[] = {
+ 3UL * GHz,
+ 1 * GHz,
+ 702 * MHz,
+ 253500 * KHz,
+ 126750 * KHz,
+ 0,
+};
+
+struct pll {
+ void *reg;
+ void *pwr_reg;
+ u32 rstb;
+ u8 pcwbits;
+ void *div_reg;
+ u8 div_shift;
+ void *pcw_reg;
+ u8 pcw_shift;
+ const u32 *div_rate;
+};
+
+#define PLL(_id, _reg, _pwr_reg, _rstb, _pcwbits, _div_reg, _div_shift, \
+ _pcw_reg, _pcw_shift, _div_rate) \
+ [_id] = { \
+ .reg = (void *)APMIXED_REG(_reg), \
+ .pwr_reg = (void *)APMIXED_REG(_pwr_reg), \
+ .rstb = _rstb, \
+ .pcwbits = _pcwbits, \
+ .div_reg = (void *)APMIXED_REG(_div_reg), \
+ .div_shift = _div_shift, \
+ .pcw_reg = (void *)APMIXED_REG(_pcw_reg), \
+ .pcw_shift = _pcw_shift, \
+ .div_rate = _div_rate, \
+ }
+
+static const struct pll plls[] = {
+ PLL(APMIXED_ARMCA15PLL, armca15pll_con0, armca15pll_pwr_con0, 0, 21,
+ armca15pll_con1, 24, armca15pll_con1, 0, pll_div_rate),
+ PLL(APMIXED_ARMCA7PLL, armca7pll_con0, armca7pll_pwr_con0, PLL_RSTB, 21,
+ armca7pll_con1, 24, armca7pll_con1, 0, pll_div_rate),
+ PLL(APMIXED_MAINPLL, mainpll_con0, mainpll_pwr_con0, PLL_RSTB, 21,
+ mainpll_con0, 4, mainpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_UNIVPLL, univpll_con0, univpll_pwr_con0, PLL_RSTB, 7,
+ univpll_con0, 4, univpll_con1, 14, univpll_div_rate),
+ PLL(APMIXED_MMPLL, mmpll_con0, mmpll_pwr_con0, 0, 21,
+ mmpll_con1, 24, mmpll_con1, 0, mmpll_div_rate),
+ PLL(APMIXED_MSDCPLL, msdcpll_con0, msdcpll_pwr_con0, 0, 21,
+ msdcpll_con0, 4, msdcpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_VENCPLL, vencpll_con0, vencpll_pwr_con0, 0, 21,
+ vencpll_con0, 4, vencpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_TVDPLL, tvdpll_con0, tvdpll_pwr_con0, 0, 21,
+ tvdpll_con0, 4, tvdpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_MPLL, mpll_con0, mpll_pwr_con0, 0, 21,
+ mpll_con0, 4, mpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_VCODECPLL, vcodecpll_con0, vcodecpll_pwr_con0, 0, 21,
+ vcodecpll_con0, 4, vcodecpll_con1, 0, pll_div_rate),
+ PLL(APMIXED_APLL1, apll1_con0, apll1_pwr_con0, 0, 31,
+ apll1_con0, 4, apll1_con1, 0, pll_div_rate),
+ PLL(APMIXED_APLL2, apll2_con0, apll2_pwr_con0, 0, 31,
+ apll2_con0, 4, apll2_con1, 0, pll_div_rate),
+ PLL(APMIXED_LVDSPLL, lvdspll_con0, lvdspll_pwr_con0, 0, 21,
+ lvdspll_con0, 4, lvdspll_con1, 0, pll_div_rate),
+ PLL(APMIXED_MSDCPLL2, msdcpll2_con0, msdcpll2_pwr_con0, 0, 21,
+ msdcpll2_con0, 4, msdcpll2_con1, 0, pll_div_rate),
+};
+
+static void pll_set_rate_regs(const struct pll *pll, u32 pcw, u32 postdiv)
+{
+ u32 val;
+
+ /* set postdiv */
+ val = read32(pll->div_reg);
+ val &= ~(PLL_POSTDIV_MASK << pll->div_shift);
+ val |= postdiv << pll->div_shift;
+
+ /* postdiv and pcw need to set at the same time if on same register */
+ if (pll->div_reg != pll->pcw_reg) {
+ write32(pll->div_reg, val);
+ val = read32(pll->pcw_reg);
+ }
+
+ /* set pcw */
+ val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift);
+ val |= pcw << pll->pcw_shift;
+ val |= PLL_PCW_CHG;
+ write32(pll->pcw_reg, val);
+}
+
+static void pll_calc_values(const struct pll *pll, u32 *pcw, u32 *postdiv,
+ u32 freq)
+{
+ const u32 fin_hz = CLK26M_HZ;
+ const u32 *div_rate = pll->div_rate;
+ u32 val;
+
+ assert(freq <= div_rate[0]);
+ assert(freq >= 1 * GHz / 16);
+
+ for (val = 1; div_rate[val] != 0; val++) {
+ if (freq > div_rate[val])
+ break;
+ }
+ val--;
+ *postdiv = val;
+
+ /* _pcw = freq * 2^postdiv / fin * 2^pcwbits_fractional */
+ val += pll->pcwbits - PCW_INTEGER_BITS;
+
+ *pcw = ((u64)freq << val) / fin_hz;
+}
+
+static int pll_set_rate(const struct pll *pll, u32 rate)
+{
+ u32 pcw = 0;
+ u32 postdiv;
+
+ pll_calc_values(pll, &pcw, &postdiv, rate);
+ pll_set_rate_regs(pll, pcw, postdiv);
+
+ return 0;
+}
+
+void mt_pll_init(void)
+{
+ int i;
+
+ /* reduce CLKSQ disable time */
+ write32(&mt8173_apmixed->clksq_stb_con0, (0x05 << 8) | (0x01 << 0));
+ /* extend PWR/ISO control timing to 1us */
+ write32(&mt8173_apmixed->pll_iso_con0, (0x8 << 16) | (0x8 << 0));
+ write32(&mt8173_apmixed->ap_pll_con6, 0x00000000);
+
+ /*************
+ * xPLL PWR ON
+ **************/
+ for (i = 0; i < APMIXED_NR_PLL; i++)
+ setbits_le32(plls[i].pwr_reg, PLL_PWR_ON);
+
+ udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us) */
+
+ /******************
+ * xPLL ISO Disable
+ *******************/
+ for (i = 0; i < APMIXED_NR_PLL; i++)
+ clrbits_le32(plls[i].pwr_reg, PLL_ISO);
+
+ /********************
+ * xPLL Frequency Set
+ *********************/
+
+ pll_set_rate(&plls[APMIXED_ARMCA15PLL], ARMCA15PLL_HZ);
+ pll_set_rate(&plls[APMIXED_ARMCA7PLL], ARMCA7PLL_HZ);
+ pll_set_rate(&plls[APMIXED_MAINPLL], MAINPLL_HZ);
+ pll_set_rate(&plls[APMIXED_UNIVPLL], UNIVPLL_HZ);
+ pll_set_rate(&plls[APMIXED_MMPLL], MMPLL_HZ);
+ pll_set_rate(&plls[APMIXED_MSDCPLL], MSDCPLL_HZ);
+ pll_set_rate(&plls[APMIXED_VENCPLL], VENCPLL_HZ);
+ pll_set_rate(&plls[APMIXED_TVDPLL], TVDPLL_HZ);
+ pll_set_rate(&plls[APMIXED_MPLL], MPLL_HZ);
+ pll_set_rate(&plls[APMIXED_VCODECPLL], VCODECPLL_HZ);
+ pll_set_rate(&plls[APMIXED_LVDSPLL], LVDSPLL_HZ);
+ pll_set_rate(&plls[APMIXED_MSDCPLL2], MSDCPLL2_HZ);
+ pll_set_rate(&plls[APMIXED_APLL1], APLL1_HZ);
+ pll_set_rate(&plls[APMIXED_APLL2], APLL2_HZ);
+
+ /***********************
+ * xPLL Frequency Enable
+ ************************/
+ for (i = 0; i < APMIXED_NR_PLL; i++)
+ setbits_le32(plls[i].reg, PLL_EN);
+
+ udelay(40); /* wait for PLL stable (min delay is 20us) */
+
+ /***************
+ * xPLL DIV RSTB
+ ****************/
+ for (i = 0; i < APMIXED_NR_PLL; i++) {
+ if (plls[i].rstb)
+ setbits_le32(plls[i].reg, plls[i].rstb);
+ }
+
+ /**************
+ * INFRA CLKMUX
+ ***************/
+
+ /* enable infrasys DCM */
+ setbits_le32(&mt8173_infracfg->top_dcmctl, 0x1);
+
+ write32(&mt8173_topckgen->clk_mode, 0x1);
+ write32(&mt8173_topckgen->clk_mode, 0x0); /* enable TOPCKGEN */
+
+ /************
+ * TOP CLKMUX -- DO NOT CHANGE WITHOUT ADJUSTING <soc/pll.h> CONSTANTS!
+ *************/
+
+ /* CLK_CFG_0 */
+ mux_set_sel(&muxes[TOP_AXI_SEL], 5); /* 5: univpll2_d2 */
+ mux_set_sel(&muxes[TOP_MEM_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_DDRPHYCFG_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_MM_SEL], 1); /* 1: vencpll_d2 */
+ /* CLK_CFG_1 */
+ mux_set_sel(&muxes[TOP_PWM_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_VDEC_SEL], 1); /* 1: vcodecpll_ck */
+ mux_set_sel(&muxes[TOP_VENC_SEL], 1); /* 1: vcodecpll_ck */
+ mux_set_sel(&muxes[TOP_MFG_SEL], 1); /* 1: mmpll_ck */
+ /* CLK_CFG_2 */
+ mux_set_sel(&muxes[TOP_CAMTG_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_UART_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_SPI_SEL], 1); /* 1: syspll3_d2 */
+ mux_set_sel(&muxes[TOP_USB20_SEL], 1); /* 1: univpll1_d8 */
+ /* CLK_CFG_4 */
+ mux_set_sel(&muxes[TOP_MSDC30_2_SEL], 2); /* 2: msdcpll_d4 */
+ mux_set_sel(&muxes[TOP_MSDC30_3_SEL], 5); /* 5: msdcpll_d4 */
+ mux_set_sel(&muxes[TOP_AUDIO_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_AUD_INTBUS_SEL], 1); /* 1: syspll1_d4 */
+ /* CLK_CFG_5 */
+ mux_set_sel(&muxes[TOP_PMICSPI_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_SCP_SEL], 1); /* 1: syspll1_d2 */
+ mux_set_sel(&muxes[TOP_ATB_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_VENC_LT_SEL], 6); /* 6: univpll1_d2 */
+ /* CLK_CFG_6 */
+ mux_set_sel(&muxes[TOP_DPI0_SEL], 1); /* 1: tvdpll_d2 */
+ mux_set_sel(&muxes[TOP_IRDA_SEL], 1); /* 1: univpll2_d4 */
+ mux_set_sel(&muxes[TOP_CCI400_SEL], 5); /* 5: syspll_d2 */
+ mux_set_sel(&muxes[TOP_AUD_1_SEL], 1); /* 1: apll1_ck */
+ /* CLK_CFG_7 */
+ mux_set_sel(&muxes[TOP_AUD_2_SEL], 1); /* 1: apll2_ck */
+ mux_set_sel(&muxes[TOP_MEM_MFG_IN_SEL], 1); /* 1: mmpll_ck */
+ mux_set_sel(&muxes[TOP_AXI_MFG_IN_SEL], 1); /* 1: hd_faxi_ck */
+ mux_set_sel(&muxes[TOP_SCAM_SEL], 1); /* 1: syspll3_d2 */
+ /* CLK_CFG_12 */
+ mux_set_sel(&muxes[TOP_SPINFI_IFR_SEL], 0); /* 0: clk26m */
+ mux_set_sel(&muxes[TOP_HDMI_SEL], 1); /* 1: AD_HDMITX_CLK */
+ mux_set_sel(&muxes[TOP_DPILVDS_SEL], 1); /* 1: AD_LVDSPLL_CK */
+ /* CLK_CFG_13 */
+ mux_set_sel(&muxes[TOP_MSDC50_2_H_SEL], 2); /* 2: syspll2_d2 */
+ mux_set_sel(&muxes[TOP_HDCP_SEL], 2); /* 2: syspll3_d4 */
+ mux_set_sel(&muxes[TOP_HDCP_24M_SEL], 2); /* 2: univpll_d52 */
+ mux_set_sel(&muxes[TOP_RTC_SEL], 1); /* 1: clkrtc_ext */
+ /* CLK_CFG_3 */
+ mux_set_sel(&muxes[TOP_USB30_SEL], 1); /* 1: univpll3_d2 */
+ mux_set_sel(&muxes[TOP_MSDC50_0_H_SEL], 2); /* 2: syspll2_d2 */
+ mux_set_sel(&muxes[TOP_MSDC50_0_SEL], 6); /* 6: msdcpll_d4 */
+ mux_set_sel(&muxes[TOP_MSDC30_1_SEL], 2); /* 2: msdcpll_d4 */
+
+ /* enable scpsys clock off control */
+ write32(&mt8173_topckgen->clk_scp_cfg_0,
+ (1 << 10) | (1 << 9) | (1 << 5) | (1 << 4) | (1 << 2) |
+ (1 << 1) | (1 << 0));
+ write32(&mt8173_topckgen->clk_scp_cfg_1,
+ (1 << 4) | (1 << 2) | (1 << 0));
+}
+
+/* after pmic_init */
+void mt_pll_post_init(void)
+{
+ /* CPU clock divide by 1 */
+ clrbits_le32(&mt8173_infracfg->top_ckdiv1, 0x3ff);
+
+ /* select ARMPLL */
+ /* TODO: possibly raise ARMPLL frequency here */
+ /* NOTICE: raise Vproc voltage before raise ARMPLL frequency */
+ write32(&mt8173_infracfg->top_ckmuxsel, (1 << 2) | 1);
+}