diff options
Diffstat (limited to 'drivers')
49 files changed, 3713 insertions, 567 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e2d9bd760c84..bf7d540d6965 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -31,22 +31,12 @@ config COMMON_CLK_WM831X source "drivers/clk/versatile/Kconfig" -config COMMON_CLK_MAX_GEN - bool - config COMMON_CLK_MAX77686 - tristate "Clock driver for Maxim 77686 MFD" - depends on MFD_MAX77686 - select COMMON_CLK_MAX_GEN - ---help--- - This driver supports Maxim 77686 crystal oscillator clock. - -config COMMON_CLK_MAX77802 - tristate "Clock driver for Maxim 77802 PMIC" - depends on MFD_MAX77686 - select COMMON_CLK_MAX_GEN + tristate "Clock driver for Maxim 77620/77686/77802 MFD" + depends on MFD_MAX77686 || MFD_MAX77620 ---help--- - This driver supports Maxim 77802 crystal oscillator clock. + This driver supports Maxim 77620/77686/77802 crystal oscillator + clock. config COMMON_CLK_RK808 tristate "Clock driver for RK808/RK818" @@ -210,6 +200,7 @@ config COMMON_CLK_OXNAS source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" +source "drivers/clk/mediatek/Kconfig" source "drivers/clk/meson/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3b6f9cf3464a..e775a836247c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,9 +27,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o -obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o -obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o diff --git a/drivers/clk/axis/clk-artpec6.c b/drivers/clk/axis/clk-artpec6.c index ffc988b098e4..da1a073c2236 100644 --- a/drivers/clk/axis/clk-artpec6.c +++ b/drivers/clk/axis/clk-artpec6.c @@ -113,8 +113,8 @@ static void of_artpec6_clkctrl_setup(struct device_node *np) of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data); } -CLK_OF_DECLARE(artpec6_clkctrl, "axis,artpec6-clkctrl", - of_artpec6_clkctrl_setup); +CLK_OF_DECLARE_DRIVER(artpec6_clkctrl, "axis,artpec6-clkctrl", + of_artpec6_clkctrl_setup); static int artpec6_clkctrl_probe(struct platform_device *pdev) { diff --git a/drivers/clk/berlin/berlin2-avpll.c b/drivers/clk/berlin/berlin2-avpll.c index fd0f26c38465..cfcae468e989 100644 --- a/drivers/clk/berlin/berlin2-avpll.c +++ b/drivers/clk/berlin/berlin2-avpll.c @@ -188,7 +188,7 @@ static const struct clk_ops berlin2_avpll_vco_ops = { .recalc_rate = berlin2_avpll_vco_recalc_rate, }; -struct clk * __init berlin2_avpll_vco_register(void __iomem *base, +int __init berlin2_avpll_vco_register(void __iomem *base, const char *name, const char *parent_name, u8 vco_flags, unsigned long flags) { @@ -197,7 +197,7 @@ struct clk * __init berlin2_avpll_vco_register(void __iomem *base, vco = kzalloc(sizeof(*vco), GFP_KERNEL); if (!vco) - return ERR_PTR(-ENOMEM); + return -ENOMEM; vco->base = base; vco->flags = vco_flags; @@ -208,7 +208,7 @@ struct clk * __init berlin2_avpll_vco_register(void __iomem *base, init.num_parents = 1; init.flags = flags; - return clk_register(NULL, &vco->hw); + return clk_hw_register(NULL, &vco->hw); } struct berlin2_avpll_channel { @@ -364,7 +364,7 @@ static const struct clk_ops berlin2_avpll_channel_ops = { */ static const u8 quirk_index[] __initconst = { 0, 6, 5, 4, 3, 2, 1, 7 }; -struct clk * __init berlin2_avpll_channel_register(void __iomem *base, +int __init berlin2_avpll_channel_register(void __iomem *base, const char *name, u8 index, const char *parent_name, u8 ch_flags, unsigned long flags) { @@ -373,7 +373,7 @@ struct clk * __init berlin2_avpll_channel_register(void __iomem *base, ch = kzalloc(sizeof(*ch), GFP_KERNEL); if (!ch) - return ERR_PTR(-ENOMEM); + return -ENOMEM; ch->base = base; if (ch_flags & BERLIN2_AVPLL_SCRAMBLE_QUIRK) @@ -389,5 +389,5 @@ struct clk * __init berlin2_avpll_channel_register(void __iomem *base, init.num_parents = 1; init.flags = flags; - return clk_register(NULL, &ch->hw); + return clk_hw_register(NULL, &ch->hw); } diff --git a/drivers/clk/berlin/berlin2-avpll.h b/drivers/clk/berlin/berlin2-avpll.h index a37f5068d299..17e311153b42 100644 --- a/drivers/clk/berlin/berlin2-avpll.h +++ b/drivers/clk/berlin/berlin2-avpll.h @@ -19,17 +19,13 @@ #ifndef __BERLIN2_AVPLL_H #define __BERLIN2_AVPLL_H -struct clk; - #define BERLIN2_AVPLL_BIT_QUIRK BIT(0) #define BERLIN2_AVPLL_SCRAMBLE_QUIRK BIT(1) -struct clk * __init -berlin2_avpll_vco_register(void __iomem *base, const char *name, +int berlin2_avpll_vco_register(void __iomem *base, const char *name, const char *parent_name, u8 vco_flags, unsigned long flags); -struct clk * __init -berlin2_avpll_channel_register(void __iomem *base, const char *name, +int berlin2_avpll_channel_register(void __iomem *base, const char *name, u8 index, const char *parent_name, u8 ch_flags, unsigned long flags); diff --git a/drivers/clk/berlin/berlin2-div.c b/drivers/clk/berlin/berlin2-div.c index 81ff97f8aa0b..41ab2d392c57 100644 --- a/drivers/clk/berlin/berlin2-div.c +++ b/drivers/clk/berlin/berlin2-div.c @@ -234,7 +234,7 @@ static const struct clk_ops berlin2_div_mux_ops = { .get_parent = berlin2_div_get_parent, }; -struct clk * __init +struct clk_hw * __init berlin2_div_register(const struct berlin2_div_map *map, void __iomem *base, const char *name, u8 div_flags, const char **parent_names, int num_parents, @@ -259,7 +259,7 @@ berlin2_div_register(const struct berlin2_div_map *map, if ((div_flags & BERLIN2_DIV_HAS_MUX) == 0) mux_ops = NULL; - return clk_register_composite(NULL, name, parent_names, num_parents, + return clk_hw_register_composite(NULL, name, parent_names, num_parents, &div->hw, mux_ops, &div->hw, rate_ops, &div->hw, gate_ops, flags); } diff --git a/drivers/clk/berlin/berlin2-div.h b/drivers/clk/berlin/berlin2-div.h index 15e3384f3116..e835ddf8374a 100644 --- a/drivers/clk/berlin/berlin2-div.h +++ b/drivers/clk/berlin/berlin2-div.h @@ -19,7 +19,7 @@ #ifndef __BERLIN2_DIV_H #define __BERLIN2_DIV_H -struct clk; +struct clk_hw; #define BERLIN2_DIV_HAS_GATE BIT(0) #define BERLIN2_DIV_HAS_MUX BIT(1) @@ -80,7 +80,7 @@ struct berlin2_div_data { u8 div_flags; }; -struct clk * __init +struct clk_hw * berlin2_div_register(const struct berlin2_div_map *map, void __iomem *base, const char *name, u8 div_flags, const char **parent_names, int num_parents, diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c index 1c2294d3ba85..4ffbe80f6323 100644 --- a/drivers/clk/berlin/berlin2-pll.c +++ b/drivers/clk/berlin/berlin2-pll.c @@ -84,7 +84,7 @@ static const struct clk_ops berlin2_pll_ops = { .recalc_rate = berlin2_pll_recalc_rate, }; -struct clk * __init +int __init berlin2_pll_register(const struct berlin2_pll_map *map, void __iomem *base, const char *name, const char *parent_name, unsigned long flags) @@ -94,7 +94,7 @@ berlin2_pll_register(const struct berlin2_pll_map *map, pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) - return ERR_PTR(-ENOMEM); + return -ENOMEM; /* copy pll_map to allow __initconst */ memcpy(&pll->map, map, sizeof(*map)); @@ -106,5 +106,5 @@ berlin2_pll_register(const struct berlin2_pll_map *map, init.num_parents = 1; init.flags = flags; - return clk_register(NULL, &pll->hw); + return clk_hw_register(NULL, &pll->hw); } diff --git a/drivers/clk/berlin/berlin2-pll.h b/drivers/clk/berlin/berlin2-pll.h index 8831ce27ac1e..583e024b9bed 100644 --- a/drivers/clk/berlin/berlin2-pll.h +++ b/drivers/clk/berlin/berlin2-pll.h @@ -19,8 +19,6 @@ #ifndef __BERLIN2_PLL_H #define __BERLIN2_PLL_H -struct clk; - struct berlin2_pll_map { const u8 vcodiv[16]; u8 mult; @@ -29,9 +27,8 @@ struct berlin2_pll_map { u8 divsel_shift; }; -struct clk * __init -berlin2_pll_register(const struct berlin2_pll_map *map, - void __iomem *base, const char *name, - const char *parent_name, unsigned long flags); +int berlin2_pll_register(const struct berlin2_pll_map *map, + void __iomem *base, const char *name, + const char *parent_name, unsigned long flags); #endif /* __BERLIN2_PLL_H */ diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c index 23e0e3be6c37..edf3b96b3b73 100644 --- a/drivers/clk/berlin/bg2.c +++ b/drivers/clk/berlin/bg2.c @@ -92,8 +92,7 @@ */ #define MAX_CLKS 41 -static struct clk *clks[MAX_CLKS]; -static struct clk_onecell_data clk_data; +static struct clk_hw_onecell_data *clk_data; static DEFINE_SPINLOCK(lock); static void __iomem *gbase; @@ -505,8 +504,17 @@ static void __init berlin2_clock_setup(struct device_node *np) struct device_node *parent_np = of_get_parent(np); const char *parent_names[9]; struct clk *clk; + struct clk_hw *hw; + struct clk_hw **hws; u8 avpll_flags = 0; - int n; + int n, ret; + + clk_data = kzalloc(sizeof(*clk_data) + + sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL); + if (!clk_data) + return; + clk_data->num = MAX_CLKS; + hws = clk_data->hws; gbase = of_iomap(parent_np, 0); if (!gbase) @@ -526,118 +534,118 @@ static void __init berlin2_clock_setup(struct device_node *np) } /* simple register PLLs */ - clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0, + ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0, clk_names[SYSPLL], clk_names[REFCLK], 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; - clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0, + ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0, clk_names[MEMPLL], clk_names[REFCLK], 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; - clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0, + ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0, clk_names[CPUPLL], clk_names[REFCLK], 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; if (of_device_is_compatible(np, "marvell,berlin2-global-register")) avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK; /* audio/video VCOs */ - clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA", + ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA", clk_names[REFCLK], avpll_flags, 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; for (n = 0; n < 8; n++) { - clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0, + ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0, clk_names[AVPLL_A1 + n], n, "avpll_vcoA", avpll_flags, 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; } - clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB", + ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB", clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; for (n = 0; n < 8; n++) { - clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31, + ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31, clk_names[AVPLL_B1 + n], n, "avpll_vcoB", BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0); - if (IS_ERR(clk)) + if (ret) goto bg2_fail; } /* reference clock bypass switches */ parent_names[0] = clk_names[SYSPLL]; parent_names[1] = clk_names[REFCLK]; - clk = clk_register_mux(NULL, "syspll_byp", parent_names, 2, + hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2, 0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; - clk_names[SYSPLL] = __clk_get_name(clk); + clk_names[SYSPLL] = clk_hw_get_name(hw); parent_names[0] = clk_names[MEMPLL]; parent_names[1] = clk_names[REFCLK]; - clk = clk_register_mux(NULL, "mempll_byp", parent_names, 2, + hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2, 0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; - clk_names[MEMPLL] = __clk_get_name(clk); + clk_names[MEMPLL] = clk_hw_get_name(hw); parent_names[0] = clk_names[CPUPLL]; parent_names[1] = clk_names[REFCLK]; - clk = clk_register_mux(NULL, "cpupll_byp", parent_names, 2, + hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2, 0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; - clk_names[CPUPLL] = __clk_get_name(clk); + clk_names[CPUPLL] = clk_hw_get_name(hw); /* clock muxes */ parent_names[0] = clk_names[AVPLL_B3]; parent_names[1] = clk_names[AVPLL_A3]; - clk = clk_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2, 0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; parent_names[0] = clk_names[VIDEO0_PLL]; parent_names[1] = clk_names[VIDEO_EXT0]; - clk = clk_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2, 0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; parent_names[0] = clk_names[VIDEO1_PLL]; parent_names[1] = clk_names[VIDEO_EXT0]; - clk = clk_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2, 0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; parent_names[0] = clk_names[AVPLL_A2]; parent_names[1] = clk_names[AVPLL_B2]; - clk = clk_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2, 0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; parent_names[0] = clk_names[VIDEO2_PLL]; parent_names[1] = clk_names[VIDEO_EXT0]; - clk = clk_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2, 0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; parent_names[0] = clk_names[AVPLL_B1]; parent_names[1] = clk_names[AVPLL_A5]; - clk = clk_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2, + hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2, 0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock); - if (IS_ERR(clk)) + if (IS_ERR(hw)) goto bg2_fail; /* clock divider cells */ @@ -648,7 +656,7 @@ static void __init berlin2_clock_setup(struct device_node *np) for (k = 0; k < dd->num_parents; k++) parent_names[k] = clk_names[dd->parent_ids[k]]; - clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase, + hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase, dd->name, dd->div_flags, parent_names, dd->num_parents, dd->flags, &lock); } @@ -657,18 +665,18 @@ static void __init berlin2_clock_setup(struct device_node *np) for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) { const struct berlin2_gate_data *gd = &bg2_gates[n]; - clks[CLKID_GETH0 + n] = clk_register_gate(NULL, gd->name, + hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name, gd->parent_name, gd->flags, gbase + REG_CLKENABLE, gd->bit_idx, 0, &lock); } /* twdclk is derived from cpu/3 */ - clks[CLKID_TWD] = - clk_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3); + hws[CLKID_TWD] = + clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3); /* check for errors on leaf clocks */ for (n = 0; n < MAX_CLKS; n++) { - if (!IS_ERR(clks[n])) + if (!IS_ERR(hws[n])) continue; pr_err("%s: Unable to register leaf clock %d\n", @@ -677,9 +685,7 @@ static void __init berlin2_clock_setup(struct device_node *np) } /* register clk-provider */ - clk_data.clks = clks; - clk_data.clk_num = MAX_CLKS; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data); return; diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c index f144547cf76c..0718e831475f 100644 --- a/drivers/clk/berlin/bg2q.c +++ b/drivers/clk/berlin/bg2q.c @@ -46,8 +46,7 @@ #define REG_SDIO1XIN_CLKCTL 0x015c #define MAX_CLKS 28 -static struct clk *clks[MAX_CLKS]; -static struct clk_onecell_data clk_data; +static struct clk_hw_onecell_data *clk_data; static DEFINE_SPINLOCK(lock); static void __iomem *gbase; static void __iomem *cpupll_base; @@ -293,7 +292,15 @@ static void __init berlin2q_clock_setup(struct device_node *np) struct device_node *parent_np = of_get_parent(np); const char *parent_names[9]; struct clk *clk; - int n; + struct clk_hw **hws; + int n, ret; + + clk_data = kzalloc(sizeof(*clk_data) + + sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL); + if (!clk_data) + return; + clk_data->num = MAX_CLKS; + hws = clk_data->hws; gbase = of_iomap(parent_np, 0); if (!gbase) { @@ -317,14 +324,14 @@ static void __init berlin2q_clock_setup(struct device_node *np) } /* simple register PLLs */ - clk = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0, + ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0, clk_names[SYSPLL], clk_names[REFCLK], 0); - if (IS_ERR(clk)) + if (ret) goto bg2q_fail; - clk = berlin2_pll_register(&bg2q_pll_map, cpupll_base, + ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base, clk_names[CPUPLL], clk_names[REFCLK], 0); - if (IS_ERR(clk)) + if (ret) goto bg2q_fail; /* TODO: add BG2Q AVPLL */ @@ -342,7 +349,7 @@ static void __init berlin2q_clock_setup(struct device_node *np) for (k = 0; k < dd->num_parents; k++) parent_names[k] = clk_names[dd->parent_ids[k]]; - clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase, + hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase, dd->name, dd->div_flags, parent_names, dd->num_parents, dd->flags, &lock); } @@ -351,22 +358,22 @@ static void __init berlin2q_clock_setup(struct device_node *np) for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) { const struct berlin2_gate_data *gd = &bg2q_gates[n]; - clks[CLKID_GFX2DAXI + n] = clk_register_gate(NULL, gd->name, + hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name, gd->parent_name, gd->flags, gbase + REG_CLKENABLE, gd->bit_idx, 0, &lock); } /* cpuclk divider is fixed to 1 */ - clks[CLKID_CPU] = - clk_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL], + hws[CLKID_CPU] = + clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL], 0, 1, 1); /* twdclk is derived from cpu/3 */ - clks[CLKID_TWD] = - clk_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3); + hws[CLKID_TWD] = + clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3); /* check for errors on leaf clocks */ for (n = 0; n < MAX_CLKS; n++) { - if (!IS_ERR(clks[n])) + if (!IS_ERR(hws[n])) continue; pr_err("%s: Unable to register leaf clock %d\n", @@ -375,9 +382,7 @@ static void __init berlin2q_clock_setup(struct device_node *np) } /* register clk-provider */ - clk_data.clks = clks; - clk_data.clk_num = MAX_CLKS; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data); return; diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index a0f55bc1ad3d..96386ffc8483 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -352,7 +352,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, /* if read only, just return current value */ if (divider->flags & CLK_DIVIDER_READ_ONLY) { - bestdiv = readl(divider->reg) >> divider->shift; + bestdiv = clk_readl(divider->reg) >> divider->shift; bestdiv &= div_mask(divider->width); bestdiv = _get_div(divider->table, bestdiv, divider->flags, divider->width); diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 4db3be214077..a5d402de5584 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/of.h> +#include <linux/platform_device.h> /* * DOC: basic fixed multiplier and divider clock that cannot gate @@ -147,27 +148,25 @@ static const struct of_device_id set_rate_parent_matches[] = { { /* Sentinel */ }, }; -/** - * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock - */ -void __init of_fixed_factor_clk_setup(struct device_node *node) +static struct clk *_of_fixed_factor_clk_setup(struct device_node *node) { struct clk *clk; const char *clk_name = node->name; const char *parent_name; unsigned long flags = 0; u32 div, mult; + int ret; if (of_property_read_u32(node, "clock-div", &div)) { pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", __func__, node->name); - return; + return ERR_PTR(-EIO); } if (of_property_read_u32(node, "clock-mult", &mult)) { pr_err("%s Fixed factor clock <%s> must have a clock-mult property\n", __func__, node->name); - return; + return ERR_PTR(-EIO); } of_property_read_string(node, "clock-output-names", &clk_name); @@ -178,10 +177,67 @@ void __init of_fixed_factor_clk_setup(struct device_node *node) clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags, mult, div); - if (!IS_ERR(clk)) - of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (IS_ERR(clk)) + return clk; + + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (ret) { + clk_unregister(clk); + return ERR_PTR(ret); + } + + return clk; +} + +/** + * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock + */ +void __init of_fixed_factor_clk_setup(struct device_node *node) +{ + _of_fixed_factor_clk_setup(node); } -EXPORT_SYMBOL_GPL(of_fixed_factor_clk_setup); CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", of_fixed_factor_clk_setup); + +static int of_fixed_factor_clk_remove(struct platform_device *pdev) +{ + struct clk *clk = platform_get_drvdata(pdev); + + clk_unregister_fixed_factor(clk); + + return 0; +} + +static int of_fixed_factor_clk_probe(struct platform_device *pdev) +{ + struct clk *clk; + + /* + * This function is not executed when of_fixed_factor_clk_setup + * succeeded. + */ + clk = _of_fixed_factor_clk_setup(pdev->dev.of_node); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + platform_set_drvdata(pdev, clk); + + return 0; +} + +static const struct of_device_id of_fixed_factor_clk_ids[] = { + { .compatible = "fixed-factor-clock" }, + { } +}; +MODULE_DEVICE_TABLE(of, of_fixed_factor_clk_ids); + +static struct platform_driver of_fixed_factor_clk_driver = { + .driver = { + .name = "of_fixed_factor_clk", + .of_match_table = of_fixed_factor_clk_ids, + }, + .probe = of_fixed_factor_clk_probe, + .remove = of_fixed_factor_clk_remove, +}; +builtin_platform_driver(of_fixed_factor_clk_driver); #endif diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 2edb39342a02..b5c46b3f8764 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -15,6 +15,7 @@ #include <linux/io.h> #include <linux/err.h> #include <linux/of.h> +#include <linux/platform_device.h> /* * DOC: basic fixed-rate clock that cannot gate @@ -157,18 +158,16 @@ void clk_hw_unregister_fixed_rate(struct clk_hw *hw) EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate); #ifdef CONFIG_OF -/** - * of_fixed_clk_setup() - Setup function for simple fixed rate clock - */ -void of_fixed_clk_setup(struct device_node *node) +static struct clk *_of_fixed_clk_setup(struct device_node *node) { struct clk *clk; const char *clk_name = node->name; u32 rate; u32 accuracy = 0; + int ret; if (of_property_read_u32(node, "clock-frequency", &rate)) - return; + return ERR_PTR(-EIO); of_property_read_u32(node, "clock-accuracy", &accuracy); @@ -176,9 +175,66 @@ void of_fixed_clk_setup(struct device_node *node) clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, 0, rate, accuracy); - if (!IS_ERR(clk)) - of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (IS_ERR(clk)) + return clk; + + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (ret) { + clk_unregister(clk); + return ERR_PTR(ret); + } + + return clk; +} + +/** + * of_fixed_clk_setup() - Setup function for simple fixed rate clock + */ +void __init of_fixed_clk_setup(struct device_node *node) +{ + _of_fixed_clk_setup(node); } -EXPORT_SYMBOL_GPL(of_fixed_clk_setup); CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); + +static int of_fixed_clk_remove(struct platform_device *pdev) +{ + struct clk *clk = platform_get_drvdata(pdev); + + clk_unregister_fixed_rate(clk); + + return 0; +} + +static int of_fixed_clk_probe(struct platform_device *pdev) +{ + struct clk *clk; + + /* + * This function is not executed when of_fixed_clk_setup + * succeeded. + */ + clk = _of_fixed_clk_setup(pdev->dev.of_node); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + platform_set_drvdata(pdev, clk); + + return 0; +} + +static const struct of_device_id of_fixed_clk_ids[] = { + { .compatible = "fixed-clock" }, + { } +}; +MODULE_DEVICE_TABLE(of, of_fixed_clk_ids); + +static struct platform_driver of_fixed_clk_driver = { + .driver = { + .name = "of_fixed_clk", + .of_match_table = of_fixed_clk_ids, + }, + .probe = of_fixed_clk_probe, + .remove = of_fixed_clk_remove, +}; +builtin_platform_driver(of_fixed_clk_driver); #endif diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c index 5097831387ff..8430e45427f4 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/clk-ls1x.c @@ -48,13 +48,13 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk *__init clk_register_pll(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags) +static struct clk_hw *__init clk_hw_register_pll(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags) { + int ret; struct clk_hw *hw; - struct clk *clk; struct clk_init_data init; /* allocate the divider */ @@ -72,12 +72,13 @@ static struct clk *__init clk_register_pll(struct device *dev, hw->init = &init; /* register the clock */ - clk = clk_register(dev, hw); - - if (IS_ERR(clk)) + ret = clk_hw_register(dev, hw); + if (ret) { kfree(hw); + hw = ERR_PTR(ret); + } - return clk; + return hw; } static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; @@ -86,14 +87,14 @@ static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; void __init ls1x_clk_init(void) { - struct clk *clk; + struct clk_hw *hw; - clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); - clk_register_clkdev(clk, "osc_33m_clk", NULL); + hw = clk_hw_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); + clk_hw_register_clkdev(hw, "osc_33m_clk", NULL); /* clock derived from 33 MHz OSC clk */ - clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); - clk_register_clkdev(clk, "pll_clk", NULL); + hw = clk_hw_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk_hw_register_clkdev(hw, "pll_clk", NULL); /* clock derived from PLL clk */ /* _____ @@ -102,17 +103,17 @@ void __init ls1x_clk_init(void) * \___ PLL ___ CPU DIV ___| | * |_____| */ - clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk", + hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk", CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV, DIV_CPU_SHIFT, DIV_CPU_WIDTH, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST, &_lock); - clk_register_clkdev(clk, "cpu_clk_div", NULL); - clk = clk_register_mux(NULL, "cpu_clk", cpu_parents, + clk_hw_register_clkdev(hw, "cpu_clk_div", NULL); + hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents, ARRAY_SIZE(cpu_parents), CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock); - clk_register_clkdev(clk, "cpu_clk", NULL); + clk_hw_register_clkdev(hw, "cpu_clk", NULL); /* _____ * _______________________| | @@ -120,15 +121,15 @@ void __init ls1x_clk_init(void) * \___ PLL ___ DC DIV ___| | * |_____| */ - clk = clk_register_divider(NULL, "dc_clk_div", "pll_clk", + hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk", 0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT, DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_register_clkdev(clk, "dc_clk_div", NULL); - clk = clk_register_mux(NULL, "dc_clk", dc_parents, + clk_hw_register_clkdev(hw, "dc_clk_div", NULL); + hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents, ARRAY_SIZE(dc_parents), CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock); - clk_register_clkdev(clk, "dc_clk", NULL); + clk_hw_register_clkdev(hw, "dc_clk", NULL); /* _____ * _______________________| | @@ -136,26 +137,26 @@ void __init ls1x_clk_init(void) * \___ PLL ___ DDR DIV ___| | * |_____| */ - clk = clk_register_divider(NULL, "ahb_clk_div", "pll_clk", + hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk", 0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT, DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_register_clkdev(clk, "ahb_clk_div", NULL); - clk = clk_register_mux(NULL, "ahb_clk", ahb_parents, + clk_hw_register_clkdev(hw, "ahb_clk_div", NULL); + hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents, ARRAY_SIZE(ahb_parents), CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); - clk_register_clkdev(clk, "ahb_clk", NULL); - clk_register_clkdev(clk, "stmmaceth", NULL); + clk_hw_register_clkdev(hw, "ahb_clk", NULL); + clk_hw_register_clkdev(hw, "stmmaceth", NULL); /* clock derived from AHB clk */ /* APB clk is always half of the AHB clk */ - clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, + hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, DIV_APB); - clk_register_clkdev(clk, "apb_clk", NULL); - clk_register_clkdev(clk, "ls1x_i2c", NULL); - clk_register_clkdev(clk, "ls1x_pwmtimer", NULL); - clk_register_clkdev(clk, "ls1x_spi", NULL); - clk_register_clkdev(clk, "ls1x_wdt", NULL); - clk_register_clkdev(clk, "serial8250", NULL); + clk_hw_register_clkdev(hw, "apb_clk", NULL); + clk_hw_register_clkdev(hw, "ls1x_i2c", NULL); + clk_hw_register_clkdev(hw, "ls1x_pwmtimer", NULL); + clk_hw_register_clkdev(hw, "ls1x_spi", NULL); + clk_hw_register_clkdev(hw, "ls1x_wdt", NULL); + clk_hw_register_clkdev(hw, "serial8250", NULL); } diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c deleted file mode 100644 index 35af9cb6da4f..000000000000 --- a/drivers/clk/clk-max-gen.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * clk-max-gen.c - Generic clock driver for Maxim PMICs clocks - * - * Copyright (C) 2014 Google, Inc - * - * Copyright (C) 2012 Samsung Electornics - * Jonghwa Lee <jonghwa3.lee@samsung.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This driver is based on clk-max77686.c - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/regmap.h> -#include <linux/platform_device.h> -#include <linux/clk-provider.h> -#include <linux/mutex.h> -#include <linux/clkdev.h> -#include <linux/of.h> -#include <linux/export.h> - -#include "clk-max-gen.h" - -struct max_gen_clk { - struct regmap *regmap; - u32 mask; - u32 reg; - struct clk_hw hw; -}; - -static struct max_gen_clk *to_max_gen_clk(struct clk_hw *hw) -{ - return container_of(hw, struct max_gen_clk, hw); -} - -static int max_gen_clk_prepare(struct clk_hw *hw) -{ - struct max_gen_clk *max_gen = to_max_gen_clk(hw); - - return regmap_update_bits(max_gen->regmap, max_gen->reg, - max_gen->mask, max_gen->mask); -} - -static void max_gen_clk_unprepare(struct clk_hw *hw) -{ - struct max_gen_clk *max_gen = to_max_gen_clk(hw); - - regmap_update_bits(max_gen->regmap, max_gen->reg, - max_gen->mask, ~max_gen->mask); -} - -static int max_gen_clk_is_prepared(struct clk_hw *hw) -{ - struct max_gen_clk *max_gen = to_max_gen_clk(hw); - int ret; - u32 val; - - ret = regmap_read(max_gen->regmap, max_gen->reg, &val); - - if (ret < 0) - return -EINVAL; - - return val & max_gen->mask; -} - -static unsigned long max_gen_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return 32768; -} - -struct clk_ops max_gen_clk_ops = { - .prepare = max_gen_clk_prepare, - .unprepare = max_gen_clk_unprepare, - .is_prepared = max_gen_clk_is_prepared, - .recalc_rate = max_gen_recalc_rate, -}; -EXPORT_SYMBOL_GPL(max_gen_clk_ops); - -static struct clk *max_gen_clk_register(struct device *dev, - struct max_gen_clk *max_gen) -{ - struct clk *clk; - struct clk_hw *hw = &max_gen->hw; - int ret; - - clk = devm_clk_register(dev, hw); - if (IS_ERR(clk)) - return clk; - - ret = clk_register_clkdev(clk, hw->init->name, NULL); - - if (ret) - return ERR_PTR(ret); - - return clk; -} - -int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap, - u32 reg, struct clk_init_data *clks_init, int num_init) -{ - int i, ret; - struct max_gen_clk *max_gen_clks; - struct clk **clocks; - struct device *dev = pdev->dev.parent; - const char *clk_name; - struct clk_init_data *init; - - clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, GFP_KERNEL); - if (!clocks) - return -ENOMEM; - - max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk) - * num_init, GFP_KERNEL); - if (!max_gen_clks) - return -ENOMEM; - - for (i = 0; i < num_init; i++) { - max_gen_clks[i].regmap = regmap; - max_gen_clks[i].mask = 1 << i; - max_gen_clks[i].reg = reg; - - init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL); - if (!init) - return -ENOMEM; - - if (dev->of_node && - !of_property_read_string_index(dev->of_node, - "clock-output-names", - i, &clk_name)) - init->name = clk_name; - else - init->name = clks_init[i].name; - - init->ops = clks_init[i].ops; - init->flags = clks_init[i].flags; - - max_gen_clks[i].hw.init = init; - - clocks[i] = max_gen_clk_register(dev, &max_gen_clks[i]); - if (IS_ERR(clocks[i])) { - ret = PTR_ERR(clocks[i]); - dev_err(dev, "failed to register %s\n", - max_gen_clks[i].hw.init->name); - return ret; - } - } - - platform_set_drvdata(pdev, clocks); - - if (dev->of_node) { - struct clk_onecell_data *of_data; - - of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL); - if (!of_data) - return -ENOMEM; - - of_data->clks = clocks; - of_data->clk_num = num_init; - ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, - of_data); - - if (ret) { - dev_err(dev, "failed to register OF clock provider\n"); - return ret; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(max_gen_clk_probe); - -int max_gen_clk_remove(struct platform_device *pdev, int num_init) -{ - struct device *dev = pdev->dev.parent; - - if (dev->of_node) - of_clk_del_provider(dev->of_node); - - return 0; -} -EXPORT_SYMBOL_GPL(max_gen_clk_remove); diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h deleted file mode 100644 index 997e86fc3f4d..000000000000 --- a/drivers/clk/clk-max-gen.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks - * - * Copyright (C) 2014 Google, Inc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __CLK_MAX_GEN_H__ -#define __CLK_MAX_GEN_H__ - -#include <linux/types.h> -#include <linux/device.h> -#include <linux/clkdev.h> -#include <linux/regmap.h> -#include <linux/platform_device.h> - -int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap, - u32 reg, struct clk_init_data *clks_init, int num_init); -int max_gen_clk_remove(struct platform_device *pdev, int num_init); -extern struct clk_ops max_gen_clk_ops; - -#endif /* __CLK_MAX_GEN_H__ */ diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index 9b6f2772e948..b637f5979023 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c @@ -1,5 +1,5 @@ /* - * clk-max77686.c - Clock driver for Maxim 77686 + * clk-max77686.c - Clock driver for Maxim 77686/MAX77802 * * Copyright (C) 2012 Samsung Electornics * Jonghwa Lee <jonghwa3.lee@samsung.com> @@ -25,46 +25,284 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/mfd/max77620.h> #include <linux/mfd/max77686.h> #include <linux/mfd/max77686-private.h> #include <linux/clk-provider.h> #include <linux/mutex.h> #include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/regmap.h> #include <dt-bindings/clock/maxim,max77686.h> -#include "clk-max-gen.h" +#include <dt-bindings/clock/maxim,max77802.h> +#include <dt-bindings/clock/maxim,max77620.h> -static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { +#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3 + +enum max77686_chip_name { + CHIP_MAX77686, + CHIP_MAX77802, + CHIP_MAX77620, +}; + +struct max77686_hw_clk_info { + const char *name; + u32 clk_reg; + u32 clk_enable_mask; + u32 flags; +}; + +struct max77686_clk_init_data { + struct regmap *regmap; + struct clk_hw hw; + struct clk_init_data clk_idata; + const struct max77686_hw_clk_info *clk_info; +}; + +struct max77686_clk_driver_data { + enum max77686_chip_name chip; + struct max77686_clk_init_data *max_clk_data; + size_t num_clks; +}; + +static const struct +max77686_hw_clk_info max77686_hw_clks_info[MAX77686_CLKS_NUM] = { [MAX77686_CLK_AP] = { .name = "32khz_ap", - .ops = &max_gen_clk_ops, + .clk_reg = MAX77686_REG_32KHZ, + .clk_enable_mask = BIT(MAX77686_CLK_AP), }, [MAX77686_CLK_CP] = { .name = "32khz_cp", - .ops = &max_gen_clk_ops, + .clk_reg = MAX77686_REG_32KHZ, + .clk_enable_mask = BIT(MAX77686_CLK_CP), }, [MAX77686_CLK_PMIC] = { .name = "32khz_pmic", - .ops = &max_gen_clk_ops, + .clk_reg = MAX77686_REG_32KHZ, + .clk_enable_mask = BIT(MAX77686_CLK_PMIC), + }, +}; + +static const struct +max77686_hw_clk_info max77802_hw_clks_info[MAX77802_CLKS_NUM] = { + [MAX77802_CLK_32K_AP] = { + .name = "32khz_ap", + .clk_reg = MAX77802_REG_32KHZ, + .clk_enable_mask = BIT(MAX77802_CLK_32K_AP), + }, + [MAX77802_CLK_32K_CP] = { + .name = "32khz_cp", + .clk_reg = MAX77802_REG_32KHZ, + .clk_enable_mask = BIT(MAX77802_CLK_32K_CP), + }, +}; + +static const struct +max77686_hw_clk_info max77620_hw_clks_info[MAX77620_CLKS_NUM] = { + [MAX77620_CLK_32K_OUT0] = { + .name = "32khz_out0", + .clk_reg = MAX77620_REG_CNFG1_32K, + .clk_enable_mask = MAX77620_CNFG1_32K_OUT0_EN, }, }; +static struct max77686_clk_init_data *to_max77686_clk_init_data( + struct clk_hw *hw) +{ + return container_of(hw, struct max77686_clk_init_data, hw); +} + +static int max77686_clk_prepare(struct clk_hw *hw) +{ + struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); + + return regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg, + max77686->clk_info->clk_enable_mask, + max77686->clk_info->clk_enable_mask); +} + +static void max77686_clk_unprepare(struct clk_hw *hw) +{ + struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); + + regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg, + max77686->clk_info->clk_enable_mask, + ~max77686->clk_info->clk_enable_mask); +} + +static int max77686_clk_is_prepared(struct clk_hw *hw) +{ + struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); + int ret; + u32 val; + + ret = regmap_read(max77686->regmap, max77686->clk_info->clk_reg, &val); + + if (ret < 0) + return -EINVAL; + + return val & max77686->clk_info->clk_enable_mask; +} + +static unsigned long max77686_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return 32768; +} + +static struct clk_ops max77686_clk_ops = { + .prepare = max77686_clk_prepare, + .unprepare = max77686_clk_unprepare, + .is_prepared = max77686_clk_is_prepared, + .recalc_rate = max77686_recalc_rate, +}; + +static struct clk_hw * +of_clk_max77686_get(struct of_phandle_args *clkspec, void *data) +{ + struct max77686_clk_driver_data *drv_data = data; + unsigned int idx = clkspec->args[0]; + + if (idx >= drv_data->num_clks) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return &drv_data->max_clk_data[idx].hw; +} + static int max77686_clk_probe(struct platform_device *pdev) { - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + const struct platform_device_id *id = platform_get_device_id(pdev); + struct max77686_clk_driver_data *drv_data; + const struct max77686_hw_clk_info *hw_clks; + struct regmap *regmap; + int i, ret, num_clks; + + drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); + if (!drv_data) + return -ENOMEM; + + regmap = dev_get_regmap(parent, NULL); + if (!regmap) { + dev_err(dev, "Failed to get rtc regmap\n"); + return -ENODEV; + } + + drv_data->chip = id->driver_data; + + switch (drv_data->chip) { + case CHIP_MAX77686: + num_clks = MAX77686_CLKS_NUM; + hw_clks = max77686_hw_clks_info; + break; + + case CHIP_MAX77802: + num_clks = MAX77802_CLKS_NUM; + hw_clks = max77802_hw_clks_info; + break; + + case CHIP_MAX77620: + num_clks = MAX77620_CLKS_NUM; + hw_clks = max77620_hw_clks_info; + break; - return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ, - max77686_clks_init, MAX77686_CLKS_NUM); + default: + dev_err(dev, "Unknown Chip ID\n"); + return -EINVAL; + } + + drv_data->max_clk_data = devm_kcalloc(dev, num_clks, + sizeof(*drv_data->max_clk_data), + GFP_KERNEL); + if (!drv_data->max_clk_data) + return -ENOMEM; + + for (i = 0; i < num_clks; i++) { + struct max77686_clk_init_data *max_clk_data; + const char *clk_name; + + max_clk_data = &drv_data->max_clk_data[i]; + + max_clk_data->regmap = regmap; + max_clk_data->clk_info = &hw_clks[i]; + max_clk_data->clk_idata.flags = hw_clks[i].flags; + max_clk_data->clk_idata.ops = &max77686_clk_ops; + + if (parent->of_node && + !of_property_read_string_index(parent->of_node, + "clock-output-names", + i, &clk_name)) + max_clk_data->clk_idata.name = clk_name; + else + max_clk_data->clk_idata.name = hw_clks[i].name; + + max_clk_data->hw.init = &max_clk_data->clk_idata; + + ret = devm_clk_hw_register(dev, &max_clk_data->hw); + if (ret) { + dev_err(dev, "Failed to clock register: %d\n", ret); + return ret; + } + + ret = clk_hw_register_clkdev(&max_clk_data->hw, + max_clk_data->clk_idata.name, NULL); + if (ret < 0) { + dev_err(dev, "Failed to clkdev register: %d\n", ret); + return ret; + } + } + + if (parent->of_node) { + ret = of_clk_add_hw_provider(parent->of_node, of_clk_max77686_get, + drv_data); + + if (ret < 0) { + dev_err(dev, "Failed to register OF clock provider: %d\n", + ret); + return ret; + } + } + + /* MAX77802: Enable low-jitter mode on the 32khz clocks. */ + if (drv_data->chip == CHIP_MAX77802) { + ret = regmap_update_bits(regmap, MAX77802_REG_32KHZ, + 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT, + 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT); + if (ret < 0) { + dev_err(dev, "Failed to config low-jitter: %d\n", ret); + goto remove_of_clk_provider; + } + } + + return 0; + +remove_of_clk_provider: + if (parent->of_node) + of_clk_del_provider(parent->of_node); + + return ret; } static int max77686_clk_remove(struct platform_device *pdev) { - return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM); + struct device *parent = pdev->dev.parent; + + if (parent->of_node) + of_clk_del_provider(parent->of_node); + + return 0; } static const struct platform_device_id max77686_clk_id[] = { - { "max77686-clk", 0}, - { }, + { "max77686-clk", .driver_data = CHIP_MAX77686, }, + { "max77802-clk", .driver_data = CHIP_MAX77802, }, + { "max77620-clock", .driver_data = CHIP_MAX77620, }, + {}, }; MODULE_DEVICE_TABLE(platform, max77686_clk_id); diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c deleted file mode 100644 index 355dd2e522c3..000000000000 --- a/drivers/clk/clk-max77802.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * clk-max77802.c - Clock driver for Maxim 77802 - * - * Copyright (C) 2014 Google, Inc - * - * Copyright (C) 2012 Samsung Electornics - * Jonghwa Lee <jonghwa3.lee@samsung.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This driver is based on clk-max77686.c - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/mfd/max77686-private.h> -#include <linux/clk-provider.h> -#include <linux/mutex.h> -#include <linux/clkdev.h> - -#include <dt-bindings/clock/maxim,max77802.h> -#include "clk-max-gen.h" - -#define MAX77802_CLOCK_OPMODE_MASK 0x1 -#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3 - -static struct clk_init_data max77802_clks_init[MAX77802_CLKS_NUM] = { - [MAX77802_CLK_32K_AP] = { - .name = "32khz_ap", - .ops = &max_gen_clk_ops, - }, - [MAX77802_CLK_32K_CP] = { - .name = "32khz_cp", - .ops = &max_gen_clk_ops, - }, -}; - -static int max77802_clk_probe(struct platform_device *pdev) -{ - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - int ret; - - ret = max_gen_clk_probe(pdev, iodev->regmap, MAX77802_REG_32KHZ, - max77802_clks_init, MAX77802_CLKS_NUM); - - if (ret) { - dev_err(&pdev->dev, "generic probe failed %d\n", ret); - return ret; - } - - /* Enable low-jitter mode on the 32khz clocks. */ - ret = regmap_update_bits(iodev->regmap, MAX77802_REG_32KHZ, - 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT, - 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT); - if (ret < 0) - dev_err(&pdev->dev, "failed to enable low-jitter mode\n"); - - return ret; -} - -static int max77802_clk_remove(struct platform_device *pdev) -{ - return max_gen_clk_remove(pdev, MAX77802_CLKS_NUM); -} - -static const struct platform_device_id max77802_clk_id[] = { - { "max77802-clk", 0}, - { }, -}; -MODULE_DEVICE_TABLE(platform, max77802_clk_id); - -static struct platform_driver max77802_clk_driver = { - .driver = { - .name = "max77802-clk", - }, - .probe = max77802_clk_probe, - .remove = max77802_clk_remove, - .id_table = max77802_clk_id, -}; - -module_platform_driver(max77802_clk_driver); - -MODULE_DESCRIPTION("MAXIM 77802 Clock Driver"); -MODULE_AUTHOR("Javier Martinez Canillas <javier@osg.samsung.com"); -MODULE_LICENSE("GPL"); diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 58566a17944a..20b105584f82 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -766,7 +766,11 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) if (!hwc) return NULL; - hwc->reg = cg->regs + 0x20 * idx; + if (cg->info.flags & CG_VER3) + hwc->reg = cg->regs + 0x70000 + 0x20 * idx; + else + hwc->reg = cg->regs + 0x20 * idx; + hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]]; /* diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c index 697c66757400..c98b1ec76f54 100644 --- a/drivers/clk/clk-twl6040.c +++ b/drivers/clk/clk-twl6040.c @@ -26,60 +26,73 @@ #include <linux/mfd/twl6040.h> #include <linux/clk-provider.h> -struct twl6040_clk { +struct twl6040_pdmclk { struct twl6040 *twl6040; struct device *dev; - struct clk_hw mcpdm_fclk; + struct clk_hw pdmclk_hw; struct clk *clk; int enabled; }; -static int twl6040_bitclk_is_enabled(struct clk_hw *hw) +static int twl6040_pdmclk_is_prepared(struct clk_hw *hw) { - struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk, - mcpdm_fclk); - return twl6040_clk->enabled; + struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk, + pdmclk_hw); + + return pdmclk->enabled; } -static int twl6040_bitclk_prepare(struct clk_hw *hw) +static int twl6040_pdmclk_prepare(struct clk_hw *hw) { - struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk, - mcpdm_fclk); + struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk, + pdmclk_hw); int ret; - ret = twl6040_power(twl6040_clk->twl6040, 1); + ret = twl6040_power(pdmclk->twl6040, 1); if (!ret) - twl6040_clk->enabled = 1; + pdmclk->enabled = 1; return ret; } -static void twl6040_bitclk_unprepare(struct clk_hw *hw) +static void twl6040_pdmclk_unprepare(struct clk_hw *hw) { - struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk, - mcpdm_fclk); + struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk, + pdmclk_hw); int ret; - ret = twl6040_power(twl6040_clk->twl6040, 0); + ret = twl6040_power(pdmclk->twl6040, 0); if (!ret) - twl6040_clk->enabled = 0; + pdmclk->enabled = 0; + +} + +static unsigned long twl6040_pdmclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk, + pdmclk_hw); + + return twl6040_get_sysclk(pdmclk->twl6040); } -static const struct clk_ops twl6040_mcpdm_ops = { - .is_enabled = twl6040_bitclk_is_enabled, - .prepare = twl6040_bitclk_prepare, - .unprepare = twl6040_bitclk_unprepare, +static const struct clk_ops twl6040_pdmclk_ops = { + .is_prepared = twl6040_pdmclk_is_prepared, + .prepare = twl6040_pdmclk_prepare, + .unprepare = twl6040_pdmclk_unprepare, + .recalc_rate = twl6040_pdmclk_recalc_rate, }; -static struct clk_init_data wm831x_clkout_init = { - .name = "mcpdm_fclk", - .ops = &twl6040_mcpdm_ops, +static struct clk_init_data twl6040_pdmclk_init = { + .name = "pdmclk", + .ops = &twl6040_pdmclk_ops, + .flags = CLK_GET_RATE_NOCACHE, }; -static int twl6040_clk_probe(struct platform_device *pdev) +static int twl6040_pdmclk_probe(struct platform_device *pdev) { struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent); - struct twl6040_clk *clkdata; + struct twl6040_pdmclk *clkdata; clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL); if (!clkdata) @@ -88,26 +101,27 @@ static int twl6040_clk_probe(struct platform_device *pdev) clkdata->dev = &pdev->dev; clkdata->twl6040 = twl6040; - clkdata->mcpdm_fclk.init = &wm831x_clkout_init; - clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk); + clkdata->pdmclk_hw.init = &twl6040_pdmclk_init; + clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->pdmclk_hw); if (IS_ERR(clkdata->clk)) return PTR_ERR(clkdata->clk); platform_set_drvdata(pdev, clkdata); - return 0; + return of_clk_add_provider(pdev->dev.parent->of_node, + of_clk_src_simple_get, clkdata->clk); } -static struct platform_driver twl6040_clk_driver = { +static struct platform_driver twl6040_pdmclk_driver = { .driver = { - .name = "twl6040-clk", + .name = "twl6040-pdmclk", }, - .probe = twl6040_clk_probe, + .probe = twl6040_pdmclk_probe, }; -module_platform_driver(twl6040_clk_driver); +module_platform_driver(twl6040_pdmclk_driver); MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock"); MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); -MODULE_ALIAS("platform:twl6040-clk"); +MODULE_ALIAS("platform:twl6040-pdmclk"); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 820a939fb6bb..71cc56712666 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2449,8 +2449,16 @@ static int __clk_core_init(struct clk_core *core) hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { struct clk_core *parent = __clk_init_parent(orphan); - if (parent) - clk_core_reparent(orphan, parent); + /* + * we could call __clk_set_parent, but that would result in a + * redundant call to the .set_rate op, if it exists + */ + if (parent) { + __clk_set_parent_before(orphan, parent); + __clk_set_parent_after(orphan, parent, NULL); + __clk_recalc_accuracies(orphan); + __clk_recalc_rates(orphan, 0); + } } /* @@ -2491,7 +2499,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, /* This is to allow this function to be chained to others */ if (IS_ERR_OR_NULL(hw)) - return (struct clk *) hw; + return ERR_CAST(hw); clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) @@ -3186,7 +3194,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, { struct of_clk_provider *provider; struct clk *clk = ERR_PTR(-EPROBE_DEFER); - struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); + struct clk_hw *hw; if (!clkspec) return ERR_PTR(-EINVAL); @@ -3194,12 +3202,13 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, /* Check if we have such a provider in our array */ mutex_lock(&of_clk_mutex); list_for_each_entry(provider, &of_clk_providers, link) { - if (provider->node == clkspec->np) + if (provider->node == clkspec->np) { hw = __of_clk_get_hw_from_provider(provider, clkspec); - if (!IS_ERR(hw)) { clk = __clk_create_clk(hw, dev_id, con_id); + } - if (!IS_ERR(clk) && !__clk_get(clk)) { + if (!IS_ERR(clk)) { + if (!__clk_get(clk)) { __clk_free_clk(clk); clk = ERR_PTR(-ENOENT); } @@ -3451,6 +3460,10 @@ void __init of_clk_init(const struct of_device_id *matches) &clk_provider_list, node) { if (force || parent_ready(clk_provider->np)) { + /* Don't populate platform devices */ + of_node_set_flag(clk_provider->np, + OF_POPULATED); + clk_provider->clk_init_cb(clk_provider->np); of_clk_set_defaults(clk_provider->np, true); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 6ed4f8fa0667..6bafcaa4451f 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -22,6 +22,10 @@ #include "clk.h" +static u32 share_count_sai1; +static u32 share_count_sai2; +static u32 share_count_sai3; + static struct clk *clks[IMX7D_CLK_END]; static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk", "pll_enet_500m_clk", "pll_dram_main_clk", @@ -779,6 +783,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); + clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0); clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); @@ -786,9 +791,12 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0); clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0); clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0); - clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate4("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0); - clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate4("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0); - clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate4("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0); + clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2_shared2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0, &share_count_sai1); + clks[IMX7D_SAI1_IPG_CLK] = imx_clk_gate2_shared2("sai1_ipg_clk", "ipg_root_clk", base + 0x48c0, 0, &share_count_sai1); + clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2_shared2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0, &share_count_sai2); + clks[IMX7D_SAI2_IPG_CLK] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_root_clk", base + 0x48d0, 0, &share_count_sai2); + clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2_shared2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0, &share_count_sai3); + clks[IMX7D_SAI3_IPG_CLK] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_root_clk", base + 0x48e0, 0, &share_count_sai3); clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0); clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate4("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0); clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate4("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0); @@ -860,8 +868,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); - clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]); - /* set uart module clock's parent clock source that must be great then 80MHz */ clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index a81c0385ed64..3799ff82a9b4 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -134,6 +134,15 @@ static inline struct clk *imx_clk_gate2_shared(const char *name, shift, 0x3, 0, &imx_ccm_lock, share_count); } +static inline struct clk *imx_clk_gate2_shared2(const char *name, + const char *parent, void __iomem *reg, u8 shift, + unsigned int *share_count) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT | + CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0, + &imx_ccm_lock, share_count); +} + static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 cgr_val) { diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig new file mode 100644 index 000000000000..380c372d528e --- /dev/null +++ b/drivers/clk/mediatek/Kconfig @@ -0,0 +1,21 @@ +# +# MediaTek SoC drivers +# +config COMMON_CLK_MEDIATEK + bool + ---help--- + Mediatek SoCs' clock support. + +config COMMON_CLK_MT8135 + bool "Clock driver for Mediatek MT8135" + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + ---help--- + This driver supports Mediatek MT8135 clocks. + +config COMMON_CLK_MT8173 + bool "Clock driver for Mediatek MT8173" + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + ---help--- + This driver supports Mediatek MT8173 clocks. diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 95fdfacb2ebf..32e7222e7305 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -1,4 +1,4 @@ -obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o +obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o -obj-y += clk-mt8135.o -obj-y += clk-mt8173.o +obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o +obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c index 2a76901bf04b..d8787bf444eb 100644 --- a/drivers/clk/mediatek/clk-gate.c +++ b/drivers/clk/mediatek/clk-gate.c @@ -97,7 +97,7 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = { .disable = mtk_cg_disable_inv, }; -struct clk * __init mtk_clk_register_gate( +struct clk *mtk_clk_register_gate( const char *name, const char *parent_name, struct regmap *regmap, diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 5ada644e6200..bb30f7063569 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -24,7 +24,7 @@ #include "clk-mtk.h" #include "clk-gate.h" -struct clk_onecell_data * __init mtk_alloc_clk_data(unsigned int clk_num) +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) { int i; struct clk_onecell_data *clk_data; @@ -49,7 +49,7 @@ err_out: return NULL; } -void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, +void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, struct clk_onecell_data *clk_data) { int i; @@ -72,7 +72,7 @@ void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, } } -void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks, +void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, struct clk_onecell_data *clk_data) { int i; @@ -95,7 +95,7 @@ void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks, } } -int __init mtk_clk_register_gates(struct device_node *node, +int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, int num, struct clk_onecell_data *clk_data) { @@ -135,7 +135,7 @@ int __init mtk_clk_register_gates(struct device_node *node, return 0; } -struct clk * __init mtk_clk_register_composite(const struct mtk_composite *mc, +struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) { struct clk *clk; @@ -222,7 +222,7 @@ err_out: return ERR_PTR(ret); } -void __init mtk_clk_register_composites(const struct mtk_composite *mcs, +void mtk_clk_register_composites(const struct mtk_composite *mcs, int num, void __iomem *base, spinlock_t *lock, struct clk_onecell_data *clk_data) { diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 966cab1348da..0c2deac17ce9 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -313,7 +313,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, return clk; } -void __init mtk_clk_register_plls(struct device_node *node, +void mtk_clk_register_plls(struct device_node *node, const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data) { void __iomem *base; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index a4c6684b3019..b736277f0cf6 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -583,6 +583,9 @@ static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17); static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18); static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19); static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23); +static MESON_GATE(emmc_a, HHI_GCLK_MPEG0, 24); +static MESON_GATE(emmc_b, HHI_GCLK_MPEG0, 25); +static MESON_GATE(emmc_c, HHI_GCLK_MPEG0, 26); static MESON_GATE(spi, HHI_GCLK_MPEG0, 30); static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2); @@ -748,6 +751,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_AO_AHB_BUS] = &gxbb_ao_ahb_bus.hw, [CLKID_AO_IFACE] = &gxbb_ao_iface.hw, [CLKID_AO_I2C] = &gxbb_ao_i2c.hw, + [CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw, + [CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw, + [CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw, }, .num = NR_CLKS, }; @@ -847,6 +853,9 @@ static struct clk_gate *gxbb_clk_gates[] = { &gxbb_ao_ahb_bus, &gxbb_ao_iface, &gxbb_ao_i2c, + &gxbb_emmc_a, + &gxbb_emmc_b, + &gxbb_emmc_c, }; static int gxbb_clkc_probe(struct platform_device *pdev) @@ -937,8 +946,4 @@ static struct platform_driver gxbb_driver = { }, }; -static int __init gxbb_clkc_init(void) -{ - return platform_driver_register(&gxbb_driver); -} -device_initcall(gxbb_clkc_init); +builtin_platform_driver(gxbb_driver); diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index a2adf3448b59..217df516de44 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -172,7 +172,7 @@ /* CLKID_CPUCLK */ #define CLKID_HDMI_PLL 2 #define CLKID_FIXED_PLL 3 -#define CLKID_FCLK_DIV2 4 +/* CLKID_FCLK_DIV2 */ #define CLKID_FCLK_DIV3 5 #define CLKID_FCLK_DIV4 6 #define CLKID_FCLK_DIV5 7 @@ -262,8 +262,11 @@ #define CLKID_AO_AHB_BUS 91 #define CLKID_AO_IFACE 92 #define CLKID_AO_I2C 93 +/* CLKID_SD_EMMC_A */ +/* CLKID_SD_EMMC_B */ +/* CLKID_SD_EMMC_C */ -#define NR_CLKS 94 +#define NR_CLKS 97 /* include the CLKIDs that have been made part of the stable DT binding */ #include <dt-bindings/clock/gxbb-clkc.h> diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index 3165da77d525..fddc8ac5faff 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig @@ -24,6 +24,9 @@ config ARMADA_39X_CLK bool select MVEBU_CLK_COMMON +config ARMADA_37XX_CLK + bool + config ARMADA_XP_CLK bool select MVEBU_CLK_COMMON diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 7172ef65693d..d9ae97fb43c4 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile @@ -6,6 +6,9 @@ obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o obj-$(CONFIG_ARMADA_39X_CLK) += armada-39x.o +obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-xtal.o +obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-tbg.o +obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-periph.o obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c new file mode 100644 index 000000000000..45905fc0d75b --- /dev/null +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -0,0 +1,447 @@ +/* + * Marvell Armada 37xx SoC Peripheral clocks + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2 or later. This program is licensed "as is" + * without any warranty of any kind, whether express or implied. + * + * Most of the peripheral clocks can be modelled like this: + * _____ _______ _______ + * TBG-A-P --| | | | | | ______ + * TBG-B-P --| Mux |--| /div1 |--| /div2 |--| Gate |--> perip_clk + * TBG-A-S --| | | | | | |______| + * TBG-B-S --|_____| |_______| |_______| + * + * However some clocks may use only one or two block or and use the + * xtal clock as parent. + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define TBG_SEL 0x0 +#define DIV_SEL0 0x4 +#define DIV_SEL1 0x8 +#define DIV_SEL2 0xC +#define CLK_SEL 0x10 +#define CLK_DIS 0x14 + +struct clk_periph_driver_data { + struct clk_hw_onecell_data *hw_data; + spinlock_t lock; +}; + +struct clk_double_div { + struct clk_hw hw; + void __iomem *reg1; + u8 shift1; + void __iomem *reg2; + u8 shift2; +}; + +#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) + +struct clk_periph_data { + const char *name; + const char * const *parent_names; + int num_parents; + struct clk_hw *mux_hw; + struct clk_hw *rate_hw; + struct clk_hw *gate_hw; + bool is_double_div; +}; + +static const struct clk_div_table clk_table6[] = { + { .val = 1, .div = 1, }, + { .val = 2, .div = 2, }, + { .val = 3, .div = 3, }, + { .val = 4, .div = 4, }, + { .val = 5, .div = 5, }, + { .val = 6, .div = 6, }, + { .val = 0, .div = 0, }, /* last entry */ +}; + +static const struct clk_div_table clk_table1[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 0, }, /* last entry */ +}; + +static const struct clk_div_table clk_table2[] = { + { .val = 0, .div = 2, }, + { .val = 1, .div = 4, }, + { .val = 0, .div = 0, }, /* last entry */ +}; +static const struct clk_ops clk_double_div_ops; + +#define PERIPH_GATE(_name, _bit) \ +struct clk_gate gate_##_name = { \ + .reg = (void *)CLK_DIS, \ + .bit_idx = _bit, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_gate_ops, \ + } \ +}; + +#define PERIPH_MUX(_name, _shift) \ +struct clk_mux mux_##_name = { \ + .reg = (void *)TBG_SEL, \ + .shift = _shift, \ + .mask = 3, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_mux_ro_ops, \ + } \ +}; + +#define PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2) \ +struct clk_double_div rate_##_name = { \ + .reg1 = (void *)_reg1, \ + .reg2 = (void *)_reg2, \ + .shift1 = _shift1, \ + .shift2 = _shift2, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_double_div_ops, \ + } \ +}; + +#define PERIPH_DIV(_name, _reg, _shift, _table) \ +struct clk_divider rate_##_name = { \ + .reg = (void *)_reg, \ + .table = _table, \ + .shift = _shift, \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_divider_ro_ops, \ + } \ +}; + +#define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\ +static PERIPH_GATE(_name, _bit); \ +static PERIPH_MUX(_name, _shift); \ +static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); + +#define PERIPH_CLK_FULL(_name, _bit, _shift, _reg, _shift1, _table) \ +static PERIPH_GATE(_name, _bit); \ +static PERIPH_MUX(_name, _shift); \ +static PERIPH_DIV(_name, _reg, _shift1, _table); + +#define PERIPH_CLK_GATE_DIV(_name, _bit, _reg, _shift, _table) \ +static PERIPH_GATE(_name, _bit); \ +static PERIPH_DIV(_name, _reg, _shift, _table); + +#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \ +static PERIPH_MUX(_name, _shift); \ +static PERIPH_DIV(_name, _reg, _shift_div, _table); + +#define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\ +static PERIPH_MUX(_name, _shift); \ +static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); + +#define REF_CLK_FULL(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ + .mux_hw = &mux_##_name.hw, \ + .gate_hw = &gate_##_name.hw, \ + .rate_hw = &rate_##_name.hw, \ + } + +#define REF_CLK_FULL_DD(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ + .mux_hw = &mux_##_name.hw, \ + .gate_hw = &gate_##_name.hw, \ + .rate_hw = &rate_##_name.hw, \ + .is_double_div = true, \ + } + +#define REF_CLK_GATE(_name, _parent_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ _parent_name}, \ + .num_parents = 1, \ + .gate_hw = &gate_##_name.hw, \ + } + +#define REF_CLK_GATE_DIV(_name, _parent_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ _parent_name}, \ + .num_parents = 1, \ + .gate_hw = &gate_##_name.hw, \ + .rate_hw = &rate_##_name.hw, \ + } + +#define REF_CLK_MUX_DIV(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ + .mux_hw = &mux_##_name.hw, \ + .rate_hw = &rate_##_name.hw, \ + } + +#define REF_CLK_MUX_DD(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ + .mux_hw = &mux_##_name.hw, \ + .rate_hw = &rate_##_name.hw, \ + .is_double_div = true, \ + } + +/* NB periph clocks */ +PERIPH_CLK_FULL_DD(mmc, 2, 0, DIV_SEL2, DIV_SEL2, 16, 13); +PERIPH_CLK_FULL_DD(sata_host, 3, 2, DIV_SEL2, DIV_SEL2, 10, 7); +PERIPH_CLK_FULL_DD(sec_at, 6, 4, DIV_SEL1, DIV_SEL1, 3, 0); +PERIPH_CLK_FULL_DD(sec_dap, 7, 6, DIV_SEL1, DIV_SEL1, 9, 6); +PERIPH_CLK_FULL_DD(tscem, 8, 8, DIV_SEL1, DIV_SEL1, 15, 12); +PERIPH_CLK_FULL(tscem_tmx, 10, 10, DIV_SEL1, 18, clk_table6); +static PERIPH_GATE(avs, 11); +PERIPH_CLK_FULL_DD(pwm, 13, 14, DIV_SEL0, DIV_SEL0, 3, 0); +PERIPH_CLK_FULL_DD(sqf, 12, 12, DIV_SEL1, DIV_SEL1, 27, 24); +static PERIPH_GATE(i2c_2, 16); +static PERIPH_GATE(i2c_1, 17); +PERIPH_CLK_GATE_DIV(ddr_phy, 19, DIV_SEL0, 18, clk_table2); +PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12); +PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6); +PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6); +PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); +PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); + +static struct clk_periph_data data_nb[] ={ + REF_CLK_FULL_DD(mmc), + REF_CLK_FULL_DD(sata_host), + REF_CLK_FULL_DD(sec_at), + REF_CLK_FULL_DD(sec_dap), + REF_CLK_FULL_DD(tscem), + REF_CLK_FULL(tscem_tmx), + REF_CLK_GATE(avs, "xtal"), + REF_CLK_FULL_DD(sqf), + REF_CLK_FULL_DD(pwm), + REF_CLK_GATE(i2c_2, "xtal"), + REF_CLK_GATE(i2c_1, "xtal"), + REF_CLK_GATE_DIV(ddr_phy, "TBG-A-S"), + REF_CLK_FULL_DD(ddr_fclk), + REF_CLK_FULL(trace), + REF_CLK_FULL(counter), + REF_CLK_FULL_DD(eip97), + REF_CLK_MUX_DIV(cpu), + { }, +}; + +/* SB periph clocks */ +PERIPH_CLK_MUX_DD(gbe_50, 6, DIV_SEL2, DIV_SEL2, 6, 9); +PERIPH_CLK_MUX_DD(gbe_core, 8, DIV_SEL1, DIV_SEL1, 18, 21); +PERIPH_CLK_MUX_DD(gbe_125, 10, DIV_SEL1, DIV_SEL1, 6, 9); +static PERIPH_GATE(gbe1_50, 0); +static PERIPH_GATE(gbe0_50, 1); +static PERIPH_GATE(gbe1_125, 2); +static PERIPH_GATE(gbe0_125, 3); +PERIPH_CLK_GATE_DIV(gbe1_core, 4, DIV_SEL1, 13, clk_table1); +PERIPH_CLK_GATE_DIV(gbe0_core, 5, DIV_SEL1, 14, clk_table1); +PERIPH_CLK_GATE_DIV(gbe_bm, 12, DIV_SEL1, 0, clk_table1); +PERIPH_CLK_FULL_DD(sdio, 11, 14, DIV_SEL0, DIV_SEL0, 3, 6); +PERIPH_CLK_FULL_DD(usb32_usb2_sys, 16, 16, DIV_SEL0, DIV_SEL0, 9, 12); +PERIPH_CLK_FULL_DD(usb32_ss_sys, 17, 18, DIV_SEL0, DIV_SEL0, 15, 18); + +static struct clk_periph_data data_sb[] = { + REF_CLK_MUX_DD(gbe_50), + REF_CLK_MUX_DD(gbe_core), + REF_CLK_MUX_DD(gbe_125), + REF_CLK_GATE(gbe1_50, "gbe_50"), + REF_CLK_GATE(gbe0_50, "gbe_50"), + REF_CLK_GATE(gbe1_125, "gbe_125"), + REF_CLK_GATE(gbe0_125, "gbe_125"), + REF_CLK_GATE_DIV(gbe1_core, "gbe_core"), + REF_CLK_GATE_DIV(gbe0_core, "gbe_core"), + REF_CLK_GATE_DIV(gbe_bm, "gbe_core"), + REF_CLK_FULL_DD(sdio), + REF_CLK_FULL_DD(usb32_usb2_sys), + REF_CLK_FULL_DD(usb32_ss_sys), + { }, +}; + +static unsigned int get_div(void __iomem *reg, int shift) +{ + u32 val; + + val = (readl(reg) >> shift) & 0x7; + if (val > 6) + return 0; + return val; +} + +static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_double_div *double_div = to_clk_double_div(hw); + unsigned int div; + + div = get_div(double_div->reg1, double_div->shift1); + div *= get_div(double_div->reg2, double_div->shift2); + + return DIV_ROUND_UP_ULL((u64)parent_rate, div); +} + +static const struct clk_ops clk_double_div_ops = { + .recalc_rate = clk_double_div_recalc_rate, +}; + +static const struct of_device_id armada_3700_periph_clock_of_match[] = { + { .compatible = "marvell,armada-3700-periph-clock-nb", + .data = data_nb, }, + { .compatible = "marvell,armada-3700-periph-clock-sb", + .data = data_sb, }, + { } +}; +static int armada_3700_add_composite_clk(const struct clk_periph_data *data, + void __iomem *reg, spinlock_t *lock, + struct device *dev, struct clk_hw *hw) +{ + const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, + *rate_ops = NULL; + struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *rate_hw = NULL; + + if (data->mux_hw) { + struct clk_mux *mux; + + mux_hw = data->mux_hw; + mux = to_clk_mux(mux_hw); + mux->lock = lock; + mux_ops = mux_hw->init->ops; + mux->reg = reg + (u64)mux->reg; + } + + if (data->gate_hw) { + struct clk_gate *gate; + + gate_hw = data->gate_hw; + gate = to_clk_gate(gate_hw); + gate->lock = lock; + gate_ops = gate_hw->init->ops; + gate->reg = reg + (u64)gate->reg; + } + + if (data->rate_hw) { + rate_hw = data->rate_hw; + rate_ops = rate_hw->init->ops; + if (data->is_double_div) { + struct clk_double_div *rate; + + rate = to_clk_double_div(rate_hw); + rate->reg1 = reg + (u64)rate->reg1; + rate->reg2 = reg + (u64)rate->reg2; + } else { + struct clk_divider *rate = to_clk_divider(rate_hw); + const struct clk_div_table *clkt; + int table_size = 0; + + rate->reg = reg + (u64)rate->reg; + for (clkt = rate->table; clkt->div; clkt++) + table_size++; + rate->width = order_base_2(table_size); + rate->lock = lock; + } + } + + hw = clk_hw_register_composite(dev, data->name, data->parent_names, + data->num_parents, mux_hw, + mux_ops, rate_hw, rate_ops, + gate_hw, gate_ops, CLK_IGNORE_UNUSED); + + if (IS_ERR(hw)) + return PTR_ERR(hw); + + return 0; +} + +static int armada_3700_periph_clock_probe(struct platform_device *pdev) +{ + struct clk_periph_driver_data *driver_data; + struct device_node *np = pdev->dev.of_node; + const struct clk_periph_data *data; + struct device *dev = &pdev->dev; + int num_periph = 0, i, ret; + struct resource *res; + void __iomem *reg; + + data = of_device_get_match_data(dev); + if (!data) + return -ENODEV; + + while (data[num_periph].name) + num_periph++; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(dev, res); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); + if (!driver_data) + return -ENOMEM; + + driver_data->hw_data = devm_kzalloc(dev, sizeof(*driver_data->hw_data) + + sizeof(*driver_data->hw_data->hws) * num_periph, + GFP_KERNEL); + if (!driver_data->hw_data) + return -ENOMEM; + driver_data->hw_data->num = num_periph; + + spin_lock_init(&driver_data->lock); + + for (i = 0; i < num_periph; i++) { + struct clk_hw *hw = driver_data->hw_data->hws[i]; + + if (armada_3700_add_composite_clk(&data[i], reg, + &driver_data->lock, dev, hw)) + dev_err(dev, "Can't register periph clock %s\n", + data[i].name); + + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, + driver_data->hw_data); + if (ret) { + for (i = 0; i < num_periph; i++) + clk_hw_unregister(driver_data->hw_data->hws[i]); + return ret; + } + + platform_set_drvdata(pdev, driver_data); + return 0; +} + +static int armada_3700_periph_clock_remove(struct platform_device *pdev) +{ + struct clk_periph_driver_data *data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *hw_data = data->hw_data; + int i; + + of_clk_del_provider(pdev->dev.of_node); + + for (i = 0; i < hw_data->num; i++) + clk_hw_unregister(hw_data->hws[i]); + + return 0; +} + +static struct platform_driver armada_3700_periph_clock_driver = { + .probe = armada_3700_periph_clock_probe, + .remove = armada_3700_periph_clock_remove, + .driver = { + .name = "marvell-armada-3700-periph-clock", + .of_match_table = armada_3700_periph_clock_of_match, + }, +}; + +builtin_platform_driver(armada_3700_periph_clock_driver); diff --git a/drivers/clk/mvebu/armada-37xx-tbg.c b/drivers/clk/mvebu/armada-37xx-tbg.c new file mode 100644 index 000000000000..aa80db11f543 --- /dev/null +++ b/drivers/clk/mvebu/armada-37xx-tbg.c @@ -0,0 +1,158 @@ +/* + * Marvell Armada 37xx SoC Time Base Generator clocks + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2 or later. This program is licensed "as is" + * without any warranty of any kind, whether express or implied. + */ + +#include <linux/clk-provider.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define NUM_TBG 4 + +#define TBG_CTRL0 0x4 +#define TBG_CTRL1 0x8 +#define TBG_CTRL7 0x20 +#define TBG_CTRL8 0x30 + +#define TBG_DIV_MASK 0x1FF + +#define TBG_A_REFDIV 0 +#define TBG_B_REFDIV 16 + +#define TBG_A_FBDIV 2 +#define TBG_B_FBDIV 18 + +#define TBG_A_VCODIV_SE 0 +#define TBG_B_VCODIV_SE 16 + +#define TBG_A_VCODIV_DIFF 1 +#define TBG_B_VCODIV_DIFF 17 + +struct tbg_def { + char *name; + u32 refdiv_offset; + u32 fbdiv_offset; + u32 vcodiv_reg; + u32 vcodiv_offset; +}; + +static const struct tbg_def tbg[NUM_TBG] = { + {"TBG-A-P", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL8, TBG_A_VCODIV_DIFF}, + {"TBG-B-P", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL8, TBG_B_VCODIV_DIFF}, + {"TBG-A-S", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL1, TBG_A_VCODIV_SE}, + {"TBG-B-S", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL1, TBG_B_VCODIV_SE}, +}; + +static unsigned int tbg_get_mult(void __iomem *reg, const struct tbg_def *ptbg) +{ + u32 val; + + val = readl(reg + TBG_CTRL0); + + return ((val >> ptbg->fbdiv_offset) & TBG_DIV_MASK) << 2; +} + +static unsigned int tbg_get_div(void __iomem *reg, const struct tbg_def *ptbg) +{ + u32 val; + unsigned int div; + + val = readl(reg + TBG_CTRL7); + + div = (val >> ptbg->refdiv_offset) & TBG_DIV_MASK; + if (div == 0) + div = 1; + val = readl(reg + ptbg->vcodiv_reg); + + div *= 1 << ((val >> ptbg->vcodiv_offset) & TBG_DIV_MASK); + + return div; +} + + +static int armada_3700_tbg_clock_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct clk_hw_onecell_data *hw_tbg_data; + struct device *dev = &pdev->dev; + const char *parent_name; + struct resource *res; + struct clk *parent; + void __iomem *reg; + int i, ret; + + hw_tbg_data = devm_kzalloc(&pdev->dev, sizeof(*hw_tbg_data) + + sizeof(*hw_tbg_data->hws) * NUM_TBG, + GFP_KERNEL); + if (!hw_tbg_data) + return -ENOMEM; + hw_tbg_data->num = NUM_TBG; + platform_set_drvdata(pdev, hw_tbg_data); + + parent = devm_clk_get(dev, NULL); + if (IS_ERR(parent)) { + dev_err(dev, "Could get the clock parent\n"); + return -EINVAL; + } + parent_name = __clk_get_name(parent); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(dev, res); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + for (i = 0; i < NUM_TBG; i++) { + const char *name; + unsigned int mult, div; + + name = tbg[i].name; + mult = tbg_get_mult(reg, &tbg[i]); + div = tbg_get_div(reg, &tbg[i]); + hw_tbg_data->hws[i] = clk_hw_register_fixed_factor(NULL, name, + parent_name, 0, mult, div); + if (IS_ERR(hw_tbg_data->hws[i])) + dev_err(dev, "Can't register TBG clock %s\n", name); + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, hw_tbg_data); + + return ret; +} + +static int armada_3700_tbg_clock_remove(struct platform_device *pdev) +{ + int i; + struct clk_hw_onecell_data *hw_tbg_data = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + for (i = 0; i < hw_tbg_data->num; i++) + clk_hw_unregister_fixed_factor(hw_tbg_data->hws[i]); + + return 0; +} + +static const struct of_device_id armada_3700_tbg_clock_of_match[] = { + { .compatible = "marvell,armada-3700-tbg-clock", }, + { } +}; + +static struct platform_driver armada_3700_tbg_clock_driver = { + .probe = armada_3700_tbg_clock_probe, + .remove = armada_3700_tbg_clock_remove, + .driver = { + .name = "marvell-armada-3700-tbg-clock", + .of_match_table = armada_3700_tbg_clock_of_match, + }, +}; + +builtin_platform_driver(armada_3700_tbg_clock_driver); diff --git a/drivers/clk/mvebu/armada-37xx-xtal.c b/drivers/clk/mvebu/armada-37xx-xtal.c new file mode 100644 index 000000000000..612d65ede10a --- /dev/null +++ b/drivers/clk/mvebu/armada-37xx-xtal.c @@ -0,0 +1,91 @@ +/* + * Marvell Armada 37xx SoC xtal clocks + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/clk-provider.h> +#include <linux/mfd/syscon.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define NB_GPIO1_LATCH 0xC +#define XTAL_MODE BIT(31) + +static int armada_3700_xtal_clock_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const char *xtal_name = "xtal"; + struct device_node *parent; + struct regmap *regmap; + struct clk_hw *xtal_hw; + unsigned int rate; + u32 reg; + int ret; + + xtal_hw = devm_kzalloc(&pdev->dev, sizeof(*xtal_hw), GFP_KERNEL); + if (!xtal_hw) + return -ENOMEM; + + platform_set_drvdata(pdev, xtal_hw); + + parent = np->parent; + if (!parent) { + dev_err(&pdev->dev, "no parent\n"); + return -ENODEV; + } + + regmap = syscon_node_to_regmap(parent); + if (IS_ERR(regmap)) { + dev_err(&pdev->dev, "cannot get regmap\n"); + return PTR_ERR(regmap); + } + + ret = regmap_read(regmap, NB_GPIO1_LATCH, ®); + if (ret) { + dev_err(&pdev->dev, "cannot read from regmap\n"); + return ret; + } + + if (reg & XTAL_MODE) + rate = 40000000; + else + rate = 25000000; + + of_property_read_string_index(np, "clock-output-names", 0, &xtal_name); + xtal_hw = clk_hw_register_fixed_rate(NULL, xtal_name, NULL, 0, rate); + if (IS_ERR(xtal_hw)) + return PTR_ERR(xtal_hw); + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, xtal_hw); + + return ret; +} + +static int armada_3700_xtal_clock_remove(struct platform_device *pdev) +{ + of_clk_del_provider(pdev->dev.of_node); + + return 0; +} + +static const struct of_device_id armada_3700_xtal_clock_of_match[] = { + { .compatible = "marvell,armada-3700-xtal-clock", }, + { } +}; + +static struct platform_driver armada_3700_xtal_clock_driver = { + .probe = armada_3700_xtal_clock_probe, + .remove = armada_3700_xtal_clock_remove, + .driver = { + .name = "marvell-armada-3700-xtal-clock", + .of_match_table = armada_3700_xtal_clock_of_match, + }, +}; + +builtin_platform_driver(armada_3700_xtal_clock_driver); diff --git a/drivers/clk/mvebu/armada-39x.c b/drivers/clk/mvebu/armada-39x.c index efb974df9822..4fdfd32247a9 100644 --- a/drivers/clk/mvebu/armada-39x.c +++ b/drivers/clk/mvebu/armada-39x.c @@ -142,6 +142,8 @@ static const struct clk_gating_soc_desc armada_39x_gating_desc[] __initconst = { { "pex3", NULL, 7 }, { "pex0", NULL, 8 }, { "usb3h0", NULL, 9 }, + { "usb3h1", NULL, 10 }, + { "sata0", NULL, 15 }, { "sdio", NULL, 17 }, { "xor0", NULL, 22 }, { "xor1", NULL, 28 }, diff --git a/drivers/clk/nxp/clk-lpc18xx-creg.c b/drivers/clk/nxp/clk-lpc18xx-creg.c index 9e35749dafdf..c6e802e7e6ec 100644 --- a/drivers/clk/nxp/clk-lpc18xx-creg.c +++ b/drivers/clk/nxp/clk-lpc18xx-creg.c @@ -184,7 +184,8 @@ static void __init lpc18xx_creg_clk_init(struct device_node *np) of_clk_add_provider(np, of_clk_src_onecell_get, &clk_creg_early_data); } -CLK_OF_DECLARE(lpc18xx_creg_clk, "nxp,lpc1850-creg-clk", lpc18xx_creg_clk_init); +CLK_OF_DECLARE_DRIVER(lpc18xx_creg_clk, "nxp,lpc1850-creg-clk", + lpc18xx_creg_clk_init); static struct clk *clk_creg[CREG_CLK_MAX]; static struct clk_onecell_data clk_creg_data = { diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 95e3b3e0fa1c..1e7c86f618c1 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -87,6 +87,23 @@ config MSM_LCC_8960 Say Y if you want to use audio devices such as i2s, pcm, SLIMBus, etc. +config MDM_GCC_9615 + tristate "MDM9615 Global Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the global clock controller on mdm9615 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + i2c, USB, SD/eMMC, etc. + +config MDM_LCC_9615 + tristate "MDM9615 LPASS Clock Controller" + select MDM_GCC_9615 + depends on COMMON_CLK_QCOM + help + Support for the LPASS clock controller on mdm9615 devices. + Say Y if you want to use audio devices such as i2s, pcm, + SLIMBus, etc. + config MSM_MMCC_8960 tristate "MSM8960 Multimedia Clock Controller" select MSM_GCC_8960 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 2a25f4e75f49..1fb1f5476cb0 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -12,17 +12,20 @@ clk-qcom-y += clk-regmap-mux.o clk-qcom-y += reset.o clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o +# Keep alphabetically sorted by config obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o +obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o +obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o -obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o +obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c index 3cd1af0af0d9..b593065de8db 100644 --- a/drivers/clk/qcom/gcc-ipq4019.c +++ b/drivers/clk/qcom/gcc-ipq4019.c @@ -1332,7 +1332,6 @@ static struct platform_driver gcc_ipq4019_driver = { .probe = gcc_ipq4019_probe, .driver = { .name = "qcom,gcc-ipq4019", - .owner = THIS_MODULE, .of_match_table = gcc_ipq4019_match_table, }, }; diff --git a/drivers/clk/qcom/gcc-mdm9615.c b/drivers/clk/qcom/gcc-mdm9615.c new file mode 100644 index 000000000000..0f648fcb2b65 --- /dev/null +++ b/drivers/clk/qcom/gcc-mdm9615.c @@ -0,0 +1,1727 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) BayLibre, SAS. + * Author : Neil Armstrong <narmstrong@baylibre.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,gcc-mdm9615.h> +#include <dt-bindings/reset/qcom,gcc-mdm9615.h> + +#include "common.h" +#include "clk-regmap.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" + +static struct clk_fixed_factor cxo = { + .mult = 1, + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "cxo", + .parent_names = (const char *[]){ "cxo_board" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_pll pll0 = { + .l_reg = 0x30c4, + .m_reg = 0x30c8, + .n_reg = 0x30cc, + .config_reg = 0x30d4, + .mode_reg = 0x30c0, + .status_reg = 0x30d8, + .status_bit = 16, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pll0", + .parent_names = (const char *[]){ "cxo" }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap pll0_vote = { + .enable_reg = 0x34c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "pll0_vote", + .parent_names = (const char *[]){ "pll8" }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static struct clk_regmap pll4_vote = { + .enable_reg = 0x34c0, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "pll4_vote", + .parent_names = (const char *[]){ "pll4" }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static struct clk_pll pll8 = { + .l_reg = 0x3144, + .m_reg = 0x3148, + .n_reg = 0x314c, + .config_reg = 0x3154, + .mode_reg = 0x3140, + .status_reg = 0x3158, + .status_bit = 16, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pll8", + .parent_names = (const char *[]){ "cxo" }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap pll8_vote = { + .enable_reg = 0x34c0, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "pll8_vote", + .parent_names = (const char *[]){ "pll8" }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static struct clk_pll pll14 = { + .l_reg = 0x31c4, + .m_reg = 0x31c8, + .n_reg = 0x31cc, + .config_reg = 0x31d4, + .mode_reg = 0x31c0, + .status_reg = 0x31d8, + .status_bit = 16, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pll14", + .parent_names = (const char *[]){ "cxo" }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap pll14_vote = { + .enable_reg = 0x34c0, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "pll14_vote", + .parent_names = (const char *[]){ "pll14" }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +enum { + P_CXO, + P_PLL8, + P_PLL14, +}; + +static const struct parent_map gcc_cxo_pll8_map[] = { + { P_CXO, 0 }, + { P_PLL8, 3 } +}; + +static const char * const gcc_cxo_pll8[] = { + "cxo", + "pll8_vote", +}; + +static const struct parent_map gcc_cxo_pll14_map[] = { + { P_CXO, 0 }, + { P_PLL14, 4 } +}; + +static const char * const gcc_cxo_pll14[] = { + "cxo", + "pll14_vote", +}; + +static const struct parent_map gcc_cxo_map[] = { + { P_CXO, 0 }, +}; + +static const char * const gcc_cxo[] = { + "cxo", +}; + +static struct freq_tbl clk_tbl_gsbi_uart[] = { + { 1843200, P_PLL8, 2, 6, 625 }, + { 3686400, P_PLL8, 2, 12, 625 }, + { 7372800, P_PLL8, 2, 24, 625 }, + { 14745600, P_PLL8, 2, 48, 625 }, + { 16000000, P_PLL8, 4, 1, 6 }, + { 24000000, P_PLL8, 4, 1, 4 }, + { 32000000, P_PLL8, 4, 1, 3 }, + { 40000000, P_PLL8, 1, 5, 48 }, + { 46400000, P_PLL8, 1, 29, 240 }, + { 48000000, P_PLL8, 4, 1, 2 }, + { 51200000, P_PLL8, 1, 2, 15 }, + { 56000000, P_PLL8, 1, 7, 48 }, + { 58982400, P_PLL8, 1, 96, 625 }, + { 64000000, P_PLL8, 2, 1, 3 }, + { } +}; + +static struct clk_rcg gsbi1_uart_src = { + .ns_reg = 0x29d4, + .md_reg = 0x29d0, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_uart, + .clkr = { + .enable_reg = 0x29d4, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi1_uart_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi1_uart_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 10, + .clkr = { + .enable_reg = 0x29d4, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi1_uart_clk", + .parent_names = (const char *[]){ + "gsbi1_uart_src", + }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi2_uart_src = { + .ns_reg = 0x29f4, + .md_reg = 0x29f0, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_uart, + .clkr = { + .enable_reg = 0x29f4, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi2_uart_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi2_uart_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 6, + .clkr = { + .enable_reg = 0x29f4, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi2_uart_clk", + .parent_names = (const char *[]){ + "gsbi2_uart_src", + }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi3_uart_src = { + .ns_reg = 0x2a14, + .md_reg = 0x2a10, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_uart, + .clkr = { + .enable_reg = 0x2a14, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi3_uart_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi3_uart_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 2, + .clkr = { + .enable_reg = 0x2a14, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi3_uart_clk", + .parent_names = (const char *[]){ + "gsbi3_uart_src", + }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi4_uart_src = { + .ns_reg = 0x2a34, + .md_reg = 0x2a30, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_uart, + .clkr = { + .enable_reg = 0x2a34, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi4_uart_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi4_uart_clk = { + .halt_reg = 0x2fd0, + .halt_bit = 26, + .clkr = { + .enable_reg = 0x2a34, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi4_uart_clk", + .parent_names = (const char *[]){ + "gsbi4_uart_src", + }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi5_uart_src = { + .ns_reg = 0x2a54, + .md_reg = 0x2a50, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_uart, + .clkr = { + .enable_reg = 0x2a54, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi5_uart_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi5_uart_clk = { + .halt_reg = 0x2fd0, + .halt_bit = 22, + .clkr = { + .enable_reg = 0x2a54, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi5_uart_clk", + .parent_names = (const char *[]){ + "gsbi5_uart_src", + }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct freq_tbl clk_tbl_gsbi_qup[] = { + { 960000, P_CXO, 4, 1, 5 }, + { 4800000, P_CXO, 4, 0, 1 }, + { 9600000, P_CXO, 2, 0, 1 }, + { 15060000, P_PLL8, 1, 2, 51 }, + { 24000000, P_PLL8, 4, 1, 4 }, + { 25600000, P_PLL8, 1, 1, 15 }, + { 48000000, P_PLL8, 4, 1, 2 }, + { 51200000, P_PLL8, 1, 2, 15 }, + { } +}; + +static struct clk_rcg gsbi1_qup_src = { + .ns_reg = 0x29cc, + .md_reg = 0x29c8, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_qup, + .clkr = { + .enable_reg = 0x29cc, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi1_qup_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi1_qup_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 9, + .clkr = { + .enable_reg = 0x29cc, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi1_qup_clk", + .parent_names = (const char *[]){ "gsbi1_qup_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi2_qup_src = { + .ns_reg = 0x29ec, + .md_reg = 0x29e8, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_qup, + .clkr = { + .enable_reg = 0x29ec, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi2_qup_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi2_qup_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 4, + .clkr = { + .enable_reg = 0x29ec, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi2_qup_clk", + .parent_names = (const char *[]){ "gsbi2_qup_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi3_qup_src = { + .ns_reg = 0x2a0c, + .md_reg = 0x2a08, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_qup, + .clkr = { + .enable_reg = 0x2a0c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi3_qup_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi3_qup_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 0, + .clkr = { + .enable_reg = 0x2a0c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi3_qup_clk", + .parent_names = (const char *[]){ "gsbi3_qup_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi4_qup_src = { + .ns_reg = 0x2a2c, + .md_reg = 0x2a28, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_qup, + .clkr = { + .enable_reg = 0x2a2c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi4_qup_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi4_qup_clk = { + .halt_reg = 0x2fd0, + .halt_bit = 24, + .clkr = { + .enable_reg = 0x2a2c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi4_qup_clk", + .parent_names = (const char *[]){ "gsbi4_qup_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gsbi5_qup_src = { + .ns_reg = 0x2a4c, + .md_reg = 0x2a48, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_gsbi_qup, + .clkr = { + .enable_reg = 0x2a4c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gsbi5_qup_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + }, +}; + +static struct clk_branch gsbi5_qup_clk = { + .halt_reg = 0x2fd0, + .halt_bit = 20, + .clkr = { + .enable_reg = 0x2a4c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gsbi5_qup_clk", + .parent_names = (const char *[]){ "gsbi5_qup_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static const struct freq_tbl clk_tbl_gp[] = { + { 9600000, P_CXO, 2, 0, 0 }, + { 19200000, P_CXO, 1, 0, 0 }, + { } +}; + +static struct clk_rcg gp0_src = { + .ns_reg = 0x2d24, + .md_reg = 0x2d00, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_map, + }, + .freq_tbl = clk_tbl_gp, + .clkr = { + .enable_reg = 0x2d24, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gp0_src", + .parent_names = gcc_cxo, + .num_parents = 1, + .ops = &clk_rcg_ops, + .flags = CLK_SET_PARENT_GATE, + }, + } +}; + +static struct clk_branch gp0_clk = { + .halt_reg = 0x2fd8, + .halt_bit = 7, + .clkr = { + .enable_reg = 0x2d24, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gp0_clk", + .parent_names = (const char *[]){ "gp0_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gp1_src = { + .ns_reg = 0x2d44, + .md_reg = 0x2d40, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_map, + }, + .freq_tbl = clk_tbl_gp, + .clkr = { + .enable_reg = 0x2d44, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gp1_src", + .parent_names = gcc_cxo, + .num_parents = 1, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch gp1_clk = { + .halt_reg = 0x2fd8, + .halt_bit = 6, + .clkr = { + .enable_reg = 0x2d44, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gp1_clk", + .parent_names = (const char *[]){ "gp1_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg gp2_src = { + .ns_reg = 0x2d64, + .md_reg = 0x2d60, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_map, + }, + .freq_tbl = clk_tbl_gp, + .clkr = { + .enable_reg = 0x2d64, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gp2_src", + .parent_names = gcc_cxo, + .num_parents = 1, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch gp2_clk = { + .halt_reg = 0x2fd8, + .halt_bit = 5, + .clkr = { + .enable_reg = 0x2d64, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gp2_clk", + .parent_names = (const char *[]){ "gp2_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch pmem_clk = { + .hwcg_reg = 0x25a0, + .hwcg_bit = 6, + .halt_reg = 0x2fc8, + .halt_bit = 20, + .clkr = { + .enable_reg = 0x25a0, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "pmem_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_rcg prng_src = { + .ns_reg = 0x2e80, + .p = { + .pre_div_shift = 3, + .pre_div_width = 4, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "prng_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + }, + }, +}; + +static struct clk_branch prng_clk = { + .halt_reg = 0x2fd8, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 10, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "prng_clk", + .parent_names = (const char *[]){ "prng_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + }, + }, +}; + +static const struct freq_tbl clk_tbl_sdc[] = { + { 144000, P_CXO, 1, 1, 133 }, + { 400000, P_PLL8, 4, 1, 240 }, + { 16000000, P_PLL8, 4, 1, 6 }, + { 17070000, P_PLL8, 1, 2, 45 }, + { 20210000, P_PLL8, 1, 1, 19 }, + { 24000000, P_PLL8, 4, 1, 4 }, + { 38400000, P_PLL8, 2, 1, 5 }, + { 48000000, P_PLL8, 4, 1, 2 }, + { 64000000, P_PLL8, 3, 1, 2 }, + { 76800000, P_PLL8, 1, 1, 5 }, + { } +}; + +static struct clk_rcg sdc1_src = { + .ns_reg = 0x282c, + .md_reg = 0x2828, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_sdc, + .clkr = { + .enable_reg = 0x282c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "sdc1_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch sdc1_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 6, + .clkr = { + .enable_reg = 0x282c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "sdc1_clk", + .parent_names = (const char *[]){ "sdc1_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg sdc2_src = { + .ns_reg = 0x284c, + .md_reg = 0x2848, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_sdc, + .clkr = { + .enable_reg = 0x284c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "sdc2_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch sdc2_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 5, + .clkr = { + .enable_reg = 0x284c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "sdc2_clk", + .parent_names = (const char *[]){ "sdc2_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static const struct freq_tbl clk_tbl_usb[] = { + { 60000000, P_PLL8, 1, 5, 32 }, + { } +}; + +static struct clk_rcg usb_hs1_xcvr_src = { + .ns_reg = 0x290c, + .md_reg = 0x2908, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_usb, + .clkr = { + .enable_reg = 0x290c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "usb_hs1_xcvr_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch usb_hs1_xcvr_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 0, + .clkr = { + .enable_reg = 0x290c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "usb_hs1_xcvr_clk", + .parent_names = (const char *[]){ "usb_hs1_xcvr_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg usb_hsic_xcvr_fs_src = { + .ns_reg = 0x2928, + .md_reg = 0x2924, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_usb, + .clkr = { + .enable_reg = 0x2928, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "usb_hsic_xcvr_fs_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch usb_hsic_xcvr_fs_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 9, + .clkr = { + .enable_reg = 0x2928, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "usb_hsic_xcvr_fs_clk", + .parent_names = + (const char *[]){ "usb_hsic_xcvr_fs_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static const struct freq_tbl clk_tbl_usb_hs1_system[] = { + { 60000000, P_PLL8, 1, 5, 32 }, + { } +}; + +static struct clk_rcg usb_hs1_system_src = { + .ns_reg = 0x36a4, + .md_reg = 0x36a0, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_usb_hs1_system, + .clkr = { + .enable_reg = 0x36a4, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "usb_hs1_system_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch usb_hs1_system_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 4, + .clkr = { + .enable_reg = 0x36a4, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .parent_names = + (const char *[]){ "usb_hs1_system_src" }, + .num_parents = 1, + .name = "usb_hs1_system_clk", + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, + }, +}; + +static const struct freq_tbl clk_tbl_usb_hsic_system[] = { + { 64000000, P_PLL8, 1, 1, 6 }, + { } +}; + +static struct clk_rcg usb_hsic_system_src = { + .ns_reg = 0x2b58, + .md_reg = 0x2b54, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll8_map, + }, + .freq_tbl = clk_tbl_usb_hsic_system, + .clkr = { + .enable_reg = 0x2b58, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "usb_hsic_system_src", + .parent_names = gcc_cxo_pll8, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch usb_hsic_system_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 7, + .clkr = { + .enable_reg = 0x2b58, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .parent_names = + (const char *[]){ "usb_hsic_system_src" }, + .num_parents = 1, + .name = "usb_hsic_system_clk", + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static const struct freq_tbl clk_tbl_usb_hsic_hsic[] = { + { 48000000, P_PLL14, 1, 0, 0 }, + { } +}; + +static struct clk_rcg usb_hsic_hsic_src = { + .ns_reg = 0x2b50, + .md_reg = 0x2b4c, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = gcc_cxo_pll14_map, + }, + .freq_tbl = clk_tbl_usb_hsic_hsic, + .clkr = { + .enable_reg = 0x2b50, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "usb_hsic_hsic_src", + .parent_names = gcc_cxo_pll14, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + } +}; + +static struct clk_branch usb_hsic_hsic_clk = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x2b50, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .parent_names = (const char *[]){ "usb_hsic_hsic_src" }, + .num_parents = 1, + .name = "usb_hsic_hsic_clk", + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch usb_hsic_hsio_cal_clk = { + .halt_reg = 0x2fc8, + .halt_bit = 8, + .clkr = { + .enable_reg = 0x2b48, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .parent_names = (const char *[]){ "cxo" }, + .num_parents = 1, + .name = "usb_hsic_hsio_cal_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch ce1_core_clk = { + .hwcg_reg = 0x2724, + .hwcg_bit = 6, + .halt_reg = 0x2fd4, + .halt_bit = 27, + .clkr = { + .enable_reg = 0x2724, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "ce1_core_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch ce1_h_clk = { + .halt_reg = 0x2fd4, + .halt_bit = 1, + .clkr = { + .enable_reg = 0x2720, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "ce1_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch dma_bam_h_clk = { + .hwcg_reg = 0x25c0, + .hwcg_bit = 6, + .halt_reg = 0x2fc8, + .halt_bit = 12, + .clkr = { + .enable_reg = 0x25c0, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "dma_bam_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch gsbi1_h_clk = { + .hwcg_reg = 0x29c0, + .hwcg_bit = 6, + .halt_reg = 0x2fcc, + .halt_bit = 11, + .clkr = { + .enable_reg = 0x29c0, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gsbi1_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch gsbi2_h_clk = { + .hwcg_reg = 0x29e0, + .hwcg_bit = 6, + .halt_reg = 0x2fcc, + .halt_bit = 7, + .clkr = { + .enable_reg = 0x29e0, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gsbi2_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch gsbi3_h_clk = { + .hwcg_reg = 0x2a00, + .hwcg_bit = 6, + .halt_reg = 0x2fcc, + .halt_bit = 3, + .clkr = { + .enable_reg = 0x2a00, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gsbi3_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch gsbi4_h_clk = { + .hwcg_reg = 0x2a20, + .hwcg_bit = 6, + .halt_reg = 0x2fd0, + .halt_bit = 27, + .clkr = { + .enable_reg = 0x2a20, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gsbi4_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch gsbi5_h_clk = { + .hwcg_reg = 0x2a40, + .hwcg_bit = 6, + .halt_reg = 0x2fd0, + .halt_bit = 23, + .clkr = { + .enable_reg = 0x2a40, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gsbi5_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch usb_hs1_h_clk = { + .hwcg_reg = 0x2900, + .hwcg_bit = 6, + .halt_reg = 0x2fc8, + .halt_bit = 1, + .clkr = { + .enable_reg = 0x2900, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "usb_hs1_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch usb_hsic_h_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 28, + .clkr = { + .enable_reg = 0x2920, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "usb_hsic_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch sdc1_h_clk = { + .hwcg_reg = 0x2820, + .hwcg_bit = 6, + .halt_reg = 0x2fc8, + .halt_bit = 11, + .clkr = { + .enable_reg = 0x2820, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "sdc1_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch sdc2_h_clk = { + .hwcg_reg = 0x2840, + .hwcg_bit = 6, + .halt_reg = 0x2fc8, + .halt_bit = 10, + .clkr = { + .enable_reg = 0x2840, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "sdc2_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch adm0_clk = { + .halt_reg = 0x2fdc, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 14, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "adm0_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch adm0_pbus_clk = { + .hwcg_reg = 0x2208, + .hwcg_bit = 6, + .halt_reg = 0x2fdc, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 13, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "adm0_pbus_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch pmic_arb0_h_clk = { + .halt_reg = 0x2fd8, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 22, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "pmic_arb0_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch pmic_arb1_h_clk = { + .halt_reg = 0x2fd8, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 21, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "pmic_arb1_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch pmic_ssbi2_clk = { + .halt_reg = 0x2fd8, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 23, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "pmic_ssbi2_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch rpm_msg_ram_h_clk = { + .hwcg_reg = 0x27e0, + .hwcg_bit = 6, + .halt_reg = 0x2fd8, + .halt_check = BRANCH_HALT_VOTED, + .halt_bit = 12, + .clkr = { + .enable_reg = 0x3080, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "rpm_msg_ram_h_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_hw *gcc_mdm9615_hws[] = { + &cxo.hw, +}; + +static struct clk_regmap *gcc_mdm9615_clks[] = { + [PLL0] = &pll0.clkr, + [PLL0_VOTE] = &pll0_vote, + [PLL4_VOTE] = &pll4_vote, + [PLL8] = &pll8.clkr, + [PLL8_VOTE] = &pll8_vote, + [PLL14] = &pll14.clkr, + [PLL14_VOTE] = &pll14_vote, + [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr, + [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr, + [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr, + [GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr, + [GSBI3_UART_SRC] = &gsbi3_uart_src.clkr, + [GSBI3_UART_CLK] = &gsbi3_uart_clk.clkr, + [GSBI4_UART_SRC] = &gsbi4_uart_src.clkr, + [GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr, + [GSBI5_UART_SRC] = &gsbi5_uart_src.clkr, + [GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr, + [GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr, + [GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr, + [GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr, + [GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr, + [GSBI3_QUP_SRC] = &gsbi3_qup_src.clkr, + [GSBI3_QUP_CLK] = &gsbi3_qup_clk.clkr, + [GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr, + [GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr, + [GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr, + [GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr, + [GP0_SRC] = &gp0_src.clkr, + [GP0_CLK] = &gp0_clk.clkr, + [GP1_SRC] = &gp1_src.clkr, + [GP1_CLK] = &gp1_clk.clkr, + [GP2_SRC] = &gp2_src.clkr, + [GP2_CLK] = &gp2_clk.clkr, + [PMEM_A_CLK] = &pmem_clk.clkr, + [PRNG_SRC] = &prng_src.clkr, + [PRNG_CLK] = &prng_clk.clkr, + [SDC1_SRC] = &sdc1_src.clkr, + [SDC1_CLK] = &sdc1_clk.clkr, + [SDC2_SRC] = &sdc2_src.clkr, + [SDC2_CLK] = &sdc2_clk.clkr, + [USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_src.clkr, + [USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr, + [USB_HS1_SYSTEM_CLK_SRC] = &usb_hs1_system_src.clkr, + [USB_HS1_SYSTEM_CLK] = &usb_hs1_system_clk.clkr, + [USB_HSIC_XCVR_FS_SRC] = &usb_hsic_xcvr_fs_src.clkr, + [USB_HSIC_XCVR_FS_CLK] = &usb_hsic_xcvr_fs_clk.clkr, + [USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_src.clkr, + [USB_HSIC_SYSTEM_CLK] = &usb_hsic_system_clk.clkr, + [USB_HSIC_HSIC_CLK_SRC] = &usb_hsic_hsic_src.clkr, + [USB_HSIC_HSIC_CLK] = &usb_hsic_hsic_clk.clkr, + [USB_HSIC_HSIO_CAL_CLK] = &usb_hsic_hsio_cal_clk.clkr, + [CE1_CORE_CLK] = &ce1_core_clk.clkr, + [CE1_H_CLK] = &ce1_h_clk.clkr, + [DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr, + [GSBI1_H_CLK] = &gsbi1_h_clk.clkr, + [GSBI2_H_CLK] = &gsbi2_h_clk.clkr, + [GSBI3_H_CLK] = &gsbi3_h_clk.clkr, + [GSBI4_H_CLK] = &gsbi4_h_clk.clkr, + [GSBI5_H_CLK] = &gsbi5_h_clk.clkr, + [USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr, + [USB_HSIC_H_CLK] = &usb_hsic_h_clk.clkr, + [SDC1_H_CLK] = &sdc1_h_clk.clkr, + [SDC2_H_CLK] = &sdc2_h_clk.clkr, + [ADM0_CLK] = &adm0_clk.clkr, + [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr, + [PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr, + [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr, + [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr, + [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr, +}; + +static const struct qcom_reset_map gcc_mdm9615_resets[] = { + [DMA_BAM_RESET] = { 0x25c0, 7 }, + [CE1_H_RESET] = { 0x2720, 7 }, + [CE1_CORE_RESET] = { 0x2724, 7 }, + [SDC1_RESET] = { 0x2830 }, + [SDC2_RESET] = { 0x2850 }, + [ADM0_C2_RESET] = { 0x220c, 4 }, + [ADM0_C1_RESET] = { 0x220c, 3 }, + [ADM0_C0_RESET] = { 0x220c, 2 }, + [ADM0_PBUS_RESET] = { 0x220c, 1 }, + [ADM0_RESET] = { 0x220c }, + [USB_HS1_RESET] = { 0x2910 }, + [USB_HSIC_RESET] = { 0x2934 }, + [GSBI1_RESET] = { 0x29dc }, + [GSBI2_RESET] = { 0x29fc }, + [GSBI3_RESET] = { 0x2a1c }, + [GSBI4_RESET] = { 0x2a3c }, + [GSBI5_RESET] = { 0x2a5c }, + [PDM_RESET] = { 0x2CC0, 12 }, +}; + +static const struct regmap_config gcc_mdm9615_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x3660, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_mdm9615_desc = { + .config = &gcc_mdm9615_regmap_config, + .clks = gcc_mdm9615_clks, + .num_clks = ARRAY_SIZE(gcc_mdm9615_clks), + .resets = gcc_mdm9615_resets, + .num_resets = ARRAY_SIZE(gcc_mdm9615_resets), +}; + +static const struct of_device_id gcc_mdm9615_match_table[] = { + { .compatible = "qcom,gcc-mdm9615" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_mdm9615_match_table); + +static int gcc_mdm9615_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct regmap *regmap; + struct clk *clk; + int i; + + regmap = qcom_cc_map(pdev, &gcc_mdm9615_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + for (i = 0; i < ARRAY_SIZE(gcc_mdm9615_hws); i++) { + clk = devm_clk_register(dev, gcc_mdm9615_hws[i]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + + return qcom_cc_really_probe(pdev, &gcc_mdm9615_desc, regmap); +} + +static struct platform_driver gcc_mdm9615_driver = { + .probe = gcc_mdm9615_probe, + .driver = { + .name = "gcc-mdm9615", + .of_match_table = gcc_mdm9615_match_table, + }, +}; + +static int __init gcc_mdm9615_init(void) +{ + return platform_driver_register(&gcc_mdm9615_driver); +} +core_initcall(gcc_mdm9615_init); + +static void __exit gcc_mdm9615_exit(void) +{ + platform_driver_unregister(&gcc_mdm9615_driver); +} +module_exit(gcc_mdm9615_exit); + +MODULE_DESCRIPTION("QCOM GCC MDM9615 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gcc-mdm9615"); diff --git a/drivers/clk/qcom/lcc-mdm9615.c b/drivers/clk/qcom/lcc-mdm9615.c new file mode 100644 index 000000000000..3237ef4c1197 --- /dev/null +++ b/drivers/clk/qcom/lcc-mdm9615.c @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) BayLibre, SAS. + * Author : Neil Armstrong <narmstrong@baylibre.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,lcc-mdm9615.h> + +#include "common.h" +#include "clk-regmap.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" + +static struct clk_pll pll4 = { + .l_reg = 0x4, + .m_reg = 0x8, + .n_reg = 0xc, + .config_reg = 0x14, + .mode_reg = 0x0, + .status_reg = 0x18, + .status_bit = 16, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pll4", + .parent_names = (const char *[]){ "cxo" }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +enum { + P_CXO, + P_PLL4, +}; + +static const struct parent_map lcc_cxo_pll4_map[] = { + { P_CXO, 0 }, + { P_PLL4, 2 } +}; + +static const char * const lcc_cxo_pll4[] = { + "cxo", + "pll4_vote", +}; + +static struct freq_tbl clk_tbl_aif_osr_492[] = { + { 512000, P_PLL4, 4, 1, 240 }, + { 768000, P_PLL4, 4, 1, 160 }, + { 1024000, P_PLL4, 4, 1, 120 }, + { 1536000, P_PLL4, 4, 1, 80 }, + { 2048000, P_PLL4, 4, 1, 60 }, + { 3072000, P_PLL4, 4, 1, 40 }, + { 4096000, P_PLL4, 4, 1, 30 }, + { 6144000, P_PLL4, 4, 1, 20 }, + { 8192000, P_PLL4, 4, 1, 15 }, + { 12288000, P_PLL4, 4, 1, 10 }, + { 24576000, P_PLL4, 4, 1, 5 }, + { 27000000, P_CXO, 1, 0, 0 }, + { } +}; + +static struct freq_tbl clk_tbl_aif_osr_393[] = { + { 512000, P_PLL4, 4, 1, 192 }, + { 768000, P_PLL4, 4, 1, 128 }, + { 1024000, P_PLL4, 4, 1, 96 }, + { 1536000, P_PLL4, 4, 1, 64 }, + { 2048000, P_PLL4, 4, 1, 48 }, + { 3072000, P_PLL4, 4, 1, 32 }, + { 4096000, P_PLL4, 4, 1, 24 }, + { 6144000, P_PLL4, 4, 1, 16 }, + { 8192000, P_PLL4, 4, 1, 12 }, + { 12288000, P_PLL4, 4, 1, 8 }, + { 24576000, P_PLL4, 4, 1, 4 }, + { 27000000, P_CXO, 1, 0, 0 }, + { } +}; + +static struct clk_rcg mi2s_osr_src = { + .ns_reg = 0x48, + .md_reg = 0x4c, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 24, + .m_val_shift = 8, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = lcc_cxo_pll4_map, + }, + .freq_tbl = clk_tbl_aif_osr_393, + .clkr = { + .enable_reg = 0x48, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "mi2s_osr_src", + .parent_names = lcc_cxo_pll4, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + }, +}; + +static const char * const lcc_mi2s_parents[] = { + "mi2s_osr_src", +}; + +static struct clk_branch mi2s_osr_clk = { + .halt_reg = 0x50, + .halt_bit = 1, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x48, + .enable_mask = BIT(17), + .hw.init = &(struct clk_init_data){ + .name = "mi2s_osr_clk", + .parent_names = lcc_mi2s_parents, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_regmap_div mi2s_div_clk = { + .reg = 0x48, + .shift = 10, + .width = 4, + .clkr = { + .enable_reg = 0x48, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "mi2s_div_clk", + .parent_names = lcc_mi2s_parents, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_branch mi2s_bit_div_clk = { + .halt_reg = 0x50, + .halt_bit = 0, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x48, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "mi2s_bit_div_clk", + .parent_names = (const char *[]){ "mi2s_div_clk" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_regmap_mux mi2s_bit_clk = { + .reg = 0x48, + .shift = 14, + .width = 1, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "mi2s_bit_clk", + .parent_names = (const char *[]){ + "mi2s_bit_div_clk", + "mi2s_codec_clk", + }, + .num_parents = 2, + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +#define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \ +static struct clk_rcg prefix##_osr_src = { \ + .ns_reg = _ns, \ + .md_reg = _md, \ + .mn = { \ + .mnctr_en_bit = 8, \ + .mnctr_reset_bit = 7, \ + .mnctr_mode_shift = 5, \ + .n_val_shift = 24, \ + .m_val_shift = 8, \ + .width = 8, \ + }, \ + .p = { \ + .pre_div_shift = 3, \ + .pre_div_width = 2, \ + }, \ + .s = { \ + .src_sel_shift = 0, \ + .parent_map = lcc_cxo_pll4_map, \ + }, \ + .freq_tbl = clk_tbl_aif_osr_393, \ + .clkr = { \ + .enable_reg = _ns, \ + .enable_mask = BIT(9), \ + .hw.init = &(struct clk_init_data){ \ + .name = #prefix "_osr_src", \ + .parent_names = lcc_cxo_pll4, \ + .num_parents = 2, \ + .ops = &clk_rcg_ops, \ + .flags = CLK_SET_RATE_GATE, \ + }, \ + }, \ +}; \ + \ +static const char * const lcc_##prefix##_parents[] = { \ + #prefix "_osr_src", \ +}; \ + \ +static struct clk_branch prefix##_osr_clk = { \ + .halt_reg = hr, \ + .halt_bit = 1, \ + .halt_check = BRANCH_HALT_ENABLE, \ + .clkr = { \ + .enable_reg = _ns, \ + .enable_mask = BIT(21), \ + .hw.init = &(struct clk_init_data){ \ + .name = #prefix "_osr_clk", \ + .parent_names = lcc_##prefix##_parents, \ + .num_parents = 1, \ + .ops = &clk_branch_ops, \ + .flags = CLK_SET_RATE_PARENT, \ + }, \ + }, \ +}; \ + \ +static struct clk_regmap_div prefix##_div_clk = { \ + .reg = _ns, \ + .shift = 10, \ + .width = 8, \ + .clkr = { \ + .hw.init = &(struct clk_init_data){ \ + .name = #prefix "_div_clk", \ + .parent_names = lcc_##prefix##_parents, \ + .num_parents = 1, \ + .ops = &clk_regmap_div_ops, \ + }, \ + }, \ +}; \ + \ +static struct clk_branch prefix##_bit_div_clk = { \ + .halt_reg = hr, \ + .halt_bit = 0, \ + .halt_check = BRANCH_HALT_ENABLE, \ + .clkr = { \ + .enable_reg = _ns, \ + .enable_mask = BIT(19), \ + .hw.init = &(struct clk_init_data){ \ + .name = #prefix "_bit_div_clk", \ + .parent_names = (const char *[]){ \ + #prefix "_div_clk" \ + }, \ + .num_parents = 1, \ + .ops = &clk_branch_ops, \ + .flags = CLK_SET_RATE_PARENT, \ + }, \ + }, \ +}; \ + \ +static struct clk_regmap_mux prefix##_bit_clk = { \ + .reg = _ns, \ + .shift = 18, \ + .width = 1, \ + .clkr = { \ + .hw.init = &(struct clk_init_data){ \ + .name = #prefix "_bit_clk", \ + .parent_names = (const char *[]){ \ + #prefix "_bit_div_clk", \ + #prefix "_codec_clk", \ + }, \ + .num_parents = 2, \ + .ops = &clk_regmap_mux_closest_ops, \ + .flags = CLK_SET_RATE_PARENT, \ + }, \ + }, \ +} + +CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68); +CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80); +CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74); +CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c); + +static struct freq_tbl clk_tbl_pcm_492[] = { + { 256000, P_PLL4, 4, 1, 480 }, + { 512000, P_PLL4, 4, 1, 240 }, + { 768000, P_PLL4, 4, 1, 160 }, + { 1024000, P_PLL4, 4, 1, 120 }, + { 1536000, P_PLL4, 4, 1, 80 }, + { 2048000, P_PLL4, 4, 1, 60 }, + { 3072000, P_PLL4, 4, 1, 40 }, + { 4096000, P_PLL4, 4, 1, 30 }, + { 6144000, P_PLL4, 4, 1, 20 }, + { 8192000, P_PLL4, 4, 1, 15 }, + { 12288000, P_PLL4, 4, 1, 10 }, + { 24576000, P_PLL4, 4, 1, 5 }, + { 27000000, P_CXO, 1, 0, 0 }, + { } +}; + +static struct freq_tbl clk_tbl_pcm_393[] = { + { 256000, P_PLL4, 4, 1, 384 }, + { 512000, P_PLL4, 4, 1, 192 }, + { 768000, P_PLL4, 4, 1, 128 }, + { 1024000, P_PLL4, 4, 1, 96 }, + { 1536000, P_PLL4, 4, 1, 64 }, + { 2048000, P_PLL4, 4, 1, 48 }, + { 3072000, P_PLL4, 4, 1, 32 }, + { 4096000, P_PLL4, 4, 1, 24 }, + { 6144000, P_PLL4, 4, 1, 16 }, + { 8192000, P_PLL4, 4, 1, 12 }, + { 12288000, P_PLL4, 4, 1, 8 }, + { 24576000, P_PLL4, 4, 1, 4 }, + { 27000000, P_CXO, 1, 0, 0 }, + { } +}; + +static struct clk_rcg pcm_src = { + .ns_reg = 0x54, + .md_reg = 0x58, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 16, + .m_val_shift = 16, + .width = 16, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = lcc_cxo_pll4_map, + }, + .freq_tbl = clk_tbl_pcm_393, + .clkr = { + .enable_reg = 0x54, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "pcm_src", + .parent_names = lcc_cxo_pll4, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + }, +}; + +static struct clk_branch pcm_clk_out = { + .halt_reg = 0x5c, + .halt_bit = 0, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x54, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "pcm_clk_out", + .parent_names = (const char *[]){ "pcm_src" }, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_regmap_mux pcm_clk = { + .reg = 0x54, + .shift = 10, + .width = 1, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "pcm_clk", + .parent_names = (const char *[]){ + "pcm_clk_out", + "pcm_codec_clk", + }, + .num_parents = 2, + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_rcg slimbus_src = { + .ns_reg = 0xcc, + .md_reg = 0xd0, + .mn = { + .mnctr_en_bit = 8, + .mnctr_reset_bit = 7, + .mnctr_mode_shift = 5, + .n_val_shift = 24, + .m_val_shift = 8, + .width = 8, + }, + .p = { + .pre_div_shift = 3, + .pre_div_width = 2, + }, + .s = { + .src_sel_shift = 0, + .parent_map = lcc_cxo_pll4_map, + }, + .freq_tbl = clk_tbl_aif_osr_393, + .clkr = { + .enable_reg = 0xcc, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "slimbus_src", + .parent_names = lcc_cxo_pll4, + .num_parents = 2, + .ops = &clk_rcg_ops, + .flags = CLK_SET_RATE_GATE, + }, + }, +}; + +static const char * const lcc_slimbus_parents[] = { + "slimbus_src", +}; + +static struct clk_branch audio_slimbus_clk = { + .halt_reg = 0xd4, + .halt_bit = 0, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0xcc, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "audio_slimbus_clk", + .parent_names = lcc_slimbus_parents, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch sps_slimbus_clk = { + .halt_reg = 0xd4, + .halt_bit = 1, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0xcc, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "sps_slimbus_clk", + .parent_names = lcc_slimbus_parents, + .num_parents = 1, + .ops = &clk_branch_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_regmap *lcc_mdm9615_clks[] = { + [PLL4] = &pll4.clkr, + [MI2S_OSR_SRC] = &mi2s_osr_src.clkr, + [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr, + [MI2S_DIV_CLK] = &mi2s_div_clk.clkr, + [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr, + [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr, + [PCM_SRC] = &pcm_src.clkr, + [PCM_CLK_OUT] = &pcm_clk_out.clkr, + [PCM_CLK] = &pcm_clk.clkr, + [SLIMBUS_SRC] = &slimbus_src.clkr, + [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr, + [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr, + [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr, + [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr, + [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr, + [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr, + [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr, + [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr, + [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr, + [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr, + [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr, + [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr, + [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr, + [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr, + [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr, + [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr, + [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr, + [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr, + [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr, + [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr, + [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr, + [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr, +}; + +static const struct regmap_config lcc_mdm9615_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xfc, + .fast_io = true, +}; + +static const struct qcom_cc_desc lcc_mdm9615_desc = { + .config = &lcc_mdm9615_regmap_config, + .clks = lcc_mdm9615_clks, + .num_clks = ARRAY_SIZE(lcc_mdm9615_clks), +}; + +static const struct of_device_id lcc_mdm9615_match_table[] = { + { .compatible = "qcom,lcc-mdm9615" }, + { } +}; +MODULE_DEVICE_TABLE(of, lcc_mdm9615_match_table); + +static int lcc_mdm9615_probe(struct platform_device *pdev) +{ + u32 val; + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &lcc_mdm9615_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* Use the correct frequency plan depending on speed of PLL4 */ + regmap_read(regmap, 0x4, &val); + if (val == 0x12) { + slimbus_src.freq_tbl = clk_tbl_aif_osr_492; + mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492; + codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; + spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; + codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; + spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; + pcm_src.freq_tbl = clk_tbl_pcm_492; + } + /* Enable PLL4 source on the LPASS Primary PLL Mux */ + regmap_write(regmap, 0xc4, 0x1); + + return qcom_cc_really_probe(pdev, &lcc_mdm9615_desc, regmap); +} + +static struct platform_driver lcc_mdm9615_driver = { + .probe = lcc_mdm9615_probe, + .driver = { + .name = "lcc-mdm9615", + .of_match_table = lcc_mdm9615_match_table, + }, +}; +module_platform_driver(lcc_mdm9615_driver); + +MODULE_DESCRIPTION("QCOM LCC MDM9615 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:lcc-mdm9615"); diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c index 847dd9dadeca..18220458ee6c 100644 --- a/drivers/clk/qcom/mmcc-msm8996.c +++ b/drivers/clk/qcom/mmcc-msm8996.c @@ -2888,6 +2888,14 @@ static struct clk_hw *mmcc_msm8996_hws[] = { &gpll0_div.hw, }; +static struct gdsc mmagic_bimc_gdsc = { + .gdscr = 0x529c, + .pd = { + .name = "mmagic_bimc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct gdsc mmagic_video_gdsc = { .gdscr = 0x119c, .gds_hw_ctrl = 0x120c, @@ -3201,6 +3209,7 @@ static struct clk_regmap *mmcc_msm8996_clocks[] = { }; static struct gdsc *mmcc_msm8996_gdscs[] = { + [MMAGIC_BIMC_GDSC] = &mmagic_bimc_gdsc, [MMAGIC_VIDEO_GDSC] = &mmagic_video_gdsc, [MMAGIC_MDSS_GDSC] = &mmagic_mdss_gdsc, [MMAGIC_CAMSS_GDSC] = &mmagic_camss_gdsc, diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index d359c92e13a6..e38bf60c0ff4 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -69,6 +69,7 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), /* Core Clock Outputs */ DEF_FIXED("ztr", R8A7795_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), @@ -87,10 +88,10 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), - DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074), - DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078), - DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268), - DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c), + DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x0074), + DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x0078), + DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x0268), + DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x026c), DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index c84b549c14d2..c0dee762ed23 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -45,6 +45,7 @@ enum clk_ids { CLK_S3, CLK_SDSRC, CLK_SSPSRC, + CLK_RINT, /* Module Clocks */ MOD_CLK_BASE @@ -94,10 +95,16 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), + + DEF_DIV6_RO("osc", R8A7796_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), + DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), + + DEF_BASE("r", R8A7796_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), }; static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("scif2", 310, R8A7796_CLK_S3D4), + DEF_MOD("rwdt0", 402, R8A7796_CLK_R), DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), }; diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index fc17b5295e16..51d4bac97ab3 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -31,7 +31,7 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) return; WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg, - !(reg & lock), 100, 70000)); + reg & lock, 100, 70000)); } int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index b38d71cec74c..e54266cc1c51 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -91,7 +91,8 @@ static void __init sun4i_a10_mod0_setup(struct device_node *node) sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock, reg); } -CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup); +CLK_OF_DECLARE_DRIVER(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", + sun4i_a10_mod0_setup); static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev) { diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c index a5666e1d0ce7..ea1eed24778c 100644 --- a/drivers/clk/sunxi/clk-sun8i-apb0.c +++ b/drivers/clk/sunxi/clk-sun8i-apb0.c @@ -82,8 +82,8 @@ err_unmap: of_address_to_resource(node, 0, &res); release_mem_region(res.start, resource_size(&res)); } -CLK_OF_DECLARE(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk", - sun8i_a23_apb0_setup); +CLK_OF_DECLARE_DRIVER(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk", + sun8i_a23_apb0_setup); static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev) { |