Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] clk: rockchip: add 533.25MHz to rk3399 clock rates table
From: Xing Zheng @ 2016-10-21  4:03 UTC (permalink / raw)
  To: linux-arm-kernel

We need to get the accurate 533.25MHz for the DP display.

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
---

 drivers/clk/rockchip/clk-rk3399.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 2c7cba7..a87cb49 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -93,6 +93,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
 	RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+	RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0),
 	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
-- 
2.7.4

^ permalink raw reply related

* [PATCH v14 4/4] arm: dts: mt2701: Use real clock for UARTs
From: Erin Lo @ 2016-10-21  3:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477020742-13889-1-git-send-email-erin.lo@mediatek.com>

We used to use a fixed rate clock for the UARTs. Now that we have clock
support we can associate the correct clocks to the UARTs and drop the
26MHz fixed rate UART clock.

Signed-off-by: Erin Lo <erin.lo@mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index c9a8dbf..7eab6f4 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -73,12 +73,6 @@
 		#clock-cells = <0>;
 	};
 
-	uart_clk: dummy26m {
-		compatible = "fixed-clock";
-		clock-frequency = <26000000>;
-		#clock-cells = <0>;
-	};
-
 	clk26m: oscillator at 0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -186,7 +180,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11002000 0 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -195,7 +190,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11003000 0 0x400>;
 		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -204,7 +200,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11004000 0 0x400>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -213,7 +210,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11005000 0 0x400>;
 		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 };
-- 
1.9.1

^ permalink raw reply related

* [PATCH v14 3/4] arm: dts: mt2701: Add clock controller device nodes
From: Erin Lo @ 2016-10-21  3:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477020742-13889-1-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao@mediatek.com>

Add clock controller nodes for MT2701, include topckgen, infracfg,
pericfg, apmixedsys, mmsys, imgsys, vdecsys, hifsys, ethsys and
bdpsys. This patch also add two oscillators that provide clocks for
MT2701.

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Erin Lo <erin.lo@mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 18596a2..c9a8dbf 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -12,8 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/clock/mt2701-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/mt2701-resets.h>
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -77,6 +79,20 @@
 		#clock-cells = <0>;
 	};
 
+	clk26m: oscillator at 0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	rtc32k: oscillator at 1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000>;
+		clock-output-names = "rtc32k";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupt-parent = <&gic>;
@@ -104,6 +120,26 @@
 		reg = <0 0x10005000 0 0x1000>;
 	};
 
+	topckgen: syscon at 10000000 {
+		compatible = "mediatek,mt2701-topckgen", "syscon";
+		reg = <0 0x10000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: syscon at 10001000 {
+		compatible = "mediatek,mt2701-infracfg", "syscon";
+		reg = <0 0x10001000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	pericfg: syscon at 10003000 {
+		compatible = "mediatek,mt2701-pericfg", "syscon";
+		reg = <0 0x10003000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
 	watchdog: watchdog at 10007000 {
 		compatible = "mediatek,mt2701-wdt",
 			     "mediatek,mt6589-wdt";
@@ -128,6 +164,12 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	apmixedsys: syscon at 10209000 {
+		compatible = "mediatek,mt2701-apmixedsys", "syscon";
+		reg = <0 0x10209000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	gic: interrupt-controller at 10211000 {
 		compatible = "arm,cortex-a7-gic";
 		interrupt-controller;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v14 2/4] reset: mediatek: Add MT2701 reset driver
From: Erin Lo @ 2016-10-21  3:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477020742-13889-1-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang@mediatek.com>

In infrasys and perifsys, there are many reset
control bits for kinds of modules. These bits are
used as actual reset controllers to be registered
into kernel's generic reset controller framework.

Signed-off-by: Shunli Wang <shunli.wang@mediatek.com>
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Erin Lo <erin.lo@mediatek.com>
Tested-by: John Crispin <blogic@openwrt.org>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/clk/mediatek/clk-mt2701-hif.c |  6 +++++-
 drivers/clk/mediatek/clk-mt2701.c     | 12 ++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
index e2b0039..4c0688f 100644
--- a/drivers/clk/mediatek/clk-mt2701-hif.c
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -53,8 +53,12 @@ static int mtk_hifsys_init(struct platform_device *pdev)
 						clk_data);
 
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		return r;
 
-	return r;
+	mtk_register_reset_controller(node, 1, 0x34);
+
+	return 0;
 }
 
 static const struct of_device_id of_match_clk_mt2701_hif[] = {
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
index c225256..b2148b6 100644
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -802,8 +802,12 @@ static int mtk_infrasys_init(struct platform_device *pdev)
 						infra_clk_data);
 
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		return r;
 
-	return r;
+	mtk_register_reset_controller(node, 2, 0x30);
+
+	return 0;
 }
 
 static const struct mtk_gate_regs peri0_cg_regs = {
@@ -920,8 +924,12 @@ static int mtk_pericfg_init(struct platform_device *pdev)
 			&lock, clk_data);
 
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		return r;
 
-	return r;
+	mtk_register_reset_controller(node, 2, 0x0);
+
+	return 0;
 }
 
 #define MT8590_PLL_FMAX		(2000 * MHZ)
-- 
1.9.1

^ permalink raw reply related

* [PATCH v14 1/4] clk: mediatek: Add MT2701 clock support
From: Erin Lo @ 2016-10-21  3:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477020742-13889-1-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang@mediatek.com>

Add MT2701 clock support, include topckgen, apmixedsys,
infracfg, pericfg and subsystem clocks.

Signed-off-by: Shunli Wang <shunli.wang@mediatek.com>
Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Erin Lo <erin.lo@mediatek.com>
Tested-by: John Crispin <blogic@openwrt.org>
---
 drivers/clk/mediatek/Kconfig           |   43 ++
 drivers/clk/mediatek/Makefile          |    7 +
 drivers/clk/mediatek/clk-gate.c        |   52 ++
 drivers/clk/mediatek/clk-gate.h        |    2 +
 drivers/clk/mediatek/clk-mt2701-bdp.c  |  148 +++++
 drivers/clk/mediatek/clk-mt2701-eth.c  |   90 +++
 drivers/clk/mediatek/clk-mt2701-hif.c  |   87 +++
 drivers/clk/mediatek/clk-mt2701-img.c  |   90 +++
 drivers/clk/mediatek/clk-mt2701-mm.c   |  133 ++++
 drivers/clk/mediatek/clk-mt2701-vdec.c |  101 +++
 drivers/clk/mediatek/clk-mt2701.c      | 1046 ++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c         |   40 ++
 drivers/clk/mediatek/clk-mtk.h         |   41 +-
 drivers/clk/mediatek/clk-pll.c         |    1 +
 14 files changed, 1876 insertions(+), 5 deletions(-)
 create mode 100644 drivers/clk/mediatek/clk-mt2701-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-eth.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-hif.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 380c372..7202db5 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -6,6 +6,49 @@ config COMMON_CLK_MEDIATEK
 	---help---
 	  Mediatek SoCs' clock support.
 
+config COMMON_CLK_MT2701
+	bool "Clock driver for Mediatek MT2701"
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	---help---
+	  This driver supports Mediatek MT2701 basic clocks.
+
+config COMMON_CLK_MT2701_MMSYS
+	bool "Clock driver for Mediatek MT2701 mmsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 mmsys clocks.
+
+config COMMON_CLK_MT2701_IMGSYS
+	bool "Clock driver for Mediatek MT2701 imgsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 imgsys clocks.
+
+config COMMON_CLK_MT2701_VDECSYS
+	bool "Clock driver for Mediatek MT2701 vdecsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 vdecsys clocks.
+
+config COMMON_CLK_MT2701_HIFSYS
+	bool "Clock driver for Mediatek MT2701 hifsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 hifsys clocks.
+
+config COMMON_CLK_MT2701_ETHSYS
+	bool "Clock driver for Mediatek MT2701 ethsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 ethsys clocks.
+
+config COMMON_CLK_MT2701_BDPSYS
+	bool "Clock driver for Mediatek MT2701 bdpsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 bdpsys clocks.
+
 config COMMON_CLK_MT8135
 	bool "Clock driver for Mediatek MT8135"
 	select COMMON_CLK_MEDIATEK
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 32e7222..19ae7ef 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,11 @@
 obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
+obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
+obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
+obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index d8787bf..934bf0e 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
 	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
 }
 
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
 static int mtk_cg_enable(struct clk_hw *hw)
 {
 	mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
 	mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+}
