clock: tl1: initial add tl1 clock driver
authorJian Hu <jian.hu@amlogic.com>
Tue, 11 Sep 2018 04:22:40 +0000 (12:22 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Sat, 29 Sep 2018 13:03:18 +0000 (06:03 -0700)
PD#172587: clock: tl1: initial add tl1 clock driver

Initial add tl1 clock driver refered to txlx clock driver.

Change-Id: I2f25c465ae7f3f4e65e842a9d0c35f0e0e75662f
Signed-off-by: Jian Hu <jian.hu@amlogic.com>
14 files changed:
Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt
MAINTAINERS
drivers/amlogic/clk/Makefile
drivers/amlogic/clk/clkc.h
drivers/amlogic/clk/tl1/Makefile [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1.h [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_ao.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk-mpll.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk-pll.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk_gpu.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk_media.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk_misc.c [new file with mode: 0644]
drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c [new file with mode: 0644]

index 7f42f88..a0588e4 100644 (file)
@@ -19,6 +19,8 @@ Required Properties:
        "amlogic,g12b-clkc-1"   - for g12b ee part1 clock
        "amlogic,g12b-clkc-2"   - for g12b ee part2 clock
        "amlogic,g12b-aoclkc"   - for g12b ao clock
+       "amlogic,tl1-clkc"      - for tl1 ee clock
+       "amlogic,tl1-aoclkc"    - for tl1 ao clock
 
 - reg: physical base address of the clock controller and length of memory
        mapped region.
index e126940..179435a 100644 (file)
@@ -14626,3 +14626,9 @@ F:      drivers/amlogic/input/sensor/cy8c4014.c
 F:     Documentation/devicetree/bindings/amlogic/input/pca9557_keypad.txt
 F:     drivers/amlogic/input/keyboard/pca9557_keypad.c
 F:     Documentation/devicetree/bindings/is31fl3236a.txt
+
+AMLOGIC TL1 CLOCK DRIVERS
+M:     Jian Hu <jian.hu@amlogic.com>
+F:     include/dt-bindings/clock/amlogic,tl1-clkc.h
+F:     drivers/amlogic/clk/tl1/*
+
index f7090d4..77fdb66 100644 (file)
@@ -17,5 +17,6 @@ obj-$(CONFIG_AMLOGIC_GX_CLK) += txlx/
 obj-$(CONFIG_AMLOGIC_GX_CLK) += txl/
 obj-$(CONFIG_AMLOGIC_GX_CLK) += g12a/
 obj-$(CONFIG_AMLOGIC_GX_CLK) += g12b/
+obj-$(CONFIG_AMLOGIC_GX_CLK) += tl1/
 
 obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/
index 4fae6a2..7deac3e 100644 (file)
@@ -258,6 +258,12 @@ extern const struct clk_ops meson_g12a_pcie_pll_ops;
 extern const struct clk_ops meson_g12a_mpll_ro_ops;
 extern const struct clk_ops meson_g12a_mpll_ops;
 
+extern const struct clk_ops meson_tl1_pll_ro_ops;
+extern const struct clk_ops meson_tl1_pll_ops;
+extern const struct clk_ops meson_tl1_mpll_ro_ops;
+extern const struct clk_ops meson_tl1_mpll_ops;
+
+
 extern void meson_clk_register_composite(struct clk **soc_clks,
                        struct meson_composite *composite,
                        unsigned int length);
@@ -291,5 +297,11 @@ void meson_g12a_media_init(void);
 void meson_g12a_gpu_init(void);
 void meson_g12a_misc_init(void);
 
+/*tl1*/
+void meson_tl1_sdemmc_init(void);
+void meson_tl1_media_init(void);
+void meson_tl1_gpu_init(void);
+void meson_tl1_misc_init(void);
+
 extern int clk_numbers;
 #endif /* __CLKC_H */
diff --git a/drivers/amlogic/clk/tl1/Makefile b/drivers/amlogic/clk/tl1/Makefile
new file mode 100644 (file)
index 0000000..cdc82ae
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for Meson TL1 clk
+#
+
+obj-$(CONFIG_AMLOGIC_GX_CLK) += tl1.o tl1_ao.o         \
+                               tl1_clk_sdemmc.o        \
+                               tl1_clk_media.o         \
+                               tl1_clk_misc.o          \
+                               tl1_clk_gpu.o           \
+                               tl1_clk-pll.o           \
+                               tl1_clk-mpll.o          \
diff --git a/drivers/amlogic/clk/tl1/tl1.c b/drivers/amlogic/clk/tl1/tl1.c
new file mode 100644 (file)
index 0000000..efe6814
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+#define MESON_GATE_TL1(_name, _reg, _bit)                      \
+struct clk_gate _name = {                                      \
+       .reg = (void __iomem *) _reg,                           \
+       .bit_idx = (_bit),                                      \
+       .lock = &clk_lock,                                      \
+       .hw.init = &(struct clk_init_data) {                    \
+               .name = #_name,                                 \
+               .ops = &clk_gate_ops,                           \
+               .parent_names = (const char *[]){ "clk81" },    \
+               .num_parents = 1,                               \
+               .flags = CLK_IGNORE_UNUSED,                     \
+       },                                                      \
+}
+
+
+static struct clk_onecell_data clk_data;
+
+static struct meson_clk_pll tl1_sys_pll = {
+       .m = {
+               .reg_off = HHI_SYS_PLL_CNTL0,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_SYS_PLL_CNTL0,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_SYS_PLL_CNTL0,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = tl1_pll_rate_table,
+       .rate_count = ARRAY_SIZE(tl1_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll",
+               .ops = &meson_tl1_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll tl1_gp0_pll = {
+       .m = {
+               .reg_off = HHI_GP0_PLL_CNTL0,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_GP0_PLL_CNTL0,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_GP0_PLL_CNTL0,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = tl1_pll_rate_table,
+       .rate_count = ARRAY_SIZE(tl1_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "gp0_pll",
+               .ops = &meson_tl1_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll tl1_gp1_pll = {
+       .m = {
+               .reg_off = HHI_GP1_PLL_CNTL0,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_GP1_PLL_CNTL0,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_GP1_PLL_CNTL0,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = tl1_pll_rate_table,
+       .rate_count = ARRAY_SIZE(tl1_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "gp1_pll",
+               .ops = &meson_tl1_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct meson_clk_pll tl1_hifi_pll = {
+       .m = {
+               .reg_off = HHI_HIFI_PLL_CNTL0,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_HIFI_PLL_CNTL0,
+               .shift   = 10,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_HIFI_PLL_CNTL0,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .rate_table = tl1_pll_rate_table,
+       .rate_count = ARRAY_SIZE(tl1_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "hifi_pll",
+               .ops = &meson_tl1_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+#if 0
+static struct meson_clk_pll tl1_adc_pll = {
+       .m = {
+               .reg_off = HHI_ADC_PLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_ADC_PLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_ADC_PLL_CNTL,
+               .shift   = 14,
+               .width   = 2,
+       },
+       .rate_table = sys_pll_rate_table,
+       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+#endif
+
+static struct meson_clk_pll tl1_fixed_pll = {
+       .m = {
+               .reg_off = HHI_FIX_PLL_CNTL0,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_FIX_PLL_CNTL0,
+               .shift   = 10,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_FIX_PLL_CNTL0,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .frac = {
+               .reg_off = HHI_FIX_PLL_CNTL1,
+               .shift   = 0,
+               .width   = 19,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "fixed_pll",
+               .ops = &meson_tl1_pll_ro_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+/*tl1 fixed multiplier and divider clock*/
+static struct clk_fixed_factor tl1_fclk_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor tl1_fclk_div3 = {
+       .mult = 1,
+       .div = 3,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor tl1_fclk_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor tl1_fclk_div5 = {
+       .mult = 1,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor tl1_fclk_div7 = {
+       .mult = 1,
+       .div = 7,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor tl1_fclk_div2p5 = {
+       .mult = 2,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2p5",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll tl1_mpll0 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL1,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL1,
+               .shift   = 20,
+               .width   = 9,
+       },
+       .sdm_en = 30,
+       .en_dds = 31,
+       .mpll_cntl0_reg = HHI_MPLL_CNTL0,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &meson_tl1_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll tl1_mpll1 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL3,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL3,
+               .shift   = 20,
+               .width   = 9,
+       },
+       .sdm_en = 30,
+       .en_dds = 31,
+       .mpll_cntl0_reg = HHI_MPLL_CNTL0,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &meson_tl1_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll tl1_mpll2 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL5,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL5,
+               .shift   = 20,
+               .width   = 9,
+       },
+       .sdm_en = 30,
+       .en_dds = 31,
+       .mpll_cntl0_reg = HHI_MPLL_CNTL0,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &meson_tl1_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll tl1_mpll3 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 20,
+               .width   = 9,
+       },
+       .sdm_en = 30,
+       .en_dds = 31,
+       .mpll_cntl0_reg = HHI_MPLL_CNTL0,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll3",
+               .ops = &meson_tl1_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+/*
+ *static struct meson_clk_pll tl1_hdmi_pll = {
+ *     .m = {
+ *             .reg_off = HHI_HDMI_PLL_CNTL,
+ *             .shift   = 0,
+ *             .width   = 9,
+ *     },
+ *     .n = {
+ *             .reg_off = HHI_HDMI_PLL_CNTL,
+ *             .shift   = 9,
+ *             .width   = 5,
+ *     },
+ *     .lock = &clk_lock,
+ *     .hw.init = &(struct clk_init_data){
+ *             .name = "hdmi_pll",
+ *             .ops = &meson_clk_pll_ro_ops,
+ *             .parent_names = (const char *[]){ "xtal" },
+ *             .num_parents = 1,
+ *             .flags = CLK_GET_RATE_NOCACHE,
+ *     },
+ * };
+ */
+
+/*
+ * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
+ * post-dividers and should be modelled with their respective PLLs via the
+ * forthcoming coordinated clock rates feature
+ */
+static u32 mux_table_cpu_p[]   = { 0, 1, 2 };
+static u32 mux_table_cpu_px[]   = { 0, 1 };
+static struct meson_cpu_mux_divider tl1_cpu_fclk_p = {
+       .reg = (void *)HHI_SYS_CPU_CLK_CNTL0,
+       .cpu_fclk_p00 = {
+               .mask = 0x3,
+               .shift = 0,
+               .width = 2,
+       },
+       .cpu_fclk_p0 = {
+               .mask = 0x1,
+               .shift = 2,
+               .width = 1,
+       },
+       .cpu_fclk_p10 = {
+               .mask = 0x3,
+               .shift = 16,
+               .width = 2,
+       },
+       .cpu_fclk_p1 = {
+               .mask = 0x1,
+               .shift = 18,
+               .width = 1,
+       },
+       .cpu_fclk_p = {
+               .mask = 0x1,
+               .shift = 10,
+               .width = 1,
+       },
+       .cpu_fclk_p01 = {
+               .shift = 4,
+               .width = 6,
+       },
+       .cpu_fclk_p11 = {
+               .shift = 20,
+               .width = 6,
+       },
+       .table = mux_table_cpu_p,
+       .rate_table = fclk_pll_rate_table,
+       .rate_count = ARRAY_SIZE(fclk_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_fixedpll_p",
+               .ops = &meson_fclk_cpu_ops,
+               .parent_names = (const char *[]){ "xtal", "fclk_div2",
+                       "fclk_div3"},
+               .num_parents = 3,
+               .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED),
+       },
+};
+
+static struct meson_clk_cpu tl1_cpu_clk = {
+       .reg_off = HHI_SYS_CPU_CLK_CNTL0,
+       .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
+       .mux.reg = (void *)HHI_SYS_CPU_CLK_CNTL0,
+       .mux.shift = 11,
+       .mux.mask = 0x1,
+       .mux.lock = &clk_lock,
+       .mux.table = mux_table_cpu_px,
+       .mux.hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &meson_clk_cpu_ops,
+               .parent_names = (const char *[]){ "cpu_fixedpll_p", "sys_pll"},
+               .num_parents = 2,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static u32 mux_table_clk81[]   = { 6, 5, 7 };
+
+static struct clk_mux tl1_mpeg_clk_sel = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 12,
+       .flags = CLK_MUX_READ_ONLY,
+       .table = mux_table_clk81,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_sel",
+               .ops = &clk_mux_ro_ops,
+               /*
+                * FIXME bits 14:12 selects from 8 possible parents:
+                * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
+                * fclk_div4, fclk_div3, fclk_div5
+                */
+               .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
+                       "fclk_div5" },
+               .num_parents = 3,
+               .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+static struct clk_divider tl1_mpeg_clk_div = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .shift = 0,
+       .width = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_sel" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+/* the mother of dragons^W gates */
+static struct clk_gate tl1_clk81 = {
+       .reg = (void *)HHI_MPEG_CLK_CNTL,
+       .bit_idx = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "clk81",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_div" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+       },
+};
+
+/* Everything Else (EE) domain gates */
+/* HHI_GCLK_MPEG0 26 bits valid */
+static MESON_GATE_TL1(tl1_ddr, HHI_GCLK_MPEG0,         0);
+static MESON_GATE_TL1(tl1_dos, HHI_GCLK_MPEG0,         1);
+static MESON_GATE_TL1(tl1_eth_phy, HHI_GCLK_MPEG0,     4);
+static MESON_GATE_TL1(tl1_isa, HHI_GCLK_MPEG0,         5);
+static MESON_GATE_TL1(tl1_pl310, HHI_GCLK_MPEG0,       6);
+static MESON_GATE_TL1(tl1_periphs, HHI_GCLK_MPEG0,     7);
+static MESON_GATE_TL1(tl1_i2c, HHI_GCLK_MPEG0,         9);
+static MESON_GATE_TL1(tl1_sana, HHI_GCLK_MPEG0,                10);
+static MESON_GATE_TL1(tl1_smart_card, HHI_GCLK_MPEG0,  11);
+static MESON_GATE_TL1(tl1_uart0, HHI_GCLK_MPEG0,       13);
+static MESON_GATE_TL1(tl1_stream, HHI_GCLK_MPEG0,      15);
+static MESON_GATE_TL1(tl1_async_fifo, HHI_GCLK_MPEG0,  16);
+static MESON_GATE_TL1(tl1_tvfe, HHI_GCLK_MPEG0,                18);
+static MESON_GATE_TL1(tl1_hiu_reg, HHI_GCLK_MPEG0,     19);
+static MESON_GATE_TL1(tl1_hdmirx_pclk, HHI_GCLK_MPEG0, 21);
+static MESON_GATE_TL1(tl1_atv_demod, HHI_GCLK_MPEG0,   22);
+static MESON_GATE_TL1(tl1_assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE_TL1(tl1_emmc_b, HHI_GCLK_MPEG0,      25);
+static MESON_GATE_TL1(tl1_emmc_c, HHI_GCLK_MPEG0,      26);
+static MESON_GATE_TL1(tl1_adec, HHI_GCLK_MPEG0,                27);
+static MESON_GATE_TL1(tl1_acodec, HHI_GCLK_MPEG0,      28);
+static MESON_GATE_TL1(tl1_tcon, HHI_GCLK_MPEG0,                29);
+static MESON_GATE_TL1(tl1_spi, HHI_GCLK_MPEG0,         30);
+static MESON_GATE_TL1(tl1_dsp, HHI_GCLK_MPEG0,         31);
+/* HHI_GCLK_MPEG1 11 bits valid */
+static MESON_GATE_TL1(tl1_audio, HHI_GCLK_MPEG1,       0);
+static MESON_GATE_TL1(tl1_eth_core, HHI_GCLK_MPEG1,    3);
+static MESON_GATE_TL1(tl1_demux, HHI_GCLK_MPEG1,       4);
+static MESON_GATE_TL1(tl1_aififo, HHI_GCLK_MPEG1,      11);
+static MESON_GATE_TL1(tl1_adc, HHI_GCLK_MPEG1,         13);
+static MESON_GATE_TL1(tl1_uart1, HHI_GCLK_MPEG1,       16);
+static MESON_GATE_TL1(tl1_g2d, HHI_GCLK_MPEG1,         20);
+static MESON_GATE_TL1(tl1_reset, HHI_GCLK_MPEG1,       23);
+static MESON_GATE_TL1(tl1_u_parser, HHI_GCLK_MPEG1,    25);
+static MESON_GATE_TL1(tl1_usb_general, HHI_GCLK_MPEG1, 26);
+static MESON_GATE_TL1(tl1_ahb_arb0, HHI_GCLK_MPEG1,    29);
+/* HHI_GCLK_MPEG2 11 bits valid */
+static MESON_GATE_TL1(tl1_ahb_data_bus, HHI_GCLK_MPEG2,        1);
+static MESON_GATE_TL1(tl1_ahb_ctrl_bus, HHI_GCLK_MPEG2,        2);
+static MESON_GATE_TL1(tl1_bt656, HHI_GCLK_MPEG2,       6);
+static MESON_GATE_TL1(tl1_usb1_to_ddr, HHI_GCLK_MPEG2, 8);
+static MESON_GATE_TL1(tl1_mmc_pclk, HHI_GCLK_MPEG2,    11);
+static MESON_GATE_TL1(tl1_hdcp22_pclk, HHI_GCLK_MPEG2, 13);
+static MESON_GATE_TL1(tl1_uart2, HHI_GCLK_MPEG2,       15);
+static MESON_GATE_TL1(tl1_ts, HHI_GCLK_MPEG2,          22);
+static MESON_GATE_TL1(tl1_demod_comb, HHI_GCLK_MPEG2,  25);
+static MESON_GATE_TL1(tl1_vpu_intr, HHI_GCLK_MPEG2,    28);
+static MESON_GATE_TL1(tl1_gic, HHI_GCLK_MPEG2,         30);
+/* HHI_GCLK_OTHER 17bits valid */
+static MESON_GATE_TL1(tl1_vclk2_venci0, HHI_GCLK_OTHER,        1);
+static MESON_GATE_TL1(tl1_vclk2_venci1, HHI_GCLK_OTHER,        2);
+static MESON_GATE_TL1(tl1_vclk2_vencp0, HHI_GCLK_OTHER,        3);
+static MESON_GATE_TL1(tl1_vclk2_vencp1, HHI_GCLK_OTHER,        4);
+static MESON_GATE_TL1(tl1_vclk2_venct0, HHI_GCLK_OTHER,        5);
+static MESON_GATE_TL1(tl1_vclk2_venct1, HHI_GCLK_OTHER,        6);
+static MESON_GATE_TL1(tl1_vclk2_other, HHI_GCLK_OTHER, 7);
+static MESON_GATE_TL1(tl1_vclk2_enci, HHI_GCLK_OTHER,  8);
+static MESON_GATE_TL1(tl1_vclk2_encp, HHI_GCLK_OTHER,  9);
+static MESON_GATE_TL1(tl1_dac_clk, HHI_GCLK_OTHER,     10);
+static MESON_GATE_TL1(tl1_enc480p, HHI_GCLK_OTHER,     20);
+static MESON_GATE_TL1(tl1_rng1, HHI_GCLK_OTHER,                21);
+static MESON_GATE_TL1(tl1_vclk2_enct, HHI_GCLK_OTHER,  22);
+static MESON_GATE_TL1(tl1_vclk2_encl, HHI_GCLK_OTHER,  23);
+static MESON_GATE_TL1(tl1_vclk2_venclmmc, HHI_GCLK_OTHER, 24);
+static MESON_GATE_TL1(tl1_vclk2_vencl, HHI_GCLK_OTHER, 25);
+static MESON_GATE_TL1(tl1_vclk2_other1, HHI_GCLK_OTHER,        26);
+/* end Everything Else (EE) domain gates */
+/* Always On (AO) domain gates */
+static MESON_GATE(tl1_dma, HHI_GCLK_AO,                        0);
+static MESON_GATE(tl1_efuse, HHI_GCLK_AO,              1);
+static MESON_GATE(tl1_rom_boot, HHI_GCLK_AO,           2);
+static MESON_GATE(tl1_reset_sec, HHI_GCLK_AO,          3);
+static MESON_GATE(tl1_sec_ahb_apb3, HHI_GCLK_AO,       4);
+
+static struct clk_gate tl1_spicc_0 = {
+       .reg = (void *)HHI_GCLK_MPEG0,
+       .bit_idx = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "tl1_spicc_0",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "clk81" },
+               .num_parents = 1,
+               .flags = 0,
+       },
+};
+
+static struct clk_gate tl1_spicc_1 = {
+       .reg = (void *)HHI_GCLK_MPEG0,
+       .bit_idx = 14,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "tl1_spicc_1",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "clk81" },
+               .num_parents = 1,
+               .flags = 0,
+       },
+};
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw *tl1_clk_hws[] = {
+       [CLKID_SYS_PLL]         = &tl1_sys_pll.hw,
+       [CLKID_FIXED_PLL]       = &tl1_fixed_pll.hw,
+       [CLKID_GP0_PLL]         = &tl1_gp0_pll.hw,
+       [CLKID_GP1_PLL]         = &tl1_gp1_pll.hw,
+       [CLKID_HIFI_PLL]        = &tl1_hifi_pll.hw,
+       /*[CLKID_ADC_PLL]       = &tl1_adc_pll.hw,*/
+       [CLKID_FCLK_DIV2]       = &tl1_fclk_div2.hw,
+       [CLKID_FCLK_DIV3]       = &tl1_fclk_div3.hw,
+       [CLKID_FCLK_DIV4]       = &tl1_fclk_div4.hw,
+       [CLKID_FCLK_DIV5]       = &tl1_fclk_div5.hw,
+       [CLKID_FCLK_DIV7]       = &tl1_fclk_div7.hw,
+       [CLKID_FCLK_DIV2P5]     = &tl1_fclk_div2p5.hw,
+       [CLKID_MPEG_SEL]        = &tl1_mpeg_clk_sel.hw,
+       [CLKID_MPEG_DIV]        = &tl1_mpeg_clk_div.hw,
+       [CLKID_CLK81]           = &tl1_clk81.hw,
+       [CLKID_MPLL0]           = &tl1_mpll0.hw,
+       [CLKID_MPLL1]           = &tl1_mpll1.hw,
+       [CLKID_MPLL2]           = &tl1_mpll2.hw,
+       [CLKID_MPLL3]           = &tl1_mpll3.hw,
+       [CLKID_DDR]             = &tl1_ddr.hw, /*MPEG0 0*/
+       [CLKID_DOS]             = &tl1_dos.hw, /*MPEG0 1*/
+       [CLKID_ETH_PHY]         = &tl1_eth_phy.hw, /*MPEG0 4*/
+       [CLKID_ISA]             = &tl1_isa.hw, /*MPEG0 5*/
+       [CLKID_PL310]           = &tl1_pl310.hw, /*MPEG0 6*/
+       [CLKID_PERIPHS]         = &tl1_periphs.hw, /*MPEG0 7*/
+       [CLKID_SPICC0]          = &tl1_spicc_0.hw, /*MPEG0 8*/
+       [CLKID_I2C]             = &tl1_i2c.hw, /*MPEG0 9*/
+       [CLKID_SANA]            = &tl1_sana.hw, /*MPEG0 10*/
+       [CLKID_SMART_CARD]      = &tl1_smart_card.hw, /*MPEG0 11*/
+       [CLKID_UART0]           = &tl1_uart0.hw, /*MPEG0 13*/
+       [CLKID_SPICC1]          = &tl1_spicc_1.hw, /*MPEG0 14*/
+       [CLKID_STREAM]          = &tl1_stream.hw, /*MPEG0 15*/
+       [CLKID_ASYNC_FIFO]      = &tl1_async_fifo.hw,/*MPEG0 16*/
+       [CLKID_TVFE]            = &tl1_tvfe.hw, /*MPEG0 18*/
+       [CLKID_HIU_REG]         = &tl1_hiu_reg.hw, /*MPEG0 19*/
+       [CLKID_HDMIRX_PCLK]     = &tl1_hdmirx_pclk.hw, /*MPEG0 21*/
+       [CLKID_ATV_DEMOD]       = &tl1_atv_demod.hw, /*MPEG0 22*/
+       [CLKID_ASSIST_MISC]     = &tl1_assist_misc.hw, /*MPEG0 23*/
+       [CLKID_SD_EMMC_B]       = &tl1_emmc_b.hw, /*MPEG0 25*/
+       [CLKID_SD_EMMC_C]       = &tl1_emmc_c.hw, /*MPEG0 26*/
+       [CLKID_ADEC]            = &tl1_adec.hw, /*MPEG0 27*/
+       [CLKID_ACODEC]          = &tl1_acodec.hw, /*MPEG0 28*/
+       [CLKID_TCON]            = &tl1_tcon.hw, /*MPEG0 29*/
+       [CLKID_SPI]             = &tl1_spi.hw, /*MPEG0 30*/
+       [CLKID_DSP]             = &tl1_dsp.hw, /*MPEG0 31*/
+       [CLKID_AUDIO]           = &tl1_audio.hw, /*MPEG1 0*/
+       [CLKID_ETH_CORE]        = &tl1_eth_core.hw, /*MPEG1 3*/
+       [CLKID_DEMUX]           = &tl1_demux.hw, /*MPEG1 4*/
+       [CLKID_AIFIFO]          = &tl1_aififo.hw,/*MPEG1 11*/
+       [CLKID_ADC]             = &tl1_adc.hw, /*MPEG1 13*/
+       [CLKID_UART1]           = &tl1_uart1.hw, /*MPEG1 16*/
+       [CLKID_G2D]             = &tl1_g2d.hw, /*MPEG1 20*/
+       [CLKID_RESET]           = &tl1_reset.hw, /*MPEG1 23*/
+       [CLKID_U_PARSER]        = &tl1_u_parser.hw, /*MPEG1 25*/
+       [CLKID_USB_GENERAL]     = &tl1_usb_general.hw, /*MPEG1 26*/
+       [CLKID_AHB_ARB0]        = &tl1_ahb_arb0.hw, /*MPEG1 29*/
+       [CLKID_AHB_DATA_BUS]    = &tl1_ahb_data_bus.hw, /*MPEG2 1*/
+       [CLKID_AHB_CTRL_BUS]    = &tl1_ahb_ctrl_bus.hw, /*MPEG2 2*/
+       [CLKID_BT656]           = &tl1_bt656.hw, /*MPEG2 6*/
+       [CLKID_USB1_TO_DDR]     = &tl1_usb1_to_ddr.hw, /*MPEG2 8*/
+       [CLKID_MMC_PCLK]        = &tl1_mmc_pclk.hw, /*MPEG2 11*/
+       [CLKID_HDCP22_PCLK]     = &tl1_hdcp22_pclk.hw, /*MPEG2 13*/
+       [CLKID_UART2]           = &tl1_uart2.hw, /*MPEG2 15*/
+       [CLKID_TS]              = &tl1_ts.hw, /*MPEG2 22*/
+       [CLKID_VPU_INTR]        = &tl1_vpu_intr.hw, /*MPEG2 25*/
+       [CLKID_DEMOD_COMB]      = &tl1_demod_comb.hw, /*MPEG2 28*/
+       [CLKID_GIC]             = &tl1_gic.hw, /*MPEG2 30*/
+       [CLKID_VCLK2_VENCI0]    = &tl1_vclk2_venci0.hw, /*OTHER 1*/
+       [CLKID_VCLK2_VENCI1]    = &tl1_vclk2_venci1.hw, /*OTHER 2*/
+       [CLKID_VCLK2_VENCP0]    = &tl1_vclk2_vencp0.hw, /*OTHER 3*/
+       [CLKID_VCLK2_VENCP1]    = &tl1_vclk2_vencp1.hw, /*OTHER 4*/
+       [CLKID_VCLK2_VENCT0]    = &tl1_vclk2_venct0.hw, /*OTHER 5*/
+       [CLKID_VCLK2_VENCT1]    = &tl1_vclk2_venct1.hw, /*OTHER 6*/
+       [CLKID_VCLK2_OTHER]     = &tl1_vclk2_other.hw, /*OTHER 7*/
+       [CLKID_VCLK2_ENCI]      = &tl1_vclk2_enci.hw, /*OTHER 8*/
+       [CLKID_VCLK2_ENCP]      = &tl1_vclk2_encp.hw, /*OTHER 9*/
+       [CLKID_DAC_CLK]         = &tl1_dac_clk.hw, /*OTHER 10*/
+       [CLKID_ENC480P]         = &tl1_enc480p.hw, /*OTHER 20*/
+       [CLKID_RNG1]            = &tl1_rng1.hw, /*OTHER 21*/
+       [CLKID_VCLK2_ENCT]      = &tl1_vclk2_enct.hw, /*OTHER 22*/
+       [CLKID_VCLK2_ENCL]      = &tl1_vclk2_encl.hw, /*OTHER 23*/
+       [CLKID_VCLK2_VENCLMMC]  = &tl1_vclk2_venclmmc.hw, /*OTHER 24*/
+       [CLKID_VCLK2_VENCL]     = &tl1_vclk2_vencl.hw, /*OTHER 25*/
+       [CLKID_VCLK2_OTHER1]    = &tl1_vclk2_other1.hw, /*OTHER 26*/
+       [CLKID_DMA]             = &tl1_dma.hw, /*AO 0*/
+       [CLKID_EFUSE]           = &tl1_efuse.hw, /*AO 1*/
+       [CLKID_ROM_BOOT]        = &tl1_rom_boot.hw, /*AO 2*/
+       [CLKID_RESET_SEC]       = &tl1_reset_sec.hw, /*AO 3*/
+       [CLKID_SEC_AHB_APB3]    = &tl1_sec_ahb_apb3.hw, /*AO 4*/
+
+       [CLKID_CPU_FCLK_P]      = &tl1_cpu_fclk_p.hw,
+       [CLKID_CPU_CLK]         = &tl1_cpu_clk.mux.hw,
+};
+/* Convenience tables to populate base addresses in .probe */
+
+static struct meson_clk_pll *const tl1_clk_plls[] = {
+       &tl1_fixed_pll,
+       &tl1_sys_pll,
+       &tl1_gp0_pll,
+       &tl1_gp1_pll,
+       &tl1_hifi_pll,
+       /*&tl1_adc_pll,*/
+       /*&tl1_hdmi_pll,*/
+};
+
+static struct meson_clk_mpll *const tl1_clk_mplls[] = {
+       &tl1_mpll0,
+       &tl1_mpll1,
+       &tl1_mpll2,
+       &tl1_mpll3,
+};
+
+static struct clk_gate *tl1_clk_gates[] = {
+       &tl1_clk81,
+       &tl1_ddr,
+       &tl1_dos,
+       &tl1_eth_phy,
+       &tl1_isa,
+       &tl1_pl310,
+       &tl1_periphs,
+       &tl1_spicc_0,
+       &tl1_i2c,
+       &tl1_sana,
+       &tl1_smart_card,
+       &tl1_uart0,
+       &tl1_spicc_1,
+       &tl1_stream,
+       &tl1_async_fifo,
+       &tl1_tvfe,
+       &tl1_hiu_reg,
+       &tl1_hdmirx_pclk,
+       &tl1_atv_demod,
+       &tl1_assist_misc,
+       &tl1_emmc_b,
+       &tl1_emmc_c,
+       &tl1_adec,
+       &tl1_acodec,
+       &tl1_tcon,
+       &tl1_spi,
+       &tl1_dsp,/*gate0 end*/
+       &tl1_audio,
+       &tl1_eth_core,
+       &tl1_demux,
+       &tl1_aififo,
+       &tl1_adc,
+       &tl1_uart1,
+       &tl1_g2d,
+       &tl1_reset,
+       &tl1_u_parser,
+       &tl1_usb_general,
+       &tl1_ahb_arb0, /*gate1 end*/
+       &tl1_ahb_data_bus,
+       &tl1_ahb_ctrl_bus,
+       &tl1_bt656,
+       &tl1_usb1_to_ddr,
+       &tl1_mmc_pclk,
+       &tl1_hdcp22_pclk,
+       &tl1_uart2,
+       &tl1_ts,
+       &tl1_vpu_intr,
+       &tl1_demod_comb,
+       &tl1_gic,/*gate2 end*/
+       &tl1_vclk2_venci0,
+       &tl1_vclk2_venci1,
+       &tl1_vclk2_vencp0,
+       &tl1_vclk2_vencp1,
+       &tl1_vclk2_venct0,
+       &tl1_vclk2_venct1,
+       &tl1_vclk2_other,
+       &tl1_vclk2_enci,
+       &tl1_vclk2_encp,
+       &tl1_dac_clk,
+       &tl1_enc480p,
+       &tl1_rng1,
+       &tl1_vclk2_enct,
+       &tl1_vclk2_encl,
+       &tl1_vclk2_venclmmc,
+       &tl1_vclk2_vencl,
+       &tl1_vclk2_other1,/* other end */
+       &tl1_dma,
+       &tl1_efuse,
+       &tl1_rom_boot,
+       &tl1_reset_sec,
+       &tl1_sec_ahb_apb3,
+};
+
+static void __init tl1_clkc_init(struct device_node *np)
+{
+       int clkid, i;
+       int ret = 0;
+       struct clk_hw *parent_hw;
+       struct clk *parent_clk;
+
+       /*  Generic clocks and PLLs */
+       clk_base = of_iomap(np, 0);
+       if (!clk_base) {
+               pr_err("%s: Unable to map clk base\n", __func__);
+               return;
+       }
+
+       /* Populate base address for PLLs */
+       for (i = 0; i < ARRAY_SIZE(tl1_clk_plls); i++)
+       tl1_clk_plls[i]->base = clk_base;
+
+       /* Populate base address for MPLLs */
+       for (i = 0; i < ARRAY_SIZE(tl1_clk_mplls); i++)
+       tl1_clk_mplls[i]->base = clk_base;
+
+       /* Populate the base address for the MPEG clks */
+       tl1_mpeg_clk_sel.reg = clk_base
+                       + (unsigned long)tl1_mpeg_clk_sel.reg;
+       tl1_mpeg_clk_div.reg = clk_base
+                       + (unsigned long)tl1_mpeg_clk_div.reg;
+
+       /* Populate the base address for CPU clk */
+       tl1_cpu_fclk_p.reg = clk_base
+                       + (unsigned long)tl1_cpu_fclk_p.reg;
+       tl1_cpu_clk.base = clk_base;
+       tl1_cpu_clk.mux.reg = clk_base
+                               + (unsigned long)tl1_cpu_clk.mux.reg;
+
+       /* Populate base address for gates */
+       for (i = 0; i < ARRAY_SIZE(tl1_clk_gates); i++)
+               tl1_clk_gates[i]->reg = clk_base +
+                       (unsigned long)tl1_clk_gates[i]->reg;
+
+       if (!clks) {
+               clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL);
+               if (!clks) {
+                       pr_err("%s: alloc clks fail!", __func__);
+                       return;
+               }
+       } else {
+               pr_err("%s: error: not kzalloc clks in eeclk!", __func__);
+               return;
+       }
+       clk_numbers = NR_CLKS;
+       clk_data.clks = clks;
+       clk_data.clk_num = NR_CLKS;
+
+       /*register all clks*/
+       for (clkid = 0; clkid < CLOCK_GATE; clkid++) {
+               if (tl1_clk_hws[clkid]) {
+               clks[clkid] = clk_register(NULL, tl1_clk_hws[clkid]);
+               WARN_ON(IS_ERR(clks[clkid]));
+               }
+       }
+
+       meson_tl1_sdemmc_init();
+       meson_tl1_media_init();
+       meson_tl1_gpu_init();
+       meson_tl1_misc_init();
+
+       parent_hw = clk_hw_get_parent(&tl1_cpu_clk.mux.hw);
+       parent_clk = parent_hw->clk;
+       ret = clk_notifier_register(parent_clk, &tl1_cpu_clk.clk_nb);
+       if (ret) {
+               pr_err("%s: failed to register clock notifier for cpu_clk\n",
+               __func__);
+               goto iounmap;
+       }
+
+       ret = of_clk_add_provider(np, of_clk_src_onecell_get,
+                       &clk_data);
+       if (ret < 0) {
+               pr_err("%s fail ret: %d\n", __func__, ret);
+               return;
+       }
+
+       return;
+
+iounmap:
+       iounmap(clk_base);
+       pr_err("%s iomap failed ret: %d\n", __func__, ret);
+}
+
+CLK_OF_DECLARE(tl1, "amlogic,tl1-clkc", tl1_clkc_init);
diff --git a/drivers/amlogic/clk/tl1/tl1.h b/drivers/amlogic/clk/tl1/tl1.h
new file mode 100644 (file)
index 0000000..92d8996
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1.h
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __TL1_H
+#define __TL1_H
+
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the data sheet are listed in comment blocks below.
+ * Those offsets must be multiplied by 4 before adding them to the base address
+ * to get the right value
+ */
+#define HHI_GP0_PLL_CNTL0              0x40 /* 0x10 offset in datasheet very*/
+#define HHI_GP0_PLL_CNTL1              0x44 /* 0x11 offset in datasheet */
+#define HHI_GP0_PLL_CNTL2              0x48 /* 0x12 offset in datasheet */
+#define HHI_GP0_PLL_CNTL3              0x4c /* 0x13 offset in datasheet */
+#define HHI_GP0_PLL_CNTL4              0x50 /* 0x14 offset in datasheet */
+#define HHI_GP0_PLL_CNTL5              0x54 /* 0x15 offset in datasheet */
+#define HHI_GP0_PLL_CNTL6              0x58 /* 0x16 offset in datasheet */
+#define HHI_GP0_PLL_STS                        0x5c /* 0x17 offset in datasheet */
+#define HHI_GP1_PLL_CNTL0              0x60 /* 0x18 offset in datasheet */
+#define HHI_GP1_PLL_CNTL1              0x64 /* 0x19 offset in datasheet */
+#define HHI_GP1_PLL_CNTL2              0x68 /* 0x1a offset in datasheet */
+#define HHI_GP1_PLL_CNTL3              0x6c /* 0x1b offset in datasheet */
+#define HHI_GP1_PLL_CNTL4              0x70 /* 0x1c offset in datasheet */
+#define HHI_GP1_PLL_CNTL5              0x74 /* 0x1d offset in datasheet */
+#define HHI_GP1_PLL_CNTL6              0x78 /* 0x1e offset in datasheet */
+#define HHI_GP1_PLL_STS                        0x7c /* 0x1f offset in datasheet very*/
+
+#define HHI_HIFI_PLL_CNTL0             0xd8 /* 0x36 offset in datasheet very*/
+#define HHI_HIFI_PLL_CNTL1             0xdc /* 0x37 offset in datasheet */
+#define HHI_HIFI_PLL_CNTL2             0xe0 /* 0x38 offset in datasheet */
+#define HHI_HIFI_PLL_CNTL4             0xe4 /* 0x39 offset in datasheet */
+#define HHI_HIFI_PLL_CNTL5             0xe8 /* 0x3a offset in datasheet */
+#define HHI_HIFI_PLL_CNTL6             0xec /* 0x3b offset in datasheet */
+#define HHI_HIFI_PLL_STS               0xf0 /* 0x3c offset in datasheet very*/
+
+#define HHI_GCLK_MPEG0                 0x140 /* 0x50 offset in datasheet */
+#define HHI_GCLK_MPEG1                 0x144 /* 0x51 offset in datasheet */
+#define HHI_GCLK_MPEG2                 0x148 /* 0x52 offset in datasheet */
+#define HHI_GCLK_OTHER                 0x150 /* 0x54 offset in datasheet */
+
+#define HHI_GCLK_AO                    0x154 /* 0x55 offset in datasheet */
+
+#define HHI_VID_CLK_DIV                        0x164 /* 0x59 offset in datasheet */
+#define HHI_SPICC_HCLK_CNTL            0x168 /* 0x5a offset in datasheet */
+
+#define HHI_MPEG_CLK_CNTL              0x174 /* 0x5d offset in datasheet */
+#define HHI_VID_CLK_CNTL               0x17c /* 0x5f offset in datasheet */
+#define HHI_TS_CLK_CNTL                        0x190 /* 0x64 offset in datasheet1 */
+#define HHI_VID_CLK_CNTL2              0x194 /* 0x65 offset in datasheet */
+#define HHI_SYS_CPU_CLK_CNTL0          0x19c /* 0x67 offset in datasheet */
+#define HHI_AUD_CLK_CNTL3              0x1A4 /* 0x69 offset in datasheet */
+#define HHI_AUD_CLK_CNTL4              0x1A8 /* 0x6a offset in datasheet */
+#define HHI_MALI_CLK_CNTL              0x1b0 /* 0x6c offset in datasheet */
+#define HHI_VPU_CLKC_CNTL              0x1b4 /* 0x6d offset in datasheet1 */
+#define HHI_VPU_CLK_CNTL               0x1bC /* 0x6f offset in datasheet1 */
+#define HHI_AUDPLL_CLK_OUT_CNTL        0x1E0 /* 0x74 offset in datasheet1 */
+#define HHI_VDEC_CLK_CNTL              0x1E0 /* 0x78 offset in datasheet1 */
+#define HHI_VDEC2_CLK_CNTL             0x1E4 /* 0x79 offset in datasheet1 */
+#define HHI_VDEC3_CLK_CNTL             0x1E8 /* 0x7a offset in datasheet1 */
+#define HHI_VDEC4_CLK_CNTL             0x1EC /* 0x7b offset in datasheet1 */
+#define HHI_HDCP22_CLK_CNTL            0x1F0 /* 0x7c offset in datasheet1 */
+#define HHI_VAPBCLK_CNTL               0x1F4 /* 0x7d offset in datasheet1 */
+#define HHI_HDMIRX_CLK_CNTL            0x200 /* 0x80 offset in datasheet1 */
+#define HHI_HDMIRX_AUD_CLK_CNTL                0x204 /* 0x81 offset in datasheet1 */
+#define HHI_VPU_CLKB_CNTL              0x20C /* 0x83 offset in datasheet1 */
+
+#define HHI_VDIN_MEAS_CLK_CNTL         0x250 /* 0x94 offset in datasheet1 */
+#define HHI_NAND_CLK_CNTL              0x25C /* 0x97 offset in datasheet1*/
+#define HHI_SD_EMMC_CLK_CNTL           0x264 /* 0x99 offset in datasheet1*/
+#define HHI_TCON_CLK_CNTL              0x270 /* 0x9c offset in datasheet1*/
+
+#define HHI_MPLL_CNTL0                 0x278 /* 0x9e offset in datasheet very*/
+#define HHI_MPLL_CNTL1                 0x27c /* 0x9f offset in datasheet */
+#define HHI_MPLL_CNTL2                 0x280 /* 0xa0 offset in datasheet */
+#define HHI_MPLL_CNTL3                 0x284 /* 0xa1 offset in datasheet */
+#define HHI_MPLL_CNTL4                 0x288 /* 0xa2 offset in datasheet */
+#define HHI_MPLL_CNTL5                 0x28c /* 0xa3 offset in datasheet */
+#define HHI_MPLL_CNTL6                 0x290 /* 0xa4 offset in datasheet */
+#define HHI_MPLL_CNTL7                 0x294 /* 0xa5 offset in datasheet */
+#define HHI_MPLL_CNTL8                 0x298 /* 0xa6 offset in datasheet */
+#define HHI_MPLL_STS                   0x29c /* 0xa7 offset in datasheet very*/
+
+#define HHI_FIX_PLL_CNTL0              0x2a0 /* 0xa8 offset in datasheet very*/
+#define HHI_FIX_PLL_CNTL1              0x2a4 /* 0xa9 offset in datasheet */
+#define HHI_FIX_PLL_CNTL2              0x2a8 /* 0xaa offset in datasheet */
+#define HHI_FIX_PLL_CNTL3              0x2ac /* 0xab offset in datasheet */
+#define HHI_FIX_PLL_CNTL4              0x2b0 /* 0xac offset in datasheet */
+#define HHI_FIX_PLL_CNTL5              0x2b4 /* 0xad offset in datasheet */
+#define HHI_FIX_PLL_CNTL6              0x2b8 /* 0xae offset in datasheet */
+#define HHI_FIX_PLL_STS                        0x2bc /* 0xaf offset in datasheet very*/
+
+#define HHI_MPLL3_CNTL0                        0x2E0 /* 0xb8 offset in datasheet */
+#define HHI_MPLL3_CNTL1                        0x2E4 /* 0xb9 offset in datasheet */
+#define HHI_PLL_TOP_MISC               0x2E8 /* 0xba offset in datasheet */
+
+#define HHI_ADC_PLL_CNTL               0x2A8 /* 0xaa offset in datasheet */
+#define HHI_ADC_PLL_CNTL2              0x2AC /* 0xab offset in datasheet */
+#define HHI_ADC_PLL_CNTL3              0x2B0 /* 0xac offset in datasheet */
+#define HHI_ADC_PLL_CNTL4              0x2B4 /* 0xad offset in datasheet */
+
+#define HHI_SYS_PLL_CNTL0              0x2f4 /* 0xbd offset in datasheet */
+#define HHI_SYS_PLL_CNTL1              0x2f8 /* 0xbe offset in datasheet */
+#define HHI_SYS_PLL_CNTL2              0x2fc /* 0xbf offset in datasheet */
+#define HHI_SYS_PLL_CNTL3              0x300 /* 0xc0 offset in datasheet */
+#define HHI_SYS_PLL_CNTL4              0x304 /* 0xc1 offset in datasheet */
+#define HHI_SYS_PLL_CNTL5              0x308 /* 0xc2 offset in datasheet */
+#define HHI_SYS_PLL_CNTL6              0x30c /* 0xc3 offset in datasheet */
+
+#define HHI_HDMI_PLL_CNTL              0x320 /* 0xc8 offset in datasheet */
+#define HHI_HDMI_PLL_CNTL2             0x324 /* 0xc9 offset in datasheet */
+#define HHI_HDMI_PLL_CNTL3             0x328 /* 0xca offset in datasheet */
+#define HHI_HDMI_PLL_CNTL4             0x32C /* 0xcb offset in datasheet */
+#define HHI_HDMI_PLL_CNTL5             0x330 /* 0xcc offset in datasheet */
+#define HHI_VID_LOCK_CLK_CNTL          0x3c8 /* 0xf2 offset in datasheet1 */
+#define HHI_BT656_CLK_CNTL             0x3d4 /* 0xf5 offset in datasheet1 */
+#define HHI_SPICC_CLK_CNTL             0x3dc /* 0xf7 offset in datasheet1 */
+
+/* AO registers*/
+#define AO_RTI_PWR_CNTL_REG0           0x10 /* 0x4 offset in datasheet1*/
+#define AO_CLK_GATE0                   0x4c /* 0x13 offset in datasheet1 */
+#define AO_CLK_GATE0_SP                        0x50 /* 0x14 offset in datasheet1 */
+#define AO_SAR_CLK                     0x90 /* 0x24 offset in datasheet1 */
+
+/*tl1: pll: FDCO: 3G~6G FDCO = 24*(M+frac)/N
+ *N: recommend is 1
+ *clk_out = FDCO >> OD
+ */
+static const struct pll_rate_table tl1_pll_rate_table[] = {
+       PLL_RATE(24000000ULL,   128, 1, 7), /*DCO=3072M*/
+       PLL_RATE(48000000ULL,   128, 1, 6), /*DCO=3072M*/
+       PLL_RATE(96000000ULL,   128, 1, 5), /*DCO=3072M*/
+       PLL_RATE(192000000ULL,  128, 1, 4), /*DCO=3072M*/
+       PLL_RATE(312000000ULL,  208, 1, 4), /*DCO=4992M*/
+       PLL_RATE(408000000ULL,  136, 1, 3), /*DCO=3264M*/
+       PLL_RATE(600000000ULL,  200, 1, 3), /*DCO=4800M*/
+       PLL_RATE(696000000ULL,  232, 1, 3), /*DCO=5568M*/
+       PLL_RATE(792000000ULL,  132, 1, 2), /*DCO=3168M*/
+       PLL_RATE(846000000ULL,  141, 1, 2), /*DCO=3384M*/
+       PLL_RATE(912000000ULL,  152, 1, 2), /*DCO=3648M*/
+       PLL_RATE(1008000000ULL, 168, 1, 2), /*DCO=4032M*/
+       PLL_RATE(1104000000ULL, 184, 1, 2), /*DCO=4416M*/
+       PLL_RATE(1200000000ULL, 200, 1, 2), /*DCO=4800M*/
+       PLL_RATE(1296000000ULL, 216, 1, 2), /*DCO=5184M*/
+       PLL_RATE(1398000000ULL, 233, 1, 2), /*DCO=5592M*/
+       PLL_RATE(1494000000ULL, 249, 1, 2), /*DCO=5976M*/
+       PLL_RATE(1512000000ULL, 126, 1, 1), /*DCO=3024M*/
+       PLL_RATE(1608000000ULL, 134, 1, 1), /*DCO=3216M*/
+       PLL_RATE(1704000000ULL, 142, 1, 1), /*DCO=3408M*/
+       PLL_RATE(1800000000ULL, 150, 1, 1), /*DCO=3600M*/
+       PLL_RATE(1896000000ULL, 158, 1, 1), /*DCO=3792M*/
+       PLL_RATE(1908000000ULL, 159, 1, 1), /*DCO=3816M*/
+       PLL_RATE(1920000000ULL, 160, 1, 1), /*DCO=3840M*/
+       PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/
+       PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/
+       PLL_RATE(2196000000ULL, 183, 1, 1), /*DCO=4392M*/
+       PLL_RATE(2292000000ULL, 191, 1, 1), /*DCO=4584M*/
+       PLL_RATE(2400000000ULL, 200, 1, 1), /*DCO=4800M*/
+       PLL_RATE(2496000000ULL, 208, 1, 1), /*DCO=4992M*/
+       PLL_RATE(2592000000ULL, 216, 1, 1), /*DCO=5184M*/
+       PLL_RATE(2700000000ULL, 225, 1, 1), /*DCO=5400M*/
+       PLL_RATE(2796000000ULL, 233, 1, 1), /*DCO=5592M*/
+       PLL_RATE(2892000000ULL, 241, 1, 1), /*DCO=5784M*/
+       PLL_RATE(3000000000ULL, 125, 1, 0), /*DCO=3000M*/
+       PLL_RATE(3096000000ULL, 129, 1, 0), /*DCO=3096M*/
+       PLL_RATE(3192000000ULL, 133, 1, 0), /*DCO=3192M*/
+       PLL_RATE(3288000000ULL, 137, 1, 0), /*DCO=3288M*/
+       PLL_RATE(3408000000ULL, 142, 1, 0), /*DCO=3408M*/
+       PLL_RATE(3504000000ULL, 146, 1, 0), /*DCO=3504M*/
+       PLL_RATE(3600000000ULL, 150, 1, 0), /*DCO=3600M*/
+       PLL_RATE(3696000000ULL, 154, 1, 0), /*DCO=3696M*/
+       PLL_RATE(3792000000ULL, 158, 1, 0), /*DCO=3792M*/
+       PLL_RATE(3888000000ULL, 162, 1, 0), /*DCO=3888M*/
+       PLL_RATE(4008000000ULL, 167, 1, 0), /*DCO=4008M*/
+       PLL_RATE(4104000000ULL, 171, 1, 0), /*DCO=4104M*/
+       PLL_RATE(4200000000ULL, 175, 1, 0), /*DCO=4200M*/
+       PLL_RATE(4296000000ULL, 179, 1, 0), /*DCO=4296M*/
+       PLL_RATE(4392000000ULL, 183, 1, 0), /*DCO=4392M*/
+       PLL_RATE(4488000000ULL, 187, 1, 0), /*DCO=4488M*/
+       PLL_RATE(4608000000ULL, 192, 1, 0), /*DCO=4608M*/
+       PLL_RATE(4704000000ULL, 196, 1, 0), /*DCO=4704M*/
+       PLL_RATE(4800000000ULL, 200, 1, 0), /*DCO=4800M*/
+       PLL_RATE(4896000000ULL, 204, 1, 0), /*DCO=4896M*/
+       PLL_RATE(4992000000ULL, 208, 1, 0), /*DCO=4992M*/
+       PLL_RATE(5088000000ULL, 212, 1, 0), /*DCO=5088M*/
+       PLL_RATE(5208000000ULL, 217, 1, 0), /*DCO=5208M*/
+       PLL_RATE(5304000000ULL, 221, 1, 0), /*DCO=5304M*/
+       PLL_RATE(5400000000ULL, 225, 1, 0), /*DCO=5400M*/
+       PLL_RATE(5496000000ULL, 229, 1, 0), /*DCO=5496M*/
+       PLL_RATE(5592000000ULL, 233, 1, 0), /*DCO=5592M*/
+       PLL_RATE(5688000000ULL, 237, 1, 0), /*DCO=5688M*/
+       PLL_RATE(5808000000ULL, 242, 1, 0), /*DCO=5808M*/
+       PLL_RATE(5904000000ULL, 246, 1, 0), /*DCO=5904M*/
+       PLL_RATE(6000000000ULL, 250, 1, 0), /*DCO=6000M*/
+
+       { /* sentinel */ },
+
+};
+
+/*fix pll rate table*/
+static const struct fclk_rate_table fclk_pll_rate_table[] = {
+       FCLK_PLL_RATE(50000000, 1, 1, 19),
+       FCLK_PLL_RATE(100000000, 1, 1, 9),
+       FCLK_PLL_RATE(167000000, 2, 1, 3),
+       FCLK_PLL_RATE(200000000, 1, 1, 4),
+       FCLK_PLL_RATE(250000000, 1, 1, 3),
+       FCLK_PLL_RATE(333000000, 2, 1, 1),
+       FCLK_PLL_RATE(500000000, 1, 1, 1),
+       FCLK_PLL_RATE(667000000, 2, 0, 0),
+       FCLK_PLL_RATE(1000000000, 1, 0, 0),
+};
+
+#endif /* __TL1_H */
diff --git a/drivers/amlogic/clk/tl1/tl1_ao.c b/drivers/amlogic/clk/tl1/tl1_ao.c
new file mode 100644 (file)
index 0000000..b3c099c
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_ao.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+#define MESON_AO_GATE_TL1(_name, _reg, _bit)                   \
+struct clk_gate _name = {                                      \
+       .reg = (void __iomem *) _reg,                           \
+       .bit_idx = (_bit),                                      \
+       .lock = &clk_lock,                                      \
+       .hw.init = &(struct clk_init_data) {                    \
+               .name = #_name,                                 \
+               .ops = &clk_gate_ops,                           \
+               .parent_names = (const char *[]){ "clk81" },    \
+               .num_parents = 1,                               \
+               .flags = CLK_IGNORE_UNUSED,                     \
+       },                                                      \
+}
+
+/* tl1 ao clock gates */
+MESON_AO_GATE_TL1(tl1_ao_ahb_bus, AO_CLK_GATE0, 0);
+MESON_AO_GATE_TL1(tl1_ao_ir, AO_CLK_GATE0, 1);
+MESON_AO_GATE_TL1(tl1_ao_i2c_master, AO_CLK_GATE0, 2);
+MESON_AO_GATE_TL1(tl1_ao_i2c_slave, AO_CLK_GATE0, 3);
+MESON_AO_GATE_TL1(tl1_ao_uart1, AO_CLK_GATE0, 4);
+MESON_AO_GATE_TL1(tl1_ao_prod_i2c, AO_CLK_GATE0, 5);
+MESON_AO_GATE_TL1(tl1_ao_uart2, AO_CLK_GATE0, 6);
+MESON_AO_GATE_TL1(tl1_ao_ir_blaster, AO_CLK_GATE0, 7);
+MESON_AO_GATE_TL1(tl1_ao_sar_adc, AO_CLK_GATE0, 8);
+/* FIXME for AO_CLK_GATE0_SP clocks */
+
+static struct clk_mux aoclk81 = {
+       .reg = (void *)AO_RTI_PWR_CNTL_REG0,
+       .mask = 0x1,
+       .shift = 8,
+       .flags = CLK_MUX_READ_ONLY,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "aoclk81",
+               .ops = &clk_mux_ops,
+               .parent_names = (const char *[]){ "clk81", "ao_slow_clk" },
+               .num_parents = 2,
+               .flags = (CLK_SET_RATE_NO_REPARENT),
+       },
+};
+
+/* sar_adc_clk */
+static struct clk_mux tl1_saradc_mux = {
+       .reg = (void *)AO_SAR_CLK,
+       .mask = 0x3,
+       .shift = 9,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "tl1_saradc_mux",
+               .ops = &clk_mux_ops,
+               .parent_names = (const char *[]){ "xtal", "aoclk81"},
+               .num_parents = 2,
+               .flags = (CLK_GET_RATE_NOCACHE),
+       },
+};
+
+static struct clk_divider tl1_saradc_div = {
+       .reg = (void *)AO_SAR_CLK,
+       .shift = 0,
+       .width = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "tl1_saradc_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "tl1_saradc_mux" },
+               .num_parents = 1,
+               .flags = (CLK_DIVIDER_ROUND_CLOSEST),
+       },
+};
+
+static struct clk_gate tl1_saradc_gate = {
+       .reg = (void *)AO_SAR_CLK,
+       .bit_idx = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "tl1_saradc_gate",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "tl1_saradc_div" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT),
+       },
+};
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw *tl1_ao_clk_hws[] = {
+       [CLKID_AO_CLK81 - CLKID_AO_CLK81]
+               = &aoclk81.hw,
+       [CLKID_SARADC_MUX - CLKID_AO_CLK81]
+               = &tl1_saradc_mux.hw,
+       [CLKID_SARADC_DIV - CLKID_AO_CLK81]
+               = &tl1_saradc_div.hw,
+       [CLKID_SARADC_GATE - CLKID_AO_CLK81]
+               = &tl1_saradc_gate.hw,
+       [CLKID_AO_AHB_BUS - CLKID_AO_CLK81]
+               = &tl1_ao_ahb_bus.hw,
+       [CLKID_AO_IR - CLKID_AO_CLK81]
+               = &tl1_ao_ir.hw,
+       [CLKID_AO_I2C_MASTER - CLKID_AO_CLK81]
+               = &tl1_ao_i2c_master.hw,
+       [CLKID_AO_I2C_SLAVE - CLKID_AO_CLK81]
+               = &tl1_ao_i2c_slave.hw,
+       [CLKID_AO_UART1 - CLKID_AO_CLK81]
+               = &tl1_ao_uart1.hw,
+       [CLKID_AO_PROD_I2C - CLKID_AO_CLK81]
+               = &tl1_ao_prod_i2c.hw,
+       [CLKID_AO_UART2 - CLKID_AO_CLK81]
+               = &tl1_ao_uart2.hw,
+       [CLKID_AO_IR_BLASTER - CLKID_AO_CLK81]
+               = &tl1_ao_ir_blaster.hw,
+       [CLKID_AO_SAR_ADC - CLKID_AO_CLK81]
+               = &tl1_ao_sar_adc.hw,
+};
+
+static struct clk_gate *tl1_ao_clk_gates[] = {
+       &tl1_ao_ahb_bus,
+       &tl1_ao_i2c_master,
+       &tl1_ao_i2c_slave,
+       &tl1_ao_uart1,
+       &tl1_ao_prod_i2c,
+       &tl1_ao_uart2,
+       &tl1_ao_ir_blaster,
+       &tl1_ao_sar_adc,
+};
+
+static int tl1_aoclkc_probe(struct platform_device *pdev)
+{
+       void __iomem *aoclk_base;
+       int clkid, i;
+       struct device *dev = &pdev->dev;
+
+       /*  Generic clocks and PLLs */
+       aoclk_base = of_iomap(dev->of_node, 0);
+       if (!aoclk_base) {
+               pr_err("%s: Unable to map clk base\n", __func__);
+               return -ENXIO;
+       }
+       /* Populate the base address for ao clk */
+       for (i = 0; i < ARRAY_SIZE(tl1_ao_clk_gates); i++)
+               tl1_ao_clk_gates[i]->reg = aoclk_base +
+                       (unsigned long)tl1_ao_clk_gates[i]->reg;
+
+       aoclk81.reg = aoclk_base + (unsigned long)aoclk81.reg;
+       tl1_saradc_mux.reg = aoclk_base + (unsigned long)tl1_saradc_mux.reg;
+       tl1_saradc_div.reg = aoclk_base + (unsigned long)tl1_saradc_div.reg;
+       tl1_saradc_gate.reg = aoclk_base + (unsigned long)tl1_saradc_gate.reg;
+
+       for (clkid = CLKID_AO_BASE; clkid < NR_CLKS; clkid++) {
+               if (tl1_ao_clk_hws[clkid-CLKID_AO_BASE]) {
+                       clks[clkid] = clk_register(NULL,
+                       tl1_ao_clk_hws[clkid-CLKID_AO_BASE]);
+                       WARN_ON(IS_ERR(clks[clkid]));
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id tl1_aoclkc_match_table[] = {
+       { .compatible = "amlogic,tl1-aoclkc" },
+       { },
+};
+
+static struct platform_driver tl1_aoclk_driver = {
+       .probe          = tl1_aoclkc_probe,
+       .driver         = {
+               .name   = "tl1-aoclkc",
+               .of_match_table = tl1_aoclkc_match_table,
+       },
+};
+
+builtin_platform_driver(tl1_aoclk_driver);
diff --git a/drivers/amlogic/clk/tl1/tl1_clk-mpll.c b/drivers/amlogic/clk/tl1/tl1_clk-mpll.c
new file mode 100644 (file)
index 0000000..81e9dfe
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk-mpll.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * MultiPhase Locked Loops are outputs from a PLL with additional frequency
+ * scaling capabilities. MPLL rates are calculated as:
+ *
+ * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+
+#include "../clkc.h"
+/* #undef pr_debug */
+/* #define pr_debug pr_info */
+#define SDM_MAX 16384
+#define MAX_RATE       500000000
+#define MIN_RATE       3920000
+
+#define TL1_MPLL_CNTL0 0x00000543
+#define TL1_MPLL_CNTL2 0x40000033
+
+
+#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
+
+static unsigned long mpll_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long rate = 0;
+       unsigned long reg, sdm, n2;
+       u64 rate64 = parent_rate;
+
+       p = &mpll->sdm;
+       reg = readl(mpll->base + p->reg_off);
+       sdm = PARM_GET(p->width, p->shift, reg);
+
+       p = &mpll->n2;
+       reg = readl(mpll->base + p->reg_off);
+       n2 = PARM_GET(p->width, p->shift, reg);
+
+       if (n2 == 0 && sdm == 0) {
+               rate = 0;
+       } else {
+               rate64 = rate64 * SDM_MAX;
+               do_div(rate64, ((SDM_MAX * n2) + sdm));
+               rate = rate64;
+       }
+
+       return rate;
+}
+
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                    unsigned long *parent_rate)
+{
+       unsigned long rate_val = rate;
+
+       if (rate_val < MIN_RATE)
+               rate = MIN_RATE;
+       if (rate_val > MAX_RATE)
+               rate = MAX_RATE;
+
+       return rate_val;
+}
+
+
+static int mpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long reg, sdm, n2;
+       unsigned long flags = 0;
+
+       if ((rate > MAX_RATE) || (rate < MIN_RATE)) {
+               pr_err("Err: can not set rate to %lu!\n", rate);
+               pr_err("Range[3920000 - 500000000]\n");
+               return -1;
+       }
+
+       if (mpll->lock)
+               spin_lock_irqsave(mpll->lock, flags);
+
+       /* calculate new n2 and sdm */
+       n2 = parent_rate / rate;
+       sdm = DIV_ROUND_UP((parent_rate - n2 * rate) * SDM_MAX, rate);
+       if (sdm >= SDM_MAX)
+               sdm = SDM_MAX - 1;
+
+       pr_debug("%s: sdm: %lu n2: %lu rate: %lu parent_rate: %lu\n",
+               __func__, sdm, n2, rate, parent_rate);
+
+       writel(TL1_MPLL_CNTL0, mpll->base + mpll->mpll_cntl0_reg);
+
+       p = &mpll->sdm;
+       writel(TL1_MPLL_CNTL2, mpll->base + p->reg_off + (unsigned long)(1*4));
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, sdm);
+       p = &mpll->n2;
+       reg = PARM_SET(p->width, p->shift, reg, n2);
+       reg = PARM_SET(1, mpll->sdm_en, reg, 1);
+       reg = PARM_SET(1, mpll->en_dds, reg, 1);
+       writel(reg, mpll->base + p->reg_off);
+
+       if (mpll->lock)
+               spin_unlock_irqrestore(mpll->lock, flags);
+
+       return 0;
+}
+
+static int mpll_enable(struct clk_hw *hw)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p = &mpll->sdm;
+       unsigned long reg;
+       unsigned long flags = 0;
+
+       if (mpll->lock)
+               spin_lock_irqsave(mpll->lock, flags);
+
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(1, mpll->sdm_en, reg, 1);
+       reg = PARM_SET(1, mpll->en_dds, reg, 1);
+       writel(reg, mpll->base + p->reg_off);
+
+       if (mpll->lock)
+               spin_unlock_irqrestore(mpll->lock, flags);
+
+       return 0;
+}
+
+static void mpll_disable(struct clk_hw *hw)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p = &mpll->sdm;
+       unsigned long reg;
+       unsigned long flags = 0;
+
+       if (mpll->lock)
+               spin_lock_irqsave(mpll->lock, flags);
+
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(1, mpll->sdm_en, reg, 0);
+       reg = PARM_SET(1, mpll->en_dds, reg, 0);
+       writel(reg, mpll->base + p->reg_off);
+
+       if (mpll->lock)
+               spin_unlock_irqrestore(mpll->lock, flags);
+}
+
+const struct clk_ops meson_tl1_mpll_ops = {
+       .recalc_rate = mpll_recalc_rate,
+       .round_rate     = meson_clk_pll_round_rate,
+       .set_rate = mpll_set_rate,
+       .enable = mpll_enable,
+       .disable = mpll_disable,
+};
+
+const struct clk_ops meson_tl1_mpll_ro_ops = {
+       .recalc_rate = mpll_recalc_rate,
+};
diff --git a/drivers/amlogic/clk/tl1/tl1_clk-pll.c b/drivers/amlogic/clk/tl1/tl1_clk-pll.c
new file mode 100644 (file)
index 0000000..8a9f42f
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk-pll.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * In the most basic form, a Meson PLL is composed as follows:
+ *
+ *                     PLL
+ *      +------------------------------+
+ *      |                              |
+ * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
+ *      |         ^        ^           |
+ *      +------------------------------+
+ *                |        |
+ *               FREF     VCO
+ *
+ * out = (in * M / N) >> OD
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/amlogic/cpu_version.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+
+#define MESON_PLL_RESET                                BIT(29)
+#define MESON_PLL_ENABLE                       BIT(28)
+#define MESON_PLL_LOCK                         BIT(31)
+
+/* tl1 */
+#define TL1_SYS_PLL_CNTL1 0x00000000
+#define TL1_SYS_PLL_CNTL2 0x00000000
+#define TL1_SYS_PLL_CNTL3 0x48681c00
+#define TL1_SYS_PLL_CNTL4 0x88770290
+#define TL1_SYS_PLL_CNTL5 0x39272000
+
+
+#define TL1_GP0_PLL_CNTL1 0x00000000
+#define TL1_GP0_PLL_CNTL2 0x00000000
+#define TL1_GP0_PLL_CNTL3 0x48681c00
+#define TL1_GP0_PLL_CNTL4 0x33771290
+#define TL1_GP0_PLL_CNTL5 0x39272000
+
+#define TL1_HIFI_PLL_CNTL1 0x00000000
+#define TL1_HIFI_PLL_CNTL2 0x00000000
+#define TL1_HIFI_PLL_CNTL3 0x6a285c00
+#define TL1_HIFI_PLL_CNTL4 0x65771290
+#define TL1_HIFI_PLL_CNTL5 0x39272000
+
+#define TL1_PLL_CNTL6 0x56540000
+
+#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
+
+static unsigned long meson_tl1_pll_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+       struct parm *p;
+       u64 parent_rate_mhz = parent_rate;
+       unsigned long rate_mhz;
+       u16 n, m, od, od2 = 0;
+       u32 reg, frac = 0;
+       u64 tmp64;
+
+       p = &pll->n;
+       reg = readl(pll->base + p->reg_off);
+       n = PARM_GET(p->width, p->shift, reg);
+
+       p = &pll->m;
+       reg = readl(pll->base + p->reg_off);
+       m = PARM_GET(p->width, p->shift, reg);
+
+       p = &pll->od;
+       reg = readl(pll->base + p->reg_off);
+       od = PARM_GET(p->width, p->shift, reg);
+
+       p = &pll->od2;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               od2 = PARM_GET(p->width, p->shift, reg);
+       }
+
+       p = &pll->frac;
+
+       if (p->width >= 2) {
+               reg = readl(pll->base + p->reg_off);
+               frac = PARM_GET(p->width - 1, p->shift, reg);
+
+               if (reg & (1 << (p->width - 1))) {
+                       tmp64 = (parent_rate_mhz * m -
+                               ((parent_rate_mhz * frac)
+                               >> (p->width - 2)));
+                       do_div(tmp64, n);
+                       rate_mhz = (unsigned long)tmp64;
+               } else {
+                       tmp64 = (parent_rate_mhz * m +
+                               ((parent_rate_mhz * frac)
+                               >> (p->width - 2)));
+                       do_div(tmp64, n);
+                       rate_mhz = (unsigned long)tmp64;
+               }
+
+               if (!strcmp(clk_hw_get_name(hw), "pcie_pll"))
+                       rate_mhz = rate_mhz/4/od;
+               else
+                       rate_mhz = rate_mhz >> od;
+       } else {
+               if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) {
+                       tmp64 = parent_rate_mhz * m;
+                       do_div(tmp64, n * 4 * od);
+                       rate_mhz = (unsigned long)tmp64;
+               } else {
+                       tmp64 = parent_rate_mhz * m;
+                       do_div(tmp64, n);
+                       rate_mhz = tmp64 >> od >> od2;
+               }
+       }
+
+       return rate_mhz;
+}
+
+static long meson_tl1_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                    unsigned long *parent_rate)
+{
+       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+       const struct pll_rate_table *rate_table = pll->rate_table;
+       int i;
+
+       for (i = 0; i < pll->rate_count; i++) {
+               if (rate <= rate_table[i].rate)
+                       return rate_table[i].rate;
+       }
+
+       /* else return the smallest value */
+       return rate_table[0].rate;
+}
+
+static const struct pll_rate_table *meson_tl1_get_pll_settings
+       (struct meson_clk_pll *pll, unsigned long rate)
+{
+       const struct pll_rate_table *rate_table = pll->rate_table;
+       int i;
+
+       for (i = 0; i < pll->rate_count; i++) {
+               if (rate == rate_table[i].rate)
+                       return &rate_table[i];
+       }
+       return NULL;
+}
+
+static int meson_tl1_pll_wait_lock(struct meson_clk_pll *pll,
+                                  struct parm *p_n)
+{
+       int delay = 24000000;
+       u32 reg;
+
+       while (delay > 0) {
+               reg = readl(pll->base + p_n->reg_off);
+
+               if (reg & MESON_PLL_LOCK)
+                       return 0;
+               delay--;
+       }
+       return -ETIMEDOUT;
+}
+
+static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                                 unsigned long parent_rate)
+{
+       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+       struct parm *p;
+       const struct pll_rate_table *rate_set;
+       unsigned long old_rate;
+       int ret = 0;
+       u32 reg;
+       unsigned long flags = 0;
+       void *cntlbase;
+
+       if (parent_rate == 0 || rate == 0)
+               return -EINVAL;
+
+       old_rate = rate;
+
+       rate_set = meson_tl1_get_pll_settings(pll, rate);
+       if (!rate_set)
+               return -EINVAL;
+
+       p = &pll->n;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       if (readl(pll->base + p->reg_off) & MESON_PLL_ENABLE) {
+               old_rate = meson_tl1_pll_recalc_rate(hw, parent_rate);
+               old_rate = meson_tl1_pll_round_rate(hw, old_rate, NULL);
+
+               if (old_rate == rate) {
+                       if (pll->lock)
+                               spin_unlock_irqrestore(pll->lock, flags);
+                       return ret;
+               }
+       }
+
+       cntlbase = pll->base + p->reg_off;
+
+
+       if (!strcmp(clk_hw_get_name(hw), "sys_pll")) {
+               writel((readl(cntlbase) | MESON_PLL_RESET)
+                       & (~MESON_PLL_ENABLE), cntlbase);
+               writel(TL1_SYS_PLL_CNTL1,
+                               cntlbase + (unsigned long)(1*4));
+               writel(TL1_SYS_PLL_CNTL2,
+                               cntlbase + (unsigned long)(2*4));
+               writel(TL1_SYS_PLL_CNTL3,
+                               cntlbase + (unsigned long)(3*4));
+               writel(TL1_SYS_PLL_CNTL4,
+                               cntlbase + (unsigned long)(4*4));
+               writel(TL1_SYS_PLL_CNTL5,
+                               cntlbase + (unsigned long)(5*4));
+               writel(TL1_PLL_CNTL6,
+                               cntlbase + (unsigned long)(6*4));
+               udelay(10);
+       }  else if (!strcmp(clk_hw_get_name(hw), "gp0_pll")) {
+               writel((readl(cntlbase) | MESON_PLL_RESET)
+                       & (~MESON_PLL_ENABLE), cntlbase);
+               writel(TL1_GP0_PLL_CNTL1,
+                               cntlbase + (unsigned long)(1*4));
+               writel(TL1_GP0_PLL_CNTL2,
+                               cntlbase + (unsigned long)(2*4));
+               writel(TL1_GP0_PLL_CNTL3,
+                               cntlbase + (unsigned long)(3*4));
+               writel(TL1_GP0_PLL_CNTL4,
+                               cntlbase + (unsigned long)(4*4));
+               writel(TL1_GP0_PLL_CNTL5,
+                               cntlbase + (unsigned long)(5*4));
+               writel(TL1_PLL_CNTL6,
+                               cntlbase + (unsigned long)(6*4));
+               udelay(10);
+       } else if (!strcmp(clk_hw_get_name(hw), "hifi_pll")) {
+               writel((readl(cntlbase) | MESON_PLL_RESET)
+                       & (~MESON_PLL_ENABLE), cntlbase);
+               writel(TL1_GP0_PLL_CNTL1,
+                               cntlbase + (unsigned long)(1*4));
+               writel(TL1_GP0_PLL_CNTL2,
+                               cntlbase + (unsigned long)(2*4));
+               writel(TL1_GP0_PLL_CNTL3,
+                               cntlbase + (unsigned long)(3*4));
+               writel(TL1_GP0_PLL_CNTL4,
+                               cntlbase + (unsigned long)(4*4));
+               writel(TL1_GP0_PLL_CNTL5,
+                               cntlbase + (unsigned long)(5*4));
+               writel(TL1_PLL_CNTL6,
+                               cntlbase + (unsigned long)(6*4));
+               udelay(10);
+       } else {
+               pr_err("%s: %s pll not found!!!\n",
+                       __func__, clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       reg = readl(pll->base + p->reg_off);
+
+       reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
+       writel(reg, pll->base + p->reg_off);
+
+       p = &pll->m;
+       reg = readl(pll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
+       writel(reg, pll->base + p->reg_off);
+
+       p = &pll->od;
+       /*check OD width*/
+       if (rate_set->od >> p->width) {
+               ret = -EINVAL;
+               pr_warn("%s: OD width is wrong at rate %lu !!\n",
+                       __func__, rate);
+               goto OUT;
+       }
+       reg = readl(pll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
+       writel(reg, pll->base + p->reg_off);
+
+       p = &pll->od2;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
+               writel(reg, pll->base + p->reg_off);
+       }
+
+       p = &pll->frac;
+       if (p->width) {
+               reg = readl(pll->base + p->reg_off);
+               reg = PARM_SET(p->width, p->shift, reg, rate_set->frac);
+               writel(reg, pll->base + p->reg_off);
+       }
+
+       p = &pll->n;
+
+       /* PLL reset */
+       writel(readl(pll->base + p->reg_off) | MESON_PLL_ENABLE,
+               pll->base + p->reg_off);
+       udelay(50);
+       writel(readl(pll->base + p->reg_off) & (~MESON_PLL_RESET),
+               pll->base + p->reg_off);
+       ret = meson_tl1_pll_wait_lock(pll, p);
+
+OUT:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       if (ret) {
+               pr_warn("%s: pll did not lock, trying to lock rate %lu again\n",
+                       __func__, rate);
+               meson_tl1_pll_set_rate(hw, rate, parent_rate);
+       }
+
+       return ret;
+}
+
+static int meson_tl1_pll_enable(struct clk_hw *hw)
+{
+       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+       struct parm *p;
+       int ret = 0;
+       unsigned long flags = 0;
+       unsigned long first_set = 1;
+       struct clk_hw *parent;
+       unsigned long rate;
+
+       p = &pll->n;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       if (readl(pll->base + p->reg_off) & MESON_PLL_ENABLE) {
+               if (pll->lock)
+                       spin_unlock_irqrestore(pll->lock, flags);
+               return ret;
+       }
+
+       if (!strcmp(clk_hw_get_name(hw), "gp0_pll")
+               || !strcmp(clk_hw_get_name(hw), "hifi_pll")
+               || !strcmp(clk_hw_get_name(hw), "sys_pll")) {
+               void *cntlbase = pll->base + p->reg_off;
+
+                       if (readl(cntlbase + (unsigned long)(6*4))
+                                               == TL1_PLL_CNTL6)
+                               first_set = 0;
+
+       }
+
+       parent = clk_hw_get_parent(hw);
+
+       /*First init, just set minimal rate.*/
+       if (first_set)
+               rate = pll->rate_table[0].rate;
+       else {
+               rate = meson_tl1_pll_recalc_rate(hw, clk_hw_get_rate(parent));
+               rate = meson_tl1_pll_round_rate(hw, rate, NULL);
+       }
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       ret = meson_tl1_pll_set_rate(hw, rate, clk_hw_get_rate(parent));
+
+       return ret;
+}
+
+static void meson_tl1_pll_disable(struct clk_hw *hw)
+{
+       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+       struct parm *p = &pll->n;
+       unsigned long flags = 0;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       writel(readl(pll->base + p->reg_off) | (MESON_PLL_RESET),
+               pll->base + p->reg_off);
+       writel(readl(pll->base + p->reg_off) & (~MESON_PLL_ENABLE),
+               pll->base + p->reg_off);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+}
+
+const struct clk_ops meson_tl1_pll_ops = {
+       .recalc_rate    = meson_tl1_pll_recalc_rate,
+       .round_rate     = meson_tl1_pll_round_rate,
+       .set_rate       = meson_tl1_pll_set_rate,
+       .enable         = meson_tl1_pll_enable,
+       .disable        = meson_tl1_pll_disable,
+};
+
+const struct clk_ops meson_tl1_pll_ro_ops = {
+       .recalc_rate    = meson_tl1_pll_recalc_rate,
+};
+
diff --git a/drivers/amlogic/clk/tl1/tl1_clk_gpu.c b/drivers/amlogic/clk/tl1/tl1_clk_gpu.c
new file mode 100644 (file)
index 0000000..ab8c3ce
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk_gpu.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+PNAME(gpus_parent_names) = { "xtal", "gp0_pll", "hifi_pll",
+       "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7"};
+
+PNAME(gpumux_parent_names) = { "gpu_p0_composite", "gpu_p1_composite"};
+
+/* gpu p0 */
+static MUX(gpu_p0_mux, HHI_MALI_CLK_CNTL, 0x7, 9, gpus_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(gpu_p0_div, HHI_MALI_CLK_CNTL, 0, 7, "gpu_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(gpu_p0_gate, HHI_MALI_CLK_CNTL, 8, "gpu_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+/* gpu p1 */
+static MUX(gpu_p1_mux, HHI_MALI_CLK_CNTL, 0x7, 25, gpus_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(gpu_p1_div, HHI_MALI_CLK_CNTL, 16, 7, "gpu_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(gpu_p1_gate, HHI_MALI_CLK_CNTL, 24, "gpu_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+static MESON_MUX(gpu_mux, HHI_MALI_CLK_CNTL, 0x1, 31,
+gpumux_parent_names, CLK_GET_RATE_NOCACHE);
+
+/* for init mux/div/gate clocks reg base*/
+static struct clk_mux *tl1_gpu_clk_muxes[] = {
+       &gpu_p0_mux,
+       &gpu_p1_mux,
+       &gpu_mux,
+};
+
+static struct clk_divider *tl1_gpu_clk_divs[] = {
+       &gpu_p0_div,
+       &gpu_p1_div,
+};
+
+static struct clk_gate *tl1_gpu_clk_gates[] = {
+       &gpu_p0_gate,
+       &gpu_p1_gate,
+};
+
+static struct meson_composite gpu_composite[] = {
+       {CLKID_GPU_P0_COMP, "gpu_p0_composite",
+       gpus_parent_names, ARRAY_SIZE(gpus_parent_names),
+       &gpu_p0_mux.hw, &gpu_p0_div.hw,
+       &gpu_p0_gate.hw, 0
+       },/*gpu_p0*/
+
+       {CLKID_GPU_P1_COMP, "gpu_p1_composite",
+       gpus_parent_names, ARRAY_SIZE(gpus_parent_names),
+       &gpu_p1_mux.hw, &gpu_p1_div.hw, &gpu_p1_gate.hw, 0
+       },/*gpu_p1*/
+
+       {},
+};
+void meson_tl1_gpu_init(void)
+{
+       int i, length;
+
+       length = ARRAY_SIZE(gpu_composite);
+       /* Populate base address for gpu muxes, divs,gates */
+       for (i = 0; i < ARRAY_SIZE(tl1_gpu_clk_muxes); i++)
+               tl1_gpu_clk_muxes[i]->reg = clk_base +
+                       (unsigned long)tl1_gpu_clk_muxes[i]->reg;
+       for (i = 0; i < ARRAY_SIZE(tl1_gpu_clk_divs); i++)
+               tl1_gpu_clk_divs[i]->reg = clk_base +
+                       (unsigned long)tl1_gpu_clk_divs[i]->reg;
+       for (i = 0; i < ARRAY_SIZE(tl1_gpu_clk_gates); i++)
+               tl1_gpu_clk_gates[i]->reg = clk_base +
+                       (unsigned long)tl1_gpu_clk_gates[i]->reg;
+
+       meson_clk_register_composite(clks, gpu_composite, length - 1);
+
+       clks[CLKID_GPU_MUX] = clk_register(NULL, &gpu_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_GPU_MUX]));
+
+       clk_set_parent(clks[CLKID_GPU_MUX], clks[CLKID_GPU_P0_COMP]);
+       clk_prepare_enable(clks[CLKID_GPU_P0_COMP]);
+       clk_prepare_enable(clks[CLKID_GPU_P1_COMP]);
+       clk_set_rate(clks[CLKID_GPU_MUX], 400000000);
+}
diff --git a/drivers/amlogic/clk/tl1/tl1_clk_media.c b/drivers/amlogic/clk/tl1/tl1_clk_media.c
new file mode 100644 (file)
index 0000000..6be0ef2
--- /dev/null
@@ -0,0 +1,650 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk_media.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+/* cts_vdin_meas_clk */
+PNAME(meas_parent_names) = { "xtal", "fclk_div4",
+"fclk_div3", "fclk_div5", "vid_pll", "null", "null", "null" };
+static MUX(vdin_meas_mux, HHI_VDIN_MEAS_CLK_CNTL, 0x7, 9, meas_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vdin_meas_div, HHI_VDIN_MEAS_CLK_CNTL, 0, 7, "vdin_meas_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vdin_meas_gate, HHI_VDIN_MEAS_CLK_CNTL, 8, "vdin_meas_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts_vpu_p0_clk */
+PNAME(vpu_parent_names) = { "fclk_div3", "fclk_div4", "fclk_div5",
+"fclk_div7", "mpll1", "vid_pll", "hifi_pll",  "gp0_pll"};
+static MUX(vpu_p0_mux, HHI_VPU_CLK_CNTL, 0x7, 9, vpu_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vpu_p0_div, HHI_VPU_CLK_CNTL, 0, 7, "vpu_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_p0_gate, HHI_VPU_CLK_CNTL, 8, "vpu_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts_vpu_p1_clk */
+static MUX(vpu_p1_mux, HHI_VPU_CLK_CNTL, 0x7, 25, vpu_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vpu_p1_div, HHI_VPU_CLK_CNTL, 16, 7, "vpu_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_p1_gate, HHI_VPU_CLK_CNTL, 24, "vpu_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+/* vpu mux clk */
+PNAME(vpu_mux_parent_names) = { "vpu_p0_composite", "vpu_p1_composite" };
+static MESON_MUX(vpu_mux, HHI_VPU_CLK_CNTL, 0x1, 31,
+               vpu_mux_parent_names, CLK_GET_RATE_NOCACHE);
+
+/* vpu_clkb_tmp */
+PNAME(vpu_clkb_parent_names) = { "vpu_mux",
+                               "fclk_div4", "fclk_div5", "fclk_div7" };
+static MUX(vpu_clkb_tmp_mux, HHI_VPU_CLKB_CNTL, 0x3, 20,
+vpu_clkb_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(vpu_clkb_tmp_div, HHI_VPU_CLKB_CNTL, 16, 4, "vpu_clkb_tmp_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_clkb_tmp_gate, HHI_VPU_CLKB_CNTL, 24, "vpu_clkb_tmp_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* vpu_clkb */
+PNAME(vpu_clkb_nomux_parent_names) = { "vpu_clkb_tmp_composite" };
+static DIV(vpu_clkb_div, HHI_VPU_CLKB_CNTL, 0, 8, "vpu_clkb_tmp_composite",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_clkb_gate, HHI_VPU_CLKB_CNTL, 8, "vpu_clkb_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* vpu_clkc*/
+PNAME(vpu_clkc_parent_names) = { "fclk_div4", "fclk_div3", "fclk_div5",
+"fclk_div7", "mpll1", "vid_pll", "mpll2",  "gp0_pll"};
+static MUX(vpu_clkc_p0_mux, HHI_VPU_CLKC_CNTL, 0x7, 9, vpu_clkc_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vpu_clkc_p0_div, HHI_VPU_CLKC_CNTL, 0, 7, "vpu_clkc_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_clkc_p0_gate, HHI_VPU_CLKC_CNTL, 8, "vpu_clkc_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+
+static MUX(vpu_clkc_p1_mux, HHI_VPU_CLKC_CNTL, 0x7, 25, vpu_clkc_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vpu_clkc_p1_div, HHI_VPU_CLKC_CNTL, 16, 7, "vpu_clkc_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vpu_clkc_p1_gate, HHI_VPU_CLKC_CNTL, 24, "vpu_clkc_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* vpu_clkc mux clk */
+PNAME(vpu_clkc_mux_parent_names) = { "vpu_clkc_p0_composite",
+                               "vpu_clkc_p1_composite" };
+static MESON_MUX(vpu_clkc_mux, HHI_VPU_CLKC_CNTL, 0x1, 31,
+               vpu_clkc_mux_parent_names, CLK_GET_RATE_NOCACHE);
+
+/* cts_bt656_clk0 */
+PNAME(bt656_clk0_parent_names) = { "fclk_div2", "fclk_div3", "fclk_div5",
+                                                               "fclk_div7" };
+static MUX(bt656_clk0_mux, HHI_BT656_CLK_CNTL, 0x3, 9, bt656_clk0_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(bt656_clk0_div, HHI_BT656_CLK_CNTL, 0, 7, "bt656_clk0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(bt656_clk0_gate, HHI_BT656_CLK_CNTL, 7, "bt656_clk0_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts_tcon_pll_clk */
+PNAME(tcon_pll_parent_names) = { "xtal", "fclk_div5", "fclk_div4",
+"fclk_div3", "mpll2", "mpll3", "vid_pll", "gp0" };
+static MUX(tcon_pll_mux, HHI_TCON_CLK_CNTL, 0x3, 7, tcon_pll_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(tcon_pll_div, HHI_TCON_CLK_CNTL, 0, 6, "tcon_pll_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(tcon_pll_gate, HHI_TCON_CLK_CNTL, 6, "tcon_pll_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts_vapb p0 clk */
+PNAME(vapb_parent_names) = { "fclk_div4", "fclk_div3", "fclk_div5",
+"fclk_div7", "mpll1", "vid_pll", "mpll2",  "fclk_div2p5"};
+static MUX(vapb_p0_mux, HHI_VAPBCLK_CNTL, 0x7, 9, vapb_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vapb_p0_div, HHI_VAPBCLK_CNTL, 0, 7, "vapb_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vapb_p0_gate, HHI_VAPBCLK_CNTL, 8, "vapb_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+/* cts_vapb p1 clk */
+static MUX(vapb_p1_mux, HHI_VAPBCLK_CNTL, 0x7, 25, vapb_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vapb_p1_div, HHI_VAPBCLK_CNTL, 16, 7, "vapb_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vapb_p1_gate, HHI_VAPBCLK_CNTL, 24, "vapb_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts_vapb mux clk */
+PNAME(vapb_mux_parent_names) = { "vapb_p0_composite", "vapb_p1_composite" };
+static MESON_MUX(vapb_mux, HHI_VAPBCLK_CNTL, 0x1, 31,
+vapb_mux_parent_names, CLK_GET_RATE_NOCACHE);
+static GATE(ge2d_gate, HHI_VAPBCLK_CNTL, 30, "vapb_mux",
+                       CLK_GET_RATE_NOCACHE);
+
+/*hdmirx cfg clock*/
+PNAME(hdmirx_parent_names) = { "xtal", "fclk_div4", "fclk_div3", "fclk_div5" };
+static MUX(hdmirx_cfg_mux, HHI_HDMIRX_CLK_CNTL, 0x3, 9, hdmirx_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hdmirx_cfg_div, HHI_HDMIRX_CLK_CNTL, 0, 7, "hdmirx_cfg_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hdmirx_cfg_gate, HHI_HDMIRX_CLK_CNTL, 8, "hdmirx_cfg_div",
+                       CLK_GET_RATE_NOCACHE);
+/*hdmirx modet clock*/
+static MUX(hdmirx_modet_mux, HHI_HDMIRX_CLK_CNTL, 0x3, 25, hdmirx_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hdmirx_modet_div, HHI_HDMIRX_CLK_CNTL, 16, 7, "hdmirx_modet_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hdmirx_modet_gate, HHI_HDMIRX_CLK_CNTL, 24, "hdmirx_modet_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/*hdmirx audmeas clock*/
+PNAME(hdmirx_ref_parent_names) = { "fclk_div4",
+"fclk_div3", "fclk_div5", "fclk_div7" };
+static MUX(hdmirx_audmeas_mux, HHI_HDMIRX_AUD_CLK_CNTL, 0x3, 9,
+hdmirx_ref_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(hdmirx_audmeas_div, HHI_HDMIRX_AUD_CLK_CNTL, 0, 7,
+"hdmirx_audmeas_mux", CLK_GET_RATE_NOCACHE);
+static GATE(hdmirx_audmeas_gate, HHI_HDMIRX_AUD_CLK_CNTL, 8,
+"hdmirx_audmeas_div", CLK_GET_RATE_NOCACHE);
+/* hdmirx acr clock*/
+static MUX(hdmirx_acr_mux, HHI_HDMIRX_AUD_CLK_CNTL, 0x3, 25,
+hdmirx_ref_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(hdmirx_acr_div, HHI_HDMIRX_AUD_CLK_CNTL, 16, 7, "hdmirx_acr_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hdmirx_acr_gate, HHI_HDMIRX_AUD_CLK_CNTL, 24, "hdmirx_acr_div",
+                       CLK_GET_RATE_NOCACHE);
+/* hdcp22 skpclk*/
+
+PNAME(hdcp22_skp_parent_names) = { "xtal",
+"fclk_div4", "fclk_div3", "fclk_div5" };
+static MUX(hdcp22_skp_mux, HHI_HDCP22_CLK_CNTL, 0x3, 25,
+                       hdcp22_skp_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(hdcp22_skp_div, HHI_HDCP22_CLK_CNTL, 16, 7, "hdcp22_skp_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hdcp22_skp_gate, HHI_HDCP22_CLK_CNTL, 24, "hdcp22_skp_div",
+                       CLK_GET_RATE_NOCACHE);
+/* hdcp22 esm clock */
+PNAME(hdcp22_esm_parent_names) = { "fclk_div7",
+"fclk_div4", "fclk_div3", "fclk_div5"  };
+static MUX(hdcp22_esm_mux, HHI_HDCP22_CLK_CNTL, 0x3, 9,
+hdcp22_esm_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static DIV(hdcp22_esm_div, HHI_HDCP22_CLK_CNTL, 0, 7, "hdcp22_esm_mux",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static GATE(hdcp22_esm_gate, HHI_HDCP22_CLK_CNTL, 8, "hdcp22_esm_div",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+
+/*vdec clock*/
+/* cts_vdec_clk */
+PNAME(dec_parent_names) = { "fclk_div2p5", "fclk_div3",
+"fclk_div4", "fclk_div5", "fclk_div7", "hifi", "gp0_pll", "xtal" };
+static MUX(vdec_p0_mux, HHI_VDEC_CLK_CNTL, 0x7, 9, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vdec_p0_div, HHI_VDEC_CLK_CNTL, 0, 7, "vdec_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vdec_p0_gate, HHI_VDEC_CLK_CNTL, 8, "vdec_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+static MUX(vdec_p1_mux, HHI_VDEC3_CLK_CNTL, 0x7, 9, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vdec_p1_div, HHI_VDEC3_CLK_CNTL, 0, 7, "vdec_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vdec_p1_gate, HHI_VDEC3_CLK_CNTL, 8, "vdec_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* vdec_mux clk */
+PNAME(vdec_mux_parent_names) = { "vdec_p0_composite", "vdec_p1_composite" };
+static MESON_MUX(vdec_mux, HHI_VDEC3_CLK_CNTL, 0x1, 15,
+vdec_mux_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+
+/* hcodev clock*/
+static MUX(hcodec_p0_mux, HHI_VDEC_CLK_CNTL, 0x7, 25, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hcodec_p0_div, HHI_VDEC_CLK_CNTL, 16, 7, "hcodec_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hcodec_p0_gate, HHI_VDEC_CLK_CNTL, 24, "hcodec_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+static MUX(hcodec_p1_mux, HHI_VDEC3_CLK_CNTL, 0x7, 25, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hcodec_p1_div, HHI_VDEC3_CLK_CNTL, 16, 7, "hcodec_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hcodec_p1_gate, HHI_VDEC3_CLK_CNTL, 24, "hcodec_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* hcodec_mux clk */
+PNAME(hcodec_mux_parent_names) = {
+"hcodec_p0_composite", "hcodec_p1_composite" };
+static MESON_MUX(hcodec_mux, HHI_VDEC3_CLK_CNTL, 0x1, 31,
+hcodec_mux_parent_names, CLK_GET_RATE_NOCACHE);
+
+
+/* hevc clock */
+static MUX(hevc_p0_mux, HHI_VDEC2_CLK_CNTL, 0x7, 25, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hevc_p0_div, HHI_VDEC2_CLK_CNTL, 16, 7, "hevc_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hevc_p0_gate, HHI_VDEC2_CLK_CNTL, 24, "hevc_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+static MUX(hevc_p1_mux, HHI_VDEC4_CLK_CNTL, 0x7, 25, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hevc_p1_div, HHI_VDEC4_CLK_CNTL, 16, 7, "hevc_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hevc_p1_gate, HHI_VDEC4_CLK_CNTL, 24, "hevc_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* hevc_mux clk */
+PNAME(hevc_mux_parent_names) = { "hevc_p0_composite", "hevc_p1_composite" };
+static MESON_MUX(hevc_mux, HHI_VDEC4_CLK_CNTL, 0x1, 31,
+hevc_mux_parent_names, CLK_GET_RATE_NOCACHE);
+
+/* hevcf clock */
+static MUX(hevcf_p0_mux, HHI_VDEC2_CLK_CNTL, 0x7, 9, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hevcf_p0_div, HHI_VDEC2_CLK_CNTL, 0, 7, "hevcf_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hevcf_p0_gate, HHI_VDEC2_CLK_CNTL, 8, "hevcf_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+static MUX(hevcf_p1_mux, HHI_VDEC4_CLK_CNTL, 0x7, 9, dec_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(hevcf_p1_div, HHI_VDEC4_CLK_CNTL, 0, 7, "hevcf_p1_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(hevcf_p1_gate, HHI_VDEC4_CLK_CNTL, 8, "hevcf_p1_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* hevcf_mux clk */
+PNAME(hevcf_mux_parent_names) = { "hevcf_p0_composite", "hevcf_p1_composite" };
+static MESON_MUX(hevcf_mux, HHI_VDEC4_CLK_CNTL, 0x1, 15,
+hevcf_mux_parent_names, CLK_GET_RATE_NOCACHE);
+
+/* cts_vid_lock_clk */
+PNAME(vid_lock_parent_names) = { "xtal", "cts_encl_clk",
+"cts_enci_clk", "cts_encp_clk" };
+static MUX(vid_lock_mux, HHI_VID_LOCK_CLK_CNTL, 0x3, 9, vid_lock_parent_names,
+                       CLK_GET_RATE_NOCACHE);
+static DIV(vid_lock_div, HHI_VID_LOCK_CLK_CNTL, 0, 7, "vdec_p0_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(vid_lock_gate, HHI_VID_LOCK_CLK_CNTL, 7, "vdec_p0_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* cts demod core clock */
+PNAME(cts_demod_parent_names) = { "xtal",
+"fclk_div4", "fclk_div3", "adc_dpll_int"};
+static MUX(cts_demod_mux, HHI_AUDPLL_CLK_OUT_CNTL, 0x3, 9,
+cts_demod_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(cts_demod_div, HHI_AUDPLL_CLK_OUT_CNTL, 0, 7, "cts_demod_mux",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(cts_demod_gate, HHI_AUDPLL_CLK_OUT_CNTL, 8, "cts_demod_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* adc extclk in clock */
+PNAME(adc_extclk_in_parent_names) = { "xtal", "fclk_div4", "fclk_div3",
+"fclk_div5", "fclk_div7", "mpll2", "gp0_pll", "gp1_pll" };
+static MUX(adc_extclk_in_mux, HHI_AUDPLL_CLK_OUT_CNTL, 0x7, 25,
+adc_extclk_in_parent_names, CLK_GET_RATE_NOCACHE);
+static DIV(adc_extclk_in_div, HHI_AUDPLL_CLK_OUT_CNTL, 16, 7,
+"adc_extclk_in_mux", CLK_GET_RATE_NOCACHE);
+static GATE(adc_extclk_in_gate, HHI_AUDPLL_CLK_OUT_CNTL, 24,
+"adc_extclk_in_div", CLK_GET_RATE_NOCACHE);
+
+#if 0
+static struct clk_hw *media_vhec_mux[] = {
+       [CLKID_VDEC_MUX - CLKID_VDEC_MUX] = &vdec_mux.hw,
+       [CLKID_HCODEC_MUX - CLKID_VDEC_MUX] = &hcodec_mux.hw,
+       [CLKID_HEVC_MUX - CLKID_VDEC_MUX] = &hevc_mux.hw,
+};
+#endif
+
+/* for init mux clocks reg base*/
+static struct clk_mux *tl1_media_clk_muxes[] = {
+       &vdin_meas_mux,
+       &vpu_p0_mux,
+       &vpu_p1_mux,
+       &vpu_mux,
+       &vapb_p0_mux,
+       &vapb_p1_mux,
+       &vapb_mux,
+       &vpu_clkb_tmp_mux,
+       &hdmirx_cfg_mux,
+       &hdmirx_modet_mux,
+       &hdmirx_audmeas_mux,
+       &hdmirx_acr_mux,
+       &hdcp22_skp_mux,
+       &hdcp22_esm_mux,
+       &vdec_p0_mux,
+       &vdec_p1_mux,
+       &vdec_mux,
+       &hcodec_p0_mux,
+       &hcodec_p1_mux,
+       &hcodec_mux,
+       &hevc_p0_mux,
+       &hevc_p1_mux,
+       &hevc_mux,
+       &hevcf_p0_mux,
+       &hevcf_p1_mux,
+       &hevcf_mux,
+       &vpu_clkc_p0_mux,
+       &vpu_clkc_p1_mux,
+       &vpu_clkc_mux,
+       &vid_lock_mux,
+       &bt656_clk0_mux,
+       &tcon_pll_mux,
+       &cts_demod_mux,
+       &adc_extclk_in_mux,
+};
+
+/* for init div clocks reg base*/
+static struct clk_divider *tl1_media_clk_divs[] = {
+       &vdin_meas_div,
+       &vpu_p0_div,
+       &vpu_p1_div,
+       &vapb_p0_div,
+       &vapb_p1_div,
+       &vpu_clkb_tmp_div,
+       &vpu_clkb_div,
+       &hdmirx_cfg_div,
+       &hdmirx_modet_div,
+       &hdmirx_audmeas_div,
+       &hdmirx_acr_div,
+       &hdcp22_skp_div,
+       &hdcp22_esm_div,
+       &vdec_p0_div,
+       &vdec_p1_div,
+       &hcodec_p0_div,
+       &hcodec_p1_div,
+       &hevc_p0_div,
+       &hevc_p1_div,
+       &hevcf_p0_div,
+       &hevcf_p1_div,
+       &vpu_clkc_p0_div,
+       &vpu_clkc_p1_div,
+       &vid_lock_div,
+       &bt656_clk0_div,
+       &tcon_pll_div,
+       &cts_demod_div,
+       &adc_extclk_in_div,
+};
+
+/* for init gate clocks reg base*/
+static struct clk_gate *tl1_media_clk_gates[] = {
+       &vdin_meas_gate,
+       &vpu_p0_gate,
+       &vpu_p1_gate,
+       &vapb_p0_gate,
+       &vapb_p1_gate,
+       &ge2d_gate,
+       &vpu_clkb_tmp_gate,
+       &vpu_clkb_gate,
+       &hdmirx_cfg_gate,
+       &hdmirx_modet_gate,
+       &hdmirx_audmeas_gate,
+       &hdmirx_acr_gate,
+       &hdcp22_skp_gate,
+       &hdcp22_esm_gate,
+       &vdec_p0_gate,
+       &vdec_p1_gate,
+       &hcodec_p0_gate,
+       &hcodec_p1_gate,
+       &hevc_p0_gate,
+       &hevc_p1_gate,
+       &hevcf_p0_gate,
+       &hevcf_p1_gate,
+       &vpu_clkc_p0_gate,
+       &vpu_clkc_p1_gate,
+       &vid_lock_gate,
+       &bt656_clk0_gate,
+       &tcon_pll_gate,
+       &cts_demod_gate,
+       &adc_extclk_in_gate,
+};
+
+static struct meson_composite m_composite[] = {
+       {CLKID_VPU_CLKB_TMP_COMP, "vpu_clkb_tmp_composite",
+       vpu_clkb_parent_names, ARRAY_SIZE(vpu_clkb_parent_names),
+       &vpu_clkb_tmp_mux.hw, &vpu_clkb_tmp_div.hw,
+       &vpu_clkb_tmp_gate.hw, 0
+       },/*vpu_clkb_tmp*/
+
+       {CLKID_VPU_CLKB_COMP, "vpu_clkb_composite",
+       vpu_clkb_nomux_parent_names, ARRAY_SIZE(vpu_clkb_nomux_parent_names),
+       NULL, &vpu_clkb_div.hw, &vpu_clkb_gate.hw, 0
+       },/*vpu_clkb*/
+
+       {CLKID_VDIN_MEAS_COMP, "vdin_meas_composite",
+       meas_parent_names, ARRAY_SIZE(meas_parent_names),
+       &vdin_meas_mux.hw, &vdin_meas_div.hw,
+       &vdin_meas_gate.hw, 0
+       },/*vdin_meas*/
+
+       {CLKID_VPU_P0_COMP, "vpu_p0_composite",
+       vpu_parent_names, ARRAY_SIZE(vpu_parent_names),
+       &vpu_p0_mux.hw, &vpu_p0_div.hw,
+       &vpu_p0_gate.hw, 0
+       },/* cts_vpu_clk p0*/
+
+       {CLKID_VPU_P1_COMP, "vpu_p1_composite",
+       vpu_parent_names, ARRAY_SIZE(vpu_parent_names),
+       &vpu_p1_mux.hw, &vpu_p1_div.hw,
+       &vpu_p1_gate.hw, 0
+       },
+
+       {CLKID_VAPB_P0_COMP, "vapb_p0_composite",
+       vpu_parent_names, ARRAY_SIZE(vpu_parent_names),
+       &vapb_p0_mux.hw, &vapb_p0_div.hw,
+       &vapb_p0_gate.hw, 0
+       },
+
+       {CLKID_VAPB_P1_COMP, "vapb_p1_composite",
+       vpu_parent_names, ARRAY_SIZE(vpu_parent_names),
+       &vapb_p1_mux.hw, &vapb_p1_div.hw,
+       &vapb_p1_gate.hw, 0
+       },
+
+       {CLKID_HDMIRX_CFG_COMP, "hdmirx_cfg_composite",
+       hdmirx_parent_names, ARRAY_SIZE(hdmirx_parent_names),
+       &hdmirx_cfg_mux.hw, &hdmirx_cfg_div.hw,
+       &hdmirx_cfg_gate.hw, 0
+       },
+
+       {CLKID_HDMIRX_MODET_COMP, "hdmirx_modet_composite",
+       hdmirx_parent_names, ARRAY_SIZE(hdmirx_parent_names),
+       &hdmirx_modet_mux.hw, &hdmirx_modet_div.hw,
+       &hdmirx_modet_gate.hw, 0
+       },
+
+       {CLKID_HDMIRX_AUDMEAS_COMP, "hdmirx_audmeas_composite",
+       hdmirx_ref_parent_names, ARRAY_SIZE(hdmirx_ref_parent_names),
+       &hdmirx_audmeas_mux.hw, &hdmirx_audmeas_div.hw,
+       &hdmirx_audmeas_gate.hw, 0
+       },
+
+       {CLKID_HDMIRX_ACR_COMP, "hdmirx_acr_composite",
+       hdmirx_ref_parent_names, ARRAY_SIZE(hdmirx_ref_parent_names),
+       &hdmirx_acr_mux.hw, &hdmirx_acr_div.hw,
+       &hdmirx_acr_gate.hw, 0
+       },
+
+       {CLKID_HDCP22_SKP_COMP, "hdcp22_skp_composite",
+       hdcp22_skp_parent_names, ARRAY_SIZE(hdcp22_skp_parent_names),
+       &hdcp22_skp_mux.hw, &hdcp22_skp_div.hw,
+       &hdcp22_skp_gate.hw, 0
+       },
+
+       {CLKID_HDCP22_ESM_COMP, "hdcp22_esm_composite",
+       hdcp22_esm_parent_names, ARRAY_SIZE(hdcp22_esm_parent_names),
+       &hdcp22_esm_mux.hw, &hdcp22_esm_div.hw,
+       &hdcp22_esm_gate.hw, 0
+       },
+
+       {CLKID_VDEC_P0_COMP, "vdec_p0_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &vdec_p0_mux.hw, &vdec_p0_div.hw,
+       &vdec_p0_gate.hw, 0
+       },
+
+       {CLKID_VDEC_P1_COMP, "vdec_p1_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &vdec_p1_mux.hw, &vdec_p1_div.hw,
+       &vdec_p1_gate.hw, 0
+       },
+
+       {CLKID_HCODEC_P0_COMP, "hcodec_p0_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hcodec_p0_mux.hw, &hcodec_p0_div.hw,
+       &hcodec_p0_gate.hw, 0
+       },
+
+       {CLKID_HCODEC_P1_COMP, "hcodec_p1_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hcodec_p1_mux.hw, &hcodec_p1_div.hw,
+       &hcodec_p1_gate.hw, 0
+       },
+
+       {CLKID_HEVC_P0_COMP, "hevc_p0_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hevc_p0_mux.hw, &hevc_p0_div.hw,
+       &hevc_p0_gate.hw, 0
+       },
+
+       {CLKID_HEVC_P1_COMP, "hevc_p1_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hevc_p1_mux.hw, &hevc_p1_div.hw,
+       &hevc_p1_gate.hw, 0
+       },
+
+       {CLKID_HEVCF_P0_COMP, "hevcf_p0_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hevcf_p0_mux.hw, &hevcf_p0_div.hw,
+       &hevcf_p0_gate.hw, 0
+       },
+
+       {CLKID_HEVCF_P1_COMP, "hevcf_p1_composite",
+       dec_parent_names, ARRAY_SIZE(dec_parent_names),
+       &hevcf_p1_mux.hw, &hevcf_p1_div.hw,
+       &hevcf_p1_gate.hw, 0
+       },
+
+       {CLKID_VID_LOCK_COMP, "vid_lock_composite",
+       vid_lock_parent_names, ARRAY_SIZE(vid_lock_parent_names),
+       &vid_lock_mux.hw, &vid_lock_div.hw,
+       &vid_lock_gate.hw, 0
+       },
+
+       {CLKID_BT656_CLK0_COMP, "bt656_clk0_composite",
+       bt656_clk0_parent_names, ARRAY_SIZE(bt656_clk0_parent_names),
+       &bt656_clk0_mux.hw, &bt656_clk0_div.hw,
+       &bt656_clk0_gate.hw, 0
+       },
+
+       {CLKID_TCON_PLL_COMP, "tcon_pll_composite",
+       tcon_pll_parent_names, ARRAY_SIZE(tcon_pll_parent_names),
+       &tcon_pll_mux.hw, &tcon_pll_div.hw,
+       &tcon_pll_gate.hw, 0
+       },
+
+       {CLKID_DEMOD_COMP, "demod_composite",
+       cts_demod_parent_names, ARRAY_SIZE(cts_demod_parent_names),
+       &cts_demod_mux.hw, &cts_demod_div.hw,
+       &cts_demod_gate.hw, 0
+       },
+
+       {CLKID_ADC_EXTCLK_COMP, "adc_extclk_composite",
+       adc_extclk_in_parent_names, ARRAY_SIZE(adc_extclk_in_parent_names),
+       &adc_extclk_in_mux.hw, &adc_extclk_in_div.hw,
+       &adc_extclk_in_gate.hw, 0
+       },
+
+       {CLKID_VPU_CLKC_P0_COMP, "vpu_clkc_p0_composite",
+       vpu_clkc_parent_names, ARRAY_SIZE(vpu_clkc_parent_names),
+       &vpu_clkc_p0_mux.hw, &vpu_clkc_p0_div.hw,
+       &vpu_clkc_p0_gate.hw, 0
+       },
+
+       {CLKID_VPU_CLKC_P1_COMP, "vpu_clkc_p1_composite",
+       vpu_clkc_parent_names, ARRAY_SIZE(vpu_clkc_parent_names),
+       &vpu_clkc_p1_mux.hw, &vpu_clkc_p1_div.hw,
+       &vpu_clkc_p1_gate.hw, 0
+       },
+
+       {},
+};
+
+/* array for single hw*/
+static struct meson_hw m_hw[] = {
+       {CLKID_VDEC_MUX, &vdec_mux.hw},
+       {CLKID_HCODEC_MUX, &hcodec_mux.hw},
+       {CLKID_HEVC_MUX, &hevc_mux.hw},
+};
+void meson_tl1_media_init(void)
+{
+       int i;
+       int length, lengthhw;
+
+       length = ARRAY_SIZE(m_composite);
+       lengthhw = ARRAY_SIZE(m_hw);
+
+       /* Populate base address for media muxes */
+       for (i = 0; i < ARRAY_SIZE(tl1_media_clk_muxes); i++)
+               tl1_media_clk_muxes[i]->reg = clk_base +
+                       (unsigned long)tl1_media_clk_muxes[i]->reg;
+
+       /* Populate base address for media divs */
+       for (i = 0; i < ARRAY_SIZE(tl1_media_clk_divs); i++)
+               tl1_media_clk_divs[i]->reg = clk_base +
+                       (unsigned long)tl1_media_clk_divs[i]->reg;
+
+       /* Populate base address for media gates */
+       for (i = 0; i < ARRAY_SIZE(tl1_media_clk_gates); i++)
+               tl1_media_clk_gates[i]->reg = clk_base +
+                       (unsigned long)tl1_media_clk_gates[i]->reg;
+
+       meson_clk_register_composite(clks, m_composite, length - 1);
+
+       clks[CLKID_VPU_MUX] = clk_register(NULL, &vpu_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_VPU_MUX]));
+       clk_prepare_enable(clks[CLKID_VPU_MUX]);
+
+       clks[CLKID_VAPB_MUX] = clk_register(NULL, &vapb_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_VAPB_MUX]));
+       clk_prepare_enable(clks[CLKID_VAPB_MUX]);
+
+       clks[CLKID_GE2D_GATE] = clk_register(NULL, &ge2d_gate.hw);
+       WARN_ON(IS_ERR(clks[CLKID_GE2D_GATE]));
+
+       /*mux*/
+       clks[CLKID_VDEC_MUX] = clk_register(NULL, &vdec_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_VDEC_MUX]));
+
+       clks[CLKID_HCODEC_MUX] = clk_register(NULL, &hcodec_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_HCODEC_MUX]));
+
+       clks[CLKID_HEVC_MUX] = clk_register(NULL, &hevc_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_HEVC_MUX]));
+
+       clks[CLKID_HEVCF_MUX] = clk_register(NULL, &hevcf_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_HEVCF_MUX]));
+
+       clks[CLKID_VPU_CLKC_MUX] = clk_register(NULL, &vpu_clkc_mux.hw);
+       WARN_ON(IS_ERR(clks[CLKID_VPU_CLKC_MUX]));
+
+       /* todo: set default div4 parent for tmp clkb */
+       clk_set_parent(clks[CLKID_VPU_CLKB_TMP_COMP], clks[CLKID_FCLK_DIV4]);
+}
diff --git a/drivers/amlogic/clk/tl1/tl1_clk_misc.c b/drivers/amlogic/clk/tl1/tl1_clk_misc.c
new file mode 100644 (file)
index 0000000..1d264aa
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk_misc.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+/*ts clock */
+PNAME(ts_parent_names) = { "xtal" };
+static DIV(tl1_ts_div, HHI_TS_CLK_CNTL, 0, 7, "xtal",
+                       CLK_GET_RATE_NOCACHE);
+static GATE(tl1_ts_gate, HHI_TS_CLK_CNTL, 8, "tl1_ts_clk_div",
+                       CLK_GET_RATE_NOCACHE);
+
+/* spicc0 and spicc1 clocks */
+static const char * const spicc_parent_names[] = { "xtal",
+       "clk81", "fclk_div4", "fclk_div3", "fclk_div2", "fclk_div5",
+       "fclk_div7", "gpo_pll"};
+
+static struct clk_mux tl1_spicc0_mux = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "spicc0_mux",
+               .ops = &clk_mux_ops,
+               .parent_names = spicc_parent_names,
+               .num_parents = ARRAY_SIZE(spicc_parent_names),
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_divider tl1_spicc0_div = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .shift = 0,
+       .width = 6,
+       .lock = &clk_lock,
+       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       .hw.init = &(struct clk_init_data){
+               .name = "spicc0_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "spicc0_mux" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_gate tl1_spicc0_gate = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .bit_idx = 6,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data) {
+               .name = "spicc0_gate",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "spicc0_div" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_mux tl1_spicc1_mux = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 23,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "spicc1_mux",
+               .ops = &clk_mux_ops,
+               .parent_names = spicc_parent_names,
+               .num_parents = ARRAY_SIZE(spicc_parent_names),
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_divider tl1_spicc1_div = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .shift = 16,
+       .width = 6,
+       .lock = &clk_lock,
+       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       .hw.init = &(struct clk_init_data){
+               .name = "spicc_p1_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "spicc_p1_mux" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_gate tl1_spicc1_gate = {
+       .reg = (void *)HHI_SPICC_CLK_CNTL,
+       .bit_idx = 22,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data) {
+               .name = "spicc_p1_gate",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "spicc_p1_div" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_mux *tl1_misc_clk_muxes[] = {
+       &tl1_spicc0_mux,
+       &tl1_spicc1_mux,
+};
+
+static struct clk_divider *tl1_misc_clk_divs[] = {
+       &tl1_spicc0_div,
+       &tl1_spicc1_div,
+       &tl1_ts_div,
+};
+
+static struct clk_gate *tl1_media_clk_gates[] = {
+       &tl1_spicc0_gate,
+       &tl1_spicc1_gate,
+       &tl1_ts_gate,
+};
+
+static struct meson_composite misc_composite[] = {
+       {CLKID_TS_CLK_COMP, "ts_clk_composite",
+       ts_parent_names, ARRAY_SIZE(ts_parent_names),
+       NULL, &tl1_ts_div.hw,
+       &tl1_ts_gate.hw, 0
+       },/* ts_clk */
+
+       {CLKID_SPICC0_COMP, "spicc0_composite",
+       spicc_parent_names, ARRAY_SIZE(spicc_parent_names),
+       &tl1_spicc0_mux.hw, &tl1_spicc0_div.hw,
+       &tl1_spicc0_gate.hw, 0
+       },/* spicc0 */
+
+       {CLKID_SPICC1_COMP, "spicc1_composite",
+       spicc_parent_names, ARRAY_SIZE(spicc_parent_names),
+       &tl1_spicc1_mux.hw, &tl1_spicc1_div.hw,
+       &tl1_spicc1_gate.hw, 0
+       },/* spicc1 */
+
+       {},
+};
+void meson_tl1_misc_init(void)
+{
+       int i, length;
+
+       /* Populate base address for misc muxes */
+       for (i = 0; i < ARRAY_SIZE(tl1_misc_clk_muxes); i++)
+               tl1_misc_clk_muxes[i]->reg = clk_base +
+                       (unsigned long)tl1_misc_clk_muxes[i]->reg;
+
+       /* Populate base address for misc divs */
+       for (i = 0; i < ARRAY_SIZE(tl1_misc_clk_divs); i++)
+               tl1_misc_clk_divs[i]->reg = clk_base +
+                       (unsigned long)tl1_misc_clk_divs[i]->reg;
+
+       /* Populate base address for misc gates */
+       for (i = 0; i < ARRAY_SIZE(tl1_media_clk_gates); i++)
+               tl1_media_clk_gates[i]->reg = clk_base +
+                       (unsigned long)tl1_media_clk_gates[i]->reg;
+
+       length = ARRAY_SIZE(misc_composite);
+
+       meson_clk_register_composite(clks, misc_composite, length - 1);
+}
diff --git a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c
new file mode 100644 (file)
index 0000000..37c3740
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/amlogic,tl1-clkc.h>
+
+#include "../clkc.h"
+#include "tl1.h"
+
+PNAME(sd_emmc_parent_names) = { "xtal", "fclk_div2",
+       "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0" };
+/*sd_emmc B*/
+static MUX(sd_emmc_p0_mux_B, HHI_SD_EMMC_CLK_CNTL, 0x7, 25,
+sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static DIV(sd_emmc_p0_div_B, HHI_SD_EMMC_CLK_CNTL, 16, 7, "sd_emmc_p0_mux_B",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static GATE(sd_emmc_p0_gate_B, HHI_SD_EMMC_CLK_CNTL, 23, "sd_emmc_p0_div_B",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+/*sd_emmc C*/
+static MUX(sd_emmc_p0_mux_C, HHI_NAND_CLK_CNTL, 0x7, 9,
+sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static DIV(sd_emmc_p0_div_C, HHI_NAND_CLK_CNTL, 0, 7, "sd_emmc_p0_mux_C",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+static GATE(sd_emmc_p0_gate_C, HHI_NAND_CLK_CNTL, 7, "sd_emmc_p0_div_C",
+                       CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED);
+
+static struct meson_composite sdemmc_comp[] = {
+       {CLKID_SD_EMMC_B_P0_COMP, "sd_emmc_p0_B_comp",
+       sd_emmc_parent_names, ARRAY_SIZE(sd_emmc_parent_names),
+       &sd_emmc_p0_mux_B.hw, &sd_emmc_p0_div_B.hw,
+       &sd_emmc_p0_gate_B.hw, 0
+       },/* sd_emmc_B */
+
+       {CLKID_SD_EMMC_C_P0_COMP, "sd_emmc_p0_C_comp",
+       sd_emmc_parent_names, ARRAY_SIZE(sd_emmc_parent_names),
+       &sd_emmc_p0_mux_C.hw, &sd_emmc_p0_div_C.hw,
+       &sd_emmc_p0_gate_C.hw, 0
+       },/* sd_emmc_C */
+
+       {},
+};
+
+void meson_tl1_sdemmc_init(void)
+{
+       int length = ARRAY_SIZE(sdemmc_comp);
+
+       /* Populate base address for reg */
+       sd_emmc_p0_mux_B.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_mux_B.reg);
+       sd_emmc_p0_div_B.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_div_B.reg);
+       sd_emmc_p0_gate_B.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_gate_B.reg);
+       sd_emmc_p0_mux_C.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_mux_C.reg);
+       sd_emmc_p0_div_C.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_div_C.reg);
+       sd_emmc_p0_gate_C.reg = clk_base
+                               + (unsigned long)(sd_emmc_p0_gate_C.reg);
+
+       meson_clk_register_composite(clks, sdemmc_comp, length - 1);
+}