From matthias.bgg at gmail.com  Thu Feb  5 09:05:43 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 5 Feb 2015 18:05:43 +0100
Subject: [PATCH v3] MediaTek PMIC support
In-Reply-To: <1423149938-14471-1-git-send-email-s.hauer@pengutronix.de>
References: <1423149938-14471-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <CABuKBeK-EuWqsCkZcGgLpuL2_FsZwd1T6PwkZB5+kudKxfPZfw@mail.gmail.com>

Hi Sascha,

2015-02-05 16:25 GMT+01:00 Sascha Hauer <s.hauer at pengutronix.de>:
> This series adds initial support for the MediaTek MT6397 PMIC and the
> necessary infrastructure to attach it on the MT8135 / MT8173 SoCs.
>
> The infrastructure includes:
>
> - pericfg / infracfg controller support
>   The pericfg / infracfg controllers contain miscellaneous registers for
>   reset controllers and clocks.
>
> - PMIC wrapper support
>   On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
>   SPI. The SPI master interface is not directly visible to the CPU, but
>   only through the PMIC wrapper inside the SoC. The communication between
>   the SoC and the PMIC can optionally be encrypted. Also a non standard
>   Dual IO SPI mode can be used to increase speed. The MT8135 also supports
>   a special feature named "IP Pairing". With IP Pairing the pins of some
>   SoC internal peripherals can be on the PMIC. The signals of these pins
>   are routed over the SPI bus using the pwrap bridge. Because of these
>   optional non SPI conform features the PMIC driver is not implemented as
>   a SPI bus master driver.
>
> The MT6397 PMIC itself is implemented as a regular mfd device driver which
> uses regmap to access the PMIC registers.
>
> This series also adds regulator support for the MT6397 PMIC.
>
> The first 6 patches can be merged through the ARM SoC tree. The mfd
> patch is independent of the first 6 patches and can be merged through the
> mfd maintainer trees.

As clock driver and reset controller registers are mixed together in
Mediatek SoCs I would pretty like to see the reset driver in the clock
driver. This is also the way other SoCs handle this case.
As syscon is available at this time, both the clock and the reset
driver should use this (via syscon_node_to_regmap). For your reset
driver, this should be a minimal change as you already use regmap.

Please coordinate with James and Henry to get this into one series using syscon.

Thanks,
Matthias

>
> changes since v2:
>
> - put device tree docs into a separate patch
> - Fix lockdep issues in irq mt6397 handler
> - cosmetic changes
>
> Changes since v1:
>
> - document reset bindings for infracfg/pericfg
> - fix base addresses in infracfg binding example
> - Remove more Email addresses from Flora Fu (She is not working at
>   MediaTek anymore, her address is no longer valid)
> - drop Regulator support patch, it's already in next
>
> Sascha
>



-- 
motzblog.wordpress.com


From matthias.bgg at gmail.com  Thu Feb  5 09:24:54 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 5 Feb 2015 18:24:54 +0100
Subject: [PATCH v4 0/7] clk: Add common clock support for Mediatek MT8135
 and MT8173.
In-Reply-To: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
References: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>

Hi Henry,

2015-01-30 6:13 GMT+01:00 Henry Chen <henryc.chen at mediatek.com>:
> This patchset contains the initial common clock support for Mediatek SoCs.
> Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes and clock gates.
>
> This patchset also contains a basic clock support for Mediatek MT8135 and MT8173.
>
> This driver is based on 3.19-rc1 + MT8135 and MT8173 basic support.
>
> Changes in v2:
> - Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch.
>
> Changes in v3:
> - Rebase to 3.19-rc1.
> - Refine code. Remove unneed functions, debug logs and comments, and fine tune error logs.
>
> Changes in v4:
> - Support MT8173 platform.
> - Re-ordered patchset. driver/clk/Makefile in 2nd patch.
> - Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from clk-mt8135.c/clk-mt8173.c to clk-mtk.c.
> - Refine code. Rmove unnessacary debug information and unsed defines, add prefix "mtk_" for static functions.
> - Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on gate/mux/fixed-factor.
> - Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock.
> - Example above include a node for the clock controller itself, followed by the i2c controller example above.

You use pericfg and infracfg which will be used by other drivers as
well. So please use syscon for this driver. As it is no longer a
platform device it is present early in boot.
The changes should look something like the patch beneath. Please
beware that it does only show the general concept and may not even
compile. I asked Sascha to implement the reset controller as part of
the clk driver, as the registers addresses are mixed between both,
clock and reset controller. Please coordinate with him to get them
integrated (even as one series or as incremental series).

diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 76562ba..886a816 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -128,7 +128,7 @@
         infracfg: infracfg at 10001000 {
             #address-cells = <1>;
             #size-cells = <1>;
-            compatible = "mediatek,mt8135-infracfg";
+            compatible = "mediatek,mt8135-infracfg", "syscon";
             reg = <0 0x10001000 0 0x1000>;
             #clock-cells = <1>;
         };
@@ -136,7 +136,7 @@
         pericfg: pericfg at 10003000 {
             #address-cells = <1>;
             #size-cells = <1>;
-            compatible = "mediatek,mt8135-pericfg";
+            compatible = "mediatek,mt8135-pericfg", "syscon";
             reg = <0 0x10003000 0 0x1000>;
             #clock-cells = <1>;
         };
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index f05507a..8af91d9 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -28,11 +28,15 @@ static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
     struct mtk_clk_gate *cg = to_clk_gate(hw);
     u32 mask;
     u32 val;
+    int ret;

     mask = BIT(cg->bit);
-    val = mask & readl(cg->sta_addr);
+    ret = regmap_read(cg->base, cg->sta_addr, &val);

-    return val == 0;
+    if (ret < 0)
+        return ret;
+
+    return (val & mask) == 0;
 }

 static int mtk_cg_bit_is_set(struct clk_hw *hw)
@@ -40,25 +44,29 @@ static int mtk_cg_bit_is_set(struct clk_hw *hw)
     struct mtk_clk_gate *cg = to_clk_gate(hw);
     u32 mask;
     u32 val;
+    int ret;

     mask = BIT(cg->bit);
-    val = mask & readl(cg->sta_addr);
+    ret = regmap_read(cg->base, cg->sta_addr, &val);
+
+    if (ret < 0)
+        return ret;

-    return val != 0;
+    return (val & mask) != 0;
 }

 static void mtk_cg_set_bit(struct clk_hw *hw)
 {
     struct mtk_clk_gate *cg = to_clk_gate(hw);

-    writel_relaxed(BIT(cg->bit), cg->set_addr);
+    regmap_write(cg->base, cg->set_addr, BIT(cg->bit));
 }

 static void mtk_cg_clr_bit(struct clk_hw *hw)
 {
     struct mtk_clk_gate *cg = to_clk_gate(hw);

-    writel_relaxed(BIT(cg->bit), cg->clr_addr);
+    regmap_write(cg->base, cg->clr_addr, BIT(cg->bit));
 }

 static int mtk_cg_enable(struct clk_hw *hw)
@@ -100,9 +108,10 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 struct clk *mtk_clk_register_gate(
         const char *name,
         const char *parent_name,
-        void __iomem *set_addr,
-        void __iomem *clr_addr,
-        void __iomem *sta_addr,
+        struct regmap *base,
+        int set_addr,
+        int clr_addr,
+        int sta_addr,
         u8 bit,
         const struct clk_ops *ops,
         spinlock_t *lock)
@@ -124,6 +133,7 @@ struct clk *mtk_clk_register_gate(
     init.num_parents = parent_name ? 1 : 0;
     init.ops = ops;

+    cg->base = base;
     cg->set_addr = set_addr;
     cg->clr_addr = clr_addr;
     cg->sta_addr = sta_addr;
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index d67a574..75fcb6709 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -24,9 +24,10 @@

 struct mtk_clk_gate {
     struct clk_hw    hw;
-    void __iomem    *set_addr;
-    void __iomem    *clr_addr;
-    void __iomem    *sta_addr;
+    struct regmap *base;
+    int set_addr;
+    int clr_addr;
+    int sta_addr;
     u8        bit;
     spinlock_t    *lock;
 };
diff --git a/drivers/clk/mediatek/clk-mt8135.c
b/drivers/clk/mediatek/clk-mt8135.c
index e212bfd..d24dd3b 100644
--- a/drivers/clk/mediatek/clk-mt8135.c
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -844,13 +844,13 @@ CLK_OF_DECLARE(mtk_infrasys,
"mediatek,mt8135-infracfg", mtk_infrasys_init);
 static void __init mtk_pericfg_init(struct device_node *node)
 {
     struct clk_onecell_data *clk_data;
-    void __iomem *base;
+    static struct regmap *base;
     int r;

-    base = of_iomap(node, 0);
-    if (!base) {
-        pr_err("%s(): ioremap failed\n", __func__);
-        return;
+    base = syscon_node_to_regmap(node);
+    if (IS_ERR(base)) {
+        pr_err("%s(): failed to retrieve gpbr regmap, aborting.\n", __func__);
+        return -ENOMEM;
     }

     clk_data = mtk_alloc_clk_data(PERI_NR_CLK);
@@ -862,5 +862,6 @@ static void __init mtk_pericfg_init(struct
device_node *node)
     if (r)
         pr_err("%s(): could not register clock provider: %d\n",
             __func__, r);
+    mtk_register_softrst(np, 12, base, RK3288_SOFTRST);
 }
 CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index ce4f2ac..0923a3a 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -46,7 +46,7 @@ void mtk_init_factors(struct mtk_fixed_factor *clks, int num,
     }
 }

-void mtk_init_clk_gates(void __iomem *reg_base,
+void mtk_init_clk_gates(struct regmap *base,
         struct mtk_gate *clks, int num,
         struct clk_onecell_data *clk_data, spinlock_t *lock)
 {
@@ -57,9 +57,10 @@ void mtk_init_clk_gates(void __iomem *reg_base,
         struct mtk_gate *gate = &clks[i];

         clk = mtk_clk_register_gate(gate->name, gate->parent_name,
-                reg_base + gate->regs->set_ofs,
-                reg_base + gate->regs->clr_ofs,
-                reg_base + gate->regs->sta_ofs,
+                base,
+                gate->regs->set_ofs,
+                gate->regs->clr_ofs,
+                gate->regs->sta_ofs,
                 gate->shift, gate->ops, lock);

         if (IS_ERR(clk)) {


>
> James Liao (7):
>   clk: dts: mediatek: add Mediatek MT8135 clock bindings
>   clk: mediatek: Add initial common clock support for Mediatek SoCs.
>   clk: mediatek: Add basic clocks for Mediatek MT8135.
>   dts: mediatek: Enable clock support for Mediatek MT8135.
>   clk: dts: mediatek: add Mediatek MT8173 clock bindings
>   clk: mediatek: Add basic clocks for Mediatek MT8173.
>   dts: mediatek: Enable clock support for Mediatek MT8173.
>
>  .../bindings/clock/mediatek,mt8135-clock.txt       |   44 +
>  .../bindings/clock/mediatek,mt8173-clock.txt       |   42 +
>  arch/arm/boot/dts/mt8135.dtsi                      |   47 +
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   46 +
>  drivers/clk/Makefile                               |    1 +
>  drivers/clk/mediatek/Makefile                      |    3 +
>  drivers/clk/mediatek/clk-gate.c                    |  140 +++
>  drivers/clk/mediatek/clk-gate.h                    |   49 +
>  drivers/clk/mediatek/clk-mt8135-pll.c              |  860 ++++++++++++++++
>  drivers/clk/mediatek/clk-mt8135-pll.h              |   28 +
>  drivers/clk/mediatek/clk-mt8135.c                  |  866 +++++++++++++++++
>  drivers/clk/mediatek/clk-mt8173-pll.c              |  807 +++++++++++++++
>  drivers/clk/mediatek/clk-mt8173-pll.h              |   14 +
>  drivers/clk/mediatek/clk-mt8173.c                  | 1028 ++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.c                     |  154 +++
>  drivers/clk/mediatek/clk-mtk.h                     |  132 +++
>  drivers/clk/mediatek/clk-pll.c                     |   63 ++
>  drivers/clk/mediatek/clk-pll.h                     |   52 +
>  include/dt-bindings/clock/mt8135-clk.h             |  190 ++++
>  include/dt-bindings/clock/mt8173-clk.h             |  214 ++++
>  20 files changed, 4780 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8135-clock.txt
>  create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt8173-clock.txt
>  create mode 100644 drivers/clk/mediatek/Makefile
>  create mode 100644 drivers/clk/mediatek/clk-gate.c
>  create mode 100644 drivers/clk/mediatek/clk-gate.h
>  create mode 100644 drivers/clk/mediatek/clk-mt8135-pll.c
>  create mode 100644 drivers/clk/mediatek/clk-mt8135-pll.h
>  create mode 100644 drivers/clk/mediatek/clk-mt8135.c
>  create mode 100644 drivers/clk/mediatek/clk-mt8173-pll.c
>  create mode 100644 drivers/clk/mediatek/clk-mt8173-pll.h
>  create mode 100644 drivers/clk/mediatek/clk-mt8173.c
>  create mode 100644 drivers/clk/mediatek/clk-mtk.c
>  create mode 100644 drivers/clk/mediatek/clk-mtk.h
>  create mode 100644 drivers/clk/mediatek/clk-pll.c
>  create mode 100644 drivers/clk/mediatek/clk-pll.h
>  create mode 100644 include/dt-bindings/clock/mt8135-clk.h
>  create mode 100644 include/dt-bindings/clock/mt8173-clk.h
>
> --
> 1.8.1.1.dirty
>



-- 
motzblog.wordpress.com


From s.hauer at pengutronix.de  Fri Feb  6 02:30:33 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 6 Feb 2015 11:30:33 +0100
Subject: [PATCH v4 0/7] clk: Add common clock support for Mediatek MT8135
 and MT8173.
In-Reply-To: <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>
References: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
 <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>
Message-ID: <20150206103033.GS18908@pengutronix.de>

On Thu, Feb 05, 2015 at 06:24:54PM +0100, Matthias Brugger wrote:
> Hi Henry,
> 
> 2015-01-30 6:13 GMT+01:00 Henry Chen <henryc.chen at mediatek.com>:
> > This patchset contains the initial common clock support for Mediatek SoCs.
> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes and clock gates.
> >
> > This patchset also contains a basic clock support for Mediatek MT8135 and MT8173.
> >
> > This driver is based on 3.19-rc1 + MT8135 and MT8173 basic support.
> >
> > Changes in v2:
> > - Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch.
> >
> > Changes in v3:
> > - Rebase to 3.19-rc1.
> > - Refine code. Remove unneed functions, debug logs and comments, and fine tune error logs.
> >
> > Changes in v4:
> > - Support MT8173 platform.
> > - Re-ordered patchset. driver/clk/Makefile in 2nd patch.
> > - Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from clk-mt8135.c/clk-mt8173.c to clk-mtk.c.
> > - Refine code. Rmove unnessacary debug information and unsed defines, add prefix "mtk_" for static functions.
> > - Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on gate/mux/fixed-factor.
> > - Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock.
> > - Example above include a node for the clock controller itself, followed by the i2c controller example above.
> 
> You use pericfg and infracfg which will be used by other drivers as
> well. So please use syscon for this driver. As it is no longer a
> platform device it is present early in boot.
> The changes should look something like the patch beneath. Please
> beware that it does only show the general concept and may not even
> compile. I asked Sascha to implement the reset controller as part of
> the clk driver, as the registers addresses are mixed between both,
> clock and reset controller. Please coordinate with him to get them
> integrated (even as one series or as incremental series).

I don't really understand the "as part of the clk driver part". I now
have replaced the devm_regmap_init_mmio with syscon_node_to_regmap
in the pericfg / infracfg drivers. Is that all that you want or do you
want me to move the source code to drivers/clk/mediatek?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From matthias.bgg at gmail.com  Fri Feb  6 06:20:35 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 6 Feb 2015 15:20:35 +0100
Subject: [PATCH v4 0/7] clk: Add common clock support for Mediatek MT8135
 and MT8173.
In-Reply-To: <20150206103033.GS18908@pengutronix.de>
References: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
 <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>
 <20150206103033.GS18908@pengutronix.de>
Message-ID: <CABuKBeJBp115aD_xb7_2471h=iyr5Wc33m2EX715MxNc=_1p2A@mail.gmail.com>

2015-02-06 11:30 GMT+01:00 Sascha Hauer <s.hauer at pengutronix.de>:
> On Thu, Feb 05, 2015 at 06:24:54PM +0100, Matthias Brugger wrote:
>> Hi Henry,
>>
>> 2015-01-30 6:13 GMT+01:00 Henry Chen <henryc.chen at mediatek.com>:
>> > This patchset contains the initial common clock support for Mediatek SoCs.
>> > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes and clock gates.
>> >
>> > This patchset also contains a basic clock support for Mediatek MT8135 and MT8173.
>> >
>> > This driver is based on 3.19-rc1 + MT8135 and MT8173 basic support.
>> >
>> > Changes in v2:
>> > - Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch.
>> >
>> > Changes in v3:
>> > - Rebase to 3.19-rc1.
>> > - Refine code. Remove unneed functions, debug logs and comments, and fine tune error logs.
>> >
>> > Changes in v4:
>> > - Support MT8173 platform.
>> > - Re-ordered patchset. driver/clk/Makefile in 2nd patch.
>> > - Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from clk-mt8135.c/clk-mt8173.c to clk-mtk.c.
>> > - Refine code. Rmove unnessacary debug information and unsed defines, add prefix "mtk_" for static functions.
>> > - Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on gate/mux/fixed-factor.
>> > - Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock.
>> > - Example above include a node for the clock controller itself, followed by the i2c controller example above.
>>
>> You use pericfg and infracfg which will be used by other drivers as
>> well. So please use syscon for this driver. As it is no longer a
>> platform device it is present early in boot.
>> The changes should look something like the patch beneath. Please
>> beware that it does only show the general concept and may not even
>> compile. I asked Sascha to implement the reset controller as part of
>> the clk driver, as the registers addresses are mixed between both,
>> clock and reset controller. Please coordinate with him to get them
>> integrated (even as one series or as incremental series).
>
> I don't really understand the "as part of the clk driver part". I now
> have replaced the devm_regmap_init_mmio with syscon_node_to_regmap
> in the pericfg / infracfg drivers. Is that all that you want or do you
> want me to move the source code to drivers/clk/mediatek?

Yes, I propose to move the source code to drivers/clk/mediatek.
Please have a look on other clock drivers which implement the reset
controller, e.g. rockchip.

Thanks,
Matthias

>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



-- 
motzblog.wordpress.com


From s.hauer at pengutronix.de  Fri Feb  6 07:15:42 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 6 Feb 2015 16:15:42 +0100
Subject: [PATCH v4 0/7] clk: Add common clock support for Mediatek MT8135
 and MT8173.
In-Reply-To: <CABuKBeJBp115aD_xb7_2471h=iyr5Wc33m2EX715MxNc=_1p2A@mail.gmail.com>
References: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
 <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>
 <20150206103033.GS18908@pengutronix.de>
 <CABuKBeJBp115aD_xb7_2471h=iyr5Wc33m2EX715MxNc=_1p2A@mail.gmail.com>
Message-ID: <20150206151542.GO12209@pengutronix.de>

On Fri, Feb 06, 2015 at 03:20:35PM +0100, Matthias Brugger wrote:
> > I don't really understand the "as part of the clk driver part". I now
> > have replaced the devm_regmap_init_mmio with syscon_node_to_regmap
> > in the pericfg / infracfg drivers. Is that all that you want or do you
> > want me to move the source code to drivers/clk/mediatek?
> 
> Yes, I propose to move the source code to drivers/clk/mediatek.
> Please have a look on other clock drivers which implement the reset
> controller, e.g. rockchip.

Ok, I'm halfway through implementing this, but let's have weekend first.

Henry, If you're fine with this I'll change your clock series according
to Matthias suggestions.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From HenryC.Chen at mediatek.com  Sun Feb  8 19:05:41 2015
From: HenryC.Chen at mediatek.com (=?big5?B?SGVucnlDIENoZW4gKLOvq9i7qCk=?=)
Date: Mon, 9 Feb 2015 03:05:41 +0000
Subject: [PATCH v4 0/7] clk: Add common clock support for Mediatek
 MT8135 and MT8173.
In-Reply-To: <20150206151542.GO12209@pengutronix.de>
References: <1422594798-13375-1-git-send-email-henryc.chen@mediatek.com>
 <CABuKBeJSH3WzG3QC=9OoPzXE6fd9W2U67V4c19NzWcPxWR7VDg@mail.gmail.com>
 <20150206103033.GS18908@pengutronix.de>
 <CABuKBeJBp115aD_xb7_2471h=iyr5Wc33m2EX715MxNc=_1p2A@mail.gmail.com>
 <20150206151542.GO12209@pengutronix.de>
Message-ID: <973C649EAEADCC47B3D0BEB0BD37EB2F0495E9A3@mtkmbs08n1>

Hi Sascha,

It's okay for me, thanks.

Henry

> -----Original Message-----
> From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> Sent: Friday, February 06, 2015 11:16 PM
> To: Matthias Brugger
> Cc: HenryC Chen (???); Rob Herring; Mike Turquette; srv_heupstream;
> Sascha Hauer; JamesJJ Liao (???); Eddie Huang (???); Pawel Moll;
> Mark Rutland; Ian Campbell; Kumar Gala; Russell King; Catalin Marinas;
> Vladimir Murzin; Ashwin Chaugule; Yingjoe Chen (???);
> devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linux-mediatek at lists.infradead.org
> Subject: Re: [PATCH v4 0/7] clk: Add common clock support for Mediatek
> MT8135 and MT8173.
> 
> On Fri, Feb 06, 2015 at 03:20:35PM +0100, Matthias Brugger wrote:
> > > I don't really understand the "as part of the clk driver part". I
> > > now have replaced the devm_regmap_init_mmio with
> > > syscon_node_to_regmap in the pericfg / infracfg drivers. Is that
> all
> > > that you want or do you want me to move the source code to
> drivers/clk/mediatek?
> >
> > Yes, I propose to move the source code to drivers/clk/mediatek.
> > Please have a look on other clock drivers which implement the reset
> > controller, e.g. rockchip.
> 
> Ok, I'm halfway through implementing this, but let's have weekend first.
> 
> Henry, If you're fine with this I'll change your clock series according
> to Matthias suggestions.
> 
> Sascha
> 
> --
> Pengutronix e.K.                           |
> |
> Industrial Linux Solutions                 | http://www.pengutronix.de/
> |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0
> |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-
> 5555 |

************* Email Confidentiality Notice ********************
The information contained in this e-mail message (including any 
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be 
conveyed only to the designated recipient(s). Any use, dissemination, 
distribution, printing, retaining or copying of this e-mail (including its 
attachments) by unintended recipient(s) is strictly prohibited and may 
be unlawful. If you are not an intended recipient of this e-mail, or believe 
that you have received this e-mail in error, please notify the sender 
immediately (by replying to this e-mail), delete any and all copies of 
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!

From matthias.bgg at gmail.com  Thu Feb 19 02:41:33 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 19 Feb 2015 11:41:33 +0100
Subject: [PATCH] clocksource: mtk: Fix race conditions in probe code
Message-ID: <1424342493-31391-1-git-send-email-matthias.bgg@gmail.com>

We have two race conditions in the probe code which could lead to a null
pointer dereference in the interrupt handler.

The interrupt handler accesses the clockevent device, which may not yet be
registered.

First race condition happens when the interrupt handler gets registered before
the interrupts get disabled. The second race condition happens when the
interrupts get enabled, but the clockevent device is not yet registered.

Fix that by disabling the interrupts before we register the interrupt and enable
the interrupts after the clockevent device got registered.

Reported-by: Gongbae Park <yongbae2 at gmail.com>
Signed-off-by: Matthias Brugger <matthias.bgg at gmail.com>
Cc: stable at vger.kernel.org
---
 drivers/clocksource/mtk_timer.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index 32a3d25..68ab423 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -224,6 +224,8 @@ static void __init mtk_timer_init(struct device_node *node)
 	}
 	rate = clk_get_rate(clk);
 
+	mtk_timer_global_reset(evt);
+
 	if (request_irq(evt->dev.irq, mtk_timer_interrupt,
 			IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
 		pr_warn("failed to setup irq %d\n", evt->dev.irq);
@@ -232,8 +234,6 @@ static void __init mtk_timer_init(struct device_node *node)
 
 	evt->ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
 
-	mtk_timer_global_reset(evt);
-
 	/* Configure clock source */
 	mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
 	clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
@@ -241,10 +241,11 @@ static void __init mtk_timer_init(struct device_node *node)
 
 	/* Configure clock event */
 	mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
-	mtk_timer_enable_irq(evt, GPT_CLK_EVT);
-
 	clockevents_config_and_register(&evt->dev, rate, 0x3,
 					0xffffffff);
+
+	mtk_timer_enable_irq(evt, GPT_CLK_EVT);
+
 	return;
 
 err_clk_disable:
-- 
1.9.1



From s.hauer at pengutronix.de  Sun Feb 22 03:49:20 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:20 +0100
Subject: [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and
 MT8173
Message-ID: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>

This patchset contains the initial common clock support for Mediatek SoCs.
Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes
and clock gates.

Sascha

Changes in v2:
- Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch.

Changes in v3:
- Rebase to 3.19-rc1.
- Refine code. Remove unneed functions, debug logs and comments, and fine tune
  error logs.

Changes in v4:
- Support MT8173 platform.
- Re-ordered patchset. driver/clk/Makefile in 2nd patch.
- Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from
  clk-mt8135.c/clk-mt8173.c to clk-mtk.c.
- Refine code. Rmove unnessacary debug information and unsed defines,
  add prefix "mtk_" for static functions.
- Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on
  gate/mux/fixed-factor.
- Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock.
- Example above include a node for the clock controller itself, followed
  by the i2c controller example above.

Changes in v5:
- Add reset controller support for pericfg/infracfg
- Use regmap for the gates
- remove now unnecessary spinlock for the gates
- Add PMIC wrapper support as of v3

Changes in v6:
- rework PLL support, only a fraction of original size now
- Move binding docs to Documentation/devicetree/bindings/arm/mediatek since
  the units are not really clock specific (they contain reset controllers)



From s.hauer at pengutronix.de  Sun Feb 22 03:49:25 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:25 +0100
Subject: [PATCH 5/5] dt-bindings: ARM: Mediatek: Document devicetree bindings
 for clock/reset controllers
In-Reply-To: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
References: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424605765-19751-6-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  | 23 +++++++++++++++++
 .../bindings/arm/mediatek/mediatek,infracfg.txt    | 30 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,pericfg.txt     | 30 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,topckgen.txt    | 23 +++++++++++++++++
 4 files changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
new file mode 100644
index 0000000..5af6d73
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -0,0 +1,23 @@
+Mediatek apmixedsys controller
+==============================
+
+The Mediatek apmixedsys controller provides the PLLs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-apmixedsys"
+	- "mediatek,mt8173-apmixedsys"
+- #clock-cells: Must be 1
+
+The apmixedsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+apmixedsys: apmixedsys at 10209000 {
+	compatible = "mediatek,mt8173-apmixedsys";
+	reg = <0 0x10209000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
new file mode 100644
index 0000000..684da473
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -0,0 +1,30 @@
+Mediatek infracfg controller
+============================
+
+The Mediatek infracfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-infracfg", "syscon"
+	- "mediatek,mt8173-infracfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The infracfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+infracfg: infracfg at 10001000 {
+	compatible = "mediatek,mt8173-infracfg", "syscon";
+	reg = <0 0x10001000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
new file mode 100644
index 0000000..fdb45c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -0,0 +1,30 @@
+Mediatek pericfg controller
+===========================
+
+The Mediatek pericfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-pericfg", "syscon"
+	- "mediatek,mt8173-pericfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The pericfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+pericfg: pericfg at 10003000 {
+	compatible = "mediatek,mt8173-pericfg", "syscon";
+	reg = <0 0x10003000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
new file mode 100644
index 0000000..a425248
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -0,0 +1,23 @@
+Mediatek topckgen controller
+============================
+
+The Mediatek topckgen controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-topckgen"
+	- "mediatek,mt8173-topckgen"
+- #clock-cells: Must be 1
+
+The topckgen controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+topckgen: topckgen at 10000000 {
+	compatible = "mediatek,mt8173-topckgen";
+	reg = <0 0x10000000 0 0x1000>;
+	#clock-cells = <1>;
+};
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 03:49:22 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:22 +0100
Subject: [PATCH 2/5] clk: mediatek: Add reset controller support
In-Reply-To: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
References: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424605765-19751-3-git-send-email-s.hauer@pengutronix.de>

The pericfg and infracfg units also provide reset lines to several
other SoC internal units. Add support for the reset controller.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/mediatek/Makefile  |  1 +
 drivers/clk/mediatek/clk-mtk.h | 10 +++++
 drivers/clk/mediatek/reset.c   | 99 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)
 create mode 100644 drivers/clk/mediatek/reset.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index c384e97..0b6f1c3 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1 +1,2 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index c7c0d35..fb61040 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -161,4 +161,14 @@ static inline void mtk_register_reset_controller(struct device_node *np,
 }
 #endif
 
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+}
+#endif
+
 #endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
new file mode 100644
index 0000000..3a85a53
--- /dev/null
+++ b/drivers/clk/mediatek/reset.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+struct mtk_reset {
+	struct regmap *regmap;
+	int regofs;
+	struct reset_controller_dev rcdev;
+};
+
+static int mtk_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), ~0);
+}
+
+static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), 0);
+}
+
+static int mtk_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	ret = mtk_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return mtk_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_reset_ops = {
+	.assert = mtk_reset_assert,
+	.deassert = mtk_reset_deassert,
+	.reset = mtk_reset,
+};
+
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+	struct mtk_reset *data;
+	int ret;
+	struct regmap *regmap;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
+				PTR_ERR(regmap));
+		return;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return;
+
+	data->regmap = regmap;
+	data->regofs = regofs;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = num_regs * 32;
+	data->rcdev.ops = &mtk_reset_ops;
+	data->rcdev.of_node = np;
+
+	ret = reset_controller_register(&data->rcdev);
+	if (ret) {
+		pr_err("could not register reset controller: %d\n", ret);
+		kfree(data);
+		return;
+	}
+}
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 03:49:21 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:21 +0100
Subject: [PATCH 1/5] clk: mediatek: Add initial common clock support for
 Mediatek SoCs.