+
 const struct clk_ops mtk_clk_gate_ops_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable,
@@ -97,6 +137,18 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
 	.disable	= mtk_cg_disable_inv,
 };
 
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable_no_setclr,
+	.disable	= mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv_no_setclr,
+	.disable	= mtk_cg_disable_inv_no_setclr,
+};
+
 struct clk *mtk_clk_register_gate(
 		const char *name,
 		const char *parent_name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index b182160..72ef89b 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
 
 extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
 
 struct clk *mtk_clk_register_gate(
 		const char *name,
diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
new file mode 100644
index 0000000..dbf6ab2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs bdp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_BDP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate bdp_clks[] = {
+	GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+	GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+	GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+	GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+	GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+	GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+	GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+	GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+	GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+	GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+	GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+	GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+	GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+	GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+	GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+	GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+	GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+	GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+	GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+	GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+	GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+	GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+	GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+	GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+	GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+	GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+	GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+	GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+	GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+	GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+	GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+	GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+	GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+	GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+	GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+	GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+	GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+	GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+	GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+	GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+	GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+	GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static int mtk_bdpsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_bdp[] = {
+	{ .compatible = "mediatek,mt2701-bdpsys", },
+	{}
+};
+
+static int clk_mt2701_bdp_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_bdpsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_bdp_drv = {
+	.probe = clk_mt2701_bdp_probe,
+	.driver = {
+		.name = "clk-mt2701-bdp",
+		.of_match_table = of_match_clk_mt2701_bdp,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_bdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
new file mode 100644
index 0000000..b2a71a4
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-eth.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &eth_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate eth_clks[] = {
+	GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+	GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+	GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+	GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+	GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+	GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+	GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+	GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static int mtk_ethsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+	mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_eth[] = {
+	{ .compatible = "mediatek,mt2701-ethsys", },
+	{}
+};
+
+static int clk_mt2701_eth_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_ethsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_eth_drv = {
+	.probe = clk_mt2701_eth_probe,
+	.driver = {
+		.name = "clk-mt2701-eth",
+		.of_match_table = of_match_clk_mt2701_eth,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_eth_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
new file mode 100644
index 0000000..e2b0039
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs hif_cg_regs = {
+	.sta_ofs = 0x0030,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &hif_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate hif_clks[] = {
+	GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+	GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+	GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+	GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+	GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static int mtk_hifsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+	mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_hif[] = {
+	{ .compatible = "mediatek,mt2701-hifsys", },
+	{}
+};
+
+static int clk_mt2701_hif_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_hifsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_hif_drv = {
+	.probe = clk_mt2701_hif_probe,
+	.driver = {
+		.name = "clk-mt2701-hif",
+		.of_match_table = of_match_clk_mt2701_hif,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_hif_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
new file mode 100644
index 0000000..c8a7a73
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-img.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+	.set_ofs = 0x0004,
+	.clr_ofs = 0x0008,
+	.sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &img_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate img_clks[] = {
+	GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+	GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+	GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+	GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+	GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+	GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static int mtk_imgsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_img[] = {
+	{ .compatible = "mediatek,mt2701-imgsys", },
+	{}
+};
+
+static int clk_mt2701_img_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_imgsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_img_drv = {
+	.probe = clk_mt2701_img_probe,
+	.driver = {
+		.name = "clk-mt2701-img",
+		.of_match_table = of_match_clk_mt2701_img,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
new file mode 100644
index 0000000..a63ea2f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-mm.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs disp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_DISP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate mm_clks[] = {
+	GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+	GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+	GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+	GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+	GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+	GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+	GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+	GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+	GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+	GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+	GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+	GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+	GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+	GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+	GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+	GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+	GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+	GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+	GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+	GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+	GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+	GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+	GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static int mtk_mmsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_mm[] = {
+	{ .compatible = "mediatek,mt2701-mmsys", },
+	{}
+};
+
+static int clk_mt2701_mm_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_mmsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_mm_drv = {
+	.probe = clk_mt2701_mm_probe,
+	.driver = {
+		.name = "clk-mt2701-mm",
+		.of_match_table = of_match_clk_mt2701_mm,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
new file mode 100644
index 0000000..405e25d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+	.set_ofs = 0x0000,
+	.clr_ofs = 0x0004,
+	.sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x000c,
+	.sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate vdec_clks[] = {
+	GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+	GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static int mtk_vdecsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701_vdec[] = {
+	{ .compatible = "mediatek,mt2701-vdecsys", },
+	{}
+};
+
+static int clk_mt2701_vdec_probe(struct platform_device *pdev)
+{
+	int r;
+
+	r = mtk_vdecsys_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_vdec_drv = {
+	.probe = clk_mt2701_vdec_probe,
+	.driver = {
+		.name = "clk-mt2701-vdec",
+		.of_match_table = of_match_clk_mt2701_vdec,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
new file mode 100644
index 0000000..c225256
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -0,0 +1,1046 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE		0
+
+static DEFINE_SPINLOCK(lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+		108 * MHZ),
+	FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+		400 * MHZ),
+	FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+		295750000),
+	FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m",
+		300 * MHZ),
+	FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+		416 * MHZ),
+	FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+		143 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+		DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+	FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+	FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+	FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+	FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+	FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+	FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+	FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+	FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+	FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+	FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+	FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+	FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+	FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+	FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+	FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+	FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+	FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+	FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+	FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+	FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+	FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+};
+
+static const char * const axi_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"mmpll_d2",
+	"dmpll_d2"
+};
+
+static const char * const mem_parents[] = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const pwm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4",
+};
+
+static const char * const vdec_parents[] = {
+	"clk26m",
+	"vdecpll_ck",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"vencpll_ck",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const mfg_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_x2_ck",
+	"msdcpll_ck",
+	"clk26m",
+	"syspll_d3",
+	"univpll_d3",
+	"univpll1_d2"
+};
+
+static const char * const camtg_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const uart_parents[] = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const msdc30_parents[] = {
+	"clk26m",
+	"msdcpll_d2",
+	"syspll2_d2",
+	"syspll1_d4",
+	"univpll1_d4",
+	"univpll2_d4"
+};
+
+static const char * const audio_parents[] = {
+	"clk26m",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll2_d4",
+	"syspll4_d2",
+	"syspll3_d4",
+	"syspll2_d8",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const scp_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const dpi0_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] = {
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const tve_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] = {
+	"clk26m",
+	"hdmipll_ck",
+	"hdmipll_d2",
+	"hdmipll_d3"
+};
+
+static const char * const apll_parents[] = {
+	"clk26m",
+	"audpll",
+	"audpll_d4",
+	"audpll_d8",
+	"audpll_d16",
+	"audpll_d24",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const rtc_parents[] = {
+	"32k_internal",
+	"32k_external",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] = {
+	"clk26m",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll3_d2",
+	"syspll2_d4",
+	"univpll3_d4",
+	"syspll4_d4",
+	"clk26m"
+};
+
+static const char * const emmc_hclk_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll1_d4",
+	"syspll2_d2"
+};
+
+static const char * const flash_parents[] = {
+	"clk26m_d8",
+	"clk26m",
+	"syspll2_d8",
+	"syspll3_d4",
+	"univpll3_d4",
+	"syspll4_d2",
+	"syspll2_d4",
+	"univpll2_d4"
+};
+
+static const char * const di_parents[] = {
+	"clk26m",
+	"tvd2pll_ck",
+	"tvd2pll_d2",
+	"clk26m"
+};
+
+static const char * const nr_osd_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] = {
+	"clk26m",
+	"syspll_d3",
+	"clk26m",
+	"syspll1_d16",
+	"syspll4_d2",
+	"syspll1_d4",
+	"vencpll_ck",
+	"clk26m"
+};
+
+static const char * const intdir_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"syspll_d2",
+	"univpll_d2"
+};
+
+static const char * const asm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll2_d2",
+	"syspll_d5"
+};
+
+static const char * const ms_card_parents[] = {
+	"clk26m",
+	"univpll3_d8",
+	"syspll4_d4"
+};
+
+static const char * const ethif_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"dmpll_ck",
+	"dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] = {
+	"clk26m",
+	"univpll_d52"
+};
+
+static const char * const cmsys_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"syspll2_d2",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll2_d4",
+	"syspll1_d8",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const clk_8bdac_parents[] = {
+	"32k_internal",
+	"8bdac_ck",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const aud2dvd_parents[] = {
+	"a1sys_hp_ck",
+	"a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll_d108",
+	"univpll2_d8",
+	"univpll2_d16",
+	"univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] = {
+	"clk26m",
+	"aud1pll_98m_ck",
+	"aud2pll_90m_ck",
+	"hadds2pll_98m",
+	"audio_ext1_ck",
+	"audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] = {
+	"aud_mux1_sel",
+	"aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] = {
+	"clk26m",
+	"armpll",
+	"mainpll",
+	"mmpll"
+};
+
+static const struct mtk_composite top_muxes[] = {
+	MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0040, 0, 3, 7, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+		0x0040, 8, 1, 15, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel",
+		ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+		0x0040, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+		0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+		0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+		0x0050, 16, 3, 23),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+		0x0050, 24, 3, 31),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+		0x0060, 0, 1, 7),
+
+	MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+		0x0060, 8, 3, 15),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+		0x0060, 16, 2, 23),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+		0x0060, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+		0x0070, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+		0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+		0x0070, 16, 1, 23),
+	MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0070, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+		0x0080, 0, 4, 7),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+		0x0080, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+		0x0080, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+		0x0080, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+		0x0090, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+		0x0090, 8, 2, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+		0x0090, 16, 3, 23),
+
+	MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+		0x00A0, 0, 2, 7, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+		0x00A0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+		0x00A0, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+		0x00B0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+		0x00B0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+		0x00B0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+		0x00B0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+		hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+		0x00C0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+		0x00C0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+		0x00C0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+		0x00D0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+		0x00D0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+		0x00D0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+		0x00E0, 0, 1, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+		0x00E0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+		0x00E0, 16, 4, 23),
+
+	MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+		0x00E0, 24, 3, 31),
+	MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+		0x00F0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+		0x00F0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+		0x00F0, 16, 1, 23),
+
+	MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+		0x0100, 0, 3),
+
+	MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+		0x012c, 0, 3),
+	MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+		0x012c, 3, 3),
+	MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+		0x012c, 6, 3),
+	MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+		0x012c, 15, 1, 23),
+	MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+		0x012c, 16, 1, 24),
+	MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+		0x012c, 17, 1, 25),
+	MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+		0x012c, 18, 1, 26),
+	MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+		0x012c, 19, 1, 27),
+	MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+		0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+	DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+		0x0120, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+		0x0120, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+		0x0120, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+		0x0120, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+		0x0124, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+		0x0124, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+		0x0124, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+		0x0124, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+		0x0128, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+		0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs = {
+	.sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &top_aud_cg_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate top_clks[] = {
+	GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+		21),
+	GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+		22),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+		23),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+		24),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+		25),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+		26),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+		27),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+		28),
+};
+
+void __iomem *devm_of_iomap(struct device *dev, int index)
+{
+	struct resource res;
+
+	if (!dev)
+		return NULL;
+
+	if (of_address_to_resource(dev->of_node, index, &res))
+		return NULL;
+
+	return devm_ioremap(dev, res.start, resource_size(&res));
+}
+
+static int mtk_topckgen_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	base = devm_of_iomap(&pdev->dev, 0);
+	if (!base)
+		return -ENOMEM;
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+								clk_data);
+
+	mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+								clk_data);
+
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+				base, &lock, clk_data);
+
+	mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+				base, &lock, clk_data);
+
+	mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &infra_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate infra_clks[] = {
+	GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+	GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+	GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+	GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+	GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+	FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void mtk_infrasys_init_early(struct device_node *node)
+{
+	int r, i;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+		for (i = 0; i < CLK_INFRA_NR; i++)
+			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+	}
+
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt2701-infracfg",
+			mtk_infrasys_init_early);
+
+static int mtk_infrasys_init(struct platform_device *pdev)
+{
+	int r, i;
+	struct device_node *node = pdev->dev.of_node;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+	} else {
+		for (i = 0; i < CLK_INFRA_NR; i++) {
+			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+				infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+		}
+	}
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						infra_clk_data);
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+
+	return r;
+}
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate peri_clks[] = {
+	GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+	GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+	GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+	GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+	GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+	GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+	GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+	GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+	GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+	GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+	GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+	GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+		0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+		0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+		0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+		0x40c, 3, 1),
+};
+
+static int mtk_pericfg_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	base = devm_of_iomap(&pdev->dev, 0);
+	if (!base)
+		return -ENOMEM;
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+						clk_data);
+
+	mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+			&lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+#define MT8590_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8590_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+			_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8590_RST_BAR,			\
+		.fmax = MT8590_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001,
+			PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+		  HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+		  HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+				21, 0x230, 4, 0x0, 0x234, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+				21, 0x240, 4, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+				21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+				31, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+				31, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+				31, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+				31, 0x2a0, 4, 0x0, 0x2a4, 0),
+	PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+				31, 0x2b0, 4, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+				31, 0x2c0, 4, 0x0, 0x2c4, 0),
+	PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+				21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static int mtk_apmixedsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+	if (!clk_data)
+		return -ENOMEM;
+
+	mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+								clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2701[] = {
+	{
+		.compatible = "mediatek,mt2701-topckgen",
+		.data = mtk_topckgen_init,
+	}, {
+		.compatible = "mediatek,mt2701-infracfg",
+		.data = mtk_infrasys_init,
+	}, {
+		.compatible = "mediatek,mt2701-pericfg",
+		.data = mtk_pericfg_init,
+	}, {
+		.compatible = "mediatek,mt2701-apmixedsys",
+		.data = mtk_apmixedsys_init,
+	}, {
+		/* sentinel */
+	}
+};
+
+static int clk_mt2701_probe(struct platform_device *pdev)
+{
+	int (*clk_init)(struct platform_device *);
+	int r;
+
+	clk_init = of_device_get_match_data(&pdev->dev);
+	if (!clk_init)
+		return -EINVAL;
+
+	r = clk_init(pdev);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+	}
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_drv = {
+	.probe = clk_mt2701_probe,
+	.driver = {
+		.name = "clk-mt2701",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt2701,
+	},
+};
+
+static int __init clk_mt2701_init(void)
+{
+	return platform_driver_register(&clk_mt2701_drv);
+}
+
+arch_initcall(clk_mt2701_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index bb30f70..0541df7 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_clk *rc = &clks[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
+			continue;
+
 		clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
 					      rc->rate);
 
@@ -81,6 +84,9 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_factor *ff = &clks[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
+			continue;
+
 		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
 				CLK_SET_RATE_PARENT, ff->mult, ff->div);
 
@@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device_node *node,
 	for (i = 0; i < num; i++) {
 		const struct mtk_gate *gate = &clks[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
+			continue;
+
 		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
 				regmap,
 				gate->regs->set_ofs,
@@ -232,6 +241,9 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
 	for (i = 0; i < num; i++) {
 		const struct mtk_composite *mc = &mcs[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
+			continue;
+
 		clk = mtk_clk_register_composite(mc, base, lock);
 
 		if (IS_ERR(clk)) {
@@ -244,3 +256,31 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
 			clk_data->clks[mc->id] = clk;
 	}
 }
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i <  num; i++) {
+		const struct mtk_clk_divider *mcd = &mcds[i];
+
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
+			continue;
+
+		clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+			mcd->flags, base +  mcd->div_reg, mcd->div_shift,
+			mcd->div_width, mcd->clk_divider_flags, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+				mcd->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mcd->id] = clk;
+	}
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 9f24fcf..f5d6b70 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -87,7 +87,8 @@ struct mtk_composite {
  * In case the rate change propagation to parent clocks is undesirable,
  * this macro allows to specify the clock flags manually.
  */
-#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) {	\
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+			_gate, _flags) {				\
 		.id = _id,						\
 		.name = _name,						\
 		.mux_reg = _reg,					\
@@ -106,7 +107,8 @@ struct mtk_composite {
  * parent clock by default.
  */
 #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
-	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
+	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+		_gate, CLK_SET_RATE_PARENT)
 
 #define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
 		.id = _id,						\
@@ -121,7 +123,8 @@ struct mtk_composite {
 		.flags = CLK_SET_RATE_PARENT,				\
 	}
 
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,	\
+					_div_width, _div_shift) {	\
 		.id = _id,						\
 		.parent = _parent,					\
 		.name = _name,						\
@@ -156,12 +159,40 @@ struct mtk_gate {
 	const struct clk_ops *ops;
 };
 
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
-		int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+			const struct mtk_gate *clks, int num,
+			struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+	int id;
+	const char *name;
+	const char *parent_name;
+	unsigned long flags;
+
+	u32 div_reg;
+	unsigned char div_shift;
+	unsigned char div_width;
+	unsigned char clk_divider_flags;
+	const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.div_reg = _reg,				\
+		.div_shift = _shift,				\
+		.div_width = _width,				\
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data);
 
 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR	BIT(0)
+#define PLL_AO		BIT(1)
 
 struct mtk_pll_div_table {
 	u32 div;
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 0c2deac..a409142 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
 	pll->data = data;
 
 	init.name = data->name;
+	init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
 	init.ops = &mtk_pll_ops;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v14 0/4] Add clock support for Mediatek MT2701
From: Erin Lo @ 2016-10-21  3:32 UTC (permalink / raw)
  To: linux-arm-kernel

This series is based on v4.9-rc1, add clock and reset controller support
for Mediatek MT2701.

changes since v13:
- Rebase to v4.9-rc1.

changes since v12:
- Rebase to clk-next.
- Use CLK_OF_DECLARE_DRIVER() instead of CLK_OF_DECLARE().
- Use dev_* and devm_* APIs instead of pr_* and ioremap().
- Refine init functions. Share error messages in common probe().
- Fix null pointer checking for clk_data.

changes since v11:
- Rebase to clk-next.
- Return error code from probe() if clock registration fail.

changes since v10:
- Remove COMMON_CLK dependency from clk/mediatek/Kconfig.

changes since v9:
- Rebase to v4.8-rc1.
- Drop a fix patch of parent clock initial state. It will be replaced by a new
  patch from Mike/Stephen.
- Replace clk.h with clk-provider.h.
- Correct register settings of clocks.

changes since v8:
- Rebase to v4.7-rc1.
- Include mt2701-resets.h in mt2701.dtsi.
- Remove an unused property from apmixedsys DT node.

changes since v7:
- Rebase to clk-next.
- Implement subsystem clocks in seperated files.
- Replace critical clock enabling with CLK_IS_CRITICAL flag.
- Reduce most clock registrations in CLK_OF_DECLARE().
- Remove __init and __initconst from most init fucntions and data,
  and replace driver registration with platform_driver_register().
- Replace some common function or variable names with unique names.
- Use real clock for UARTs.

changes since v6:
- Rebase to v4.6-rc1.
- Register subsystem clocks in probe() instead of CLK_OF_DECLARE().
- Add clocks that referred by subsystem clocks.
- Fix clk_data size of apmixedsys.
- Add config options for each subsystem clock provider.

changes since v5:
- Rebase to v4.5-rc1 and [1].
- Enable critical clocks for MT2701
- Refine dt-binding documents, add reset controller support for hifsys.

changes since v4:
- Rebase to v4.5-rc1.
- Remove CLK_SET_RATE_PARENT from divider flags.
- Add img_jpgdec_smi clock.
- Move clk/mediatek/Kconfig into menu section in clk/Kconfig.

changes since v3:
- Change the parent of mm_mdp_bls_26m from clk26m to pwm_sel.

changes since v2:
- Fix ethsys definition.
- Replace read-modify-write with regmap_update_bits() in clock operations.
- Move mt2701-resets.h to include/dt-bindings/reset/.
- Add hifsys reset patch from John Crispin.

changes since v1:
- Document MT2701 compatible strings.

[1] https://patchwork.kernel.org/patch/8147901/

Erin Lo (1):
  arm: dts: mt2701: Use real clock for UARTs

James Liao (1):
  arm: dts: mt2701: Add clock controller device nodes

Shunli Wang (2):
  clk: mediatek: Add MT2701 clock support
  reset: mediatek: Add MT2701 reset driver

 arch/arm/boot/dts/mt2701.dtsi          |   50 +-
 drivers/clk/mediatek/Kconfig           |   43 ++
 drivers/clk/mediatek/Makefile          |    7 +
 drivers/clk/mediatek/clk-gate.c        |   52 ++
 drivers/clk/mediatek/clk-gate.h        |    2 +
 drivers/clk/mediatek/clk-mt2701-bdp.c  |  148 +++++
 drivers/clk/mediatek/clk-mt2701-eth.c  |   90 +++
 drivers/clk/mediatek/clk-mt2701-hif.c  |   91 +++
 drivers/clk/mediatek/clk-mt2701-img.c  |   90 +++
 drivers/clk/mediatek/clk-mt2701-mm.c   |  133 ++++
 drivers/clk/mediatek/clk-mt2701-vdec.c |  101 +++
 drivers/clk/mediatek/clk-mt2701.c      | 1054 ++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c         |   40 ++
 drivers/clk/mediatek/clk-mtk.h         |   41 +-
 drivers/clk/mediatek/clk-pll.c         |    1 +
 15 files changed, 1933 insertions(+), 10 deletions(-)
 create mode 100644 drivers/clk/mediatek/clk-mt2701-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-eth.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-hif.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701.c

--
1.9.1

^ permalink raw reply

* [PATCH v2 0/8] crypto: ARM/arm64 - big endian fixes
From: Herbert Xu @ 2016-10-21  3:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476209720-21114-1-git-send-email-ard.biesheuvel@linaro.org>

On Tue, Oct 11, 2016 at 07:15:12PM +0100, Ard Biesheuvel wrote:
> As it turns out, none of the accelerated crypto routines under arch/arm64/crypto
> currently work, or have ever worked correctly when built for big endian. So this
> series fixes all of them. This v2 now includes a similar fix for 32-bit ARM as
> well, and an additional fix for XTS which escaped my attention before.
> 
> Each of these patches carries a fixes tag, and could be backported to stable.
> However, for patches #1 and #5, the fixes tag denotes the oldest commit that the
> fix is compatible with, not the patch that introduced the algorithm. This is due
> to the fact that the key schedules are incompatible between generic AES and the
> arm64 Crypto Extensions implementation (but only when building for big endian)
> This is not a problem in practice, but it does mean that the AES-CCM and AES in
> EBC/CBC/CTR/XTS mode implementations before v3.19 require a different fix, i.e.,
> one that is compatible with the generic AES key schedule generation code (which
> it currently no longer uses)
> 
> In any case, please apply with cc to stable.
> 
> Ard Biesheuvel (8):
>   crypto: arm64/aes-ce - fix for big endian
>   crypto: arm64/ghash-ce - fix for big endian
>   crypto: arm64/sha1-ce - fix for big endian
>   crypto: arm64/sha2-ce - fix for big endian
>   crypto: arm64/aes-ccm-ce: fix for big endian
>   crypto: arm64/aes-neon - fix for big endian
>   crypto: arm64/aes-xts-ce: fix for big endian
>   crypto: arm/aes-ce - fix for big endian
> 
>  arch/arm/crypto/aes-ce-glue.c       |  5 ++
>  arch/arm64/crypto/aes-ce-ccm-core.S | 53 ++++++++++----------
>  arch/arm64/crypto/aes-ce-cipher.c   | 25 +++++----
>  arch/arm64/crypto/aes-ce.S          |  1 +
>  arch/arm64/crypto/aes-modes.S       |  3 +-
>  arch/arm64/crypto/aes-neon.S        | 25 +++++----
>  arch/arm64/crypto/ghash-ce-core.S   |  6 +--
>  arch/arm64/crypto/sha1-ce-core.S    |  4 +-
>  arch/arm64/crypto/sha2-ce-core.S    |  4 +-
>  9 files changed, 72 insertions(+), 54 deletions(-)

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] drm/sun4i: Add a few formats
From: Chen-Yu Tsai @ 2016-10-21  3:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161018084614.2443-1-maxime.ripard@free-electrons.com>

On Tue, Oct 18, 2016 at 4:46 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The planes can do more than what was previously exposed. Add support for
> them.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_backend.c | 20 ++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun4i_layer.c   |  6 ++++++
>  2 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
> index afb7ddf660ef..b184a476a480 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
> @@ -96,6 +96,22 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
>                 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
>                 break;
>
> +       case DRM_FORMAT_ARGB4444:
> +               *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444;
> +               break;
> +
> +       case DRM_FORMAT_ARGB1555:
> +               *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555;
> +               break;
> +
> +       case DRM_FORMAT_RGBA5551:
> +               *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551;
> +               break;
> +
> +       case DRM_FORMAT_RGBA4444:
> +               *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444;

The A20 manual only lists ARGB4444, not RGBA4444. There might be
some discrepancy here. We can deal with them

Also there are some more formats missing from the list, could you
add them as well?

> +               break;
> +
>         case DRM_FORMAT_XRGB8888:
>                 *mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888;
>                 break;
> @@ -104,6 +120,10 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
>                 *mode = SUN4I_BACKEND_LAY_FBFMT_RGB888;
>                 break;
>
> +       case DRM_FORMAT_RGB565:
> +               *mode = SUN4I_BACKEND_LAY_FBFMT_RGB565;
> +               break;
> +
>         default:
>                 return -EINVAL;
>         }
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> index f0035bf5efea..5d53c977bca5 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -73,12 +73,18 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
>  static const uint32_t sun4i_backend_layer_formats_primary[] = {
>         DRM_FORMAT_ARGB8888,
>         DRM_FORMAT_RGB888,
> +       DRM_FORMAT_RGB565,
>         DRM_FORMAT_XRGB8888,
>  };
>
>  static const uint32_t sun4i_backend_layer_formats_overlay[] = {
>         DRM_FORMAT_ARGB8888,
> +       DRM_FORMAT_ARGB4444,
> +       DRM_FORMAT_ARGB1555,
> +       DRM_FORMAT_RGBA5551,
> +       DRM_FORMAT_RGBA4444,
>         DRM_FORMAT_RGB888,
> +       DRM_FORMAT_RGB565,
>         DRM_FORMAT_XRGB8888,

Could you explain in the commit log why these 2 aren't the same?

Thanks
ChenYu

>  };
>
> --
> 2.9.3
>

