From: James Liao <[email protected]>

This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
INFRA and PERI clocks.

Signed-off-by: James Liao <[email protected]>
Signed-off-by: Henry Chen <[email protected]>
Signed-off-by: Sascha Hauer <[email protected]>
---
 drivers/clk/mediatek/Makefile         |   1 +
 drivers/clk/mediatek/clk-mt8135-pll.c | 860 +++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mt8135-pll.h |  28 ++
 drivers/clk/mediatek/clk-mt8135.c     | 873 ++++++++++++++++++++++++++++++++++
 4 files changed, 1762 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8135-pll.c
 create mode 100644 drivers/clk/mediatek/clk-mt8135-pll.h
 create mode 100644 drivers/clk/mediatek/clk-mt8135.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 0b6f1c3..afb52e5 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,2 +1,3 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o clk-mt8135-pll.o
diff --git a/drivers/clk/mediatek/clk-mt8135-pll.c 
b/drivers/clk/mediatek/clk-mt8135-pll.c
new file mode 100644
index 0000000..81f5a00
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135-pll.c
@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+#include "clk-mt8135-pll.h"
+
+#define PLL_BASE_EN    BIT(0)
+#define PLL_PWR_ON     BIT(0)
+#define PLL_ISO_EN     BIT(1)
+#define PLL_PCW_CHG    BIT(31)
+#define RST_BAR_MASK   BIT(27)
+#define AUDPLL_TUNER_EN        BIT(31)
+
+#define PLL_PREDIV_H           5
+#define PLL_PREDIV_L           4
+#define PLL_PREDIV_MASK                GENMASK(PLL_PREDIV_H, PLL_PREDIV_L)
+#define PLL_VCODIV_L           19
+#define PLL_VCODIV_MASK                BIT(19)
+
+static const u32 pll_vcodivsel_map[2] = { 1, 2 };
+static const u32 pll_prediv_map[4] = { 1, 2, 4, 4 };
+static const u32 pll_posdiv_map[8] = { 1, 2, 4, 8, 16, 16, 16, 16 };
+static const u32 pll_fbksel_map[4] = { 1, 2, 4, 4 };
+
+static u32 mtk_calc_pll_vco_freq(
+               u32 fin,
+               u32 pcw,
+               u32 vcodivsel,
+               u32 prediv,
+               u32 pcwfbits)
+{
+       /* vco = (fin * pcw * vcodivsel / prediv) >> pcwfbits; */
+       u64 vco = fin;
+       u8 c = 0;
+
+       vco = vco * pcw * vcodivsel;
+       do_div(vco, prediv);
+
+       if (vco & GENMASK(pcwfbits - 1, 0))
+               c = 1;
+
+       vco >>= pcwfbits;
+
+       if (c)
+               ++vco;
+
+       return (u32)vco;
+}
+
+static u32 mtk_freq_limit(u32 freq)
+{
+       static const u32 freq_max = 2000 * 1000 * 1000;         /* 2000 MHz */
+       static const u32 freq_min = 1000 * 1000 * 1000 / 16;    /* 62.5 MHz */
+
+       if (freq <= freq_min)
+               freq = freq_min + 16;
+       else if (freq > freq_max)
+               freq = freq_max;
+
+       return freq;
+}
+
+static int mtk_calc_pll_freq_cfg(
+               u32 *pcw,
+               u32 *postdiv_idx,
+               u32 freq,
+               u32 fin,
+               int pcwfbits)
+{
+       static const u64 freq_max = 2000 * 1000 * 1000; /* 2000 MHz */
+       static const u64 freq_min = 1000 * 1000 * 1000; /* 1000 MHz */
+       static const u64 postdiv[] = { 1, 2, 4, 8, 16 };
+       u64 n_info;
+       u32 idx;
+
+       /* search suitable postdiv */
+       for (idx = 0;
+               idx < ARRAY_SIZE(postdiv) && postdiv[idx] * freq <= freq_min;
+               idx++)
+               ;
+
+       if (idx >= ARRAY_SIZE(postdiv))
+               return -EINVAL; /* freq is out of range (too low) */
+       else if (postdiv[idx] * freq > freq_max)
+               return -EINVAL; /* freq is out of range (too high) */
+
+       /* n_info = freq * postdiv / 26MHz * 2^pcwfbits */
+       n_info = (postdiv[idx] * freq) << pcwfbits;
+       do_div(n_info, fin);
+
+       *postdiv_idx = idx;
+       *pcw = (u32)n_info;
+
+       return 0;
+}
+
+static int mtk_clk_pll_is_enabled(struct clk_hw *hw)
+{
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+       return (readl_relaxed(pll->base_addr) & PLL_BASE_EN) != 0;
+}
+
+static int mtk_clk_pll_prepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       u32 r;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON;
+       writel_relaxed(r, pll->pwr_addr);
+       wmb();  /* sync write before delay */
+       udelay(1);
+
+       r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN;
+       writel_relaxed(r, pll->pwr_addr);
+       wmb();  /* sync write before delay */
+       udelay(1);
+
+       r = readl_relaxed(pll->base_addr) | pll->en_mask;
+       writel_relaxed(r, pll->base_addr);
+       wmb();  /* sync write before delay */
+       udelay(20);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(pll->base_addr) | RST_BAR_MASK;
+               writel_relaxed(r, pll->base_addr);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+
+       return 0;
+}
+
+static void mtk_clk_pll_unprepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       u32 r;
+
+       if (pll->flags & PLL_AO)
+               return;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(pll->base_addr) & ~RST_BAR_MASK;
+               writel_relaxed(r, pll->base_addr);
+       }
+
+       r = readl_relaxed(pll->base_addr) & ~PLL_BASE_EN;
+       writel_relaxed(r, pll->base_addr);
+
+       r = readl_relaxed(pll->pwr_addr) | PLL_ISO_EN;
+       writel_relaxed(r, pll->pwr_addr);
+
+       r = readl_relaxed(pll->pwr_addr) & ~PLL_PWR_ON;
+       writel_relaxed(r, pll->pwr_addr);
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static long mtk_clk_pll_round_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long *prate)
+{
+       u32 pcwfbits = 14;
+       u32 pcw = 0;
+       u32 postdiv = 0;
+       u32 r;
+
+       *prate = *prate ? *prate : 26000000;
+       rate = mtk_freq_limit(rate);
+       mtk_calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+       r = mtk_calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+       r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv];
+
+       return r;
+}
+
+#define SDM_PLL_POSTDIV_H      8
+#define SDM_PLL_POSTDIV_L      6
+#define SDM_PLL_POSTDIV_MASK   GENMASK(SDM_PLL_POSTDIV_H, SDM_PLL_POSTDIV_L)
+#define SDM_PLL_PCW_H          20
+#define SDM_PLL_PCW_L          0
+#define SDM_PLL_PCW_MASK       GENMASK(SDM_PLL_PCW_H, SDM_PLL_PCW_L)
+
+static unsigned long mtk_clk_pll_recalc_rate(
+               struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+       u32 con0 = readl_relaxed(pll->base_addr);
+       u32 con1 = readl_relaxed(pll->base_addr + 4);
+
+       u32 vcodivsel = (con0 & PLL_VCODIV_MASK) >> PLL_VCODIV_L;
+       u32 prediv = (con0 & PLL_PREDIV_MASK) >> PLL_PREDIV_L;
+       u32 posdiv = (con0 & SDM_PLL_POSTDIV_MASK) >> SDM_PLL_POSTDIV_L;
+       u32 pcw = (con1 & SDM_PLL_PCW_MASK) >> SDM_PLL_PCW_L;
+       u32 pcwfbits = 14;
+
+       u32 vco_freq;
+       unsigned long r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       vcodivsel = pll_vcodivsel_map[vcodivsel];
+       prediv = pll_prediv_map[prediv];
+
+       vco_freq = mtk_calc_pll_vco_freq(
+                       parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+       r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv];
+
+       return r;
+}
+
+static void mtk_clk_pll_set_rate_regs(
+               struct clk_hw *hw,
+               u32 pcw,
+               u32 postdiv_idx)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con1_addr = pll->base_addr + 4;
+       u32 con0;
+       u32 con1;
+       u32 pll_en;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       con0 = readl_relaxed(con0_addr);
+       con1 = readl_relaxed(con1_addr);
+
+       pll_en = con0 & PLL_BASE_EN;
+
+       /* set postdiv */
+       con0 &= ~SDM_PLL_POSTDIV_MASK;
+       con0 |= postdiv_idx << SDM_PLL_POSTDIV_L;
+       writel_relaxed(con0, con0_addr);
+
+       /* set pcw */
+       con1 &= ~SDM_PLL_PCW_MASK;
+       con1 |= pcw << SDM_PLL_PCW_L;
+
+       if (pll_en)
+               con1 |= PLL_PCW_CHG;
+
+       writel_relaxed(con1, con1_addr);
+
+       if (pll_en) {
+               wmb();  /* sync write before delay */
+               udelay(20);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int mtk_clk_pll_set_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long parent_rate)
+{
+       u32 pcwfbits = 14;
+       u32 pcw = 0;
+       u32 postdiv_idx = 0;
+       int r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       r = mtk_calc_pll_freq_cfg(&pcw, &postdiv_idx, rate,
+                       parent_rate, pcwfbits);
+
+       if (r == 0)
+               mtk_clk_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+       return r;
+}
+
+const struct clk_ops mt8135_pll_ops = {
+       .is_enabled     = mtk_clk_pll_is_enabled,
+       .prepare        = mtk_clk_pll_prepare,
+       .unprepare      = mtk_clk_pll_unprepare,
+       .recalc_rate    = mtk_clk_pll_recalc_rate,
+       .round_rate     = mtk_clk_pll_round_rate,
+       .set_rate       = mtk_clk_pll_set_rate,
+};
+
+#define ARM_PLL_POSTDIV_H      26
+#define ARM_PLL_POSTDIV_L      24
+#define ARM_PLL_POSTDIV_MASK   GENMASK(ARM_PLL_POSTDIV_H, ARM_PLL_POSTDIV_L)
+#define ARM_PLL_PCW_H          20
+#define ARM_PLL_PCW_L          0
+#define ARM_PLL_PCW_MASK       GENMASK(ARM_PLL_PCW_H, ARM_PLL_PCW_L)
+
+static unsigned long mtk_clk_arm_pll_recalc_rate(
+               struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+       u32 con0 = readl_relaxed(pll->base_addr);
+       u32 con1 = readl_relaxed(pll->base_addr + 4);
+
+       u32 vcodivsel = (con0 & PLL_VCODIV_MASK) >> PLL_VCODIV_L;
+       u32 prediv = (con0 & PLL_PREDIV_MASK) >> PLL_PREDIV_L;
+       u32 posdiv = (con1 & ARM_PLL_POSTDIV_MASK) >> ARM_PLL_POSTDIV_L;
+       u32 pcw = (con1 & ARM_PLL_PCW_MASK) >> ARM_PLL_PCW_L;
+       u32 pcwfbits = 14;
+
+       u32 vco_freq;
+       unsigned long r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       vcodivsel = pll_vcodivsel_map[vcodivsel];
+       prediv = pll_prediv_map[prediv];
+
+       vco_freq = mtk_calc_pll_vco_freq(
+                       parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+       r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv];
+
+       return r;
+}
+
+static void mtk_clk_arm_pll_set_rate_regs(
+               struct clk_hw *hw,
+               u32 pcw,
+               u32 postdiv_idx)
+
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con1_addr = pll->base_addr + 4;
+       u32 con0;
+       u32 con1;
+       u32 pll_en;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       con0 = readl_relaxed(con0_addr);
+       con1 = readl_relaxed(con1_addr);
+
+       pll_en = con0 & PLL_BASE_EN;
+
+       /* postdiv */
+       con1 &= ~ARM_PLL_POSTDIV_MASK;
+       con1 |= postdiv_idx << ARM_PLL_POSTDIV_L;
+
+       /* pcw */
+       con1 &= ~ARM_PLL_PCW_MASK;
+       con1 |= pcw << ARM_PLL_PCW_L;
+
+       if (pll_en)
+               con1 |= PLL_PCW_CHG;
+
+       writel_relaxed(con1, con1_addr);
+
+       if (pll_en) {
+               wmb();  /* sync write before delay */
+               udelay(20);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int mtk_clk_arm_pll_set_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long parent_rate)
+{
+       u32 pcwfbits = 14;
+       u32 pcw = 0;
+       u32 postdiv_idx = 0;
+       int r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       r = mtk_calc_pll_freq_cfg(&pcw, &postdiv_idx, rate,
+                       parent_rate, pcwfbits);
+
+       if (r == 0)
+               mtk_clk_arm_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+       return r;
+}
+
+const struct clk_ops mt8135_arm_pll_ops = {
+       .is_enabled     = mtk_clk_pll_is_enabled,
+       .prepare        = mtk_clk_pll_prepare,
+       .unprepare      = mtk_clk_pll_unprepare,
+       .recalc_rate    = mtk_clk_arm_pll_recalc_rate,
+       .round_rate     = mtk_clk_pll_round_rate,
+       .set_rate       = mtk_clk_arm_pll_set_rate,
+};
+
+static int mtk_clk_lc_pll_prepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       u32 r;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       r = readl_relaxed(pll->base_addr) | pll->en_mask;
+       writel_relaxed(r, pll->base_addr);
+       wmb();  /* sync write before delay */
+       udelay(20);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(pll->base_addr) | RST_BAR_MASK;
+               writel_relaxed(r, pll->base_addr);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+
+       return 0;
+}
+
+static void mtk_clk_lc_pll_unprepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       u32 r;
+
+       if (pll->flags & PLL_AO)
+               return;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(pll->base_addr) & ~RST_BAR_MASK;
+               writel_relaxed(r, pll->base_addr);
+       }
+
+       r = readl_relaxed(pll->base_addr) & ~PLL_BASE_EN;
+       writel_relaxed(r, pll->base_addr);
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+#define LC_PLL_FBKSEL_H                21
+#define LC_PLL_FBKSEL_L                20
+#define LC_PLL_FBKSEL_MASK     GENMASK(LC_PLL_FBKSEL_H, LC_PLL_FBKSEL_L)
+#define LC_PLL_POSTDIV_H       8
+#define LC_PLL_POSTDIV_L       6
+#define LC_PLL_POSTDIV_MASK    GENMASK(LC_PLL_POSTDIV_H, LC_PLL_POSTDIV_L)
+#define LC_PLL_FBKDIV_H                15
+#define LC_PLL_FBKDIV_L                9
+#define LC_PLL_FBKDIV_MASK     GENMASK(LC_PLL_FBKDIV_H, LC_PLL_FBKDIV_L)
+
+static unsigned long mtk_clk_lc_pll_recalc_rate(
+               struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+       u32 con0 = readl_relaxed(pll->base_addr);
+
+       u32 fbksel = (con0 & LC_PLL_FBKSEL_MASK) >> LC_PLL_FBKSEL_L;
+       u32 vcodivsel = (con0 & PLL_VCODIV_MASK) >> PLL_VCODIV_L;
+       u32 fbkdiv = (con0 & LC_PLL_FBKDIV_MASK) >> LC_PLL_FBKDIV_L;
+       u32 prediv = (con0 & PLL_PREDIV_MASK) >> PLL_PREDIV_L;
+       u32 posdiv = (con0 & LC_PLL_POSTDIV_MASK) >> LC_PLL_POSTDIV_L;
+
+       u32 vco_freq;
+       unsigned long r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       vcodivsel = pll_vcodivsel_map[vcodivsel];
+       fbksel = pll_fbksel_map[fbksel];
+       prediv = pll_prediv_map[prediv];
+
+       vco_freq = parent_rate * fbkdiv * fbksel * vcodivsel / prediv;
+       r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv];
+
+       return r;
+}
+
+static void mtk_clk_lc_pll_set_rate_regs(
+               struct clk_hw *hw,
+               u32 pcw,
+               u32 postdiv_idx)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       u32 con0;
+       u32 pll_en;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       con0 = readl_relaxed(con0_addr);
+
+       pll_en = con0 & PLL_BASE_EN;
+
+       /* postdiv */
+       con0 &= ~LC_PLL_POSTDIV_MASK;
+       con0 |= postdiv_idx << LC_PLL_POSTDIV_L;
+
+       /* fkbdiv */
+       con0 &= ~LC_PLL_FBKDIV_MASK;
+       con0 |= pcw << LC_PLL_FBKDIV_L;
+
+       writel_relaxed(con0, con0_addr);
+
+       if (pll_en) {
+               wmb();  /* sync write before delay */
+               udelay(20);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static long mtk_clk_lc_pll_round_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long *prate)
+{
+       u32 pcwfbits = 0;
+       u32 pcw = 0;
+       u32 postdiv = 0;
+       u32 r;
+
+       *prate = *prate ? *prate : 26000000;
+       rate = mtk_freq_limit(rate);
+       mtk_calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+       r = mtk_calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+       r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv];
+
+       return r;
+}
+
+static int mtk_clk_lc_pll_set_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long parent_rate)
+{
+       u32 pcwfbits = 0;
+       u32 pcw = 0;
+       u32 postdiv_idx = 0;
+       int r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       r = mtk_calc_pll_freq_cfg(&pcw, &postdiv_idx, rate,
+                       parent_rate, pcwfbits);
+
+       if (r == 0)
+               mtk_clk_lc_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+       return r;
+}
+
+const struct clk_ops mt8135_lc_pll_ops = {
+       .is_enabled     = mtk_clk_pll_is_enabled,
+       .prepare        = mtk_clk_lc_pll_prepare,
+       .unprepare      = mtk_clk_lc_pll_unprepare,
+       .recalc_rate    = mtk_clk_lc_pll_recalc_rate,
+       .round_rate     = mtk_clk_lc_pll_round_rate,
+       .set_rate       = mtk_clk_lc_pll_set_rate,
+};
+
+static int mtk_clk_aud_pll_prepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con4_addr = pll->base_addr + 16;
+       u32 r;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON;
+       writel_relaxed(r, pll->pwr_addr);
+       wmb();  /* sync write before delay */
+       udelay(1);
+
+       r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN;
+       writel_relaxed(r, pll->pwr_addr);
+       wmb();  /* sync write before delay */
+       udelay(1);
+
+       r = readl_relaxed(con0_addr) | pll->en_mask;
+       writel_relaxed(r, con0_addr);
+
+       r = readl_relaxed(con4_addr) | AUDPLL_TUNER_EN;
+       writel_relaxed(r, con4_addr);
+       wmb();  /* sync write before delay */
+       udelay(20);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(con0_addr) | RST_BAR_MASK;
+               writel_relaxed(r, con0_addr);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+
+       return 0;
+}
+
+static void mtk_clk_aud_pll_unprepare(struct clk_hw *hw)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con4_addr = pll->base_addr + 16;
+       u32 r;
+
+       if (pll->flags & PLL_AO)
+               return;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       if (pll->flags & HAVE_RST_BAR) {
+               r = readl_relaxed(con0_addr) & ~RST_BAR_MASK;
+               writel_relaxed(r, con0_addr);
+       }
+
+       r = readl_relaxed(con4_addr) & ~AUDPLL_TUNER_EN;
+       writel_relaxed(r, con4_addr);
+
+       r = readl_relaxed(con0_addr) & ~PLL_BASE_EN;
+       writel_relaxed(r, con0_addr);
+
+       r = readl_relaxed(pll->pwr_addr) | PLL_ISO_EN;
+       writel_relaxed(r, pll->pwr_addr);
+
+       r = readl_relaxed(pll->pwr_addr) & ~PLL_PWR_ON;
+       writel_relaxed(r, pll->pwr_addr);
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+#define AUD_PLL_POSTDIV_H      8
+#define AUD_PLL_POSTDIV_L      6
+#define AUD_PLL_POSTDIV_MASK   GENMASK(AUD_PLL_POSTDIV_H, AUD_PLL_POSTDIV_L)
+#define AUD_PLL_PCW_H          30
+#define AUD_PLL_PCW_L          0
+#define AUD_PLL_PCW_MASK       GENMASK(AUD_PLL_PCW_H, AUD_PLL_PCW_L)
+
+static unsigned long mtk_clk_aud_pll_recalc_rate(
+               struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+       u32 con0 = readl_relaxed(pll->base_addr);
+       u32 con1 = readl_relaxed(pll->base_addr + 4);
+
+       u32 vcodivsel = (con0 & PLL_VCODIV_MASK) >> PLL_VCODIV_L;
+       u32 prediv = (con0 & PLL_PREDIV_MASK) >> PLL_PREDIV_L;
+       u32 posdiv = (con0 & AUD_PLL_POSTDIV_MASK) >> AUD_PLL_POSTDIV_L;
+       u32 pcw = (con1 & AUD_PLL_PCW_MASK) >> AUD_PLL_PCW_L;
+       u32 pcwfbits = 24;
+
+       u32 vco_freq;
+       unsigned long r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       vcodivsel = pll_vcodivsel_map[vcodivsel];
+       prediv = pll_prediv_map[prediv];
+
+       vco_freq = mtk_calc_pll_vco_freq(
+                       parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+       r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv];
+
+       return r;
+}
+
+static void mtk_clk_aud_pll_set_rate_regs(
+               struct clk_hw *hw,
+               u32 pcw,
+               u32 postdiv_idx)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con1_addr = pll->base_addr + 4;
+       void __iomem *con4_addr = pll->base_addr + 16;
+       u32 con0;
+       u32 con1;
+       u32 pll_en;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       con0 = readl_relaxed(con0_addr);
+       con1 = readl_relaxed(con1_addr);
+
+       pll_en = con0 & PLL_BASE_EN;
+
+       /* set postdiv */
+       con0 &= ~AUD_PLL_POSTDIV_MASK;
+       con0 |= postdiv_idx << AUD_PLL_POSTDIV_L;
+       writel_relaxed(con0, con0_addr);
+
+       /* set pcw */
+       con1 &= ~AUD_PLL_PCW_MASK;
+       con1 |= pcw << AUD_PLL_PCW_L;
+
+       if (pll_en)
+               con1 |= PLL_PCW_CHG;
+
+       writel_relaxed(con1, con1_addr);
+       writel_relaxed(con1 + 1, con4_addr);
+       /* AUDPLL_CON4[30:0] (AUDPLL_TUNER_N_INFO) = (pcw + 1) */
+
+       if (pll_en) {
+               wmb();  /* sync write before delay */
+               udelay(20);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static long mtk_clk_aud_pll_round_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long *prate)
+{
+       u32 pcwfbits = 24;
+       u32 pcw = 0;
+       u32 postdiv = 0;
+       u32 r;
+
+       *prate = *prate ? *prate : 26000000;
+       rate = mtk_freq_limit(rate);
+       mtk_calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+       r = mtk_calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+       r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv];
+
+       return r;
+}
+
+static int mtk_clk_aud_pll_set_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long parent_rate)
+{
+       u32 pcwfbits = 24;
+       u32 pcw = 0;
+       u32 postdiv_idx = 0;
+       int r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       r = mtk_calc_pll_freq_cfg(&pcw, &postdiv_idx, rate,
+                       parent_rate, pcwfbits);
+
+       if (r == 0)
+               mtk_clk_aud_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+       return r;
+}
+
+const struct clk_ops mt8135_aud_pll_ops = {
+       .is_enabled     = mtk_clk_pll_is_enabled,
+       .prepare        = mtk_clk_aud_pll_prepare,
+       .unprepare      = mtk_clk_aud_pll_unprepare,
+       .recalc_rate    = mtk_clk_aud_pll_recalc_rate,
+       .round_rate     = mtk_clk_aud_pll_round_rate,
+       .set_rate       = mtk_clk_aud_pll_set_rate,
+};
+
+#define TVD_PLL_POSTDIV_H      8
+#define TVD_PLL_POSTDIV_L      6
+#define TVD_PLL_POSTDIV_MASK   GENMASK(TVD_PLL_POSTDIV_H, TVD_PLL_POSTDIV_L)
+#define TVD_PLL_PCW_H          30
+#define TVD_PLL_PCW_L          0
+#define TVD_PLL_PCW_MASK       GENMASK(TVD_PLL_PCW_H, TVD_PLL_PCW_L)
+
+static void mtk_clk_tvd_pll_set_rate_regs(
+               struct clk_hw *hw,
+               u32 pcw,
+               u32 postdiv_idx)
+{
+       unsigned long flags = 0;
+       struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+       void __iomem *con0_addr = pll->base_addr;
+       void __iomem *con1_addr = pll->base_addr + 4;
+       u32 con0;
+       u32 con1;
+       u32 pll_en;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       con0 = readl_relaxed(con0_addr);
+       con1 = readl_relaxed(con1_addr);
+
+       pll_en = con0 & PLL_BASE_EN;
+
+       /* set postdiv */
+       con0 &= ~TVD_PLL_POSTDIV_MASK;
+       con0 |= postdiv_idx << TVD_PLL_POSTDIV_L;
+       writel_relaxed(con0, con0_addr);
+
+       /* set pcw */
+       con1 &= ~TVD_PLL_PCW_MASK;
+       con1 |= pcw << TVD_PLL_PCW_L;
+
+       if (pll_en)
+               con1 |= PLL_PCW_CHG;
+
+       writel_relaxed(con1, con1_addr);
+
+       if (pll_en) {
+               wmb();  /* sync write before delay */
+               udelay(20);
+       }
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int mtk_clk_tvd_pll_set_rate(
+               struct clk_hw *hw,
+               unsigned long rate,
+               unsigned long parent_rate)
+{
+       u32 pcwfbits = 24;
+       u32 pcw = 0;
+       u32 postdiv_idx = 0;
+       int r;
+
+       parent_rate = parent_rate ? parent_rate : 26000000;
+       r = mtk_calc_pll_freq_cfg(&pcw, &postdiv_idx, rate,
+                       parent_rate, pcwfbits);
+
+       if (r == 0)
+               mtk_clk_tvd_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+       return r;
+}
+
+const struct clk_ops mt8135_tvd_pll_ops = {
+       .is_enabled     = mtk_clk_pll_is_enabled,
+       .prepare        = mtk_clk_pll_prepare,
+       .unprepare      = mtk_clk_pll_unprepare,
+       .recalc_rate    = mtk_clk_aud_pll_recalc_rate,
+       .round_rate     = mtk_clk_aud_pll_round_rate,
+       .set_rate       = mtk_clk_tvd_pll_set_rate,
+};
diff --git a/drivers/clk/mediatek/clk-mt8135-pll.h 
b/drivers/clk/mediatek/clk-mt8135-pll.h
new file mode 100644
index 0000000..dba18e08
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135-pll.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __DRV_CLK_MT8135_PLL_H
+#define __DRV_CLK_MT8135_PLL_H
+
+/*
+ * This is a private header file. DO NOT include it except clk-*.c.
+ */
+
+extern const struct clk_ops mt8135_pll_ops;
+extern const struct clk_ops mt8135_arm_pll_ops;
+extern const struct clk_ops mt8135_lc_pll_ops;
+extern const struct clk_ops mt8135_aud_pll_ops;
+extern const struct clk_ops mt8135_tvd_pll_ops;
+
+#endif /* __DRV_CLK_MT8135_PLL_H */
diff --git a/drivers/clk/mediatek/clk-mt8135.c 
b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 0000000..93e5f02
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,873 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+#include "clk-gate.h"
+#include "clk-mt8135-pll.h"
+
+#include <dt-bindings/clock/mt8135-clk.h>
+
+/* ROOT */
+#define clk_null               "clk_null"
+#define clk26m                 "clk26m"
+#define rtc32k                 "rtc32k"
+
+#define dsi0_lntc_dsiclk       "dsi0_lntc_dsi"
+#define hdmitx_clkdig_cts      "hdmitx_dig_cts"
+#define clkph_mck              "clkph_mck"
+#define cpum_tck_in            "cpum_tck_in"
+
+/* PLL */
+#define armpll1                        "armpll1"
+#define armpll2                        "armpll2"
+#define mainpll                        "mainpll"
+#define univpll                        "univpll"
+#define mmpll                  "mmpll"
+#define msdcpll                        "msdcpll"
+#define tvdpll                 "tvdpll"
+#define lvdspll                        "lvdspll"
+#define audpll                 "audpll"
+#define vdecpll                        "vdecpll"
+
+#define mainpll_806m           "mainpll_806m"
+#define mainpll_537p3m         "mainpll_537p3m"
+#define mainpll_322p4m         "mainpll_322p4m"
+#define mainpll_230p3m         "mainpll_230p3m"
+
+#define univpll_624m           "univpll_624m"
+#define univpll_416m           "univpll_416m"
+#define univpll_249p6m         "univpll_249p6m"
+#define univpll_178p3m         "univpll_178p3m"
+#define univpll_48m            "univpll_48m"
+
+/* DIV */
+#define mmpll_d2               "mmpll_d2"
+#define mmpll_d3               "mmpll_d3"
+#define mmpll_d5               "mmpll_d5"
+#define mmpll_d7               "mmpll_d7"
+#define mmpll_d4               "mmpll_d4"
+#define mmpll_d6               "mmpll_d6"
+
+#define syspll_d2              "syspll_d2"
+#define syspll_d4              "syspll_d4"
+#define syspll_d6              "syspll_d6"
+#define syspll_d8              "syspll_d8"
+#define syspll_d10             "syspll_d10"
+#define syspll_d12             "syspll_d12"
+#define syspll_d16             "syspll_d16"
+#define syspll_d24             "syspll_d24"
+#define syspll_d3              "syspll_d3"
+#define syspll_d2p5            "syspll_d2p5"
+#define syspll_d5              "syspll_d5"
+#define syspll_d3p5            "syspll_d3p5"
+
+#define univpll1_d2            "univpll1_d2"
+#define univpll1_d4            "univpll1_d4"
+#define univpll1_d6            "univpll1_d6"
+#define univpll1_d8            "univpll1_d8"
+#define univpll1_d10           "univpll1_d10"
+
+#define univpll2_d2            "univpll2_d2"
+#define univpll2_d4            "univpll2_d4"
+#define univpll2_d6            "univpll2_d6"
+#define univpll2_d8            "univpll2_d8"
+
+#define univpll_d3             "univpll_d3"
+#define univpll_d5             "univpll_d5"
+#define univpll_d7             "univpll_d7"
+#define univpll_d10            "univpll_d10"
+#define univpll_d26            "univpll_d26"
+
+#define apll_ck                        "apll"
+#define apll_d4                        "apll_d4"
+#define apll_d8                        "apll_d8"
+#define apll_d16               "apll_d16"
+#define apll_d24               "apll_d24"
+
+#define lvdspll_d2             "lvdspll_d2"
+#define lvdspll_d4             "lvdspll_d4"
+#define lvdspll_d8             "lvdspll_d8"
+
+#define lvdstx_clkdig_cts      "lvdstx_dig_cts"
+#define vpll_dpix_ck           "vpll_dpix_ck"
+#define tvhdmi_h_ck            "tvhdmi_h_ck"
+#define hdmitx_clkdig_d2       "hdmitx_dig_d2"
+#define hdmitx_clkdig_d3       "hdmitx_dig_d3"
+#define tvhdmi_d2              "tvhdmi_d2"
+#define tvhdmi_d4              "tvhdmi_d4"
+#define mempll_mck_d4          "mempll_mck_d4"
+
+/* TOP */
+#define axi_sel                        "axi_sel"
+#define smi_sel                        "smi_sel"
+#define mfg_sel                        "mfg_sel"
+#define irda_sel               "irda_sel"
+#define cam_sel                        "cam_sel"
+#define aud_intbus_sel         "aud_intbus_sel"
+#define jpg_sel                        "jpg_sel"
+#define disp_sel               "disp_sel"
+#define msdc30_1_sel           "msdc30_1_sel"
+#define msdc30_2_sel           "msdc30_2_sel"
+#define msdc30_3_sel           "msdc30_3_sel"
+#define msdc30_4_sel           "msdc30_4_sel"
+#define usb20_sel              "usb20_sel"
+#define venc_sel               "venc_sel"
+#define spi_sel                        "spi_sel"
+#define uart_sel               "uart_sel"
+#define mem_sel                        "mem_sel"
+#define camtg_sel              "camtg_sel"
+#define audio_sel              "audio_sel"
+#define fix_sel                        "fix_sel"
+#define vdec_sel               "vdec_sel"
+#define ddrphycfg_sel          "ddrphycfg_sel"
+#define dpilvds_sel            "dpilvds_sel"
+#define pmicspi_sel            "pmicspi_sel"
+#define msdc30_0_sel           "msdc30_0_sel"
+#define smi_mfg_as_sel         "smi_mfg_as_sel"
+#define gcpu_sel               "gcpu_sel"
+#define dpi1_sel               "dpi1_sel"
+#define cci_sel                        "cci_sel"
+#define apll_sel               "apll_sel"
+#define hdmipll_sel            "hdmipll_sel"
+
+/* PERI0 */
+#define i2c5_ck                        "i2c5_ck"
+#define i2c4_ck                        "i2c4_ck"
+#define i2c3_ck                        "i2c3_ck"
+#define i2c2_ck                        "i2c2_ck"
+#define i2c1_ck                        "i2c1_ck"
+#define i2c0_ck                        "i2c0_ck"
+#define uart3_ck               "uart3_ck"
+#define uart2_ck               "uart2_ck"
+#define uart1_ck               "uart1_ck"
+#define uart0_ck               "uart0_ck"
+#define irda_ck                        "irda_ck"
+#define nli_ck                 "nli_ck"
+#define md_hif_ck              "md_hif_ck"
+#define ap_hif_ck              "ap_hif_ck"
+#define msdc30_3_ck            "msdc30_3_ck"
+#define msdc30_2_ck            "msdc30_2_ck"
+#define msdc30_1_ck            "msdc30_1_ck"
+#define msdc20_2_ck            "msdc20_2_ck"
+#define msdc20_1_ck            "msdc20_1_ck"
+#define ap_dma_ck              "ap_dma_ck"
+#define usb1_ck                        "usb1_ck"
+#define usb0_ck                        "usb0_ck"
+#define pwm_ck                 "pwm_ck"
+#define pwm7_ck                        "pwm7_ck"
+#define pwm6_ck                        "pwm6_ck"
+#define pwm5_ck                        "pwm5_ck"
+#define pwm4_ck                        "pwm4_ck"
+#define pwm3_ck                        "pwm3_ck"
+#define pwm2_ck                        "pwm2_ck"
+#define pwm1_ck                        "pwm1_ck"
+#define therm_ck               "therm_ck"
+#define nfi_ck                 "nfi_ck"
+
+/* PERI1 */
+#define usbslv_ck              "usbslv_ck"
+#define usb1_mcu_ck            "usb1_mcu_ck"
+#define usb0_mcu_ck            "usb0_mcu_ck"
+#define gcpu_ck                        "gcpu_ck"
+#define fhctl_ck               "fhctl_ck"
+#define spi1_ck                        "spi1_ck"
+#define auxadc_ck              "auxadc_ck"
+#define peri_pwrap_ck          "peri_pwrap_ck"
+#define i2c6_ck                        "i2c6_ck"
+
+/* INFRA */
+#define pmic_wrap_ck           "pmic_wrap_ck"
+#define pmicspi_ck             "pmicspi_ck"
+#define ccif1_ap_ctrl          "ccif1_ap_ctrl"
+#define ccif0_ap_ctrl          "ccif0_ap_ctrl"
+#define kp_ck                  "kp_ck"
+#define cpum_ck                        "cpum_ck"
+#define m4u_ck                 "m4u_ck"
+#define mfgaxi_ck              "mfgaxi_ck"
+#define devapc_ck              "devapc_ck"
+#define audio_ck               "audio_ck"
+#define mfg_bus_ck             "mfg_bus_ck"
+#define smi_ck                 "smi_ck"
+#define dbgclk_ck              "dbgclk_ck"
+
+static DEFINE_SPINLOCK(lock);
+
+static struct mtk_fixed_factor root_clk_alias[] __initdata = {
+       FACTOR(TOP_DSI0_LNTC_DSICLK, dsi0_lntc_dsiclk, clk_null, 1, 1),
+       FACTOR(TOP_HDMITX_CLKDIG_CTS, hdmitx_clkdig_cts, clk_null, 1, 1),
+       FACTOR(TOP_CLKPH_MCK, clkph_mck, clk_null, 1, 1),
+       FACTOR(TOP_CPUM_TCK_IN, cpum_tck_in, clk_null, 1, 1),
+};
+
+static struct mtk_fixed_factor top_divs[] __initdata = {
+       FACTOR(TOP_MAINPLL_806M, mainpll_806m, mainpll, 1, 2),
+       FACTOR(TOP_MAINPLL_537P3M, mainpll_537p3m, mainpll, 1, 3),
+       FACTOR(TOP_MAINPLL_322P4M, mainpll_322p4m, mainpll, 1, 5),
+       FACTOR(TOP_MAINPLL_230P3M, mainpll_230p3m, mainpll, 1, 7),
+
+       FACTOR(TOP_UNIVPLL_624M, univpll_624m, univpll, 1, 2),
+       FACTOR(TOP_UNIVPLL_416M, univpll_416m, univpll, 1, 3),
+       FACTOR(TOP_UNIVPLL_249P6M, univpll_249p6m, univpll, 1, 5),
+       FACTOR(TOP_UNIVPLL_178P3M, univpll_178p3m, univpll, 1, 7),
+       FACTOR(TOP_UNIVPLL_48M, univpll_48m, univpll, 1, 26),
+
+       FACTOR(TOP_MMPLL_D2, mmpll_d2, mmpll, 1, 2),
+       FACTOR(TOP_MMPLL_D3, mmpll_d3, mmpll, 1, 3),
+       FACTOR(TOP_MMPLL_D5, mmpll_d5, mmpll, 1, 5),
+       FACTOR(TOP_MMPLL_D7, mmpll_d7, mmpll, 1, 7),
+       FACTOR(TOP_MMPLL_D4, mmpll_d4, mmpll_d2, 1, 2),
+       FACTOR(TOP_MMPLL_D6, mmpll_d6, mmpll_d3, 1, 2),
+
+       FACTOR(TOP_SYSPLL_D2, syspll_d2, mainpll_806m, 1, 1),
+       FACTOR(TOP_SYSPLL_D4, syspll_d4, mainpll_806m, 1, 2),
+       FACTOR(TOP_SYSPLL_D6, syspll_d6, mainpll_806m, 1, 3),
+       FACTOR(TOP_SYSPLL_D8, syspll_d8, mainpll_806m, 1, 4),
+       FACTOR(TOP_SYSPLL_D10, syspll_d10, mainpll_806m, 1, 5),
+       FACTOR(TOP_SYSPLL_D12, syspll_d12, mainpll_806m, 1, 6),
+       FACTOR(TOP_SYSPLL_D16, syspll_d16, mainpll_806m, 1, 8),
+       FACTOR(TOP_SYSPLL_D24, syspll_d24, mainpll_806m, 1, 12),
+
+       FACTOR(TOP_SYSPLL_D3, syspll_d3, mainpll_537p3m, 1, 1),
+
+       FACTOR(TOP_SYSPLL_D2P5, syspll_d2p5, mainpll_322p4m, 2, 1),
+       FACTOR(TOP_SYSPLL_D5, syspll_d5, mainpll_322p4m, 1, 1),
+
+       FACTOR(TOP_SYSPLL_D3P5, syspll_d3p5, mainpll_230p3m, 2, 1),
+
+       FACTOR(TOP_UNIVPLL1_D2, univpll1_d2, univpll_624m, 1, 2),
+       FACTOR(TOP_UNIVPLL1_D4, univpll1_d4, univpll_624m, 1, 4),
+       FACTOR(TOP_UNIVPLL1_D6, univpll1_d6, univpll_624m, 1, 6),
+       FACTOR(TOP_UNIVPLL1_D8, univpll1_d8, univpll_624m, 1, 8),
+       FACTOR(TOP_UNIVPLL1_D10, univpll1_d10, univpll_624m, 1, 10),
+
+       FACTOR(TOP_UNIVPLL2_D2, univpll2_d2, univpll_416m, 1, 2),
+       FACTOR(TOP_UNIVPLL2_D4, univpll2_d4, univpll_416m, 1, 4),
+       FACTOR(TOP_UNIVPLL2_D6, univpll2_d6, univpll_416m, 1, 6),
+       FACTOR(TOP_UNIVPLL2_D8, univpll2_d8, univpll_416m, 1, 8),
+
+       FACTOR(TOP_UNIVPLL_D3, univpll_d3, univpll_416m, 1, 1),
+       FACTOR(TOP_UNIVPLL_D5, univpll_d5, univpll_249p6m, 1, 1),
+       FACTOR(TOP_UNIVPLL_D7, univpll_d7, univpll_178p3m, 1, 1),
+       FACTOR(TOP_UNIVPLL_D10, univpll_d10, univpll_249p6m, 1, 5),
+       FACTOR(TOP_UNIVPLL_D26, univpll_d26, univpll_48m, 1, 1),
+
+       FACTOR(TOP_APLL_CK, apll_ck, audpll, 1, 1),
+       FACTOR(TOP_APLL_D4, apll_d4, audpll, 1, 4),
+       FACTOR(TOP_APLL_D8, apll_d8, audpll, 1, 8),
+       FACTOR(TOP_APLL_D16, apll_d16, audpll, 1, 16),
+       FACTOR(TOP_APLL_D24, apll_d24, audpll, 1, 24),
+
+       FACTOR(TOP_LVDSPLL_D2, lvdspll_d2, lvdspll, 1, 2),
+       FACTOR(TOP_LVDSPLL_D4, lvdspll_d4, lvdspll, 1, 4),
+       FACTOR(TOP_LVDSPLL_D8, lvdspll_d8, lvdspll, 1, 8),
+
+       FACTOR(TOP_LVDSTX_CLKDIG_CT, lvdstx_clkdig_cts, lvdspll, 1, 1),
+       FACTOR(TOP_VPLL_DPIX_CK, vpll_dpix_ck, lvdspll, 1, 1),
+
+       FACTOR(TOP_TVHDMI_H_CK, tvhdmi_h_ck, tvdpll, 1, 1),
+
+       FACTOR(TOP_HDMITX_CLKDIG_D2, hdmitx_clkdig_d2, hdmitx_clkdig_cts, 1, 2),
+       FACTOR(TOP_HDMITX_CLKDIG_D3, hdmitx_clkdig_d3, hdmitx_clkdig_cts, 1, 3),
+
+       FACTOR(TOP_TVHDMI_D2, tvhdmi_d2, tvhdmi_h_ck, 1, 2),
+       FACTOR(TOP_TVHDMI_D4, tvhdmi_d4, tvhdmi_h_ck, 1, 4),
+
+       FACTOR(TOP_MEMPLL_MCK_D4, mempll_mck_d4, clkph_mck, 1, 4),
+};
+
+static const char *axi_parents[] __initconst = {
+               clk26m,
+               syspll_d3,
+               syspll_d4,
+               syspll_d6,
+               univpll_d5,
+               univpll2_d2,
+               syspll_d3p5};
+
+static const char *smi_parents[] __initconst = {
+               clk26m,
+               clkph_mck,
+               syspll_d2p5,
+               syspll_d3,
+               syspll_d8,
+               univpll_d5,
+               univpll1_d2,
+               univpll1_d6,
+               mmpll_d3,
+               mmpll_d4,
+               mmpll_d5,
+               mmpll_d6,
+               mmpll_d7,
+               vdecpll,
+               lvdspll};
+
+static const char *mfg_parents[] __initconst = {
+               clk26m,
+               univpll1_d4,
+               syspll_d2,
+               syspll_d2p5,
+               syspll_d3,
+               univpll_d5,
+               univpll1_d2,
+               mmpll_d2,
+               mmpll_d3,
+               mmpll_d4,
+               mmpll_d5,
+               mmpll_d6,
+               mmpll_d7};
+
+static const char *irda_parents[] __initconst = {
+               clk26m,
+               univpll2_d8,
+               univpll1_d6};
+
+static const char *cam_parents[] __initconst = {
+               clk26m,
+               syspll_d3,
+               syspll_d3p5,
+               syspll_d4,
+               univpll_d5,
+               univpll2_d2,
+               univpll_d7,
+               univpll1_d4};
+
+static const char *aud_intbus_parents[] __initconst = {
+               clk26m,
+               syspll_d6,
+               univpll_d10};
+
+static const char *jpg_parents[] __initconst = {
+               clk26m,
+               syspll_d5,
+               syspll_d4,
+               syspll_d3,
+               univpll_d7,
+               univpll2_d2,
+               univpll_d5};
+
+static const char *disp_parents[] __initconst = {
+               clk26m,
+               syspll_d3p5,
+               syspll_d3,
+               univpll2_d2,
+               univpll_d5,
+               univpll1_d2,
+               lvdspll,
+               vdecpll};
+
+static const char *msdc30_parents[] __initconst = {
+               clk26m,
+               syspll_d6,
+               syspll_d5,
+               univpll1_d4,
+               univpll2_d4,
+               msdcpll};
+
+static const char *usb20_parents[] __initconst = {
+               clk26m,
+               univpll2_d6,
+               univpll1_d10};
+
+static const char *venc_parents[] __initconst = {
+               clk26m,
+               syspll_d3,
+               syspll_d8,
+               univpll_d5,
+               univpll1_d6,
+               mmpll_d4,
+               mmpll_d5,
+               mmpll_d6};
+
+static const char *spi_parents[] __initconst = {
+               clk26m,
+               syspll_d6,
+               syspll_d8,
+               syspll_d10,
+               univpll1_d6,
+               univpll1_d8};
+
+static const char *uart_parents[] __initconst = {
+               clk26m,
+               univpll2_d8};
+
+static const char *mem_parents[] __initconst = {
+               clk26m,
+               clkph_mck};
+
+static const char *camtg_parents[] __initconst = {
+               clk26m,
+               univpll_d26,
+               univpll1_d6,
+               syspll_d16,
+               syspll_d8};
+
+static const char *audio_parents[] __initconst = {
+               clk26m,
+               syspll_d24};
+
+static const char *fix_parents[] __initconst = {
+               rtc32k,
+               clk26m,
+               univpll_d5,
+               univpll_d7,
+               univpll1_d2,
+               univpll1_d4,
+               univpll1_d6,
+               univpll1_d8};
+
+static const char *vdec_parents[] __initconst = {
+               clk26m,
+               vdecpll,
+               clkph_mck,
+               syspll_d2p5,
+               syspll_d3,
+               syspll_d3p5,
+               syspll_d4,
+               syspll_d5,
+               syspll_d6,
+               syspll_d8,
+               univpll1_d2,
+               univpll2_d2,
+               univpll_d7,
+               univpll_d10,
+               univpll2_d4,
+               lvdspll};
+
+static const char *ddrphycfg_parents[] __initconst = {
+               clk26m,
+               axi_sel,
+               syspll_d12};
+
+static const char *dpilvds_parents[] __initconst = {
+               clk26m,
+               lvdspll,
+               lvdspll_d2,
+               lvdspll_d4,
+               lvdspll_d8};
+
+static const char *pmicspi_parents[] __initconst = {
+               clk26m,
+               univpll2_d6,
+               syspll_d8,
+               syspll_d10,
+               univpll1_d10,
+               mempll_mck_d4,
+               univpll_d26,
+               syspll_d24};
+
+static const char *smi_mfg_as_parents[] __initconst = {
+               clk26m,
+               smi_sel,
+               mfg_sel,
+               mem_sel};
+
+static const char *gcpu_parents[] __initconst = {
+               clk26m,
+               syspll_d4,
+               univpll_d7,
+               syspll_d5,
+               syspll_d6};
+
+static const char *dpi1_parents[] __initconst = {
+               clk26m,
+               tvhdmi_h_ck,
+               tvhdmi_d2,
+               tvhdmi_d4};
+
+static const char *cci_parents[] __initconst = {
+               clk26m,
+               mainpll_537p3m,
+               univpll_d3,
+               syspll_d2p5,
+               syspll_d3,
+               syspll_d5};
+
+static const char *apll_parents[] __initconst = {
+               clk26m,
+               apll_ck,
+               apll_d4,
+               apll_d8,
+               apll_d16,
+               apll_d24};
+
+static const char *hdmipll_parents[] __initconst = {
+               clk26m,
+               hdmitx_clkdig_cts,
+               hdmitx_clkdig_d2,
+               hdmitx_clkdig_d3};
+
+static struct mtk_mux top_muxes[] __initdata = {
+       /* CLK_CFG_0 */
+       MUX(TOP_AXI_SEL, axi_sel, axi_parents,
+               0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+       MUX(TOP_SMI_SEL, smi_sel, smi_parents, 0x0140, 8, 4, 15),
+       MUX(TOP_MFG_SEL, mfg_sel, mfg_parents, 0x0140, 16, 4, 23),
+       MUX(TOP_IRDA_SEL, irda_sel, irda_parents, 0x0140, 24, 2, 31),
+       /* CLK_CFG_1 */
+       MUX(TOP_CAM_SEL, cam_sel, cam_parents, 0x0144, 0, 3, 7),
+       MUX(TOP_AUD_INTBUS_SEL, aud_intbus_sel, aud_intbus_parents,
+               0x0144, 8, 2, 15),
+       MUX(TOP_JPG_SEL, jpg_sel, jpg_parents, 0x0144, 16, 3, 23),
+       MUX(TOP_DISP_SEL, disp_sel, disp_parents, 0x0144, 24, 3, 31),
+       /* CLK_CFG_2 */
+       MUX(TOP_MSDC30_1_SEL, msdc30_1_sel, msdc30_parents, 0x0148, 0, 3, 7),
+       MUX(TOP_MSDC30_2_SEL, msdc30_2_sel, msdc30_parents, 0x0148, 8, 3, 15),
+       MUX(TOP_MSDC30_3_SEL, msdc30_3_sel, msdc30_parents, 0x0148, 16, 3, 23),
+       MUX(TOP_MSDC30_4_SEL, msdc30_4_sel, msdc30_parents, 0x0148, 24, 3, 31),
+       /* CLK_CFG_3 */
+       MUX(TOP_USB20_SEL, usb20_sel, usb20_parents, 0x014c, 0, 2, 7),
+       /* CLK_CFG_4 */
+       MUX(TOP_VENC_SEL, venc_sel, venc_parents, 0x0150, 8, 3, 15),
+       MUX(TOP_SPI_SEL, spi_sel, spi_parents, 0x0150, 16, 3, 23),
+       MUX(TOP_UART_SEL, uart_sel, uart_parents, 0x0150, 24, 2, 31),
+       /* CLK_CFG_6 */
+       MUX(TOP_MEM_SEL, mem_sel, mem_parents, 0x0158, 0, 2, 7),
+       MUX(TOP_CAMTG_SEL, camtg_sel, camtg_parents, 0x0158, 8, 3, 15),
+       MUX(TOP_AUDIO_SEL, audio_sel, audio_parents, 0x0158, 24, 2, 31),
+       /* CLK_CFG_7 */
+       MUX(TOP_FIX_SEL, fix_sel, fix_parents, 0x015c, 0, 3, 7),
+       MUX(TOP_VDEC_SEL, vdec_sel, vdec_parents, 0x015c, 8, 4, 15),
+       MUX(TOP_DDRPHYCFG_SEL, ddrphycfg_sel, ddrphycfg_parents,
+               0x015c, 16, 2, 23),
+       MUX(TOP_DPILVDS_SEL, dpilvds_sel, dpilvds_parents, 0x015c, 24, 3, 31),
+       /* CLK_CFG_8 */
+       MUX(TOP_PMICSPI_SEL, pmicspi_sel, pmicspi_parents, 0x0164, 0, 3, 7),
+       MUX(TOP_MSDC30_0_SEL, msdc30_0_sel, msdc30_parents, 0x0164, 8, 3, 15),
+       MUX(TOP_SMI_MFG_AS_SEL, smi_mfg_as_sel, smi_mfg_as_parents,
+               0x0164, 16, 2, 23),
+       MUX(TOP_GCPU_SEL, gcpu_sel, gcpu_parents, 0x0164, 24, 3, 31),
+       /* CLK_CFG_9 */
+       MUX(TOP_DPI1_SEL, dpi1_sel, dpi1_parents, 0x0168, 0, 2, 7),
+       MUX(TOP_CCI_SEL, cci_sel, cci_parents, 0x0168, 8, 3, 15),
+       MUX(TOP_APLL_SEL, apll_sel, apll_parents, 0x0168, 16, 3, 23),
+       MUX(TOP_HDMIPLL_SEL, hdmipll_sel, hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static void __init mtk_init_clk_topckgen(void __iomem *top_base,
+               struct clk_onecell_data *clk_data)
+{
+       int i;
+       struct clk *clk;
+
+       for (i = 0; i < ARRAY_SIZE(top_muxes); i++) {
+               struct mtk_mux *mux = &top_muxes[i];
+
+               clk = mtk_clk_register_mux(mux->name,
+                       mux->parent_names, mux->num_parents,
+                       top_base + mux->reg, mux->shift, mux->width,
+                       mux->gate, &lock);
+
+               if (IS_ERR(clk)) {
+                       pr_err("Failed to register clk %s: %ld\n",
+                                       mux->name, PTR_ERR(clk));
+                       continue;
+               }
+
+               if (clk_data)
+                       clk_data->clks[mux->id] = clk;
+       }
+}
+
+static struct mtk_pll plls[] __initdata = {
+       PLL(APMIXED_ARMPLL1, armpll1, clk26m, 0x0200, 0x0218,
+               0x80000001, HAVE_PLL_HP, &mt8135_arm_pll_ops),
+       PLL(APMIXED_ARMPLL2, armpll2, clk26m, 0x02cc, 0x02e4,
+               0x80000001, HAVE_PLL_HP, &mt8135_arm_pll_ops),
+       PLL(APMIXED_MAINPLL, mainpll, clk26m, 0x021c, 0x0234,
+               0xf0000001, HAVE_PLL_HP | HAVE_RST_BAR | PLL_AO,
+               &mt8135_pll_ops),
+       PLL(APMIXED_UNIVPLL, univpll, clk26m, 0x0238, 0x0250,
+               0xf3000001, HAVE_RST_BAR | HAVE_FIX_FRQ | PLL_AO,
+               &mt8135_lc_pll_ops),
+       PLL(APMIXED_MMPLL, mmpll, clk26m, 0x0254, 0x026c,
+               0xf0000001, HAVE_PLL_HP | HAVE_RST_BAR, &mt8135_pll_ops),
+       PLL(APMIXED_MSDCPLL, msdcpll, clk26m, 0x0278, 0x0290,
+               0x80000001, HAVE_PLL_HP, &mt8135_pll_ops),
+       PLL(APMIXED_TVDPLL, tvdpll, clk26m, 0x0294, 0x02ac,
+               0x80000001, HAVE_PLL_HP, &mt8135_tvd_pll_ops),
+       PLL(APMIXED_LVDSPLL, lvdspll, clk26m, 0x02b0, 0x02c8,
+               0x80000001, HAVE_PLL_HP, &mt8135_pll_ops),
+       PLL(APMIXED_AUDPLL, audpll, clk26m, 0x02e8, 0x0300,
+               0x80000001, 0, &mt8135_aud_pll_ops),
+       PLL(APMIXED_VDECPLL, vdecpll, clk26m, 0x0304, 0x031c,
+               0x80000001, HAVE_PLL_HP, &mt8135_pll_ops),
+};
+
+static void __init mtk_init_clk_apmixedsys(void __iomem *apmixed_base,
+               struct clk_onecell_data *clk_data)
+{
+       int i;
+       struct clk *clk;
+
+       for (i = 0; i < ARRAY_SIZE(plls); i++) {
+               struct mtk_pll *pll = &plls[i];
+
+               clk = mtk_clk_register_pll(pll->name, pll->parent_name,
+                               apmixed_base + pll->reg,
+                               apmixed_base + pll->pwr_reg,
+                               pll->en_mask, pll->flags, pll->ops, &lock);
+
+               if (IS_ERR(clk)) {
+                       pr_err("Failed to register clk %s: %ld\n",
+                                       pll->name, PTR_ERR(clk));
+                       continue;
+               }
+
+               if (clk_data)
+                       clk_data->clks[pll->id] = clk;
+       }
+}
+
+static struct mtk_gate_regs infra_cg_regs = {
+       .set_ofs = 0x0040,
+       .clr_ofs = 0x0044,
+       .sta_ofs = 0x0048,
+};
+
+static struct mtk_gate infra_clks[] __initdata = {
+       GATE(INFRA_PMIC_WRAP_CK, pmic_wrap_ck, axi_sel, infra_cg_regs,
+               23, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_PMICSPI_CK, pmicspi_ck, pmicspi_sel, infra_cg_regs,
+               22, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_CCIF1_AP_CTRL, ccif1_ap_ctrl, axi_sel, infra_cg_regs,
+               21, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_CCIF0_AP_CTRL, ccif0_ap_ctrl, axi_sel, infra_cg_regs,
+               20, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_KP_CK, kp_ck, axi_sel, infra_cg_regs,
+               16, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_CPUM_CK, cpum_ck, cpum_tck_in, infra_cg_regs,
+               15, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_M4U_CK, m4u_ck, mem_sel, infra_cg_regs,
+               8, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_MFGAXI_CK, mfgaxi_ck, axi_sel, infra_cg_regs,
+               7, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_DEVAPC_CK, devapc_ck, axi_sel, infra_cg_regs,
+               6, &mtk_clk_gate_ops_setclr_inv),
+       GATE(INFRA_AUDIO_CK, audio_ck, aud_intbus_sel, infra_cg_regs,
+               5, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_MFG_BUS_CK, mfg_bus_ck, axi_sel, infra_cg_regs,
+               2, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_SMI_CK, smi_ck, smi_sel, infra_cg_regs,
+               1, &mtk_clk_gate_ops_setclr),
+       GATE(INFRA_DBGCLK_CK, dbgclk_ck, axi_sel, infra_cg_regs,
+               0, &mtk_clk_gate_ops_setclr),
+};
+
+static struct mtk_gate_regs peri0_cg_regs = {
+       .set_ofs = 0x0008,
+       .clr_ofs = 0x0010,
+       .sta_ofs = 0x0018,
+};
+
+static struct mtk_gate_regs peri1_cg_regs = {
+       .set_ofs = 0x000c,
+       .clr_ofs = 0x0014,
+       .sta_ofs = 0x001c,
+};
+
+static struct mtk_gate peri_clks[] __initdata = {
+       /* PERI0 */
+       GATE(PERI_I2C5_CK, i2c5_ck, axi_sel, peri0_cg_regs,
+               31, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C4_CK, i2c4_ck, axi_sel, peri0_cg_regs,
+               30, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C3_CK, i2c3_ck, axi_sel, peri0_cg_regs,
+               29, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C2_CK, i2c2_ck, axi_sel, peri0_cg_regs,
+               28, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C1_CK, i2c1_ck, axi_sel, peri0_cg_regs,
+               27, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C0_CK, i2c0_ck, axi_sel, peri0_cg_regs,
+               26, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_UART3_CK, uart3_ck, axi_sel, peri0_cg_regs,
+               25, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_UART2_CK, uart2_ck, axi_sel, peri0_cg_regs,
+               24, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_UART1_CK, uart1_ck, axi_sel, peri0_cg_regs,
+               23, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_UART0_CK, uart0_ck, axi_sel, peri0_cg_regs,
+               22, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_IRDA_CK, irda_ck, irda_sel, peri0_cg_regs,
+               21, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_NLI_CK, nli_ck, axi_sel, peri0_cg_regs,
+               20, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MD_HIF_CK, md_hif_ck, axi_sel, peri0_cg_regs,
+               19, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_AP_HIF_CK, ap_hif_ck, axi_sel, peri0_cg_regs,
+               18, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MSDC30_3_CK, msdc30_3_ck, msdc30_4_sel, peri0_cg_regs,
+               17, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MSDC30_2_CK, msdc30_2_ck, msdc30_3_sel, peri0_cg_regs,
+               16, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MSDC30_1_CK, msdc30_1_ck, msdc30_2_sel, peri0_cg_regs,
+               15, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MSDC20_2_CK, msdc20_2_ck, msdc30_1_sel, peri0_cg_regs,
+               14, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_MSDC20_1_CK, msdc20_1_ck, msdc30_0_sel, peri0_cg_regs,
+               13, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_AP_DMA_CK, ap_dma_ck, axi_sel, peri0_cg_regs,
+               12, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_USB1_CK, usb1_ck, usb20_sel, peri0_cg_regs,
+               11, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_USB0_CK, usb0_ck, usb20_sel, peri0_cg_regs,
+               10, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM_CK, pwm_ck, axi_sel, peri0_cg_regs,
+               9, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM7_CK, pwm7_ck, axi_sel, peri0_cg_regs,
+               8, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM6_CK, pwm6_ck, axi_sel, peri0_cg_regs,
+               7, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM5_CK, pwm5_ck, axi_sel, peri0_cg_regs,
+               6, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM4_CK, pwm4_ck, axi_sel, peri0_cg_regs,
+               5, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM3_CK, pwm3_ck, axi_sel, peri0_cg_regs,
+               4, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM2_CK, pwm2_ck, axi_sel, peri0_cg_regs,
+               3, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PWM1_CK, pwm1_ck, axi_sel, peri0_cg_regs,
+               2, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_THERM_CK, therm_ck, axi_sel, peri0_cg_regs,
+               1, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_NFI_CK, nfi_ck, axi_sel, peri0_cg_regs,
+               0, &mtk_clk_gate_ops_setclr),
+       /* PERI1 */
+       GATE(PERI_USBSLV_CK, usbslv_ck, axi_sel, peri1_cg_regs,
+               8, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_USB1_MCU_CK, usb1_mcu_ck, axi_sel, peri1_cg_regs,
+               7, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_USB0_MCU_CK, usb0_mcu_ck, axi_sel, peri1_cg_regs,
+               6, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_GCPU_CK, gcpu_ck, gcpu_sel, peri1_cg_regs,
+               5, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_FHCTL_CK, fhctl_ck, clk26m, peri1_cg_regs,
+               4, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_SPI1_CK, spi1_ck, spi_sel, peri1_cg_regs,
+               3, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_AUXADC_CK, auxadc_ck, clk26m, peri1_cg_regs,
+               2, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_PERI_PWRAP_CK, peri_pwrap_ck, axi_sel, peri1_cg_regs,
+               1, &mtk_clk_gate_ops_setclr),
+       GATE(PERI_I2C6_CK, i2c6_ck, axi_sel, peri1_cg_regs,
+               0, &mtk_clk_gate_ops_setclr),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       int r;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s(): ioremap failed\n", __func__);
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(TOP_NR_CLK);
+
+       mtk_init_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+       mtk_init_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+       mtk_init_clk_topckgen(base, clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       int r;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s(): ioremap failed\n", __func__);
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(APMIXED_NR_CLK);
+
+       mtk_init_clk_apmixedsys(base, clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+               mtk_apmixedsys_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       struct regmap *regmap;
+       int r;
+
+       regmap = syscon_node_to_regmap(node);
+       if (IS_ERR(regmap)) {
+               pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+                               PTR_ERR(regmap));
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(INFRA_NR_CLK);
+
+       mtk_init_clk_gates(regmap, infra_clks, ARRAY_SIZE(infra_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+
+       mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       struct regmap *regmap;
+       int r;
+
+       regmap = syscon_node_to_regmap(node);
+       if (IS_ERR(regmap)) {
+               pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+                               PTR_ERR(regmap));
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(PERI_NR_CLK);
+
+       mtk_init_clk_gates(regmap, peri_clks, ARRAY_SIZE(peri_clks),
+                                               clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+
+       mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to