In-Reply-To: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
References: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424605765-19751-2-git-send-email-s.hauer@pengutronix.de>

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

This patch adds common clock support for Mediatek SoCs, including plls,
muxes and clock gates.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/Makefile            |   1 +
 drivers/clk/mediatek/Makefile   |   1 +
 drivers/clk/mediatek/clk-gate.c | 137 +++++++++++++++++
 drivers/clk/mediatek/clk-gate.h |  49 ++++++
 drivers/clk/mediatek/clk-mtk.c  | 195 ++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h  | 164 ++++++++++++++++++++
 drivers/clk/mediatek/clk-pll.c  | 330 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 877 insertions(+)
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-gate.c
 create mode 100644 drivers/clk/mediatek/clk-gate.h
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h
 create mode 100644 drivers/clk/mediatek/clk-pll.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..ce6c250 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
+obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 0000000..c384e97
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1 @@
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 0000000..9d77ee3
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val == 0;
+}
+
+static int mtk_cg_bit_is_set(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static void mtk_cg_set_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+}
+
+static void mtk_cg_clr_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+}
+
+static int mtk_cg_enable(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+}
+
+static int mtk_cg_enable_inv(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+}
+
+const struct clk_ops mtk_clk_gate_ops_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable,
+	.disable	= mtk_cg_disable,
+};
+
+const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv,
+	.disable	= mtk_cg_disable_inv,
+};
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops)
+{
+	struct mtk_clk_gate *cg;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = ops;
+
+	cg->regmap = regmap;
+	cg->set_ofs = set_ofs;
+	cg->clr_ofs = clr_ofs;
+	cg->sta_ofs = sta_ofs;
+	cg->bit = bit;
+
+	cg->hw.init = &init;
+
+	clk = clk_register(NULL, &cg->hw);
+	if (IS_ERR(clk))
+		kfree(cg);
+
+	return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 0000000..6b6780b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_GATE_H
+#define __DRV_CLK_GATE_H
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	int		set_ofs;
+	int		clr_ofs;
+	int		sta_ofs;
+	u8		bit;
+};
+
+static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_gate, hw);
+}
+
+extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 0000000..aeb2cc0
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+{
+	int i;
+	struct clk_onecell_data *clk_data;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return NULL;
+
+	clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_out;
+
+	clk_data->clk_num = clk_num;
+
+	for (i = 0; i < clk_num; ++i)
+		clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+	return clk_data;
+err_out:
+	kfree(clk_data);
+
+	return NULL;
+}
+
+void mtk_clk_register_factors(struct mtk_fixed_factor *clks, int num,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < num; i++) {
+		struct mtk_fixed_factor *ff = &clks[i];
+
+		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+				CLK_SET_RATE_PARENT, ff->mult, ff->div);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					ff->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[ff->id] = clk;
+	}
+}
+
+int mtk_clk_register_gates(struct device_node *node, struct mtk_gate *clks, int num,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	if (!clk_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+				PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		struct mtk_gate *gate = &clks[i];
+
+		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+				regmap,
+				gate->regs->set_ofs,
+				gate->regs->clr_ofs,
+				gate->regs->sta_ofs,
+				gate->shift, gate->ops);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					gate->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[gate->id] = clk;
+	}
+
+	return 0;
+}
+
+struct clk *mtk_clk_register_composite(struct mtk_composite *mc, void __iomem *base,
+		spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
+	const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
+	const char **parent_names;
+	int num_parents;
+	int ret;
+
+	if (mc->mux_shift >= 0) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = base + mc->mux_reg;
+		mux->mask = BIT(mc->mux_width) - 1;
+		mux->shift = mc->mux_shift;
+		mux->lock = lock;
+
+		mux_hw = &mux->hw;
+		mux_ops = &clk_mux_ops;
+
+		parent_names = mc->parent_names;
+		num_parents = mc->num_parents;
+	} else {
+		parent_names = &mc->parent;
+		num_parents = 1;
+	}
+
+	if (mc->gate_shift >= 0) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		gate->reg = base + mc->gate_reg;
+		gate->bit_idx = mc->gate_shift;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = lock;
+
+		gate_hw = &gate->hw;
+		gate_ops = &clk_gate_ops;
+	}
+
+	if (mc->divider_shift >= 0) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		div->reg = base + mc->divider_reg;
+		div->shift = mc->divider_shift;
+		div->width = mc->divider_width;
+		div->lock = lock;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
+		mux_hw, mux_ops,
+		div_hw, div_ops,
+		gate_hw, gate_ops,
+		mc->flags);
+
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(mux);
+	}
+
+	return clk;
+err_out:
+	kfree(mux);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 0000000..c7c0d35
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define MAX_MUX_GATE_BIT	31
+#define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
+
+#define MHZ (1000 * 1000)
+
+struct mtk_fixed_factor {
+	int id;
+	const char *name;
+	const char *parent_name;
+	int mult;
+	int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.mult = _mult,				\
+		.div = _div,				\
+	}
+
+extern void mtk_clk_register_factors(struct mtk_fixed_factor *clks, int num,
+		struct clk_onecell_data *clk_data);
+
+struct mtk_composite {
+	int id;
+	const char *name;
+	const char **parent_names;
+	const char *parent;
+	unsigned flags;
+
+	uint32_t mux_reg;
+	uint32_t divider_reg;
+	uint32_t gate_reg;
+
+	signed char mux_shift;
+	signed char mux_width;
+	signed char gate_shift;
+
+	signed char divider_shift;
+	signed char divider_width;
+
+	signed char num_parents;
+};
+
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_reg = _reg,					\
+		.gate_shift = _gate,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = -1,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+		.id = _id,						\
+		.parent = _parent,					\
+		.name = _name,						\
+		.divider_reg = _div_reg,				\
+		.divider_shift = _div_shift,				\
+		.divider_width = _div_width,				\
+		.gate_reg = _gate_reg,					\
+		.gate_shift = _gate_shift,				\
+		.mux_shift = -1,					\
+		.flags = 0,						\
+	}
+
+struct clk *mtk_clk_register_composite(struct mtk_composite *mc, void __iomem *base,
+		spinlock_t *lock);
+
+struct mtk_gate_regs {
+	u32 sta_ofs;
+	u32 clr_ofs;
+	u32 set_ofs;
+};
+
+struct mtk_gate {
+	int id;
+	const char *name;
+	const char *parent_name;
+	struct mtk_gate_regs *regs;
+	int shift;
+	const struct clk_ops *ops;
+};
+
+int mtk_clk_register_gates(struct device_node *node, struct mtk_gate *clks, int num,
+		struct clk_onecell_data *clk_data);
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
+
+#define HAVE_RST_BAR	BIT(0)
+
+struct mtk_pll_data {
+	int id;
+	const char *name;
+	uint32_t reg;
+	uint32_t pwr_reg;
+	uint32_t en_mask;
+	uint32_t pd_reg;
+	uint32_t tuner_reg;
+	int pd_shift;
+	unsigned int flags;
+	const struct clk_ops *ops;
+	u32 rst_bar_mask;
+	unsigned long fmax;
+	int pcwbits;
+	uint32_t pcw_reg;
+	int pcw_shift;
+};
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls);
+
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+}
+#endif
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 0000000..06cd8c7
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+
+#define CON0_BASE_EN		BIT(0)
+#define CON0_PWR_ON		BIT(0)
+#define CON0_ISO_EN		BIT(1)
+#define CON0_PCW_CHG		BIT(31)
+
+#define AUDPLL_TUNER_EN		BIT(31)
+
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base_addr;
+	void __iomem	*pd_addr;
+	void __iomem	*pwr_addr;
+	void __iomem	*tuner_addr;
+	void __iomem	*pcw_addr;
+	const struct mtk_pll_data *data;
+};
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+static int mtk_pll_is_prepared(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	return (readl(pll->base_addr) & CON0_BASE_EN) != 0;
+}
+
+static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
+		u32 pcw, int postdiv)
+{
+	int pcwbits = pll->data->pcwbits;
+	int pcwfbits;
+	u64 vco;
+	u8 c = 0;
+
+	/* The fractional part of the PLL divider. */
+	pcwfbits = pcwbits > 7 ? pcwbits - 7 : 0;
+
+	vco = (u64)fin * pcw;
+
+	if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+		c = 1;
+
+	vco >>= pcwfbits;
+
+	if (c)
+		++vco;
+
+	return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+static void mtk_pll_set_rate_regs(struct clk_hw *hw, u32 pcw,
+		int postdiv)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 con1, pd, val;
+	int pll_en;
+
+	/* set postdiv */
+	pd = readl(pll->pd_addr);
+	pd &= ~(0x7 << pll->data->pd_shift);
+	pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+	writel(pd, pll->pd_addr);
+
+	pll_en = readl(pll->base_addr) & CON0_BASE_EN;
+
+	/* set pcw */
+	val = readl(pll->pcw_addr);
+
+	val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
+			pll->data->pcw_shift);
+	val |= pcw << pll->data->pcw_shift;
+	writel(val, pll->pcw_addr);
+
+	con1 = readl(pll->base_addr + 4);
+
+	if (pll_en)
+		con1 |= CON0_PCW_CHG;
+
+	writel(con1, pll->base_addr + 4);
+	if (pll->tuner_addr)
+		writel(con1 + 1, pll->tuner_addr);
+
+	if (pll_en)
+		usleep_range(20, 1000);
+}
+
+/*
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @pll:	The pll
+ * @pcw:	The pcw value (output)
+ * @postdiv:	The post divider (output)
+ * @freq:	The desired target frequency
+ * @fin:	The input frequency
+ *
+ */
+static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+		u32 freq, u32 fin)
+{
+	unsigned long fmin = 1000 * MHZ;
+	u64 _pcw;
+	u32 val;
+
+	if (freq > pll->data->fmax)
+		freq = pll->data->fmax;
+
+	for (val = 0; val < 4; val++) {
+		*postdiv = 1 << val;
+		if (freq * *postdiv >= fmin)
+			break;
+	}
+
+	/* _pcw = freq * postdiv / fin * 2^pcwfbits */
+	_pcw = ((u64)freq << val) << (pll->data->pcwbits - 7);
+	do_div(_pcw, fin);
+
+	*pcw = (u32)_pcw;
+}
+
+static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	u32 postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+	mtk_pll_set_rate_regs(hw, pcw, postdiv);
+
+	return 0;
+}
+
+static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 postdiv;
+	u32 pcw;
+
+	postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & 0x7;
+	postdiv = 1 << postdiv;
+
+	pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
+	pcw &= GENMASK(pll->data->pcwbits - 1, 0);
+
+	return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
+}
+
+static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	int postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
+
+	return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
+}
+
+static int mtk_pll_prepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	r = readl(pll->pwr_addr) | CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+	usleep_range(1, 100);
+
+	r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+	usleep_range(1, 100);
+
+	r = readl(pll->base_addr) | pll->data->en_mask;
+	writel(r, pll->base_addr);
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	usleep_range(20, 1000);
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr) | pll->data->rst_bar_mask;
+		writel(r, pll->base_addr);
+	}
+
+	return 0;
+}
+
+static void mtk_pll_unprepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr) & ~pll->data->rst_bar_mask;
+		writel(r, pll->base_addr);
+	}
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	r = readl(pll->base_addr) & ~CON0_BASE_EN;
+	writel(r, pll->base_addr);
+
+	r = readl(pll->pwr_addr) | CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+
+	r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+}
+
+static const struct clk_ops mtk_pll_ops = {
+	.is_prepared	= mtk_pll_is_prepared,
+	.prepare	= mtk_pll_prepare,
+	.unprepare	= mtk_pll_unprepare,
+	.recalc_rate	= mtk_pll_recalc_rate,
+	.round_rate	= mtk_pll_round_rate,
+	.set_rate	= mtk_pll_set_rate,
+};
+
+static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
+		void __iomem *base)
+{
+	struct mtk_clk_pll *pll;
+	struct clk_init_data init;
+	struct clk *clk;
+	const char *parent_name = "clk26m";
+
+	pr_debug("%s(): name: %s\n", __func__, data->name);
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	pll->base_addr = base + data->reg;
+	pll->pwr_addr = base + data->pwr_reg;
+	pll->pd_addr = base + data->pd_reg;
+	pll->pcw_addr = base + data->pcw_reg;
+	if (data->tuner_reg)
+		pll->tuner_addr = base + data->tuner_reg;
+	pll->hw.init = &init;
+	pll->data = data;
+
+	init.name = data->name;
+	init.ops = &mtk_pll_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r, i;
+	struct clk *clk;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(num_plls);
+	if (!clk_data)
+		return;
+
+	for (i = 0; i < num_plls; i++) {
+		const struct mtk_pll_data *pll = &plls[i];
+
+		clk = mtk_clk_register_pll(pll, base);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					pll->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[pll->id] = clk;
+	}
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 03:49:23 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:23 +0100
Subject: [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135.
In-Reply-To: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
References: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424605765-19751-4-git-send-email-s.hauer@pengutronix.de>

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

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

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/mediatek/Makefile                      |   1 +
 drivers/clk/mediatek/clk-mt8135.c                  | 634 +++++++++++++++++++++
 include/dt-bindings/clock/mt8135-clk.h             | 190 ++++++
 .../dt-bindings/reset-controller/mt8135-resets.h   |  64 +++
 4 files changed, 889 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8135.c
 create mode 100644 include/dt-bindings/clock/mt8135-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 0b6f1c3..12ce576 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,2 +1,3 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 0000000..6157447
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/mt8135-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static DEFINE_SPINLOCK(lock);
+
+static struct mtk_fixed_factor root_clk_alias[] __initdata = {
+	FACTOR(TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+	FACTOR(TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+	FACTOR(TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+	FACTOR(TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+};
+
+static struct mtk_fixed_factor top_divs[] __initdata = {
+	FACTOR(TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
+	FACTOR(TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
+	FACTOR(TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
+	FACTOR(TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
+
+	FACTOR(TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+	FACTOR(TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+	FACTOR(TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
+	FACTOR(TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
+	FACTOR(TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
+
+	FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+	FACTOR(TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
+	FACTOR(TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+	FACTOR(TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+	FACTOR(TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
+	FACTOR(TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
+
+	FACTOR(TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
+	FACTOR(TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
+	FACTOR(TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
+	FACTOR(TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
+	FACTOR(TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
+	FACTOR(TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
+	FACTOR(TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
+	FACTOR(TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
+
+	FACTOR(TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
+
+	FACTOR(TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
+	FACTOR(TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
+
+	FACTOR(TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
+
+	FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+	FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+	FACTOR(TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
+	FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+	FACTOR(TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
+
+	FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
+	FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
+	FACTOR(TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
+	FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
+
+	FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
+	FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+	FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
+	FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 5),
+	FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+
+	FACTOR(TOP_APLL_CK, "apll_ck", "audpll", 1, 1),
+	FACTOR(TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
+	FACTOR(TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
+	FACTOR(TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
+	FACTOR(TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
+
+	FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
+	FACTOR(TOP_VPLL_DPIX_CK, "vpll_dpix_ck", "lvdspll", 1, 1),
+
+	FACTOR(TOP_TVHDMI_H_CK, "tvhdmi_h_ck", "tvdpll", 1, 1),
+
+	FACTOR(TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
+	FACTOR(TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
+
+	FACTOR(TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
+	FACTOR(TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
+
+	FACTOR(TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+};
+
+static const char *axi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d4",
+	"syspll_d6",
+	"univpll_d5",
+	"univpll2_d2",
+	"syspll_d3p5"
+};
+
+static const char *smi_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll1_d6",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7",
+	"vdecpll",
+	"lvdspll"
+};
+
+static const char *mfg_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d4",
+	"syspll_d2",
+	"syspll_d2p5",
+	"syspll_d3",
+	"univpll_d5",
+	"univpll1_d2",
+	"mmpll_d2",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7"
+};
+
+static const char *irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll1_d6"
+};
+
+static const char *cam_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll1_d4"
+};
+
+static const char *aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"univpll_d10"
+};
+
+static const char *jpg_parents[] __initconst = {
+	"clk26m",
+	"syspll_d5",
+	"syspll_d4",
+	"syspll_d3",
+	"univpll_d7",
+	"univpll2_d2",
+	"univpll_d5"
+};
+
+static const char *disp_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3p5",
+	"syspll_d3",
+	"univpll2_d2",
+	"univpll_d5",
+	"univpll1_d2",
+	"lvdspll",
+	"vdecpll"
+};
+
+static const char *msdc30_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d5",
+	"univpll1_d4",
+	"univpll2_d4",
+	"msdcpll"
+};
+
+static const char *usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"univpll1_d10"
+};
+
+static const char *venc_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d6",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6"
+};
+
+static const char *spi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char *uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char *mem_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck"
+};
+
+static const char *camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll1_d6",
+	"syspll_d16",
+	"syspll_d8"
+};
+
+static const char *audio_parents[] __initconst = {
+	"clk26m",
+	"syspll_d24"
+};
+
+static const char *fix_parents[] __initconst = {
+	"rtc32k",
+	"clk26m",
+	"univpll_d5",
+	"univpll_d7",
+	"univpll1_d2",
+	"univpll1_d4",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char *vdec_parents[] __initconst = {
+	"clk26m",
+	"vdecpll",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"syspll_d5",
+	"syspll_d6",
+	"syspll_d8",
+	"univpll1_d2",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll_d10",
+	"univpll2_d4",
+	"lvdspll"
+};
+
+static const char *ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"syspll_d12"
+};
+
+static const char *dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8"
+};
+
+static const char *pmicspi_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d10",
+	"mempll_mck_d4",
+	"univpll_d26",
+	"syspll_d24"
+};
+
+static const char *smi_mfg_as_parents[] __initconst = {
+	"clk26m",
+	"smi_sel",
+	"mfg_sel",
+	"mem_sel"
+};
+
+static const char *gcpu_parents[] __initconst = {
+	"clk26m",
+	"syspll_d4",
+	"univpll_d7",
+	"syspll_d5",
+	"syspll_d6"
+};
+
+static const char *dpi1_parents[] __initconst = {
+	"clk26m",
+	"tvhdmi_h_ck",
+	"tvhdmi_d2",
+	"tvhdmi_d4"
+};
+
+static const char *cci_parents[] __initconst = {
+	"clk26m",
+	"mainpll_537p3m",
+	"univpll_d3",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d5"
+};
+
+static const char *apll_parents[] __initconst = {
+	"clk26m",
+	"apll_ck",
+	"apll_d4",
+	"apll_d8",
+	"apll_d16",
+	"apll_d24"
+};
+
+static const char *hdmipll_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_clkdig_cts",
+	"hdmitx_clkdig_d2",
+	"hdmitx_clkdig_d3"
+};
+
+static struct mtk_composite top_muxes[] __initdata = {
+	/* CLK_CFG_0 */
+	MUX_GATE(TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+	MUX_GATE(TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
+	MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
+	MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
+	MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0144, 8, 2, 15),
+	MUX_GATE(TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
+	MUX_GATE(TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
+	MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
+	MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
+	MUX_GATE(TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
+	/* CLK_CFG_4 */
+	MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
+	MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
+	MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
+	MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
+	MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
+	MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
+	MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+		0x015c, 16, 2, 23),
+	MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
+	/* CLK_CFG_8 */
+	MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
+	MUX_GATE(TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
+	MUX_GATE(TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
+		0x0164, 16, 2, 23),
+	MUX_GATE(TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
+	/* CLK_CFG_9 */
+	MUX_GATE(TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
+	MUX_GATE(TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
+	MUX_GATE(TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
+	MUX_GATE(TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static void __init mtk_init_clk_topckgen(void __iomem *top_base,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < ARRAY_SIZE(top_muxes); i++) {
+		struct mtk_composite *mux = &top_muxes[i];
+
+		clk = mtk_clk_register_composite(mux, top_base, &lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					mux->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mux->id] = clk;
+	}
+}
+
+static struct mtk_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 struct mtk_gate infra_clks[] __initdata = {
+	GATE_ICG(INFRA_PMIC_WRAP_CK, "pmic_wrap_ck", "axi_sel", 23),
+	GATE_ICG(INFRA_PMICSPI_CK, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
+	GATE_ICG(INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
+	GATE_ICG(INFRA_KP_CK, "kp_ck", "axi_sel", 16),
+	GATE_ICG(INFRA_CPUM_CK, "cpum_ck", "cpum_tck_in", 15),
+	GATE_ICG(INFRA_M4U_CK, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(INFRA_MFGAXI_CK, "mfgaxi_ck", "axi_sel", 7),
+	GATE_ICG(INFRA_DEVAPC_CK, "devapc_ck", "axi_sel", 6),
+	GATE_ICG(INFRA_AUDIO_CK, "audio_ck", "aud_intbus_sel", 5),
+	GATE_ICG(INFRA_MFG_BUS_CK, "mfg_bus_ck", "axi_sel", 2),
+	GATE_ICG(INFRA_SMI_CK, "smi_ck", "smi_sel", 1),
+	GATE_ICG(INFRA_DBGCLK_CK, "dbgclk_ck", "axi_sel", 0),
+};
+
+static struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#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 struct mtk_gate peri_clks[] __initdata = {
+	/* PERI0 */
+	GATE_PERI0(PERI_I2C5_CK, "i2c5_ck", "axi_sel", 31),
+	GATE_PERI0(PERI_I2C4_CK, "i2c4_ck", "axi_sel", 30),
+	GATE_PERI0(PERI_I2C3_CK, "i2c3_ck", "axi_sel", 29),
+	GATE_PERI0(PERI_I2C2_CK, "i2c2_ck", "axi_sel", 28),
+	GATE_PERI0(PERI_I2C1_CK, "i2c1_ck", "axi_sel", 27),
+	GATE_PERI0(PERI_I2C0_CK, "i2c0_ck", "axi_sel", 26),
+	GATE_PERI0(PERI_UART3_CK, "uart3_ck", "axi_sel", 25),
+	GATE_PERI0(PERI_UART2_CK, "uart2_ck", "axi_sel", 24),
+	GATE_PERI0(PERI_UART1_CK, "uart1_ck", "axi_sel", 23),
+	GATE_PERI0(PERI_UART0_CK, "uart0_ck", "axi_sel", 22),
+	GATE_PERI0(PERI_IRDA_CK, "irda_ck", "irda_sel", 21),
+	GATE_PERI0(PERI_NLI_CK, "nli_ck", "axi_sel", 20),
+	GATE_PERI0(PERI_MD_HIF_CK, "md_hif_ck", "axi_sel", 19),
+	GATE_PERI0(PERI_AP_HIF_CK, "ap_hif_ck", "axi_sel", 18),
+	GATE_PERI0(PERI_MSDC30_3_CK, "msdc30_3_ck", "msdc30_4_sel", 17),
+	GATE_PERI0(PERI_MSDC30_2_CK, "msdc30_2_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(PERI_MSDC30_1_CK, "msdc30_1_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(PERI_MSDC20_2_CK, "msdc20_2_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(PERI_MSDC20_1_CK, "msdc20_1_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(PERI_AP_DMA_CK, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(PERI_USB1_CK, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(PERI_USB0_CK, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(PERI_PWM_CK, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(PERI_PWM7_CK, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(PERI_PWM6_CK, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(PERI_PWM5_CK, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(PERI_PWM4_CK, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(PERI_PWM3_CK, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(PERI_PWM2_CK, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(PERI_PWM1_CK, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(PERI_THERM_CK, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(PERI_NFI_CK, "nfi_ck", "axi_sel", 0),
+	/* PERI1 */
+	GATE_PERI1(PERI_USBSLV_CK, "usbslv_ck", "axi_sel", 8),
+	GATE_PERI1(PERI_USB1_MCU_CK, "usb1_mcu_ck", "axi_sel", 7),
+	GATE_PERI1(PERI_USB0_MCU_CK, "usb0_mcu_ck", "axi_sel", 6),
+	GATE_PERI1(PERI_GCPU_CK, "gcpu_ck", "gcpu_sel", 5),
+	GATE_PERI1(PERI_FHCTL_CK, "fhctl_ck", "clk26m", 4),
+	GATE_PERI1(PERI_SPI1_CK, "spi1_ck", "spi_sel", 3),
+	GATE_PERI1(PERI_AUXADC_CK, "auxadc_ck", "clk26m", 2),
+	GATE_PERI1(PERI_PERI_PWRAP_CK, "peri_pwrap_ck", "axi_sel", 1),
+	GATE_PERI1(PERI_I2C6_CK, "i2c6_ck", "axi_sel", 0),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_init_clk_topckgen(base, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
+
+#define MT8135_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8135_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_MT8135_RST_BAR,			\
+		.fmax = MT8135_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 struct mtk_pll_data plls[] = {
+	PLL(APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
+	PLL(APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
+	PLL(APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
+	PLL(APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
+	PLL(APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
+	PLL(APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x296, 6, 0x0, 0x298, 0),
+	PLL(APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
+	PLL(APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
+	PLL(APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls));
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 0000000..8aea762
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define TOP_DSI0_LNTC_DSICLK	1
+#define TOP_HDMITX_CLKDIG_CTS	2
+#define TOP_CLKPH_MCK		3
+#define TOP_CPUM_TCK_IN		4
+#define TOP_MAINPLL_806M	5
+#define TOP_MAINPLL_537P3M	6
+#define TOP_MAINPLL_322P4M	7
+#define TOP_MAINPLL_230P3M	8
+#define TOP_UNIVPLL_624M	9
+#define TOP_UNIVPLL_416M	10
+#define TOP_UNIVPLL_249P6M	11
+#define TOP_UNIVPLL_178P3M	12
+#define TOP_UNIVPLL_48M		13
+#define TOP_MMPLL_D2		14
+#define TOP_MMPLL_D3		15
+#define TOP_MMPLL_D5		16
+#define TOP_MMPLL_D7		17
+#define TOP_MMPLL_D4		18
+#define TOP_MMPLL_D6		19
+#define TOP_SYSPLL_D2		20
+#define TOP_SYSPLL_D4		21
+#define TOP_SYSPLL_D6		22
+#define TOP_SYSPLL_D8		23
+#define TOP_SYSPLL_D10		24
+#define TOP_SYSPLL_D12		25
+#define TOP_SYSPLL_D16		26
+#define TOP_SYSPLL_D24		27
+#define TOP_SYSPLL_D3		28
+#define TOP_SYSPLL_D2P5		29
+#define TOP_SYSPLL_D5		30
+#define TOP_SYSPLL_D3P5		31
+#define TOP_UNIVPLL1_D2		32
+#define TOP_UNIVPLL1_D4		33
+#define TOP_UNIVPLL1_D6		34
+#define TOP_UNIVPLL1_D8		35
+#define TOP_UNIVPLL1_D10	36
+#define TOP_UNIVPLL2_D2		37
+#define TOP_UNIVPLL2_D4		38
+#define TOP_UNIVPLL2_D6		39
+#define TOP_UNIVPLL2_D8		40
+#define TOP_UNIVPLL_D3		41
+#define TOP_UNIVPLL_D5		42
+#define TOP_UNIVPLL_D7		43
+#define TOP_UNIVPLL_D10		44
+#define TOP_UNIVPLL_D26		45
+#define TOP_APLL_CK		46
+#define TOP_APLL_D4		47
+#define TOP_APLL_D8		48
+#define TOP_APLL_D16		49
+#define TOP_APLL_D24		50
+#define TOP_LVDSPLL_D2		51
+#define TOP_LVDSPLL_D4		52
+#define TOP_LVDSPLL_D8		53
+#define TOP_LVDSTX_CLKDIG_CT	54
+#define TOP_VPLL_DPIX_CK	55
+#define TOP_TVHDMI_H_CK		56
+#define TOP_HDMITX_CLKDIG_D2	57
+#define TOP_HDMITX_CLKDIG_D3	58
+#define TOP_TVHDMI_D2		59
+#define TOP_TVHDMI_D4		60
+#define TOP_MEMPLL_MCK_D4	61
+#define TOP_AXI_SEL		62
+#define TOP_SMI_SEL		63
+#define TOP_MFG_SEL		64
+#define TOP_IRDA_SEL		65
+#define TOP_CAM_SEL		66
+#define TOP_AUD_INTBUS_SEL	67
+#define TOP_JPG_SEL		68
+#define TOP_DISP_SEL		69
+#define TOP_MSDC30_1_SEL	70
+#define TOP_MSDC30_2_SEL	71
+#define TOP_MSDC30_3_SEL	72
+#define TOP_MSDC30_4_SEL	73
+#define TOP_USB20_SEL		74
+#define TOP_VENC_SEL		75
+#define TOP_SPI_SEL		76
+#define TOP_UART_SEL		77
+#define TOP_MEM_SEL		78
+#define TOP_CAMTG_SEL		79
+#define TOP_AUDIO_SEL		80
+#define TOP_FIX_SEL		81
+#define TOP_VDEC_SEL		82
+#define TOP_DDRPHYCFG_SEL	83
+#define TOP_DPILVDS_SEL		84
+#define TOP_PMICSPI_SEL		85
+#define TOP_MSDC30_0_SEL	86
+#define TOP_SMI_MFG_AS_SEL	87
+#define TOP_GCPU_SEL		88
+#define TOP_DPI1_SEL		89
+#define TOP_CCI_SEL		90
+#define TOP_APLL_SEL		91
+#define TOP_HDMIPLL_SEL		92
+#define TOP_NR_CLK		93
+
+/* APMIXED_SYS */
+
+#define APMIXED_ARMPLL1		1
+#define APMIXED_ARMPLL2		2
+#define APMIXED_MAINPLL		3
+#define APMIXED_UNIVPLL		4
+#define APMIXED_MMPLL		5
+#define APMIXED_MSDCPLL		6
+#define APMIXED_TVDPLL		7
+#define APMIXED_LVDSPLL		8
+#define APMIXED_AUDPLL		9
+#define APMIXED_VDECPLL		10
+#define APMIXED_NR_CLK		11
+
+/* INFRA_SYS */
+
+#define INFRA_PMIC_WRAP_CK	1
+#define INFRA_PMICSPI_CK	2
+#define INFRA_CCIF1_AP_CTRL	3
+#define INFRA_CCIF0_AP_CTRL	4
+#define INFRA_KP_CK		5
+#define INFRA_CPUM_CK		6
+#define INFRA_M4U_CK		7
+#define INFRA_MFGAXI_CK		8
+#define INFRA_DEVAPC_CK		9
+#define INFRA_AUDIO_CK		10
+#define INFRA_MFG_BUS_CK	11
+#define INFRA_SMI_CK		12
+#define INFRA_DBGCLK_CK		13
+#define INFRA_NR_CLK		14
+
+/* PERI_SYS */
+
+#define PERI_I2C5_CK		1
+#define PERI_I2C4_CK		2
+#define PERI_I2C3_CK		3
+#define PERI_I2C2_CK		4
+#define PERI_I2C1_CK		5
+#define PERI_I2C0_CK		6
+#define PERI_UART3_CK		7
+#define PERI_UART2_CK		8
+#define PERI_UART1_CK		9
+#define PERI_UART0_CK		10
+#define PERI_IRDA_CK		11
+#define PERI_NLI_CK		12
+#define PERI_MD_HIF_CK		13
+#define PERI_AP_HIF_CK		14
+#define PERI_MSDC30_3_CK	15
+#define PERI_MSDC30_2_CK	16
+#define PERI_MSDC30_1_CK	17
+#define PERI_MSDC20_2_CK	18
+#define PERI_MSDC20_1_CK	19
+#define PERI_AP_DMA_CK		20
+#define PERI_USB1_CK		21
+#define PERI_USB0_CK		22
+#define PERI_PWM_CK		23
+#define PERI_PWM7_CK		24
+#define PERI_PWM6_CK		25
+#define PERI_PWM5_CK		26
+#define PERI_PWM4_CK		27
+#define PERI_PWM3_CK		28
+#define PERI_PWM2_CK		29
+#define PERI_PWM1_CK		30
+#define PERI_THERM_CK		31
+#define PERI_NFI_CK		32
+#define PERI_USBSLV_CK		33
+#define PERI_USB1_MCU_CK	34
+#define PERI_USB0_MCU_CK	35
+#define PERI_GCPU_CK		36
+#define PERI_FHCTL_CK		37
+#define PERI_SPI1_CK		38
+#define PERI_AUXADC_CK		39
+#define PERI_PERI_PWRAP_CK	40
+#define PERI_I2C6_CK		41
+#define PERI_NR_CLK		42
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 0000000..1fb6295
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST        0
+#define MT8135_INFRA_DRAMC0_A0_RST      1
+#define MT8135_INFRA_CCIF0_RST          2
+#define MT8135_INFRA_APCIRQ_EINT_RST    3
+#define MT8135_INFRA_APXGPT_RST         4
+#define MT8135_INFRA_SCPSYS_RST         5
+#define MT8135_INFRA_CCIF1_RST          6
+#define MT8135_INFRA_PMIC_WRAP_RST      7
+#define MT8135_INFRA_KP_RST             8
+#define MT8135_INFRA_EMI_RST            32
+#define MT8135_INFRA_DRAMC0_RST         34
+#define MT8135_INFRA_SMI_RST            35
+#define MT8135_INFRA_M4U_RST            36
+
+/*  PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST        0
+#define MT8135_PERI_UART1_SW_RST        1
+#define MT8135_PERI_UART2_SW_RST        2
+#define MT8135_PERI_UART3_SW_RST        3
+#define MT8135_PERI_IRDA_SW_RST         4
+#define MT8135_PERI_PTP_SW_RST          5
+#define MT8135_PERI_AP_HIF_SW_RST       6
+#define MT8135_PERI_GPCU_SW_RST         7
+#define MT8135_PERI_MD_HIF_SW_RST       8
+#define MT8135_PERI_NLI_SW_RST          9
+#define MT8135_PERI_AUXADC_SW_RST       10
+#define MT8135_PERI_DMA_SW_RST          11
+#define MT8135_PERI_NFI_SW_RST          14
+#define MT8135_PERI_PWM_SW_RST          15
+#define MT8135_PERI_THERM_SW_RST        16
+#define MT8135_PERI_MSDC0_SW_RST        17
+#define MT8135_PERI_MSDC1_SW_RST        18
+#define MT8135_PERI_MSDC2_SW_RST        19
+#define MT8135_PERI_MSDC3_SW_RST        20
+#define MT8135_PERI_I2C0_SW_RST         22
+#define MT8135_PERI_I2C1_SW_RST         23
+#define MT8135_PERI_I2C2_SW_RST         24
+#define MT8135_PERI_I2C3_SW_RST         25
+#define MT8135_PERI_I2C4_SW_RST         26
+#define MT8135_PERI_I2C5_SW_RST         27
+#define MT8135_PERI_I2C6_SW_RST         28
+#define MT8135_PERI_USB_SW_RST          29
+#define MT8135_PERI_SPI1_SW_RST         33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 03:49:24 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 12:49:24 +0100
Subject: [PATCH 4/5] clk: mediatek: Add basic clocks for Mediatek MT8173.
In-Reply-To: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
References: <1424605765-19751-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424605765-19751-5-git-send-email-s.hauer@pengutronix.de>

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

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

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/mediatek/Makefile                      |   1 +
 drivers/clk/mediatek/clk-mt8173.c                  | 820 +++++++++++++++++++++
 include/dt-bindings/clock/mt8173-clk.h             | 231 ++++++
 .../dt-bindings/reset-controller/mt8173-resets.h   |  63 ++
 4 files changed, 1115 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8173.c
 create mode 100644 include/dt-bindings/clock/mt8173-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 12ce576..8e4b2a4 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,3 +1,4 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 obj-y += clk-mt8135.o
+obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
new file mode 100644
index 0000000..014e552
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+static DEFINE_SPINLOCK(lock);
+
+static struct mtk_fixed_factor root_clk_alias[] __initdata = {
+	FACTOR(TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
+	FACTOR(TOP_DPI_CK, "dpi_ck", "clk_null", 1, 1),
+	FACTOR(TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
+	FACTOR(TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+};
+
+static struct mtk_fixed_factor top_divs[] __initdata = {
+	FACTOR(TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
+	FACTOR(TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
+
+	FACTOR(TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
+	FACTOR(TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
+	FACTOR(TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
+	FACTOR(TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+
+	FACTOR(TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
+	FACTOR(TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
+
+	FACTOR(TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
+	FACTOR(TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
+	FACTOR(TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
+	FACTOR(TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
+	FACTOR(TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+
+	FACTOR(TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
+	FACTOR(TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
+	FACTOR(TOP_FPC_CK, "fpc_ck", "clk26m", 1, 1),
+
+	FACTOR(TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
+	FACTOR(TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
+
+	FACTOR(TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
+	FACTOR(TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
+
+	FACTOR(TOP_DMPLL_CK, "dmpll_ck", "clkph_mck_o", 1, 1),
+	FACTOR(TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+	FACTOR(TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+	FACTOR(TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+	FACTOR(TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
+
+	FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(TOP_MSDCPLL2_CK, "msdcpll2_ck", "msdcpll2", 1, 1),
+	FACTOR(TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
+	FACTOR(TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
+
+	FACTOR(TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
+	FACTOR(TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
+	FACTOR(TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
+	FACTOR(TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
+	FACTOR(TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
+	FACTOR(TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
+	FACTOR(TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
+	FACTOR(TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
+	FACTOR(TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
+	FACTOR(TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
+	FACTOR(TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
+	FACTOR(TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
+	FACTOR(TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
+	FACTOR(TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+
+	FACTOR(TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll_594m", 1, 1),
+	FACTOR(TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
+	FACTOR(TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
+	FACTOR(TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
+	FACTOR(TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
+
+	FACTOR(TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
+	FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
+	FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
+	FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
+	FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
+	FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
+	FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
+	FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
+	FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
+	FACTOR(TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
+	FACTOR(TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
+	FACTOR(TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
+	FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
+	FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
+	FACTOR(TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+
+	FACTOR(TOP_VCODECPLL_CK, "vcodecpll_ck", "vcodecpll", 1, 3),
+	FACTOR(TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
+
+	FACTOR(TOP_VENCPLL_CK, "vencpll_ck", "vencpll", 1, 1),
+	FACTOR(TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
+	FACTOR(TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
+};
+
+static const char *axi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char *mem_parents[] __initconst = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char *ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char *mm_parents[] __initconst = {
+	"clk26m",
+	"vencpll_d2",
+	"main_h364m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2"
+};
+
+static const char *pwm_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char *vdec_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"mmpll_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char *venc_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char *mfg_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"univpll_d3",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll2_d2"
+};
+
+static const char *camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"univpll1_d4"
+};
+
+static const char *uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char *spi_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char *usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char *usb30_parents[] __initconst = {
+	"clk26m",
+	"univpll3_d2",
+	"usb_syspll_125m",
+	"univpll2_d4"
+};
+
+static const char *msdc50_0_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char *msdc50_0_parents[] __initconst = {
+	"clk26m",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"msdcpll_d4",
+	"vencpll_d4",
+	"tvdpll_ck",
+	"univpll_d2",
+	"univpll1_d2",
+	"mmpll_ck",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"msdcpll2_d4"
+};
+
+static const char *msdc30_1_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4"
+};
+
+static const char *msdc30_2_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d2"
+};
+
+static const char *msdc30_3_parents[] __initconst = {
+	"clk26m",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"univpll2_d2",
+	"msdcpll2_d4",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"msdcpll_d4"
+};
+
+static const char *audio_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d4",
+	"syspll4_d4",
+	"syspll1_d16"
+};
+
+static const char *aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d8",
+	"dmpll_d4",
+	"dmpll_d8"
+};
+
+static const char *pmicspi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll3_d4",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d8",
+	"dmpll_d16"
+};
+
+static const char *scp_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char *atb_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"dmpll_d2"
+};
+
+static const char *venc_lt_parents[] __initconst = {
+	"clk26m",
+	"univpll_d3",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"syspll1_d2",
+	"univpll_d5",
+	"vcodecpll_370p5",
+	"dmpll_ck"
+};
+
+static const char *dpi0_parents[] __initconst = {
+	"clk26m",
+	"tvdpll_d2",
+	"tvdpll_d4",
+	"clk26m",
+	"clk26m",
+	"tvdpll_d8",
+	"tvdpll_d16"
+};
+
+static const char *irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"syspll2_d4"
+};
+
+static const char *cci400_parents[] __initconst = {
+	"clk26m",
+	"vencpll_ck",
+	"armca7pll_754m",
+	"armca7pll_502m",
+	"univpll_d2",
+	"syspll_d2",
+	"msdcpll_ck",
+	"dmpll_ck"
+};
+
+static const char *aud_1_parents[] __initconst = {
+	"clk26m",
+	"apll1_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char *aud_2_parents[] __initconst = {
+	"clk26m",
+	"apll2_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char *mem_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m"
+};
+
+static const char *axi_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"dmpll_d2"
+};
+
+static const char *scam_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"univpll2_d4",
+	"dmpll_d4"
+};
+
+static const char *spinfi_ifr_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll3_d4",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll3_d2",
+	"syspll1_d4",
+	"univpll1_d4"
+};
+
+static const char *hdmi_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_dig_cts",
+	"hdmitxpll_d2",
+	"hdmitxpll_d3"
+};
+
+static const char *dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8",
+	"fpc_ck"
+};
+
+static const char *msdc50_2_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char *hdcp_parents[] __initconst = {
+	"clk26m",
+	"syspll4_d2",
+	"syspll3_d4",
+	"univpll2_d4"
+};
+
+static const char *hdcp_24m_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll2_d8"
+};
+
+static const char *rtc_parents[] __initconst = {
+	"clkrtc_int",
+	"clkrtc_ext",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char *i2s0_m_ck_parents[] __initconst = {
+	"apll1_div1",
+	"apll2_div1"
+};
+
+static const char *i2s1_m_ck_parents[] __initconst = {
+	"apll1_div2",
+	"apll2_div2"
+};
+
+static const char *i2s2_m_ck_parents[] __initconst = {
+	"apll1_div3",
+	"apll2_div3"
+};
+
+static const char *i2s3_m_ck_parents[] __initconst = {
+	"apll1_div4",
+	"apll2_div4"
+};
+
+static const char *i2s3_b_ck_parents[] __initconst = {
+	"apll1_div5",
+	"apll2_div5"
+};
+
+static struct mtk_composite top_muxes[] __initdata = {
+	/* CLK_CFG_0 */
+	MUX(TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
+	MUX(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
+	MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
+	MUX_GATE(TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+	MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+	MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
+	MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
+	MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+	MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
+	MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
+	MUX_GATE(TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
+	MUX_GATE(TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
+	MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
+	/* CLK_CFG_4 */
+	MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
+	MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
+	MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
+	MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
+	/* CLK_CFG_5 */
+	MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
+	MUX_GATE(TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
+	MUX_GATE(TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
+	MUX_GATE(TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+	MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
+	MUX_GATE(TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
+	MUX_GATE(TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
+	MUX_GATE(TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
+	MUX_GATE(TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
+	MUX_GATE(TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
+	/* CLK_CFG_12 */
+	MUX_GATE(TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
+	MUX_GATE(TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
+	MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
+	/* CLK_CFG_13 */
+	MUX_GATE(TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
+	MUX_GATE(TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
+	MUX_GATE(TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
+	MUX(TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
+
+	DIV_GATE(TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
+	DIV_GATE(TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
+	DIV_GATE(TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
+	DIV_GATE(TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
+	DIV_GATE(TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
+	DIV_GATE(TOP_APLL1_DIV5, "apll1_div5", "aud_1_sel", 0x12c, 13, 0x12c, 4, 0),
+
+	DIV_GATE(TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
+	DIV_GATE(TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
+	DIV_GATE(TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
+	DIV_GATE(TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
+	DIV_GATE(TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
+	DIV_GATE(TOP_APLL2_DIV5, "apll2_div5", "aud_2_sel", 0x12c, 21, 0x12c, 4, 4),
+
+	MUX(TOP_I2S0_M_CK_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
+	MUX(TOP_I2S1_M_CK_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
+	MUX(TOP_I2S2_M_CK_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
+	MUX(TOP_I2S3_M_CK_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
+	MUX(TOP_I2S3_B_CK_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
+};
+
+static void __init mtk_init_clk_topckgen(void __iomem *top_base,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < ARRAY_SIZE(top_muxes); i++) {
+		struct mtk_composite *mux = &top_muxes[i];
+
+		clk = mtk_clk_register_composite(mux, top_base, &lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					mux->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mux->id] = clk;
+	}
+}
+
+static struct mtk_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 struct mtk_gate infra_clks[] __initdata = {
+	GATE_ICG(INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+	GATE_ICG(INFRA_SMI, "infra_smi", "mm_sel", 1),
+	GATE_ICG(INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
+	GATE_ICG(INFRA_GCE, "infra_gce", "axi_sel", 6),
+	GATE_ICG(INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
+	GATE_ICG(INFRA_M4U, "infra_m4u", "mem_sel", 8),
+	GATE_ICG(INFRA_CPUM, "infra_cpum", "clk_null", 15),
+	GATE_ICG(INFRA_KP, "infra_kp", "axi_sel", 16),
+	GATE_ICG(INFRA_CEC, "infra_cec", "clk26m", 18),
+	GATE_ICG(INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
+	GATE_ICG(INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
+};
+
+static struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#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 struct mtk_gate peri_clks[] __initdata = {
+	/* PERI0 */
+	GATE_PERI0(PERI_NFI, "peri_nfi", "axi_sel", 0),
+	GATE_PERI0(PERI_THERM, "peri_therm", "axi_sel", 1),
+	GATE_PERI0(PERI_PWM1, "peri_pwm1", "axi_sel", 2),
+	GATE_PERI0(PERI_PWM2, "peri_pwm2", "axi_sel", 3),
+	GATE_PERI0(PERI_PWM3, "peri_pwm3", "axi_sel", 4),
+	GATE_PERI0(PERI_PWM4, "peri_pwm4", "axi_sel", 5),
+	GATE_PERI0(PERI_PWM5, "peri_pwm5", "axi_sel", 6),
+	GATE_PERI0(PERI_PWM6, "peri_pwm6", "axi_sel", 7),
+	GATE_PERI0(PERI_PWM7, "peri_pwm7", "axi_sel", 8),
+	GATE_PERI0(PERI_PWM, "peri_pwm", "axi_sel", 9),
+	GATE_PERI0(PERI_USB0, "peri_usb0", "usb20_sel", 10),
+	GATE_PERI0(PERI_USB1, "peri_usb1", "usb20_sel", 11),
+	GATE_PERI0(PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
+	GATE_PERI0(PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
+	GATE_PERI0(PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
+	GATE_PERI0(PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
+	GATE_PERI0(PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
+	GATE_PERI0(PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
+	GATE_PERI0(PERI_IRDA, "peri_irda", "irda_sel", 18),
+	GATE_PERI0(PERI_UART0, "peri_uart0", "uart_sel", 19),
+	GATE_PERI0(PERI_UART1, "peri_uart1", "uart_sel", 20),
+	GATE_PERI0(PERI_UART2, "peri_uart2", "uart_sel", 21),
+	GATE_PERI0(PERI_UART3, "peri_uart3", "uart_sel", 22),
+	GATE_PERI0(PERI_I2C0, "peri_i2c0", "axi_sel", 23),
+	GATE_PERI0(PERI_I2C1, "peri_i2c1", "axi_sel", 24),
+	GATE_PERI0(PERI_I2C2, "peri_i2c2", "axi_sel", 25),
+	GATE_PERI0(PERI_I2C3, "peri_i2c3", "axi_sel", 26),
+	GATE_PERI0(PERI_I2C4, "peri_i2c4", "axi_sel", 27),
+	GATE_PERI0(PERI_AUXADC, "peri_auxadc", "clk26m", 28),
+	GATE_PERI0(PERI_SPI0, "peri_spi0", "spi_sel", 29),
+	GATE_PERI0(PERI_I2C5, "peri_i2c5", "axi_sel", 30),
+	GATE_PERI0(PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
+	/* PERI1 */
+	GATE_PERI1(PERI_SPI, "peri_spi", "spi_sel", 0),
+	GATE_PERI1(PERI_IRRX, "peri_irrx", "spi_sel", 1),
+	GATE_PERI1(PERI_I2C6, "peri_i2c6", "axi_sel", 2),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_init_clk_topckgen(base, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+
+#define MT8173_PLL_FMAX		(3000UL * MHZ)
+
+#define CON0_MT8173_RST_BAR	BIT(24)
+
+#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_MT8173_RST_BAR,			\
+		.fmax = MT8173_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 plls[] = {
+	PLL(APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
+	PLL(APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
+	PLL(APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
+	PLL(APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+	PLL(APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
+	PLL(APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
+	PLL(APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
+	PLL(APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
+	PLL(APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
+	PLL(APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
+	PLL(APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+	PLL(APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls));
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
new file mode 100644
index 0000000..e648b28
--- /dev/null
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8173_H
+#define _DT_BINDINGS_CLK_MT8173_H
+
+/* TOPCKGEN */
+
+#define TOP_CLKPH_MCK_O		1
+#define TOP_DPI_CK		2
+#define TOP_USB_SYSPLL_125M	3
+#define TOP_HDMITX_DIG_CTS	4
+#define TOP_ARMCA7PLL_754M	5
+#define TOP_ARMCA7PLL_502M	6
+#define TOP_MAIN_H546M		7
+#define TOP_MAIN_H364M		8
+#define TOP_MAIN_H218P4M	9
+#define TOP_MAIN_H156M		10
+#define TOP_TVDPLL_445P5M	11
+#define TOP_TVDPLL_594M		12
+#define TOP_UNIV_624M		13
+#define TOP_UNIV_416M		14
+#define TOP_UNIV_249P6M		15
+#define TOP_UNIV_178P3M		16
+#define TOP_UNIV_48M		17
+#define TOP_CLKRTC_EXT		18
+#define TOP_CLKRTC_INT		19
+#define TOP_FPC_CK		20
+#define TOP_HDMITXPLL_D2	21
+#define TOP_HDMITXPLL_D3	22
+#define TOP_ARMCA7PLL_D2	23
+#define TOP_ARMCA7PLL_D3	24
+#define TOP_APLL1_CK		25
+#define TOP_APLL2_CK		26
+#define TOP_DMPLL_CK		27
+#define TOP_DMPLL_D2		28
+#define TOP_DMPLL_D4		29
+#define TOP_DMPLL_D8		30
+#define TOP_DMPLL_D16		31
+#define TOP_LVDSPLL_D2		32
+#define TOP_LVDSPLL_D4		33
+#define TOP_LVDSPLL_D8		34
+#define TOP_MMPLL_CK		35
+#define TOP_MMPLL_D2		36
+#define TOP_MSDCPLL_CK		37
+#define TOP_MSDCPLL_D2		38
+#define TOP_MSDCPLL_D4		39
+#define TOP_MSDCPLL2_CK		40
+#define TOP_MSDCPLL2_D2		41
+#define TOP_MSDCPLL2_D4		42
+#define TOP_SYSPLL_D2		43
+#define TOP_SYSPLL1_D2		44
+#define TOP_SYSPLL1_D4		45
+#define TOP_SYSPLL1_D8		46
+#define TOP_SYSPLL1_D16		47
+#define TOP_SYSPLL_D3		48
+#define TOP_SYSPLL2_D2		49
+#define TOP_SYSPLL2_D4		50
+#define TOP_SYSPLL_D5		51
+#define TOP_SYSPLL3_D2		52
+#define TOP_SYSPLL3_D4		53
+#define TOP_SYSPLL_D7		54
+#define TOP_SYSPLL4_D2		55
+#define TOP_SYSPLL4_D4		56
+#define TOP_TVDPLL_CK		57
+#define TOP_TVDPLL_D2		58
+#define TOP_TVDPLL_D4		59
+#define TOP_TVDPLL_D8		60
+#define TOP_TVDPLL_D16		61
+#define TOP_UNIVPLL_D2		62
+#define TOP_UNIVPLL1_D2		63
+#define TOP_UNIVPLL1_D4		64
+#define TOP_UNIVPLL1_D8		65
+#define TOP_UNIVPLL_D3		66
+#define TOP_UNIVPLL2_D2		67
+#define TOP_UNIVPLL2_D4		68
+#define TOP_UNIVPLL2_D8		69
+#define TOP_UNIVPLL_D5		70
+#define TOP_UNIVPLL3_D2		71
+#define TOP_UNIVPLL3_D4		72
+#define TOP_UNIVPLL3_D8		73
+#define TOP_UNIVPLL_D7		74
+#define TOP_UNIVPLL_D26		75
+#define TOP_UNIVPLL_D52		76
+#define TOP_VCODECPLL_CK	77
+#define TOP_VCODECPLL_370P5	78
+#define TOP_VENCPLL_CK		79
+#define TOP_VENCPLL_D2		80
+#define TOP_VENCPLL_D4		81
+#define TOP_AXI_SEL		82
+#define TOP_MEM_SEL		83
+#define TOP_DDRPHYCFG_SEL	84
+#define TOP_MM_SEL		85
+#define TOP_PWM_SEL		86
+#define TOP_VDEC_SEL		87
+#define TOP_VENC_SEL		88
+#define TOP_MFG_SEL		89
+#define TOP_CAMTG_SEL		90
+#define TOP_UART_SEL		91
+#define TOP_SPI_SEL		92
+#define TOP_USB20_SEL		93
+#define TOP_USB30_SEL		94
+#define TOP_MSDC50_0_H_SEL	95
+#define TOP_MSDC50_0_SEL	96
+#define TOP_MSDC30_1_SEL	97
+#define TOP_MSDC30_2_SEL	98
+#define TOP_MSDC30_3_SEL	99
+#define TOP_AUDIO_SEL		100
+#define TOP_AUD_INTBUS_SEL	101
+#define TOP_PMICSPI_SEL		102
+#define TOP_SCP_SEL		103
+#define TOP_ATB_SEL		104
+#define TOP_VENC_LT_SEL		105
+#define TOP_DPI0_SEL		106
+#define TOP_IRDA_SEL		107
+#define TOP_CCI400_SEL		108
+#define TOP_AUD_1_SEL		109
+#define TOP_AUD_2_SEL		110
+#define TOP_MEM_MFG_IN_SEL	111
+#define TOP_AXI_MFG_IN_SEL	112
+#define TOP_SCAM_SEL		113
+#define TOP_SPINFI_IFR_SEL	114
+#define TOP_HDMI_SEL		115
+#define TOP_DPILVDS_SEL		116
+#define TOP_MSDC50_2_H_SEL	117
+#define TOP_HDCP_SEL		118
+#define TOP_HDCP_24M_SEL	119
+#define TOP_RTC_SEL		120
+#define TOP_APLL1_DIV0		121
+#define TOP_APLL1_DIV1		122
+#define TOP_APLL1_DIV2		123
+#define TOP_APLL1_DIV3		124
+#define TOP_APLL1_DIV4		125
+#define TOP_APLL1_DIV5		126
+#define TOP_APLL2_DIV0		127
+#define TOP_APLL2_DIV1		128
+#define TOP_APLL2_DIV2		129
+#define TOP_APLL2_DIV3		130
+#define TOP_APLL2_DIV4		131
+#define TOP_APLL2_DIV5		132
+#define TOP_I2S0_M_CK_SEL	133
+#define TOP_I2S1_M_CK_SEL	134
+#define TOP_I2S2_M_CK_SEL	135
+#define TOP_I2S3_M_CK_SEL	136
+#define TOP_I2S3_B_CK_SEL	137
+#define TOP_NR_CLK		138
+
+/* APMIXED_SYS */
+
+#define APMIXED_ARMCA15PLL	1
+#define APMIXED_ARMCA7PLL	2
+#define APMIXED_MAINPLL		3
+#define APMIXED_UNIVPLL		4
+#define APMIXED_MMPLL		5
+#define APMIXED_MSDCPLL		6
+#define APMIXED_VENCPLL		7
+#define APMIXED_TVDPLL		8
+#define APMIXED_MPLL		9
+#define APMIXED_VCODECPLL	10
+#define APMIXED_APLL1		11
+#define APMIXED_APLL2		12
+#define APMIXED_LVDSPLL		13
+#define APMIXED_MSDCPLL2	14
+#define APMIXED_NR_CLK		15
+
+/* INFRA_SYS */
+
+#define INFRA_DBGCLK		1
+#define INFRA_SMI		2
+#define INFRA_AUDIO		3
+#define INFRA_GCE		4
+#define INFRA_L2C_SRAM		5
+#define INFRA_M4U		6
+#define INFRA_CPUM		7
+#define INFRA_KP		8
+#define INFRA_CEC		9
+#define INFRA_PMICSPI		10
+#define INFRA_PMICWRAP		11
+#define INFRA_NR_CLK		12
+
+/* PERI_SYS */
+
+#define PERI_NFI		1
+#define PERI_THERM		2
+#define PERI_PWM1		3
+#define PERI_PWM2		4
+#define PERI_PWM3		5
+#define PERI_PWM4		6
+#define PERI_PWM5		7
+#define PERI_PWM6		8
+#define PERI_PWM7		9
+#define PERI_PWM		10
+#define PERI_USB0		11
+#define PERI_USB1		12
+#define PERI_AP_DMA		13
+#define PERI_MSDC30_0		14
+#define PERI_MSDC30_1		15
+#define PERI_MSDC30_2		16
+#define PERI_MSDC30_3		17
+#define PERI_NLI_ARB		18
+#define PERI_IRDA		19
+#define PERI_UART0		20
+#define PERI_UART1		21
+#define PERI_UART2		22
+#define PERI_UART3		23
+#define PERI_I2C0		24
+#define PERI_I2C1		25
+#define PERI_I2C2		26
+#define PERI_I2C3		27
+#define PERI_I2C4		28
+#define PERI_AUXADC		29
+#define PERI_SPI0		30
+#define PERI_I2C5		31
+#define PERI_NFIECC		32
+#define PERI_SPI		33
+#define PERI_IRRX		34
+#define PERI_I2C6		35
+#define PERI_NR_CLK		36
+
+#endif /* _DT_BINDINGS_CLK_MT8173_H */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 0000000..9464b37
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST        0
+#define MT8173_INFRA_DRAMC0_A0_RST      1
+#define MT8173_INFRA_APCIRQ_EINT_RST    3
+#define MT8173_INFRA_APXGPT_RST         4
+#define MT8173_INFRA_SCPSYS_RST         5
+#define MT8173_INFRA_KP_RST             6
+#define MT8173_INFRA_PMIC_WRAP_RST      7
+#define MT8173_INFRA_MPIP_RST           8
+#define MT8173_INFRA_CEC_RST            9
+#define MT8173_INFRA_EMI_RST            32
+#define MT8173_INFRA_DRAMC0_RST         34
+#define MT8173_INFRA_APMIXEDSYS_RST     35
+#define MT8173_INFRA_MIPI_DSI_RST       36
+#define MT8173_INFRA_TRNG_RST           37
+#define MT8173_INFRA_SYSIRQ_RST         38
+#define MT8173_INFRA_MIPI_CSI_RST       39
+#define MT8173_INFRA_GCE_FAXI_RST       40
+#define MT8173_INFRA_MMIOMMURST         47
+
+
+/*  PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST        0
+#define MT8173_PERI_UART1_SW_RST        1
+#define MT8173_PERI_UART2_SW_RST        2
+#define MT8173_PERI_UART3_SW_RST        3
+#define MT8173_PERI_IRRX_SW_RST         4
+#define MT8173_PERI_PWM_SW_RST          8
+#define MT8173_PERI_AUXADC_SW_RST       10
+#define MT8173_PERI_DMA_SW_RST          11
+#define MT8173_PERI_I2C6_SW_RST         13
+#define MT8173_PERI_NFI_SW_RST          14
+#define MT8173_PERI_THERM_SW_RST        16
+#define MT8173_PERI_MSDC2_SW_RST        17
+#define MT8173_PERI_MSDC3_SW_RST        18
+#define MT8173_PERI_MSDC0_SW_RST        19
+#define MT8173_PERI_MSDC1_SW_RST        20
+#define MT8173_PERI_I2C0_SW_RST         22
+#define MT8173_PERI_I2C1_SW_RST         23
+#define MT8173_PERI_I2C2_SW_RST         24
+#define MT8173_PERI_I2C3_SW_RST         25
+#define MT8173_PERI_I2C4_SW_RST         26
+#define MT8173_PERI_HDMI_SW_RST         29
+#define MT8173_PERI_SPI0_SW_RST         33
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 04:02:45 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:02:45 +0100
Subject: [PATCH] Mediatek PMIC wrapper support
Message-ID: <1424606567-29708-1-git-send-email-s.hauer@pengutronix.de>

This series adds support for the PMIC wrapper found on MT8135 and
MT8173 SoCs. This has been sent several times already as part of
different series, this time broken out as a series only containing
the wrapper code. No further compile time dependencies.

Matthias, I assume you can take this one through your tree, right?

Sascha



From s.hauer at pengutronix.de  Sun Feb 22 04:02:47 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:02:47 +0100
Subject: [PATCH 2/2] dt-bindings: ARM: Mediatek: document binding for the PMIC
 wrapper
In-Reply-To: <1424606567-29708-1-git-send-email-s.hauer@pengutronix.de>
References: <1424606567-29708-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424606567-29708-3-git-send-email-s.hauer@pengutronix.de>

This adds documentation for the PMIC wrapper unit found on Mediatek
MT8135 and MT8173 SoCs.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 .../devicetree/bindings/soc/mediatek/pwrap.txt     | 56 ++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/pwrap.txt

diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
new file mode 100644
index 0000000..66cc528
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
@@ -0,0 +1,56 @@
+MediaTek PMIC Wrapper Driver
+
+This document describes the binding for the MediaTek PMIC wrapper.
+
+On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
+SPI. The SPI master interface is not directly visible to the CPU, but
+only through the PMIC wrapper inside the SoC. The communication between
+the SoC and the PMIC can optionally be encrypted. Also a non standard
+Dual IO SPI mode can be used to increase speed.
+
+IP Pairing
+
+on MT8135 the pins of some SoC internal peripherals can be on the PMIC.
+The signals of these pins are routed over the SPI bus using the pwrap
+bridge. In the binding description below the properties needed for bridging
+are marked with "IP Pairing". These are optional on SoCs which do not support
+IP Pairing
+
+Required properties in pwrap device node.
+- compatible: "mediatek,mt8135-pwrap" or "mediatek,mt8173-pwrap"
+- interrupts: IRQ for pwrap in SOC
+- reg-names: Must include the following entries:
+  "pwrap": Main registers base
+  "pwrap-bridge": bridge base (IP Pairing)
+- reg: Must contain an entry for each entry in reg-names.
+- reset-names: Must include the following entries:
+  "pwrap"
+  "pwrap-bridge" (IP Pairing)
+- resets: Must contain an entry for each entry in reset-names.
+- clock-names: Must include the following entries:
+  "spi": SPI bus clock
+  "wrap": Main module clock
+- clocks: Must contain an entry for each entry in clock-names.
+
+Optional properities:
+- pmic: Mediatek PMIC MFD is the child device of pwrap
+  See the following for child node definitions:
+  Documentation/devicetree/bindings/mfd/mt6397.txt
+
+Example:
+	pwrap: pwrap at 1000f000 {
+		compatible = "mediatek,mt8135-pwrap";
+		reg = <0 0x1000f000 0 0x1000>,
+			<0 0x11017000 0 0x1000>;
+		reg-names = "pwrap", "pwrap-bridge";
+		interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+		resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
+				<&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+		reset-names = "pwrap", "pwrap-bridge";
+		clocks = <&clk26m>, <&clk26m>;
+		clock-names = "spi", "wrap";
+
+		pmic {
+			compatible = "mediatek,mt6397";
+		};
+	};
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 04:02:46 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:02:46 +0100
Subject: [PATCH 1/2] soc: mediatek: Add PMIC wrapper for MT8135 and MT8173 SoCs
In-Reply-To: <1424606567-29708-1-git-send-email-s.hauer@pengutronix.de>
References: <1424606567-29708-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424606567-29708-2-git-send-email-s.hauer@pengutronix.de>

From: Flora Fu <flora.fu at mediatek.com>

This adds support for the PMIC wrapper found on MediaTek MT8135 and
MT8173 SoCs.

On MediaTek MT8135, MT8173 and other SoCs the PMIC is connected via
SPI. The SPI master interface is not directly visible to the CPU, but
only through the PMIC wrapper inside the SoC. The communication between
the SoC and the PMIC can optionally be encrypted. Also a non standard
Dual IO SPI mode can be used to increase speed. The MT8135 also supports
a special feature named "IP Pairing". With IP Pairing the pins of some
SoC internal peripherals can be on the PMIC. The signals of these pins
are routed over the SPI bus using the pwrap bridge. Because of these
optional non SPI conform features the PMIC driver is not implemented as
a SPI bus master driver.

Signed-off-by: Flora Fu, MediaTek
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/soc/Kconfig                  |    1 +
 drivers/soc/Makefile                 |    1 +
 drivers/soc/mediatek/Kconfig         |   11 +
 drivers/soc/mediatek/Makefile        |    1 +
 drivers/soc/mediatek/mtk-pmic-wrap.c | 1027 ++++++++++++++++++++++++++++++++++
 5 files changed, 1041 insertions(+)
 create mode 100644 drivers/soc/mediatek/Kconfig
 create mode 100644 drivers/soc/mediatek/Makefile
 create mode 100644 drivers/soc/mediatek/mtk-pmic-wrap.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 76d6bd4..d8bde82f0 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/ti/Kconfig"
 source "drivers/soc/versatile/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 063113d..70042b2 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_SOC_TI)		+= ti/
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
new file mode 100644
index 0000000..b91665a
--- /dev/null
+++ b/drivers/soc/mediatek/Kconfig
@@ -0,0 +1,11 @@
+#
+# MediaTek SoC drivers
+#
+config MTK_PMIC_WRAP
+	tristate "MediaTek PMIC Wrapper Support"
+	depends on ARCH_MEDIATEK
+	select REGMAP
+	help
+	  Say yes here to add support for MediaTek PMIC Wrapper found
+	  on the MT8135 and MT8173 SoCs. The PMIC wrapper is a proprietary
+	  hardware to connect the PMIC.
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
new file mode 100644
index 0000000..ecaf4de
--- /dev/null
+++ b/drivers/soc/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
new file mode 100644
index 0000000..bd1f881
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -0,0 +1,1027 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ */
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define PWRAP_MT8135_BRIDGE_IORD_ARB_EN		0x4
+#define PWRAP_MT8135_BRIDGE_WACS3_EN		0x10
+#define PWRAP_MT8135_BRIDGE_INIT_DONE3		0x14
+#define PWRAP_MT8135_BRIDGE_WACS4_EN		0x24
+#define PWRAP_MT8135_BRIDGE_INIT_DONE4		0x28
+#define PWRAP_MT8135_BRIDGE_INT_EN		0x38
+#define PWRAP_MT8135_BRIDGE_TIMER_EN		0x48
+#define PWRAP_MT8135_BRIDGE_WDT_UNIT		0x50
+#define PWRAP_MT8135_BRIDGE_WDT_SRC_EN		0x54
+
+/* macro for wrapper status */
+#define PWRAP_GET_WACS_RDATA(x)		(((x) >> 0) & 0x0000ffff)
+#define PWRAP_GET_WACS_FSM(x)		(((x) >> 16) & 0x00000007)
+#define PWRAP_GET_WACS_REQ(x)		(((x) >> 19) & 0x00000001)
+#define PWRAP_STATE_SYNC_IDLE0		(1 << 20)
+#define PWRAP_STATE_INIT_DONE0		(1 << 21)
+
+/* macro for WACS FSM */
+#define PWRAP_WACS_FSM_IDLE		0x00
+#define PWRAP_WACS_FSM_REQ		0x02
+#define PWRAP_WACS_FSM_WFDLE		0x04
+#define PWRAP_WACS_FSM_WFVLDCLR		0x06
+#define PWRAP_WACS_INIT_DONE		0x01
+#define PWRAP_WACS_WACS_SYNC_IDLE	0x01
+#define PWRAP_WACS_SYNC_BUSY		0x00
+
+/* macro for device wrapper default value */
+#define PWRAP_DEW_READ_TEST_VAL		0x5aa5
+#define PWRAP_DEW_WRITE_TEST_VAL	0xa55a
+
+/* macro for manual command */
+#define PWRAP_MAN_CMD_SPI_WRITE		(1 << 13)
+#define PWRAP_MAN_CMD_OP_CSH		(0x0 << 8)
+#define PWRAP_MAN_CMD_OP_CSL		(0x1 << 8)
+#define PWRAP_MAN_CMD_OP_CK		(0x2 << 8)
+#define PWRAP_MAN_CMD_OP_OUTS		(0x8 << 8)
+#define PWRAP_MAN_CMD_OP_OUTD		(0x9 << 8)
+#define PWRAP_MAN_CMD_OP_OUTQ		(0xa << 8)
+
+/* macro for slave device wrapper registers */
+#define PWRAP_DEW_BASE			0xbc00
+#define PWRAP_DEW_EVENT_OUT_EN		(PWRAP_DEW_BASE + 0x0)
+#define PWRAP_DEW_DIO_EN		(PWRAP_DEW_BASE + 0x2)
+#define PWRAP_DEW_EVENT_SRC_EN		(PWRAP_DEW_BASE + 0x4)
+#define PWRAP_DEW_EVENT_SRC		(PWRAP_DEW_BASE + 0x6)
+#define PWRAP_DEW_EVENT_FLAG		(PWRAP_DEW_BASE + 0x8)
+#define PWRAP_DEW_READ_TEST		(PWRAP_DEW_BASE + 0xa)
+#define PWRAP_DEW_WRITE_TEST		(PWRAP_DEW_BASE + 0xc)
+#define PWRAP_DEW_CRC_EN		(PWRAP_DEW_BASE + 0xe)
+#define PWRAP_DEW_CRC_VAL		(PWRAP_DEW_BASE + 0x10)
+#define PWRAP_DEW_MON_GRP_SEL		(PWRAP_DEW_BASE + 0x12)
+#define PWRAP_DEW_MON_FLAG_SEL		(PWRAP_DEW_BASE + 0x14)
+#define PWRAP_DEW_EVENT_TEST		(PWRAP_DEW_BASE + 0x16)
+#define PWRAP_DEW_CIPHER_KEY_SEL	(PWRAP_DEW_BASE + 0x18)
+#define PWRAP_DEW_CIPHER_IV_SEL		(PWRAP_DEW_BASE + 0x1a)
+#define PWRAP_DEW_CIPHER_LOAD		(PWRAP_DEW_BASE + 0x1c)
+#define PWRAP_DEW_CIPHER_START		(PWRAP_DEW_BASE + 0x1e)
+#define PWRAP_DEW_CIPHER_RDY		(PWRAP_DEW_BASE + 0x20)
+#define PWRAP_DEW_CIPHER_MODE		(PWRAP_DEW_BASE + 0x22)
+#define PWRAP_DEW_CIPHER_SWRST		(PWRAP_DEW_BASE + 0x24)
+#define PWRAP_MT8173_DEW_CIPHER_IV0	(PWRAP_DEW_BASE + 0x26)
+#define PWRAP_MT8173_DEW_CIPHER_IV1	(PWRAP_DEW_BASE + 0x28)
+#define PWRAP_MT8173_DEW_CIPHER_IV2	(PWRAP_DEW_BASE + 0x2a)
+#define PWRAP_MT8173_DEW_CIPHER_IV3	(PWRAP_DEW_BASE + 0x2c)
+#define PWRAP_MT8173_DEW_CIPHER_IV4	(PWRAP_DEW_BASE + 0x2e)
+#define PWRAP_MT8173_DEW_CIPHER_IV5	(PWRAP_DEW_BASE + 0x30)
+
+/*
+ * FIXME: These shouldn't be here. These registers are on the PMIC,
+ *        so they should be touched in the PMIC driver, not the driver
+ *        granting access to it.
+ */
+#define MT6397_WRP_CKPDN		0x011a
+#define MT6397_WRP_RST_CON		0x0120
+#define MT6397_TOP_CKCON2		0x012a
+#define MT6397_TOP_CKCON3		0x01d4
+
+enum pwrap_regs {
+	PWRAP_MUX_SEL,
+	PWRAP_WRAP_EN,
+	PWRAP_DIO_EN,
+	PWRAP_SIDLY,
+	PWRAP_CSHEXT_WRITE,
+	PWRAP_CSHEXT_READ,
+	PWRAP_CSLEXT_START,
+	PWRAP_CSLEXT_END,
+	PWRAP_STAUPD_PRD,
+	PWRAP_STAUPD_GRPEN,
+	PWRAP_STAUPD_MAN_TRIG,
+	PWRAP_STAUPD_STA,
+	PWRAP_WRAP_STA,
+	PWRAP_HARB_INIT,
+	PWRAP_HARB_HPRIO,
+	PWRAP_HIPRIO_ARB_EN,
+	PWRAP_HARB_STA0,
+	PWRAP_HARB_STA1,
+	PWRAP_MAN_EN,
+	PWRAP_MAN_CMD,
+	PWRAP_MAN_RDATA,
+	PWRAP_MAN_VLDCLR,
+	PWRAP_WACS0_EN,
+	PWRAP_INIT_DONE0,
+	PWRAP_WACS0_CMD,
+	PWRAP_WACS0_RDATA,
+	PWRAP_WACS0_VLDCLR,
+	PWRAP_WACS1_EN,
+	PWRAP_INIT_DONE1,
+	PWRAP_WACS1_CMD,
+	PWRAP_WACS1_RDATA,
+	PWRAP_WACS1_VLDCLR,
+	PWRAP_WACS2_EN,
+	PWRAP_INIT_DONE2,
+	PWRAP_WACS2_CMD,
+	PWRAP_WACS2_RDATA,
+	PWRAP_WACS2_VLDCLR,
+	PWRAP_INT_EN,
+	PWRAP_INT_FLG_RAW,
+	PWRAP_INT_FLG,
+	PWRAP_INT_CLR,
+	PWRAP_SIG_ADR,
+	PWRAP_SIG_MODE,
+	PWRAP_SIG_VALUE,
+	PWRAP_SIG_ERRVAL,
+	PWRAP_CRC_EN,
+	PWRAP_TIMER_EN,
+	PWRAP_TIMER_STA,
+	PWRAP_WDT_UNIT,
+	PWRAP_WDT_SRC_EN,
+	PWRAP_WDT_FLG,
+	PWRAP_DEBUG_INT_SEL,
+	PWRAP_CIPHER_KEY_SEL,
+	PWRAP_CIPHER_IV_SEL,
+	PWRAP_CIPHER_RDY,
+	PWRAP_CIPHER_MODE,
+	PWRAP_CIPHER_SWRST,
+	PWRAP_DCM_EN,
+	PWRAP_DCM_DBC_PRD,
+
+	/* MT8135 only regs */
+	PWRAP_CSHEXT,
+	PWRAP_EVENT_IN_EN,
+	PWRAP_EVENT_DST_EN,
+	PWRAP_RRARB_INIT,
+	PWRAP_RRARB_EN,
+	PWRAP_RRARB_STA0,
+	PWRAP_RRARB_STA1,
+	PWRAP_EVENT_STA,
+	PWRAP_EVENT_STACLR,
+	PWRAP_CIPHER_LOAD,
+	PWRAP_CIPHER_START,
+
+	/* MT8173 only regs */
+	PWRAP_RDDMY,
+	PWRAP_SI_CK_CON,
+	PWRAP_DVFS_ADR0,
+	PWRAP_DVFS_WDATA0,
+	PWRAP_DVFS_ADR1,
+	PWRAP_DVFS_WDATA1,
+	PWRAP_DVFS_ADR2,
+	PWRAP_DVFS_WDATA2,
+	PWRAP_DVFS_ADR3,
+	PWRAP_DVFS_WDATA3,
+	PWRAP_DVFS_ADR4,
+	PWRAP_DVFS_WDATA4,
+	PWRAP_DVFS_ADR5,
+	PWRAP_DVFS_WDATA5,
+	PWRAP_DVFS_ADR6,
+	PWRAP_DVFS_WDATA6,
+	PWRAP_DVFS_ADR7,
+	PWRAP_DVFS_WDATA7,
+	PWRAP_SPMINF_STA,
+	PWRAP_CIPHER_EN,
+};
+
+static int mt8173_regs[] = {
+	[PWRAP_MUX_SEL] =		0x0,
+	[PWRAP_WRAP_EN] =		0x4,
+	[PWRAP_DIO_EN] =		0x8,
+	[PWRAP_SIDLY] =			0xc,
+	[PWRAP_RDDMY] =			0x10,
+	[PWRAP_SI_CK_CON] =		0x14,
+	[PWRAP_CSHEXT_WRITE] =		0x18,
+	[PWRAP_CSHEXT_READ] =		0x1c,
+	[PWRAP_CSLEXT_START] =		0x20,
+	[PWRAP_CSLEXT_END] =		0x24,
+	[PWRAP_STAUPD_PRD] =		0x28,
+	[PWRAP_STAUPD_GRPEN] =		0x2c,
+	[PWRAP_STAUPD_MAN_TRIG] =	0x40,
+	[PWRAP_STAUPD_STA] =		0x44,
+	[PWRAP_WRAP_STA] =		0x48,
+	[PWRAP_HARB_INIT] =		0x4c,
+	[PWRAP_HARB_HPRIO] =		0x50,
+	[PWRAP_HIPRIO_ARB_EN] =		0x54,
+	[PWRAP_HARB_STA0] =		0x58,
+	[PWRAP_HARB_STA1] =		0x5c,
+	[PWRAP_MAN_EN] =		0x60,
+	[PWRAP_MAN_CMD] =		0x64,
+	[PWRAP_MAN_RDATA] =		0x68,
+	[PWRAP_MAN_VLDCLR] =		0x6c,
+	[PWRAP_WACS0_EN] =		0x70,
+	[PWRAP_INIT_DONE0] =		0x74,
+	[PWRAP_WACS0_CMD] =		0x78,
+	[PWRAP_WACS0_RDATA] =		0x7c,
+	[PWRAP_WACS0_VLDCLR] =		0x80,
+	[PWRAP_WACS1_EN] =		0x84,
+	[PWRAP_INIT_DONE1] =		0x88,
+	[PWRAP_WACS1_CMD] =		0x8c,
+	[PWRAP_WACS1_RDATA] =		0x90,
+	[PWRAP_WACS1_VLDCLR] =		0x94,
+	[PWRAP_WACS2_EN] =		0x98,
+	[PWRAP_INIT_DONE2] =		0x9c,
+	[PWRAP_WACS2_CMD] =		0xa0,
+	[PWRAP_WACS2_RDATA] =		0xa4,
+	[PWRAP_WACS2_VLDCLR] =		0xa8,
+	[PWRAP_INT_EN] =		0xac,
+	[PWRAP_INT_FLG_RAW] =		0xb0,
+	[PWRAP_INT_FLG] =		0xb4,
+	[PWRAP_INT_CLR] =		0xb8,
+	[PWRAP_SIG_ADR] =		0xbc,
+	[PWRAP_SIG_MODE] =		0xc0,
+	[PWRAP_SIG_VALUE] =		0xc4,
+	[PWRAP_SIG_ERRVAL] =		0xc8,
+	[PWRAP_CRC_EN] =		0xcc,
+	[PWRAP_TIMER_EN] =		0xd0,
+	[PWRAP_TIMER_STA] =		0xd4,
+	[PWRAP_WDT_UNIT] =		0xd8,
+	[PWRAP_WDT_SRC_EN] =		0xdc,
+	[PWRAP_WDT_FLG] =		0xe0,
+	[PWRAP_DEBUG_INT_SEL] =		0xe4,
+	[PWRAP_DVFS_ADR0] =		0xe8,
+	[PWRAP_DVFS_WDATA0] =		0xec,
+	[PWRAP_DVFS_ADR1] =		0xf0,
+	[PWRAP_DVFS_WDATA1] =		0xf4,
+	[PWRAP_DVFS_ADR2] =		0xf8,
+	[PWRAP_DVFS_WDATA2] =		0xfc,
+	[PWRAP_DVFS_ADR3] =		0x100,
+	[PWRAP_DVFS_WDATA3] =		0x104,
+	[PWRAP_DVFS_ADR4] =		0x108,
+	[PWRAP_DVFS_WDATA4] =		0x10c,
+	[PWRAP_DVFS_ADR5] =		0x110,
+	[PWRAP_DVFS_WDATA5] =		0x114,
+	[PWRAP_DVFS_ADR6] =		0x118,
+	[PWRAP_DVFS_WDATA6] =		0x11c,
+	[PWRAP_DVFS_ADR7] =		0x120,
+	[PWRAP_DVFS_WDATA7] =		0x124,
+	[PWRAP_SPMINF_STA] =		0x128,
+	[PWRAP_CIPHER_KEY_SEL] =	0x12c,
+	[PWRAP_CIPHER_IV_SEL] =		0x130,
+	[PWRAP_CIPHER_EN] =		0x134,
+	[PWRAP_CIPHER_RDY] =		0x138,
+	[PWRAP_CIPHER_MODE] =		0x13c,
+	[PWRAP_CIPHER_SWRST] =		0x140,
+	[PWRAP_DCM_EN] =		0x144,
+	[PWRAP_DCM_DBC_PRD] =		0x148,
+};
+
+static int mt8135_regs[] = {
+	[PWRAP_MUX_SEL] =		0x0,
+	[PWRAP_WRAP_EN] =		0x4,
+	[PWRAP_DIO_EN] =		0x8,
+	[PWRAP_SIDLY] =			0xc,
+	[PWRAP_CSHEXT] =		0x10,
+	[PWRAP_CSHEXT_WRITE] =		0x14,
+	[PWRAP_CSHEXT_READ] =		0x18,
+	[PWRAP_CSLEXT_START] =		0x1c,
+	[PWRAP_CSLEXT_END] =		0x20,
+	[PWRAP_STAUPD_PRD] =		0x24,
+	[PWRAP_STAUPD_GRPEN] =		0x28,
+	[PWRAP_STAUPD_MAN_TRIG] =	0x2c,
+	[PWRAP_STAUPD_STA] =		0x30,
+	[PWRAP_EVENT_IN_EN] =		0x34,
+	[PWRAP_EVENT_DST_EN] =		0x38,
+	[PWRAP_WRAP_STA] =		0x3c,
+	[PWRAP_RRARB_INIT] =		0x40,
+	[PWRAP_RRARB_EN] =		0x44,
+	[PWRAP_RRARB_STA0] =		0x48,
+	[PWRAP_RRARB_STA1] =		0x4c,
+	[PWRAP_HARB_INIT] =		0x50,
+	[PWRAP_HARB_HPRIO] =		0x54,
+	[PWRAP_HIPRIO_ARB_EN] =		0x58,
+	[PWRAP_HARB_STA0] =		0x5c,
+	[PWRAP_HARB_STA1] =		0x60,
+	[PWRAP_MAN_EN] =		0x64,
+	[PWRAP_MAN_CMD] =		0x68,
+	[PWRAP_MAN_RDATA] =		0x6c,
+	[PWRAP_MAN_VLDCLR] =		0x70,
+	[PWRAP_WACS0_EN] =		0x74,
+	[PWRAP_INIT_DONE0] =		0x78,
+	[PWRAP_WACS0_CMD] =		0x7c,
+	[PWRAP_WACS0_RDATA] =		0x80,
+	[PWRAP_WACS0_VLDCLR] =		0x84,
+	[PWRAP_WACS1_EN] =		0x88,
+	[PWRAP_INIT_DONE1] =		0x8c,
+	[PWRAP_WACS1_CMD] =		0x90,
+	[PWRAP_WACS1_RDATA] =		0x94,
+	[PWRAP_WACS1_VLDCLR] =		0x98,
+	[PWRAP_WACS2_EN] =		0x9c,
+	[PWRAP_INIT_DONE2] =		0xa0,
+	[PWRAP_WACS2_CMD] =		0xa4,
+	[PWRAP_WACS2_RDATA] =		0xa8,
+	[PWRAP_WACS2_VLDCLR] =		0xac,
+	[PWRAP_INT_EN] =		0xb0,
+	[PWRAP_INT_FLG_RAW] =		0xb4,
+	[PWRAP_INT_FLG] =		0xb8,
+	[PWRAP_INT_CLR] =		0xbc,
+	[PWRAP_SIG_ADR] =		0xc0,
+	[PWRAP_SIG_MODE] =		0xc4,
+	[PWRAP_SIG_VALUE] =		0xc8,
+	[PWRAP_SIG_ERRVAL] =		0xcc,
+	[PWRAP_CRC_EN] =		0xd0,
+	[PWRAP_EVENT_STA] =		0xd4,
+	[PWRAP_EVENT_STACLR] =		0xd8,
+	[PWRAP_TIMER_EN] =		0xdc,
+	[PWRAP_TIMER_STA] =		0xe0,
+	[PWRAP_WDT_UNIT] =		0xe4,
+	[PWRAP_WDT_SRC_EN] =		0xe8,
+	[PWRAP_WDT_FLG] =		0xec,
+	[PWRAP_DEBUG_INT_SEL] =		0xf0,
+	[PWRAP_CIPHER_KEY_SEL] =	0x134,
+	[PWRAP_CIPHER_IV_SEL] =		0x138,
+	[PWRAP_CIPHER_LOAD] =		0x13c,
+	[PWRAP_CIPHER_START] =		0x140,
+	[PWRAP_CIPHER_RDY] =		0x144,
+	[PWRAP_CIPHER_MODE] =		0x148,
+	[PWRAP_CIPHER_SWRST] =		0x14c,
+	[PWRAP_DCM_EN] =		0x15c,
+	[PWRAP_DCM_DBC_PRD] =		0x160,
+};
+
+enum pwrap_type {
+	PWRAP_MT8135,
+	PWRAP_MT8173,
+};
+
+struct pmic_wrapper_type {
+	int *regs;
+	enum pwrap_type type;
+	u32 arb_en_all;
+};
+
+static struct pmic_wrapper_type pwrap_mt8135 = {
+	.regs = mt8135_regs,
+	.type = PWRAP_MT8135,
+	.arb_en_all = 0x1ff,
+};
+
+static struct pmic_wrapper_type pwrap_mt8173 = {
+	.regs = mt8173_regs,
+	.type = PWRAP_MT8173,
+	.arb_en_all = 0x3f,
+};
+
+struct pmic_wrapper {
+	struct device *dev;
+	void __iomem *base;
+	struct regmap *regmap;
+	int *regs;
+	enum pwrap_type type;
+	u32 arb_en_all;
+	struct clk *clk_spi;
+	struct clk *clk_wrap;
+	struct reset_control *rstc;
+
+	struct reset_control *rstc_bridge;
+	void __iomem *bridge_base;
+};
+
+static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
+{
+	return wrp->type == PWRAP_MT8135;
+}
+
+static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp)
+{
+	return wrp->type == PWRAP_MT8173;
+}
+
+static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg)
+{
+	return readl(wrp->base + wrp->regs[reg]);
+}
+
+static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg)
+{
+	writel(val, wrp->base + wrp->regs[reg]);
+}
+
+static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp)
+{
+	u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+	return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE;
+}
+
+static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp)
+{
+	u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+	return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR;
+}
+
+static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp)
+{
+	return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0;
+}
+
+static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp)
+{
+	u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+	return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) &&
+		(val & PWRAP_STATE_SYNC_IDLE0);
+}
+
+static int pwrap_wait_for_state(struct pmic_wrapper *wrp,
+		bool (*fp)(struct pmic_wrapper *))
+{
+	unsigned long timeout;
+
+	timeout = jiffies + usecs_to_jiffies(255);
+
+	do {
+		if (time_after(jiffies, timeout))
+			return fp(wrp) ? 0 : -ETIMEDOUT;
+		if (fp(wrp))
+			return 0;
+	} while (1);
+}
+
+static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
+{
+	int ret;
+	u32 val;
+
+	val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+	if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+		pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+	ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+	if (ret)
+		return ret;
+
+	pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata,
+			PWRAP_WACS2_CMD);
+
+	return 0;
+}
+
+static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+{
+	int ret;
+	u32 val;
+
+	val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+	if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+		pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+	ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+	if (ret)
+		return ret;
+
+	pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD);
+
+	ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+	if (ret)
+		return ret;
+
+	*rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA));
+
+	return 0;
+}
+
+static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
+{
+	return pwrap_read(context, adr, rdata);
+}
+
+static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
+{
+	return pwrap_write(context, adr, wdata);
+}
+
+static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
+{
+	int ret, i;
+
+	pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN);
+	pwrap_writel(wrp, 0, PWRAP_WRAP_EN);
+	pwrap_writel(wrp, 1, PWRAP_MUX_SEL);
+	pwrap_writel(wrp, 1, PWRAP_MAN_EN);
+	pwrap_writel(wrp, 0, PWRAP_DIO_EN);
+
+	pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL,
+			PWRAP_MAN_CMD);
+	pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+			PWRAP_MAN_CMD);
+	pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH,
+			PWRAP_MAN_CMD);
+
+	for (i = 0; i < 4; i++)
+		pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+				PWRAP_MAN_CMD);
+
+	ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
+	if (ret) {
+		dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	pwrap_writel(wrp, 0, PWRAP_MAN_EN);
+	pwrap_writel(wrp, 0, PWRAP_MUX_SEL);
+
+	return 0;
+}
+
+/*
+ * pwrap_init_sidly - configure serial input delay
+ *
+ * This configures the serial input delay. We can configure 0, 2, 4 or 6ns
+ * delay. Do a read test with all possible values and chose the best delay.
+ */
+static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+{
+	u32 rdata;
+	u32 i;
+	u32 pass = 0;
+	signed char dly[16] = {
+		-1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
+	};
+
+	for (i = 0; i < 4; i++) {
+		pwrap_writel(wrp, i, PWRAP_SIDLY);
+		pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+		printk("%s: 0x%04x\n", __func__, rdata);
+		if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+			dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+			pass |= 1 << i;
+		}
+	}
+
+	if (dly[pass] < 0) {
+		dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n",
+				pass);
+		return -EIO;
+	}
+
+	pwrap_writel(wrp, dly[pass], PWRAP_SIDLY);
+
+	return 0;
+}
+
+static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
+{
+	u32 wdata;
+	u32 rdata;
+	unsigned long rate_spi;
+	int ck_mhz;
+
+	rate_spi = clk_get_rate(wrp->clk_spi);
+
+	if (rate_spi > 26000000)
+		ck_mhz = 26;
+	else if (rate_spi > 18)
+		ck_mhz = 18;
+	else
+		ck_mhz = 0;
+
+	pwrap_read(wrp, MT6397_TOP_CKCON2, &rdata);
+	wdata = rdata & ~(0x3 << 10);
+
+	if (ck_mhz == 18)
+		wdata |= 0x1 << 10;
+
+	if (pwrap_write(wrp, MT6397_TOP_CKCON2, wdata))  {
+		dev_err(wrp->dev, "Enable PMIC TOP_CKCON2 fail\n");
+		return -EFAULT;
+	}
+
+	switch (ck_mhz) {
+	case 18:
+		if (pwrap_is_mt8135(wrp))
+			pwrap_writel(wrp, 0xc, PWRAP_CSHEXT);
+		pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE);
+		pwrap_writel(wrp, 0xc, PWRAP_CSHEXT_READ);
+		pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+		pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+		break;
+	case 26:
+		if (pwrap_is_mt8135(wrp))
+			pwrap_writel(wrp, 0x4, PWRAP_CSHEXT);
+		pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
+		pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+		pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+		pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+		break;
+	case 0:
+		if (pwrap_is_mt8135(wrp))
+			pwrap_writel(wrp, 0xf, PWRAP_CSHEXT);
+		pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_WRITE);
+		pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_READ);
+		pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_START);
+		pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_END);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Enable PMIC side reg clock */
+	if (pwrap_write(wrp, MT6397_WRP_CKPDN, 0) ||
+			pwrap_write(wrp, MT6397_WRP_RST_CON, 0)) {
+		dev_err(wrp->dev, "Enable PMIC fail\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
+{
+	return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
+}
+
+static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+{
+	u32 rdata;
+	int ret;
+
+	ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
+	if (ret)
+		return 0;
+
+	return rdata == 1;
+}
+
+static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+{
+	int ret;
+	u32 rdata;
+
+	pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
+	pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST);
+	pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL);
+	pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL);
+
+	if (pwrap_is_mt8135(wrp)) {
+		pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD);
+		pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
+	} else {
+		pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
+	}
+
+	/* Config cipher mode @PMIC */
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
+
+	/* wait for cipher data ready at AP */
+	ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+	if (ret) {
+		dev_err(wrp->dev, "cipher data ready at AP fail, ret=%d\n", ret);
+		return ret;
+	}
+
+	/* wait for cipher data ready at PMIC */
+	ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready);
+	if (ret) {
+		dev_err(wrp->dev, "timeout waiting for cipher data ready at PMIC\n");
+		return ret;
+	}
+
+	/* wait for cipher mode idle */
+	pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
+	ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+	if (ret) {
+		dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
+		return ret;
+	}
+
+	pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
+
+	/* Write Test */
+	if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
+	    pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
+			(rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
+		dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int pwrap_init(struct pmic_wrapper *wrp)
+{
+	int ret;
+	u32 rdata;
+
+	reset_control_reset(wrp->rstc);
+	if (wrp->rstc_bridge)
+		reset_control_reset(wrp->rstc_bridge);
+
+	if (pwrap_is_mt8173(wrp)) {
+		/* Enable DCM */
+		pwrap_writel(wrp, 3, PWRAP_DCM_EN);
+		pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+	}
+
+	/* Reset SPI slave */
+	ret = pwrap_reset_spislave(wrp);
+	if (ret)
+		return ret;
+
+	pwrap_writel(wrp, 1, PWRAP_WRAP_EN);
+
+	pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+	pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
+
+	ret = pwrap_init_reg_clock(wrp);
+	if (ret)
+		return ret;
+
+	/* Setup serial input delay */
+	ret = pwrap_init_sidly(wrp);
+	if (ret)
+		return ret;
+
+	if (pwrap_is_mt8173(wrp)) {
+		/*
+		 * Enable PMIC
+		 * (May not be necessary, depending on S/W partition)
+		 * set dewrap clock bit and clear dewrap reset bit
+		 */
+		if (pwrap_write(wrp, MT6397_WRP_CKPDN, 0) ||
+			pwrap_write(wrp, MT6397_WRP_RST_CON, 0)) {
+			dev_err(wrp->dev, "Enable PMIC fail\n");
+			return -EFAULT;
+		}
+	}
+
+	/* Enable dual IO mode */
+	pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
+
+	/* Check IDLE & INIT_DONE in advance */
+	ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+	if (ret) {
+		dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+
+	/* Read Test */
+	pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+	if (rdata != PWRAP_DEW_READ_TEST_VAL) {
+		dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n",
+				PWRAP_DEW_READ_TEST_VAL, rdata);
+		return -EFAULT;
+	}
+
+	/* Enable encryption */
+	ret = pwrap_init_cipher(wrp);
+	if (ret)
+		return ret;
+
+	/* Signature checking - using CRC */
+	if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
+		return -EFAULT;
+
+	pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
+	pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
+	pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
+	pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+	if (pwrap_is_mt8135(wrp))
+		pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN);
+
+	pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN);
+	pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN);
+	pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
+	pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
+	pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
+	pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+	pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+	pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+	pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
+
+	/* switch event pin from usbdl mode to normal mode @ MT6397 */
+	if (pwrap_read(wrp, MT6397_TOP_CKCON3, &rdata) ||
+			pwrap_write(wrp, MT6397_TOP_CKCON3, (rdata & 0x0007))) {
+		dev_err(wrp->dev, "switch event pin fail\n");
+		return -EFAULT;
+	}
+
+	if (pwrap_is_mt8135(wrp)) {
+		/* enable pwrap events and pwrap bridge in AP side */
+		pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN);
+		pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN);
+		writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN);
+		writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN);
+		writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN);
+		writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT);
+		writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN);
+		writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN);
+		writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
+
+		/* enable PMIC event out and sources */
+		if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+				pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+			dev_err(wrp->dev, "enable dewrap fail\n");
+			return -EFAULT;
+		}
+	} else {
+		/* PMIC_DEWRAP enables */
+		if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+				pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+			dev_err(wrp->dev, "enable dewrap fail\n");
+			return -EFAULT;
+		}
+	}
+
+	/* Setup the init done registers */
+	pwrap_writel(wrp, 1, PWRAP_INIT_DONE2);
+	pwrap_writel(wrp, 1, PWRAP_INIT_DONE0);
+	pwrap_writel(wrp, 1, PWRAP_INIT_DONE1);
+
+	if (pwrap_is_mt8135(wrp)) {
+		writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3);
+		writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4);
+	}
+
+	return 0;
+}
+
+static irqreturn_t pwrap_interrupt(int irqno, void *dev_id)
+{
+	u32 rdata;
+	struct pmic_wrapper *wrp = dev_id;
+
+	rdata = pwrap_readl(wrp, PWRAP_INT_FLG);
+
+	dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata);
+
+	pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR);
+
+	return IRQ_HANDLED;
+}
+
+static const struct regmap_config pwrap_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 16,
+	.reg_stride = 2,
+	.reg_read = pwrap_regmap_read,
+	.reg_write = pwrap_regmap_write,
+	.max_register = 0xffff,
+};
+
+static struct of_device_id of_pwrap_match_tbl[] = {
+	{
+		.compatible = "mediatek,mt8135-pwrap",
+		.data = &pwrap_mt8135,
+	}, {
+		.compatible = "mediatek,mt8173-pwrap",
+		.data = &pwrap_mt8173,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
+
+static int pwrap_probe(struct platform_device *pdev)
+{
+	int ret, irq;
+	struct pmic_wrapper *wrp;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+		of_match_device(of_pwrap_match_tbl, &pdev->dev);
+	const struct pmic_wrapper_type *type;
+	struct resource *res;
+
+	wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL);
+	if (!wrp)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, wrp);
+
+	type = of_id->data;
+	wrp->regs = type->regs;
+	wrp->type = type->type;
+	wrp->arb_en_all = type->arb_en_all;
+	wrp->dev = &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap");
+	wrp->base = devm_ioremap_resource(wrp->dev, res);
+	if (IS_ERR(wrp->base))
+		return PTR_ERR(wrp->base);
+
+	wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap");
+	if (IS_ERR(wrp->rstc)) {
+		ret = PTR_ERR(wrp->rstc);
+		dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret);
+		return ret;
+	}
+
+	if (pwrap_is_mt8135(wrp)) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+				"pwrap-bridge");
+		wrp->bridge_base = devm_ioremap_resource(wrp->dev, res);
+		if (IS_ERR(wrp->bridge_base))
+			return PTR_ERR(wrp->bridge_base);
+
+		wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge");
+		if (IS_ERR(wrp->rstc_bridge)) {
+			ret = PTR_ERR(wrp->rstc_bridge);
+			dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret);
+			return ret;
+		}
+	}
+
+	wrp->clk_spi = devm_clk_get(wrp->dev, "spi");
+	if (IS_ERR(wrp->clk_spi)) {
+		dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi));
+		return PTR_ERR(wrp->clk_spi);
+	}
+
+	wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap");
+	if (IS_ERR(wrp->clk_wrap)) {
+		dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap));
+		return PTR_ERR(wrp->clk_wrap);
+	}
+
+	ret = clk_prepare_enable(wrp->clk_spi);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(wrp->clk_wrap);
+	if (ret)
+		goto err_out1;
+
+	/* Enable internal dynamic clock */
+	pwrap_writel(wrp, 1, PWRAP_DCM_EN);
+	pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+
+	/*
+	 * The PMIC could already be initialized by the bootloader.
+	 * Skip initialization here in this case.
+	 */
+	if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) {
+		ret = pwrap_init(wrp);
+		if (ret) {
+			dev_dbg(wrp->dev, "init failed with %d\n", ret);
+			goto err_out2;
+		}
+	}
+
+	if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) {
+		dev_dbg(wrp->dev, "initialization isn't finished\n");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
+			"mt-pmic-pwrap", wrp);
+	if (ret)
+		goto err_out2;
+
+	wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config);
+	if (IS_ERR(wrp->regmap))
+		return PTR_ERR(wrp->regmap);
+
+	ret = of_platform_populate(np, NULL, NULL, wrp->dev);
+	if (ret) {
+		dev_dbg(wrp->dev, "failed to create child devices at %s\n",
+				np->full_name);
+		goto err_out2;
+	}
+
+	return 0;
+
+err_out2:
+	clk_disable_unprepare(wrp->clk_wrap);
+err_out1:
+	clk_disable_unprepare(wrp->clk_spi);
+
+	return ret;
+}
+
+static struct platform_driver pwrap_drv = {
+	.driver = {
+		.name = "mt-pmic-pwrap",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(of_pwrap_match_tbl),
+	},
+	.probe = pwrap_probe,
+};
+
+module_platform_driver(pwrap_drv);
+
+MODULE_AUTHOR("Flora Fu, MediaTek");
+MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 04:15:28 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:15:28 +0100
Subject: [PATCH] MFD: Mediatek MT6397 base support
Message-ID: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>

This adds support for the Mediatek MT6397 PMIC. It adds the register defines,
registration of child devices and interrupt support.

Lee, this series contains only the MFD parts without further dependencies. Please
take through your tree.

Sascha



From s.hauer at pengutronix.de  Sun Feb 22 04:15:29 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:15:29 +0100
Subject: [PATCH 1/2] mfd: Add support for the MediaTek MT6397 PMIC
In-Reply-To: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
References: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424607330-1829-2-git-send-email-s.hauer@pengutronix.de>

From: Flora Fu <flora.fu at mediatek.com>

This adds support for the MediaTek MT6397 PMIC. This is a
multifunction device with the following sub modules:

- Regulator
- RTC
- Audio codec
- GPIO
- Clock

It is interfaced to the host controller using SPI interface by a proprietary
hardware called PMIC wrapper or pwrap. MT6397 MFD is a child device of the
pwrap.

Signed-off-by: Flora Fu, MediaTek
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Cc: Samuel Ortiz <sameo at linux.intel.com>
Cc: Lee Jones <lee.jones at linaro.org>
---
 drivers/mfd/Kconfig                  |  10 +
 drivers/mfd/Makefile                 |   1 +
 drivers/mfd/mt6397-core.c            | 223 +++++++++++++++++++++
 include/linux/mfd/mt6397/core.h      |  64 +++++++
 include/linux/mfd/mt6397/registers.h | 362 +++++++++++++++++++++++++++++++++++
 5 files changed, 660 insertions(+)
 create mode 100644 drivers/mfd/mt6397-core.c
 create mode 100644 include/linux/mfd/mt6397/core.h
 create mode 100644 include/linux/mfd/mt6397/registers.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2e6b731..7782e95 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -489,6 +489,16 @@ config MFD_MAX8998
 	  additional drivers must be enabled in order to use the functionality
 	  of the device.
 
+config MFD_MT6397
+	tristate "MediaTek MT6397 PMIC Support"
+	select MFD_CORE
+	select IRQ_DOMAIN
+	help
+	  Say yes here to add support for MediaTek MT6397 PMIC. This is
+	  a Power Management IC. This driver provides common support for
+	  accessing the device; additional drivers must be enabled in order
+	  to use the functionality of the device.
+
 config MFD_MENF21BMC
 	tristate "MEN 14F021P00 Board Management Controller Support"
 	depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 53467e2..329d4ed 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -179,3 +179,4 @@ obj-$(CONFIG_MFD_DLN2)		+= dln2.o
 
 intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
+obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
new file mode 100644
index 0000000..b61c4eb
--- /dev/null
+++ b/drivers/mfd/mt6397-core.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+
+static const struct mfd_cell mt6397_devs[] = {
+	{
+		.name = "mt6397-rtc",
+		.of_compatible = "mediatek,mt6397-rtc",
+	}, {
+		.name = "mt6397-regulator",
+		.of_compatible = "mediatek,mt6397-regulator",
+	}, {
+		.name = "mt6397-codec",
+		.of_compatible = "mediatek,mt6397-codec",
+	}, {
+		.name = "mt6397-clk",
+		.of_compatible = "mediatek,mt6397-clk",
+	},
+};
+
+static void mt6397_irq_lock(struct irq_data *data)
+{
+	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+	mutex_lock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_sync_unlock(struct irq_data *data)
+{
+	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+	regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
+	regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
+
+	mutex_unlock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_disable(struct irq_data *data)
+{
+	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+	int shift = data->hwirq & 0xf;
+	int reg = data->hwirq >> 4;
+
+	mt6397->irq_masks_cur[reg] &= ~BIT(shift);
+}
+
+static void mt6397_irq_enable(struct irq_data *data)
+{
+	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+	int shift = data->hwirq & 0xf;
+	int reg = data->hwirq >> 4;
+
+	mt6397->irq_masks_cur[reg] |= BIT(shift);
+}
+
+static struct irq_chip mt6397_irq_chip = {
+	.name = "mt6397-irq",
+	.irq_bus_lock = mt6397_irq_lock,
+	.irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+	.irq_enable = mt6397_irq_enable,
+	.irq_disable = mt6397_irq_disable,
+};
+
+static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
+		int irqbase)
+{
+	unsigned int status;
+	int i, irq, ret;
+
+	ret = regmap_read(mt6397->regmap, reg, &status);
+	if (ret) {
+		dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
+		return;
+	}
+
+	for (i = 0; i < 16; i++) {
+		if (status & BIT(i)) {
+			irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
+			if (irq)
+				handle_nested_irq(irq);
+		}
+	}
+
+	regmap_write(mt6397->regmap, reg, status);
+}
+
+static irqreturn_t mt6397_irq_thread(int irq, void *data)
+{
+	struct mt6397_chip *mt6397 = data;
+
+	mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
+	mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
+
+	return IRQ_HANDLED;
+}
+
+static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+					irq_hw_number_t hw)
+{
+	struct mt6397_chip *mt6397 = d->host_data;
+
+	irq_set_chip_data(irq, mt6397);
+	irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
+	irq_set_nested_thread(irq, 1);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops mt6397_irq_domain_ops = {
+	.map = mt6397_irq_domain_map,
+};
+
+static int mt6397_irq_init(struct mt6397_chip *mt6397)
+{
+	int ret;
+
+	mutex_init(&mt6397->irqlock);
+
+	/* Mask all interrupt sources */
+	regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
+	regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
+
+	mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
+		MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
+	if (!mt6397->irq_domain) {
+		dev_err(mt6397->dev, "could not create irq domain\n");
+		return -ENOMEM;
+	}
+
+	ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
+		mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
+	if (ret) {
+		dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
+			mt6397->irq, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt6397_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct mt6397_chip *mt6397;
+
+	mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
+	if (!mt6397)
+		return -ENOMEM;
+
+	mt6397->dev = &pdev->dev;
+	/*
+	 * mt6397 MFD is child device of soc pmic wrapper.
+	 * Regmap is set from its parent.
+	 */
+	mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!mt6397->regmap)
+		return -ENODEV;
+
+	platform_set_drvdata(pdev, mt6397);
+
+	mt6397->irq = platform_get_irq(pdev, 0);
+	if (mt6397->irq > 0) {
+		ret = mt6397_irq_init(mt6397);
+		if (ret)
+			return ret;
+	}
+
+	ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
+			ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
+	if (ret)
+		dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
+
+	return ret;
+}
+
+static int mt6397_remove(struct platform_device *pdev)
+{
+	mfd_remove_devices(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id mt6397_of_match[] = {
+	{ .compatible = "mediatek,mt6397" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt6397_of_match);
+
+static struct platform_driver mt6397_driver = {
+	.probe = mt6397_probe,
+	.remove = mt6397_remove,
+	.driver = {
+		.name = "mt6397",
+		.of_match_table = of_match_ptr(mt6397_of_match),
+	},
+};
+
+module_platform_driver(mt6397_driver);
+
+MODULE_AUTHOR("Flora Fu, MediaTek");
+MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt6397");
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
new file mode 100644
index 0000000..cf5265b
--- /dev/null
+++ b/include/linux/mfd/mt6397/core.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_MT6397_CORE_H__
+#define __MFD_MT6397_CORE_H__
+
+enum mt6397_irq_numbers {
+	MT6397_IRQ_SPKL_AB = 0,
+	MT6397_IRQ_SPKR_AB,
+	MT6397_IRQ_SPKL,
+	MT6397_IRQ_SPKR,
+	MT6397_IRQ_BAT_L,
+	MT6397_IRQ_BAT_H,
+	MT6397_IRQ_FG_BAT_L,
+	MT6397_IRQ_FG_BAT_H,
+	MT6397_IRQ_WATCHDOG,
+	MT6397_IRQ_PWRKEY,
+	MT6397_IRQ_THR_L,
+	MT6397_IRQ_THR_H,
+	MT6397_IRQ_VBATON_UNDET,
+	MT6397_IRQ_BVALID_DET,
+	MT6397_IRQ_CHRDET,
+	MT6397_IRQ_OV,
+	MT6397_IRQ_LDO,
+	MT6397_IRQ_HOMEKEY,
+	MT6397_IRQ_ACCDET,
+	MT6397_IRQ_AUDIO,
+	MT6397_IRQ_RTC,
+	MT6397_IRQ_PWRKEY_RSTB,
+	MT6397_IRQ_HDMI_SIFM,
+	MT6397_IRQ_HDMI_CEC,
+	MT6397_IRQ_VCA15,
+	MT6397_IRQ_VSRMCA15,
+	MT6397_IRQ_VCORE,
+	MT6397_IRQ_VGPU,
+	MT6397_IRQ_VIO18,
+	MT6397_IRQ_VPCA7,
+	MT6397_IRQ_VSRMCA7,
+	MT6397_IRQ_VDRM,
+	MT6397_IRQ_NR,
+};
+
+struct mt6397_chip {
+	struct device *dev;
+	struct regmap *regmap;
+	int irq;
+	struct irq_domain *irq_domain;
+	struct mutex irqlock;
+	u16 irq_masks_cur[2];
+	u16 irq_masks_cache[2];
+};
+
+#endif /* __MFD_MT6397_CORE_H__ */
diff --git a/include/linux/mfd/mt6397/registers.h b/include/linux/mfd/mt6397/registers.h
new file mode 100644
index 0000000..f23a0a6
--- /dev/null
+++ b/include/linux/mfd/mt6397/registers.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_MT6397_REGISTERS_H__
+#define __MFD_MT6397_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6397_CID			0x0100
+#define MT6397_TOP_CKPDN		0x0102
+#define MT6397_TOP_CKPDN_SET		0x0104
+#define MT6397_TOP_CKPDN_CLR		0x0106
+#define MT6397_TOP_CKPDN2		0x0108
+#define MT6397_TOP_CKPDN2_SET		0x010A
+#define MT6397_TOP_CKPDN2_CLR		0x010C
+#define MT6397_TOP_GPIO_CKPDN		0x010E
+#define MT6397_TOP_RST_CON		0x0114
+#define MT6397_WRP_CKPDN		0x011A
+#define MT6397_WRP_RST_CON		0x0120
+#define MT6397_TOP_RST_MISC		0x0126
+#define MT6397_TOP_CKCON1		0x0128
+#define MT6397_TOP_CKCON2		0x012A
+#define MT6397_TOP_CKTST1		0x012C
+#define MT6397_TOP_CKTST2		0x012E
+#define MT6397_OC_DEG_EN		0x0130
+#define MT6397_OC_CTL0			0x0132
+#define MT6397_OC_CTL1			0x0134
+#define MT6397_OC_CTL2			0x0136
+#define MT6397_INT_RSV			0x0138
+#define MT6397_TEST_CON0		0x013A
+#define MT6397_TEST_CON1		0x013C
+#define MT6397_STATUS0			0x013E
+#define MT6397_STATUS1			0x0140
+#define MT6397_PGSTATUS			0x0142
+#define MT6397_CHRSTATUS		0x0144
+#define MT6397_OCSTATUS0		0x0146
+#define MT6397_OCSTATUS1		0x0148
+#define MT6397_OCSTATUS2		0x014A
+#define MT6397_HDMI_PAD_IE		0x014C
+#define MT6397_TEST_OUT_L		0x014E
+#define MT6397_TEST_OUT_H		0x0150
+#define MT6397_TDSEL_CON		0x0152
+#define MT6397_RDSEL_CON		0x0154
+#define MT6397_GPIO_SMT_CON0		0x0156
+#define MT6397_GPIO_SMT_CON1		0x0158
+#define MT6397_GPIO_SMT_CON2		0x015A
+#define MT6397_GPIO_SMT_CON3		0x015C
+#define MT6397_DRV_CON0			0x015E
+#define MT6397_DRV_CON1			0x0160
+#define MT6397_DRV_CON2			0x0162
+#define MT6397_DRV_CON3			0x0164
+#define MT6397_DRV_CON4			0x0166
+#define MT6397_DRV_CON5			0x0168
+#define MT6397_DRV_CON6			0x016A
+#define MT6397_DRV_CON7			0x016C
+#define MT6397_DRV_CON8			0x016E
+#define MT6397_DRV_CON9			0x0170
+#define MT6397_DRV_CON10		0x0172
+#define MT6397_DRV_CON11		0x0174
+#define MT6397_DRV_CON12		0x0176
+#define MT6397_INT_CON0			0x0178
+#define MT6397_INT_CON1			0x017E
+#define MT6397_INT_STATUS0		0x0184
+#define MT6397_INT_STATUS1		0x0186
+#define MT6397_FQMTR_CON0		0x0188
+#define MT6397_FQMTR_CON1		0x018A
+#define MT6397_FQMTR_CON2		0x018C
+#define MT6397_EFUSE_DOUT_0_15		0x01C4
+#define MT6397_EFUSE_DOUT_16_31		0x01C6
+#define MT6397_EFUSE_DOUT_32_47		0x01C8
+#define MT6397_EFUSE_DOUT_48_63		0x01CA
+#define MT6397_SPI_CON			0x01CC
+#define MT6397_TOP_CKPDN3		0x01CE
+#define MT6397_TOP_CKCON3		0x01D4
+#define MT6397_EFUSE_DOUT_64_79		0x01D6
+#define MT6397_EFUSE_DOUT_80_95		0x01D8
+#define MT6397_EFUSE_DOUT_96_111	0x01DA
+#define MT6397_EFUSE_DOUT_112_127	0x01DC
+#define MT6397_EFUSE_DOUT_128_143	0x01DE
+#define MT6397_EFUSE_DOUT_144_159	0x01E0
+#define MT6397_EFUSE_DOUT_160_175	0x01E2
+#define MT6397_EFUSE_DOUT_176_191	0x01E4
+#define MT6397_EFUSE_DOUT_192_207	0x01E6
+#define MT6397_EFUSE_DOUT_208_223	0x01E8
+#define MT6397_EFUSE_DOUT_224_239	0x01EA
+#define MT6397_EFUSE_DOUT_240_255	0x01EC
+#define MT6397_EFUSE_DOUT_256_271	0x01EE
+#define MT6397_EFUSE_DOUT_272_287	0x01F0
+#define MT6397_EFUSE_DOUT_288_300	0x01F2
+#define MT6397_EFUSE_DOUT_304_319	0x01F4
+#define MT6397_BUCK_CON0		0x0200
+#define MT6397_BUCK_CON1		0x0202
+#define MT6397_BUCK_CON2		0x0204
+#define MT6397_BUCK_CON3		0x0206
+#define MT6397_BUCK_CON4		0x0208
+#define MT6397_BUCK_CON5		0x020A
+#define MT6397_BUCK_CON6		0x020C
+#define MT6397_BUCK_CON7		0x020E
+#define MT6397_BUCK_CON8		0x0210
+#define MT6397_BUCK_CON9		0x0212
+#define MT6397_VCA15_CON0		0x0214
+#define MT6397_VCA15_CON1		0x0216
+#define MT6397_VCA15_CON2		0x0218
+#define MT6397_VCA15_CON3		0x021A
+#define MT6397_VCA15_CON4		0x021C
+#define MT6397_VCA15_CON5		0x021E
+#define MT6397_VCA15_CON6		0x0220
+#define MT6397_VCA15_CON7		0x0222
+#define MT6397_VCA15_CON8		0x0224
+#define MT6397_VCA15_CON9		0x0226
+#define MT6397_VCA15_CON10		0x0228
+#define MT6397_VCA15_CON11		0x022A
+#define MT6397_VCA15_CON12		0x022C
+#define MT6397_VCA15_CON13		0x022E
+#define MT6397_VCA15_CON14		0x0230
+#define MT6397_VCA15_CON15		0x0232
+#define MT6397_VCA15_CON16		0x0234
+#define MT6397_VCA15_CON17		0x0236
+#define MT6397_VCA15_CON18		0x0238
+#define MT6397_VSRMCA15_CON0		0x023A
+#define MT6397_VSRMCA15_CON1		0x023C
+#define MT6397_VSRMCA15_CON2		0x023E
+#define MT6397_VSRMCA15_CON3		0x0240
+#define MT6397_VSRMCA15_CON4		0x0242
+#define MT6397_VSRMCA15_CON5		0x0244
+#define MT6397_VSRMCA15_CON6		0x0246
+#define MT6397_VSRMCA15_CON7		0x0248
+#define MT6397_VSRMCA15_CON8		0x024A
+#define MT6397_VSRMCA15_CON9		0x024C
+#define MT6397_VSRMCA15_CON10		0x024E
+#define MT6397_VSRMCA15_CON11		0x0250
+#define MT6397_VSRMCA15_CON12		0x0252
+#define MT6397_VSRMCA15_CON13		0x0254
+#define MT6397_VSRMCA15_CON14		0x0256
+#define MT6397_VSRMCA15_CON15		0x0258
+#define MT6397_VSRMCA15_CON16		0x025A
+#define MT6397_VSRMCA15_CON17		0x025C
+#define MT6397_VSRMCA15_CON18		0x025E
+#define MT6397_VSRMCA15_CON19		0x0260
+#define MT6397_VSRMCA15_CON20		0x0262
+#define MT6397_VSRMCA15_CON21		0x0264
+#define MT6397_VCORE_CON0		0x0266
+#define MT6397_VCORE_CON1		0x0268
+#define MT6397_VCORE_CON2		0x026A
+#define MT6397_VCORE_CON3		0x026C
+#define MT6397_VCORE_CON4		0x026E
+#define MT6397_VCORE_CON5		0x0270
+#define MT6397_VCORE_CON6		0x0272
+#define MT6397_VCORE_CON7		0x0274
+#define MT6397_VCORE_CON8		0x0276
+#define MT6397_VCORE_CON9		0x0278
+#define MT6397_VCORE_CON10		0x027A
+#define MT6397_VCORE_CON11		0x027C
+#define MT6397_VCORE_CON12		0x027E
+#define MT6397_VCORE_CON13		0x0280
+#define MT6397_VCORE_CON14		0x0282
+#define MT6397_VCORE_CON15		0x0284
+#define MT6397_VCORE_CON16		0x0286
+#define MT6397_VCORE_CON17		0x0288
+#define MT6397_VCORE_CON18		0x028A
+#define MT6397_VGPU_CON0		0x028C
+#define MT6397_VGPU_CON1		0x028E
+#define MT6397_VGPU_CON2		0x0290
+#define MT6397_VGPU_CON3		0x0292
+#define MT6397_VGPU_CON4		0x0294
+#define MT6397_VGPU_CON5		0x0296
+#define MT6397_VGPU_CON6		0x0298
+#define MT6397_VGPU_CON7		0x029A
+#define MT6397_VGPU_CON8		0x029C
+#define MT6397_VGPU_CON9		0x029E
+#define MT6397_VGPU_CON10		0x02A0
+#define MT6397_VGPU_CON11		0x02A2
+#define MT6397_VGPU_CON12		0x02A4
+#define MT6397_VGPU_CON13		0x02A6
+#define MT6397_VGPU_CON14		0x02A8
+#define MT6397_VGPU_CON15		0x02AA
+#define MT6397_VGPU_CON16		0x02AC
+#define MT6397_VGPU_CON17		0x02AE
+#define MT6397_VGPU_CON18		0x02B0
+#define MT6397_VIO18_CON0		0x0300
+#define MT6397_VIO18_CON1		0x0302
+#define MT6397_VIO18_CON2		0x0304
+#define MT6397_VIO18_CON3		0x0306
+#define MT6397_VIO18_CON4		0x0308
+#define MT6397_VIO18_CON5		0x030A
+#define MT6397_VIO18_CON6		0x030C
+#define MT6397_VIO18_CON7		0x030E
+#define MT6397_VIO18_CON8		0x0310
+#define MT6397_VIO18_CON9		0x0312
+#define MT6397_VIO18_CON10		0x0314
+#define MT6397_VIO18_CON11		0x0316
+#define MT6397_VIO18_CON12		0x0318
+#define MT6397_VIO18_CON13		0x031A
+#define MT6397_VIO18_CON14		0x031C
+#define MT6397_VIO18_CON15		0x031E
+#define MT6397_VIO18_CON16		0x0320
+#define MT6397_VIO18_CON17		0x0322
+#define MT6397_VIO18_CON18		0x0324
+#define MT6397_VPCA7_CON0		0x0326
+#define MT6397_VPCA7_CON1		0x0328
+#define MT6397_VPCA7_CON2		0x032A
+#define MT6397_VPCA7_CON3		0x032C
+#define MT6397_VPCA7_CON4		0x032E
+#define MT6397_VPCA7_CON5		0x0330
+#define MT6397_VPCA7_CON6		0x0332
+#define MT6397_VPCA7_CON7		0x0334
+#define MT6397_VPCA7_CON8		0x0336
+#define MT6397_VPCA7_CON9		0x0338
+#define MT6397_VPCA7_CON10		0x033A
+#define MT6397_VPCA7_CON11		0x033C
+#define MT6397_VPCA7_CON12		0x033E
+#define MT6397_VPCA7_CON13		0x0340
+#define MT6397_VPCA7_CON14		0x0342
+#define MT6397_VPCA7_CON15		0x0344
+#define MT6397_VPCA7_CON16		0x0346
+#define MT6397_VPCA7_CON17		0x0348
+#define MT6397_VPCA7_CON18		0x034A
+#define MT6397_VSRMCA7_CON0		0x034C
+#define MT6397_VSRMCA7_CON1		0x034E
+#define MT6397_VSRMCA7_CON2		0x0350
+#define MT6397_VSRMCA7_CON3		0x0352
+#define MT6397_VSRMCA7_CON4		0x0354
+#define MT6397_VSRMCA7_CON5		0x0356
+#define MT6397_VSRMCA7_CON6		0x0358
+#define MT6397_VSRMCA7_CON7		0x035A
+#define MT6397_VSRMCA7_CON8		0x035C
+#define MT6397_VSRMCA7_CON9		0x035E
+#define MT6397_VSRMCA7_CON10		0x0360
+#define MT6397_VSRMCA7_CON11		0x0362
+#define MT6397_VSRMCA7_CON12		0x0364
+#define MT6397_VSRMCA7_CON13		0x0366
+#define MT6397_VSRMCA7_CON14		0x0368
+#define MT6397_VSRMCA7_CON15		0x036A
+#define MT6397_VSRMCA7_CON16		0x036C
+#define MT6397_VSRMCA7_CON17		0x036E
+#define MT6397_VSRMCA7_CON18		0x0370
+#define MT6397_VSRMCA7_CON19		0x0372
+#define MT6397_VSRMCA7_CON20		0x0374
+#define MT6397_VSRMCA7_CON21		0x0376
+#define MT6397_VDRM_CON0		0x0378
+#define MT6397_VDRM_CON1		0x037A
+#define MT6397_VDRM_CON2		0x037C
+#define MT6397_VDRM_CON3		0x037E
+#define MT6397_VDRM_CON4		0x0380
+#define MT6397_VDRM_CON5		0x0382
+#define MT6397_VDRM_CON6		0x0384
+#define MT6397_VDRM_CON7		0x0386
+#define MT6397_VDRM_CON8		0x0388
+#define MT6397_VDRM_CON9		0x038A
+#define MT6397_VDRM_CON10		0x038C
+#define MT6397_VDRM_CON11		0x038E
+#define MT6397_VDRM_CON12		0x0390
+#define MT6397_VDRM_CON13		0x0392
+#define MT6397_VDRM_CON14		0x0394
+#define MT6397_VDRM_CON15		0x0396
+#define MT6397_VDRM_CON16		0x0398
+#define MT6397_VDRM_CON17		0x039A
+#define MT6397_VDRM_CON18		0x039C
+#define MT6397_BUCK_K_CON0		0x039E
+#define MT6397_BUCK_K_CON1		0x03A0
+#define MT6397_ANALDO_CON0		0x0400
+#define MT6397_ANALDO_CON1		0x0402
+#define MT6397_ANALDO_CON2		0x0404
+#define MT6397_ANALDO_CON3		0x0406
+#define MT6397_ANALDO_CON4		0x0408
+#define MT6397_ANALDO_CON5		0x040A
+#define MT6397_ANALDO_CON6		0x040C
+#define MT6397_ANALDO_CON7		0x040E
+#define MT6397_DIGLDO_CON0		0x0410
+#define MT6397_DIGLDO_CON1		0x0412
+#define MT6397_DIGLDO_CON2		0x0414
+#define MT6397_DIGLDO_CON3		0x0416
+#define MT6397_DIGLDO_CON4		0x0418
+#define MT6397_DIGLDO_CON5		0x041A
+#define MT6397_DIGLDO_CON6		0x041C
+#define MT6397_DIGLDO_CON7		0x041E
+#define MT6397_DIGLDO_CON8		0x0420
+#define MT6397_DIGLDO_CON9		0x0422
+#define MT6397_DIGLDO_CON10		0x0424
+#define MT6397_DIGLDO_CON11		0x0426
+#define MT6397_DIGLDO_CON12		0x0428
+#define MT6397_DIGLDO_CON13		0x042A
+#define MT6397_DIGLDO_CON14		0x042C
+#define MT6397_DIGLDO_CON15		0x042E
+#define MT6397_DIGLDO_CON16		0x0430
+#define MT6397_DIGLDO_CON17		0x0432
+#define MT6397_DIGLDO_CON18		0x0434
+#define MT6397_DIGLDO_CON19		0x0436
+#define MT6397_DIGLDO_CON20		0x0438
+#define MT6397_DIGLDO_CON21		0x043A
+#define MT6397_DIGLDO_CON22		0x043C
+#define MT6397_DIGLDO_CON23		0x043E
+#define MT6397_DIGLDO_CON24		0x0440
+#define MT6397_DIGLDO_CON25		0x0442
+#define MT6397_DIGLDO_CON26		0x0444
+#define MT6397_DIGLDO_CON27		0x0446
+#define MT6397_DIGLDO_CON28		0x0448
+#define MT6397_DIGLDO_CON29		0x044A
+#define MT6397_DIGLDO_CON30		0x044C
+#define MT6397_DIGLDO_CON31		0x044E
+#define MT6397_DIGLDO_CON32		0x0450
+#define MT6397_DIGLDO_CON33		0x045A
+#define MT6397_SPK_CON0			0x0600
+#define MT6397_SPK_CON1			0x0602
+#define MT6397_SPK_CON2			0x0604
+#define MT6397_SPK_CON3			0x0606
+#define MT6397_SPK_CON4			0x0608
+#define MT6397_SPK_CON5			0x060A
+#define MT6397_SPK_CON6			0x060C
+#define MT6397_SPK_CON7			0x060E
+#define MT6397_SPK_CON8			0x0610
+#define MT6397_SPK_CON9			0x0612
+#define MT6397_SPK_CON10		0x0614
+#define MT6397_SPK_CON11		0x0616
+#define MT6397_AUDDAC_CON0		0x0700
+#define MT6397_AUDBUF_CFG0		0x0702
+#define MT6397_AUDBUF_CFG1		0x0704
+#define MT6397_AUDBUF_CFG2		0x0706
+#define MT6397_AUDBUF_CFG3		0x0708
+#define MT6397_AUDBUF_CFG4		0x070A
+#define MT6397_IBIASDIST_CFG0		0x070C
+#define MT6397_AUDACCDEPOP_CFG0		0x070E
+#define MT6397_AUD_IV_CFG0		0x0710
+#define MT6397_AUDCLKGEN_CFG0		0x0712
+#define MT6397_AUDLDO_CFG0		0x0714
+#define MT6397_AUDLDO_CFG1		0x0716
+#define MT6397_AUDNVREGGLB_CFG0		0x0718
+#define MT6397_AUD_NCP0			0x071A
+#define MT6397_AUDPREAMP_CON0		0x071C
+#define MT6397_AUDADC_CON0		0x071E
+#define MT6397_AUDADC_CON1		0x0720
+#define MT6397_AUDADC_CON2		0x0722
+#define MT6397_AUDADC_CON3		0x0724
+#define MT6397_AUDADC_CON4		0x0726
+#define MT6397_AUDADC_CON5		0x0728
+#define MT6397_AUDADC_CON6		0x072A
+#define MT6397_AUDDIGMI_CON0		0x072C
+#define MT6397_AUDLSBUF_CON0		0x072E
+#define MT6397_AUDLSBUF_CON1		0x0730
+#define MT6397_AUDENCSPARE_CON0		0x0732
+#define MT6397_AUDENCCLKSQ_CON0		0x0734
+#define MT6397_AUDPREAMPGAIN_CON0	0x0736
+#define MT6397_ZCD_CON0			0x0738
+#define MT6397_ZCD_CON1			0x073A
+#define MT6397_ZCD_CON2			0x073C
+#define MT6397_ZCD_CON3			0x073E
+#define MT6397_ZCD_CON4			0x0740
+#define MT6397_ZCD_CON5			0x0742
+#define MT6397_NCP_CLKDIV_CON0		0x0744
+#define MT6397_NCP_CLKDIV_CON1		0x0746
+
+#endif /* __MFD_MT6397_REGISTERS_H__ */
-- 
2.1.4



From s.hauer at pengutronix.de  Sun Feb 22 04:15:30 2015
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Sun, 22 Feb 2015 13:15:30 +0100
Subject: [PATCH 2/2] mfd: dt-bindings: Add bindings for the MediaTek MT6397
 PMIC
In-Reply-To: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
References: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
Message-ID: <1424607330-1829-3-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 Documentation/devicetree/bindings/mfd/mt6397.txt | 70 ++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/mt6397.txt

diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
new file mode 100644
index 0000000..15043e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -0,0 +1,70 @@
+MediaTek MT6397 Multifunction Device Driver
+
+MT6397 is a multifunction device with the following sub modules:
+- Regulator
+- RTC
+- Audio codec
+- GPIO
+- Clock
+
+It is interfaced to host controller using SPI interface by a proprietary hardware
+called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
+See the following for pwarp node definitions:
+Documentation/devicetree/bindings/soc/pwrap.txt
+
+This document describes the binding for MFD device and its sub module.
+
+Required properties:
+compatible: "mediatek,mt6397"
+
+Optional subnodes:
+
+- rtc
+	Required properties:
+		- compatible: "mediatek,mt6397-rtc"
+- regulators
+	Required properties:
+		- compatible: "mediatek,mt6397-regulator"
+	see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+- codec
+	Required properties:
+		- compatible: "mediatek,mt6397-codec"
+- clk
+	Required properties:
+		- compatible: "mediatek,mt6397-clk"
+
+Example:
+	pwrap: pwrap at 1000f000 {
+		compatible = "mediatek,mt8135-pwrap";
+
+		...
+
+		pmic {
+			compatible = "mediatek,mt6397";
+
+			codec: mt6397codec {
+				compatible = "mediatek,mt6397-codec";
+			};
+
+			regulators {
+				compatible = "mediatek,mt6397-regulator";
+
+				mt6397_vpca15_reg: buck_vpca15 {
+					regulator-compatible = "buck_vpca15";
+					regulator-name = "vpca15";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-ramp-delay = <12500>;
+					regulator-always-on;
+				};
+
+				mt6397_vgp4_reg: ldo_vgp4 {
+					regulator-compatible = "ldo_vgp4";
+					regulator-name = "vgp4";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-enable-ramp-delay = <218>;
+				};
+			};
+		};
+	};
-- 
2.1.4



From daniel.lezcano at linaro.org  Mon Feb 23 23:16:08 2015
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 24 Feb 2015 08:16:08 +0100
Subject: [PATCH] clocksource: mtk: Fix race conditions in probe code
In-Reply-To: <1424342493-31391-1-git-send-email-matthias.bgg@gmail.com>
References: <1424342493-31391-1-git-send-email-matthias.bgg@gmail.com>
Message-ID: <54EC2538.1070005@linaro.org>

On 02/19/2015 11:41 AM, Matthias Brugger wrote:
> We have two race conditions in the probe code which could lead to a null
> pointer dereference in the interrupt handler.
>
> The interrupt handler accesses the clockevent device, which may not yet be
> registered.
>
> First race condition happens when the interrupt handler gets registered before
> the interrupts get disabled. The second race condition happens when the
> interrupts get enabled, but the clockevent device is not yet registered.
>
> Fix that by disabling the interrupts before we register the interrupt and enable
> the interrupts after the clockevent device got registered.
>
> Reported-by: Gongbae Park <yongbae2 at gmail.com>
> Signed-off-by: Matthias Brugger <matthias.bgg at gmail.com>
> Cc: stable at vger.kernel.org
> ---

Applied to my tree as a fix for 3.20.

Thanks !

   -- Daniel

-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog



From lee.jones at linaro.org  Thu Feb 26 03:14:49 2015
From: lee.jones at linaro.org (Lee Jones)
Date: Thu, 26 Feb 2015 11:14:49 +0000
Subject: [PATCH 1/2] mfd: Add support for the MediaTek MT6397 PMIC
In-Reply-To: <1424607330-1829-2-git-send-email-s.hauer@pengutronix.de>
References: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
 <1424607330-1829-2-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150226111449.GA14842@x1>

On Sun, 22 Feb 2015, Sascha Hauer wrote:

> From: Flora Fu <flora.fu at mediatek.com>
> 
> This adds support for the MediaTek MT6397 PMIC. This is a
> multifunction device with the following sub modules:
> 
> - Regulator
> - RTC
> - Audio codec
> - GPIO
> - Clock
> 
> It is interfaced to the host controller using SPI interface by a proprietary
> hardware called PMIC wrapper or pwrap. MT6397 MFD is a child device of the
> pwrap.
> 
> Signed-off-by: Flora Fu, MediaTek
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> Cc: Samuel Ortiz <sameo at linux.intel.com>
> Cc: Lee Jones <lee.jones at linaro.org>
> ---
>  drivers/mfd/Kconfig                  |  10 +
>  drivers/mfd/Makefile                 |   1 +
>  drivers/mfd/mt6397-core.c            | 223 +++++++++++++++++++++
>  include/linux/mfd/mt6397/core.h      |  64 +++++++
>  include/linux/mfd/mt6397/registers.h | 362 +++++++++++++++++++++++++++++++++++
>  5 files changed, 660 insertions(+)
>  create mode 100644 drivers/mfd/mt6397-core.c
>  create mode 100644 include/linux/mfd/mt6397/core.h
>  create mode 100644 include/linux/mfd/mt6397/registers.h

I'm pretty sure I already Acked this.  Please ensure these are carried
forward to mitigate wasted time due to duplicated effort.

Patch applied, thanks.

> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 2e6b731..7782e95 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -489,6 +489,16 @@ config MFD_MAX8998
>  	  additional drivers must be enabled in order to use the functionality
>  	  of the device.
>  
> +config MFD_MT6397
> +	tristate "MediaTek MT6397 PMIC Support"
> +	select MFD_CORE
> +	select IRQ_DOMAIN
> +	help
> +	  Say yes here to add support for MediaTek MT6397 PMIC. This is
> +	  a Power Management IC. This driver provides common support for
> +	  accessing the device; additional drivers must be enabled in order
> +	  to use the functionality of the device.
> +
>  config MFD_MENF21BMC
>  	tristate "MEN 14F021P00 Board Management Controller Support"
>  	depends on I2C
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 53467e2..329d4ed 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -179,3 +179,4 @@ obj-$(CONFIG_MFD_DLN2)		+= dln2.o
>  
>  intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
>  obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
> +obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
> diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> new file mode 100644
> index 0000000..b61c4eb
> --- /dev/null
> +++ b/drivers/mfd/mt6397-core.c
> @@ -0,0 +1,223 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * 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/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mfd/mt6397/core.h>
> +#include <linux/mfd/mt6397/registers.h>
> +
> +static const struct mfd_cell mt6397_devs[] = {
> +	{
> +		.name = "mt6397-rtc",
> +		.of_compatible = "mediatek,mt6397-rtc",
> +	}, {
> +		.name = "mt6397-regulator",
> +		.of_compatible = "mediatek,mt6397-regulator",
> +	}, {
> +		.name = "mt6397-codec",
> +		.of_compatible = "mediatek,mt6397-codec",
> +	}, {
> +		.name = "mt6397-clk",
> +		.of_compatible = "mediatek,mt6397-clk",
> +	},
> +};
> +
> +static void mt6397_irq_lock(struct irq_data *data)
> +{
> +	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
> +
> +	mutex_lock(&mt6397->irqlock);
> +}
> +
> +static void mt6397_irq_sync_unlock(struct irq_data *data)
> +{
> +	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
> +
> +	regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
> +	regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
> +
> +	mutex_unlock(&mt6397->irqlock);
> +}
> +
> +static void mt6397_irq_disable(struct irq_data *data)
> +{
> +	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
> +	int shift = data->hwirq & 0xf;
> +	int reg = data->hwirq >> 4;
> +
> +	mt6397->irq_masks_cur[reg] &= ~BIT(shift);
> +}
> +
> +static void mt6397_irq_enable(struct irq_data *data)
> +{
> +	struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
> +	int shift = data->hwirq & 0xf;
> +	int reg = data->hwirq >> 4;
> +
> +	mt6397->irq_masks_cur[reg] |= BIT(shift);
> +}
> +
> +static struct irq_chip mt6397_irq_chip = {
> +	.name = "mt6397-irq",
> +	.irq_bus_lock = mt6397_irq_lock,
> +	.irq_bus_sync_unlock = mt6397_irq_sync_unlock,
> +	.irq_enable = mt6397_irq_enable,
> +	.irq_disable = mt6397_irq_disable,
> +};
> +
> +static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
> +		int irqbase)
> +{
> +	unsigned int status;
> +	int i, irq, ret;
> +
> +	ret = regmap_read(mt6397->regmap, reg, &status);
> +	if (ret) {
> +		dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
> +		return;
> +	}
> +
> +	for (i = 0; i < 16; i++) {
> +		if (status & BIT(i)) {
> +			irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
> +			if (irq)
> +				handle_nested_irq(irq);
> +		}
> +	}
> +
> +	regmap_write(mt6397->regmap, reg, status);
> +}
> +
> +static irqreturn_t mt6397_irq_thread(int irq, void *data)
> +{
> +	struct mt6397_chip *mt6397 = data;
> +
> +	mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
> +	mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
> +					irq_hw_number_t hw)
> +{
> +	struct mt6397_chip *mt6397 = d->host_data;
> +
> +	irq_set_chip_data(irq, mt6397);
> +	irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
> +	irq_set_nested_thread(irq, 1);
> +	set_irq_flags(irq, IRQF_VALID);
> +
> +	return 0;
> +}
> +
> +static struct irq_domain_ops mt6397_irq_domain_ops = {
> +	.map = mt6397_irq_domain_map,
> +};
> +
> +static int mt6397_irq_init(struct mt6397_chip *mt6397)
> +{
> +	int ret;
> +
> +	mutex_init(&mt6397->irqlock);
> +
> +	/* Mask all interrupt sources */
> +	regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
> +	regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
> +
> +	mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
> +		MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
> +	if (!mt6397->irq_domain) {
> +		dev_err(mt6397->dev, "could not create irq domain\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
> +		mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
> +	if (ret) {
> +		dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
> +			mt6397->irq, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mt6397_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct mt6397_chip *mt6397;
> +
> +	mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
> +	if (!mt6397)
> +		return -ENOMEM;
> +
> +	mt6397->dev = &pdev->dev;
> +	/*
> +	 * mt6397 MFD is child device of soc pmic wrapper.
> +	 * Regmap is set from its parent.
> +	 */
> +	mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	if (!mt6397->regmap)
> +		return -ENODEV;
> +
> +	platform_set_drvdata(pdev, mt6397);
> +
> +	mt6397->irq = platform_get_irq(pdev, 0);
> +	if (mt6397->irq > 0) {
> +		ret = mt6397_irq_init(mt6397);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
> +			ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
> +	if (ret)
> +		dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static int mt6397_remove(struct platform_device *pdev)
> +{
> +	mfd_remove_devices(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id mt6397_of_match[] = {
> +	{ .compatible = "mediatek,mt6397" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, mt6397_of_match);
> +
> +static struct platform_driver mt6397_driver = {
> +	.probe = mt6397_probe,
> +	.remove = mt6397_remove,
> +	.driver = {
> +		.name = "mt6397",
> +		.of_match_table = of_match_ptr(mt6397_of_match),
> +	},
> +};
> +
> +module_platform_driver(mt6397_driver);
> +
> +MODULE_AUTHOR("Flora Fu, MediaTek");
> +MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:mt6397");
> diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
> new file mode 100644
> index 0000000..cf5265b
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/core.h
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MFD_MT6397_CORE_H__
> +#define __MFD_MT6397_CORE_H__
> +
> +enum mt6397_irq_numbers {
> +	MT6397_IRQ_SPKL_AB = 0,
> +	MT6397_IRQ_SPKR_AB,
> +	MT6397_IRQ_SPKL,
> +	MT6397_IRQ_SPKR,
> +	MT6397_IRQ_BAT_L,
> +	MT6397_IRQ_BAT_H,
> +	MT6397_IRQ_FG_BAT_L,
> +	MT6397_IRQ_FG_BAT_H,
> +	MT6397_IRQ_WATCHDOG,
> +	MT6397_IRQ_PWRKEY,
> +	MT6397_IRQ_THR_L,
> +	MT6397_IRQ_THR_H,
> +	MT6397_IRQ_VBATON_UNDET,
> +	MT6397_IRQ_BVALID_DET,
> +	MT6397_IRQ_CHRDET,
> +	MT6397_IRQ_OV,
> +	MT6397_IRQ_LDO,
> +	MT6397_IRQ_HOMEKEY,
> +	MT6397_IRQ_ACCDET,
> +	MT6397_IRQ_AUDIO,
> +	MT6397_IRQ_RTC,
> +	MT6397_IRQ_PWRKEY_RSTB,
> +	MT6397_IRQ_HDMI_SIFM,
> +	MT6397_IRQ_HDMI_CEC,
> +	MT6397_IRQ_VCA15,
> +	MT6397_IRQ_VSRMCA15,
> +	MT6397_IRQ_VCORE,
> +	MT6397_IRQ_VGPU,
> +	MT6397_IRQ_VIO18,
> +	MT6397_IRQ_VPCA7,
> +	MT6397_IRQ_VSRMCA7,
> +	MT6397_IRQ_VDRM,
> +	MT6397_IRQ_NR,
> +};
> +
> +struct mt6397_chip {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	int irq;
> +	struct irq_domain *irq_domain;
> +	struct mutex irqlock;
> +	u16 irq_masks_cur[2];
> +	u16 irq_masks_cache[2];
> +};
> +
> +#endif /* __MFD_MT6397_CORE_H__ */
> diff --git a/include/linux/mfd/mt6397/registers.h b/include/linux/mfd/mt6397/registers.h
> new file mode 100644
> index 0000000..f23a0a6
> --- /dev/null
> +++ b/include/linux/mfd/mt6397/registers.h
> @@ -0,0 +1,362 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Flora Fu, MediaTek
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MFD_MT6397_REGISTERS_H__
> +#define __MFD_MT6397_REGISTERS_H__
> +
> +/* PMIC Registers */
> +#define MT6397_CID			0x0100
> +#define MT6397_TOP_CKPDN		0x0102
> +#define MT6397_TOP_CKPDN_SET		0x0104
> +#define MT6397_TOP_CKPDN_CLR		0x0106
> +#define MT6397_TOP_CKPDN2		0x0108
> +#define MT6397_TOP_CKPDN2_SET		0x010A
> +#define MT6397_TOP_CKPDN2_CLR		0x010C
> +#define MT6397_TOP_GPIO_CKPDN		0x010E
> +#define MT6397_TOP_RST_CON		0x0114
> +#define MT6397_WRP_CKPDN		0x011A
> +#define MT6397_WRP_RST_CON		0x0120
> +#define MT6397_TOP_RST_MISC		0x0126
> +#define MT6397_TOP_CKCON1		0x0128
> +#define MT6397_TOP_CKCON2		0x012A
> +#define MT6397_TOP_CKTST1		0x012C
> +#define MT6397_TOP_CKTST2		0x012E
> +#define MT6397_OC_DEG_EN		0x0130
> +#define MT6397_OC_CTL0			0x0132
> +#define MT6397_OC_CTL1			0x0134
> +#define MT6397_OC_CTL2			0x0136
> +#define MT6397_INT_RSV			0x0138
> +#define MT6397_TEST_CON0		0x013A
> +#define MT6397_TEST_CON1		0x013C
> +#define MT6397_STATUS0			0x013E
> +#define MT6397_STATUS1			0x0140
> +#define MT6397_PGSTATUS			0x0142
> +#define MT6397_CHRSTATUS		0x0144
> +#define MT6397_OCSTATUS0		0x0146
> +#define MT6397_OCSTATUS1		0x0148
> +#define MT6397_OCSTATUS2		0x014A
> +#define MT6397_HDMI_PAD_IE		0x014C
> +#define MT6397_TEST_OUT_L		0x014E
> +#define MT6397_TEST_OUT_H		0x0150
> +#define MT6397_TDSEL_CON		0x0152
> +#define MT6397_RDSEL_CON		0x0154
> +#define MT6397_GPIO_SMT_CON0		0x0156
> +#define MT6397_GPIO_SMT_CON1		0x0158
> +#define MT6397_GPIO_SMT_CON2		0x015A
> +#define MT6397_GPIO_SMT_CON3		0x015C
> +#define MT6397_DRV_CON0			0x015E
> +#define MT6397_DRV_CON1			0x0160
> +#define MT6397_DRV_CON2			0x0162
> +#define MT6397_DRV_CON3			0x0164
> +#define MT6397_DRV_CON4			0x0166
> +#define MT6397_DRV_CON5			0x0168
> +#define MT6397_DRV_CON6			0x016A
> +#define MT6397_DRV_CON7			0x016C
> +#define MT6397_DRV_CON8			0x016E
> +#define MT6397_DRV_CON9			0x0170
> +#define MT6397_DRV_CON10		0x0172
> +#define MT6397_DRV_CON11		0x0174
> +#define MT6397_DRV_CON12		0x0176
> +#define MT6397_INT_CON0			0x0178
> +#define MT6397_INT_CON1			0x017E
> +#define MT6397_INT_STATUS0		0x0184
> +#define MT6397_INT_STATUS1		0x0186
> +#define MT6397_FQMTR_CON0		0x0188
> +#define MT6397_FQMTR_CON1		0x018A
> +#define MT6397_FQMTR_CON2		0x018C
> +#define MT6397_EFUSE_DOUT_0_15		0x01C4
> +#define MT6397_EFUSE_DOUT_16_31		0x01C6
> +#define MT6397_EFUSE_DOUT_32_47		0x01C8
> +#define MT6397_EFUSE_DOUT_48_63		0x01CA
> +#define MT6397_SPI_CON			0x01CC
> +#define MT6397_TOP_CKPDN3		0x01CE
> +#define MT6397_TOP_CKCON3		0x01D4
> +#define MT6397_EFUSE_DOUT_64_79		0x01D6
> +#define MT6397_EFUSE_DOUT_80_95		0x01D8
> +#define MT6397_EFUSE_DOUT_96_111	0x01DA
> +#define MT6397_EFUSE_DOUT_112_127	0x01DC
> +#define MT6397_EFUSE_DOUT_128_143	0x01DE
> +#define MT6397_EFUSE_DOUT_144_159	0x01E0
> +#define MT6397_EFUSE_DOUT_160_175	0x01E2
> +#define MT6397_EFUSE_DOUT_176_191	0x01E4
> +#define MT6397_EFUSE_DOUT_192_207	0x01E6
> +#define MT6397_EFUSE_DOUT_208_223	0x01E8
> +#define MT6397_EFUSE_DOUT_224_239	0x01EA
> +#define MT6397_EFUSE_DOUT_240_255	0x01EC
> +#define MT6397_EFUSE_DOUT_256_271	0x01EE
> +#define MT6397_EFUSE_DOUT_272_287	0x01F0
> +#define MT6397_EFUSE_DOUT_288_300	0x01F2
> +#define MT6397_EFUSE_DOUT_304_319	0x01F4
> +#define MT6397_BUCK_CON0		0x0200
> +#define MT6397_BUCK_CON1		0x0202
> +#define MT6397_BUCK_CON2		0x0204
> +#define MT6397_BUCK_CON3		0x0206
> +#define MT6397_BUCK_CON4		0x0208
> +#define MT6397_BUCK_CON5		0x020A
> +#define MT6397_BUCK_CON6		0x020C
> +#define MT6397_BUCK_CON7		0x020E
> +#define MT6397_BUCK_CON8		0x0210
> +#define MT6397_BUCK_CON9		0x0212
> +#define MT6397_VCA15_CON0		0x0214
> +#define MT6397_VCA15_CON1		0x0216
> +#define MT6397_VCA15_CON2		0x0218
> +#define MT6397_VCA15_CON3		0x021A
> +#define MT6397_VCA15_CON4		0x021C
> +#define MT6397_VCA15_CON5		0x021E
> +#define MT6397_VCA15_CON6		0x0220
> +#define MT6397_VCA15_CON7		0x0222
> +#define MT6397_VCA15_CON8		0x0224
> +#define MT6397_VCA15_CON9		0x0226
> +#define MT6397_VCA15_CON10		0x0228
> +#define MT6397_VCA15_CON11		0x022A
> +#define MT6397_VCA15_CON12		0x022C
> +#define MT6397_VCA15_CON13		0x022E
> +#define MT6397_VCA15_CON14		0x0230
> +#define MT6397_VCA15_CON15		0x0232
> +#define MT6397_VCA15_CON16		0x0234
> +#define MT6397_VCA15_CON17		0x0236
> +#define MT6397_VCA15_CON18		0x0238
> +#define MT6397_VSRMCA15_CON0		0x023A
> +#define MT6397_VSRMCA15_CON1		0x023C
> +#define MT6397_VSRMCA15_CON2		0x023E
> +#define MT6397_VSRMCA15_CON3		0x0240
> +#define MT6397_VSRMCA15_CON4		0x0242
> +#define MT6397_VSRMCA15_CON5		0x0244
> +#define MT6397_VSRMCA15_CON6		0x0246
> +#define MT6397_VSRMCA15_CON7		0x0248
> +#define MT6397_VSRMCA15_CON8		0x024A
> +#define MT6397_VSRMCA15_CON9		0x024C
> +#define MT6397_VSRMCA15_CON10		0x024E
> +#define MT6397_VSRMCA15_CON11		0x0250
> +#define MT6397_VSRMCA15_CON12		0x0252
> +#define MT6397_VSRMCA15_CON13		0x0254
> +#define MT6397_VSRMCA15_CON14		0x0256
> +#define MT6397_VSRMCA15_CON15		0x0258
> +#define MT6397_VSRMCA15_CON16		0x025A
> +#define MT6397_VSRMCA15_CON17		0x025C
> +#define MT6397_VSRMCA15_CON18		0x025E
> +#define MT6397_VSRMCA15_CON19		0x0260
> +#define MT6397_VSRMCA15_CON20		0x0262
> +#define MT6397_VSRMCA15_CON21		0x0264
> +#define MT6397_VCORE_CON0		0x0266
> +#define MT6397_VCORE_CON1		0x0268
> +#define MT6397_VCORE_CON2		0x026A
> +#define MT6397_VCORE_CON3		0x026C
> +#define MT6397_VCORE_CON4		0x026E
> +#define MT6397_VCORE_CON5		0x0270
> +#define MT6397_VCORE_CON6		0x0272
> +#define MT6397_VCORE_CON7		0x0274
> +#define MT6397_VCORE_CON8		0x0276
> +#define MT6397_VCORE_CON9		0x0278
> +#define MT6397_VCORE_CON10		0x027A
> +#define MT6397_VCORE_CON11		0x027C
> +#define MT6397_VCORE_CON12		0x027E
> +#define MT6397_VCORE_CON13		0x0280
> +#define MT6397_VCORE_CON14		0x0282
> +#define MT6397_VCORE_CON15		0x0284
> +#define MT6397_VCORE_CON16		0x0286
> +#define MT6397_VCORE_CON17		0x0288
> +#define MT6397_VCORE_CON18		0x028A
> +#define MT6397_VGPU_CON0		0x028C
> +#define MT6397_VGPU_CON1		0x028E
> +#define MT6397_VGPU_CON2		0x0290
> +#define MT6397_VGPU_CON3		0x0292
> +#define MT6397_VGPU_CON4		0x0294
> +#define MT6397_VGPU_CON5		0x0296
> +#define MT6397_VGPU_CON6		0x0298
> +#define MT6397_VGPU_CON7		0x029A
> +#define MT6397_VGPU_CON8		0x029C
> +#define MT6397_VGPU_CON9		0x029E
> +#define MT6397_VGPU_CON10		0x02A0
> +#define MT6397_VGPU_CON11		0x02A2
> +#define MT6397_VGPU_CON12		0x02A4
> +#define MT6397_VGPU_CON13		0x02A6
> +#define MT6397_VGPU_CON14		0x02A8
> +#define MT6397_VGPU_CON15		0x02AA
> +#define MT6397_VGPU_CON16		0x02AC
> +#define MT6397_VGPU_CON17		0x02AE
> +#define MT6397_VGPU_CON18		0x02B0
> +#define MT6397_VIO18_CON0		0x0300
> +#define MT6397_VIO18_CON1		0x0302
> +#define MT6397_VIO18_CON2		0x0304
> +#define MT6397_VIO18_CON3		0x0306
> +#define MT6397_VIO18_CON4		0x0308
> +#define MT6397_VIO18_CON5		0x030A
> +#define MT6397_VIO18_CON6		0x030C
> +#define MT6397_VIO18_CON7		0x030E
> +#define MT6397_VIO18_CON8		0x0310
> +#define MT6397_VIO18_CON9		0x0312
> +#define MT6397_VIO18_CON10		0x0314
> +#define MT6397_VIO18_CON11		0x0316
> +#define MT6397_VIO18_CON12		0x0318
> +#define MT6397_VIO18_CON13		0x031A
> +#define MT6397_VIO18_CON14		0x031C
> +#define MT6397_VIO18_CON15		0x031E
> +#define MT6397_VIO18_CON16		0x0320
> +#define MT6397_VIO18_CON17		0x0322
> +#define MT6397_VIO18_CON18		0x0324
> +#define MT6397_VPCA7_CON0		0x0326
> +#define MT6397_VPCA7_CON1		0x0328
> +#define MT6397_VPCA7_CON2		0x032A
> +#define MT6397_VPCA7_CON3		0x032C
> +#define MT6397_VPCA7_CON4		0x032E
> +#define MT6397_VPCA7_CON5		0x0330
> +#define MT6397_VPCA7_CON6		0x0332
> +#define MT6397_VPCA7_CON7		0x0334
> +#define MT6397_VPCA7_CON8		0x0336
> +#define MT6397_VPCA7_CON9		0x0338
> +#define MT6397_VPCA7_CON10		0x033A
> +#define MT6397_VPCA7_CON11		0x033C
> +#define MT6397_VPCA7_CON12		0x033E
> +#define MT6397_VPCA7_CON13		0x0340
> +#define MT6397_VPCA7_CON14		0x0342
> +#define MT6397_VPCA7_CON15		0x0344
> +#define MT6397_VPCA7_CON16		0x0346
> +#define MT6397_VPCA7_CON17		0x0348
> +#define MT6397_VPCA7_CON18		0x034A
> +#define MT6397_VSRMCA7_CON0		0x034C
> +#define MT6397_VSRMCA7_CON1		0x034E
> +#define MT6397_VSRMCA7_CON2		0x0350
> +#define MT6397_VSRMCA7_CON3		0x0352
> +#define MT6397_VSRMCA7_CON4		0x0354
> +#define MT6397_VSRMCA7_CON5		0x0356
> +#define MT6397_VSRMCA7_CON6		0x0358
> +#define MT6397_VSRMCA7_CON7		0x035A
> +#define MT6397_VSRMCA7_CON8		0x035C
> +#define MT6397_VSRMCA7_CON9		0x035E
> +#define MT6397_VSRMCA7_CON10		0x0360
> +#define MT6397_VSRMCA7_CON11		0x0362
> +#define MT6397_VSRMCA7_CON12		0x0364
> +#define MT6397_VSRMCA7_CON13		0x0366
> +#define MT6397_VSRMCA7_CON14		0x0368
> +#define MT6397_VSRMCA7_CON15		0x036A
> +#define MT6397_VSRMCA7_CON16		0x036C
> +#define MT6397_VSRMCA7_CON17		0x036E
> +#define MT6397_VSRMCA7_CON18		0x0370
> +#define MT6397_VSRMCA7_CON19		0x0372
> +#define MT6397_VSRMCA7_CON20		0x0374
> +#define MT6397_VSRMCA7_CON21		0x0376
> +#define MT6397_VDRM_CON0		0x0378
> +#define MT6397_VDRM_CON1		0x037A
> +#define MT6397_VDRM_CON2		0x037C
> +#define MT6397_VDRM_CON3		0x037E
> +#define MT6397_VDRM_CON4		0x0380
> +#define MT6397_VDRM_CON5		0x0382
> +#define MT6397_VDRM_CON6		0x0384
> +#define MT6397_VDRM_CON7		0x0386
> +#define MT6397_VDRM_CON8		0x0388
> +#define MT6397_VDRM_CON9		0x038A
> +#define MT6397_VDRM_CON10		0x038C
> +#define MT6397_VDRM_CON11		0x038E
> +#define MT6397_VDRM_CON12		0x0390
> +#define MT6397_VDRM_CON13		0x0392
> +#define MT6397_VDRM_CON14		0x0394
> +#define MT6397_VDRM_CON15		0x0396
> +#define MT6397_VDRM_CON16		0x0398
> +#define MT6397_VDRM_CON17		0x039A
> +#define MT6397_VDRM_CON18		0x039C
> +#define MT6397_BUCK_K_CON0		0x039E
> +#define MT6397_BUCK_K_CON1		0x03A0
> +#define MT6397_ANALDO_CON0		0x0400
> +#define MT6397_ANALDO_CON1		0x0402
> +#define MT6397_ANALDO_CON2		0x0404
> +#define MT6397_ANALDO_CON3		0x0406
> +#define MT6397_ANALDO_CON4		0x0408
> +#define MT6397_ANALDO_CON5		0x040A
> +#define MT6397_ANALDO_CON6		0x040C
> +#define MT6397_ANALDO_CON7		0x040E
> +#define MT6397_DIGLDO_CON0		0x0410
> +#define MT6397_DIGLDO_CON1		0x0412
> +#define MT6397_DIGLDO_CON2		0x0414
> +#define MT6397_DIGLDO_CON3		0x0416
> +#define MT6397_DIGLDO_CON4		0x0418
> +#define MT6397_DIGLDO_CON5		0x041A
> +#define MT6397_DIGLDO_CON6		0x041C
> +#define MT6397_DIGLDO_CON7		0x041E
> +#define MT6397_DIGLDO_CON8		0x0420
> +#define MT6397_DIGLDO_CON9		0x0422
> +#define MT6397_DIGLDO_CON10		0x0424
> +#define MT6397_DIGLDO_CON11		0x0426
> +#define MT6397_DIGLDO_CON12		0x0428
> +#define MT6397_DIGLDO_CON13		0x042A
> +#define MT6397_DIGLDO_CON14		0x042C
> +#define MT6397_DIGLDO_CON15		0x042E
> +#define MT6397_DIGLDO_CON16		0x0430
> +#define MT6397_DIGLDO_CON17		0x0432
> +#define MT6397_DIGLDO_CON18		0x0434
> +#define MT6397_DIGLDO_CON19		0x0436
> +#define MT6397_DIGLDO_CON20		0x0438
> +#define MT6397_DIGLDO_CON21		0x043A
> +#define MT6397_DIGLDO_CON22		0x043C
> +#define MT6397_DIGLDO_CON23		0x043E
> +#define MT6397_DIGLDO_CON24		0x0440
> +#define MT6397_DIGLDO_CON25		0x0442
> +#define MT6397_DIGLDO_CON26		0x0444
> +#define MT6397_DIGLDO_CON27		0x0446
> +#define MT6397_DIGLDO_CON28		0x0448
> +#define MT6397_DIGLDO_CON29		0x044A
> +#define MT6397_DIGLDO_CON30		0x044C
> +#define MT6397_DIGLDO_CON31		0x044E
> +#define MT6397_DIGLDO_CON32		0x0450
> +#define MT6397_DIGLDO_CON33		0x045A
> +#define MT6397_SPK_CON0			0x0600
> +#define MT6397_SPK_CON1			0x0602
> +#define MT6397_SPK_CON2			0x0604
> +#define MT6397_SPK_CON3			0x0606
> +#define MT6397_SPK_CON4			0x0608
> +#define MT6397_SPK_CON5			0x060A
> +#define MT6397_SPK_CON6			0x060C
> +#define MT6397_SPK_CON7			0x060E
> +#define MT6397_SPK_CON8			0x0610
> +#define MT6397_SPK_CON9			0x0612
> +#define MT6397_SPK_CON10		0x0614
> +#define MT6397_SPK_CON11		0x0616
> +#define MT6397_AUDDAC_CON0		0x0700
> +#define MT6397_AUDBUF_CFG0		0x0702
> +#define MT6397_AUDBUF_CFG1		0x0704
> +#define MT6397_AUDBUF_CFG2		0x0706
> +#define MT6397_AUDBUF_CFG3		0x0708
> +#define MT6397_AUDBUF_CFG4		0x070A
> +#define MT6397_IBIASDIST_CFG0		0x070C
> +#define MT6397_AUDACCDEPOP_CFG0		0x070E
> +#define MT6397_AUD_IV_CFG0		0x0710
> +#define MT6397_AUDCLKGEN_CFG0		0x0712
> +#define MT6397_AUDLDO_CFG0		0x0714
> +#define MT6397_AUDLDO_CFG1		0x0716
> +#define MT6397_AUDNVREGGLB_CFG0		0x0718
> +#define MT6397_AUD_NCP0			0x071A
> +#define MT6397_AUDPREAMP_CON0		0x071C
> +#define MT6397_AUDADC_CON0		0x071E
> +#define MT6397_AUDADC_CON1		0x0720
> +#define MT6397_AUDADC_CON2		0x0722
> +#define MT6397_AUDADC_CON3		0x0724
> +#define MT6397_AUDADC_CON4		0x0726
> +#define MT6397_AUDADC_CON5		0x0728
> +#define MT6397_AUDADC_CON6		0x072A
> +#define MT6397_AUDDIGMI_CON0		0x072C
> +#define MT6397_AUDLSBUF_CON0		0x072E
> +#define MT6397_AUDLSBUF_CON1		0x0730
> +#define MT6397_AUDENCSPARE_CON0		0x0732
> +#define MT6397_AUDENCCLKSQ_CON0		0x0734
> +#define MT6397_AUDPREAMPGAIN_CON0	0x0736
> +#define MT6397_ZCD_CON0			0x0738
> +#define MT6397_ZCD_CON1			0x073A
> +#define MT6397_ZCD_CON2			0x073C
> +#define MT6397_ZCD_CON3			0x073E
> +#define MT6397_ZCD_CON4			0x0740
> +#define MT6397_ZCD_CON5			0x0742
> +#define MT6397_NCP_CLKDIV_CON0		0x0744
> +#define MT6397_NCP_CLKDIV_CON1		0x0746
> +
> +#endif /* __MFD_MT6397_REGISTERS_H__ */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From lee.jones at linaro.org  Thu Feb 26 03:15:39 2015
From: lee.jones at linaro.org (Lee Jones)
Date: Thu, 26 Feb 2015 11:15:39 +0000
Subject: [PATCH 2/2] mfd: dt-bindings: Add bindings for the MediaTek
 MT6397 PMIC
In-Reply-To: <1424607330-1829-3-git-send-email-s.hauer@pengutronix.de>
References: <1424607330-1829-1-git-send-email-s.hauer@pengutronix.de>
 <1424607330-1829-3-git-send-email-s.hauer@pengutronix.de>
Message-ID: <20150226111539.GB14842@x1>

On Sun, 22 Feb 2015, Sascha Hauer wrote:

> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  Documentation/devicetree/bindings/mfd/mt6397.txt | 70 ++++++++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/mt6397.txt

Binding looks pretty inert.

Applied, thanks.

> diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
> new file mode 100644
> index 0000000..15043e6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
> @@ -0,0 +1,70 @@
> +MediaTek MT6397 Multifunction Device Driver
> +
> +MT6397 is a multifunction device with the following sub modules:
> +- Regulator
> +- RTC
> +- Audio codec
> +- GPIO
> +- Clock
> +
> +It is interfaced to host controller using SPI interface by a proprietary hardware
> +called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
> +See the following for pwarp node definitions:
> +Documentation/devicetree/bindings/soc/pwrap.txt
> +
> +This document describes the binding for MFD device and its sub module.
> +
> +Required properties:
> +compatible: "mediatek,mt6397"
> +
> +Optional subnodes:
> +
> +- rtc
> +	Required properties:
> +		- compatible: "mediatek,mt6397-rtc"
> +- regulators
> +	Required properties:
> +		- compatible: "mediatek,mt6397-regulator"
> +	see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
> +- codec
> +	Required properties:
> +		- compatible: "mediatek,mt6397-codec"
> +- clk
> +	Required properties:
> +		- compatible: "mediatek,mt6397-clk"
> +
> +Example:
> +	pwrap: pwrap at 1000f000 {
> +		compatible = "mediatek,mt8135-pwrap";
> +
> +		...
> +
> +		pmic {
> +			compatible = "mediatek,mt6397";
> +
> +			codec: mt6397codec {
> +				compatible = "mediatek,mt6397-codec";
> +			};
> +
> +			regulators {
> +				compatible = "mediatek,mt6397-regulator";
> +
> +				mt6397_vpca15_reg: buck_vpca15 {
> +					regulator-compatible = "buck_vpca15";
> +					regulator-name = "vpca15";
> +					regulator-min-microvolt = <850000>;
> +					regulator-max-microvolt = <1400000>;
> +					regulator-ramp-delay = <12500>;
> +					regulator-always-on;
> +				};
> +
> +				mt6397_vgp4_reg: ldo_vgp4 {
> +					regulator-compatible = "ldo_vgp4";
> +					regulator-name = "vgp4";
> +					regulator-min-microvolt = <1200000>;
> +					regulator-max-microvolt = <3300000>;
> +					regulator-enable-ramp-delay = <218>;
> +				};
> +			};
> +		};
> +	};

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