^ permalink raw reply

* [PATCH v4 0/2] Improve DMA chaining for ahash requests
From: Herbert Xu @ 2016-10-21  3:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161005075633.12711-1-romain.perier@free-electrons.com>

On Wed, Oct 05, 2016 at 09:56:31AM +0200, Romain Perier wrote:
> This series contain performance improvement regarding ahash requests.
> So far, ahash requests were systematically not chained at the DMA level.
> However, in some case, like this is the case by using IPSec, some ahash
> requests can be processed directly by the engine, and don't have
> intermediaire partial update states.
> 
> This series firstly re-work the way outer IVs are copied from the SRAM
> into the dma pool. To do so, we introduce a common dma pool for all type
> of requests that contains outer results (like IV or digest). Then, for
> ahash requests that can be processed directly by the engine, outer
> results are copied from the SRAM into the common dma pool. These requests
> are then allowed to be chained at the DMA level.
> 
> 
> Benchmarking results with iperf throught IPSec
> ==============================================
> 		ESP			AH
> 
> Before		343 Mbits/s		492 Mbits/s
> After		422 Mbits/s		577 Mbits/s
> Improvement	+23%			+17%
> 
> Romain Perier (2):
>   crypto: marvell - Use an unique pool to copy results of requests
>   crypto: marvell - Don't break chain for computable last ahash requests
> 
>  drivers/crypto/marvell/cesa.c   |  4 ---
>  drivers/crypto/marvell/cesa.h   |  5 ++--
>  drivers/crypto/marvell/cipher.c |  8 +++--
>  drivers/crypto/marvell/hash.c   | 65 +++++++++++++++++++++++++++++++----------
>  drivers/crypto/marvell/tdma.c   | 28 +++++++++---------
>  5 files changed, 70 insertions(+), 40 deletions(-)

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH v2 1/1] crypto: atmel-aes: add support to the XTS mode
From: Herbert Xu @ 2016-10-21  3:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5ba0856b4ef013fa22c8d5ef00a7d97efe63d61f.1475497672.git.cyrille.pitchen@atmel.com>

