* [PATCH V7 10/12] clk: sprd: add clocks support for SC9860
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
This patch added the list of clocks for Spreadtrum's SC9860 SoC,
together with clock initialization code.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Kconfig | 10 +
drivers/clk/sprd/Makefile | 3 +
drivers/clk/sprd/sc9860-clk.c | 1974 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 1987 insertions(+)
create mode 100644 drivers/clk/sprd/sc9860-clk.c
diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
index 67a3287..8789247 100644
--- a/drivers/clk/sprd/Kconfig
+++ b/drivers/clk/sprd/Kconfig
@@ -2,3 +2,13 @@ config SPRD_COMMON_CLK
tristate "Clock support for Spreadtrum SoCs"
depends on ARCH_SPRD || COMPILE_TEST
default ARCH_SPRD
+
+if SPRD_COMMON_CLK
+
+# SoC Drivers
+
+config SPRD_SC9860_CLK
+ tristate "Support for the Spreadtrum SC9860 clocks"
+ depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST
+ default ARM64 && ARCH_SPRD
+endif
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index d693969..b0d81e5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -6,3 +6,6 @@ clk-sprd-y += mux.o
clk-sprd-y += div.o
clk-sprd-y += composite.o
clk-sprd-y += pll.o
+
+## SoC support
+obj-$(CONFIG_SPRD_SC9860_CLK) += sc9860-clk.o
diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c
new file mode 100644
index 0000000..ed5c027
--- /dev/null
+++ b/drivers/clk/sprd/sc9860-clk.c
@@ -0,0 +1,1974 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreatrum SC9860 clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/sprd,sc9860-clk.h>
+
+#include "common.h"
+#include "composite.h"
+#include "div.h"
+#include "gate.h"
+#include "mux.h"
+#include "pll.h"
+
+static CLK_FIXED_FACTOR(fac_4m, "fac-4m", "ext-26m",
+ 6, 1, 0);
+static CLK_FIXED_FACTOR(fac_2m, "fac-2m", "ext-26m",
+ 13, 1, 0);
+static CLK_FIXED_FACTOR(fac_1m, "fac-1m", "ext-26m",
+ 26, 1, 0);
+static CLK_FIXED_FACTOR(fac_250k, "fac-250k", "ext-26m",
+ 104, 1, 0);
+static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m", "ext-26m",
+ 1, 1, 0);
+static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m", "ext-26m",
+ 1, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_25m, "rco-25m", "ext-rc0-100m",
+ 4, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_4m, "rco-4m", "ext-rc0-100m",
+ 25, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_2m, "rco-2m", "ext-rc0-100m",
+ 50, 1, 0);
+static CLK_FIXED_FACTOR(fac_3k2, "fac-3k2", "ext-32k",
+ 10, 1, 0);
+static CLK_FIXED_FACTOR(fac_1k, "fac-1k", "ext-32k",
+ 32, 1, 0);
+
+static SPRD_SC_GATE_CLK(mpll0_gate, "mpll0-gate", "ext-26m", 0xb0,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mpll1_gate, "mpll1-gate", "ext-26m", 0xb0,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dpll0_gate, "dpll0-gate", "ext-26m", 0xb4,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dpll1_gate, "dpll1-gate", "ext-26m", 0xb4,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ltepll0_gate, "ltepll0-gate", "ext-26m", 0xb8,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(twpll_gate, "twpll-gate", "ext-26m", 0xbc,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x10c,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rpll0_gate, "rpll0-gate", "ext-26m", 0x16c,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(rpll1_gate, "rpll1-gate", "ext-26m", 0x16c,
+ 0x1000, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(cppll_gate, "cppll-gate", "ext-26m", 0x2b4,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpll_gate, "gpll-gate", "ext-26m", 0x32c,
+ 0x1000, BIT(0), CLK_IGNORE_UNUSED, CLK_GATE_SET_TO_DISABLE);
+
+static struct sprd_clk_common *sc9860_pmu_gate_clks[] = {
+ /* address base is 0x402b0000 */
+ &mpll0_gate.common,
+ &mpll1_gate.common,
+ &dpll0_gate.common,
+ &dpll1_gate.common,
+ <epll0_gate.common,
+ &twpll_gate.common,
+ <epll1_gate.common,
+ &rpll0_gate.common,
+ &rpll1_gate.common,
+ &cppll_gate.common,
+ &gpll_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_pmu_gate_hws = {
+ .hws = {
+ [CLK_FAC_4M] = &fac_4m.hw,
+ [CLK_FAC_2M] = &fac_2m.hw,
+ [CLK_FAC_1M] = &fac_1m.hw,
+ [CLK_FAC_250K] = &fac_250k.hw,
+ [CLK_FAC_RPLL0_26M] = &fac_rpll0_26m.hw,
+ [CLK_FAC_RPLL1_26M] = &fac_rpll1_26m.hw,
+ [CLK_FAC_RCO25M] = &fac_rco_25m.hw,
+ [CLK_FAC_RCO4M] = &fac_rco_4m.hw,
+ [CLK_FAC_RCO2M] = &fac_rco_2m.hw,
+ [CLK_FAC_3K2] = &fac_3k2.hw,
+ [CLK_FAC_1K] = &fac_1k.hw,
+ [CLK_MPLL0_GATE] = &mpll0_gate.common.hw,
+ [CLK_MPLL1_GATE] = &mpll1_gate.common.hw,
+ [CLK_DPLL0_GATE] = &dpll0_gate.common.hw,
+ [CLK_DPLL1_GATE] = &dpll1_gate.common.hw,
+ [CLK_LTEPLL0_GATE] = <epll0_gate.common.hw,
+ [CLK_TWPLL_GATE] = &twpll_gate.common.hw,
+ [CLK_LTEPLL1_GATE] = <epll1_gate.common.hw,
+ [CLK_RPLL0_GATE] = &rpll0_gate.common.hw,
+ [CLK_RPLL1_GATE] = &rpll1_gate.common.hw,
+ [CLK_CPPLL_GATE] = &cppll_gate.common.hw,
+ [CLK_GPLL_GATE] = &gpll_gate.common.hw,
+ },
+ .num = CLK_PMU_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_pmu_gate_desc = {
+ .clk_clks = sc9860_pmu_gate_clks,
+ .num_clk_clks = ARRAY_SIZE(sc9860_pmu_gate_clks),
+ .hw_clks = &sc9860_pmu_gate_hws,
+};
+
+/* GPLL/LPLL/DPLL/RPLL/CPLL */
+static const u64 itable1[4] = {3, 780000000, 988000000, 1196000000};
+
+/* TWPLL/MPLL0/MPLL1 */
+static const u64 itable2[4] = {3, 1638000000, 2080000000, 2600000000UL};
+
+static const struct clk_bit_field f_mpll0[PLL_FACT_MAX] = {
+ { .shift = 20, .width = 1 }, /* lock_done */
+ { .shift = 19, .width = 1 }, /* div_s */
+ { .shift = 18, .width = 1 }, /* mod_en */
+ { .shift = 17, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 11, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 56, .width = 1 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_K_FVCO(mpll0_clk, "mpll0", "mpll0-gate", 0x24,
+ 2, itable2, f_mpll0, 200,
+ 1000, 1000, 1, 1300000000);
+
+static const struct clk_bit_field f_mpll1[PLL_FACT_MAX] = {
+ { .shift = 20, .width = 1 }, /* lock_done */
+ { .shift = 19, .width = 1 }, /* div_s */
+ { .shift = 18, .width = 1 }, /* mod_en */
+ { .shift = 17, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 11, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 56, .width = 1 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(mpll1_clk, "mpll1", "mpll1-gate", 0x2c,
+ 2, itable2, f_mpll1, 200);
+
+static const struct clk_bit_field f_dpll[PLL_FACT_MAX] = {
+ { .shift = 16, .width = 1 }, /* lock_done */
+ { .shift = 15, .width = 1 }, /* div_s */
+ { .shift = 14, .width = 1 }, /* mod_en */
+ { .shift = 13, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 8, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(dpll0_clk, "dpll0", "dpll0-gate", 0x34,
+ 2, itable1, f_dpll, 200);
+
+static SPRD_PLL_WITH_ITABLE_1K(dpll1_clk, "dpll1", "dpll1-gate", 0x3c,
+ 2, itable1, f_dpll, 200);
+
+static const struct clk_bit_field f_rpll[PLL_FACT_MAX] = {
+ { .shift = 0, .width = 1 }, /* lock_done */
+ { .shift = 3, .width = 1 }, /* div_s */
+ { .shift = 80, .width = 1 }, /* mod_en */
+ { .shift = 81, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 14, .width = 2 }, /* ibias */
+ { .shift = 16, .width = 7 }, /* n */
+ { .shift = 4, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(rpll0_clk, "rpll0", "rpll0-gate", 0x44,
+ 3, itable1, f_rpll, 200);
+
+static SPRD_PLL_WITH_ITABLE_1K(rpll1_clk, "rpll1", "rpll1-gate", 0x50,
+ 3, itable1, f_rpll, 200);
+
+static const struct clk_bit_field f_twpll[PLL_FACT_MAX] = {
+ { .shift = 21, .width = 1 }, /* lock_done */
+ { .shift = 20, .width = 1 }, /* div_s */
+ { .shift = 19, .width = 1 }, /* mod_en */
+ { .shift = 18, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 13, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(twpll_clk, "twpll", "twpll-gate", 0x5c,
+ 2, itable2, f_twpll, 200);
+
+static const struct clk_bit_field f_ltepll[PLL_FACT_MAX] = {
+ { .shift = 31, .width = 1 }, /* lock_done */
+ { .shift = 27, .width = 1 }, /* div_s */
+ { .shift = 26, .width = 1 }, /* mod_en */
+ { .shift = 25, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 20, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(ltepll0_clk, "ltepll0", "ltepll0-gate",
+ 0x64, 2, itable1,
+ f_ltepll, 200);
+static SPRD_PLL_WITH_ITABLE_1K(ltepll1_clk, "ltepll1", "ltepll1-gate",
+ 0x6c, 2, itable1,
+ f_ltepll, 200);
+
+static const struct clk_bit_field f_gpll[PLL_FACT_MAX] = {
+ { .shift = 18, .width = 1 }, /* lock_done */
+ { .shift = 15, .width = 1 }, /* div_s */
+ { .shift = 14, .width = 1 }, /* mod_en */
+ { .shift = 13, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 8, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 17, .width = 1 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_K_FVCO(gpll_clk, "gpll", "gpll-gate", 0x9c,
+ 2, itable1, f_gpll, 200,
+ 1000, 1000, 1, 600000000);
+
+static const struct clk_bit_field f_cppll[PLL_FACT_MAX] = {
+ { .shift = 17, .width = 1 }, /* lock_done */
+ { .shift = 15, .width = 1 }, /* div_s */
+ { .shift = 14, .width = 1 }, /* mod_en */
+ { .shift = 13, .width = 1 }, /* sdm_en */
+ { .shift = 0, .width = 0 }, /* refin */
+ { .shift = 8, .width = 2 }, /* ibias */
+ { .shift = 0, .width = 7 }, /* n */
+ { .shift = 57, .width = 7 }, /* nint */
+ { .shift = 32, .width = 23}, /* kint */
+ { .shift = 0, .width = 0 }, /* prediv */
+ { .shift = 0, .width = 0 }, /* postdiv */
+};
+static SPRD_PLL_WITH_ITABLE_1K(cppll_clk, "cppll", "cppll-gate", 0xc4,
+ 2, itable1, f_cppll, 200);
+
+static CLK_FIXED_FACTOR(gpll_42m5, "gpll-42m5", "gpll", 20, 1, 0);
+static CLK_FIXED_FACTOR(twpll_768m, "twpll-768m", "twpll", 2, 1, 0);
+static CLK_FIXED_FACTOR(twpll_384m, "twpll-384m", "twpll", 4, 1, 0);
+static CLK_FIXED_FACTOR(twpll_192m, "twpll-192m", "twpll", 8, 1, 0);
+static CLK_FIXED_FACTOR(twpll_96m, "twpll-96m", "twpll", 16, 1, 0);
+static CLK_FIXED_FACTOR(twpll_48m, "twpll-48m", "twpll", 32, 1, 0);
+static CLK_FIXED_FACTOR(twpll_24m, "twpll-24m", "twpll", 64, 1, 0);
+static CLK_FIXED_FACTOR(twpll_12m, "twpll-12m", "twpll", 128, 1, 0);
+static CLK_FIXED_FACTOR(twpll_512m, "twpll-512m", "twpll", 3, 1, 0);
+static CLK_FIXED_FACTOR(twpll_256m, "twpll-256m", "twpll", 6, 1, 0);
+static CLK_FIXED_FACTOR(twpll_128m, "twpll-128m", "twpll", 12, 1, 0);
+static CLK_FIXED_FACTOR(twpll_64m, "twpll-64m", "twpll", 24, 1, 0);
+static CLK_FIXED_FACTOR(twpll_307m2, "twpll-307m2", "twpll", 5, 1, 0);
+static CLK_FIXED_FACTOR(twpll_153m6, "twpll-153m6", "twpll", 10, 1, 0);
+static CLK_FIXED_FACTOR(twpll_76m8, "twpll-76m8", "twpll", 20, 1, 0);
+static CLK_FIXED_FACTOR(twpll_51m2, "twpll-51m2", "twpll", 30, 1, 0);
+static CLK_FIXED_FACTOR(twpll_38m4, "twpll-38m4", "twpll", 40, 1, 0);
+static CLK_FIXED_FACTOR(twpll_19m2, "twpll-19m2", "twpll", 80, 1, 0);
+static CLK_FIXED_FACTOR(l0_614m4, "l0-614m4", "ltepll0", 2, 1, 0);
+static CLK_FIXED_FACTOR(l0_409m6, "l0-409m6", "ltepll0", 3, 1, 0);
+static CLK_FIXED_FACTOR(l0_38m, "l0-38m", "ltepll0", 32, 1, 0);
+static CLK_FIXED_FACTOR(l1_38m, "l1-38m", "ltepll1", 32, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_192m, "rpll0-192m", "rpll0", 6, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_96m, "rpll0-96m", "rpll0", 12, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_48m, "rpll0-48m", "rpll0", 24, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_468m, "rpll1-468m", "rpll1", 2, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_192m, "rpll1-192m", "rpll1", 6, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_96m, "rpll1-96m", "rpll1", 12, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_64m, "rpll1-64m", "rpll1", 18, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_48m, "rpll1-48m", "rpll1", 24, 1, 0);
+static CLK_FIXED_FACTOR(dpll0_50m, "dpll0-50m", "dpll0", 16, 1, 0);
+static CLK_FIXED_FACTOR(dpll1_50m, "dpll1-50m", "dpll1", 16, 1, 0);
+static CLK_FIXED_FACTOR(cppll_50m, "cppll-50m", "cppll", 18, 1, 0);
+static CLK_FIXED_FACTOR(m0_39m, "m0-39m", "mpll0", 32, 1, 0);
+static CLK_FIXED_FACTOR(m1_63m, "m1-63m", "mpll1", 32, 1, 0);
+
+static struct sprd_clk_common *sc9860_pll_clks[] = {
+ /* address base is 0x40400000 */
+ &mpll0_clk.common,
+ &mpll1_clk.common,
+ &dpll0_clk.common,
+ &dpll1_clk.common,
+ &rpll0_clk.common,
+ &rpll1_clk.common,
+ &twpll_clk.common,
+ <epll0_clk.common,
+ <epll1_clk.common,
+ &gpll_clk.common,
+ &cppll_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_pll_hws = {
+ .hws = {
+ [CLK_MPLL0] = &mpll0_clk.common.hw,
+ [CLK_MPLL1] = &mpll1_clk.common.hw,
+ [CLK_DPLL0] = &dpll0_clk.common.hw,
+ [CLK_DPLL1] = &dpll1_clk.common.hw,
+ [CLK_RPLL0] = &rpll0_clk.common.hw,
+ [CLK_RPLL1] = &rpll1_clk.common.hw,
+ [CLK_TWPLL] = &twpll_clk.common.hw,
+ [CLK_LTEPLL0] = <epll0_clk.common.hw,
+ [CLK_LTEPLL1] = <epll1_clk.common.hw,
+ [CLK_GPLL] = &gpll_clk.common.hw,
+ [CLK_CPPLL] = &cppll_clk.common.hw,
+ [CLK_GPLL_42M5] = &gpll_42m5.hw,
+ [CLK_TWPLL_768M] = &twpll_768m.hw,
+ [CLK_TWPLL_384M] = &twpll_384m.hw,
+ [CLK_TWPLL_192M] = &twpll_192m.hw,
+ [CLK_TWPLL_96M] = &twpll_96m.hw,
+ [CLK_TWPLL_48M] = &twpll_48m.hw,
+ [CLK_TWPLL_24M] = &twpll_24m.hw,
+ [CLK_TWPLL_12M] = &twpll_12m.hw,
+ [CLK_TWPLL_512M] = &twpll_512m.hw,
+ [CLK_TWPLL_256M] = &twpll_256m.hw,
+ [CLK_TWPLL_128M] = &twpll_128m.hw,
+ [CLK_TWPLL_64M] = &twpll_64m.hw,
+ [CLK_TWPLL_307M2] = &twpll_307m2.hw,
+ [CLK_TWPLL_153M6] = &twpll_153m6.hw,
+ [CLK_TWPLL_76M8] = &twpll_76m8.hw,
+ [CLK_TWPLL_51M2] = &twpll_51m2.hw,
+ [CLK_TWPLL_38M4] = &twpll_38m4.hw,
+ [CLK_TWPLL_19M2] = &twpll_19m2.hw,
+ [CLK_L0_614M4] = &l0_614m4.hw,
+ [CLK_L0_409M6] = &l0_409m6.hw,
+ [CLK_L0_38M] = &l0_38m.hw,
+ [CLK_L1_38M] = &l1_38m.hw,
+ [CLK_RPLL0_192M] = &rpll0_192m.hw,
+ [CLK_RPLL0_96M] = &rpll0_96m.hw,
+ [CLK_RPLL0_48M] = &rpll0_48m.hw,
+ [CLK_RPLL1_468M] = &rpll1_468m.hw,
+ [CLK_RPLL1_192M] = &rpll1_192m.hw,
+ [CLK_RPLL1_96M] = &rpll1_96m.hw,
+ [CLK_RPLL1_64M] = &rpll1_64m.hw,
+ [CLK_RPLL1_48M] = &rpll1_48m.hw,
+ [CLK_DPLL0_50M] = &dpll0_50m.hw,
+ [CLK_DPLL1_50M] = &dpll1_50m.hw,
+ [CLK_CPPLL_50M] = &cppll_50m.hw,
+ [CLK_M0_39M] = &m0_39m.hw,
+ [CLK_M1_63M] = &m1_63m.hw,
+ },
+ .num = CLK_PLL_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_pll_desc = {
+ .clk_clks = sc9860_pll_clks,
+ .num_clk_clks = ARRAY_SIZE(sc9860_pll_clks),
+ .hw_clks = &sc9860_pll_hws,
+};
+
+#define SC9860_MUX_FLAG \
+ (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT)
+
+static const char * const ap_apb_parents[] = { "ext-26m", "twpll-64m",
+ "twpll-96m", "twpll-128m" };
+static SPRD_MUX_CLK(ap_apb, "ap-apb", ap_apb_parents,
+ 0x20, 0, 1, SC9860_MUX_FLAG);
+
+static const char * const ap_apb_usb3[] = { "ext-32k", "twpll-24m" };
+static SPRD_MUX_CLK(ap_usb3, "ap-usb3", ap_apb_usb3,
+ 0x2c, 0, 1, SC9860_MUX_FLAG);
+
+static const char * const uart_parents[] = { "ext-26m", "twpll-48m",
+ "twpll-51m2", "twpll-96m" };
+static SPRD_COMP_CLK(uart0_clk, "uart0", uart_parents, 0x30,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart1_clk, "uart1", uart_parents, 0x34,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart2_clk, "uart2", uart_parents, 0x38,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart3_clk, "uart3", uart_parents, 0x3c,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart4_clk, "uart4", uart_parents, 0x40,
+ 0, 2, 8, 3, 0);
+
+static const char * const i2c_parents[] = { "ext-26m", "twpll-48m",
+ "twpll-51m2", "twpll-153m6" };
+static SPRD_COMP_CLK(i2c0_clk, "i2c0", i2c_parents, 0x44,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c1_clk, "i2c1", i2c_parents, 0x48,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c2_clk, "i2c2", i2c_parents, 0x4c,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c3_clk, "i2c3", i2c_parents, 0x50,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c4_clk, "i2c4", i2c_parents, 0x54,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c5_clk, "i2c5", i2c_parents, 0x58,
+ 0, 2, 8, 3, 0);
+
+static const char * const spi_parents[] = { "ext-26m", "twpll-128m",
+ "twpll-153m6", "twpll-192m" };
+static SPRD_COMP_CLK(spi0_clk, "spi0", spi_parents, 0x5c,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi1_clk, "spi1", spi_parents, 0x60,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi2_clk, "spi2", spi_parents, 0x64,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi3_clk, "spi3", spi_parents, 0x68,
+ 0, 2, 8, 3, 0);
+
+static const char * const iis_parents[] = { "ext-26m",
+ "twpll-128m",
+ "twpll-153m6" };
+static SPRD_COMP_CLK(iis0_clk, "iis0", iis_parents, 0x6c,
+ 0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis1_clk, "iis1", iis_parents, 0x70,
+ 0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis2_clk, "iis2", iis_parents, 0x74,
+ 0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis3_clk, "iis3", iis_parents, 0x78,
+ 0, 2, 8, 6, 0);
+
+static struct sprd_clk_common *sc9860_ap_clks[] = {
+ /* address base is 0x20000000 */
+ &ap_apb.common,
+ &ap_usb3.common,
+ &uart0_clk.common,
+ &uart1_clk.common,
+ &uart2_clk.common,
+ &uart3_clk.common,
+ &uart4_clk.common,
+ &i2c0_clk.common,
+ &i2c1_clk.common,
+ &i2c2_clk.common,
+ &i2c3_clk.common,
+ &i2c4_clk.common,
+ &i2c5_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &spi2_clk.common,
+ &spi3_clk.common,
+ &iis0_clk.common,
+ &iis1_clk.common,
+ &iis2_clk.common,
+ &iis3_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_ap_clk_hws = {
+ .hws = {
+ [CLK_AP_APB] = &ap_apb.common.hw,
+ [CLK_AP_USB3] = &ap_usb3.common.hw,
+ [CLK_UART0] = &uart0_clk.common.hw,
+ [CLK_UART1] = &uart1_clk.common.hw,
+ [CLK_UART2] = &uart2_clk.common.hw,
+ [CLK_UART3] = &uart3_clk.common.hw,
+ [CLK_UART4] = &uart4_clk.common.hw,
+ [CLK_I2C0] = &i2c0_clk.common.hw,
+ [CLK_I2C1] = &i2c1_clk.common.hw,
+ [CLK_I2C2] = &i2c2_clk.common.hw,
+ [CLK_I2C3] = &i2c3_clk.common.hw,
+ [CLK_I2C4] = &i2c4_clk.common.hw,
+ [CLK_I2C5] = &i2c5_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_SPI2] = &spi2_clk.common.hw,
+ [CLK_SPI3] = &spi3_clk.common.hw,
+ [CLK_IIS0] = &iis0_clk.common.hw,
+ [CLK_IIS1] = &iis1_clk.common.hw,
+ [CLK_IIS2] = &iis2_clk.common.hw,
+ [CLK_IIS3] = &iis3_clk.common.hw,
+ },
+ .num = CLK_AP_CLK_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_ap_clk_desc = {
+ .clk_clks = sc9860_ap_clks,
+ .num_clk_clks = ARRAY_SIZE(sc9860_ap_clks),
+ .hw_clks = &sc9860_ap_clk_hws,
+};
+
+static const char * const aon_apb_parents[] = { "rco-25m", "ext-26m",
+ "ext-rco-100m", "twpll-96m",
+ "twpll-128m",
+ "twpll-153m6" };
+static SPRD_COMP_CLK(aon_apb, "aon-apb", aon_apb_parents, 0x230,
+ 0, 3, 8, 2, 0);
+
+static const char * const aux_parents[] = { "ext-32k", "rpll0-26m",
+ "rpll1-26m", "ext-26m",
+ "cppll-50m", "rco-25m",
+ "dpll0-50m", "dpll1-50m",
+ "gpll-42m5", "twpll-48m",
+ "m0-39m", "m1-63m",
+ "l0-38m", "l1-38m" };
+
+static SPRD_COMP_CLK(aux0_clk, "aux0", aux_parents, 0x238,
+ 0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(aux1_clk, "aux1", aux_parents, 0x23c,
+ 0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(aux2_clk, "aux2", aux_parents, 0x240,
+ 0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(probe_clk, "probe", aux_parents, 0x244,
+ 0, 5, 8, 4, 0);
+
+static const char * const sp_ahb_parents[] = { "rco-4m", "ext-26m",
+ "ext-rco-100m", "twpll-96m",
+ "twpll-128m",
+ "twpll-153m6" };
+static SPRD_COMP_CLK(sp_ahb, "sp-ahb", sp_ahb_parents, 0x2d0,
+ 0, 3, 8, 2, 0);
+
+static const char * const cci_parents[] = { "ext-26m", "twpll-384m",
+ "l0-614m4", "twpll-768m" };
+static SPRD_COMP_CLK(cci_clk, "cci", cci_parents, 0x300,
+ 0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(gic_clk, "gic", cci_parents, 0x304,
+ 0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(cssys_clk, "cssys", cci_parents, 0x310,
+ 0, 2, 8, 2, 0);
+
+static const char * const sdio_2x_parents[] = { "fac-1m", "ext-26m",
+ "twpll-307m2", "twpll-384m",
+ "l0-409m6" };
+static SPRD_COMP_CLK(sdio0_2x, "sdio0-2x", sdio_2x_parents, 0x328,
+ 0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(sdio1_2x, "sdio1-2x", sdio_2x_parents, 0x330,
+ 0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(sdio2_2x, "sdio2-2x", sdio_2x_parents, 0x338,
+ 0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(emmc_2x, "emmc-2x", sdio_2x_parents, 0x340,
+ 0, 3, 8, 4, 0);
+
+static SPRD_DIV_CLK(sdio0_1x, "sdio0-1x", "sdio0-2x", 0x32c,
+ 8, 1, 0);
+static SPRD_DIV_CLK(sdio1_1x, "sdio1-1x", "sdio1-2x", 0x334,
+ 8, 1, 0);
+static SPRD_DIV_CLK(sdio2_1x, "sdio2-1x", "sdio2-2x", 0x33c,
+ 8, 1, 0);
+static SPRD_DIV_CLK(emmc_1x, "emmc-1x", "emmc-2x", 0x344,
+ 8, 1, 0);
+
+static const char * const adi_parents[] = { "rco-4m", "ext-26m",
+ "rco-25m", "twpll-38m4",
+ "twpll-51m2" };
+static SPRD_MUX_CLK(adi_clk, "adi", adi_parents, 0x234,
+ 0, 3, SC9860_MUX_FLAG);
+
+static const char * const pwm_parents[] = { "ext-32k", "ext-26m",
+ "rco-4m", "rco-25m",
+ "twpll-48m" };
+static SPRD_MUX_CLK(pwm0_clk, "pwm0", pwm_parents, 0x248,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm1_clk, "pwm1", pwm_parents, 0x24c,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm2_clk, "pwm2", pwm_parents, 0x250,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm3_clk, "pwm3", pwm_parents, 0x254,
+ 0, 3, SC9860_MUX_FLAG);
+
+static const char * const efuse_parents[] = { "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(efuse_clk, "efuse", efuse_parents, 0x258,
+ 0, 1, SC9860_MUX_FLAG);
+
+static const char * const cm3_uart_parents[] = { "rco-4m", "ext-26m",
+ "rco-100m", "twpll-48m",
+ "twpll-51m2", "twpll-96m",
+ "twpll-128m" };
+static SPRD_MUX_CLK(cm3_uart0, "cm3-uart0", cm3_uart_parents, 0x25c,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(cm3_uart1, "cm3-uart1", cm3_uart_parents, 0x260,
+ 0, 3, SC9860_MUX_FLAG);
+
+static const char * const thm_parents[] = { "ext-32k", "fac-250k" };
+static SPRD_MUX_CLK(thm_clk, "thm", thm_parents, 0x270,
+ 0, 1, SC9860_MUX_FLAG);
+
+static const char * const cm3_i2c_parents[] = { "rco-4m",
+ "ext-26m",
+ "rco-100m",
+ "twpll-48m",
+ "twpll-51m2",
+ "twpll-153m6" };
+static SPRD_MUX_CLK(cm3_i2c0, "cm3-i2c0", cm3_i2c_parents, 0x274,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(cm3_i2c1, "cm3-i2c1", cm3_i2c_parents, 0x278,
+ 0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(aon_i2c, "aon-i2c", cm3_i2c_parents, 0x280,
+ 0, 3, SC9860_MUX_FLAG);
+
+static const char * const cm4_spi_parents[] = { "ext-26m", "twpll-96m",
+ "rco-100m", "twpll-128m",
+ "twpll-153m6", "twpll-192m" };
+static SPRD_MUX_CLK(cm4_spi, "cm4-spi", cm4_spi_parents, 0x27c,
+ 0, 3, SC9860_MUX_FLAG);
+
+static SPRD_MUX_CLK(avs_clk, "avs", uart_parents, 0x284,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const ca53_dap_parents[] = { "ext-26m", "rco-4m",
+ "rco-100m", "twpll-76m8",
+ "twpll-128m", "twpll-153m6" };
+static SPRD_MUX_CLK(ca53_dap, "ca53-dap", ca53_dap_parents, 0x288,
+ 0, 3, SC9860_MUX_FLAG);
+
+static const char * const ca53_ts_parents[] = { "ext-32k", "ext-26m",
+ "clk-twpll-128m",
+ "clk-twpll-153m6" };
+static SPRD_MUX_CLK(ca53_ts, "ca53-ts", ca53_ts_parents, 0x290,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const djtag_tck_parents[] = { "rco-4m", "ext-26m" };
+static SPRD_MUX_CLK(djtag_tck, "djtag-tck", djtag_tck_parents, 0x2c8,
+ 0, 1, SC9860_MUX_FLAG);
+
+static const char * const pmu_parents[] = { "ext-32k", "rco-4m", "clk-4m" };
+static SPRD_MUX_CLK(pmu_clk, "pmu", pmu_parents, 0x2e0,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const pmu_26m_parents[] = { "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(pmu_26m, "pmu-26m", pmu_26m_parents, 0x2e4,
+ 0, 1, SC9860_MUX_FLAG);
+
+static const char * const debounce_parents[] = { "ext-32k", "rco-4m",
+ "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(debounce_clk, "debounce", debounce_parents, 0x2e8,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const otg2_ref_parents[] = { "twpll-12m", "twpll-24m" };
+static SPRD_MUX_CLK(otg2_ref, "otg2-ref", otg2_ref_parents, 0x2f4,
+ 0, 1, SC9860_MUX_FLAG);
+
+static const char * const usb3_ref_parents[] = { "twpll-24m", "twpll-19m2",
+ "twpll-48m" };
+static SPRD_MUX_CLK(usb3_ref, "usb3-ref", usb3_ref_parents, 0x2f8,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const ap_axi_parents[] = { "ext-26m", "twpll-76m8",
+ "twpll-128m", "twpll-256m" };
+static SPRD_MUX_CLK(ap_axi, "ap-axi", ap_axi_parents, 0x324,
+ 0, 2, SC9860_MUX_FLAG);
+
+static struct sprd_clk_common *sc9860_aon_prediv[] = {
+ /* address base is 0x402d0000 */
+ &aon_apb.common,
+ &aux0_clk.common,
+ &aux1_clk.common,
+ &aux2_clk.common,
+ &probe_clk.common,
+ &sp_ahb.common,
+ &cci_clk.common,
+ &gic_clk.common,
+ &cssys_clk.common,
+ &sdio0_2x.common,
+ &sdio1_2x.common,
+ &sdio2_2x.common,
+ &emmc_2x.common,
+ &sdio0_1x.common,
+ &sdio1_1x.common,
+ &sdio2_1x.common,
+ &emmc_1x.common,
+ &adi_clk.common,
+ &pwm0_clk.common,
+ &pwm1_clk.common,
+ &pwm2_clk.common,
+ &pwm3_clk.common,
+ &efuse_clk.common,
+ &cm3_uart0.common,
+ &cm3_uart1.common,
+ &thm_clk.common,
+ &cm3_i2c0.common,
+ &cm3_i2c1.common,
+ &cm4_spi.common,
+ &aon_i2c.common,
+ &avs_clk.common,
+ &ca53_dap.common,
+ &ca53_ts.common,
+ &djtag_tck.common,
+ &pmu_clk.common,
+ &pmu_26m.common,
+ &debounce_clk.common,
+ &otg2_ref.common,
+ &usb3_ref.common,
+ &ap_axi.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aon_prediv_hws = {
+ .hws = {
+ [CLK_AON_APB] = &aon_apb.common.hw,
+ [CLK_AUX0] = &aux0_clk.common.hw,
+ [CLK_AUX1] = &aux1_clk.common.hw,
+ [CLK_AUX2] = &aux2_clk.common.hw,
+ [CLK_PROBE] = &probe_clk.common.hw,
+ [CLK_SP_AHB] = &sp_ahb.common.hw,
+ [CLK_CCI] = &cci_clk.common.hw,
+ [CLK_GIC] = &gic_clk.common.hw,
+ [CLK_CSSYS] = &cssys_clk.common.hw,
+ [CLK_SDIO0_2X] = &sdio0_2x.common.hw,
+ [CLK_SDIO1_2X] = &sdio1_2x.common.hw,
+ [CLK_SDIO2_2X] = &sdio2_2x.common.hw,
+ [CLK_EMMC_2X] = &emmc_2x.common.hw,
+ [CLK_SDIO0_1X] = &sdio0_1x.common.hw,
+ [CLK_SDIO1_1X] = &sdio1_1x.common.hw,
+ [CLK_SDIO2_1X] = &sdio2_1x.common.hw,
+ [CLK_EMMC_1X] = &emmc_1x.common.hw,
+ [CLK_ADI] = &adi_clk.common.hw,
+ [CLK_PWM0] = &pwm0_clk.common.hw,
+ [CLK_PWM1] = &pwm1_clk.common.hw,
+ [CLK_PWM2] = &pwm2_clk.common.hw,
+ [CLK_PWM3] = &pwm3_clk.common.hw,
+ [CLK_EFUSE] = &efuse_clk.common.hw,
+ [CLK_CM3_UART0] = &cm3_uart0.common.hw,
+ [CLK_CM3_UART1] = &cm3_uart1.common.hw,
+ [CLK_THM] = &thm_clk.common.hw,
+ [CLK_CM3_I2C0] = &cm3_i2c0.common.hw,
+ [CLK_CM3_I2C1] = &cm3_i2c1.common.hw,
+ [CLK_CM4_SPI] = &cm4_spi.common.hw,
+ [CLK_AON_I2C] = &aon_i2c.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_CA53_DAP] = &ca53_dap.common.hw,
+ [CLK_CA53_TS] = &ca53_ts.common.hw,
+ [CLK_DJTAG_TCK] = &djtag_tck.common.hw,
+ [CLK_PMU] = &pmu_clk.common.hw,
+ [CLK_PMU_26M] = &pmu_26m.common.hw,
+ [CLK_DEBOUNCE] = &debounce_clk.common.hw,
+ [CLK_OTG2_REF] = &otg2_ref.common.hw,
+ [CLK_USB3_REF] = &usb3_ref.common.hw,
+ [CLK_AP_AXI] = &ap_axi.common.hw,
+ },
+ .num = CLK_AON_PREDIV_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aon_prediv_desc = {
+ .clk_clks = sc9860_aon_prediv,
+ .num_clk_clks = ARRAY_SIZE(sc9860_aon_prediv),
+ .hw_clks = &sc9860_aon_prediv_hws,
+};
+
+static SPRD_SC_GATE_CLK(usb3_eb, "usb3-eb", "ap-axi", 0x0,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(usb3_suspend, "usb3-suspend", "ap-axi", 0x0,
+ 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(usb3_ref_eb, "usb3-ref-eb", "ap-axi", 0x0,
+ 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dma_eb, "dma-eb", "ap-axi", 0x0,
+ 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio0_eb, "sdio0-eb", "ap-axi", 0x0,
+ 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio1_eb, "sdio1-eb", "ap-axi", 0x0,
+ 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio2_eb, "sdio2-eb", "ap-axi", 0x0,
+ 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(emmc_eb, "emmc-eb", "ap-axi", 0x0,
+ 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rom_eb, "rom-eb", "ap-axi", 0x0,
+ 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(busmon_eb, "busmon-eb", "ap-axi", 0x0,
+ 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cc63s_eb, "cc63s-eb", "ap-axi", 0x0,
+ 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cc63p_eb, "cc63p-eb", "ap-axi", 0x0,
+ 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ce0_eb, "ce0-eb", "ap-axi", 0x0,
+ 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ce1_eb, "ce1-eb", "ap-axi", 0x0,
+ 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+
+static struct sprd_clk_common *sc9860_apahb_gate[] = {
+ /* address base is 0x20210000 */
+ &usb3_eb.common,
+ &usb3_suspend.common,
+ &usb3_ref_eb.common,
+ &dma_eb.common,
+ &sdio0_eb.common,
+ &sdio1_eb.common,
+ &sdio2_eb.common,
+ &emmc_eb.common,
+ &rom_eb.common,
+ &busmon_eb.common,
+ &cc63s_eb.common,
+ &cc63p_eb.common,
+ &ce0_eb.common,
+ &ce1_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_apahb_gate_hws = {
+ .hws = {
+ [CLK_USB3_EB] = &usb3_eb.common.hw,
+ [CLK_USB3_SUSPEND_EB] = &usb3_suspend.common.hw,
+ [CLK_USB3_REF_EB] = &usb3_ref_eb.common.hw,
+ [CLK_DMA_EB] = &dma_eb.common.hw,
+ [CLK_SDIO0_EB] = &sdio0_eb.common.hw,
+ [CLK_SDIO1_EB] = &sdio1_eb.common.hw,
+ [CLK_SDIO2_EB] = &sdio2_eb.common.hw,
+ [CLK_EMMC_EB] = &emmc_eb.common.hw,
+ [CLK_ROM_EB] = &rom_eb.common.hw,
+ [CLK_BUSMON_EB] = &busmon_eb.common.hw,
+ [CLK_CC63S_EB] = &cc63s_eb.common.hw,
+ [CLK_CC63P_EB] = &cc63p_eb.common.hw,
+ [CLK_CE0_EB] = &ce0_eb.common.hw,
+ [CLK_CE1_EB] = &ce1_eb.common.hw,
+ },
+ .num = CLK_APAHB_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_apahb_gate_desc = {
+ .clk_clks = sc9860_apahb_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_apahb_gate),
+ .hw_clks = &sc9860_apahb_gate_hws,
+};
+
+static SPRD_SC_GATE_CLK(avs_lit_eb, "avs-lit-eb", "aon-apb", 0x0,
+ 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_big_eb, "avs-big-eb", "aon-apb", 0x0,
+ 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc5_eb, "ap-intc5-eb", "aon-apb", 0x0,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpio_eb, "gpio-eb", "aon-apb", 0x0,
+ 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm0_eb, "pwm0-eb", "aon-apb", 0x0,
+ 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm1_eb, "pwm1-eb", "aon-apb", 0x0,
+ 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm2_eb, "pwm2-eb", "aon-apb", 0x0,
+ 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm3_eb, "pwm3-eb", "aon-apb", 0x0,
+ 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(kpd_eb, "kpd-eb", "aon-apb", 0x0,
+ 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_sys_eb, "aon-sys-eb", "aon-apb", 0x0,
+ 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_sys_eb, "ap-sys-eb", "aon-apb", 0x0,
+ 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_tmr_eb, "aon-tmr-eb", "aon-apb", 0x0,
+ 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr0_eb, "ap-tmr0-eb", "aon-apb", 0x0,
+ 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(efuse_eb, "efuse-eb", "aon-apb", 0x0,
+ 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_eb, "eic-eb", "aon-apb", 0x0,
+ 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pub1_reg_eb, "pub1-reg-eb", "aon-apb", 0x0,
+ 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(adi_eb, "adi-eb", "aon-apb", 0x0,
+ 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc0_eb, "ap-intc0-eb", "aon-apb", 0x0,
+ 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc1_eb, "ap-intc1-eb", "aon-apb", 0x0,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc2_eb, "ap-intc2-eb", "aon-apb", 0x0,
+ 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc3_eb, "ap-intc3-eb", "aon-apb", 0x0,
+ 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc4_eb, "ap-intc4-eb", "aon-apb", 0x0,
+ 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(splk_eb, "splk-eb", "aon-apb", 0x0,
+ 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mspi_eb, "mspi-eb", "aon-apb", 0x0,
+ 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pub0_reg_eb, "pub0-reg-eb", "aon-apb", 0x0,
+ 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pin_eb, "pin-eb", "aon-apb", 0x0,
+ 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_ckg_eb, "aon-ckg-eb", "aon-apb", 0x0,
+ 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu_eb, "gpu-eb", "aon-apb", 0x0,
+ 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_ts0_eb, "apcpu-ts0-eb", "aon-apb", 0x0,
+ 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_ts1_eb, "apcpu-ts1-eb", "aon-apb", 0x0,
+ 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dap_eb, "dap-eb", "aon-apb", 0x0,
+ 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c_eb, "i2c-eb", "aon-apb", 0x0,
+ 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pmu_eb, "pmu-eb", "aon-apb", 0x4,
+ 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(thm_eb, "thm-eb", "aon-apb", 0x4,
+ 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux0_eb, "aux0-eb", "aon-apb", 0x4,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux1_eb, "aux1-eb", "aon-apb", 0x4,
+ 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux2_eb, "aux2-eb", "aon-apb", 0x4,
+ 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(probe_eb, "probe-eb", "aon-apb", 0x4,
+ 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu0_avs_eb, "gpu0-avs-eb", "aon-apb", 0x4,
+ 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu1_avs_eb, "gpu1-avs-eb", "aon-apb", 0x4,
+ 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_wdg_eb, "apcpu-wdg-eb", "aon-apb", 0x4,
+ 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr1_eb, "ap-tmr1-eb", "aon-apb", 0x4,
+ 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr2_eb, "ap-tmr2-eb", "aon-apb", 0x4,
+ 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(disp_emc_eb, "disp-emc-eb", "aon-apb", 0x4,
+ 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(zip_emc_eb, "zip-emc-eb", "aon-apb", 0x4,
+ 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gsp_emc_eb, "gsp-emc-eb", "aon-apb", 0x4,
+ 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(osc_aon_eb, "osc-aon-eb", "aon-apb", 0x4,
+ 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_trx_eb, "lvds-trx-eb", "aon-apb", 0x4,
+ 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_tcxo_eb, "lvds-tcxo-eb", "aon-apb", 0x4,
+ 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mdar_eb, "mdar-eb", "aon-apb", 0x4,
+ 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rtc4m0_cal_eb, "rtc4m0-cal-eb", "aon-apb", 0x4,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rct100m_cal_eb, "rct100m-cal-eb", "aon-apb", 0x4,
+ 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(djtag_eb, "djtag-eb", "aon-apb", 0x4,
+ 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mbox_eb, "mbox-eb", "aon-apb", 0x4,
+ 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_dma_eb, "aon-dma-eb", "aon-apb", 0x4,
+ 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dbg_emc_eb, "dbg-emc-eb", "aon-apb", 0x4,
+ 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_pll_div_en, "lvds-pll-div-en", "aon-apb", 0x4,
+ 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(def_eb, "def-eb", "aon-apb", 0x4,
+ 0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_apb_rsv0, "aon-apb-rsv0", "aon-apb", 0x4,
+ 0x1000, BIT(26), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(orp_jtag_eb, "orp-jtag-eb", "aon-apb", 0x4,
+ 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(vsp_eb, "vsp-eb", "aon-apb", 0x4,
+ 0x1000, BIT(28), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cam_eb, "cam-eb", "aon-apb", 0x4,
+ 0x1000, BIT(29), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(disp_eb, "disp-eb", "aon-apb", 0x4,
+ 0x1000, BIT(30), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dbg_axi_if_eb, "dbg-axi-if-eb", "aon-apb", 0x4,
+ 0x1000, BIT(31), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio0_2x_en, "sdio0-2x-en", "aon-apb", 0x13c,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(sdio1_2x_en, "sdio1-2x-en", "aon-apb", 0x13c,
+ 0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(sdio2_2x_en, "sdio2-2x-en", "aon-apb", 0x13c,
+ 0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(emmc_2x_en, "emmc-2x-en", "aon-apb", 0x13c,
+ 0x1000, BIT(9), 0, 0);
+
+static struct sprd_clk_common *sc9860_aon_gate[] = {
+ /* address base is 0x402e0000 */
+ &avs_lit_eb.common,
+ &avs_big_eb.common,
+ &ap_intc5_eb.common,
+ &gpio_eb.common,
+ &pwm0_eb.common,
+ &pwm1_eb.common,
+ &pwm2_eb.common,
+ &pwm3_eb.common,
+ &kpd_eb.common,
+ &aon_sys_eb.common,
+ &ap_sys_eb.common,
+ &aon_tmr_eb.common,
+ &ap_tmr0_eb.common,
+ &efuse_eb.common,
+ &eic_eb.common,
+ &pub1_reg_eb.common,
+ &adi_eb.common,
+ &ap_intc0_eb.common,
+ &ap_intc1_eb.common,
+ &ap_intc2_eb.common,
+ &ap_intc3_eb.common,
+ &ap_intc4_eb.common,
+ &splk_eb.common,
+ &mspi_eb.common,
+ &pub0_reg_eb.common,
+ &pin_eb.common,
+ &aon_ckg_eb.common,
+ &gpu_eb.common,
+ &apcpu_ts0_eb.common,
+ &apcpu_ts1_eb.common,
+ &dap_eb.common,
+ &i2c_eb.common,
+ &pmu_eb.common,
+ &thm_eb.common,
+ &aux0_eb.common,
+ &aux1_eb.common,
+ &aux2_eb.common,
+ &probe_eb.common,
+ &gpu0_avs_eb.common,
+ &gpu1_avs_eb.common,
+ &apcpu_wdg_eb.common,
+ &ap_tmr1_eb.common,
+ &ap_tmr2_eb.common,
+ &disp_emc_eb.common,
+ &zip_emc_eb.common,
+ &gsp_emc_eb.common,
+ &osc_aon_eb.common,
+ &lvds_trx_eb.common,
+ &lvds_tcxo_eb.common,
+ &mdar_eb.common,
+ &rtc4m0_cal_eb.common,
+ &rct100m_cal_eb.common,
+ &djtag_eb.common,
+ &mbox_eb.common,
+ &aon_dma_eb.common,
+ &dbg_emc_eb.common,
+ &lvds_pll_div_en.common,
+ &def_eb.common,
+ &aon_apb_rsv0.common,
+ &orp_jtag_eb.common,
+ &vsp_eb.common,
+ &cam_eb.common,
+ &disp_eb.common,
+ &dbg_axi_if_eb.common,
+ &sdio0_2x_en.common,
+ &sdio1_2x_en.common,
+ &sdio2_2x_en.common,
+ &emmc_2x_en.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
+ .hws = {
+ [CLK_AVS_LIT_EB] = &avs_lit_eb.common.hw,
+ [CLK_AVS_BIG_EB] = &avs_big_eb.common.hw,
+ [CLK_AP_INTC5_EB] = &ap_intc5_eb.common.hw,
+ [CLK_GPIO_EB] = &gpio_eb.common.hw,
+ [CLK_PWM0_EB] = &pwm0_eb.common.hw,
+ [CLK_PWM1_EB] = &pwm1_eb.common.hw,
+ [CLK_PWM2_EB] = &pwm2_eb.common.hw,
+ [CLK_PWM3_EB] = &pwm3_eb.common.hw,
+ [CLK_KPD_EB] = &kpd_eb.common.hw,
+ [CLK_AON_SYS_EB] = &aon_sys_eb.common.hw,
+ [CLK_AP_SYS_EB] = &ap_sys_eb.common.hw,
+ [CLK_AON_TMR_EB] = &aon_tmr_eb.common.hw,
+ [CLK_AP_TMR0_EB] = &ap_tmr0_eb.common.hw,
+ [CLK_EFUSE_EB] = &efuse_eb.common.hw,
+ [CLK_EIC_EB] = &eic_eb.common.hw,
+ [CLK_PUB1_REG_EB] = &pub1_reg_eb.common.hw,
+ [CLK_ADI_EB] = &adi_eb.common.hw,
+ [CLK_AP_INTC0_EB] = &ap_intc0_eb.common.hw,
+ [CLK_AP_INTC1_EB] = &ap_intc1_eb.common.hw,
+ [CLK_AP_INTC2_EB] = &ap_intc2_eb.common.hw,
+ [CLK_AP_INTC3_EB] = &ap_intc3_eb.common.hw,
+ [CLK_AP_INTC4_EB] = &ap_intc4_eb.common.hw,
+ [CLK_SPLK_EB] = &splk_eb.common.hw,
+ [CLK_MSPI_EB] = &mspi_eb.common.hw,
+ [CLK_PUB0_REG_EB] = &pub0_reg_eb.common.hw,
+ [CLK_PIN_EB] = &pin_eb.common.hw,
+ [CLK_AON_CKG_EB] = &aon_ckg_eb.common.hw,
+ [CLK_GPU_EB] = &gpu_eb.common.hw,
+ [CLK_APCPU_TS0_EB] = &apcpu_ts0_eb.common.hw,
+ [CLK_APCPU_TS1_EB] = &apcpu_ts1_eb.common.hw,
+ [CLK_DAP_EB] = &dap_eb.common.hw,
+ [CLK_I2C_EB] = &i2c_eb.common.hw,
+ [CLK_PMU_EB] = &pmu_eb.common.hw,
+ [CLK_THM_EB] = &thm_eb.common.hw,
+ [CLK_AUX0_EB] = &aux0_eb.common.hw,
+ [CLK_AUX1_EB] = &aux1_eb.common.hw,
+ [CLK_AUX2_EB] = &aux2_eb.common.hw,
+ [CLK_PROBE_EB] = &probe_eb.common.hw,
+ [CLK_GPU0_AVS_EB] = &gpu0_avs_eb.common.hw,
+ [CLK_GPU1_AVS_EB] = &gpu1_avs_eb.common.hw,
+ [CLK_APCPU_WDG_EB] = &apcpu_wdg_eb.common.hw,
+ [CLK_AP_TMR1_EB] = &ap_tmr1_eb.common.hw,
+ [CLK_AP_TMR2_EB] = &ap_tmr2_eb.common.hw,
+ [CLK_DISP_EMC_EB] = &disp_emc_eb.common.hw,
+ [CLK_ZIP_EMC_EB] = &zip_emc_eb.common.hw,
+ [CLK_GSP_EMC_EB] = &gsp_emc_eb.common.hw,
+ [CLK_OSC_AON_EB] = &osc_aon_eb.common.hw,
+ [CLK_LVDS_TRX_EB] = &lvds_trx_eb.common.hw,
+ [CLK_LVDS_TCXO_EB] = &lvds_tcxo_eb.common.hw,
+ [CLK_MDAR_EB] = &mdar_eb.common.hw,
+ [CLK_RTC4M0_CAL_EB] = &rtc4m0_cal_eb.common.hw,
+ [CLK_RCT100M_CAL_EB] = &rct100m_cal_eb.common.hw,
+ [CLK_DJTAG_EB] = &djtag_eb.common.hw,
+ [CLK_MBOX_EB] = &mbox_eb.common.hw,
+ [CLK_AON_DMA_EB] = &aon_dma_eb.common.hw,
+ [CLK_DBG_EMC_EB] = &dbg_emc_eb.common.hw,
+ [CLK_LVDS_PLL_DIV_EN] = &lvds_pll_div_en.common.hw,
+ [CLK_DEF_EB] = &def_eb.common.hw,
+ [CLK_AON_APB_RSV0] = &aon_apb_rsv0.common.hw,
+ [CLK_ORP_JTAG_EB] = &orp_jtag_eb.common.hw,
+ [CLK_VSP_EB] = &vsp_eb.common.hw,
+ [CLK_CAM_EB] = &cam_eb.common.hw,
+ [CLK_DISP_EB] = &disp_eb.common.hw,
+ [CLK_DBG_AXI_IF_EB] = &dbg_axi_if_eb.common.hw,
+ [CLK_SDIO0_2X_EN] = &sdio0_2x_en.common.hw,
+ [CLK_SDIO1_2X_EN] = &sdio1_2x_en.common.hw,
+ [CLK_SDIO2_2X_EN] = &sdio2_2x_en.common.hw,
+ [CLK_EMMC_2X_EN] = &emmc_2x_en.common.hw,
+ },
+ .num = CLK_AON_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aon_gate_desc = {
+ .clk_clks = sc9860_aon_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_aon_gate),
+ .hw_clks = &sc9860_aon_gate_hws,
+};
+
+static const u8 mcu_table[] = { 0, 1, 2, 3, 4, 8 };
+static const char * const lit_mcu_parents[] = { "ext-26m", "twpll-512m",
+ "twpll-768m", "ltepll0",
+ "twpll", "mpll0" };
+static SPRD_COMP_CLK_TABLE(lit_mcu, "lit-mcu", lit_mcu_parents, 0x20,
+ mcu_table, 0, 4, 4, 3, 0);
+
+static const char * const big_mcu_parents[] = { "ext-26m", "twpll-512m",
+ "twpll-768m", "ltepll0",
+ "twpll", "mpll1" };
+static SPRD_COMP_CLK_TABLE(big_mcu, "big-mcu", big_mcu_parents, 0x24,
+ mcu_table, 0, 4, 4, 3, 0);
+
+static struct sprd_clk_common *sc9860_aonsecure_clk[] = {
+ /* address base is 0x40880000 */
+ &lit_mcu.common,
+ &big_mcu.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aonsecure_clk_hws = {
+ .hws = {
+ [CLK_LIT_MCU] = &lit_mcu.common.hw,
+ [CLK_BIG_MCU] = &big_mcu.common.hw,
+ },
+ .num = CLK_AONSECURE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aonsecure_clk_desc = {
+ .clk_clks = sc9860_aonsecure_clk,
+ .num_clk_clks = ARRAY_SIZE(sc9860_aonsecure_clk),
+ .hw_clks = &sc9860_aonsecure_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(agcp_iis0_eb, "agcp-iis0-eb", "aon-apb",
+ 0x0, 0x100, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis1_eb, "agcp-iis1-eb", "aon-apb",
+ 0x0, 0x100, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis2_eb, "agcp-iis2-eb", "aon-apb",
+ 0x0, 0x100, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis3_eb, "agcp-iis3-eb", "aon-apb",
+ 0x0, 0x100, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_uart_eb, "agcp-uart-eb", "aon-apb",
+ 0x0, 0x100, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_dmacp_eb, "agcp-dmacp-eb", "aon-apb",
+ 0x0, 0x100, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_dmaap_eb, "agcp-dmaap-eb", "aon-apb",
+ 0x0, 0x100, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_arc48k_eb, "agcp-arc48k-eb", "aon-apb",
+ 0x0, 0x100, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_src44p1k_eb, "agcp-src44p1k-eb", "aon-apb",
+ 0x0, 0x100, BIT(11), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_mcdt_eb, "agcp-mcdt-eb", "aon-apb",
+ 0x0, 0x100, BIT(12), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_vbcifd_eb, "agcp-vbcifd-eb", "aon-apb",
+ 0x0, 0x100, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_vbc_eb, "agcp-vbc-eb", "aon-apb",
+ 0x0, 0x100, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_spinlock_eb, "agcp-spinlock-eb", "aon-apb",
+ 0x0, 0x100, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_icu_eb, "agcp-icu-eb", "aon-apb",
+ 0x0, 0x100, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(agcp_ap_ashb_eb, "agcp-ap-ashb-eb", "aon-apb",
+ 0x0, 0x100, BIT(17), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_cp_ashb_eb, "agcp-cp-ashb-eb", "aon-apb",
+ 0x0, 0x100, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_aud_eb, "agcp-aud-eb", "aon-apb",
+ 0x0, 0x100, BIT(19), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_audif_eb, "agcp-audif-eb", "aon-apb",
+ 0x0, 0x100, BIT(20), 0, 0);
+
+static struct sprd_clk_common *sc9860_agcp_gate[] = {
+ /* address base is 0x415e0000 */
+ &agcp_iis0_eb.common,
+ &agcp_iis1_eb.common,
+ &agcp_iis2_eb.common,
+ &agcp_iis3_eb.common,
+ &agcp_uart_eb.common,
+ &agcp_dmacp_eb.common,
+ &agcp_dmaap_eb.common,
+ &agcp_arc48k_eb.common,
+ &agcp_src44p1k_eb.common,
+ &agcp_mcdt_eb.common,
+ &agcp_vbcifd_eb.common,
+ &agcp_vbc_eb.common,
+ &agcp_spinlock_eb.common,
+ &agcp_icu_eb.common,
+ &agcp_ap_ashb_eb.common,
+ &agcp_cp_ashb_eb.common,
+ &agcp_aud_eb.common,
+ &agcp_audif_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_agcp_gate_hws = {
+ .hws = {
+ [CLK_AGCP_IIS0_EB] = &agcp_iis0_eb.common.hw,
+ [CLK_AGCP_IIS1_EB] = &agcp_iis1_eb.common.hw,
+ [CLK_AGCP_IIS2_EB] = &agcp_iis2_eb.common.hw,
+ [CLK_AGCP_IIS3_EB] = &agcp_iis3_eb.common.hw,
+ [CLK_AGCP_UART_EB] = &agcp_uart_eb.common.hw,
+ [CLK_AGCP_DMACP_EB] = &agcp_dmacp_eb.common.hw,
+ [CLK_AGCP_DMAAP_EB] = &agcp_dmaap_eb.common.hw,
+ [CLK_AGCP_ARC48K_EB] = &agcp_arc48k_eb.common.hw,
+ [CLK_AGCP_SRC44P1K_EB] = &agcp_src44p1k_eb.common.hw,
+ [CLK_AGCP_MCDT_EB] = &agcp_mcdt_eb.common.hw,
+ [CLK_AGCP_VBCIFD_EB] = &agcp_vbcifd_eb.common.hw,
+ [CLK_AGCP_VBC_EB] = &agcp_vbc_eb.common.hw,
+ [CLK_AGCP_SPINLOCK_EB] = &agcp_spinlock_eb.common.hw,
+ [CLK_AGCP_ICU_EB] = &agcp_icu_eb.common.hw,
+ [CLK_AGCP_AP_ASHB_EB] = &agcp_ap_ashb_eb.common.hw,
+ [CLK_AGCP_CP_ASHB_EB] = &agcp_cp_ashb_eb.common.hw,
+ [CLK_AGCP_AUD_EB] = &agcp_aud_eb.common.hw,
+ [CLK_AGCP_AUDIF_EB] = &agcp_audif_eb.common.hw,
+ },
+ .num = CLK_AGCP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_agcp_gate_desc = {
+ .clk_clks = sc9860_agcp_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_agcp_gate),
+ .hw_clks = &sc9860_agcp_gate_hws,
+};
+
+static const char * const gpu_parents[] = { "twpll-512m",
+ "twpll-768m",
+ "gpll" };
+static SPRD_COMP_CLK(gpu_clk, "gpu", gpu_parents, 0x20,
+ 0, 2, 8, 4, 0);
+
+static struct sprd_clk_common *sc9860_gpu_clk[] = {
+ /* address base is 0x60200000 */
+ &gpu_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_gpu_clk_hws = {
+ .hws = {
+ [CLK_GPU] = &gpu_clk.common.hw,
+ },
+ .num = CLK_GPU_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_gpu_clk_desc = {
+ .clk_clks = sc9860_gpu_clk,
+ .num_clk_clks = ARRAY_SIZE(sc9860_gpu_clk),
+ .hw_clks = &sc9860_gpu_clk_hws,
+};
+
+static const char * const ahb_parents[] = { "ext-26m", "twpll-96m",
+ "twpll-128m", "twpll-153m6" };
+static SPRD_MUX_CLK(ahb_vsp, "ahb-vsp", ahb_parents, 0x20,
+ 0, 2, SC9860_MUX_FLAG);
+
+static const char * const vsp_parents[] = { "twpll-76m8", "twpll-128m",
+ "twpll-256m", "twpll-307m2",
+ "twpll-384m" };
+static SPRD_COMP_CLK(vsp_clk, "vsp", vsp_parents, 0x24, 0, 3, 8, 2, 0);
+
+static const char * const dispc_parents[] = { "twpll-76m8", "twpll-128m",
+ "twpll-256m", "twpll-307m2" };
+static SPRD_COMP_CLK(vsp_enc, "vsp-enc", dispc_parents, 0x28, 0, 2, 8, 2, 0);
+
+static const char * const vpp_parents[] = { "twpll-96m", "twpll-153m6",
+ "twpll-192m", "twpll-256m" };
+static SPRD_MUX_CLK(vpp_clk, "vpp", vpp_parents, 0x2c,
+ 0, 2, SC9860_MUX_FLAG);
+static const char * const vsp_26m_parents[] = { "ext-26m" };
+static SPRD_MUX_CLK(vsp_26m, "vsp-26m", vsp_26m_parents, 0x30,
+ 0, 1, SC9860_MUX_FLAG);
+
+static struct sprd_clk_common *sc9860_vsp_clk[] = {
+ /* address base is 0x61000000 */
+ &ahb_vsp.common,
+ &vsp_clk.common,
+ &vsp_enc.common,
+ &vpp_clk.common,
+ &vsp_26m.common,
+};
+
+static struct clk_hw_onecell_data sc9860_vsp_clk_hws = {
+ .hws = {
+ [CLK_AHB_VSP] = &ahb_vsp.common.hw,
+ [CLK_VSP] = &vsp_clk.common.hw,
+ [CLK_VSP_ENC] = &vsp_enc.common.hw,
+ [CLK_VPP] = &vpp_clk.common.hw,
+ [CLK_VSP_26M] = &vsp_26m.common.hw,
+ },
+ .num = CLK_VSP_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_vsp_clk_desc = {
+ .clk_clks = sc9860_vsp_clk,
+ .num_clk_clks = ARRAY_SIZE(sc9860_vsp_clk),
+ .hw_clks = &sc9860_vsp_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(vsp_dec_eb, "vsp-dec-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_ckg_eb, "vsp-ckg-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_mmu_eb, "vsp-mmu-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_enc_eb, "vsp-enc-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(vpp_eb, "vpp-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_26m_eb, "vsp-26m-eb", "ahb-vsp", 0x0,
+ 0x1000, BIT(5), 0, 0);
+static SPRD_GATE_CLK(vsp_axi_gate, "vsp-axi-gate", "ahb-vsp", 0x8,
+ BIT(0), 0, 0);
+static SPRD_GATE_CLK(vsp_enc_gate, "vsp-enc-gate", "ahb-vsp", 0x8,
+ BIT(1), 0, 0);
+static SPRD_GATE_CLK(vpp_axi_gate, "vpp-axi-gate", "ahb-vsp", 0x8,
+ BIT(2), 0, 0);
+static SPRD_GATE_CLK(vsp_bm_gate, "vsp-bm-gate", "ahb-vsp", 0x8,
+ BIT(8), 0, 0);
+static SPRD_GATE_CLK(vsp_enc_bm_gate, "vsp-enc-bm-gate", "ahb-vsp", 0x8,
+ BIT(9), 0, 0);
+static SPRD_GATE_CLK(vpp_bm_gate, "vpp-bm-gate", "ahb-vsp", 0x8,
+ BIT(10), 0, 0);
+
+static struct sprd_clk_common *sc9860_vsp_gate[] = {
+ /* address base is 0x61100000 */
+ &vsp_dec_eb.common,
+ &vsp_ckg_eb.common,
+ &vsp_mmu_eb.common,
+ &vsp_enc_eb.common,
+ &vpp_eb.common,
+ &vsp_26m_eb.common,
+ &vsp_axi_gate.common,
+ &vsp_enc_gate.common,
+ &vpp_axi_gate.common,
+ &vsp_bm_gate.common,
+ &vsp_enc_bm_gate.common,
+ &vpp_bm_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_vsp_gate_hws = {
+ .hws = {
+ [CLK_VSP_DEC_EB] = &vsp_dec_eb.common.hw,
+ [CLK_VSP_CKG_EB] = &vsp_ckg_eb.common.hw,
+ [CLK_VSP_MMU_EB] = &vsp_mmu_eb.common.hw,
+ [CLK_VSP_ENC_EB] = &vsp_enc_eb.common.hw,
+ [CLK_VPP_EB] = &vpp_eb.common.hw,
+ [CLK_VSP_26M_EB] = &vsp_26m_eb.common.hw,
+ [CLK_VSP_AXI_GATE] = &vsp_axi_gate.common.hw,
+ [CLK_VSP_ENC_GATE] = &vsp_enc_gate.common.hw,
+ [CLK_VPP_AXI_GATE] = &vpp_axi_gate.common.hw,
+ [CLK_VSP_BM_GATE] = &vsp_bm_gate.common.hw,
+ [CLK_VSP_ENC_BM_GATE] = &vsp_enc_bm_gate.common.hw,
+ [CLK_VPP_BM_GATE] = &vpp_bm_gate.common.hw,
+ },
+ .num = CLK_VSP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_vsp_gate_desc = {
+ .clk_clks = sc9860_vsp_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_vsp_gate),
+ .hw_clks = &sc9860_vsp_gate_hws,
+};
+
+static SPRD_MUX_CLK(ahb_cam, "ahb-cam", ahb_parents, 0x20,
+ 0, 2, SC9860_MUX_FLAG);
+static const char * const sensor_parents[] = { "ext-26m", "twpll-48m",
+ "twpll-76m8", "twpll-96m" };
+static SPRD_COMP_CLK(sensor0_clk, "sensor0", sensor_parents, 0x24,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(sensor1_clk, "sensor1", sensor_parents, 0x28,
+ 0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(sensor2_clk, "sensor2", sensor_parents, 0x2c,
+ 0, 2, 8, 3, 0);
+static SPRD_GATE_CLK(mipi_csi0_eb, "mipi-csi0-eb", "ahb-cam", 0x4c,
+ BIT(16), 0, 0);
+static SPRD_GATE_CLK(mipi_csi1_eb, "mipi-csi1-eb", "ahb-cam", 0x50,
+ BIT(16), 0, 0);
+
+static struct sprd_clk_common *sc9860_cam_clk[] = {
+ /* address base is 0x62000000 */
+ &ahb_cam.common,
+ &sensor0_clk.common,
+ &sensor1_clk.common,
+ &sensor2_clk.common,
+ &mipi_csi0_eb.common,
+ &mipi_csi1_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_cam_clk_hws = {
+ .hws = {
+ [CLK_AHB_CAM] = &ahb_cam.common.hw,
+ [CLK_SENSOR0] = &sensor0_clk.common.hw,
+ [CLK_SENSOR1] = &sensor1_clk.common.hw,
+ [CLK_SENSOR2] = &sensor2_clk.common.hw,
+ [CLK_MIPI_CSI0_EB] = &mipi_csi0_eb.common.hw,
+ [CLK_MIPI_CSI1_EB] = &mipi_csi1_eb.common.hw,
+ },
+ .num = CLK_CAM_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_cam_clk_desc = {
+ .clk_clks = sc9860_cam_clk,
+ .num_clk_clks = ARRAY_SIZE(sc9860_cam_clk),
+ .hw_clks = &sc9860_cam_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(dcam0_eb, "dcam0-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(dcam1_eb, "dcam1-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(isp0_eb, "isp0-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(csi0_eb, "csi0-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(csi1_eb, "csi1-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(jpg0_eb, "jpg0-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(jpg1_eb, "jpg1-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(cam_ckg_eb, "cam-ckg-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(cam_mmu_eb, "cam-mmu-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(isp1_eb, "isp1-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(cpp_eb, "cpp-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(mmu_pf_eb, "mmu-pf-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(11), 0, 0);
+static SPRD_SC_GATE_CLK(isp2_eb, "isp2-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(12), 0, 0);
+static SPRD_SC_GATE_CLK(dcam2isp_if_eb, "dcam2isp-if-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(isp2dcam_if_eb, "isp2dcam-if-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(isp_lclk_eb, "isp-lclk-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(isp_iclk_eb, "isp-iclk-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(16), 0, 0);
+static SPRD_SC_GATE_CLK(isp_mclk_eb, "isp-mclk-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(17), 0, 0);
+static SPRD_SC_GATE_CLK(isp_pclk_eb, "isp-pclk-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(isp_isp2dcam_eb, "isp-isp2dcam-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(19), 0, 0);
+static SPRD_SC_GATE_CLK(dcam0_if_eb, "dcam0-if-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(20), 0, 0);
+static SPRD_SC_GATE_CLK(clk26m_if_eb, "clk26m-if-eb", "ahb-cam", 0x0,
+ 0x1000, BIT(21), 0, 0);
+static SPRD_GATE_CLK(cphy0_gate, "cphy0-gate", "ahb-cam", 0x8,
+ BIT(0), 0, 0);
+static SPRD_GATE_CLK(mipi_csi0_gate, "mipi-csi0-gate", "ahb-cam", 0x8,
+ BIT(1), 0, 0);
+static SPRD_GATE_CLK(cphy1_gate, "cphy1-gate", "ahb-cam", 0x8,
+ BIT(2), 0, 0);
+static SPRD_GATE_CLK(mipi_csi1, "mipi-csi1", "ahb-cam", 0x8,
+ BIT(3), 0, 0);
+static SPRD_GATE_CLK(dcam0_axi_gate, "dcam0-axi-gate", "ahb-cam", 0x8,
+ BIT(4), 0, 0);
+static SPRD_GATE_CLK(dcam1_axi_gate, "dcam1-axi-gate", "ahb-cam", 0x8,
+ BIT(5), 0, 0);
+static SPRD_GATE_CLK(sensor0_gate, "sensor0-gate", "ahb-cam", 0x8,
+ BIT(6), 0, 0);
+static SPRD_GATE_CLK(sensor1_gate, "sensor1-gate", "ahb-cam", 0x8,
+ BIT(7), 0, 0);
+static SPRD_GATE_CLK(jpg0_axi_gate, "jpg0-axi-gate", "ahb-cam", 0x8,
+ BIT(8), 0, 0);
+static SPRD_GATE_CLK(gpg1_axi_gate, "gpg1-axi-gate", "ahb-cam", 0x8,
+ BIT(9), 0, 0);
+static SPRD_GATE_CLK(isp0_axi_gate, "isp0-axi-gate", "ahb-cam", 0x8,
+ BIT(10), 0, 0);
+static SPRD_GATE_CLK(isp1_axi_gate, "isp1-axi-gate", "ahb-cam", 0x8,
+ BIT(11), 0, 0);
+static SPRD_GATE_CLK(isp2_axi_gate, "isp2-axi-gate", "ahb-cam", 0x8,
+ BIT(12), 0, 0);
+static SPRD_GATE_CLK(cpp_axi_gate, "cpp-axi-gate", "ahb-cam", 0x8,
+ BIT(13), 0, 0);
+static SPRD_GATE_CLK(d0_if_axi_gate, "d0-if-axi-gate", "ahb-cam", 0x8,
+ BIT(14), 0, 0);
+static SPRD_GATE_CLK(d2i_if_axi_gate, "d2i-if-axi-gate", "ahb-cam", 0x8,
+ BIT(15), 0, 0);
+static SPRD_GATE_CLK(i2d_if_axi_gate, "i2d-if-axi-gate", "ahb-cam", 0x8,
+ BIT(16), 0, 0);
+static SPRD_GATE_CLK(spare_axi_gate, "spare-axi-gate", "ahb-cam", 0x8,
+ BIT(17), 0, 0);
+static SPRD_GATE_CLK(sensor2_gate, "sensor2-gate", "ahb-cam", 0x8,
+ BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(d0if_in_d_en, "d0if-in-d-en", "ahb-cam", 0x28,
+ 0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(d1if_in_d_en, "d1if-in-d-en", "ahb-cam", 0x28,
+ 0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(d0if_in_d2i_en, "d0if-in-d2i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(d1if_in_d2i_en, "d1if-in-d2i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(ia_in_d2i_en, "ia-in-d2i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(ib_in_d2i_en, "ib-in-d2i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(ic_in_d2i_en, "ic-in-d2i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(ia_in_i_en, "ia-in-i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(ib_in_i_en, "ib-in-i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(ic_in_i_en, "ic-in-i-en", "ahb-cam", 0x28,
+ 0x1000, BIT(9), 0, 0);
+
+static struct sprd_clk_common *sc9860_cam_gate[] = {
+ /* address base is 0x62100000 */
+ &dcam0_eb.common,
+ &dcam1_eb.common,
+ &isp0_eb.common,
+ &csi0_eb.common,
+ &csi1_eb.common,
+ &jpg0_eb.common,
+ &jpg1_eb.common,
+ &cam_ckg_eb.common,
+ &cam_mmu_eb.common,
+ &isp1_eb.common,
+ &cpp_eb.common,
+ &mmu_pf_eb.common,
+ &isp2_eb.common,
+ &dcam2isp_if_eb.common,
+ &isp2dcam_if_eb.common,
+ &isp_lclk_eb.common,
+ &isp_iclk_eb.common,
+ &isp_mclk_eb.common,
+ &isp_pclk_eb.common,
+ &isp_isp2dcam_eb.common,
+ &dcam0_if_eb.common,
+ &clk26m_if_eb.common,
+ &cphy0_gate.common,
+ &mipi_csi0_gate.common,
+ &cphy1_gate.common,
+ &mipi_csi1.common,
+ &dcam0_axi_gate.common,
+ &dcam1_axi_gate.common,
+ &sensor0_gate.common,
+ &sensor1_gate.common,
+ &jpg0_axi_gate.common,
+ &gpg1_axi_gate.common,
+ &isp0_axi_gate.common,
+ &isp1_axi_gate.common,
+ &isp2_axi_gate.common,
+ &cpp_axi_gate.common,
+ &d0_if_axi_gate.common,
+ &d2i_if_axi_gate.common,
+ &i2d_if_axi_gate.common,
+ &spare_axi_gate.common,
+ &sensor2_gate.common,
+ &d0if_in_d_en.common,
+ &d1if_in_d_en.common,
+ &d0if_in_d2i_en.common,
+ &d1if_in_d2i_en.common,
+ &ia_in_d2i_en.common,
+ &ib_in_d2i_en.common,
+ &ic_in_d2i_en.common,
+ &ia_in_i_en.common,
+ &ib_in_i_en.common,
+ &ic_in_i_en.common,
+};
+
+static struct clk_hw_onecell_data sc9860_cam_gate_hws = {
+ .hws = {
+ [CLK_DCAM0_EB] = &dcam0_eb.common.hw,
+ [CLK_DCAM1_EB] = &dcam1_eb.common.hw,
+ [CLK_ISP0_EB] = &isp0_eb.common.hw,
+ [CLK_CSI0_EB] = &csi0_eb.common.hw,
+ [CLK_CSI1_EB] = &csi1_eb.common.hw,
+ [CLK_JPG0_EB] = &jpg0_eb.common.hw,
+ [CLK_JPG1_EB] = &jpg1_eb.common.hw,
+ [CLK_CAM_CKG_EB] = &cam_ckg_eb.common.hw,
+ [CLK_CAM_MMU_EB] = &cam_mmu_eb.common.hw,
+ [CLK_ISP1_EB] = &isp1_eb.common.hw,
+ [CLK_CPP_EB] = &cpp_eb.common.hw,
+ [CLK_MMU_PF_EB] = &mmu_pf_eb.common.hw,
+ [CLK_ISP2_EB] = &isp2_eb.common.hw,
+ [CLK_DCAM2ISP_IF_EB] = &dcam2isp_if_eb.common.hw,
+ [CLK_ISP2DCAM_IF_EB] = &isp2dcam_if_eb.common.hw,
+ [CLK_ISP_LCLK_EB] = &isp_lclk_eb.common.hw,
+ [CLK_ISP_ICLK_EB] = &isp_iclk_eb.common.hw,
+ [CLK_ISP_MCLK_EB] = &isp_mclk_eb.common.hw,
+ [CLK_ISP_PCLK_EB] = &isp_pclk_eb.common.hw,
+ [CLK_ISP_ISP2DCAM_EB] = &isp_isp2dcam_eb.common.hw,
+ [CLK_DCAM0_IF_EB] = &dcam0_if_eb.common.hw,
+ [CLK_CLK26M_IF_EB] = &clk26m_if_eb.common.hw,
+ [CLK_CPHY0_GATE] = &cphy0_gate.common.hw,
+ [CLK_MIPI_CSI0_GATE] = &mipi_csi0_gate.common.hw,
+ [CLK_CPHY1_GATE] = &cphy1_gate.common.hw,
+ [CLK_MIPI_CSI1] = &mipi_csi1.common.hw,
+ [CLK_DCAM0_AXI_GATE] = &dcam0_axi_gate.common.hw,
+ [CLK_DCAM1_AXI_GATE] = &dcam1_axi_gate.common.hw,
+ [CLK_SENSOR0_GATE] = &sensor0_gate.common.hw,
+ [CLK_SENSOR1_GATE] = &sensor1_gate.common.hw,
+ [CLK_JPG0_AXI_GATE] = &jpg0_axi_gate.common.hw,
+ [CLK_GPG1_AXI_GATE] = &gpg1_axi_gate.common.hw,
+ [CLK_ISP0_AXI_GATE] = &isp0_axi_gate.common.hw,
+ [CLK_ISP1_AXI_GATE] = &isp1_axi_gate.common.hw,
+ [CLK_ISP2_AXI_GATE] = &isp2_axi_gate.common.hw,
+ [CLK_CPP_AXI_GATE] = &cpp_axi_gate.common.hw,
+ [CLK_D0_IF_AXI_GATE] = &d0_if_axi_gate.common.hw,
+ [CLK_D2I_IF_AXI_GATE] = &d2i_if_axi_gate.common.hw,
+ [CLK_I2D_IF_AXI_GATE] = &i2d_if_axi_gate.common.hw,
+ [CLK_SPARE_AXI_GATE] = &spare_axi_gate.common.hw,
+ [CLK_SENSOR2_GATE] = &sensor2_gate.common.hw,
+ [CLK_D0IF_IN_D_EN] = &d0if_in_d_en.common.hw,
+ [CLK_D1IF_IN_D_EN] = &d1if_in_d_en.common.hw,
+ [CLK_D0IF_IN_D2I_EN] = &d0if_in_d2i_en.common.hw,
+ [CLK_D1IF_IN_D2I_EN] = &d1if_in_d2i_en.common.hw,
+ [CLK_IA_IN_D2I_EN] = &ia_in_d2i_en.common.hw,
+ [CLK_IB_IN_D2I_EN] = &ib_in_d2i_en.common.hw,
+ [CLK_IC_IN_D2I_EN] = &ic_in_d2i_en.common.hw,
+ [CLK_IA_IN_I_EN] = &ia_in_i_en.common.hw,
+ [CLK_IB_IN_I_EN] = &ib_in_i_en.common.hw,
+ [CLK_IC_IN_I_EN] = &ic_in_i_en.common.hw,
+ },
+ .num = CLK_CAM_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_cam_gate_desc = {
+ .clk_clks = sc9860_cam_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_cam_gate),
+ .hw_clks = &sc9860_cam_gate_hws,
+};
+
+static SPRD_MUX_CLK(ahb_disp, "ahb-disp", ahb_parents, 0x20,
+ 0, 2, SC9860_MUX_FLAG);
+static SPRD_COMP_CLK(dispc0_dpi, "dispc0-dpi", dispc_parents, 0x34,
+ 0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(dispc1_dpi, "dispc1-dpi", dispc_parents, 0x40,
+ 0, 2, 8, 2, 0);
+
+static struct sprd_clk_common *sc9860_disp_clk[] = {
+ /* address base is 0x63000000 */
+ &ahb_disp.common,
+ &dispc0_dpi.common,
+ &dispc1_dpi.common,
+};
+
+static struct clk_hw_onecell_data sc9860_disp_clk_hws = {
+ .hws = {
+ [CLK_AHB_DISP] = &ahb_disp.common.hw,
+ [CLK_DISPC0_DPI] = &dispc0_dpi.common.hw,
+ [CLK_DISPC1_DPI] = &dispc1_dpi.common.hw,
+ },
+ .num = CLK_DISP_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_disp_clk_desc = {
+ .clk_clks = sc9860_disp_clk,
+ .num_clk_clks = ARRAY_SIZE(sc9860_disp_clk),
+ .hw_clks = &sc9860_disp_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(dispc0_eb, "dispc0-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(dispc1_eb, "dispc1-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(dispc_mmu_eb, "dispc-mmu-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(gsp0_eb, "gsp0-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(gsp1_eb, "gsp1-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(gsp0_mmu_eb, "gsp0-mmu-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(gsp1_mmu_eb, "gsp1-mmu-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(dsi0_eb, "dsi0-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(dsi1_eb, "dsi1-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(disp_ckg_eb, "disp-ckg-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(disp_gpu_eb, "disp-gpu-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(gpu_mtx_eb, "gpu-mtx-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(gsp_mtx_eb, "gsp-mtx-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(tmc_mtx_eb, "tmc-mtx-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(dispc_mtx_eb, "dispc-mtx-eb", "ahb-disp", 0x0,
+ 0x1000, BIT(16), 0, 0);
+static SPRD_GATE_CLK(dphy0_gate, "dphy0-gate", "ahb-disp", 0x8,
+ BIT(0), 0, 0);
+static SPRD_GATE_CLK(dphy1_gate, "dphy1-gate", "ahb-disp", 0x8,
+ BIT(1), 0, 0);
+static SPRD_GATE_CLK(gsp0_a_gate, "gsp0-a-gate", "ahb-disp", 0x8,
+ BIT(2), 0, 0);
+static SPRD_GATE_CLK(gsp1_a_gate, "gsp1-a-gate", "ahb-disp", 0x8,
+ BIT(3), 0, 0);
+static SPRD_GATE_CLK(gsp0_f_gate, "gsp0-f-gate", "ahb-disp", 0x8,
+ BIT(4), 0, 0);
+static SPRD_GATE_CLK(gsp1_f_gate, "gsp1-f-gate", "ahb-disp", 0x8,
+ BIT(5), 0, 0);
+static SPRD_GATE_CLK(d_mtx_f_gate, "d-mtx-f-gate", "ahb-disp", 0x8,
+ BIT(6), 0, 0);
+static SPRD_GATE_CLK(d_mtx_a_gate, "d-mtx-a-gate", "ahb-disp", 0x8,
+ BIT(7), 0, 0);
+static SPRD_GATE_CLK(d_noc_f_gate, "d-noc-f-gate", "ahb-disp", 0x8,
+ BIT(8), 0, 0);
+static SPRD_GATE_CLK(d_noc_a_gate, "d-noc-a-gate", "ahb-disp", 0x8,
+ BIT(9), 0, 0);
+static SPRD_GATE_CLK(gsp_mtx_f_gate, "gsp-mtx-f-gate", "ahb-disp", 0x8,
+ BIT(10), 0, 0);
+static SPRD_GATE_CLK(gsp_mtx_a_gate, "gsp-mtx-a-gate", "ahb-disp", 0x8,
+ BIT(11), 0, 0);
+static SPRD_GATE_CLK(gsp_noc_f_gate, "gsp-noc-f-gate", "ahb-disp", 0x8,
+ BIT(12), 0, 0);
+static SPRD_GATE_CLK(gsp_noc_a_gate, "gsp-noc-a-gate", "ahb-disp", 0x8,
+ BIT(13), 0, 0);
+static SPRD_GATE_CLK(dispm0idle_gate, "dispm0idle-gate", "ahb-disp", 0x8,
+ BIT(14), 0, 0);
+static SPRD_GATE_CLK(gspm0idle_gate, "gspm0idle-gate", "ahb-disp", 0x8,
+ BIT(15), 0, 0);
+
+static struct sprd_clk_common *sc9860_disp_gate[] = {
+ /* address base is 0x63100000 */
+ &dispc0_eb.common,
+ &dispc1_eb.common,
+ &dispc_mmu_eb.common,
+ &gsp0_eb.common,
+ &gsp1_eb.common,
+ &gsp0_mmu_eb.common,
+ &gsp1_mmu_eb.common,
+ &dsi0_eb.common,
+ &dsi1_eb.common,
+ &disp_ckg_eb.common,
+ &disp_gpu_eb.common,
+ &gpu_mtx_eb.common,
+ &gsp_mtx_eb.common,
+ &tmc_mtx_eb.common,
+ &dispc_mtx_eb.common,
+ &dphy0_gate.common,
+ &dphy1_gate.common,
+ &gsp0_a_gate.common,
+ &gsp1_a_gate.common,
+ &gsp0_f_gate.common,
+ &gsp1_f_gate.common,
+ &d_mtx_f_gate.common,
+ &d_mtx_a_gate.common,
+ &d_noc_f_gate.common,
+ &d_noc_a_gate.common,
+ &gsp_mtx_f_gate.common,
+ &gsp_mtx_a_gate.common,
+ &gsp_noc_f_gate.common,
+ &gsp_noc_a_gate.common,
+ &dispm0idle_gate.common,
+ &gspm0idle_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_disp_gate_hws = {
+ .hws = {
+ [CLK_DISPC0_EB] = &dispc0_eb.common.hw,
+ [CLK_DISPC1_EB] = &dispc1_eb.common.hw,
+ [CLK_DISPC_MMU_EB] = &dispc_mmu_eb.common.hw,
+ [CLK_GSP0_EB] = &gsp0_eb.common.hw,
+ [CLK_GSP1_EB] = &gsp1_eb.common.hw,
+ [CLK_GSP0_MMU_EB] = &gsp0_mmu_eb.common.hw,
+ [CLK_GSP1_MMU_EB] = &gsp1_mmu_eb.common.hw,
+ [CLK_DSI0_EB] = &dsi0_eb.common.hw,
+ [CLK_DSI1_EB] = &dsi1_eb.common.hw,
+ [CLK_DISP_CKG_EB] = &disp_ckg_eb.common.hw,
+ [CLK_DISP_GPU_EB] = &disp_gpu_eb.common.hw,
+ [CLK_GPU_MTX_EB] = &gpu_mtx_eb.common.hw,
+ [CLK_GSP_MTX_EB] = &gsp_mtx_eb.common.hw,
+ [CLK_TMC_MTX_EB] = &tmc_mtx_eb.common.hw,
+ [CLK_DISPC_MTX_EB] = &dispc_mtx_eb.common.hw,
+ [CLK_DPHY0_GATE] = &dphy0_gate.common.hw,
+ [CLK_DPHY1_GATE] = &dphy1_gate.common.hw,
+ [CLK_GSP0_A_GATE] = &gsp0_a_gate.common.hw,
+ [CLK_GSP1_A_GATE] = &gsp1_a_gate.common.hw,
+ [CLK_GSP0_F_GATE] = &gsp0_f_gate.common.hw,
+ [CLK_GSP1_F_GATE] = &gsp1_f_gate.common.hw,
+ [CLK_D_MTX_F_GATE] = &d_mtx_f_gate.common.hw,
+ [CLK_D_MTX_A_GATE] = &d_mtx_a_gate.common.hw,
+ [CLK_D_NOC_F_GATE] = &d_noc_f_gate.common.hw,
+ [CLK_D_NOC_A_GATE] = &d_noc_a_gate.common.hw,
+ [CLK_GSP_MTX_F_GATE] = &gsp_mtx_f_gate.common.hw,
+ [CLK_GSP_MTX_A_GATE] = &gsp_mtx_a_gate.common.hw,
+ [CLK_GSP_NOC_F_GATE] = &gsp_noc_f_gate.common.hw,
+ [CLK_GSP_NOC_A_GATE] = &gsp_noc_a_gate.common.hw,
+ [CLK_DISPM0IDLE_GATE] = &dispm0idle_gate.common.hw,
+ [CLK_GSPM0IDLE_GATE] = &gspm0idle_gate.common.hw,
+ },
+ .num = CLK_DISP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_disp_gate_desc = {
+ .clk_clks = sc9860_disp_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_disp_gate),
+ .hw_clks = &sc9860_disp_gate_hws,
+};
+
+static SPRD_SC_GATE_CLK(sim0_eb, "sim0-eb", "ap-apb", 0x0,
+ 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis0_eb, "iis0-eb", "ap-apb", 0x0,
+ 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis1_eb, "iis1-eb", "ap-apb", 0x0,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis2_eb, "iis2-eb", "ap-apb", 0x0,
+ 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis3_eb, "iis3-eb", "ap-apb", 0x0,
+ 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi0_eb, "spi0-eb", "ap-apb", 0x0,
+ 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi1_eb, "spi1-eb", "ap-apb", 0x0,
+ 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi2_eb, "spi2-eb", "ap-apb", 0x0,
+ 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c0_eb, "i2c0-eb", "ap-apb", 0x0,
+ 0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c1_eb, "i2c1-eb", "ap-apb", 0x0,
+ 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c2_eb, "i2c2-eb", "ap-apb", 0x0,
+ 0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c3_eb, "i2c3-eb", "ap-apb", 0x0,
+ 0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c4_eb, "i2c4-eb", "ap-apb", 0x0,
+ 0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c5_eb, "i2c5-eb", "ap-apb", 0x0,
+ 0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart0_eb, "uart0-eb", "ap-apb", 0x0,
+ 0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart1_eb, "uart1-eb", "ap-apb", 0x0,
+ 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart2_eb, "uart2-eb", "ap-apb", 0x0,
+ 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart3_eb, "uart3-eb", "ap-apb", 0x0,
+ 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart4_eb, "uart4-eb", "ap-apb", 0x0,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_ckg_eb, "ap-ckg-eb", "ap-apb", 0x0,
+ 0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi3_eb, "spi3-eb", "ap-apb", 0x0,
+ 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+
+static struct sprd_clk_common *sc9860_apapb_gate[] = {
+ /* address base is 0x70b00000 */
+ &sim0_eb.common,
+ &iis0_eb.common,
+ &iis1_eb.common,
+ &iis2_eb.common,
+ &iis3_eb.common,
+ &spi0_eb.common,
+ &spi1_eb.common,
+ &spi2_eb.common,
+ &i2c0_eb.common,
+ &i2c1_eb.common,
+ &i2c2_eb.common,
+ &i2c3_eb.common,
+ &i2c4_eb.common,
+ &i2c5_eb.common,
+ &uart0_eb.common,
+ &uart1_eb.common,
+ &uart2_eb.common,
+ &uart3_eb.common,
+ &uart4_eb.common,
+ &ap_ckg_eb.common,
+ &spi3_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_apapb_gate_hws = {
+ .hws = {
+ [CLK_SIM0_EB] = &sim0_eb.common.hw,
+ [CLK_IIS0_EB] = &iis0_eb.common.hw,
+ [CLK_IIS1_EB] = &iis1_eb.common.hw,
+ [CLK_IIS2_EB] = &iis2_eb.common.hw,
+ [CLK_IIS3_EB] = &iis3_eb.common.hw,
+ [CLK_SPI0_EB] = &spi0_eb.common.hw,
+ [CLK_SPI1_EB] = &spi1_eb.common.hw,
+ [CLK_SPI2_EB] = &spi2_eb.common.hw,
+ [CLK_I2C0_EB] = &i2c0_eb.common.hw,
+ [CLK_I2C1_EB] = &i2c1_eb.common.hw,
+ [CLK_I2C2_EB] = &i2c2_eb.common.hw,
+ [CLK_I2C3_EB] = &i2c3_eb.common.hw,
+ [CLK_I2C4_EB] = &i2c4_eb.common.hw,
+ [CLK_I2C5_EB] = &i2c5_eb.common.hw,
+ [CLK_UART0_EB] = &uart0_eb.common.hw,
+ [CLK_UART1_EB] = &uart1_eb.common.hw,
+ [CLK_UART2_EB] = &uart2_eb.common.hw,
+ [CLK_UART3_EB] = &uart3_eb.common.hw,
+ [CLK_UART4_EB] = &uart4_eb.common.hw,
+ [CLK_AP_CKG_EB] = &ap_ckg_eb.common.hw,
+ [CLK_SPI3_EB] = &spi3_eb.common.hw,
+ },
+ .num = CLK_APAPB_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_apapb_gate_desc = {
+ .clk_clks = sc9860_apapb_gate,
+ .num_clk_clks = ARRAY_SIZE(sc9860_apapb_gate),
+ .hw_clks = &sc9860_apapb_gate_hws,
+};
+
+static const struct of_device_id sprd_sc9860_clk_ids[] = {
+ { .compatible = "sprd,sc9860-pmu-gate", /* 0x402b */
+ .data = &sc9860_pmu_gate_desc },
+ { .compatible = "sprd,sc9860-pll", /* 0x4040 */
+ .data = &sc9860_pll_desc },
+ { .compatible = "sprd,sc9860-ap-clk", /* 0x2000 */
+ .data = &sc9860_ap_clk_desc },
+ { .compatible = "sprd,sc9860-aon-prediv", /* 0x402d */
+ .data = &sc9860_aon_prediv_desc },
+ { .compatible = "sprd,sc9860-apahb-gate", /* 0x2021 */
+ .data = &sc9860_apahb_gate_desc },
+ { .compatible = "sprd,sc9860-aon-gate", /* 0x402e */
+ .data = &sc9860_aon_gate_desc },
+ { .compatible = "sprd,sc9860-aonsecure-clk", /* 0x4088 */
+ .data = &sc9860_aonsecure_clk_desc },
+ { .compatible = "sprd,sc9860-agcp-gate", /* 0x415e */
+ .data = &sc9860_agcp_gate_desc },
+ { .compatible = "sprd,sc9860-gpu-clk", /* 0x6020 */
+ .data = &sc9860_gpu_clk_desc },
+ { .compatible = "sprd,sc9860-vsp-clk", /* 0x6100 */
+ .data = &sc9860_vsp_clk_desc },
+ { .compatible = "sprd,sc9860-vsp-gate", /* 0x6110 */
+ .data = &sc9860_vsp_gate_desc },
+ { .compatible = "sprd,sc9860-cam-clk", /* 0x6200 */
+ .data = &sc9860_cam_clk_desc },
+ { .compatible = "sprd,sc9860-cam-gate", /* 0x6210 */
+ .data = &sc9860_cam_gate_desc },
+ { .compatible = "sprd,sc9860-disp-clk", /* 0x6300 */
+ .data = &sc9860_disp_clk_desc },
+ { .compatible = "sprd,sc9860-disp-gate", /* 0x6310 */
+ .data = &sc9860_disp_gate_desc },
+ { .compatible = "sprd,sc9860-apapb-gate", /* 0x70b0 */
+ .data = &sc9860_apapb_gate_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids);
+
+static int sc9860_clk_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ const struct sprd_clk_desc *desc;
+
+ match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node);
+ if (!match) {
+ pr_err("%s: of_match_node() failed", __func__);
+ return -ENODEV;
+ }
+
+ desc = match->data;
+ sprd_clk_regmap_init(pdev, desc);
+
+ return sprd_clk_probe(&pdev->dev, desc->hw_clks);
+}
+
+static struct platform_driver sc9860_clk_driver = {
+ .probe = sc9860_clk_probe,
+ .driver = {
+ .name = "sc9860-clk",
+ .of_match_table = sprd_sc9860_clk_ids,
+ },
+};
+module_platform_driver(sc9860_clk_driver);
+
+MODULE_DESCRIPTION("Spreadtrum SC9860 Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sc9860-clk");
--
2.7.4
^ permalink raw reply related
* [PATCH V7 09/12] clk: sprd: Add dt-bindings include file for SC9860
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
This file defines all SC9860 clock indexes, it should be included in the
device tree in which there's device using the clocks.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Acked-by: Rob Herring <robh@kernel.org>
---
include/dt-bindings/clock/sprd,sc9860-clk.h | 404 ++++++++++++++++++++++++++++
1 file changed, 404 insertions(+)
create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h
diff --git a/include/dt-bindings/clock/sprd,sc9860-clk.h b/include/dt-bindings/clock/sprd,sc9860-clk.h
new file mode 100644
index 0000000..4cb202f
--- /dev/null
+++ b/include/dt-bindings/clock/sprd,sc9860-clk.h
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+//
+// Spreadtrum SC9860 platform clocks
+//
+// Copyright (C) 2017, Spreadtrum Communications Inc.
+
+#ifndef _DT_BINDINGS_CLK_SC9860_H_
+#define _DT_BINDINGS_CLK_SC9860_H_
+
+#define CLK_FAC_4M 0
+#define CLK_FAC_2M 1
+#define CLK_FAC_1M 2
+#define CLK_FAC_250K 3
+#define CLK_FAC_RPLL0_26M 4
+#define CLK_FAC_RPLL1_26M 5
+#define CLK_FAC_RCO25M 6
+#define CLK_FAC_RCO4M 7
+#define CLK_FAC_RCO2M 8
+#define CLK_FAC_3K2 9
+#define CLK_FAC_1K 10
+#define CLK_MPLL0_GATE 11
+#define CLK_MPLL1_GATE 12
+#define CLK_DPLL0_GATE 13
+#define CLK_DPLL1_GATE 14
+#define CLK_LTEPLL0_GATE 15
+#define CLK_TWPLL_GATE 16
+#define CLK_LTEPLL1_GATE 17
+#define CLK_RPLL0_GATE 18
+#define CLK_RPLL1_GATE 19
+#define CLK_CPPLL_GATE 20
+#define CLK_GPLL_GATE 21
+#define CLK_PMU_GATE_NUM (CLK_GPLL_GATE + 1)
+
+#define CLK_MPLL0 0
+#define CLK_MPLL1 1
+#define CLK_DPLL0 2
+#define CLK_DPLL1 3
+#define CLK_RPLL0 4
+#define CLK_RPLL1 5
+#define CLK_TWPLL 6
+#define CLK_LTEPLL0 7
+#define CLK_LTEPLL1 8
+#define CLK_GPLL 9
+#define CLK_CPPLL 10
+#define CLK_GPLL_42M5 11
+#define CLK_TWPLL_768M 12
+#define CLK_TWPLL_384M 13
+#define CLK_TWPLL_192M 14
+#define CLK_TWPLL_96M 15
+#define CLK_TWPLL_48M 16
+#define CLK_TWPLL_24M 17
+#define CLK_TWPLL_12M 18
+#define CLK_TWPLL_512M 19
+#define CLK_TWPLL_256M 20
+#define CLK_TWPLL_128M 21
+#define CLK_TWPLL_64M 22
+#define CLK_TWPLL_307M2 23
+#define CLK_TWPLL_153M6 24
+#define CLK_TWPLL_76M8 25
+#define CLK_TWPLL_51M2 26
+#define CLK_TWPLL_38M4 27
+#define CLK_TWPLL_19M2 28
+#define CLK_L0_614M4 29
+#define CLK_L0_409M6 30
+#define CLK_L0_38M 31
+#define CLK_L1_38M 32
+#define CLK_RPLL0_192M 33
+#define CLK_RPLL0_96M 34
+#define CLK_RPLL0_48M 35
+#define CLK_RPLL1_468M 36
+#define CLK_RPLL1_192M 37
+#define CLK_RPLL1_96M 38
+#define CLK_RPLL1_64M 39
+#define CLK_RPLL1_48M 40
+#define CLK_DPLL0_50M 41
+#define CLK_DPLL1_50M 42
+#define CLK_CPPLL_50M 43
+#define CLK_M0_39M 44
+#define CLK_M1_63M 45
+#define CLK_PLL_NUM (CLK_M1_63M + 1)
+
+
+#define CLK_AP_APB 0
+#define CLK_AP_USB3 1
+#define CLK_UART0 2
+#define CLK_UART1 3
+#define CLK_UART2 4
+#define CLK_UART3 5
+#define CLK_UART4 6
+#define CLK_I2C0 7
+#define CLK_I2C1 8
+#define CLK_I2C2 9
+#define CLK_I2C3 10
+#define CLK_I2C4 11
+#define CLK_I2C5 12
+#define CLK_SPI0 13
+#define CLK_SPI1 14
+#define CLK_SPI2 15
+#define CLK_SPI3 16
+#define CLK_IIS0 17
+#define CLK_IIS1 18
+#define CLK_IIS2 19
+#define CLK_IIS3 20
+#define CLK_AP_CLK_NUM (CLK_IIS3 + 1)
+
+#define CLK_AON_APB 0
+#define CLK_AUX0 1
+#define CLK_AUX1 2
+#define CLK_AUX2 3
+#define CLK_PROBE 4
+#define CLK_SP_AHB 5
+#define CLK_CCI 6
+#define CLK_GIC 7
+#define CLK_CSSYS 8
+#define CLK_SDIO0_2X 9
+#define CLK_SDIO1_2X 10
+#define CLK_SDIO2_2X 11
+#define CLK_EMMC_2X 12
+#define CLK_SDIO0_1X 13
+#define CLK_SDIO1_1X 14
+#define CLK_SDIO2_1X 15
+#define CLK_EMMC_1X 16
+#define CLK_ADI 17
+#define CLK_PWM0 18
+#define CLK_PWM1 19
+#define CLK_PWM2 20
+#define CLK_PWM3 21
+#define CLK_EFUSE 22
+#define CLK_CM3_UART0 23
+#define CLK_CM3_UART1 24
+#define CLK_THM 25
+#define CLK_CM3_I2C0 26
+#define CLK_CM3_I2C1 27
+#define CLK_CM4_SPI 28
+#define CLK_AON_I2C 29
+#define CLK_AVS 30
+#define CLK_CA53_DAP 31
+#define CLK_CA53_TS 32
+#define CLK_DJTAG_TCK 33
+#define CLK_PMU 34
+#define CLK_PMU_26M 35
+#define CLK_DEBOUNCE 36
+#define CLK_OTG2_REF 37
+#define CLK_USB3_REF 38
+#define CLK_AP_AXI 39
+#define CLK_AON_PREDIV_NUM (CLK_AP_AXI + 1)
+
+#define CLK_USB3_EB 0
+#define CLK_USB3_SUSPEND_EB 1
+#define CLK_USB3_REF_EB 2
+#define CLK_DMA_EB 3
+#define CLK_SDIO0_EB 4
+#define CLK_SDIO1_EB 5
+#define CLK_SDIO2_EB 6
+#define CLK_EMMC_EB 7
+#define CLK_ROM_EB 8
+#define CLK_BUSMON_EB 9
+#define CLK_CC63S_EB 10
+#define CLK_CC63P_EB 11
+#define CLK_CE0_EB 12
+#define CLK_CE1_EB 13
+#define CLK_APAHB_GATE_NUM (CLK_CE1_EB + 1)
+
+#define CLK_AVS_LIT_EB 0
+#define CLK_AVS_BIG_EB 1
+#define CLK_AP_INTC5_EB 2
+#define CLK_GPIO_EB 3
+#define CLK_PWM0_EB 4
+#define CLK_PWM1_EB 5
+#define CLK_PWM2_EB 6
+#define CLK_PWM3_EB 7
+#define CLK_KPD_EB 8
+#define CLK_AON_SYS_EB 9
+#define CLK_AP_SYS_EB 10
+#define CLK_AON_TMR_EB 11
+#define CLK_AP_TMR0_EB 12
+#define CLK_EFUSE_EB 13
+#define CLK_EIC_EB 14
+#define CLK_PUB1_REG_EB 15
+#define CLK_ADI_EB 16
+#define CLK_AP_INTC0_EB 17
+#define CLK_AP_INTC1_EB 18
+#define CLK_AP_INTC2_EB 19
+#define CLK_AP_INTC3_EB 20
+#define CLK_AP_INTC4_EB 21
+#define CLK_SPLK_EB 22
+#define CLK_MSPI_EB 23
+#define CLK_PUB0_REG_EB 24
+#define CLK_PIN_EB 25
+#define CLK_AON_CKG_EB 26
+#define CLK_GPU_EB 27
+#define CLK_APCPU_TS0_EB 28
+#define CLK_APCPU_TS1_EB 29
+#define CLK_DAP_EB 30
+#define CLK_I2C_EB 31
+#define CLK_PMU_EB 32
+#define CLK_THM_EB 33
+#define CLK_AUX0_EB 34
+#define CLK_AUX1_EB 35
+#define CLK_AUX2_EB 36
+#define CLK_PROBE_EB 37
+#define CLK_GPU0_AVS_EB 38
+#define CLK_GPU1_AVS_EB 39
+#define CLK_APCPU_WDG_EB 40
+#define CLK_AP_TMR1_EB 41
+#define CLK_AP_TMR2_EB 42
+#define CLK_DISP_EMC_EB 43
+#define CLK_ZIP_EMC_EB 44
+#define CLK_GSP_EMC_EB 45
+#define CLK_OSC_AON_EB 46
+#define CLK_LVDS_TRX_EB 47
+#define CLK_LVDS_TCXO_EB 48
+#define CLK_MDAR_EB 49
+#define CLK_RTC4M0_CAL_EB 50
+#define CLK_RCT100M_CAL_EB 51
+#define CLK_DJTAG_EB 52
+#define CLK_MBOX_EB 53
+#define CLK_AON_DMA_EB 54
+#define CLK_DBG_EMC_EB 55
+#define CLK_LVDS_PLL_DIV_EN 56
+#define CLK_DEF_EB 57
+#define CLK_AON_APB_RSV0 58
+#define CLK_ORP_JTAG_EB 59
+#define CLK_VSP_EB 60
+#define CLK_CAM_EB 61
+#define CLK_DISP_EB 62
+#define CLK_DBG_AXI_IF_EB 63
+#define CLK_SDIO0_2X_EN 64
+#define CLK_SDIO1_2X_EN 65
+#define CLK_SDIO2_2X_EN 66
+#define CLK_EMMC_2X_EN 67
+#define CLK_AON_GATE_NUM (CLK_EMMC_2X_EN + 1)
+
+#define CLK_LIT_MCU 0
+#define CLK_BIG_MCU 1
+#define CLK_AONSECURE_NUM (CLK_BIG_MCU + 1)
+
+#define CLK_AGCP_IIS0_EB 0
+#define CLK_AGCP_IIS1_EB 1
+#define CLK_AGCP_IIS2_EB 2
+#define CLK_AGCP_IIS3_EB 3
+#define CLK_AGCP_UART_EB 4
+#define CLK_AGCP_DMACP_EB 5
+#define CLK_AGCP_DMAAP_EB 6
+#define CLK_AGCP_ARC48K_EB 7
+#define CLK_AGCP_SRC44P1K_EB 8
+#define CLK_AGCP_MCDT_EB 9
+#define CLK_AGCP_VBCIFD_EB 10
+#define CLK_AGCP_VBC_EB 11
+#define CLK_AGCP_SPINLOCK_EB 12
+#define CLK_AGCP_ICU_EB 13
+#define CLK_AGCP_AP_ASHB_EB 14
+#define CLK_AGCP_CP_ASHB_EB 15
+#define CLK_AGCP_AUD_EB 16
+#define CLK_AGCP_AUDIF_EB 17
+#define CLK_AGCP_GATE_NUM (CLK_AGCP_AUDIF_EB + 1)
+
+#define CLK_GPU 0
+#define CLK_GPU_NUM (CLK_GPU + 1)
+
+#define CLK_AHB_VSP 0
+#define CLK_VSP 1
+#define CLK_VSP_ENC 2
+#define CLK_VPP 3
+#define CLK_VSP_26M 4
+#define CLK_VSP_NUM (CLK_VSP_26M + 1)
+
+#define CLK_VSP_DEC_EB 0
+#define CLK_VSP_CKG_EB 1
+#define CLK_VSP_MMU_EB 2
+#define CLK_VSP_ENC_EB 3
+#define CLK_VPP_EB 4
+#define CLK_VSP_26M_EB 5
+#define CLK_VSP_AXI_GATE 6
+#define CLK_VSP_ENC_GATE 7
+#define CLK_VPP_AXI_GATE 8
+#define CLK_VSP_BM_GATE 9
+#define CLK_VSP_ENC_BM_GATE 10
+#define CLK_VPP_BM_GATE 11
+#define CLK_VSP_GATE_NUM (CLK_VPP_BM_GATE + 1)
+
+#define CLK_AHB_CAM 0
+#define CLK_SENSOR0 1
+#define CLK_SENSOR1 2
+#define CLK_SENSOR2 3
+#define CLK_MIPI_CSI0_EB 4
+#define CLK_MIPI_CSI1_EB 5
+#define CLK_CAM_NUM (CLK_MIPI_CSI1_EB + 1)
+
+#define CLK_DCAM0_EB 0
+#define CLK_DCAM1_EB 1
+#define CLK_ISP0_EB 2
+#define CLK_CSI0_EB 3
+#define CLK_CSI1_EB 4
+#define CLK_JPG0_EB 5
+#define CLK_JPG1_EB 6
+#define CLK_CAM_CKG_EB 7
+#define CLK_CAM_MMU_EB 8
+#define CLK_ISP1_EB 9
+#define CLK_CPP_EB 10
+#define CLK_MMU_PF_EB 11
+#define CLK_ISP2_EB 12
+#define CLK_DCAM2ISP_IF_EB 13
+#define CLK_ISP2DCAM_IF_EB 14
+#define CLK_ISP_LCLK_EB 15
+#define CLK_ISP_ICLK_EB 16
+#define CLK_ISP_MCLK_EB 17
+#define CLK_ISP_PCLK_EB 18
+#define CLK_ISP_ISP2DCAM_EB 19
+#define CLK_DCAM0_IF_EB 20
+#define CLK_CLK26M_IF_EB 21
+#define CLK_CPHY0_GATE 22
+#define CLK_MIPI_CSI0_GATE 23
+#define CLK_CPHY1_GATE 24
+#define CLK_MIPI_CSI1 25
+#define CLK_DCAM0_AXI_GATE 26
+#define CLK_DCAM1_AXI_GATE 27
+#define CLK_SENSOR0_GATE 28
+#define CLK_SENSOR1_GATE 29
+#define CLK_JPG0_AXI_GATE 30
+#define CLK_GPG1_AXI_GATE 31
+#define CLK_ISP0_AXI_GATE 32
+#define CLK_ISP1_AXI_GATE 33
+#define CLK_ISP2_AXI_GATE 34
+#define CLK_CPP_AXI_GATE 35
+#define CLK_D0_IF_AXI_GATE 36
+#define CLK_D2I_IF_AXI_GATE 37
+#define CLK_I2D_IF_AXI_GATE 38
+#define CLK_SPARE_AXI_GATE 39
+#define CLK_SENSOR2_GATE 40
+#define CLK_D0IF_IN_D_EN 41
+#define CLK_D1IF_IN_D_EN 42
+#define CLK_D0IF_IN_D2I_EN 43
+#define CLK_D1IF_IN_D2I_EN 44
+#define CLK_IA_IN_D2I_EN 45
+#define CLK_IB_IN_D2I_EN 46
+#define CLK_IC_IN_D2I_EN 47
+#define CLK_IA_IN_I_EN 48
+#define CLK_IB_IN_I_EN 49
+#define CLK_IC_IN_I_EN 50
+#define CLK_CAM_GATE_NUM (CLK_IC_IN_I_EN + 1)
+
+#define CLK_AHB_DISP 0
+#define CLK_DISPC0_DPI 1
+#define CLK_DISPC1_DPI 2
+#define CLK_DISP_NUM (CLK_DISPC1_DPI + 1)
+
+#define CLK_DISPC0_EB 0
+#define CLK_DISPC1_EB 1
+#define CLK_DISPC_MMU_EB 2
+#define CLK_GSP0_EB 3
+#define CLK_GSP1_EB 4
+#define CLK_GSP0_MMU_EB 5
+#define CLK_GSP1_MMU_EB 6
+#define CLK_DSI0_EB 7
+#define CLK_DSI1_EB 8
+#define CLK_DISP_CKG_EB 9
+#define CLK_DISP_GPU_EB 10
+#define CLK_GPU_MTX_EB 11
+#define CLK_GSP_MTX_EB 12
+#define CLK_TMC_MTX_EB 13
+#define CLK_DISPC_MTX_EB 14
+#define CLK_DPHY0_GATE 15
+#define CLK_DPHY1_GATE 16
+#define CLK_GSP0_A_GATE 17
+#define CLK_GSP1_A_GATE 18
+#define CLK_GSP0_F_GATE 19
+#define CLK_GSP1_F_GATE 20
+#define CLK_D_MTX_F_GATE 21
+#define CLK_D_MTX_A_GATE 22
+#define CLK_D_NOC_F_GATE 23
+#define CLK_D_NOC_A_GATE 24
+#define CLK_GSP_MTX_F_GATE 25
+#define CLK_GSP_MTX_A_GATE 26
+#define CLK_GSP_NOC_F_GATE 27
+#define CLK_GSP_NOC_A_GATE 28
+#define CLK_DISPM0IDLE_GATE 29
+#define CLK_GSPM0IDLE_GATE 30
+#define CLK_DISP_GATE_NUM (CLK_GSPM0IDLE_GATE + 1)
+
+#define CLK_SIM0_EB 0
+#define CLK_IIS0_EB 1
+#define CLK_IIS1_EB 2
+#define CLK_IIS2_EB 3
+#define CLK_IIS3_EB 4
+#define CLK_SPI0_EB 5
+#define CLK_SPI1_EB 6
+#define CLK_SPI2_EB 7
+#define CLK_I2C0_EB 8
+#define CLK_I2C1_EB 9
+#define CLK_I2C2_EB 10
+#define CLK_I2C3_EB 11
+#define CLK_I2C4_EB 12
+#define CLK_I2C5_EB 13
+#define CLK_UART0_EB 14
+#define CLK_UART1_EB 15
+#define CLK_UART2_EB 16
+#define CLK_UART3_EB 17
+#define CLK_UART4_EB 18
+#define CLK_AP_CKG_EB 19
+#define CLK_SPI3_EB 20
+#define CLK_APAPB_GATE_NUM (CLK_SPI3_EB + 1)
+
+#endif /* _DT_BINDINGS_CLK_SC9860_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 08/12] dt-bindings: Add Spreadtrum clock binding documentation
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
Introduce a new binding with its documentation for Spreadtrum clock
sub-framework.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/clock/sprd.txt | 63 ++++++++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt
diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt
new file mode 100644
index 0000000..e9d179e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd.txt
@@ -0,0 +1,63 @@
+Spreadtrum Clock Binding
+------------------------
+
+Required properties:
+- compatible: should contain the following compatible strings:
+ - "sprd,sc9860-pmu-gate"
+ - "sprd,sc9860-pll"
+ - "sprd,sc9860-ap-clk"
+ - "sprd,sc9860-aon-prediv"
+ - "sprd,sc9860-apahb-gate"
+ - "sprd,sc9860-aon-gate"
+ - "sprd,sc9860-aonsecure-clk"
+ - "sprd,sc9860-agcp-gate"
+ - "sprd,sc9860-gpu-clk"
+ - "sprd,sc9860-vsp-clk"
+ - "sprd,sc9860-vsp-gate"
+ - "sprd,sc9860-cam-clk"
+ - "sprd,sc9860-cam-gate"
+ - "sprd,sc9860-disp-clk"
+ - "sprd,sc9860-disp-gate"
+ - "sprd,sc9860-apapb-gate"
+
+- #clock-cells: must be 1
+
+- clocks : Should be the input parent clock(s) phandle for the clock, this
+ property here just simply shows which clock group the clocks'
+ parents are in, since each clk node would represent many clocks
+ which are defined in the driver. The detailed dependency
+ relationship (i.e. how many parents and which are the parents)
+ are implemented in driver code.
+
+Optional properties:
+
+- reg: Contain the registers base address and length. It must be configured
+ only if no 'sprd,syscon' under the node.
+
+- sprd,syscon: phandle to the syscon which is in the same address area with
+ the clock, and so we can get regmap for the clocks from the
+ syscon device.
+
+Example:
+
+ pmu_gate: pmu-gate {
+ compatible = "sprd,sc9860-pmu-gate";
+ sprd,syscon = <&pmu_regs>;
+ clocks = <&ext_26m>;
+ #clock-cells = <1>;
+ };
+
+ pll: pll {
+ compatible = "sprd,sc9860-pll";
+ sprd,syscon = <&ana_regs>;
+ clocks = <&pmu_gate 0>;
+ #clock-cells = <1>;
+ };
+
+ ap_clk: clock-controller@20000000 {
+ compatible = "sprd,sc9860-ap-clk";
+ reg = <0 0x20000000 0 0x400>;
+ clocks = <&ext_26m>, <&pll 0>,
+ <&pmu_gate 0>;
+ #clock-cells = <1>;
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH V7 07/12] clk: sprd: add adjustable pll support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
Introduced a common adjustable pll clock driver for Spreadtrum SoCs.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/pll.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/pll.h | 108 +++++++++++++++++++
3 files changed, 375 insertions(+)
create mode 100644 drivers/clk/sprd/pll.c
create mode 100644 drivers/clk/sprd/pll.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 2262e76..d693969 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -5,3 +5,4 @@ clk-sprd-y += gate.o
clk-sprd-y += mux.o
clk-sprd-y += div.o
clk-sprd-y += composite.o
+clk-sprd-y += pll.o
diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c
new file mode 100644
index 0000000..36b4402
--- /dev/null
+++ b/drivers/clk/sprd/pll.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum pll clock driver
+//
+// Copyright (C) 2015~2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "pll.h"
+
+#define CLK_PLL_1M 1000000
+#define CLK_PLL_10M (CLK_PLL_1M * 10)
+
+#define pindex(pll, member) \
+ (pll->factors[member].shift / (8 * sizeof(pll->regs_num)))
+
+#define pshift(pll, member) \
+ (pll->factors[member].shift % (8 * sizeof(pll->regs_num)))
+
+#define pwidth(pll, member) \
+ pll->factors[member].width
+
+#define pmask(pll, member) \
+ ((pwidth(pll, member)) ? \
+ GENMASK(pwidth(pll, member) + pshift(pll, member) - 1, \
+ pshift(pll, member)) : 0)
+
+#define pinternal(pll, cfg, member) \
+ (cfg[pindex(pll, member)] & pmask(pll, member))
+
+#define pinternal_val(pll, cfg, member) \
+ (pinternal(pll, cfg, member) >> pshift(pll, member))
+
+static inline unsigned int
+sprd_pll_read(const struct sprd_pll *pll, u8 index)
+{
+ const struct sprd_clk_common *common = &pll->common;
+ unsigned int val = 0;
+
+ if (WARN_ON(index >= pll->regs_num))
+ return 0;
+
+ regmap_read(common->regmap, common->reg + index * 4, &val);
+
+ return val;
+}
+
+static inline void
+sprd_pll_write(const struct sprd_pll *pll, u8 index,
+ u32 msk, u32 val)
+{
+ const struct sprd_clk_common *common = &pll->common;
+ unsigned int offset, reg;
+ int ret = 0;
+
+ if (WARN_ON(index >= pll->regs_num))
+ return;
+
+ offset = common->reg + index * 4;
+ ret = regmap_read(common->regmap, offset, ®);
+ if (!ret)
+ regmap_write(common->regmap, offset, (reg & ~msk) | val);
+}
+
+static unsigned long pll_get_refin(const struct sprd_pll *pll)
+{
+ u32 shift, mask, index, refin_id = 3;
+ const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+ if (pwidth(pll, PLL_REFIN)) {
+ index = pindex(pll, PLL_REFIN);
+ shift = pshift(pll, PLL_REFIN);
+ mask = pmask(pll, PLL_REFIN);
+ refin_id = (sprd_pll_read(pll, index) & mask) >> shift;
+ if (refin_id > 3)
+ refin_id = 3;
+ }
+
+ return refin[refin_id];
+}
+
+static u32 pll_get_ibias(u64 rate, const u64 *table)
+{
+ u32 i, num = table[0];
+
+ for (i = 1; i < num + 1; i++)
+ if (rate <= table[i])
+ break;
+
+ return (i == num + 1) ? num : i;
+}
+
+static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll,
+ unsigned long parent_rate)
+{
+ u32 *cfg;
+ u32 i, mask, regs_num = pll->regs_num;
+ unsigned long rate, nint, kint = 0;
+ u64 refin;
+ u16 k1, k2;
+
+ cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ return -ENOMEM;
+
+ for (i = 0; i < regs_num; i++)
+ cfg[i] = sprd_pll_read(pll, i);
+
+ refin = pll_get_refin(pll);
+
+ if (pinternal(pll, cfg, PLL_PREDIV))
+ refin = refin * 2;
+
+ if (pwidth(pll, PLL_POSTDIV) &&
+ ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
+ (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV))))
+ refin = refin / 2;
+
+ if (!pinternal(pll, cfg, PLL_DIV_S)) {
+ rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M;
+ } else {
+ nint = pinternal_val(pll, cfg, PLL_NINT);
+ if (pinternal(pll, cfg, PLL_SDM_EN))
+ kint = pinternal_val(pll, cfg, PLL_KINT);
+
+ mask = pmask(pll, PLL_KINT);
+
+ k1 = pll->k1;
+ k2 = pll->k2;
+ rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1,
+ ((mask >> __ffs(mask)) + 1)) *
+ k2 + refin * nint * CLK_PLL_1M;
+ }
+
+ return rate;
+}
+
+#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val) \
+ (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT))
+
+static int _sprd_pll_set_rate(const struct sprd_pll *pll,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct reg_cfg *cfg;
+ int ret = 0;
+ u32 mask, shift, width, ibias_val, index;
+ u32 regs_num = pll->regs_num, i = 0;
+ unsigned long kint, nint;
+ u64 tmp, refin, fvco = rate;
+
+ cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ return -ENOMEM;
+
+ refin = pll_get_refin(pll);
+
+ mask = pmask(pll, PLL_PREDIV);
+ index = pindex(pll, PLL_PREDIV);
+ width = pwidth(pll, PLL_PREDIV);
+ if (width && (sprd_pll_read(pll, index) & mask))
+ refin = refin * 2;
+
+ mask = pmask(pll, PLL_POSTDIV);
+ index = pindex(pll, PLL_POSTDIV);
+ width = pwidth(pll, PLL_POSTDIV);
+ cfg[index].msk = mask;
+ if (width && ((pll->fflag == 1 && fvco <= pll->fvco) ||
+ (pll->fflag == 0 && fvco > pll->fvco)))
+ cfg[index].val |= mask;
+
+ if (width && fvco <= pll->fvco)
+ fvco = fvco * 2;
+
+ mask = pmask(pll, PLL_DIV_S);
+ index = pindex(pll, PLL_DIV_S);
+ cfg[index].val |= mask;
+ cfg[index].msk |= mask;
+
+ mask = pmask(pll, PLL_SDM_EN);
+ index = pindex(pll, PLL_SDM_EN);
+ cfg[index].val |= mask;
+ cfg[index].msk |= mask;
+
+ nint = do_div(fvco, refin * CLK_PLL_1M);
+ mask = pmask(pll, PLL_NINT);
+ index = pindex(pll, PLL_NINT);
+ shift = pshift(pll, PLL_NINT);
+ cfg[index].val |= (nint << shift) & mask;
+ cfg[index].msk |= mask;
+
+ mask = pmask(pll, PLL_KINT);
+ index = pindex(pll, PLL_KINT);
+ width = pwidth(pll, PLL_KINT);
+ shift = pshift(pll, PLL_KINT);
+ tmp = fvco - refin * nint * CLK_PLL_1M;
+ tmp = do_div(tmp, 10000) * ((mask >> shift) + 1);
+ kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100);
+ cfg[index].val |= (kint << shift) & mask;
+ cfg[index].msk |= mask;
+
+ ibias_val = pll_get_ibias(fvco, pll->itable);
+
+ mask = pmask(pll, PLL_IBIAS);
+ index = pindex(pll, PLL_IBIAS);
+ shift = pshift(pll, PLL_IBIAS);
+ cfg[index].val |= ibias_val << shift & mask;
+ cfg[index].msk |= mask;
+
+ for (i = 0; i < regs_num; i++) {
+ if (cfg[i].msk) {
+ sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val);
+ ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk,
+ cfg[i].val);
+ }
+ }
+
+ if (!ret)
+ udelay(pll->udelay);
+
+ return ret;
+}
+
+static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+ return _sprd_pll_recalc_rate(pll, parent_rate);
+}
+
+static int sprd_pll_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+ return _sprd_pll_set_rate(pll, rate, parent_rate);
+}
+
+static int sprd_pll_clk_prepare(struct clk_hw *hw)
+{
+ struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+ udelay(pll->udelay);
+
+ return 0;
+}
+
+static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ return rate;
+}
+
+const struct clk_ops sprd_pll_ops = {
+ .prepare = sprd_pll_clk_prepare,
+ .recalc_rate = sprd_pll_recalc_rate,
+ .round_rate = sprd_pll_round_rate,
+ .set_rate = sprd_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_pll_ops);
diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h
new file mode 100644
index 0000000..5141756
--- /dev/null
+++ b/drivers/clk/sprd/pll.h
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum pll clock driver
+//
+// Copyright (C) 2015~2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_PLL_H_
+#define _SPRD_PLL_H_
+
+#include "common.h"
+
+struct reg_cfg {
+ u32 val;
+ u32 msk;
+};
+
+struct clk_bit_field {
+ u8 shift;
+ u8 width;
+};
+
+enum {
+ PLL_LOCK_DONE,
+ PLL_DIV_S,
+ PLL_MOD_EN,
+ PLL_SDM_EN,
+ PLL_REFIN,
+ PLL_IBIAS,
+ PLL_N,
+ PLL_NINT,
+ PLL_KINT,
+ PLL_PREDIV,
+ PLL_POSTDIV,
+
+ PLL_FACT_MAX
+};
+
+/*
+ * struct sprd_pll - definition of adjustable pll clock
+ *
+ * @reg: registers used to set the configuration of pll clock,
+ * reg[0] shows how many registers this pll clock uses.
+ * @itable: pll ibias table, itable[0] means how many items this
+ * table includes
+ * @udelay delay time after setting rate
+ * @factors used to calculate the pll clock rate
+ * @fvco: fvco threshold rate
+ * @fflag: fvco flag
+ */
+struct sprd_pll {
+ u32 regs_num;
+ const u64 *itable;
+ const struct clk_bit_field *factors;
+ u16 udelay;
+ u16 k1;
+ u16 k2;
+ u16 fflag;
+ u64 fvco;
+
+ struct sprd_clk_common common;
+};
+
+#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
+ _regs_num, _itable, _factors, \
+ _udelay, _k1, _k2, _fflag, _fvco) \
+ struct sprd_pll _struct = { \
+ .regs_num = _regs_num, \
+ .itable = _itable, \
+ .factors = _factors, \
+ .udelay = _udelay, \
+ .k1 = _k1, \
+ .k2 = _k2, \
+ .fflag = _fflag, \
+ .fvco = _fvco, \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ &sprd_pll_ops, \
+ 0), \
+ }, \
+ }
+
+#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg, \
+ _regs_num, _itable, _factors, \
+ _udelay, _k1, _k2) \
+ SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
+ _regs_num, _itable, _factors, \
+ _udelay, _k1, _k2, 0, 0)
+
+#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg, \
+ _regs_num, _itable, _factors, _udelay) \
+ SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
+ _regs_num, _itable, _factors, \
+ _udelay, 1000, 1000, 0, 0)
+
+static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_pll, common);
+}
+
+extern const struct clk_ops sprd_pll_ops;
+
+#endif /* _SPRD_PLL_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 06/12] clk: sprd: add composite clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
This patch introduced composite driver for Spreadtrum's SoCs. The
functions of this composite clock simply consist of divider and
mux clocks.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/composite.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/composite.h | 51 +++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+)
create mode 100644 drivers/clk/sprd/composite.c
create mode 100644 drivers/clk/sprd/composite.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 80e6039..2262e76 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -4,3 +4,4 @@ clk-sprd-y += common.o
clk-sprd-y += gate.o
clk-sprd-y += mux.o
clk-sprd-y += div.o
+clk-sprd-y += composite.o
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..ebb6448
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum composite clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+
+#include "composite.h"
+
+static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_round_rate(&cc->common, &cc->div,
+ rate, parent_rate);
+}
+
+static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate);
+}
+
+static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_set_rate(&cc->common, &cc->div,
+ rate, parent_rate);
+}
+
+static u8 sprd_comp_get_parent(struct clk_hw *hw)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_mux_helper_get_parent(&cc->common, &cc->mux);
+}
+
+static int sprd_comp_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index);
+}
+
+const struct clk_ops sprd_comp_ops = {
+ .get_parent = sprd_comp_get_parent,
+ .set_parent = sprd_comp_set_parent,
+
+ .round_rate = sprd_comp_round_rate,
+ .recalc_rate = sprd_comp_recalc_rate,
+ .set_rate = sprd_comp_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_comp_ops);
diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h
new file mode 100644
index 0000000..0984e9e
--- /dev/null
+++ b/drivers/clk/sprd/composite.h
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum composite clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_COMPOSITE_H_
+#define _SPRD_COMPOSITE_H_
+
+#include "common.h"
+#include "mux.h"
+#include "div.h"
+
+struct sprd_comp {
+ struct sprd_mux_ssel mux;
+ struct sprd_div_internal div;
+ struct sprd_clk_common common;
+};
+
+#define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table, \
+ _mshift, _mwidth, _dshift, _dwidth, _flags) \
+ struct sprd_comp _struct = { \
+ .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \
+ .div = _SPRD_DIV_CLK(_dshift, _dwidth), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parent, \
+ &sprd_comp_ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift, \
+ _mwidth, _dshift, _dwidth, _flags) \
+ SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, \
+ NULL, _mshift, _mwidth, \
+ _dshift, _dwidth, _flags)
+
+static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_comp, common);
+}
+
+extern const struct clk_ops sprd_comp_ops;
+
+#endif /* _SPRD_COMPOSITE_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 05/12] clk: sprd: add divider clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
This is a feature that can also be found in sprd composite clocks,
provide a bunch of helpers that can be reused later on.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/div.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/div.h | 75 +++++++++++++++++++++++++++++++++++++++
3 files changed, 166 insertions(+)
create mode 100644 drivers/clk/sprd/div.c
create mode 100644 drivers/clk/sprd/div.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index cee36b5..80e6039 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
clk-sprd-y += gate.o
clk-sprd-y += mux.o
+clk-sprd-y += div.o
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
new file mode 100644
index 0000000..887a863
--- /dev/null
+++ b/drivers/clk/sprd/div.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum divider clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+
+#include "div.h"
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return divider_round_rate(&common->hw, rate, parent_rate,
+ NULL, div->width, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
+
+static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_round_rate(&cd->common, &cd->div,
+ rate, parent_rate);
+}
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long parent_rate)
+{
+ unsigned long val;
+ unsigned int reg;
+
+ regmap_read(common->regmap, common->reg, ®);
+ val = reg >> div->shift;
+ val &= (1 << div->width) - 1;
+
+ return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
+
+static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
+}
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned long val;
+ unsigned int reg;
+
+ val = divider_get_val(rate, parent_rate, NULL,
+ div->width, 0);
+
+ regmap_read(common->regmap, common->reg, ®);
+ reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
+
+ regmap_write(common->regmap, common->reg,
+ reg | (val << div->shift));
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
+
+static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_set_rate(&cd->common, &cd->div,
+ rate, parent_rate);
+}
+
+const struct clk_ops sprd_div_ops = {
+ .recalc_rate = sprd_div_recalc_rate,
+ .round_rate = sprd_div_round_rate,
+ .set_rate = sprd_div_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_div_ops);
diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h
new file mode 100644
index 0000000..b3033d2
--- /dev/null
+++ b/drivers/clk/sprd/div.h
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum divider clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_DIV_H_
+#define _SPRD_DIV_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_div_internal - Internal divider description
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ *
+ * That structure represents a single divider, and is meant to be
+ * embedded in other structures representing the various clock
+ * classes.
+ */
+struct sprd_div_internal {
+ u8 shift;
+ u8 width;
+};
+
+#define _SPRD_DIV_CLK(_shift, _width) \
+ { \
+ .shift = _shift, \
+ .width = _width, \
+ }
+
+struct sprd_div {
+ struct sprd_div_internal div;
+ struct sprd_clk_common common;
+};
+
+#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \
+ _shift, _width, _flags) \
+ struct sprd_div _struct = { \
+ .div = _SPRD_DIV_CLK(_shift, _width), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ &sprd_div_ops, \
+ _flags), \
+ } \
+ }
+
+static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_div, common);
+}
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long *parent_rate);
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long parent_rate);
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long parent_rate);
+
+extern const struct clk_ops sprd_div_ops;
+
+#endif /* _SPRD_DIV_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 04/12] clk: sprd: add mux clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
This patch adds clock multiplexor support for Spreadtrum platforms,
the mux clocks also can be found in sprd composite clocks, so
provides two helpers that can be reused later on.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/mux.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/mux.h | 74 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+)
create mode 100644 drivers/clk/sprd/mux.c
create mode 100644 drivers/clk/sprd/mux.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 8cd5592..cee36b5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
clk-sprd-y += gate.o
+clk-sprd-y += mux.o
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..624041b
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum multiplexer clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "mux.h"
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux)
+{
+ unsigned int reg;
+ u8 parent;
+ int num_parents;
+ int i;
+
+ regmap_read(common->regmap, common->reg, ®);
+ parent = reg >> mux->shift;
+ parent &= (1 << mux->width) - 1;
+
+ if (!mux->table)
+ return parent;
+
+ num_parents = clk_hw_get_num_parents(&common->hw);
+
+ for (i = 0; i < num_parents - 1; i++)
+ if (parent >= mux->table[i] && parent < mux->table[i + 1])
+ return i;
+
+ return num_parents - 1;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent);
+
+static u8 sprd_mux_get_parent(struct clk_hw *hw)
+{
+ struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+ return sprd_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux,
+ u8 index)
+{
+ unsigned int reg;
+
+ if (mux->table)
+ index = mux->table[index];
+
+ regmap_read(common->regmap, common->reg, ®);
+ reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
+ regmap_write(common->regmap, common->reg,
+ reg | (index << mux->shift));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent);
+
+static int sprd_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+ return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+const struct clk_ops sprd_mux_ops = {
+ .get_parent = sprd_mux_get_parent,
+ .set_parent = sprd_mux_set_parent,
+ .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_mux_ops);
diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h
new file mode 100644
index 0000000..548cfa0
--- /dev/null
+++ b/drivers/clk/sprd/mux.h
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum multiplexer clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_MUX_H_
+#define _SPRD_MUX_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_mux_ssel - Mux clock's source select bits in its register
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ * @table: For some mux clocks, not all sources are used on some special
+ * chips, this matches the value of mux clock's register and the
+ * sources which are used for this mux clock
+ */
+struct sprd_mux_ssel {
+ u8 shift;
+ u8 width;
+ const u8 *table;
+};
+
+struct sprd_mux {
+ struct sprd_mux_ssel mux;
+ struct sprd_clk_common common;
+};
+
+#define _SPRD_MUX_CLK(_shift, _width, _table) \
+ { \
+ .shift = _shift, \
+ .width = _width, \
+ .table = _table, \
+ }
+
+#define SPRD_MUX_CLK_TABLE(_struct, _name, _parents, _table, \
+ _reg, _shift, _width, \
+ _flags) \
+ struct sprd_mux _struct = { \
+ .mux = _SPRD_MUX_CLK(_shift, _width, _table), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parents, \
+ &sprd_mux_ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_MUX_CLK(_struct, _name, _parents, _reg, \
+ _shift, _width, _flags) \
+ SPRD_MUX_CLK_TABLE(_struct, _name, _parents, NULL, \
+ _reg, _shift, _width, _flags)
+
+static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_mux, common);
+}
+
+extern const struct clk_ops sprd_mux_ops;
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux);
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux,
+ u8 index);
+
+#endif /* _SPRD_MUX_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 03/12] clk: sprd: add gate clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
Some clocks on the Spreadtrum's SoCs are just simple gates. Add
support for those clocks.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/gate.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/gate.h | 59 ++++++++++++++++++++++++
3 files changed, 171 insertions(+)
create mode 100644 drivers/clk/sprd/gate.c
create mode 100644 drivers/clk/sprd/gate.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 74f4b80..8cd5592 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
+clk-sprd-y += gate.o
diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c
new file mode 100644
index 0000000..f59d193
--- /dev/null
+++ b/drivers/clk/sprd/gate.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum gate clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "gate.h"
+
+static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+ const struct sprd_clk_common *common = &sg->common;
+ unsigned int reg;
+ bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
+
+ set ^= en;
+
+ regmap_read(common->regmap, common->reg, ®);
+
+ if (set)
+ reg |= sg->enable_mask;
+ else
+ reg &= ~sg->enable_mask;
+
+ regmap_write(common->regmap, common->reg, reg);
+}
+
+static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+ const struct sprd_clk_common *common = &sg->common;
+ bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+ unsigned int offset;
+
+ set ^= en;
+
+ /*
+ * Each set/clear gate clock has three registers:
+ * common->reg - base register
+ * common->reg + offset - set register
+ * common->reg + 2 * offset - clear register
+ */
+ offset = set ? sg->sc_offset : sg->sc_offset * 2;
+
+ regmap_write(common->regmap, common->reg + offset,
+ sg->enable_mask);
+}
+
+static void sprd_gate_disable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_gate_toggle(sg, false);
+}
+
+static int sprd_gate_enable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_gate_toggle(sg, true);
+
+ return 0;
+}
+
+static void sprd_sc_gate_disable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_sc_gate_toggle(sg, false);
+}
+
+static int sprd_sc_gate_enable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_sc_gate_toggle(sg, true);
+
+ return 0;
+}
+static int sprd_gate_is_enabled(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+ struct sprd_clk_common *common = &sg->common;
+ unsigned int reg;
+
+ regmap_read(common->regmap, common->reg, ®);
+
+ if (sg->flags & CLK_GATE_SET_TO_DISABLE)
+ reg ^= sg->enable_mask;
+
+ reg &= sg->enable_mask;
+
+ return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_gate_ops = {
+ .disable = sprd_gate_disable,
+ .enable = sprd_gate_enable,
+ .is_enabled = sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_gate_ops);
+
+const struct clk_ops sprd_sc_gate_ops = {
+ .disable = sprd_sc_gate_disable,
+ .enable = sprd_sc_gate_enable,
+ .is_enabled = sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
+
diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h
new file mode 100644
index 0000000..2e582c6
--- /dev/null
+++ b/drivers/clk/sprd/gate.h
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum gate clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_GATE_H_
+#define _SPRD_GATE_H_
+
+#include "common.h"
+
+struct sprd_gate {
+ u32 enable_mask;
+ u16 flags;
+ u16 sc_offset;
+
+ struct sprd_clk_common common;
+};
+
+#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags, _ops) \
+ struct sprd_gate _struct = { \
+ .enable_mask = _enable_mask, \
+ .sc_offset = _sc_offset, \
+ .flags = _gate_flags, \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ _ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, \
+ _enable_mask, _flags, _gate_flags) \
+ SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0, \
+ _enable_mask, _flags, _gate_flags, \
+ &sprd_gate_ops)
+
+#define SPRD_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags) \
+ SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags, \
+ &sprd_sc_gate_ops)
+
+static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_gate, common);
+}
+
+extern const struct clk_ops sprd_gate_ops;
+extern const struct clk_ops sprd_sc_gate_ops;
+
+#endif /* _SPRD_GATE_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 02/12] clk: sprd: Add common infrastructure
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
Added Spreadtrum's clock driver framework together with common
structures and interface functions.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/sprd/Kconfig | 4 ++
drivers/clk/sprd/Makefile | 3 ++
drivers/clk/sprd/common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/common.h | 38 +++++++++++++++++++
6 files changed, 143 insertions(+)
create mode 100644 drivers/clk/sprd/Kconfig
create mode 100644 drivers/clk/sprd/Makefile
create mode 100644 drivers/clk/sprd/common.c
create mode 100644 drivers/clk/sprd/common.h
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1c4e1aa..ce1a32be 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/sprd/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7f761b..d880d13 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SIRF) += sirf/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
+obj-$(CONFIG_ARCH_SPRD) += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/
diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
new file mode 100644
index 0000000..67a3287
--- /dev/null
+++ b/drivers/clk/sprd/Kconfig
@@ -0,0 +1,4 @@
+config SPRD_COMMON_CLK
+ tristate "Clock support for Spreadtrum SoCs"
+ depends on ARCH_SPRD || COMPILE_TEST
+ default ARCH_SPRD
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..74f4b80
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
+
+clk-sprd-y += common.o
diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c
new file mode 100644
index 0000000..e038b044
--- /dev/null
+++ b/drivers/clk/sprd/common.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum clock infrastructure
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#include "common.h"
+
+static const struct regmap_config sprdclk_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xffff,
+ .fast_io = true,
+};
+
+static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
+ struct regmap *regmap)
+{
+ int i;
+ struct sprd_clk_common *cclk;
+
+ for (i = 0; i < desc->num_clk_clks; i++) {
+ cclk = desc->clk_clks[i];
+ if (!cclk)
+ continue;
+
+ cclk->regmap = regmap;
+ }
+}
+
+int sprd_clk_regmap_init(struct platform_device *pdev,
+ const struct sprd_clk_desc *desc)
+{
+ void __iomem *base;
+ struct device_node *node = pdev->dev.of_node;
+ struct regmap *regmap;
+
+ if (of_find_property(node, "sprd,syscon", NULL)) {
+ regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
+ if (IS_ERR_OR_NULL(regmap)) {
+ pr_err("%s: failed to get syscon regmap\n", __func__);
+ return PTR_ERR(regmap);
+ }
+ } else {
+ base = of_iomap(node, 0);
+ regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sprdclk_regmap_config);
+ if (IS_ERR_OR_NULL(regmap)) {
+ pr_err("failed to init regmap\n");
+ return PTR_ERR(regmap);
+ }
+ }
+
+ sprd_clk_set_regmap(desc, regmap);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
+
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
+{
+ int i, ret;
+ struct clk_hw *hw;
+
+ for (i = 0; i < clkhw->num; i++) {
+
+ hw = clkhw->hws[i];
+
+ if (!hw)
+ continue;
+
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret) {
+ dev_err(dev, "Couldn't register clock %d - %s\n",
+ i, hw->init->name);
+ return ret;
+ }
+ }
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
+ if (ret)
+ dev_err(dev, "Failed to add clock provider\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_probe);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h
new file mode 100644
index 0000000..abd9ff5
--- /dev/null
+++ b/drivers/clk/sprd/common.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum clock infrastructure
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_CLK_COMMON_H_
+#define _SPRD_CLK_COMMON_H_
+
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+struct device_node;
+
+struct sprd_clk_common {
+ struct regmap *regmap;
+ u32 reg;
+ struct clk_hw hw;
+};
+
+struct sprd_clk_desc {
+ struct sprd_clk_common **clk_clks;
+ unsigned long num_clk_clks;
+ struct clk_hw_onecell_data *hw_clks;
+};
+
+static inline struct sprd_clk_common *
+ hw_to_sprd_clk_common(const struct clk_hw *hw)
+{
+ return container_of(hw, struct sprd_clk_common, hw);
+}
+int sprd_clk_regmap_init(struct platform_device *pdev,
+ const struct sprd_clk_desc *desc);
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw);
+
+#endif /* _SPRD_CLK_COMMON_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V7 01/12] drivers: move clock common macros out from vendor directories
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>
These macros are used by more than one SoC vendor platforms, avoid to
have many copies of these code, this patch moves them to the common
header file which every clock drivers can access to.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sunxi-ng/ccu_common.h | 29 -----------------------------
drivers/clk/zte/clk.h | 18 ------------------
include/linux/clk-provider.h | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 38 insertions(+), 47 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 5d684ce..568cfae 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -31,35 +31,6 @@
struct device_node;
-#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
- &(struct clk_init_data) { \
- .flags = _flags, \
- .name = _name, \
- .parent_names = (const char *[]) { _parent }, \
- .num_parents = 1, \
- .ops = _ops, \
- }
-
-#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
- &(struct clk_init_data) { \
- .flags = _flags, \
- .name = _name, \
- .parent_names = _parents, \
- .num_parents = ARRAY_SIZE(_parents), \
- .ops = _ops, \
- }
-
-#define CLK_FIXED_FACTOR(_struct, _name, _parent, \
- _div, _mult, _flags) \
- struct clk_fixed_factor _struct = { \
- .div = _div, \
- .mult = _mult, \
- .hw.init = CLK_HW_INIT(_name, \
- _parent, \
- &clk_fixed_factor_ops, \
- _flags), \
- }
-
struct ccu_common {
void __iomem *base;
u16 reg;
diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h
index 4df0f12..f1041e3 100644
--- a/drivers/clk/zte/clk.h
+++ b/drivers/clk/zte/clk.h
@@ -14,24 +14,6 @@
#define PNAME(x) static const char *x[]
-#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
- &(struct clk_init_data) { \
- .flags = _flags, \
- .name = _name, \
- .parent_names = (const char *[]) { _parent }, \
- .num_parents = 1, \
- .ops = _ops, \
- }
-
-#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
- &(struct clk_init_data) { \
- .flags = _flags, \
- .name = _name, \
- .parent_names = _parents, \
- .num_parents = ARRAY_SIZE(_parents), \
- .ops = _ops, \
- }
-
struct zx_pll_config {
unsigned long rate;
u32 cfg0;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7c925e6..26ea037 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -806,6 +806,44 @@ extern struct of_device_id __clk_of_table;
} \
OF_DECLARE_1(clk, name, compat, name##_of_clk_init_driver)
+#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = (const char *[]) { _parent }, \
+ .num_parents = 1, \
+ .ops = _ops, \
+ })
+
+#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .ops = _ops, \
+ })
+
+#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = NULL, \
+ .num_parents = 0, \
+ .ops = _ops, \
+ })
+
+#define CLK_FIXED_FACTOR(_struct, _name, _parent, \
+ _div, _mult, _flags) \
+ struct clk_fixed_factor _struct = { \
+ .div = _div, \
+ .mult = _mult, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ &clk_fixed_factor_ops, \
+ _flags), \
+ }
+
#ifdef CONFIG_OF
int of_clk_add_provider(struct device_node *np,
struct clk *(*clk_src_get)(struct of_phandle_args *args,
--
2.7.4
^ permalink raw reply related
* [PATCH V7 00/12] add clock driver for Spreadtrum platforms
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
From: Chunyan Zhang <zhang.chunyan@linaro.org>
This series adds Spreadtrum clock support together with its binding
documentation and devicetree data.
Any comments would be greatly appreciated.
Thanks,
Chunyan
Changes from V6: (https://lkml.org/lkml/2017/11/27/217)
* Changed to use "//" format for the file header
* Addressed Stephen's comments:
- Put the common macros in clk-provider.h instead of clk_common.h, also removed
the same macros from sunxi-ng/ccu_common.h and zte/clk.h;
- Removed CLK_FIXED_RATE(), and moved the fixed rate clocks from driver to DT;
- Use devm_of_clk_add_hw_provider() instead;
- Removed sprd_regmap_{read|write}(), use regmap API directly;
- Removed all full stop on error messages.
* Use IS_ERR_OR_NULL() instead of IS_ERR() for checking regmap pointers;
Changes from V5: (https://lkml.org/lkml/2017/11/20/21)
* Rebased the whole patch-set to 4.15-rc1;
* Fixed kbuild-test warnings;
* Switched to use devm_clk_hw_register() instead of clk_hw_register();
* Removed useless debug information from sc9860-clk.c.
Changes from V4: (https://lkml.org/lkml/2017/11/10/30)
* Added acked-by of Rob Herring;
* Removed spin lock from Spreadtrum's gate, mux, div drivers, since we have
switched to use regmap.
Changes from V3: (https://lkml.org/lkml/2017/11/2/61)
* Addressed comments from Julien Thierry:
- Clean the if branch of sprd_mux_helper_get_parent()
- Have the Gate clock macros and ops for both mode (i.e. sc_gate and gate) separate;
- Have the Mux clock macros with/without table separate, and same changes
for the composite clock.
* Switched the function name from _endisable to _toggle;
* Fixed Kbuild test error:
- Added exporting sprd_clk_regmap_init() which would be used in other module(s);
* Change the function sprd_clk_set_regmap() to the static one, and removed the
declear from the include file;
* Addressed comments from Rob:
- Separate the dt-binding include file from the driver patch;
- Documented more for the property "clocks"
* Changed the syscon device names;
* Changed the name of 'sprd_mux_internal' to 'sprd_mux_ssel'
Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html)
* Switch to use regmap to access registers;
* Splited all clocks into 16 separated nodes, for each belongs to a single address area;
* Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area;
* Added syscon device tree nodes which will be quoted by the node of clocks which are in
the same address area with the syscon device;
* Revised the binding documentation according to the dt modification.
Changes from V1: (https://lkml.org/lkml/2017/6/17/356)
* Address Stephen's comments:
- Switch to use platform device driver instead of the DT probing mechanism.
- Move the common clock macro out from vendor directory, but need to remove those
overlap code from other vendors (such as sunxi-ng) once this get merged.
- Add support to be built as a module.
- Add 'sprd_' prefix for all spin locks used in these drivers.
- Mark input parameter of sprd_x with const.
- Remove unreasonable dependencies to CONFIG_64BIT.
- Add readl() after writing the same register.
- Remove CLK_IS_BASIC which is no longer used.
- Remove unnecessery CLK_IGNORE_UNUSED when defining a clock.
- Change to expose all clock index.
- Use clk_ instead of ccu.
- Add Kconfig for sprd clocks.
- Move the fixed clocks out from the soc node.
- Switch to use 64-bit math in pll driver instead of 32-bit math.
* Revise binding documentation according to dt modification.
* Rename sc9860.c to sc9860-clk.c
Chunyan Zhang (12):
drivers: move clock common macros out from vendor directories
clk: sprd: Add common infrastructure
clk: sprd: add gate clock support
clk: sprd: add mux clock support
clk: sprd: add divider clock support
clk: sprd: add composite clock support
clk: sprd: add adjustable pll support
dt-bindings: Add Spreadtrum clock binding documentation
clk: sprd: Add dt-bindings include file for SC9860
clk: sprd: add clocks support for SC9860
arm64: dts: add syscon for whale2 platform
arm64: dts: add clocks for SC9860
Documentation/devicetree/bindings/clock/sprd.txt | 63 +
arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 ++
arch/arm64/boot/dts/sprd/whale2.dtsi | 62 +-
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/sprd/Kconfig | 14 +
drivers/clk/sprd/Makefile | 11 +
drivers/clk/sprd/common.c | 96 ++
drivers/clk/sprd/common.h | 38 +
drivers/clk/sprd/composite.c | 60 +
drivers/clk/sprd/composite.h | 51 +
drivers/clk/sprd/div.c | 90 +
drivers/clk/sprd/div.h | 75 +
drivers/clk/sprd/gate.c | 111 ++
drivers/clk/sprd/gate.h | 59 +
drivers/clk/sprd/mux.c | 76 +
drivers/clk/sprd/mux.h | 74 +
drivers/clk/sprd/pll.c | 266 +++
drivers/clk/sprd/pll.h | 108 ++
drivers/clk/sprd/sc9860-clk.c | 1974 ++++++++++++++++++++++
drivers/clk/sunxi-ng/ccu_common.h | 29 -
drivers/clk/zte/clk.h | 18 -
include/dt-bindings/clock/sprd,sc9860-clk.h | 404 +++++
include/linux/clk-provider.h | 38 +
24 files changed, 3785 insertions(+), 49 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt
create mode 100644 drivers/clk/sprd/Kconfig
create mode 100644 drivers/clk/sprd/Makefile
create mode 100644 drivers/clk/sprd/common.c
create mode 100644 drivers/clk/sprd/common.h
create mode 100644 drivers/clk/sprd/composite.c
create mode 100644 drivers/clk/sprd/composite.h
create mode 100644 drivers/clk/sprd/div.c
create mode 100644 drivers/clk/sprd/div.h
create mode 100644 drivers/clk/sprd/gate.c
create mode 100644 drivers/clk/sprd/gate.h
create mode 100644 drivers/clk/sprd/mux.c
create mode 100644 drivers/clk/sprd/mux.h
create mode 100644 drivers/clk/sprd/pll.c
create mode 100644 drivers/clk/sprd/pll.h
create mode 100644 drivers/clk/sprd/sc9860-clk.c
create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h
--
2.7.4
^ permalink raw reply
* Re: [PATCH V6 0/7] dmaengine: qcom_hidma: add support for bugfixed HW
From: Sakari Ailus @ 2017-12-07 12:41 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Sinan Kaya, Sakari Ailus, dmaengine, Timur Tabi,
devicetree@vger.kernel.org, ACPI Devel Maling List, linux-arm-msm,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAJZ5v0gq-Xv1V90GEcfxdnrADQn2Gern=LBnsbSzmrU9M0+FEQ@mail.gmail.com>
On Tue, Dec 05, 2017 at 11:05:52PM +0100, Rafael J. Wysocki wrote:
> On Tue, Dec 5, 2017 at 6:04 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
> > Introduce new ACPI and OF device ids for thw HW along with the helper
> > functions.
> >
> > Changes from v5:
> > * use struct device as a calling parameter to get_match_data() callback
> > so that we can reuse the existing OF API.
> > * revert the change on acpi_get_match_data() to V4.
> >
> > Sinan Kaya (7):
> > Documentation: DT: qcom_hidma: Bump HW revision for the bugfixed HW
> > ACPI / bus: Introduce acpi_get_match_data() function
> > device property: Introduce a common API to fetch device match data
> > OF: properties: Implement get_match_data() callback
> > ACPI: properties: Implement get_match_data() callback
> > dmaengine: qcom_hidma: Add support for the new revision
> > dmaengine: qcom_hidma: Add identity register support
>
> Sakari, can you please have a look at this series?
>
> I'm particularly interested in your opinion on patches [2-3/7] and [5/7].
Reviewed. Thanks for the heads up!
--
Sakari Ailus
e-mail: sakari.ailus@iki.fi
^ permalink raw reply
* Re: [PATCH V6 3/7] device property: Introduce a common API to fetch device match data
From: Sakari Ailus @ 2017-12-07 12:40 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
linux-arm-kernel, Greg Kroah-Hartman, Rafael J. Wysocki,
Len Brown, Mika Westerberg, Sakari Ailus, Dmitry Torokhov,
Rob Herring, Kieran Bingham, open list
In-Reply-To: <1512493493-6464-4-git-send-email-okaya@codeaurora.org>
On Tue, Dec 05, 2017 at 12:04:48PM -0500, Sinan Kaya wrote:
> @@ -101,6 +103,8 @@ struct fwnode_operations {
> (*graph_get_port_parent)(struct fwnode_handle *fwnode);
> int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode,
> struct fwnode_endpoint *endpoint);
> + void *(*get_match_data)(const struct fwnode_handle *fwnode,
> + struct device *dev);
You can make dev const, too.
--
Sakari Ailus
e-mail: sakari.ailus@iki.fi
^ permalink raw reply
* Re: [PATCH V6 4/7] OF: properties: Implement get_match_data() callback
From: Sakari Ailus @ 2017-12-07 12:38 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
linux-arm-kernel, Rob Herring, Frank Rowand, open list
In-Reply-To: <1512493493-6464-5-git-send-email-okaya@codeaurora.org>
Hi Sinan,
On Tue, Dec 05, 2017 at 12:04:49PM -0500, Sinan Kaya wrote:
> Now that we have a get_match_data() callback as part of the firmware node,
> implement the OF specific piece for it.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/of/property.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 264c355..9964169 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -981,6 +981,12 @@ static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> return 0;
> }
>
> +void *of_fwnode_get_match_data(const struct fwnode_handle *fwnode,
> + struct device *dev)
static, as Rob mentioned.
> +{
> + return (void *)of_device_get_match_data(dev);
> +}
> +
> const struct fwnode_operations of_fwnode_ops = {
> .get = of_fwnode_get,
> .put = of_fwnode_put,
> @@ -996,5 +1002,6 @@ static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
> .graph_get_port_parent = of_fwnode_graph_get_port_parent,
> .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
> + .get_match_data = of_fwnode_get_match_data,
Please arrange right after device_is_available, the same applies to the
ACPI equivalent (5th patch).
> };
> EXPORT_SYMBOL_GPL(of_fwnode_ops);
With the above changes plus the ones in my comments on 3rd patch, on
patches 3--5:
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
--
Kind regards,
Sakari Ailus
e-mail: sakari.ailus@iki.fi
^ permalink raw reply
* Re: [PATCH V6 3/7] device property: Introduce a common API to fetch device match data
From: Sakari Ailus @ 2017-12-07 12:29 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
linux-arm-kernel, Greg Kroah-Hartman, Rafael J. Wysocki,
Len Brown, Mika Westerberg, Sakari Ailus, Dmitry Torokhov,
Rob Herring, Kieran Bingham, open list
In-Reply-To: <1512493493-6464-4-git-send-email-okaya@codeaurora.org>
Hi Sinan,
Thanks for the update.
Just one small comment below.
On Tue, Dec 05, 2017 at 12:04:48PM -0500, Sinan Kaya wrote:
> There is an OF/ACPI function to obtain the driver data. We want to hide
> OF/ACPI details from the device drivers and abstract following the device
> family of functions.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/base/property.c | 6 ++++++
> include/linux/fwnode.h | 4 ++++
> include/linux/property.h | 2 ++
> 3 files changed, 12 insertions(+)
>
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 7ed99c1..65bf6f2 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1335,3 +1335,9 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
> }
> EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
> +
> +void *device_get_match_data(struct device *dev)
> +{
> + return fwnode_call_ptr_op(dev_fwnode(dev), get_match_data, dev);
> +}
> +EXPORT_SYMBOL_GPL(device_get_match_data);
> diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
> index 0c35b6c..ab9aab5 100644
> --- a/include/linux/fwnode.h
> +++ b/include/linux/fwnode.h
> @@ -15,6 +15,7 @@
> #include <linux/types.h>
>
> struct fwnode_operations;
> +struct device;
>
> struct fwnode_handle {
> struct fwnode_handle *secondary;
> @@ -66,6 +67,7 @@ struct fwnode_reference_args {
> * endpoint node.
> * @graph_get_port_parent: Return the parent node of a port node.
> * @graph_parse_endpoint: Parse endpoint for port and endpoint id.
> + * @get_match_data: Return the driver match data.
Could you arrange the new get_match_data op closer to the other ops that
don't deal with the graphs? Such as device_is_available. As the ops are
dealing generally with fwnodes, I might call this device_get_match_data to
explicitly mention it's for devices.
> */
> struct fwnode_operations {
> void (*get)(struct fwnode_handle *fwnode);
> @@ -101,6 +103,8 @@ struct fwnode_operations {
> (*graph_get_port_parent)(struct fwnode_handle *fwnode);
> int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode,
> struct fwnode_endpoint *endpoint);
> + void *(*get_match_data)(const struct fwnode_handle *fwnode,
> + struct device *dev);
Same comment about the order here.
> };
>
> #define fwnode_has_op(fwnode, op) \
> diff --git a/include/linux/property.h b/include/linux/property.h
> index 6bebee1..01fa55b 100644
> --- a/include/linux/property.h
> +++ b/include/linux/property.h
> @@ -275,6 +275,8 @@ int device_add_properties(struct device *dev,
>
> enum dev_dma_attr device_get_dma_attr(struct device *dev);
>
> +void *device_get_match_data(struct device *dev);
> +
> int device_get_phy_mode(struct device *dev);
>
> void *device_get_mac_address(struct device *dev, char *addr, int alen);
--
Kind regards,
Sakari Ailus
e-mail: sakari.ailus@iki.fi
^ permalink raw reply
* Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
From: Maxime Ripard @ 2017-12-07 12:25 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Mark Rutland, Thomas Petazzoni, Jernej Skrabec, Priit Laes,
devicetree, David Airlie, linux-kernel, dri-devel, Rob Herring,
Daniel Vetter, linux-arm-kernel, Icenowy Zheng
In-Reply-To: <CAGb2v65Voua-AjHDnCLgDOKqUeSG-yD4wuSO5-BJ230FCp4OuQ@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 6914 bytes --]
Hi,
On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote:
> > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
> > + const struct drm_encoder *encoder,
> > + bool enabled)
> > +{
> > + if (enabled) {
> > + u8 val;
> > +
> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> > + SUN4I_TCON0_LVDS_IF_EN,
> > + SUN4I_TCON0_LVDS_IF_EN);
> > +
> > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > + SUN4I_TCON0_LVDS_ANA0_C(2) |
> > + SUN4I_TCON0_LVDS_ANA0_V(3) |
> > + SUN4I_TCON0_LVDS_ANA0_PD(2) |
> > + SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> > + udelay(2);
> > +
> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > + SUN4I_TCON0_LVDS_ANA0_EN_MB,
> > + SUN4I_TCON0_LVDS_ANA0_EN_MB);
> > + udelay(2);
> > +
> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> > +
> > + if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> > + val = 7;
> > + else
> > + val = 0xf;
> > +
> > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
>
> I suggest changing the prefix of the macros of the analog bits to
> SUN6I_TCON0_*. The register definitions and sequence do not apply
> to the A10/A20. Furthermore you should add a comment saying this
> doesn't apply to the A10/A20. In the future we might want to move
> this part into a separate function, referenced by a function pointer
> from the quirks structure.
I'll change the bit field names and add a comment like you suggested.
> > + } else {
> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> > + SUN4I_TCON0_LVDS_IF_EN, 0);
> > + }
> > +}
> > +
> > void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
> > const struct drm_encoder *encoder,
> > bool enabled)
> > {
> > + bool is_lvds = false;
> > int channel;
> >
> > switch (encoder->encoder_type) {
> > + case DRM_MODE_ENCODER_LVDS:
> > + is_lvds = true;
> > + /* Fallthrough */
> > case DRM_MODE_ENCODER_NONE:
> > channel = 0;
> > break;
> > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
> > return;
> > }
> >
> > + if (is_lvds && !enabled)
> > + sun4i_tcon_lvds_set_status(tcon, encoder, false);
> > +
> > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> > SUN4I_TCON_GCTL_TCON_ENABLE,
> > enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
> >
> > + if (is_lvds && enabled)
> > + sun4i_tcon_lvds_set_status(tcon, encoder, true);
> > +
> > sun4i_tcon_channel_set_status(tcon, channel, enabled);
> > }
> >
> > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
> > }
> >
> > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> > + const struct drm_encoder *encoder,
> > + const struct drm_display_mode *mode)
> > +{
> > + unsigned int bp;
> > + u8 clk_delay;
> > + u32 reg, val = 0;
> > +
> > + tcon->dclk_min_div = 7;
> > + tcon->dclk_max_div = 7;
> > + sun4i_tcon0_mode_set_common(tcon, mode);
> > +
> > + /* Adjust clock delay */
> > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> > + SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> > +
> > + /*
> > + * This is called a backporch in the register documentation,
> > + * but it really is the back porch + hsync
> > + */
> > + bp = mode->crtc_htotal - mode->crtc_hsync_start;
> > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> > + mode->crtc_htotal, bp);
> > +
> > + /* Set horizontal display timings */
> > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> > + SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
> > + SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
> > +
> > + /*
> > + * This is called a backporch in the register documentation,
> > + * but it really is the back porch + hsync
> > + */
> > + bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> > + DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> > + mode->crtc_vtotal, bp);
> > +
> > + /* Set vertical display timings */
> > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> > + SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> > + SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
>
> Can we move the above to a common function?
Until we have DSI support figured out I'd rather not do too much of
consolidation. We know already a few things are going to change there
(like the clk_delay), but it's not clear yet how much.
> > + /* Map output pins to channel 0 */
> > + regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> > + SUN4I_TCON_GCTL_IOMAP_MASK,
> > + SUN4I_TCON_GCTL_IOMAP_TCON0);
> > +
> > + /* Enable the output on the pins */
> > + regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
>
> Is this still needed? You are no longer using the TCON LCD pins
> with LVDS.
We do. It's a separate function of the pins, but it's the same pins.
> > static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
> > .has_channel_1 = true,
> > + .has_lvds_pll = true,
>
> The A31s does not have MIPI.
I'll change that.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v2 16/19] ASoC: tlv320aic31xx: Add short circuit detection support
From: Mark Brown @ 2017-12-07 12:03 UTC (permalink / raw)
To: Andrew F. Davis
Cc: Mark Rutland, devicetree, alsa-devel, Tony Lindgren,
Liam Girdwood, linux-kernel, Rob Herring, Benoît Cousson
In-Reply-To: <fd362117-ae71-a6a2-eb43-70c2457c0a5d@ti.com>
[-- Attachment #1.1: Type: text/plain, Size: 992 bytes --]
On Wed, Dec 06, 2017 at 02:22:39PM -0600, Andrew F. Davis wrote:
> On 12/01/2017 09:32 AM, Andrew F. Davis wrote:
> >> This will report the interrupt as handled even if we didn't see an
> >> interrupt we understand which will break shared interrupt lines. At the
> >> very least we should log other interrupt sources numerically.
> > Okay, I think I can make that work by checking if no bits are set in the
> > interrupt regs and returning early if not, IRQ_NONE.
> This turned out to be more difficult than I expected, plus if I do
> handle an interrupt it doesn't mean the other device did not right? So
> this wouldn't fix shared lines as far as I can tell, but I don't
> register it as shared so this should be fine.
It'll mean that we don't offer the interrupt to anything else sharing
the line.
> As for your other suggestion of "log other interrupt sources
> numerically", could you explain this or point to an example of what you
> mean?
Just print out the bits that were set.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Marek Szyprowski @ 2017-12-07 12:01 UTC (permalink / raw)
To: Peng Fan
Cc: Peng Fan, hch, robin.murphy, gregkh, robh+dt, frowand.list, iommu,
linux-kernel, devicetree
In-Reply-To: <20171127090409.posgikgumpoq4wdm@linux-u7w5.ap.freescale.net>
Hi Peng,
On 2017-11-27 10:04, Peng Fan wrote:
> On Mon, Nov 27, 2017 at 09:44:20AM +0100, Marek Szyprowski wrote:
>> On 2017-11-27 09:37, Peng Fan wrote:
>>> On Mon, Nov 27, 2017 at 09:31:00AM +0100, Marek Szyprowski wrote:
>>>> On 2017-11-26 14:13, Peng Fan wrote:
>>>>> Invoke of_reserved_mem_device_init at dma_configure, then
>>>>> there is no need to call of_reserved_mem_device_init in device
>>>>> specific probe function.
>>>>>
>>>>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>>>> This has been already tried long time ago, without success:
>>>> http://patches.linaro.org/patch/33558/
>>> Thanks for the info. I should first search mail list before
>>> sending out patches.
>> It doesn't mean that I'm against such idea. I just pointed that I've
>> already tried. That time, however there was no dma_configure() function
>> yet, which seems to be better place for of_rmem_device_init().
>>
>> I would however always call of_dma_configure(), even when reserved mem
>> node is there. IIRC on ARM64 that function configures dma_ops, without
>> which no dma is possible at all.
> So, you prefer this?
> if (dma_dev->of_node) {
> + of_reserved_mem_device_init(dev);
> ret = of_dma_configure(dev, dma_dev->of_node);
>
> However in of_reserved_mem_device, there is also an call to
> of_dma_configure.
>
> "
> /* ensure that dma_ops is set for virtual devices
> * using reserved memory
> */
> ret = of_dma_configure(dev, np);
> "
>
> If always call of_dma_configure, of_dma_configure maybe called twice.
Right, I forgot about this.
> I just checked more. of_reserved_mem_device_init only handle the first
> memory-region. To nodes which have multiple memory-region, seems 2nd and etc
> could not be handled, such as drivers/media/platform/s5p-mfc/s5p_mfc.c.
Well, maybe automatic assignment should be done only when there is only
one reserved region set? In case more than one region assigned to a device,
the driver has to create virtual child devices and configure DMA for them
to be able to let dma-mapping API to use those reserved regions. It looks
that the call to of_dma_configure(dev, np) can be moved back to the driver
(it was not possible at the time that code was merged due to missing
export symbols).
Configuring more than one reserved memory region for given device might
then moved to some helper function to have a common code for that across
the drivers.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH v2] dt-bindings: mfd: mc13xxx: Add the unit address to sysled
From: Fabio Estevam @ 2017-12-07 12:00 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA,
Fabio Estevam
From: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
As the 'reg' property is mandatory in the subnodes, improve the
example by adding the unit address to the sysled node.
This prevents the following build warning with W=1:
Node /soc/aips@70000000/spba@70000000/ecspi@70010000/pmic@0/leds/sysled has a reg or ranges property, but no unit name
Signed-off-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
Reviewed-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes since v1:
- Use the correct name (sysled_ in the warning message (Rob)
Documentation/devicetree/bindings/mfd/mc13xxx.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
index ac235fe..8261ea7 100644
--- a/Documentation/devicetree/bindings/mfd/mc13xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
@@ -130,7 +130,7 @@ ecspi@70010000 { /* ECSPI1 */
#size-cells = <0>;
led-control = <0x000 0x000 0x0e0 0x000>;
- sysled {
+ sysled@3 {
reg = <3>;
label = "system:red:live";
linux,default-trigger = "heartbeat";
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v2 0/8] arm64: Add initial Actions Semi S700 and CubieBoard7 support
From: Andreas Färber @ 2017-12-07 11:30 UTC (permalink / raw)
To: Daniel Lezcano, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Jeff Chen, Ahha Lee
Cc: Thomas Liau, 张东风, 刘炜,
张天益, 梅利,
support-om/0PrzuAKC1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Gleixner
In-Reply-To: <e43387f9-60a6-129b-d0e9-dff6d0df301a-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Am 07.12.2017 um 10:20 schrieb Daniel Lezcano:
> On 14/11/2017 00:34, Andreas Färber wrote:
>> Hello,
>>
>> This series prepares the Actions Semi S700 SoC and Cubietech CubieBoard7.
>> It boots equally far as the S900 based Bubblegum-96 these patches are based on,
>> i.e. into an initrd with serial and all four cores up.
>>
>> v2 modifies the clocksource driver patches and adds SPS patches.
>>
>> Not having succeeded to replace the bootloader on eMMC or to try
>> booting from SD, the only working way I've found to boot mainline kernels
>> appears to be booting into Android, then issuing "reboot bootloader". U-Boot
>> is lacking the saveenv command, so it wasn't possible to change the bootdelay
>> to facilitate this.
>
> Is it possible this change fixes your issue ?
>
> http://git.denx.de/?p=u-boot.git;a=commit;h=c9e87ba66540cf72c164674a71af43853d087ba8
Actions is not yet supported in mainline U-Boot, and S500 boards did not
have a problem there. The saveenv command is simply not enabled in this
config deployed by Cubietech. Since I have not succeeded in getting a
self-built U-Boot booted from SD, I cannot test individual commits on
top either.
Maybe Cubietech or Actions can comment?
Regards,
Andreas
>> Cf. https://en.opensuse.org/HCL:CubieBoard7
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] arm64: allwinner: a64: orangepi-zero-plus2: add usb otg
From: Jagan Teki @ 2017-12-07 11:05 UTC (permalink / raw)
To: Maxime Ripard
Cc: Chen-Yu Tsai, Icenowy Zheng, Rob Herring, Mark Rutland,
Catalin Marinas, Will Deacon, Michael Trimarchi,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Jagan Teki
Add usb otg support for orangepi-zero-plus2 board:
- Add usb_otg node with dr_mode as 'otg'
- USB0-IDDET connected to PA21
- VBUS connected through DCIN which always on
Tested mass storage function.
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Note: Anyone please check vbus connection [1]
Since it is connected through DCIN of vcc-5v, I've added vcc-5v0
regulator for the same and attached to usb0_vbus-supply but it is
disabling during kernel boot.
[ 1.887854] vcc5v0: disabling
[1] http://linux-sunxi.org/File:ORANGE_PI-ZERO-PLUS2_V1_0.pdf
.../dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
index d349399..7f298ee 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
@@ -73,6 +73,10 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>;
@@ -111,6 +115,10 @@
status = "okay";
};
+&ohci0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -122,3 +130,13 @@
pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
status = "okay";
};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 0 21 GPIO_ACTIVE_HIGH>; /* PA21 */
+ status = "okay";
+};
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v3 09/15] drm/sun4i: Add A83T support
From: Maxime Ripard @ 2017-12-07 10:55 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Mark Rutland, Thomas Petazzoni, plaes, devicetree, David Airlie,
linux-kernel, dri-devel, Chen-Yu Tsai, Rob Herring, Daniel Vetter,
linux-arm-kernel, icenowy
In-Reply-To: <1729482.Mgh5nx8BIs@jernej-laptop>
[-- Attachment #1.1: Type: text/plain, Size: 3853 bytes --]
Hi,
On Wed, Dec 06, 2017 at 05:37:47PM +0100, Jernej Škrabec wrote:
> Hi,
>
> Dne torek, 05. december 2017 ob 16:42:55 CET je Jernej Škrabec napisal(a):
> > Hi Maxime,
> >
> > Dne torek, 05. december 2017 ob 16:10:21 CET je Maxime Ripard napisal(a):
> > > Add support for the A83T display pipeline.
> > >
> > > Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > ---
> > >
> > > drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
> > > drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
> > > drivers/gpu/drm/sun4i/sun8i_mixer.c | 9 +++++++++
> > > 3 files changed, 15 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > b/drivers/gpu/drm/sun4i/sun4i_drv.c index 49215d91c853..6f5e721b545e
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > @@ -347,6 +347,7 @@ static const struct of_device_id sun4i_drv_of_table[]
> > > =
> > > { { .compatible = "allwinner,sun6i-a31s-display-engine" },
> > >
> > > { .compatible = "allwinner,sun7i-a20-display-engine" },
> > > { .compatible = "allwinner,sun8i-a33-display-engine" },
> > >
> > > + { .compatible = "allwinner,sun8i-a83t-display-engine" },
> > >
> > > { .compatible = "allwinner,sun8i-v3s-display-engine" },
> > > { }
> > >
> > > };
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 92f4738101e6..9b757450555f
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > @@ -1132,6 +1132,10 @@ static const struct sun4i_tcon_quirks
> > > sun8i_a33_quirks = { .has_lvds_pll = true,
> > >
> > > };
> > >
> > > +static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
> > > + /* nothing is supported */
> > > +};
> > > +
> > >
> > > static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
> > >
> > > /* nothing is supported */
> > >
> > > };
> > >
> > > @@ -1144,6 +1148,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
> > >
> > > { .compatible = "allwinner,sun6i-a31s-tcon", .data =
> &sun6i_a31s_quirks
> > > },
> > >
> > > { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, {
> > > .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, +
> {
> > > .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data =
> > > &sun8i_a83t_lcd_quirks }, { .compatible = "allwinner,sun8i-v3s-tcon",
> > > .data
> > > = &sun8i_v3s_quirks }, { }
> > >
> > > };
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > b/drivers/gpu/drm/sun4i/sun8i_mixer.c index ff235e3228ce..6829bec4ba68
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > @@ -477,6 +477,11 @@ static int sun8i_mixer_remove(struct platform_device
> > > *pdev) return 0;
> > >
> > > }
> > >
> > > +static const struct sun8i_mixer_cfg sun8i_a83t_mixer_cfg = {
> > > + .vi_num = 1,
> > > + .ui_num = 3,
> > > +};
> > > +
> >
> > I think you should expand that structure with:
> > .ccsc = 0,
> > .scaler_mask = 0xf,
> > .mod_rate = 150000000,
>
> I guess you could set higher clock if CLK_SET_RATE_PARENT flag is set to de_clk
> in A83T CCU driver. BSP sets it to 500 MHz, which is a bit high...
Actually, I didn't have to change the rate used by default, so it's
not clear what it should be on the A83T.
And yeah, I'd like to avoid setting it at 500MHz without any
particular reason. The A83T draws way to much power already without
making it worse.
I'll add the CCSC and scaler_mask fields.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v5 08/16] arm64: Add vmap_stack header file
From: Mark Rutland @ 2017-12-07 10:54 UTC (permalink / raw)
To: James Morse
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
devicetree-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Catalin Marinas,
Rob Herring, Marc Zyngier, Christoffer Dall, Lorenzo Pieralisi,
Loc Ho, Heyi Guo
In-Reply-To: <20171206190142.9246-9-james.morse-5wv7dgnIgG8@public.gmane.org>
Hi James,
On Wed, Dec 06, 2017 at 07:01:34PM +0000, James Morse wrote:
> Today the arm64 arch code allocates an extra IRQ stack per-cpu. If we
> also have SDEI and VMAP stacks we need two extra per-cpu VMAP stacks.
>
> Move the VMAP stack allocation out to a helper in a new header file.
> This avoids missing THREADINFO_GFP, or getting the all-important alignment
> wrong.
>
> Signed-off-by: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>
> Reviewed-by: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> ---
> Changes since v4:
> * Added gfp.h include
>
> Changes since v3:
> * Added BUILD_BUG() instead of a spooky link error
>
> arch/arm64/include/asm/vmap_stack.h | 26 ++++++++++++++++++++++++++
> arch/arm64/kernel/irq.c | 13 ++-----------
> 2 files changed, 28 insertions(+), 11 deletions(-)
> create mode 100644 arch/arm64/include/asm/vmap_stack.h
>
> diff --git a/arch/arm64/include/asm/vmap_stack.h b/arch/arm64/include/asm/vmap_stack.h
> new file mode 100644
> index 000000000000..5465e4e65987
> --- /dev/null
> +++ b/arch/arm64/include/asm/vmap_stack.h
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2017 Arm Ltd.
> +#ifndef __ASM_VMAP_STACK_H
> +#define __ASM_VMAP_STACK_H
> +
> +#include <linux/gfp.h>
> +#include <linux/vmalloc.h>
> +#include <asm/memory.h>
> +#include <asm/pgtable.h>
> +#include <asm/thread_info.h>
I think we also need:
#include <linux/bug.h> // for BUILD_BUG_ON()
#incldue <linux/kconfig.h> // for IS_ENABLED()
Otherwise, this looks good to me. With those includes folded in:
Reviewed-by: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Thanks,
Mark.
> +
> +/*
> + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd
> + * stacks need to have the same alignment.
> + */
> +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node)
> +{
> + BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK));
> +
> + return __vmalloc_node_range(stack_size, THREAD_ALIGN,
> + VMALLOC_START, VMALLOC_END,
> + THREADINFO_GFP, PAGE_KERNEL, 0, node,
> + __builtin_return_address(0));
> +}
> +
> +#endif /* __ASM_VMAP_STACK_H */
> diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
> index 713561e5bcab..60e5fc661f74 100644
> --- a/arch/arm64/kernel/irq.c
> +++ b/arch/arm64/kernel/irq.c
> @@ -29,6 +29,7 @@
> #include <linux/irqchip.h>
> #include <linux/seq_file.h>
> #include <linux/vmalloc.h>
> +#include <asm/vmap_stack.h>
>
> unsigned long irq_err_count;
>
> @@ -58,17 +59,7 @@ static void init_irq_stacks(void)
> unsigned long *p;
>
> for_each_possible_cpu(cpu) {
> - /*
> - * To ensure that VMAP'd stack overflow detection works
> - * correctly, the IRQ stacks need to have the same
> - * alignment as other stacks.
> - */
> - p = __vmalloc_node_range(IRQ_STACK_SIZE, THREAD_ALIGN,
> - VMALLOC_START, VMALLOC_END,
> - THREADINFO_GFP, PAGE_KERNEL,
> - 0, cpu_to_node(cpu),
> - __builtin_return_address(0));
> -
> + p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu));
> per_cpu(irq_stack_ptr, cpu) = p;
> }
> }
> --
> 2.15.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v6 03/17] mfd: madera: Add common support for Cirrus Logic Madera codecs
From: Richard Fitzgerald @ 2017-12-07 10:52 UTC (permalink / raw)
To: Linus Walleij
Cc: Alexandre Courbot, alsa-devel, Jason Cooper,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list:WOLFSON MICROELECTRONICS DRIVERS,
linux-kernel@vger.kernel.org, Rob Herring, linux-gpio, Mark Brown,
Thomas Gleixner, Lee Jones, Charles Keepax, Nikesh Oswal
In-Reply-To: <CACRpkdb_i4k3F0fmDbQciPYTBUCcfpFkqM=5e3gr75-X51TTkg@mail.gmail.com>
On 07/12/17 08:54, Linus Walleij wrote:
> On Mon, Dec 4, 2017 at 10:47 AM, Richard Fitzgerald
> <rf@opensource.wolfsonmicro.com> wrote:
>> On 02/12/17 12:10, Linus Walleij wrote:
>>> On Wed, Nov 29, 2017 at 12:36 PM, Richard Fitzgerald
>>> <rf@opensource.wolfsonmicro.com> wrote:
>>>> On 29/11/17 10:18, Linus Walleij wrote:
>>>>> On Thu, Nov 23, 2017 at 6:13 PM, Richard Fitzgerald
>>>>> <rf@opensource.wolfsonmicro.com> wrote:
>>>>>
>>>>>> +config MFD_MADERA_I2C
>>>>>> + bool "Cirrus Logic Madera codecs with I2C"
>>>>>> + select MFD_MADERA
>>>>>> + select REGMAP_I2C
>>>>>> + depends on I2C
>>>>>> + depends on PINCTRL
>>>>>> + help
>>>>>> + Support for the Cirrus Logic Madera platform audio SoC
>>>>>> + core functionality controlled via I2C.
>>>>>> +
>>>>>> +config MFD_MADERA_SPI
>>>>>> + bool "Cirrus Logic Madera codecs with SPI"
>>>>>> + select MFD_MADERA
>>>>>> + select REGMAP_SPI
>>>>>> + depends on SPI_MASTER
>>>>>> + depends on PINCTRL
>>>>>> + help
>>>>>> + Support for the Cirrus Logic Madera platform audio SoC
>>>>>> + core functionality controlled via SPI.
>>>>>
>>>>>
>>>>>
>>>>> Why do the I2C and SPI subdrivers depend on PINCTRL?
>>>>>
>>>>> They sure don't seem to be using any pinctrl-specific APIs.
>>>>>
>>>>
>>>> They require PINCTRL even if they don't call any functions on it because
>>>> the
>>>> chip won't work correctly if there isn't a PINCTRL driver to apply the
>>>> correct pinmux configuration.
>>>
>>>
>>> Apply the configuration to what? Sorry I don't get it.
>>>
>>> You can't be referring to the internal pin controller of the Madera, since
>>
>> Yes I am
>
> You are saying that the I2C and SPI interface to the Madera codec
> depends on pin control.
>
> It does not.
>
> You can most certainly talk I2C and SPI to the coded without any
> pin control. Probably the MFD driver can come up without it.
>
> If what you want is unconditional pin control enabled for this circuit,
> then have MFD_MADERA select PINCTRL.
>
>>> that has to come up before its pin controller can even be communicated
>>> with.
>>
>>
>> So?
>>
>> The MFD driver powers up the chip before registering child drivers.
>
> Including the pin controller. You just confirmed what I said: the
> I2C and SPI interfaces do not require pin control to talk to the
> chip.
>
>> Also that's not entirely relevant, the pinctrl settings can still be written
>> with the chip off because they will go into the regmap cache and be applied
>> when the chip is next resumed.
>
> You still have the dependencies wrong.
>
> Yours,
> Linus Walleij
>
So the short version of this email thread is that it should be "select
PINCTRL" ?
^ permalink raw reply
* Re: [PATCH v2 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
From: Baolin Wang @ 2017-12-07 10:52 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Baolin Wang, Thomas Gleixner, Rob Herring, Mark Rutland, DTML,
LKML, Mark Brown
In-Reply-To: <ebc1606c-d3d4-e784-87ff-c8d8ba3a80df-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Daniel,
On 7 December 2017 at 18:44, Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On 28/11/2017 03:45, Baolin Wang wrote:
>> The Spreadtrum SC9860 platform will use the architected timers as local
>> clock events, but we also need a broadcast timer device to wakeup the
>> cpus when the cpus are in sleep mode.
>>
>> Thus this patch registers the timer0 to be a broadcast timer supporting
>> periodic and oneshot events.
>
> This changelog is inadequate. It is pointless to explain why you submit
> this driver.
>
> It would be much more interesting to describe the timer internals.
Sure.
>
>> Signed-off-by: Baolin Wang <baolin.wang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
>> ---
>> Changes since v1:
>> - Change to 32bit counter to avoid build warning.
>> ---
>> drivers/clocksource/Kconfig | 8 ++
>> drivers/clocksource/Makefile | 1 +
>> drivers/clocksource/sprd-timer.c | 211 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 220 insertions(+)
>> create mode 100644 drivers/clocksource/sprd-timer.c
>
> Even if it is not a general rule, can you rename this driver to
> timer-sprd.c ? I would like little by little to converge all the timer
> names to this pattern.
OK.
>
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index c729a88..48c8702 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -441,6 +441,14 @@ config MTK_TIMER
>> help
>> Support for Mediatek timer driver.
>>
>> +config SPRD_TIMER
>> + bool "Spreadtrum timer driver"
>> + depends on GENERIC_CLOCKEVENTS
>
> Remove GENERIC_CLOCKEVENTS because of:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/clocksource/Kconfig#n2
Yes, here GENERIC_CLOCKEVENTS is redundant.
>
>> + depends on ARCH_SPRD || COMPILE_TEST
>
> Remove the dependency on ARCH_SPRD, the arch's Kconfig must select
> SPRD_TIMER.
>
> Move the COMPILE_TEST as the other drivers.
OK.
>
> bool "Spreadtrum timer driver" if COMPILE_TEST
>
>> + select TIMER_O> + help
>> + Enables the support for the Spreadtrum timer driver.
>> +
>> config SYS_SUPPORTS_SH_MTU2
>> bool
>>
>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>> index 72711f1..62bf264 100644
>> --- a/drivers/clocksource/Makefile
>> +++ b/drivers/clocksource/Makefile
>> @@ -54,6 +54,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
>> obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
>> obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
>> obj-$(CONFIG_OWL_TIMER) += owl-timer.o
>> +obj-$(CONFIG_SPRD_TIMER) += sprd-timer.o
>>
>> obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
>> obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
>> diff --git a/drivers/clocksource/sprd-timer.c b/drivers/clocksource/sprd-timer.c
>> new file mode 100644
>> index 0000000..e90f948
>> --- /dev/null
>> +++ b/drivers/clocksource/sprd-timer.c
>> @@ -0,0 +1,211 @@
>> +/*
>> + * Copyright (C) 2017 Spreadtrum Communications Inc.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0
>> + */
>
> Please fix the above with proper format (one example in timer-of.c).
OK.
>
>> +#include <linux/clocksource.h>
>> +#include <linux/clockchips.h>
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/sched_clock.h>
>
> Are you sure you need sched_clock and clocksource ?
Sorry, I forgot to remove them.
>
>> +#include <linux/slab.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>
> These headers won't be needed anymore when using the timer-of API (see
> the init function comment below).
OK.
>
>> +#define TIMER_NAME "sprd_timer"
>> +
>> +#define TIMER_LOAD_LO 0x0
>> +#define TIMER_LOAD_HI 0x4
>> +#define TIMER_VALUE_LO 0x8
>> +#define TIMER_VALUE_HI 0xc
>> +
>> +#define TIMER_CTL 0x10
>> +#define TIMER_CTL_PERIOD_MODE BIT(0)
>> +#define TIMER_CTL_ENABLE BIT(1)
>> +#define TIMER_CTL_64BIT_WIDTH BIT(16)
>> +
>> +#define TIMER_INT 0x14
>> +#define TIMER_INT_EN BIT(0)
>> +#define TIMER_INT_RAW_STS BIT(1)
>> +#define TIMER_INT_MASK_STS BIT(2)
>> +#define TIMER_INT_CLR BIT(3)
>> +
>> +#define TIMER_VALUE_SHDW_LO 0x18
>> +#define TIMER_VALUE_SHDW_HI 0x1c
>> +
>> +#define TIMER_VALUE_LO_MASK GENMASK(31, 0)
>> +
>> +struct sprd_timer_device {
>> + struct clock_event_device ce;
>> + void __iomem *base;
>> + u32 freq;
>> + int irq;
>> +};
>> +
>> +static inline struct sprd_timer_device *
>> +to_sprd_timer(struct clock_event_device *c)
>> +{
>> + return container_of(c, struct sprd_timer_device, ce);
>> +}
>> +
>> +static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag)
>> +{
>> + u32 val = readl_relaxed(timer->base + TIMER_CTL);
>> +
>> + val |= TIMER_CTL_ENABLE;
>> + if (flag & TIMER_CTL_64BIT_WIDTH)
>> + val |= TIMER_CTL_64BIT_WIDTH;
>> + else
>> + val &= ~TIMER_CTL_64BIT_WIDTH;
>> +
>> + if (flag & TIMER_CTL_PERIOD_MODE)
>> + val |= TIMER_CTL_PERIOD_MODE;
>> + else
>> + val &= ~TIMER_CTL_PERIOD_MODE;
>> +
>> + writel_relaxed(val, timer->base + TIMER_CTL);
>> +}
>> +
>> +static void sprd_timer_disable(struct sprd_timer_device *timer)
>> +{
>> + u32 val = readl_relaxed(timer->base + TIMER_CTL);
>> +
>> + val &= ~TIMER_CTL_ENABLE;
>> + writel_relaxed(val, timer->base + TIMER_CTL);
>> +}
>> +
>> +static void sprd_timer_update_counter(struct sprd_timer_device *timer,
>> + unsigned long cycles)
>> +{
>> + writel_relaxed(cycles & TIMER_VALUE_LO_MASK,
>> + timer->base + TIMER_LOAD_LO);
>> + writel_relaxed(0, timer->base + TIMER_LOAD_HI);
>> +}
>> +
>> +static void sprd_timer_enable_interrupt(struct sprd_timer_device *timer)
>> +{
>> + writel_relaxed(TIMER_INT_EN, timer->base + TIMER_INT);
>> +}
>> +
>> +static void sprd_timer_clear_interrupt(struct sprd_timer_device *timer)
>> +{
>> + u32 val = readl_relaxed(timer->base + TIMER_INT);
>> +
>> + val |= TIMER_INT_CLR;
>> + writel_relaxed(val, timer->base + TIMER_INT);
>> +}
>> +
>> +static int sprd_timer_set_next_event(unsigned long cycles,
>> + struct clock_event_device *ce)
>> +{
>> + struct sprd_timer_device *timer = to_sprd_timer(ce);
>> +
>> + sprd_timer_disable(timer);
>> + sprd_timer_update_counter(timer, cycles);
>> + sprd_timer_enable(timer, 0);
>> +
>> + return 0;
>> +}
>> +
>> +static int sprd_timer_set_periodic(struct clock_event_device *ce)
>> +{
>> + struct sprd_timer_device *timer = to_sprd_timer(ce);
>> + unsigned long cycles = DIV_ROUND_UP(timer->freq, HZ);
>> +
>> + sprd_timer_disable(timer);
>> + sprd_timer_update_counter(timer, cycles);
>> + sprd_timer_enable(timer, TIMER_CTL_PERIOD_MODE);
>> +
>> + return 0;
>> +}
>> +
>> +static int sprd_timer_shutdown(struct clock_event_device *ce)
>> +{
>> + struct sprd_timer_device *timer = to_sprd_timer(ce);
>> +
>> + sprd_timer_disable(timer);
>> + return 0;
>> +}
>> +
>> +static irqreturn_t sprd_timer_interrupt(int irq, void *dev_id)
>> +{
>> + struct sprd_timer_device *timer = dev_id;
>> +
>> + sprd_timer_clear_interrupt(timer);
>> +
>> + if (clockevent_state_oneshot(&timer->ce))
>> + sprd_timer_disable(timer);
>> +
>> + timer->ce.event_handler(&timer->ce);
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static void __init sprd_timer_clkevt_init(struct sprd_timer_device *timer)
>> +{
>> + timer->ce.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
>> + CLOCK_EVT_FEAT_ONESHOT;
>> + timer->ce.set_next_event = sprd_timer_set_next_event;
>> + timer->ce.set_state_periodic = sprd_timer_set_periodic;
>> + timer->ce.set_state_shutdown = sprd_timer_shutdown;
>> + timer->ce.name = TIMER_NAME;
>> + timer->ce.rating = 300;
>> + timer->ce.irq = timer->irq;
>> + timer->ce.cpumask = cpu_possible_mask;
>> +
>> + sprd_timer_enable_interrupt(timer);
>> + clockevents_config_and_register(&timer->ce, timer->freq, 1, UINT_MAX);
>> +}
>> +
>> +static int __init sprd_timer_init(struct device_node *np)
>> +{
>> + struct sprd_timer_device *timer;
>> + int ret;
>> +
>> + timer = kzalloc(sizeof(*timer), GFP_KERNEL);
>> + if (!timer)
>> + return -ENOMEM;
>> +
>> + ret = of_property_read_u32(np, "clock-frequency", &timer->freq);
>> + if (ret) {
>> + pr_err("failed to get clock frequency\n");
>> + goto err_freq;
>> + }
>> +
>> + timer->base = of_iomap(np, 0);
>> + if (!timer->base) {
>> + pr_err("%s: unable to map resource\n", np->name);
>> + ret = -ENXIO;
>> + goto err_freq;
>> + }
>> +
>> + timer->irq = irq_of_parse_and_map(np, 0);
>> + if (timer->irq < 0) {
>> + pr_crit("%s: unable to parse timer irq\n", np->name);
>> + ret = timer->irq;
>> + goto err_map_irq;
>> + }
>> +
>> + ret = request_irq(timer->irq, sprd_timer_interrupt, IRQF_TIMER,
>> + TIMER_NAME, timer);
>> + if (ret) {
>> + pr_err("failed to setup irq %d\n", timer->irq);
>> + goto err_request_irq;
>> + }
>> + sprd_timer_clkevt_init(timer);
>
> Please use the timer-of API, that will save you all these operations and
> checks.
>
> One example at:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/sun4i_timer.c#n143
>
> And then use the function:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/sun4i_timer.c#n174
>
I missed timer-of APIs, and I will check it and use timer-of APIs.
Really appreciated for your useful comments.
--
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox