* [PATCH 0/4] Add common clock support for Mediatek MT8135.
@ 2014-11-28 11:34 James Liao
2014-11-28 11:34 ` [PATCH 1/4] clk: Add initial common clock support for Mediatek SoC MT8135 James Liao
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: James Liao @ 2014-11-28 11:34 UTC (permalink / raw)
To: Rob Herring, Matthias Brugger, Mike Turquette
Cc: Mark Rutland, Ashwin Chaugule, srv_jamesjj.liao, Russell King,
srv_heupstream, Pawel Moll, Ian Campbell, Catalin Marinas,
linux-kernel, devicetree, Vladimir Murzin, Sascha Hauer,
Kumar Gala, Joe.C, eddie.huang, linux-arm-kernel
This patchset contains the initial common clock support for Mediatek SoCs.
Mediatek SoC's clock architecture comprises of various PLLs, dividers,
muxes and clock gates.
This patchset also contains a basic clock support for Mediatek MT8135.
This driver is based on 3.18-rc1 + MT8135 basic support.
James Liao (4):
clk: Add initial common clock support for Mediatek SoC MT8135.
clk: Add INFRA and PERI clocks for Mediatek MT8135.
clk: dts: document Mediatek MT8135 clock binding
dts: Enable clock support for Mediatek MT8135.
.../bindings/clock/mediatek,mt8135-clock.txt | 36 +
arch/arm/boot/dts/mt8135.dtsi | 47 +
drivers/clk/Makefile | 1 +
drivers/clk/mediatek/Makefile | 2 +
drivers/clk/mediatek/clk-gate.c | 151 +++
drivers/clk/mediatek/clk-gate.h | 48 +
drivers/clk/mediatek/clk-mt8135-pll.c | 891 +++++++++++++++++
drivers/clk/mediatek/clk-mt8135-pll.h | 28 +
drivers/clk/mediatek/clk-mt8135.c | 1012 ++++++++++++++++++++
drivers/clk/mediatek/clk-mtk.c | 93 ++
drivers/clk/mediatek/clk-mtk.h | 47 +
drivers/clk/mediatek/clk-pll.c | 63 ++
drivers/clk/mediatek/clk-pll.h | 50 +
include/dt-bindings/clock/mt8135-clk.h | 190 ++++
14 files changed, 2659 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt
create mode 100644 drivers/clk/mediatek/Makefile
create mode 100644 drivers/clk/mediatek/clk-gate.c
create mode 100644 drivers/clk/mediatek/clk-gate.h
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
create mode 100644 drivers/clk/mediatek/clk-mtk.c
create mode 100644 drivers/clk/mediatek/clk-mtk.h
create mode 100644 drivers/clk/mediatek/clk-pll.c
create mode 100644 drivers/clk/mediatek/clk-pll.h
create mode 100644 include/dt-bindings/clock/mt8135-clk.h
--
1.8.1.1.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] clk: Add initial common clock support for Mediatek SoC MT8135.
2014-11-28 11:34 [PATCH 0/4] Add common clock support for Mediatek MT8135 James Liao
@ 2014-11-28 11:34 ` James Liao
2014-11-28 11:34 ` [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135 James Liao
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: James Liao @ 2014-11-28 11:34 UTC (permalink / raw)
To: Rob Herring, Matthias Brugger, Mike Turquette
Cc: Mark Rutland, Ashwin Chaugule, srv_jamesjj.liao, Russell King,
srv_heupstream, Pawel Moll, Ian Campbell, Catalin Marinas,
linux-kernel, devicetree, Vladimir Murzin, Sascha Hauer,
Kumar Gala
This patch adds common clock support for Mediatek SoCs, and basic clocks
such as PLLs and TOPCKGEN clocks for MT8135.
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
---
drivers/clk/Makefile | 1 +
drivers/clk/mediatek/Makefile | 2 +
drivers/clk/mediatek/clk-mt8135-pll.c | 891 +++++++++++++++++++++++++++++++++
drivers/clk/mediatek/clk-mt8135-pll.h | 28 ++
drivers/clk/mediatek/clk-mt8135.c | 752 ++++++++++++++++++++++++++++
drivers/clk/mediatek/clk-mtk.c | 93 ++++
drivers/clk/mediatek/clk-mtk.h | 47 ++
drivers/clk/mediatek/clk-pll.c | 63 +++
drivers/clk/mediatek/clk-pll.h | 50 ++
include/dt-bindings/clock/mt8135-clk.h | 128 +++++
10 files changed, 2055 insertions(+)
create mode 100644 drivers/clk/mediatek/Makefile
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
create mode 100644 drivers/clk/mediatek/clk-mtk.c
create mode 100644 drivers/clk/mediatek/clk-mtk.h
create mode 100644 drivers/clk/mediatek/clk-pll.c
create mode 100644 drivers/clk/mediatek/clk-pll.h
create mode 100644 include/dt-bindings/clock/mt8135-clk.h
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..ce6c250 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
obj-$(CONFIG_ARCH_HIP04) += hisilicon/
obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
endif
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000..3c3432b
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1,2 @@
+obj-y += clk-mtk.o clk-pll.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..999f640
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135-pll.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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"
+
+/*
+ * clk_pll
+ */
+
+#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 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 freq_limit(u32 freq)
+{
+ static const u32 freq_max = 2000 * 1000 * 1000; /* 2000 MHz */
+ static const u32 freq_min = 1000 * 1000 * 1000 / 16; /* 1000 MHz */
+
+ if (freq <= freq_min)
+ freq = freq_min + 16;
+ else if (freq > freq_max)
+ freq = freq_max;
+
+ return freq;
+}
+
+static int 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;
+
+ pr_debug("freq: %u\n", freq);
+
+ /* 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 clk_pll_is_enabled(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ int r = (readl_relaxed(pll->base_addr) & PLL_BASE_EN) != 0;
+
+ pr_debug("%d: %s\n", r, __clk_get_name(hw->clk));
+
+ return r;
+}
+
+static int clk_pll_prepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s\n", __clk_get_name(hw->clk));
+
+ mtk_clk_lock(flags);
+
+ r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON;
+ writel_relaxed(r, pll->pwr_addr);
+ dsb();
+ udelay(1);
+
+ r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN;
+ writel_relaxed(r , pll->pwr_addr);
+ dsb();
+ udelay(1);
+
+ r = readl_relaxed(pll->base_addr) | pll->en_mask;
+ writel_relaxed(r, pll->base_addr);
+ dsb();
+ udelay(20);
+
+ if (pll->flags & HAVE_RST_BAR) {
+ r = readl_relaxed(pll->base_addr) | RST_BAR_MASK;
+ writel_relaxed(r, pll->base_addr);
+ }
+
+ mtk_clk_unlock(flags);
+
+ return 0;
+}
+
+static void clk_pll_unprepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s: PLL_AO: %d\n",
+ __clk_get_name(hw->clk), !!(pll->flags & PLL_AO));
+
+ if (pll->flags & PLL_AO)
+ return;
+
+ mtk_clk_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);
+
+ mtk_clk_unlock(flags);
+}
+
+#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 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 = calc_pll_vco_freq(
+ parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+ r = vco_freq / pll_posdiv_map[posdiv];
+
+ pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));
+
+ return r;
+}
+
+static long clk_pll_round_rate(
+ struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ int r;
+ u32 pcwfbits = 14;
+ u32 pcw = 0;
+ u32 postdiv = 0;
+
+ pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);
+
+ *prate = *prate ? *prate : 26000000;
+ rate = freq_limit(rate);
+ calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+ r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+ r = r / pll_posdiv_map[postdiv];
+ return r;
+}
+
+static void 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;
+
+ mtk_clk_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) {
+ dsb();
+ udelay(20);
+ }
+
+ mtk_clk_unlock(flags);
+}
+
+static int 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 = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits);
+
+ pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n",
+ __clk_get_name(hw->clk), rate, pcw, postdiv_idx);
+
+ if (r == 0)
+ clk_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+ return r;
+}
+
+const struct clk_ops mtk_clk_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .prepare = clk_pll_prepare,
+ .unprepare = clk_pll_unprepare,
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+ .set_rate = 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 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 = calc_pll_vco_freq(
+ parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+ r = vco_freq / pll_posdiv_map[posdiv];
+
+ pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));
+
+ return r;
+}
+
+static void 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;
+
+ mtk_clk_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) {
+ dsb();
+ udelay(20);
+ }
+
+ mtk_clk_unlock(flags);
+}
+
+static int 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 = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits);
+
+ pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n",
+ __clk_get_name(hw->clk), rate, pcw, postdiv_idx);
+
+ if (r == 0)
+ clk_arm_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+ return r;
+}
+
+const struct clk_ops mtk_clk_arm_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .prepare = clk_pll_prepare,
+ .unprepare = clk_pll_unprepare,
+ .recalc_rate = clk_arm_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+ .set_rate = clk_arm_pll_set_rate,
+};
+
+static int clk_lc_pll_prepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s\n", __clk_get_name(hw->clk));
+
+ mtk_clk_lock(flags);
+
+ r = readl_relaxed(pll->base_addr) | pll->en_mask;
+ writel_relaxed(r, pll->base_addr);
+ dsb();
+ udelay(20);
+
+ if (pll->flags & HAVE_RST_BAR) {
+ r = readl_relaxed(pll->base_addr) | RST_BAR_MASK;
+ writel_relaxed(r, pll->base_addr);
+ }
+
+ mtk_clk_unlock(flags);
+
+ return 0;
+}
+
+static void clk_lc_pll_unprepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s\n", __clk_get_name(hw->clk));
+
+ mtk_clk_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);
+
+ mtk_clk_unlock(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 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];
+
+ pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));
+
+ return r;
+}
+
+static long clk_lc_pll_round_rate(
+ struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ int r;
+ u32 pcwfbits = 0;
+ u32 pcw = 0;
+ u32 postdiv = 0;
+
+ pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);
+
+ *prate = *prate ? *prate : 26000000;
+ rate = freq_limit(rate);
+ calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+ r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+ r = r / pll_posdiv_map[postdiv];
+ return r;
+}
+
+static void 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;
+
+ mtk_clk_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) {
+ dsb();
+ udelay(20);
+ }
+ mtk_clk_unlock(flags);
+}
+
+static int 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 = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits);
+
+ pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n",
+ __clk_get_name(hw->clk), rate, pcw, postdiv_idx);
+
+ if (r == 0)
+ clk_lc_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+ return r;
+}
+
+const struct clk_ops mtk_clk_lc_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .prepare = clk_lc_pll_prepare,
+ .unprepare = clk_lc_pll_unprepare,
+ .recalc_rate = clk_lc_pll_recalc_rate,
+ .round_rate = clk_lc_pll_round_rate,
+ .set_rate = clk_lc_pll_set_rate,
+};
+
+static int clk_aud_pll_prepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s\n", __clk_get_name(hw->clk));
+
+ mtk_clk_lock(flags);
+
+ r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON;
+ writel_relaxed(r, pll->pwr_addr);
+ dsb();
+ udelay(1);
+
+ r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN;
+ writel_relaxed(r, pll->pwr_addr);
+ dsb();
+ udelay(1);
+
+ r = readl_relaxed(pll->base_addr) | pll->en_mask;
+ writel_relaxed(r, pll->base_addr);
+
+ r = readl_relaxed(pll->base_addr + 16) | AUDPLL_TUNER_EN;
+ writel_relaxed(r, pll->base_addr + 16);
+ dsb();
+ udelay(20);
+
+ if (pll->flags & HAVE_RST_BAR) {
+ r = readl_relaxed(pll->base_addr) | RST_BAR_MASK;
+ writel_relaxed(r, pll->base_addr);
+ }
+
+ mtk_clk_unlock(flags);
+
+ return 0;
+}
+
+static void clk_aud_pll_unprepare(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ pr_debug("%s\n", __clk_get_name(hw->clk));
+
+ mtk_clk_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 + 16) & ~AUDPLL_TUNER_EN;
+ writel_relaxed(r, pll->base_addr + 16);
+
+ 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);
+
+ mtk_clk_unlock(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 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 = calc_pll_vco_freq(
+ parent_rate, pcw, vcodivsel, prediv, pcwfbits);
+ r = vco_freq / pll_posdiv_map[posdiv];
+
+ pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));
+
+ return r;
+}
+
+static long clk_aud_pll_round_rate(
+ struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ int r;
+ u32 pcwfbits = 24;
+ u32 pcw = 0;
+ u32 postdiv = 0;
+
+ pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);
+
+ *prate = *prate ? *prate : 26000000;
+ rate = freq_limit(rate);
+ calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits);
+
+ r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits);
+ r = r / pll_posdiv_map[postdiv];
+ return r;
+}
+
+static void 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;
+
+ mtk_clk_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) {
+ dsb();
+ udelay(20);
+ }
+
+ mtk_clk_unlock(flags);
+}
+
+static int 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 = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits);
+
+ pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n",
+ __clk_get_name(hw->clk), rate, pcw, postdiv_idx);
+
+ if (r == 0)
+ clk_aud_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+ return r;
+}
+
+const struct clk_ops mtk_clk_aud_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .prepare = clk_aud_pll_prepare,
+ .unprepare = clk_aud_pll_unprepare,
+ .recalc_rate = clk_aud_pll_recalc_rate,
+ .round_rate = clk_aud_pll_round_rate,
+ .set_rate = 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 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;
+
+ mtk_clk_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) {
+ dsb();
+ udelay(20);
+ }
+
+ mtk_clk_unlock(flags);
+}
+
+static int 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 = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits);
+
+ pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n",
+ __clk_get_name(hw->clk), rate, pcw, postdiv_idx);
+
+ if (r == 0)
+ clk_tvd_pll_set_rate_regs(hw, pcw, postdiv_idx);
+
+ return r;
+}
+
+const struct clk_ops mtk_clk_tvd_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .prepare = clk_pll_prepare,
+ .unprepare = clk_pll_unprepare,
+ .recalc_rate = clk_aud_pll_recalc_rate,
+ .round_rate = clk_aud_pll_round_rate,
+ .set_rate = 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..0628189
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135-pll.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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 mtk_clk_pll_ops;
+extern const struct clk_ops mtk_clk_arm_pll_ops;
+extern const struct clk_ops mtk_clk_lc_pll_ops;
+extern const struct clk_ops mtk_clk_aud_pll_ops;
+extern const struct clk_ops mtk_clk_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..fa8dd7d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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 "clk-mtk.h"
+#include "clk-pll.h"
+#include "clk-mt8135-pll.h"
+
+#include <dt-bindings/clock/mt8135-clk.h>
+
+/*
+ * platform clocks
+ */
+
+/* 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"
+
+struct mtk_fixed_factor {
+ int id;
+ const char *name;
+ const char *parent_name;
+ int mult;
+ int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .mult = _mult, \
+ .div = _div, \
+ }
+
+static void __init init_factors(struct mtk_fixed_factor *clks, int num,
+ struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+
+ for (i = 0; i < num; i++) {
+ struct mtk_fixed_factor *ff = &clks[i];
+
+ clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+ 0, ff->mult, ff->div);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ ff->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[ff->id] = clk;
+
+ pr_debug("factor %3d: %s\n", i, ff->name);
+ }
+}
+
+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 void __init init_clk_root_alias(struct clk_onecell_data *clk_data)
+{
+ init_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+}
+
+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 void __init init_clk_top_div(struct clk_onecell_data *clk_data)
+{
+ init_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+}
+
+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};
+
+struct mtk_mux {
+ int id;
+ const char *name;
+ u32 reg;
+ int shift;
+ int width;
+ int gate;
+ const char **parent_names;
+ int num_parents;
+};
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width, _gate) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+ .gate = _gate, \
+ .parent_names = (const char **)_parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ }
+
+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 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);
+
+ 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;
+
+ pr_debug("mux %3d: %s\n", i, mux->name);
+ }
+}
+
+struct mtk_pll {
+ int id;
+ const char *name;
+ const char *parent_name;
+ u32 reg;
+ u32 pwr_reg;
+ u32 en_mask;
+ unsigned int flags;
+ const struct clk_ops *ops;
+};
+
+#define PLL(_id, _name, _parent, _reg, _pwr_reg, _en_mask, _flags, _ops) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .ops = _ops, \
+ }
+
+static struct mtk_pll plls[] __initdata = {
+ PLL(APMIXED_ARMPLL1, armpll1, clk26m, 0x0200, 0x0218,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_arm_pll_ops),
+ PLL(APMIXED_ARMPLL2, armpll2, clk26m, 0x02cc, 0x02e4,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_arm_pll_ops),
+ PLL(APMIXED_MAINPLL, mainpll, clk26m, 0x021c, 0x0234,
+ 0xf0000001, HAVE_PLL_HP | HAVE_RST_BAR | PLL_AO,
+ &mtk_clk_pll_ops),
+ PLL(APMIXED_UNIVPLL, univpll, clk26m, 0x0238, 0x0250,
+ 0xf3000001, HAVE_RST_BAR | HAVE_FIX_FRQ | PLL_AO,
+ &mtk_clk_lc_pll_ops),
+ PLL(APMIXED_MMPLL, mmpll, clk26m, 0x0254, 0x026c,
+ 0xf0000001, HAVE_PLL_HP | HAVE_RST_BAR, &mtk_clk_pll_ops),
+ PLL(APMIXED_MSDCPLL, msdcpll, clk26m, 0x0278, 0x0290,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_pll_ops),
+ PLL(APMIXED_TVDPLL, tvdpll, clk26m, 0x0294, 0x02ac,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_tvd_pll_ops),
+ PLL(APMIXED_LVDSPLL, lvdspll, clk26m, 0x02b0, 0x02c8,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_pll_ops),
+ PLL(APMIXED_AUDPLL, audpll, clk26m, 0x02e8, 0x0300,
+ 0x80000001, 0, &mtk_clk_aud_pll_ops),
+ PLL(APMIXED_VDECPLL, vdecpll, clk26m, 0x0304, 0x031c,
+ 0x80000001, HAVE_PLL_HP, &mtk_clk_pll_ops),
+};
+
+static void __init 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);
+
+ 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;
+
+ pr_debug("pll %3d: %s\n", i, pll->name);
+ }
+}
+
+/*
+ * device tree support
+ */
+
+static struct clk_onecell_data *alloc_clk_data(unsigned int clk_num)
+{
+ int i;
+ struct clk_onecell_data *clk_data;
+
+ clk_data = kzalloc(sizeof(clk_data), GFP_KERNEL);
+ if (!clk_data)
+ return NULL;
+
+ clk_data->clks = kcalloc(clk_num, sizeof(struct clk *), GFP_KERNEL);
+ if (!clk_data->clks) {
+ kfree(clk_data);
+ return NULL;
+ }
+
+ clk_data->clk_num = clk_num;
+
+ for (i = 0; i < clk_num; ++i)
+ clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+ return clk_data;
+}
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ pr_debug("%s: %s\n", __func__, node->name);
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("ioremap topckgen failed\n");
+ return;
+ }
+
+ clk_data = alloc_clk_data(TOP_NR_CLK);
+
+ init_clk_root_alias(clk_data);
+ init_clk_top_div(clk_data);
+ init_clk_topckgen(base, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("could not register clock provide\n");
+}
+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;
+
+ pr_debug("%s: %s\n", __func__, node->name);
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("ioremap apmixedsys failed\n");
+ return;
+ }
+
+ clk_data = alloc_clk_data(APMIXED_NR_CLK);
+
+ init_clk_apmixedsys(base, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("could not register clock provide\n");
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+ mtk_apmixedsys_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 0000000..41a12d3
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+
+static DEFINE_SPINLOCK(clk_ops_lock);
+
+spinlock_t *get_mtk_clk_lock(void)
+{
+ return &clk_ops_lock;
+}
+
+/*
+ * clk_mux
+ */
+
+struct clk *mtk_clk_register_mux(
+ const char *name,
+ const char **parent_names,
+ u8 num_parents,
+ void __iomem *base_addr,
+ u8 shift,
+ u8 width,
+ u8 gate_bit)
+{
+ struct clk *clk;
+ struct clk_mux *mux;
+ struct clk_gate *gate = NULL;
+ struct clk_hw *gate_hw = NULL;
+ const struct clk_ops *gate_ops = NULL;
+ u32 mask = BIT(width) - 1;
+
+ pr_debug("name: %s, num_parents: %d, gate_bit: %d\n",
+ name, (int)num_parents, (int)gate_bit);
+
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = base_addr;
+ mux->mask = mask;
+ mux->shift = shift;
+ mux->flags = 0;
+ mux->lock = &clk_ops_lock;
+
+ if (gate_bit <= MAX_MUX_GATE_BIT) {
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(mux);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base_addr;
+ gate->bit_idx = gate_bit;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &clk_ops_lock;
+
+ gate_hw = &gate->hw;
+ gate_ops = &clk_gate_ops;
+ }
+
+ clk = clk_register_composite(NULL, name, parent_names, num_parents,
+ &mux->hw, &clk_mux_ops,
+ NULL, NULL,
+ gate_hw, gate_ops,
+ CLK_IGNORE_UNUSED);
+
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 0000000..b69245d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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_MTK_H
+#define __DRV_CLK_MTK_H
+
+/*
+ * This is a private header file. DO NOT include it except clk-*.c.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define CLK_DEBUG 0
+#define DUMMY_REG_TEST 0
+
+extern spinlock_t *get_mtk_clk_lock(void);
+
+#define mtk_clk_lock(flags) spin_lock_irqsave(get_mtk_clk_lock(), flags)
+#define mtk_clk_unlock(flags) \
+ spin_unlock_irqrestore(get_mtk_clk_lock(), flags)
+
+#define MAX_MUX_GATE_BIT 31
+#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
+
+struct clk *mtk_clk_register_mux(
+ const char *name,
+ const char **parent_names,
+ u8 num_parents,
+ void __iomem *base_addr,
+ u8 shift,
+ u8 width,
+ u8 gate_bit);
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 0000000..864cc60
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+/*
+ * clk_pll
+ */
+
+struct clk *mtk_clk_register_pll(
+ const char *name,
+ const char *parent_name,
+ u32 *base_addr,
+ u32 *pwr_addr,
+ u32 en_mask,
+ u32 flags,
+ const struct clk_ops *ops)
+{
+ struct mtk_clk_pll *pll;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ pr_debug("name: %s\n", name);
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->base_addr = base_addr;
+ pll->pwr_addr = pwr_addr;
+ pll->en_mask = en_mask;
+ pll->flags = flags;
+ pll->hw.init = &init;
+
+ init.name = name;
+ init.ops = ops;
+ init.flags = CLK_IGNORE_UNUSED;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &pll->hw);
+
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
new file mode 100644
index 0000000..cb7f335
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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_PLL_H
+#define __DRV_CLK_PLL_H
+
+/*
+ * This is a private header file. DO NOT include it except clk-*.c.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_pll {
+ struct clk_hw hw;
+ void __iomem *base_addr;
+ void __iomem *pwr_addr;
+ u32 en_mask;
+ u32 flags;
+};
+
+#define to_mtk_clk_pll(_hw) container_of(_hw, struct mtk_clk_pll, hw)
+
+#define HAVE_RST_BAR BIT(0)
+#define HAVE_PLL_HP BIT(1)
+#define HAVE_FIX_FRQ BIT(2)
+#define PLL_AO BIT(3)
+
+struct clk *mtk_clk_register_pll(
+ const char *name,
+ const char *parent_name,
+ u32 *base_addr,
+ u32 *pwr_addr,
+ u32 en_mask,
+ u32 flags,
+ const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_PLL_H */
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 0000000..674fd1a
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2014 MediaTek Inc.
+* Author: James Liao <jamesjj.liao@mediatek.com>
+*
+* 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 _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define TOP_DSI0_LNTC_DSICLK 1
+#define TOP_HDMITX_CLKDIG_CTS 2
+#define TOP_CLKPH_MCK 3
+#define TOP_CPUM_TCK_IN 4
+#define TOP_MAINPLL_806M 5
+#define TOP_MAINPLL_537P3M 6
+#define TOP_MAINPLL_322P4M 7
+#define TOP_MAINPLL_230P3M 8
+#define TOP_UNIVPLL_624M 9
+#define TOP_UNIVPLL_416M 10
+#define TOP_UNIVPLL_249P6M 11
+#define TOP_UNIVPLL_178P3M 12
+#define TOP_UNIVPLL_48M 13
+#define TOP_MMPLL_D2 14
+#define TOP_MMPLL_D3 15
+#define TOP_MMPLL_D5 16
+#define TOP_MMPLL_D7 17
+#define TOP_MMPLL_D4 18
+#define TOP_MMPLL_D6 19
+#define TOP_SYSPLL_D2 20
+#define TOP_SYSPLL_D4 21
+#define TOP_SYSPLL_D6 22
+#define TOP_SYSPLL_D8 23
+#define TOP_SYSPLL_D10 24
+#define TOP_SYSPLL_D12 25
+#define TOP_SYSPLL_D16 26
+#define TOP_SYSPLL_D24 27
+#define TOP_SYSPLL_D3 28
+#define TOP_SYSPLL_D2P5 29
+#define TOP_SYSPLL_D5 30
+#define TOP_SYSPLL_D3P5 31
+#define TOP_UNIVPLL1_D2 32
+#define TOP_UNIVPLL1_D4 33
+#define TOP_UNIVPLL1_D6 34
+#define TOP_UNIVPLL1_D8 35
+#define TOP_UNIVPLL1_D10 36
+#define TOP_UNIVPLL2_D2 37
+#define TOP_UNIVPLL2_D4 38
+#define TOP_UNIVPLL2_D6 39
+#define TOP_UNIVPLL2_D8 40
+#define TOP_UNIVPLL_D3 41
+#define TOP_UNIVPLL_D5 42
+#define TOP_UNIVPLL_D7 43
+#define TOP_UNIVPLL_D10 44
+#define TOP_UNIVPLL_D26 45
+#define TOP_APLL_CK 46
+#define TOP_APLL_D4 47
+#define TOP_APLL_D8 48
+#define TOP_APLL_D16 49
+#define TOP_APLL_D24 50
+#define TOP_LVDSPLL_D2 51
+#define TOP_LVDSPLL_D4 52
+#define TOP_LVDSPLL_D8 53
+#define TOP_LVDSTX_CLKDIG_CT 54
+#define TOP_VPLL_DPIX_CK 55
+#define TOP_TVHDMI_H_CK 56
+#define TOP_HDMITX_CLKDIG_D2 57
+#define TOP_HDMITX_CLKDIG_D3 58
+#define TOP_TVHDMI_D2 59
+#define TOP_TVHDMI_D4 60
+#define TOP_MEMPLL_MCK_D4 61
+#define TOP_AXI_SEL 62
+#define TOP_SMI_SEL 63
+#define TOP_MFG_SEL 64
+#define TOP_IRDA_SEL 65
+#define TOP_CAM_SEL 66
+#define TOP_AUD_INTBUS_SEL 67
+#define TOP_JPG_SEL 68
+#define TOP_DISP_SEL 69
+#define TOP_MSDC30_1_SEL 70
+#define TOP_MSDC30_2_SEL 71
+#define TOP_MSDC30_3_SEL 72
+#define TOP_MSDC30_4_SEL 73
+#define TOP_USB20_SEL 74
+#define TOP_VENC_SEL 75
+#define TOP_SPI_SEL 76
+#define TOP_UART_SEL 77
+#define TOP_MEM_SEL 78
+#define TOP_CAMTG_SEL 79
+#define TOP_AUDIO_SEL 80
+#define TOP_FIX_SEL 81
+#define TOP_VDEC_SEL 82
+#define TOP_DDRPHYCFG_SEL 83
+#define TOP_DPILVDS_SEL 84
+#define TOP_PMICSPI_SEL 85
+#define TOP_MSDC30_0_SEL 86
+#define TOP_SMI_MFG_AS_SEL 87
+#define TOP_GCPU_SEL 88
+#define TOP_DPI1_SEL 89
+#define TOP_CCI_SEL 90
+#define TOP_APLL_SEL 91
+#define TOP_HDMIPLL_SEL 92
+#define TOP_NR_CLK 93
+
+/* APMIXED_SYS */
+
+#define APMIXED_ARMPLL1 1
+#define APMIXED_ARMPLL2 2
+#define APMIXED_MAINPLL 3
+#define APMIXED_UNIVPLL 4
+#define APMIXED_MMPLL 5
+#define APMIXED_MSDCPLL 6
+#define APMIXED_TVDPLL 7
+#define APMIXED_LVDSPLL 8
+#define APMIXED_AUDPLL 9
+#define APMIXED_VDECPLL 10
+#define APMIXED_NR_CLK 11
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
--
1.8.1.1.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135.
2014-11-28 11:34 [PATCH 0/4] Add common clock support for Mediatek MT8135 James Liao
2014-11-28 11:34 ` [PATCH 1/4] clk: Add initial common clock support for Mediatek SoC MT8135 James Liao
@ 2014-11-28 11:34 ` James Liao
[not found] ` <1417174490-6845-3-git-send-email-jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2014-11-28 11:34 ` [PATCH 3/4] clk: dts: document Mediatek MT8135 clock binding James Liao
2014-11-28 11:34 ` [PATCH 4/4] dts: Enable clock support for Mediatek MT8135 James Liao
3 siblings, 1 reply; 7+ messages in thread
From: James Liao @ 2014-11-28 11:34 UTC (permalink / raw)
To: Rob Herring, Matthias Brugger, Mike Turquette
Cc: Mark Rutland, Ashwin Chaugule, srv_jamesjj.liao, Russell King,
srv_heupstream, Pawel Moll, Ian Campbell, Catalin Marinas,
linux-kernel, devicetree, Vladimir Murzin, Sascha Hauer,
Kumar Gala
This patch adds clock gates support for Mediatek SoCs, and adds clocks of
INFRA sys and PERI sys for MT8135.
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
---
drivers/clk/mediatek/Makefile | 2 +-
drivers/clk/mediatek/clk-gate.c | 151 +++++++++++++++++++
drivers/clk/mediatek/clk-gate.h | 48 ++++++
drivers/clk/mediatek/clk-mt8135.c | 260 +++++++++++++++++++++++++++++++++
include/dt-bindings/clock/mt8135-clk.h | 62 ++++++++
5 files changed, 522 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/mediatek/clk-gate.c
create mode 100644 drivers/clk/mediatek/clk-gate.h
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 3c3432b..96a7044 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,2 +1,2 @@
-obj-y += clk-mtk.o clk-pll.o
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
obj-y += clk-mt8135.o clk-mt8135-pll.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 0000000..8f9a9ea
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+/*
+ * clk_gate
+ */
+
+static void cg_set_mask(struct mtk_clk_gate *cg, u32 mask)
+{
+ u32 r;
+
+ if (cg->flags & CLK_GATE_NO_SETCLR_REG) {
+ r = readl_relaxed(cg->sta_addr) | mask;
+ writel_relaxed(r, cg->sta_addr);
+ } else
+ writel_relaxed(mask, cg->set_addr);
+}
+
+static void cg_clr_mask(struct mtk_clk_gate *cg, u32 mask)
+{
+ u32 r;
+
+ if (cg->flags & CLK_GATE_NO_SETCLR_REG) {
+ r = readl_relaxed(cg->sta_addr) & ~mask;
+ writel_relaxed(r, cg->sta_addr);
+ } else
+ writel_relaxed(mask, cg->clr_addr);
+}
+
+static int cg_enable(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+ u32 mask = BIT(cg->bit);
+
+ pr_debug("%s, bit: %u\n", __clk_get_name(hw->clk), cg->bit);
+
+ mtk_clk_lock(flags);
+
+ if (cg->flags & CLK_GATE_INVERSE)
+ cg_set_mask(cg, mask);
+ else
+ cg_clr_mask(cg, mask);
+
+ mtk_clk_unlock(flags);
+
+ return 0;
+}
+
+static void cg_disable(struct clk_hw *hw)
+{
+ unsigned long flags = 0;
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+ u32 mask = BIT(cg->bit);
+
+ pr_debug("%s, bit: %u\n", __clk_get_name(hw->clk), cg->bit);
+
+ mtk_clk_lock(flags);
+
+ if (cg->flags & CLK_GATE_INVERSE)
+ cg_clr_mask(cg, mask);
+ else
+ cg_set_mask(cg, mask);
+
+ mtk_clk_unlock(flags);
+}
+
+static int cg_is_enabled(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+ u32 mask;
+ u32 val;
+ int r;
+
+ mask = BIT(cg->bit);
+ val = mask & readl(cg->sta_addr);
+
+ r = (cg->flags & CLK_GATE_INVERSE) ? (val != 0) : (val == 0);
+
+ pr_debug("%d, %s, bit[%d]\n", r, __clk_get_name(hw->clk), (int)cg->bit);
+
+ return r;
+}
+
+static const struct clk_ops mtk_clk_gate_ops = {
+ .is_enabled = cg_is_enabled,
+ .enable = cg_enable,
+ .disable = cg_disable,
+};
+
+struct clk *mtk_clk_register_gate(
+ const char *name,
+ const char *parent_name,
+ void __iomem *set_addr,
+ void __iomem *clr_addr,
+ void __iomem *sta_addr,
+ u8 bit,
+ u32 flags)
+{
+ struct mtk_clk_gate *cg;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pr_debug("name: %s, bit: %d\n", name, (int)bit);
+
+ cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+ if (!cg)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.flags = CLK_IGNORE_UNUSED;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.ops = &mtk_clk_gate_ops;
+
+ cg->set_addr = set_addr;
+ cg->clr_addr = clr_addr;
+ cg->sta_addr = sta_addr;
+ cg->bit = bit;
+ cg->flags = flags;
+
+ cg->hw.init = &init;
+
+ clk = clk_register(NULL, &cg->hw);
+ if (IS_ERR(clk))
+ kfree(cg);
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 0000000..0d71aad
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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_GATE_H
+#define __DRV_CLK_GATE_H
+
+/*
+ * This is a private header file. DO NOT include it except clk-*.c.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+ struct clk_hw hw;
+ void __iomem *set_addr;
+ void __iomem *clr_addr;
+ void __iomem *sta_addr;
+ u8 bit;
+ u32 flags;
+};
+
+#define to_clk_gate(_hw) container_of(_hw, struct mtk_clk_gate, hw)
+
+#define CLK_GATE_INVERSE BIT(0)
+#define CLK_GATE_NO_SETCLR_REG BIT(1)
+
+struct clk *mtk_clk_register_gate(
+ const char *name,
+ const char *parent_name,
+ void __iomem *set_addr,
+ void __iomem *clr_addr,
+ void __iomem *sta_addr,
+ u8 bit,
+ u32 flags);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
index fa8dd7d..2496e54 100644
--- a/drivers/clk/mediatek/clk-mt8135.c
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -18,6 +18,7 @@
#include "clk-mtk.h"
#include "clk-pll.h"
+#include "clk-gate.h"
#include "clk-mt8135-pll.h"
#include <dt-bindings/clock/mt8135-clk.h>
@@ -149,6 +150,66 @@
#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"
+
struct mtk_fixed_factor {
int id;
const char *name;
@@ -673,6 +734,157 @@ static void __init init_clk_apmixedsys(void __iomem *apmixed_base,
}
}
+struct mtk_gate_regs {
+ u32 sta_ofs;
+ u32 clr_ofs;
+ u32 set_ofs;
+};
+
+struct mtk_gate {
+ int id;
+ const char *name;
+ const char *parent_name;
+ struct mtk_gate_regs *regs;
+ int shift;
+ u32 flags;
+};
+
+#define GATE(_id, _name, _parent, _regs, _shift, _flags) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &_regs, \
+ .shift = _shift, \
+ .flags = _flags, \
+ }
+
+static void __init init_clk_gates(
+ void __iomem *reg_base,
+ struct mtk_gate *clks, int num,
+ struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+
+ for (i = 0; i < num; i++) {
+ struct mtk_gate *gate = &clks[i];
+
+ clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+ reg_base + gate->regs->set_ofs,
+ reg_base + gate->regs->clr_ofs,
+ reg_base + gate->regs->sta_ofs,
+ gate->shift, gate->flags);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ gate->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[gate->id] = clk;
+
+ pr_debug("gate %3d: %s\n", i, gate->name);
+ }
+}
+
+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, 0),
+ GATE(INFRA_PMICSPI_CK, pmicspi_ck, pmicspi_sel, infra_cg_regs, 22, 0),
+ GATE(INFRA_CCIF1_AP_CTRL, ccif1_ap_ctrl, axi_sel, infra_cg_regs, 21, 0),
+ GATE(INFRA_CCIF0_AP_CTRL, ccif0_ap_ctrl, axi_sel, infra_cg_regs, 20, 0),
+ GATE(INFRA_KP_CK, kp_ck, axi_sel, infra_cg_regs, 16, 0),
+ GATE(INFRA_CPUM_CK, cpum_ck, cpum_tck_in, infra_cg_regs, 15, 0),
+ GATE(INFRA_M4U_CK, m4u_ck, mem_sel, infra_cg_regs, 8, 0),
+ GATE(INFRA_MFGAXI_CK, mfgaxi_ck, axi_sel, infra_cg_regs, 7, 0),
+ GATE(INFRA_DEVAPC_CK, devapc_ck, axi_sel, infra_cg_regs, 6,
+ CLK_GATE_INVERSE),
+ GATE(INFRA_AUDIO_CK, audio_ck, aud_intbus_sel, infra_cg_regs, 5, 0),
+ GATE(INFRA_MFG_BUS_CK, mfg_bus_ck, axi_sel, infra_cg_regs, 2, 0),
+ GATE(INFRA_SMI_CK, smi_ck, smi_sel, infra_cg_regs, 1, 0),
+ GATE(INFRA_DBGCLK_CK, dbgclk_ck, axi_sel, infra_cg_regs, 0, 0),
+};
+
+static void __init init_clk_infrasys(void __iomem *infrasys_base,
+ struct clk_onecell_data *clk_data)
+{
+ pr_debug("init infrasys gates:\n");
+ init_clk_gates(infrasys_base, infra_clks, ARRAY_SIZE(infra_clks),
+ clk_data);
+}
+
+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, 0),
+ GATE(PERI_I2C4_CK, i2c4_ck, axi_sel, peri0_cg_regs, 30, 0),
+ GATE(PERI_I2C3_CK, i2c3_ck, axi_sel, peri0_cg_regs, 29, 0),
+ GATE(PERI_I2C2_CK, i2c2_ck, axi_sel, peri0_cg_regs, 28, 0),
+ GATE(PERI_I2C1_CK, i2c1_ck, axi_sel, peri0_cg_regs, 27, 0),
+ GATE(PERI_I2C0_CK, i2c0_ck, axi_sel, peri0_cg_regs, 26, 0),
+ GATE(PERI_UART3_CK, uart3_ck, axi_sel, peri0_cg_regs, 25, 0),
+ GATE(PERI_UART2_CK, uart2_ck, axi_sel, peri0_cg_regs, 24, 0),
+ GATE(PERI_UART1_CK, uart1_ck, axi_sel, peri0_cg_regs, 23, 0),
+ GATE(PERI_UART0_CK, uart0_ck, axi_sel, peri0_cg_regs, 22, 0),
+ GATE(PERI_IRDA_CK, irda_ck, irda_sel, peri0_cg_regs, 21, 0),
+ GATE(PERI_NLI_CK, nli_ck, axi_sel, peri0_cg_regs, 20, 0),
+ GATE(PERI_MD_HIF_CK, md_hif_ck, axi_sel, peri0_cg_regs, 19, 0),
+ GATE(PERI_AP_HIF_CK, ap_hif_ck, axi_sel, peri0_cg_regs, 18, 0),
+ GATE(PERI_MSDC30_3_CK, msdc30_3_ck, msdc30_4_sel, peri0_cg_regs, 17, 0),
+ GATE(PERI_MSDC30_2_CK, msdc30_2_ck, msdc30_3_sel, peri0_cg_regs, 16, 0),
+ GATE(PERI_MSDC30_1_CK, msdc30_1_ck, msdc30_2_sel, peri0_cg_regs, 15, 0),
+ GATE(PERI_MSDC20_2_CK, msdc20_2_ck, msdc30_1_sel, peri0_cg_regs, 14, 0),
+ GATE(PERI_MSDC20_1_CK, msdc20_1_ck, msdc30_0_sel, peri0_cg_regs, 13, 0),
+ GATE(PERI_AP_DMA_CK, ap_dma_ck, axi_sel, peri0_cg_regs, 12, 0),
+ GATE(PERI_USB1_CK, usb1_ck, usb20_sel, peri0_cg_regs, 11, 0),
+ GATE(PERI_USB0_CK, usb0_ck, usb20_sel, peri0_cg_regs, 10, 0),
+ GATE(PERI_PWM_CK, pwm_ck, axi_sel, peri0_cg_regs, 9, 0),
+ GATE(PERI_PWM7_CK, pwm7_ck, axi_sel, peri0_cg_regs, 8, 0),
+ GATE(PERI_PWM6_CK, pwm6_ck, axi_sel, peri0_cg_regs, 7, 0),
+ GATE(PERI_PWM5_CK, pwm5_ck, axi_sel, peri0_cg_regs, 6, 0),
+ GATE(PERI_PWM4_CK, pwm4_ck, axi_sel, peri0_cg_regs, 5, 0),
+ GATE(PERI_PWM3_CK, pwm3_ck, axi_sel, peri0_cg_regs, 4, 0),
+ GATE(PERI_PWM2_CK, pwm2_ck, axi_sel, peri0_cg_regs, 3, 0),
+ GATE(PERI_PWM1_CK, pwm1_ck, axi_sel, peri0_cg_regs, 2, 0),
+ GATE(PERI_THERM_CK, therm_ck, axi_sel, peri0_cg_regs, 1, 0),
+ GATE(PERI_NFI_CK, nfi_ck, axi_sel, peri0_cg_regs, 0, 0),
+ /* PERI1 */
+ GATE(PERI_USBSLV_CK, usbslv_ck, axi_sel, peri1_cg_regs, 8, 0),
+ GATE(PERI_USB1_MCU_CK, usb1_mcu_ck, axi_sel, peri1_cg_regs, 7, 0),
+ GATE(PERI_USB0_MCU_CK, usb0_mcu_ck, axi_sel, peri1_cg_regs, 6, 0),
+ GATE(PERI_GCPU_CK, gcpu_ck, gcpu_sel, peri1_cg_regs, 5, 0),
+ GATE(PERI_FHCTL_CK, fhctl_ck, clk26m, peri1_cg_regs, 4, 0),
+ GATE(PERI_SPI1_CK, spi1_ck, spi_sel, peri1_cg_regs, 3, 0),
+ GATE(PERI_AUXADC_CK, auxadc_ck, clk26m, peri1_cg_regs, 2, 0),
+ GATE(PERI_PERI_PWRAP_CK, peri_pwrap_ck, axi_sel, peri1_cg_regs, 1, 0),
+ GATE(PERI_I2C6_CK, i2c6_ck, axi_sel, peri1_cg_regs, 0, 0),
+};
+
+static void __init init_clk_perisys(void __iomem *perisys_base,
+ struct clk_onecell_data *clk_data)
+{
+ pr_debug("init perisys gates:\n");
+ init_clk_gates(perisys_base, peri_clks, ARRAY_SIZE(peri_clks),
+ clk_data);
+}
+
/*
* device tree support
*/
@@ -750,3 +962,51 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
}
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;
+ void __iomem *base;
+ int r;
+
+ pr_debug("%s: %s\n", __func__, node->name);
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("ioremap infrasys failed\n");
+ return;
+ }
+
+ clk_data = alloc_clk_data(INFRA_NR_CLK);
+
+ init_clk_infrasys(base, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("could not register clock provide\n");
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_perisys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ pr_debug("%s: %s\n", __func__, node->name);
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("ioremap infrasys failed\n");
+ return;
+ }
+
+ clk_data = alloc_clk_data(PERI_NR_CLK);
+
+ init_clk_perisys(base, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("could not register clock provide\n");
+}
+CLK_OF_DECLARE(mtk_perisys, "mediatek,mt8135-pericfg", mtk_perisys_init);
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
index 674fd1a..a477354 100644
--- a/include/dt-bindings/clock/mt8135-clk.h
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -125,4 +125,66 @@
#define APMIXED_VDECPLL 10
#define APMIXED_NR_CLK 11
+/* INFRA_SYS */
+
+#define INFRA_PMIC_WRAP_CK 1
+#define INFRA_PMICSPI_CK 2
+#define INFRA_CCIF1_AP_CTRL 3
+#define INFRA_CCIF0_AP_CTRL 4
+#define INFRA_KP_CK 5
+#define INFRA_CPUM_CK 6
+#define INFRA_M4U_CK 7
+#define INFRA_MFGAXI_CK 8
+#define INFRA_DEVAPC_CK 9
+#define INFRA_AUDIO_CK 10
+#define INFRA_MFG_BUS_CK 11
+#define INFRA_SMI_CK 12
+#define INFRA_DBGCLK_CK 13
+#define INFRA_NR_CLK 14
+
+/* PERI_SYS */
+
+#define PERI_I2C5_CK 1
+#define PERI_I2C4_CK 2
+#define PERI_I2C3_CK 3
+#define PERI_I2C2_CK 4
+#define PERI_I2C1_CK 5
+#define PERI_I2C0_CK 6
+#define PERI_UART3_CK 7
+#define PERI_UART2_CK 8
+#define PERI_UART1_CK 9
+#define PERI_UART0_CK 10
+#define PERI_IRDA_CK 11
+#define PERI_NLI_CK 12
+#define PERI_MD_HIF_CK 13
+#define PERI_AP_HIF_CK 14
+#define PERI_MSDC30_3_CK 15
+#define PERI_MSDC30_2_CK 16
+#define PERI_MSDC30_1_CK 17
+#define PERI_MSDC20_2_CK 18
+#define PERI_MSDC20_1_CK 19
+#define PERI_AP_DMA_CK 20
+#define PERI_USB1_CK 21
+#define PERI_USB0_CK 22
+#define PERI_PWM_CK 23
+#define PERI_PWM7_CK 24
+#define PERI_PWM6_CK 25
+#define PERI_PWM5_CK 26
+#define PERI_PWM4_CK 27
+#define PERI_PWM3_CK 28
+#define PERI_PWM2_CK 29
+#define PERI_PWM1_CK 30
+#define PERI_THERM_CK 31
+#define PERI_NFI_CK 32
+#define PERI_USBSLV_CK 33
+#define PERI_USB1_MCU_CK 34
+#define PERI_USB0_MCU_CK 35
+#define PERI_GCPU_CK 36
+#define PERI_FHCTL_CK 37
+#define PERI_SPI1_CK 38
+#define PERI_AUXADC_CK 39
+#define PERI_PERI_PWRAP_CK 40
+#define PERI_I2C6_CK 41
+#define PERI_NR_CLK 42
+
#endif /* _DT_BINDINGS_CLK_MT8135_H */
--
1.8.1.1.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] clk: dts: document Mediatek MT8135 clock binding
2014-11-28 11:34 [PATCH 0/4] Add common clock support for Mediatek MT8135 James Liao
2014-11-28 11:34 ` [PATCH 1/4] clk: Add initial common clock support for Mediatek SoC MT8135 James Liao
2014-11-28 11:34 ` [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135 James Liao
@ 2014-11-28 11:34 ` James Liao
2014-11-28 11:34 ` [PATCH 4/4] dts: Enable clock support for Mediatek MT8135 James Liao
3 siblings, 0 replies; 7+ messages in thread
From: James Liao @ 2014-11-28 11:34 UTC (permalink / raw)
To: Rob Herring, Matthias Brugger, Mike Turquette
Cc: Mark Rutland, Ashwin Chaugule, srv_jamesjj.liao, Russell King,
srv_heupstream, Pawel Moll, Ian Campbell, Catalin Marinas,
linux-kernel, devicetree, Vladimir Murzin, Sascha Hauer,
Kumar Gala
Document the device-tree binding of Mediatek MT8135 SoC, including
TOPCKGEN, PLLs, INFRA and PERI clock controller.
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
---
.../bindings/clock/mediatek,mt8135-clock.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt b/Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt
new file mode 100644
index 0000000..e23df49
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt
@@ -0,0 +1,36 @@
+Mediatek MT8135 Clock Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The Mediatek MT8135 clock controller generates and supplies clock to various
+controllers within Mediatek MT8135 SoC.
+
+Required Properties:
+
+- compatible: should be one of following:
+ - "mediatek,mt8135-topckgen" : for topckgen clock controller of MT8135.
+ - "mediatek,mt8135-apmixedsys" : for apmixed_sys (PLLs) of MT8135.
+ - "mediatek,mt8135-infracfg" : for infra_sys clock controller of MT8135.
+ - "mediatek,mt8135-pericfg" : for peri_sys clock controller of MT8135.
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #clock-cells: should be 1.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/mt8135-clk.h header and can be used in device tree sources.
+
+Example: I2C controller node that consumes the clock generated by the clock
+ controller (refer to the standard clock bindings for information about
+ "clocks" and "clock-names" properties):
+
+ i2c0: i2c@1100d000 {
+ compatible = "mediatek,mt8135-i2c", "mediatek,mt6589-i2c";
+ reg = <0 0x1100d000 0 0x70>, <0 0x11000300 0 0x80>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
+ clock-div = <16>;
+ clocks = <&pericfg PERI_I2C0_CK>, <&pericfg PERI_AP_DMA_CK>;
+ clock-names = "main", "dma";
+ };
--
1.8.1.1.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] dts: Enable clock support for Mediatek MT8135.
2014-11-28 11:34 [PATCH 0/4] Add common clock support for Mediatek MT8135 James Liao
` (2 preceding siblings ...)
2014-11-28 11:34 ` [PATCH 3/4] clk: dts: document Mediatek MT8135 clock binding James Liao
@ 2014-11-28 11:34 ` James Liao
3 siblings, 0 replies; 7+ messages in thread
From: James Liao @ 2014-11-28 11:34 UTC (permalink / raw)
To: Rob Herring, Matthias Brugger, Mike Turquette
Cc: Mark Rutland, Ashwin Chaugule, srv_jamesjj.liao, Russell King,
srv_heupstream, Pawel Moll, Ian Campbell, Catalin Marinas,
linux-kernel, devicetree, Vladimir Murzin, Sascha Hauer,
Kumar Gala
This patch adds MT8135 clock controllers into device tree.
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
---
arch/arm/boot/dts/mt8135.dtsi | 47 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 90a56ad..37d852b 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -12,6 +12,7 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/mt8135-clk.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "skeleton64.dtsi"
@@ -86,6 +87,24 @@
clock-frequency = <32000>;
#clock-cells = <0>;
};
+
+ clk_null: clk_null {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ clk26m: clk26m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ };
+
+ rtc32k: rtc32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32000>;
+ };
};
soc {
@@ -94,6 +113,28 @@
compatible = "simple-bus";
ranges;
+ topckgen: topckgen@10000000 {
+ compatible = "mediatek,mt8135-topckgen";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ infracfg: syscon@10001000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mediatek,mt8135-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ pericfg: syscon@10003000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mediatek,mt8135-pericfg", "syscon";
+ reg = <0 0x10003000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
timer: timer@10008000 {
compatible = "mediatek,mt8135-timer", "mediatek,mt6577-timer";
reg = <0 0x10008000 0 0x80>;
@@ -102,6 +143,12 @@
clock-names = "system-clk", "rtc-clk";
};
+ apmixedsys: apmixedsys@10209000 {
+ compatible = "mediatek,mt8135-apmixedsys";
+ reg = <0 0x10209000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
gic: interrupt-controller@10211000 {
compatible = "arm,cortex-a15-gic";
interrupt-controller;
--
1.8.1.1.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135.
[not found] ` <1417174490-6845-3-git-send-email-jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
@ 2014-11-28 12:06 ` Mark Rutland
2014-12-01 3:41 ` james liao
0 siblings, 1 reply; 7+ messages in thread
From: Mark Rutland @ 2014-11-28 12:06 UTC (permalink / raw)
Cc: Rob Herring, Matthias Brugger, Mike Turquette,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
srv_jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
Sascha Hauer, eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
Pawel Moll, Ian Campbell, Kumar Gala, Russell King,
Catalin Marinas, Vladimir Murzin, Ashwin Chaugule, Joe.C,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Fri, Nov 28, 2014 at 11:34:48AM +0000, James Liao wrote:
> This patch adds clock gates support for Mediatek SoCs, and adds clocks of
> INFRA sys and PERI sys for MT8135.
>
> Signed-off-by: James Liao <jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
> drivers/clk/mediatek/Makefile | 2 +-
> drivers/clk/mediatek/clk-gate.c | 151 +++++++++++++++++++
> drivers/clk/mediatek/clk-gate.h | 48 ++++++
> drivers/clk/mediatek/clk-mt8135.c | 260 +++++++++++++++++++++++++++++++++
> include/dt-bindings/clock/mt8135-clk.h | 62 ++++++++
Please fold the include/dt-bindings changes into the DT documentation
patch, and put that earlier in the series.
Mark.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135.
2014-11-28 12:06 ` Mark Rutland
@ 2014-12-01 3:41 ` james liao
0 siblings, 0 replies; 7+ messages in thread
From: james liao @ 2014-12-01 3:41 UTC (permalink / raw)
To: Mark Rutland
Cc: Ashwin Chaugule, Vladimir Murzin, Mike Turquette, Pawel Moll,
srv_heupstream@mediatek.com, Ian Campbell, Catalin Marinas,
linux-kernel@vger.kernel.org, HenryC.Chen, Joe.C,
devicetree@vger.kernel.org, Rob Herring, Sascha Hauer, Kumar Gala,
Matthias Brugger, Russell King, eddie.huang@mediatek.com,
linux-arm-kernel@lists.infradead.org
Hi Mark,
On Fri, 2014-11-28 at 12:06 +0000, Mark Rutland wrote:
> On Fri, Nov 28, 2014 at 11:34:48AM +0000, James Liao wrote:
> > This patch adds clock gates support for Mediatek SoCs, and adds clocks of
> > INFRA sys and PERI sys for MT8135.
> >
>
> Please fold the include/dt-bindings changes into the DT documentation
> patch, and put that earlier in the series.
>
OK, I'll send a new patchset later with the following sequence:
1. include/dt-bindings + DT documention.
2. Basic clocks (PLLs + TOPCKGEN).
3. Basic clocks (INFRA + PERI)
4. Update device tree to enable clocks.
Best regards,
James
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-12-01 3:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-28 11:34 [PATCH 0/4] Add common clock support for Mediatek MT8135 James Liao
2014-11-28 11:34 ` [PATCH 1/4] clk: Add initial common clock support for Mediatek SoC MT8135 James Liao
2014-11-28 11:34 ` [PATCH 2/4] clk: Add INFRA and PERI clocks for Mediatek MT8135 James Liao
[not found] ` <1417174490-6845-3-git-send-email-jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2014-11-28 12:06 ` Mark Rutland
2014-12-01 3:41 ` james liao
2014-11-28 11:34 ` [PATCH 3/4] clk: dts: document Mediatek MT8135 clock binding James Liao
2014-11-28 11:34 ` [PATCH 4/4] dts: Enable clock support for Mediatek MT8135 James Liao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).