On Mon, Oct 03, 2016 at 02:33:16PM +0200, Cyrille Pitchen wrote:
> This patch adds the xts(aes) algorithm, which is supported from
> hardware version 0x500 and above (sama5d2x).
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH v2] ARM: imx: gpc: Initialize all power domains
From: Shawn Guo @ 2016-10-21  3:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477013309-2808-1-git-send-email-festevam@gmail.com>

On Thu, Oct 20, 2016 at 11:28:29PM -0200, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> Since commit 0159ec670763dd ("PM / Domains: Verify the PM domain is present
> when adding a provider") the following regression is observed on imx6:
> 
> imx-gpc: probe of 20dc000.gpc failed with error -22
> 
> The imx-gpc driver probe failure causes several issues such as:
> 
> - When booting a kernel built with multi_v7_defconfig a kernel crash is
> seen.
> 
> - When booting a kernel built with imx_v6_v7_defconfig the Etnaviv GPU
> driver is not loaded due to the lack of power domains.
> 
> The gpc probe fails because of_genpd_add_provider_onecell() now checks
> if all the domains are initialized via pm_genpd_present() function
> and it fails because not all the power domains are initialized.

Thanks for the update.  Now we understand that this is a regression
caused by power domain core change.  But my question on why kernel
crashes with multi_v7_defconfig but not with imx_v6_v7_defconfig stays
unanswered.

Shawn

> 
> In order to fix this error, initialize all the power domains from
> imx_gpc_domains[], not only the imx6q_pu_domain.base one.
> 
> Reported-by: Olof's autobooter <build@lixom.net>
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
> ---
>  arch/arm/mach-imx/gpc.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 0df062d..d0463e9 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -430,7 +430,8 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
>  	if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
>  		return 0;
>  
> -	pm_genpd_init(&imx6q_pu_domain.base, NULL, false);
> +	for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
> +		pm_genpd_init(imx_gpc_domains[i], NULL, false);
>  	return of_genpd_add_provider_onecell(dev->of_node,
>  					     &imx_gpc_onecell_data);
>  
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/1] crypto: atmel-aes: fix compiler error when VERBOSE_DEBUG is defined
From: Herbert Xu @ 2016-10-21  3:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <605a4f64ee501aeaffbd43b7b45fd9b3d997bd7b.1475167206.git.cyrille.pitchen@atmel.com>

On Thu, Sep 29, 2016 at 06:46:57PM +0200, Cyrille Pitchen wrote:
> This patch fixes a compiler error when VERBOSE_DEBUG is defined. Indeed,
> in atmel_aes_write(), the 3rd argument of atmel_aes_reg_name() was
> missing.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
> Reported-by: Levent Demir <levent.demir@inria.fr>

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH 0/6] ARM: sun5i: chip: Misc improvements
From: Chen-Yu Tsai @ 2016-10-21  3:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.92d041a0a6fe40f1c8839cabb70247445eaffdfb.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:48 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> This is a bunch of patches I gathered for the CHIP, that enables a few
> things, like the WiFi regulators (and its associated power sequence), a few
> optional buses, etc.

FYI this series makes more sense if you mention the Pocket CHIP DT overlays.

ChenYu

>
> Let me know what you think,
> Maxime
>
> Antoine Tenart (1):
>   ARM: sun5i: chip: add a node for the w1 gpio controller
>
> Maxime Ripard (5):
>   ARM: sun5i: chip: Enable Wi-Fi SDIO chip
>   ARM: sun5i: Rename A10s pins
>   ARM: sun5i: Add SPI2 pins
>   ARM: sun5i: Add RGB 565 LCD pins
>   ARM: sun5i: chip: Add optional buses
>
>  arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts |  4 +-
>  arch/arm/boot/dts/sun5i-a10s.dtsi                |  4 +-
>  arch/arm/boot/dts/sun5i-r8-chip.dts              | 69 +++++++++++++++++-
>  arch/arm/boot/dts/sun5i.dtsi                     | 24 ++++++-
>  4 files changed, 97 insertions(+), 4 deletions(-)
>
> --
> git-series 0.8.10

^ permalink raw reply

* [PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
From: Sinan Kaya @ 2016-10-21  3:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161021024111.GA24336@localhost>

On 10/20/2016 7:41 PM, Bjorn Helgaas wrote:
> On Thu, Oct 20, 2016 at 01:01:04PM -0700, Sinan Kaya wrote:
>> On 10/19/2016 3:44 PM, Bjorn Helgaas wrote:
> 
>>>   - Maintain a mapping of (IRQ, penalty).  Initially all penalties are
>>>     zero.  This is for *all* IRQs, not just ISA ones.  This could be a
>>>     linked list, but the structure is not important as long as we can
>>>     add things dynamically.
>>
>> Dynamic allocation doesn't work due to early calls from x86 architecture.
>> This is the reason why we iterate the link objects.
> 
> Where exactly is this early penalization?  That seems to be the
> biggest problem.  Well, maybe the question of ACPI core parsing of
> _CRS/_PRS is a bigger structural problem, but the dynamic allocation
> thing at least seems solvable.
> 

http://marc.info/?l=linux-acpi&m=145580159209240&w=2


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH 2/6] ARM: sun5i: chip: add a node for the w1 gpio controller
From: Chen-Yu Tsai @ 2016-10-21  3:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a132bfdc6f4eae5540f1a3df4b68ba9bba9d0935.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:48 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> From: Antoine Tenart <antoine.tenart@free-electrons.com>
>
> The CHIP uses a 1-Wire bus to discover the DIPs. Enable the bus in the DT.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH V4 3/3] Revert "ACPI, PCI, IRQ: separate ISA penalty calculation"
From: Sinan Kaya @ 2016-10-21  2:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161021023109.GD31044@localhost>

On 10/20/2016 7:31 PM, Bjorn Helgaas wrote:
>> Let's try to simplify the code one more time to share code.
> I'm sort of OK with this, but it's not exactly a revert of the above
> (the commits you mention don't check "link->irq.initialized == 1".

I can split the initialized bit. If I remove it from this commit, it can
break the git bisect. That's why, I folded it into this review. I
briefly mentioned about it in the cover letter. It might not be quiet
clear.

> 
> Previously acpi_irq_penalty_init() looked at _PRS info ("possible"
> IRQs), but now we won't.  Maybe that's good; I dunno.  But it should
> be mentioned.

I'm directing all IRQs to  acpi_irq_pci_sharing_penalty function. 
acpi_irq_pci_sharing_penalty checks for the possible values here from
_PRS.

/*
 * penalize the IRQs PCI might use, but not as severely.
 */
for (i = 0; i < link->irq.possible_count; i++)
	if (link->irq.possible[i] == irq)
		penalty += PIRQ_PENALTY_PCI_POSSIBLE /
			link->irq.possible_count;

> 
> And I don't think it fixes a user-visible problem, so it doesn't need
> to be applied immediately.  I'm not sure this is worth doing by
> itself; maybe it should wait until we can do more cleanup and think
> about all these issues together?
> 

It does fix the PCI_USING penalty assignment. 

                if (link->irq.active && link->irq.active == irq)
                         penalty += PIRQ_PENALTY_PCI_USING;


If we drop this patch, then we need
[PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts

http://www.gossamer-threads.com/lists/linux/kernel/2547605

as somebody needs to increment the penalty with PCI_USING when IRQ is assigned
for a given ISA IRQ.

We might as well take [PATCH V4 1/3], [PATCH V4 2/3] and [PATCH V3 1/3]
for this regression.


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH 5/6] ARM: sun5i: Add RGB 565 LCD pins
From: Chen-Yu Tsai @ 2016-10-21  2:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <46596d638c314a117c55e6a9086669358b121f2b.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:49 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some boards use the LCD in RGB565. Enable the pin muxing option.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH v2] mmc: sunxi: Prevent against null dereference for vmmc
From: Chen-Yu Tsai @ 2016-10-21  2:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019133304.22915-1-maxime.ripard@free-electrons.com>

On Wed, Oct 19, 2016 at 9:33 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> VMMC is an optional regulator, which means that mmc_regulator_get_supply
> will only return an error in case of a deferred probe, but not when the
> regulator is not set in the DT.
>
> However, the sunxi driver assumes that VMMC is always there, and doesn't
> check the value of the regulator pointer before using it, which obviously
> leads to a (close to) null pointer dereference.
>
> Add proper checks to prevent that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH 1/6] ARM: sun5i: chip: Enable Wi-Fi SDIO chip
From: Chen-Yu Tsai @ 2016-10-21  2:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <468cbaad185a2bde92f1015a1c286f1e1ef55850.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:48 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The WiFi chip is powered through a GPIO and two regulators in parallel.
> Since that case is not supported yet, just set them as always on before we
> rework the regulator framework to deal with those.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH 3/6] ARM: sun5i: Rename A10s pins
From: Chen-Yu Tsai @ 2016-10-21  2:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <926093bcce58496cdb5cea55aaa65e958d36cb76.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:49 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The SPI2 pins on the sun5i PB bank are only available on the A10s. Rename
> the A10s only bank so that it doesn't confuse people on the other SoCs
> whose indexing would start at b.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH 6/6] ARM: sun5i: chip: Add optional buses
From: Chen-Yu Tsai @ 2016-10-21  2:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <54f17420e7532087c4c63db46a282bfc1678d39e.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:49 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The I2C1 and SPI2 buses are exposed on the CHIP headers, and are not
> explicitly dedicated to anything.
>
> Add them to the DTS with the muxing already set, but keep them disabled.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

The CHIP docs don't mention SPI2 though.

^ permalink raw reply

* [PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
From: Bjorn Helgaas @ 2016-10-21  2:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a418cf9d-5eeb-a588-6653-fd00e0c2693c@codeaurora.org>

On Thu, Oct 20, 2016 at 01:01:04PM -0700, Sinan Kaya wrote:
> On 10/19/2016 3:44 PM, Bjorn Helgaas wrote:

> >   - Maintain a mapping of (IRQ, penalty).  Initially all penalties are
> >     zero.  This is for *all* IRQs, not just ISA ones.  This could be a
> >     linked list, but the structure is not important as long as we can
> >     add things dynamically.
> 
> Dynamic allocation doesn't work due to early calls from x86 architecture.
> This is the reason why we iterate the link objects.

Where exactly is this early penalization?  That seems to be the
biggest problem.  Well, maybe the question of ACPI core parsing of
_CRS/_PRS is a bigger structural problem, but the dynamic allocation
thing at least seems solvable.

^ permalink raw reply

* [PATCH 4/6] ARM: sun5i: Add SPI2 pins
From: Chen-Yu Tsai @ 2016-10-21  2:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2a041979c4cc262535d204e6519d8a25fbbc3a94.1476704881.git-series.maxime.ripard@free-electrons.com>

On Mon, Oct 17, 2016 at 7:49 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> All the sun5i have the SPI2 pins exposed on the PE bank. Add them to the
> DT.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply

* [PATCH V4 3/3] Revert "ACPI, PCI, IRQ: separate ISA penalty calculation"
From: Bjorn Helgaas @ 2016-10-21  2:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476915664-27231-4-git-send-email-okaya@codeaurora.org>

On Wed, Oct 19, 2016 at 06:21:04PM -0400, Sinan Kaya wrote:
> This reverts commit f7eca374f000 ("ACPI,PCI,IRQ: separate ISA penalty
> calculation") and commit 487cf917ed0d ("revert "ACPI, PCI, IRQ: remove
> redundant code in acpi_irq_penalty_init()"").
> 
> Now that we understand the real issue (SCI and ISA penalty getting
> calculated before ACPI start), there is no need for special handling
> for ISA interrupts.
> 
> Let's try to simplify the code one more time to share code.

I'm sort of OK with this, but it's not exactly a revert of the above
(the commits you mention don't check "link->irq.initialized == 1".

Previously acpi_irq_penalty_init() looked at _PRS info ("possible"
IRQs), but now we won't.  Maybe that's good; I dunno.  But it should
be mentioned.

And I don't think it fixes a user-visible problem, so it doesn't need
to be applied immediately.  I'm not sure this is worth doing by
itself; maybe it should wait until we can do more cleanup and think
about all these issues together?

> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  arch/x86/pci/acpi.c         |  1 -
>  drivers/acpi/pci_link.c     | 44 +++++---------------------------------------
>  include/acpi/acpi_drivers.h |  1 -
>  3 files changed, 5 insertions(+), 41 deletions(-)
> 
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index 3cd6983..b2a4e2a 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -396,7 +396,6 @@ int __init pci_acpi_init(void)
>  		return -ENODEV;
>  
>  	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
> -	acpi_irq_penalty_init();
>  	pcibios_enable_irq = acpi_pci_irq_enable;
>  	pcibios_disable_irq = acpi_pci_irq_disable;
>  	x86_init.pci.init_irq = x86_init_noop;
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index 294b190..dd14d78 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -478,7 +478,8 @@ static int acpi_irq_pci_sharing_penalty(int irq)
>  		 * If a link is active, penalize its IRQ heavily
>  		 * so we try to choose a different IRQ.
>  		 */
> -		if (link->irq.active && link->irq.active == irq)
> +		if ((link->irq.active && link->irq.active == irq) &&
> +				(link->irq.initialized == 1))
>  			penalty += PIRQ_PENALTY_PCI_USING;
>  
>  		/*
> @@ -501,45 +502,10 @@ static int acpi_irq_get_penalty(int irq)
>  		penalty += sci_penalty;
>  
>  	if (irq < ACPI_MAX_ISA_IRQS)
> -		return penalty + acpi_isa_irq_penalty[irq];
> +		penalty += acpi_isa_irq_penalty[irq];
>  
> -	return penalty + acpi_irq_pci_sharing_penalty(irq);
> -}
> -
> -int __init acpi_irq_penalty_init(void)
> -{
> -	struct acpi_pci_link *link;
> -	int i;
> -
> -	/*
> -	 * Update penalties to facilitate IRQ balancing.
> -	 */
> -	list_for_each_entry(link, &acpi_link_list, list) {
> -
> -		/*
> -		 * reflect the possible and active irqs in the penalty table --
> -		 * useful for breaking ties.
> -		 */
> -		if (link->irq.possible_count) {
> -			int penalty =
> -			    PIRQ_PENALTY_PCI_POSSIBLE /
> -			    link->irq.possible_count;
> -
> -			for (i = 0; i < link->irq.possible_count; i++) {
> -				if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
> -					acpi_isa_irq_penalty[link->irq.
> -							 possible[i]] +=
> -					    penalty;
> -			}
> -
> -		} else if (link->irq.active &&
> -				(link->irq.active < ACPI_MAX_ISA_IRQS)) {
> -			acpi_isa_irq_penalty[link->irq.active] +=
> -			    PIRQ_PENALTY_PCI_POSSIBLE;
> -		}
> -	}
> -
> -	return 0;
> +	penalty += acpi_irq_pci_sharing_penalty(irq);
> +	return penalty;
>  }
>  
>  static int acpi_irq_balance = -1;	/* 0: static, 1: balance */
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 29c6912..797ae2e 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -78,7 +78,6 @@
>  
>  /* ACPI PCI Interrupt Link (pci_link.c) */
>  
> -int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>  			       int *polarity, char **name);
>  int acpi_pci_link_free_irq(acpi_handle handle);
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v5 23/23] phy: Add support for Qualcomm's USB HS phy
From: Peter Chen @ 2016-10-21  2:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <147700563857.2550.16732518381302920183@sboyd-linaro>

On Thu, Oct 20, 2016 at 04:20:38PM -0700, Stephen Boyd wrote:
> Quoting Stephen Boyd (2016-10-17 18:56:36)
> > +
> > +static int
> > +qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
> > +                             void *ptr)
> > +{
> > +       struct qcom_usb_hs_phy *uphy;
> > +       int is_host;
> > +       u8 addr;
> > +
> > +       uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
> > +       is_host = extcon_get_cable_state_(uphy->id_edev, EXTCON_USB_HOST);
> 
> Please don't apply this patch. This call now deadlocks on v4.9-rc1
> because of how extcon_get_cable_state_() now grabs a lock that is
> already held here when we're inside the notifier. It's not really
> required that we grab the lock in extcon there, but this has exposed a
> flaw in the logic anyway. We don't know if the id pin is going to toggle
> before or after this function is called, so we should really keep track
> of both vbus and id state in this driver and then do the same ulpi
> writes from two different notifiers for both vbus and id pin. We would
> be duplicating work sometimes, but that's pretty much the best solution
> I can come up with. Otherwise it's racy.
> 

Why you need to care id status? If EXTCON_USB event has happened, and
event is true, you can set, otherwise, it is clear operation, that's
to say you may not need have id extcon phandle, do you think so?

-- 

Best Regards,
Peter Chen

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox