From 9a34b45397e5a389e25a0c5d39983300d040e5e2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:04:59 +0200 Subject: clk: Add support for runtime PM Registers for some clocks might be located in the SOC area, which are under the power domain. To enable access to those registers respective domain has to be turned on. Additionally, registers for such clocks will usually loose its contents when power domain is turned off, so additional saving and restoring of them might be needed in the clock controller driver. This patch adds basic infrastructure in the clocks core to allow implementing driver for such clocks under power domains. Clock provider can supply a struct device pointer, which is the used by clock core for tracking and managing clock's controller runtime pm state. Each clk_prepare() operation will first call pm_runtime_get_sync() on the supplied device, while clk_unprepare() will do pm_runtime_put_sync() at the end. Additional calls to pm_runtime_get/put functions are required to ensure that any register access (like calculating/changing clock rates and unpreparing/disabling unused clocks on boot) will be done with clock controller in runtime resumend state. When one wants to register clock controller, which make use of this feature, he has to: 1. Provide a struct device to the core when registering the provider. 2. Ensure to enable runtime PM for that device before registering clocks. 3. Make sure that the runtime PM status of the controller device reflects the HW state. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Acked-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-2-git-send-email-m.szyprowski@samsung.com --- drivers/clk/clk.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 14 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fc58c52a26b4..5bb6308fbf0d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ struct clk_core { const struct clk_ops *ops; struct clk_hw *hw; struct module *owner; + struct device *dev; struct clk_core *parent; const char **parent_names; struct clk_core **parents; @@ -87,6 +89,26 @@ struct clk { struct hlist_node clks_node; }; +/*** runtime pm ***/ +static int clk_pm_runtime_get(struct clk_core *core) +{ + int ret = 0; + + if (!core->dev) + return 0; + + ret = pm_runtime_get_sync(core->dev); + return ret < 0 ? ret : 0; +} + +static void clk_pm_runtime_put(struct clk_core *core) +{ + if (!core->dev) + return; + + pm_runtime_put_sync(core->dev); +} + /*** locking ***/ static void clk_prepare_lock(void) { @@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags) static bool clk_core_is_prepared(struct clk_core *core) { + bool ret = false; + /* * .is_prepared is optional for clocks that can prepare * fall back to software usage counter if it is missing @@ -157,11 +181,18 @@ static bool clk_core_is_prepared(struct clk_core *core) if (!core->ops->is_prepared) return core->prepare_count; - return core->ops->is_prepared(core->hw); + if (!clk_pm_runtime_get(core)) { + ret = core->ops->is_prepared(core->hw); + clk_pm_runtime_put(core); + } + + return ret; } static bool clk_core_is_enabled(struct clk_core *core) { + bool ret = false; + /* * .is_enabled is only mandatory for clocks that gate * fall back to software usage counter if .is_enabled is missing @@ -169,7 +200,29 @@ static bool clk_core_is_enabled(struct clk_core *core) if (!core->ops->is_enabled) return core->enable_count; - return core->ops->is_enabled(core->hw); + /* + * Check if clock controller's device is runtime active before + * calling .is_enabled callback. If not, assume that clock is + * disabled, because we might be called from atomic context, from + * which pm_runtime_get() is not allowed. + * This function is called mainly from clk_disable_unused_subtree, + * which ensures proper runtime pm activation of controller before + * taking enable spinlock, but the below check is needed if one tries + * to call it from other places. + */ + if (core->dev) { + pm_runtime_get_noresume(core->dev); + if (!pm_runtime_active(core->dev)) { + ret = false; + goto done; + } + } + + ret = core->ops->is_enabled(core->hw); +done: + clk_pm_runtime_put(core); + + return ret; } /*** helper functions ***/ @@ -489,6 +542,8 @@ static void clk_core_unprepare(struct clk_core *core) if (core->ops->unprepare) core->ops->unprepare(core->hw); + clk_pm_runtime_put(core); + trace_clk_unprepare_complete(core); clk_core_unprepare(core->parent); } @@ -530,10 +585,14 @@ static int clk_core_prepare(struct clk_core *core) return 0; if (core->prepare_count == 0) { - ret = clk_core_prepare(core->parent); + ret = clk_pm_runtime_get(core); if (ret) return ret; + ret = clk_core_prepare(core->parent); + if (ret) + goto runtime_put; + trace_clk_prepare(core); if (core->ops->prepare) @@ -541,15 +600,18 @@ static int clk_core_prepare(struct clk_core *core) trace_clk_prepare_complete(core); - if (ret) { - clk_core_unprepare(core->parent); - return ret; - } + if (ret) + goto unprepare; } core->prepare_count++; return 0; +unprepare: + clk_core_unprepare(core->parent); +runtime_put: + clk_pm_runtime_put(core); + return ret; } static int clk_core_prepare_lock(struct clk_core *core) @@ -745,6 +807,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core) if (core->flags & CLK_IGNORE_UNUSED) return; + if (clk_pm_runtime_get(core)) + return; + if (clk_core_is_prepared(core)) { trace_clk_unprepare(core); if (core->ops->unprepare_unused) @@ -753,6 +818,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core) core->ops->unprepare(core->hw); trace_clk_unprepare_complete(core); } + + clk_pm_runtime_put(core); } static void clk_disable_unused_subtree(struct clk_core *core) @@ -768,6 +835,9 @@ static void clk_disable_unused_subtree(struct clk_core *core) if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_prepare_enable(core->parent); + if (clk_pm_runtime_get(core)) + goto unprepare_out; + flags = clk_enable_lock(); if (core->enable_count) @@ -792,6 +862,8 @@ static void clk_disable_unused_subtree(struct clk_core *core) unlock_out: clk_enable_unlock(flags); + clk_pm_runtime_put(core); +unprepare_out: if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_disable_unprepare(core->parent); } @@ -1038,9 +1110,13 @@ EXPORT_SYMBOL_GPL(clk_get_accuracy); static unsigned long clk_recalc(struct clk_core *core, unsigned long parent_rate) { - if (core->ops->recalc_rate) - return core->ops->recalc_rate(core->hw, parent_rate); - return parent_rate; + unsigned long rate = parent_rate; + + if (core->ops->recalc_rate && !clk_pm_runtime_get(core)) { + rate = core->ops->recalc_rate(core->hw, parent_rate); + clk_pm_runtime_put(core); + } + return rate; } /** @@ -1565,6 +1641,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core, { struct clk_core *top, *fail_clk; unsigned long rate = req_rate; + int ret = 0; if (!core) return 0; @@ -1581,21 +1658,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core, if (!top) return -EINVAL; + ret = clk_pm_runtime_get(core); + if (ret) + return ret; + /* notify that we are about to change rates */ fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); if (fail_clk) { pr_debug("%s: failed to set %s rate\n", __func__, fail_clk->name); clk_propagate_rate_change(top, ABORT_RATE_CHANGE); - return -EBUSY; + ret = -EBUSY; + goto err; } /* change the rates */ clk_change_rate(top); core->req_rate = req_rate; +err: + clk_pm_runtime_put(core); - return 0; + return ret; } /** @@ -1826,12 +1910,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) p_rate = parent->rate; } + ret = clk_pm_runtime_get(core); + if (ret) + goto out; + /* propagate PRE_RATE_CHANGE notifications */ ret = __clk_speculate_rates(core, p_rate); /* abort if a driver objects */ if (ret & NOTIFY_STOP_MASK) - goto out; + goto runtime_put; /* do the re-parent */ ret = __clk_set_parent(core, parent, p_index); @@ -1844,6 +1932,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) __clk_recalc_accuracies(core); } +runtime_put: + clk_pm_runtime_put(core); out: clk_prepare_unlock(); @@ -2350,7 +2440,7 @@ static inline void clk_debug_unregister(struct clk_core *core) */ static int __clk_core_init(struct clk_core *core) { - int i, ret = 0; + int i, ret; struct clk_core *orphan; struct hlist_node *tmp2; unsigned long rate; @@ -2360,6 +2450,10 @@ static int __clk_core_init(struct clk_core *core) clk_prepare_lock(); + ret = clk_pm_runtime_get(core); + if (ret) + goto unlock; + /* check to see if a clock with this name is already registered */ if (clk_core_lookup(core->name)) { pr_debug("%s: clk %s already initialized\n", @@ -2512,6 +2606,8 @@ static int __clk_core_init(struct clk_core *core) kref_init(&core->ref); out: + clk_pm_runtime_put(core); +unlock: clk_prepare_unlock(); if (!ret) @@ -2583,6 +2679,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) goto fail_name; } core->ops = hw->init->ops; + if (dev && pm_runtime_enabled(dev)) + core->dev = dev; if (dev && dev->driver) core->owner = dev->driver->owner; core->hw = hw; -- cgit v1.2.3 From d2f18d7e200b8714beffd4eae7f27335b311b2d5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:00 +0200 Subject: clk: samsung: Add support for runtime PM This patch adds struct device pointer to samsung_clk_provider and forwarding it to clk_register_* functions, so drivers can register clocks, which use runtime pm feature. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Chanwoo Choi Tested-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-3-git-send-email-m.szyprowski@samsung.com --- drivers/clk/samsung/clk-pll.c | 2 +- drivers/clk/samsung/clk.c | 12 ++++++------ drivers/clk/samsung/clk.h | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 037c61484098..41ebb94d2855 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -1388,7 +1388,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, pll->lock_reg = base + pll_clk->lock_offset; pll->con_reg = base + pll_clk->con_offset; - ret = clk_hw_register(NULL, &pll->hw); + ret = clk_hw_register(ctx->dev, &pll->hw); if (ret) { pr_err("%s: failed to register pll clock %s : %d\n", __func__, pll_clk->name, ret); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 7ce0fa86c5ff..aef97b091b50 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -134,7 +134,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_fixed_rate(NULL, list->name, + clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, list->parent_name, list->flags, list->fixed_rate); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -163,7 +163,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_fixed_factor(NULL, list->name, + clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name, list->parent_name, list->flags, list->mult, list->div); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -184,7 +184,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_mux(NULL, list->name, + clk_hw = clk_hw_register_mux(ctx->dev, list->name, list->parent_names, list->num_parents, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->mux_flags, &ctx->lock); @@ -217,13 +217,13 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) - clk_hw = clk_hw_register_divider_table(NULL, + clk_hw = clk_hw_register_divider_table(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, list->table, &ctx->lock); else - clk_hw = clk_hw_register_divider(NULL, list->name, + clk_hw = clk_hw_register_divider(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, &ctx->lock); @@ -255,7 +255,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name, + clk_hw = clk_hw_register_gate(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->bit_idx, list->gate_flags, &ctx->lock); if (IS_ERR(clk_hw)) { diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index b8ca0dd3a38b..f0acae4f5d1b 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -24,6 +24,7 @@ */ struct samsung_clk_provider { void __iomem *reg_base; + struct device *dev; spinlock_t lock; /* clk_data must be the last entry due to variable lenght 'hws' array */ struct clk_hw_onecell_data clk_data; -- cgit v1.2.3 From 523d3de41f02141f6f6cd497d07946a2837432cf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:01 +0200 Subject: clk: samsung: exynos5433: Add support for runtime PM Add runtime pm support for all clock controller units (CMU), which belong to power domains and require special handling during on/off operations. Typically special values has to be written to MUX registers to change internal clocks parents to OSC clock before turning power off. During such operation all clocks, which enter CMU has to be enabled to let MUX to stabilize. Also for each CMU there is one special parent clock, which has to be enabled all the time when any access to CMU registers is being done. This patch solves most of the mysterious external abort and freeze issues caused by a lack of proper parent CMU clock enabled or incorrect turn off procedure. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Chanwoo Choi Tested-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-4-git-send-email-m.szyprowski@samsung.com --- .../devicetree/bindings/clock/exynos5433-clock.txt | 16 + drivers/clk/samsung/clk-exynos5433.c | 409 ++++++++++++++++----- drivers/clk/samsung/clk.h | 6 + 3 files changed, 346 insertions(+), 85 deletions(-) (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt index 1dc80f8811fe..5c7dd12e667a 100644 --- a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt @@ -168,6 +168,11 @@ Required Properties: - aclk_cam1_400 - aclk_cam1_552 +Optional properties: + - power-domains: a phandle to respective power domain node as described by + generic PM domain bindings (see power/power_domain.txt for more + information). + Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. @@ -270,6 +275,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_G2D_266>, <&cmu_top CLK_ACLK_G2D_400>; + power-domains = <&pd_g2d>; }; cmu_disp: clock-controller@13b90000 { @@ -295,6 +301,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_mif CLK_SCLK_DECON_ECLK_DISP>, <&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>, <&cmu_mif CLK_ACLK_DISP_333>; + power-domains = <&pd_disp>; }; cmu_aud: clock-controller@114c0000 { @@ -304,6 +311,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "fout_aud_pll"; clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>; + power-domains = <&pd_aud>; }; cmu_bus0: clock-controller@13600000 { @@ -340,6 +348,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_g3d_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>; + power-domains = <&pd_g3d>; }; cmu_gscl: clock-controller@13cf0000 { @@ -353,6 +362,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_GSCL_111>, <&cmu_top CLK_ACLK_GSCL_333>; + power-domains = <&pd_gscl>; }; cmu_apollo: clock-controller@11900000 { @@ -384,6 +394,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_SCLK_JPEG_MSCL>, <&cmu_top CLK_ACLK_MSCL_400>; + power-domains = <&pd_mscl>; }; cmu_mfc: clock-controller@15280000 { @@ -393,6 +404,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_mfc_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>; + power-domains = <&pd_mfc>; }; cmu_hevc: clock-controller@14f80000 { @@ -402,6 +414,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_hevc_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>; + power-domains = <&pd_hevc>; }; cmu_isp: clock-controller@146d0000 { @@ -415,6 +428,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_ISP_DIS_400>, <&cmu_top CLK_ACLK_ISP_400>; + power-domains = <&pd_isp>; }; cmu_cam0: clock-controller@120d0000 { @@ -430,6 +444,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_top CLK_ACLK_CAM0_333>, <&cmu_top CLK_ACLK_CAM0_400>, <&cmu_top CLK_ACLK_CAM0_552>; + power-domains = <&pd_cam0>; }; cmu_cam1: clock-controller@145d0000 { @@ -451,6 +466,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_top CLK_ACLK_CAM1_333>, <&cmu_top CLK_ACLK_CAM1_400>, <&cmu_top CLK_ACLK_CAM1_552>; + power-domains = <&pd_cam1>; }; Example 3: UART controller node that consumes the clock generated by the clock diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 11343a597093..cd9337613dd8 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -9,9 +9,13 @@ * Common Clock Framework support for Exynos5433 SoC. */ +#include #include #include #include +#include +#include +#include #include @@ -1991,6 +1995,14 @@ static const unsigned long fsys_clk_regs[] __initconst = { ENABLE_IP_FSYS1, }; +static const struct samsung_clk_reg_dump fsys_suspend_regs[] = { + { MUX_SEL_FSYS0, 0 }, + { MUX_SEL_FSYS1, 0 }, + { MUX_SEL_FSYS2, 0 }, + { MUX_SEL_FSYS3, 0 }, + { MUX_SEL_FSYS4, 0 }, +}; + static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = { /* PHY clocks from USBDRD30_PHY */ FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY, @@ -2296,16 +2308,11 @@ static const struct samsung_cmu_info fsys_cmu_info __initconst = { .nr_clk_ids = FSYS_NR_CLK, .clk_regs = fsys_clk_regs, .nr_clk_regs = ARRAY_SIZE(fsys_clk_regs), + .suspend_regs = fsys_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(fsys_suspend_regs), + .clk_name = "aclk_fsys_200", }; -static void __init exynos5433_cmu_fsys_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &fsys_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys", - exynos5433_cmu_fsys_init); - /* * Register offset definitions for CMU_G2D */ @@ -2335,6 +2342,10 @@ static const unsigned long g2d_clk_regs[] __initconst = { DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D, }; +static const struct samsung_clk_reg_dump g2d_suspend_regs[] = { + { MUX_SEL_G2D0, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", }; PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", }; @@ -2420,16 +2431,11 @@ static const struct samsung_cmu_info g2d_cmu_info __initconst = { .nr_clk_ids = G2D_NR_CLK, .clk_regs = g2d_clk_regs, .nr_clk_regs = ARRAY_SIZE(g2d_clk_regs), + .suspend_regs = g2d_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs), + .clk_name = "aclk_g2d_400", }; -static void __init exynos5433_cmu_g2d_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &g2d_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d", - exynos5433_cmu_g2d_init); - /* * Register offset definitions for CMU_DISP */ @@ -2494,6 +2500,18 @@ static const unsigned long disp_clk_regs[] __initconst = { CLKOUT_CMU_DISP_DIV_STAT, }; +static const struct samsung_clk_reg_dump disp_suspend_regs[] = { + /* PLL has to be enabled for suspend */ + { DISP_PLL_CON0, 0x85f40502 }, + /* ignore status of external PHY muxes during suspend to avoid hangs */ + { MUX_IGNORE_DISP2, 0x00111111 }, + { MUX_SEL_DISP0, 0 }, + { MUX_SEL_DISP1, 0 }, + { MUX_SEL_DISP2, 0 }, + { MUX_SEL_DISP3, 0 }, + { MUX_SEL_DISP4, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_disp_pll_p) = { "oscclk", "fout_disp_pll", }; PNAME(mout_sclk_dsim1_user_p) = { "oscclk", "sclk_dsim1_disp", }; @@ -2841,16 +2859,11 @@ static const struct samsung_cmu_info disp_cmu_info __initconst = { .nr_clk_ids = DISP_NR_CLK, .clk_regs = disp_clk_regs, .nr_clk_regs = ARRAY_SIZE(disp_clk_regs), + .suspend_regs = disp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs), + .clk_name = "aclk_disp_333", }; -static void __init exynos5433_cmu_disp_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &disp_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp", - exynos5433_cmu_disp_init); - /* * Register offset definitions for CMU_AUD */ @@ -2885,6 +2898,11 @@ static const unsigned long aud_clk_regs[] __initconst = { ENABLE_IP_AUD1, }; +static const struct samsung_clk_reg_dump aud_suspend_regs[] = { + { MUX_SEL_AUD0, 0 }, + { MUX_SEL_AUD1, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", }; PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",}; @@ -3011,16 +3029,11 @@ static const struct samsung_cmu_info aud_cmu_info __initconst = { .nr_clk_ids = AUD_NR_CLK, .clk_regs = aud_clk_regs, .nr_clk_regs = ARRAY_SIZE(aud_clk_regs), + .suspend_regs = aud_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs), + .clk_name = "fout_aud_pll", }; -static void __init exynos5433_cmu_aud_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &aud_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud", - exynos5433_cmu_aud_init); - - /* * Register offset definitions for CMU_BUS{0|1|2} */ @@ -3222,6 +3235,10 @@ static const unsigned long g3d_clk_regs[] __initconst = { CLK_STOPCTRL, }; +static const struct samsung_clk_reg_dump g3d_suspend_regs[] = { + { MUX_SEL_G3D, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", }; PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", }; @@ -3295,15 +3312,11 @@ static const struct samsung_cmu_info g3d_cmu_info __initconst = { .nr_clk_ids = G3D_NR_CLK, .clk_regs = g3d_clk_regs, .nr_clk_regs = ARRAY_SIZE(g3d_clk_regs), + .suspend_regs = g3d_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs), + .clk_name = "aclk_g3d_400", }; -static void __init exynos5433_cmu_g3d_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &g3d_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d", - exynos5433_cmu_g3d_init); - /* * Register offset definitions for CMU_GSCL */ @@ -3342,6 +3355,12 @@ static const unsigned long gscl_clk_regs[] __initconst = { ENABLE_IP_GSCL_SECURE_SMMU_GSCL2, }; +static const struct samsung_clk_reg_dump gscl_suspend_regs[] = { + { MUX_SEL_GSCL, 0 }, + { ENABLE_ACLK_GSCL, 0xfff }, + { ENABLE_PCLK_GSCL, 0xff }, +}; + /* list of all parent clock list */ PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", }; PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", }; @@ -3436,15 +3455,11 @@ static const struct samsung_cmu_info gscl_cmu_info __initconst = { .nr_clk_ids = GSCL_NR_CLK, .clk_regs = gscl_clk_regs, .nr_clk_regs = ARRAY_SIZE(gscl_clk_regs), + .suspend_regs = gscl_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs), + .clk_name = "aclk_gscl_111", }; -static void __init exynos5433_cmu_gscl_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &gscl_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl", - exynos5433_cmu_gscl_init); - /* * Register offset definitions for CMU_APOLLO */ @@ -3970,6 +3985,11 @@ static const unsigned long mscl_clk_regs[] __initconst = { ENABLE_IP_MSCL_SECURE_SMMU_JPEG, }; +static const struct samsung_clk_reg_dump mscl_suspend_regs[] = { + { MUX_SEL_MSCL0, 0 }, + { MUX_SEL_MSCL1, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", }; PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", }; @@ -4082,15 +4102,11 @@ static const struct samsung_cmu_info mscl_cmu_info __initconst = { .nr_clk_ids = MSCL_NR_CLK, .clk_regs = mscl_clk_regs, .nr_clk_regs = ARRAY_SIZE(mscl_clk_regs), + .suspend_regs = mscl_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs), + .clk_name = "aclk_mscl_400", }; -static void __init exynos5433_cmu_mscl_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &mscl_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl", - exynos5433_cmu_mscl_init); - /* * Register offset definitions for CMU_MFC */ @@ -4120,6 +4136,10 @@ static const unsigned long mfc_clk_regs[] __initconst = { ENABLE_IP_MFC_SECURE_SMMU_MFC, }; +static const struct samsung_clk_reg_dump mfc_suspend_regs[] = { + { MUX_SEL_MFC, 0 }, +}; + PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", }; static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { @@ -4190,15 +4210,11 @@ static const struct samsung_cmu_info mfc_cmu_info __initconst = { .nr_clk_ids = MFC_NR_CLK, .clk_regs = mfc_clk_regs, .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), + .suspend_regs = mfc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs), + .clk_name = "aclk_mfc_400", }; -static void __init exynos5433_cmu_mfc_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &mfc_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc", - exynos5433_cmu_mfc_init); - /* * Register offset definitions for CMU_HEVC */ @@ -4228,6 +4244,10 @@ static const unsigned long hevc_clk_regs[] __initconst = { ENABLE_IP_HEVC_SECURE_SMMU_HEVC, }; +static const struct samsung_clk_reg_dump hevc_suspend_regs[] = { + { MUX_SEL_HEVC, 0 }, +}; + PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", }; static const struct samsung_mux_clock hevc_mux_clks[] __initconst = { @@ -4300,15 +4320,11 @@ static const struct samsung_cmu_info hevc_cmu_info __initconst = { .nr_clk_ids = HEVC_NR_CLK, .clk_regs = hevc_clk_regs, .nr_clk_regs = ARRAY_SIZE(hevc_clk_regs), + .suspend_regs = hevc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs), + .clk_name = "aclk_hevc_400", }; -static void __init exynos5433_cmu_hevc_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &hevc_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc", - exynos5433_cmu_hevc_init); - /* * Register offset definitions for CMU_ISP */ @@ -4342,6 +4358,10 @@ static const unsigned long isp_clk_regs[] __initconst = { ENABLE_IP_ISP3, }; +static const struct samsung_clk_reg_dump isp_suspend_regs[] = { + { MUX_SEL_ISP, 0 }, +}; + PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", }; PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", }; @@ -4553,15 +4573,11 @@ static const struct samsung_cmu_info isp_cmu_info __initconst = { .nr_clk_ids = ISP_NR_CLK, .clk_regs = isp_clk_regs, .nr_clk_regs = ARRAY_SIZE(isp_clk_regs), + .suspend_regs = isp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs), + .clk_name = "aclk_isp_400", }; -static void __init exynos5433_cmu_isp_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &isp_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp", - exynos5433_cmu_isp_init); - /* * Register offset definitions for CMU_CAM0 */ @@ -4625,6 +4641,15 @@ static const unsigned long cam0_clk_regs[] __initconst = { ENABLE_IP_CAM02, ENABLE_IP_CAM03, }; + +static const struct samsung_clk_reg_dump cam0_suspend_regs[] = { + { MUX_SEL_CAM00, 0 }, + { MUX_SEL_CAM01, 0 }, + { MUX_SEL_CAM02, 0 }, + { MUX_SEL_CAM03, 0 }, + { MUX_SEL_CAM04, 0 }, +}; + PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", }; PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", }; PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", }; @@ -5030,15 +5055,11 @@ static const struct samsung_cmu_info cam0_cmu_info __initconst = { .nr_clk_ids = CAM0_NR_CLK, .clk_regs = cam0_clk_regs, .nr_clk_regs = ARRAY_SIZE(cam0_clk_regs), + .suspend_regs = cam0_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs), + .clk_name = "aclk_cam0_400", }; -static void __init exynos5433_cmu_cam0_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &cam0_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0", - exynos5433_cmu_cam0_init); - /* * Register offset definitions for CMU_CAM1 */ @@ -5085,6 +5106,12 @@ static const unsigned long cam1_clk_regs[] __initconst = { ENABLE_IP_CAM12, }; +static const struct samsung_clk_reg_dump cam1_suspend_regs[] = { + { MUX_SEL_CAM10, 0 }, + { MUX_SEL_CAM11, 0 }, + { MUX_SEL_CAM12, 0 }, +}; + PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", }; PNAME(mout_sclk_isp_spi1_user_p) = { "oscclk", "sclk_isp_spi1_cam1", }; PNAME(mout_sclk_isp_spi0_user_p) = { "oscclk", "sclk_isp_spi0_cam1", }; @@ -5403,11 +5430,223 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = { .nr_clk_ids = CAM1_NR_CLK, .clk_regs = cam1_clk_regs, .nr_clk_regs = ARRAY_SIZE(cam1_clk_regs), + .suspend_regs = cam1_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs), + .clk_name = "aclk_cam1_400", +}; + + +struct exynos5433_cmu_data { + struct samsung_clk_reg_dump *clk_save; + unsigned int nr_clk_save; + const struct samsung_clk_reg_dump *clk_suspend; + unsigned int nr_clk_suspend; + + struct clk *clk; + struct clk **pclks; + int nr_pclks; + + /* must be the last entry */ + struct samsung_clk_provider ctx; +}; + +static int exynos5433_cmu_suspend(struct device *dev) +{ + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); + int i; + + samsung_clk_save(data->ctx.reg_base, data->clk_save, + data->nr_clk_save); + + for (i = 0; i < data->nr_pclks; i++) + clk_prepare_enable(data->pclks[i]); + + /* for suspend some registers have to be set to certain values */ + samsung_clk_restore(data->ctx.reg_base, data->clk_suspend, + data->nr_clk_suspend); + + for (i = 0; i < data->nr_pclks; i++) + clk_disable_unprepare(data->pclks[i]); + + clk_disable_unprepare(data->clk); + + return 0; +} + +static int exynos5433_cmu_resume(struct device *dev) +{ + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); + int i; + + clk_prepare_enable(data->clk); + + for (i = 0; i < data->nr_pclks; i++) + clk_prepare_enable(data->pclks[i]); + + samsung_clk_restore(data->ctx.reg_base, data->clk_save, + data->nr_clk_save); + + for (i = 0; i < data->nr_pclks; i++) + clk_disable_unprepare(data->pclks[i]); + + return 0; +} + +static int __init exynos5433_cmu_probe(struct platform_device *pdev) +{ + const struct samsung_cmu_info *info; + struct exynos5433_cmu_data *data; + struct samsung_clk_provider *ctx; + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *reg_base; + int i; + + info = of_device_get_match_data(dev); + + data = devm_kzalloc(dev, sizeof(*data) + + sizeof(*data->ctx.clk_data.hws) * info->nr_clk_ids, + GFP_KERNEL); + if (!data) + return -ENOMEM; + ctx = &data->ctx; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(reg_base)) { + dev_err(dev, "failed to map registers\n"); + return PTR_ERR(reg_base); + } + + for (i = 0; i < info->nr_clk_ids; ++i) + ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); + + ctx->clk_data.num = info->nr_clk_ids; + ctx->reg_base = reg_base; + ctx->dev = dev; + spin_lock_init(&ctx->lock); + + data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs, + info->nr_clk_regs); + data->nr_clk_save = info->nr_clk_regs; + data->clk_suspend = info->suspend_regs; + data->nr_clk_suspend = info->nr_suspend_regs; + data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks", + "#clock-cells"); + if (data->nr_pclks > 0) { + data->pclks = devm_kcalloc(dev, sizeof(struct clk *), + data->nr_pclks, GFP_KERNEL); + + for (i = 0; i < data->nr_pclks; i++) { + struct clk *clk = of_clk_get(dev->of_node, i); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + data->pclks[i] = clk; + } + } + + if (info->clk_name) + data->clk = clk_get(dev, info->clk_name); + clk_prepare_enable(data->clk); + + platform_set_drvdata(pdev, data); + + /* + * Enable runtime PM here to allow the clock core using runtime PM + * for the registered clocks. Additionally, we increase the runtime + * PM usage count before registering the clocks, to prevent the + * clock core from runtime suspending the device. + */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + if (info->pll_clks) + samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks, + reg_base); + if (info->mux_clks) + samsung_clk_register_mux(ctx, info->mux_clks, + info->nr_mux_clks); + if (info->div_clks) + samsung_clk_register_div(ctx, info->div_clks, + info->nr_div_clks); + if (info->gate_clks) + samsung_clk_register_gate(ctx, info->gate_clks, + info->nr_gate_clks); + if (info->fixed_clks) + samsung_clk_register_fixed_rate(ctx, info->fixed_clks, + info->nr_fixed_clks); + if (info->fixed_factor_clks) + samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks, + info->nr_fixed_factor_clks); + + samsung_clk_of_add_provider(dev->of_node, ctx); + pm_runtime_put_sync(dev); + + return 0; +} + +static const struct of_device_id exynos5433_cmu_of_match[] = { + { + .compatible = "samsung,exynos5433-cmu-aud", + .data = &aud_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-cam0", + .data = &cam0_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-cam1", + .data = &cam1_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-disp", + .data = &disp_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-g2d", + .data = &g2d_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-g3d", + .data = &g3d_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-fsys", + .data = &fsys_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-gscl", + .data = &gscl_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-mfc", + .data = &mfc_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-hevc", + .data = &hevc_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-isp", + .data = &isp_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-mscl", + .data = &mscl_cmu_info, + }, { + }, +}; + +static const struct dev_pm_ops exynos5433_cmu_pm_ops = { + SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume, + NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos5433_cmu_driver __refdata = { + .driver = { + .name = "exynos5433-cmu", + .of_match_table = exynos5433_cmu_of_match, + .suppress_bind_attrs = true, + .pm = &exynos5433_cmu_pm_ops, + }, + .probe = exynos5433_cmu_probe, }; -static void __init exynos5433_cmu_cam1_init(struct device_node *np) +static int __init exynos5433_cmu_init(void) { - samsung_cmu_register_one(np, &cam1_cmu_info); + return platform_driver_register(&exynos5433_cmu_driver); } -CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1", - exynos5433_cmu_cam1_init); +core_initcall(exynos5433_cmu_init); diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index f0acae4f5d1b..d93031e94387 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -353,6 +353,12 @@ struct samsung_cmu_info { /* list and number of clocks registers */ const unsigned long *clk_regs; unsigned int nr_clk_regs; + + /* list and number of clocks registers to set before suspend */ + const struct samsung_clk_reg_dump *suspend_regs; + unsigned int nr_suspend_regs; + /* name of the parent clock needed for CMU register access */ + const char *clk_name; }; extern struct samsung_clk_provider *__init samsung_clk_init( -- cgit v1.2.3 From 232d7e4792f4c3f8ebb5e348a0795b6a71d0e7d8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:02 +0200 Subject: clk: samsung: exynos-audss: Use local variable for controller's device Store pointer to the controller's device in local variable to avoid extracting it from platform device in each call. This will also simplify code in the future, when runtime PM support is added. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-5-git-send-email-m.szyprowski@samsung.com --- drivers/clk/samsung/clk-exynos-audss.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 1fab56f396d4..6be52fb46ff3 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -135,6 +135,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) const struct exynos_audss_clk_drvdata *variant; struct clk_hw **clk_table; struct resource *res; + struct device *dev = &pdev->dev; int i, ret = 0; variant = of_device_get_match_data(&pdev->dev); @@ -142,15 +143,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res); + reg_base = devm_ioremap_resource(dev, res); if (IS_ERR(reg_base)) { - dev_err(&pdev->dev, "failed to map audss registers\n"); + dev_err(dev, "failed to map audss registers\n"); return PTR_ERR(reg_base); } epll = ERR_PTR(-ENODEV); - clk_data = devm_kzalloc(&pdev->dev, + clk_data = devm_kzalloc(dev, sizeof(*clk_data) + sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS, GFP_KERNEL); @@ -160,8 +161,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) clk_data->num = variant->num_clks; clk_table = clk_data->hws; - pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - pll_in = devm_clk_get(&pdev->dev, "pll_in"); + pll_ref = devm_clk_get(dev, "pll_ref"); + pll_in = devm_clk_get(dev, "pll_in"); if (!IS_ERR(pll_ref)) mout_audss_p[0] = __clk_get_name(pll_ref); if (!IS_ERR(pll_in)) { @@ -172,7 +173,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) ret = clk_prepare_enable(epll); if (ret) { - dev_err(&pdev->dev, + dev_err(dev, "failed to prepare the epll clock\n"); return ret; } @@ -183,8 +184,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - cdclk = devm_clk_get(&pdev->dev, "cdclk"); - sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); + cdclk = devm_clk_get(dev, "cdclk"); + sclk_audio = devm_clk_get(dev, "sclk_audio"); if (!IS_ERR(cdclk)) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) @@ -222,7 +223,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); - sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); + sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm", @@ -237,16 +238,16 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) for (i = 0; i < clk_data->num; i++) { if (IS_ERR(clk_table[i])) { - dev_err(&pdev->dev, "failed to register clock %d\n", i); + dev_err(dev, "failed to register clock %d\n", i); ret = PTR_ERR(clk_table[i]); goto unregister; } } - ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get, + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, clk_data); if (ret) { - dev_err(&pdev->dev, "failed to add clock provider\n"); + dev_err(dev, "failed to add clock provider\n"); goto unregister; } -- cgit v1.2.3 From ae432a9b314e07d486acfadc4df2f922721e6757 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:03 +0200 Subject: clk: samsung: exynos-audss: Add support for runtime PM This patch adds support for runtime PM to Exynos Audio SubSystem driver to enable full support for audio power domain on Exynos5 SoCs. The main change is moving register saving and restoring code from system sleep PM ops to runtime PM ops and implementing system sleep PM ops with generic pm_runtime_force_suspend/resume helpers. Runtime PM of the Exynos AudSS device is managed from clock core depending on the preparation status of the provided clocks. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-6-git-send-email-m.szyprowski@samsung.com --- .../devicetree/bindings/clock/clk-exynos-audss.txt | 6 +++ drivers/clk/samsung/clk-exynos-audss.c | 51 ++++++++++++++-------- 2 files changed, 40 insertions(+), 17 deletions(-) (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt index 0c3d6015868d..f3635d5aeba4 100644 --- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -33,6 +33,12 @@ Required Properties: - clock-names: Aliases for the above clocks. They should be "pll_ref", "pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively. +Optional Properties: + + - power-domains: a phandle to respective power domain node as described by + generic PM domain bindings (see power/power_domain.txt for more + information). + The following is the list of clocks generated by the controller. Each clock is assigned an identifier and client nodes use this identifier to specify the clock which they consume. Some of the clocks are available only on a particular diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 6be52fb46ff3..ab494c104ce6 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -36,14 +37,13 @@ static struct clk *epll; #define ASS_CLK_DIV 0x4 #define ASS_CLK_GATE 0x8 -#ifdef CONFIG_PM_SLEEP static unsigned long reg_save[][2] = { { ASS_CLK_SRC, 0 }, { ASS_CLK_DIV, 0 }, { ASS_CLK_GATE, 0 }, }; -static int exynos_audss_clk_suspend(struct device *dev) +static int __maybe_unused exynos_audss_clk_suspend(struct device *dev) { int i; @@ -53,7 +53,7 @@ static int exynos_audss_clk_suspend(struct device *dev) return 0; } -static int exynos_audss_clk_resume(struct device *dev) +static int __maybe_unused exynos_audss_clk_resume(struct device *dev) { int i; @@ -62,7 +62,6 @@ static int exynos_audss_clk_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ struct exynos_audss_clk_drvdata { unsigned int has_adma_clk:1; @@ -179,7 +178,18 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) } } } - clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", + + /* + * Enable runtime PM here to allow the clock core using runtime PM + * for the registered clocks. Additionally, we increase the runtime + * PM usage count before registering the clocks, to prevent the + * clock core from runtime suspending the device. + */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(dev, "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); @@ -190,48 +200,48 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) mout_i2s_p[2] = __clk_get_name(sclk_audio); - clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s", + clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(dev, "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); - clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", + clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(dev, "dout_srp", "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); - clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, + clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(dev, "dout_aud_bus", "dout_srp", 0, reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); - clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", + clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(dev, "dout_i2s", "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, &lock); - clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk", + clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(dev, "srp_clk", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 0, 0, &lock); - clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus", + clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(dev, "i2s_bus", "dout_aud_bus", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 2, 0, &lock); - clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s", + clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(dev, "sclk_i2s", "dout_i2s", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 3, 0, &lock); - clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus", + clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(dev, "pcm_bus", "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); - clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm", + clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(dev, "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); if (variant->has_adma_clk) { - clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma", + clk_table[EXYNOS_ADMA] = clk_hw_register_gate(dev, "adma", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 9, 0, &lock); } @@ -251,10 +261,14 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) goto unregister; } + pm_runtime_put_sync(dev); + return 0; unregister: exynos_audss_clk_teardown(); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); if (!IS_ERR(epll)) clk_disable_unprepare(epll); @@ -267,6 +281,7 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) of_clk_del_provider(pdev->dev.of_node); exynos_audss_clk_teardown(); + pm_runtime_disable(&pdev->dev); if (!IS_ERR(epll)) clk_disable_unprepare(epll); @@ -275,8 +290,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) } static const struct dev_pm_ops exynos_audss_clk_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_audss_clk_suspend, - exynos_audss_clk_resume) + SET_RUNTIME_PM_OPS(exynos_audss_clk_suspend, exynos_audss_clk_resume, + NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver exynos_audss_clk_driver = { -- cgit v1.2.3 From 62d212bdb022deeb875f92f6e376c799e3f35eca Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 10 Sep 2017 20:40:05 +0800 Subject: clk: sunxi-ng: add CLK_SET_RATE_UNGATE to all H3 PLLs The PLLs on H3 have a lock bit, which will only be set to 1 when the PLL is really working. Add CLK_SET_RATE_UNGATE to the PLLs, otherwise it will timeout when trying to set PLL clock frequency without enabling it. Fixes: 0577e4853bfb ("clk: sunxi-ng: Add H3 clocks") Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 1729ff6a5aae..7a81c4885836 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -37,7 +37,7 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", 16, 2, /* P */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); /* * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from @@ -55,7 +55,7 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", 0, 5, /* M */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x0010, @@ -67,7 +67,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", "osc24M", 0x0018, @@ -79,7 +79,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", "osc24M", 0x020, @@ -88,7 +88,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", 0, 2, /* M */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", "osc24M", 0x028, @@ -97,7 +97,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", "osc24M", 0x0038, @@ -109,7 +109,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", "osc24M", 0x044, @@ -118,7 +118,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", "osc24M", 0x0048, @@ -130,7 +130,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static const char * const cpux_parents[] = { "osc32k", "osc24M", "pll-cpux" , "pll-cpux" }; -- cgit v1.2.3 From 70641ccad7d19b8229bf1cac33f5b8e03fdc7c5a Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 10 Sep 2017 20:40:06 +0800 Subject: clk: sunxi-ng: add CLK_SET_RATE_PARENT flag to H3 GPU clock The GPU clock on H3 has only one parent, PLL-GPU, and the PLL is only the parent of the GPU clock. The GPU clock can be tweaked by tweaking the PLL-GPU clock. Add CLK_SET_RATE_PARENT flag to allow tweaking the GPU clock via tweaking PLL-CPU. Fixes: 0577e4853bfb ("clk: sunxi-ng: Add H3 clocks") Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 7a81c4885836..543c46d0e045 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -484,7 +484,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", - 0x1a0, 0, 3, BIT(31), 0); + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); static struct ccu_common *sun8i_h3_ccu_clks[] = { &pll_cpux_clk.common, -- cgit v1.2.3 From a894990ac994a53bc5a0cc694eb12f3c064c18c5 Mon Sep 17 00:00:00 2001 From: Alexander Syring Date: Thu, 14 Sep 2017 14:05:19 +0200 Subject: clk: sunxi-ng: Fix missing CLK_SET_RATE_PARENT in ccu-sun4i-a10.c When using cpufreq-dt with default govenor other than "performance" system freezes while booting. Adding CLK_SET_RATE_PARENT | CLK_IS_CRITICAL to clk_cpu fixes the problem. Tested on Cubietruck (A20). Fixes: c84f5683f6E ("clk: sunxi-ng: Add sun4i/sun7i CCU driver") Acked-by: Chen-Yu Tsai Signed-off-by: Alexander Syring Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index 286b0049b7b6..a48fde191c0a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -223,7 +223,7 @@ static struct ccu_mux cpu_clk = { .hw.init = CLK_HW_INIT_PARENTS("cpu", cpu_parents, &ccu_mux_ops, - CLK_IS_CRITICAL), + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), } }; -- cgit v1.2.3 From 8d46e28fb5081b49c5b24c814ad464fb99359d58 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 9 Sep 2017 00:34:20 +0300 Subject: clk: renesas: cpg-mssr: Add R8A77970 support Add R-Car V3M (R8A77970) Clock Pulse Generator / Module Standby and Software Reset support, using the CPG/MSSR driver core and the common R-Car Gen3 code. Based on the original (and large) patch by Daisuke Matsushita . Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/clock/renesas,cpg-mssr.txt | 5 +- drivers/clk/renesas/Kconfig | 5 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a77970-cpg-mssr.c | 199 +++++++++++++++++++++ drivers/clk/renesas/renesas-cpg-mssr.c | 6 + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + 6 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/renesas/r8a77970-cpg-mssr.c (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index 316e13686568..f1890d0777a6 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt @@ -22,6 +22,7 @@ Required Properties: - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) + - "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M) - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) - reg: Base address and length of the memory resource used by the CPG/MSSR @@ -31,8 +32,8 @@ Required Properties: clock-names - clock-names: List of external parent clock names. Valid names are: - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, - r8a7795, r8a7796, r8a77995) - - "extalr" (r8a7795, r8a7796) + r8a7795, r8a7796, r8a77970, r8a77995) + - "extalr" (r8a7795, r8a7796, r8a77970) - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) - #clock-cells: Must be 2 diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index acbb38151ba1..43b5a89c4b28 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -15,6 +15,7 @@ config CLK_RENESAS select CLK_R8A7794 if ARCH_R8A7794 select CLK_R8A7795 if ARCH_R8A7795 select CLK_R8A7796 if ARCH_R8A7796 + select CLK_R8A77970 if ARCH_R8A77970 select CLK_R8A77995 if ARCH_R8A77995 select CLK_SH73A0 if ARCH_SH73A0 @@ -95,6 +96,10 @@ config CLK_R8A7796 bool "R-Car M3-W clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG +config CLK_R8A77970 + bool "R-Car V3M clock support" if COMPILE_TEST + select CLK_RCAR_GEN3_CPG + config CLK_R8A77995 bool "R-Car D3 clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 9bda3ec5b199..306861c74a87 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o +obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c new file mode 100644 index 000000000000..72f98527473a --- /dev/null +++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c @@ -0,0 +1,199 @@ +/* + * r8a77970 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2017 Cogent Embedded Inc. + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include + +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A77970_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL3, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1), + DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1), + DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1), + + DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), + + DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014), + DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), + + DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1), + DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1), +}; + +static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1), + DEF_MOD("scif4", 203, R8A77970_CLK_S2D4), + DEF_MOD("scif3", 204, R8A77970_CLK_S2D4), + DEF_MOD("scif1", 206, R8A77970_CLK_S2D4), + DEF_MOD("scif0", 207, R8A77970_CLK_S2D4), + DEF_MOD("msiof3", 208, R8A77970_CLK_MSO), + DEF_MOD("msiof2", 209, R8A77970_CLK_MSO), + DEF_MOD("msiof1", 210, R8A77970_CLK_MSO), + DEF_MOD("msiof0", 211, R8A77970_CLK_MSO), + DEF_MOD("mfis", 213, R8A77970_CLK_S2D2), + DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1), + DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1), + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1), + DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1), + DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1), + DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1), + DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1), + DEF_MOD("thermal", 522, R8A77970_CLK_CP), + DEF_MOD("pwm", 523, R8A77970_CLK_S2D4), + DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1), + DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1), + DEF_MOD("csi40", 716, R8A77970_CLK_CSI0), + DEF_MOD("du0", 724, R8A77970_CLK_S2D1), + DEF_MOD("vin3", 808, R8A77970_CLK_S2D1), + DEF_MOD("vin2", 809, R8A77970_CLK_S2D1), + DEF_MOD("vin1", 810, R8A77970_CLK_S2D1), + DEF_MOD("vin0", 811, R8A77970_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2), + DEF_MOD("gpio5", 907, R8A77970_CLK_CP), + DEF_MOD("gpio4", 908, R8A77970_CLK_CP), + DEF_MOD("gpio3", 909, R8A77970_CLK_CP), + DEF_MOD("gpio2", 910, R8A77970_CLK_CP), + DEF_MOD("gpio1", 911, R8A77970_CLK_CP), + DEF_MOD("gpio0", 912, R8A77970_CLK_CP), + DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2), + DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2), + DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2), + DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2), + DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2), + DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2), +}; + +static const unsigned int r8a77970_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL3 + * 14 13 19 (MHz) + *------------------------------------------------- + * 0 0 0 16.66 x 1 x192 x192 x96 + * 0 0 1 16.66 x 1 x192 x192 x80 + * 0 1 0 20 x 1 x160 x160 x80 + * 0 1 1 20 x 1 x160 x160 x66 + * 1 0 0 27 / 2 x236 x236 x118 + * 1 0 1 27 / 2 x236 x236 x98 + * 1 1 0 33.33 / 2 x192 x192 x96 + * 1 1 1 33.33 / 2 x192 x192 x80 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ + (((md) & BIT(13)) >> 12) | \ + (((md) & BIT(19)) >> 19)) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = { + /* EXTAL div PLL1 mult/div PLL3 mult/div */ + { 1, 192, 1, 96, 1, }, + { 1, 192, 1, 80, 1, }, + { 1, 160, 1, 80, 1, }, + { 1, 160, 1, 66, 1, }, + { 2, 236, 1, 118, 1, }, + { 2, 236, 1, 98, 1, }, + { 2, 192, 1, 96, 1, }, + { 2, 192, 1, 80, 1, }, +}; + +static int __init r8a77970_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); +} + +const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a77970_core_clks, + .num_core_clks = ARRAY_SIZE(r8a77970_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a77970_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a77970_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks), + + /* Callbacks */ + .init = r8a77970_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e580a5e6346c..1779b0cc7a2a 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -680,6 +680,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a7796_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A77970 + { + .compatible = "renesas,r8a77970-cpg-mssr", + .data = &r8a77970_cpg_mssr_info, + }, +#endif #ifdef CONFIG_CLK_R8A77995 { .compatible = "renesas,r8a77995-cpg-mssr", diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 94b9071d1061..66528ce3eb37 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -138,6 +138,7 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; extern const struct cpg_mssr_info r8a7794_cpg_mssr_info; extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; +extern const struct cpg_mssr_info r8a77970_cpg_mssr_info; extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; -- cgit v1.2.3 From 5da672cff03d3ffa36476e91943af50e3151db2a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 26 Sep 2017 10:36:20 +0800 Subject: clk: sunxi-ng: Implement reset control status readback Until now we were not providing a way to read back the status of our reset controls. Consumers had no real way to be certain whether a peripheral was held in reset or not. Implement the status callback to complete the API support. Fixes: 1d80c14248d6 ("clk: sunxi-ng: Add common infrastructure") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_reset.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c index 1dc4e98ea802..b67149143554 100644 --- a/drivers/clk/sunxi-ng/ccu_reset.c +++ b/drivers/clk/sunxi-ng/ccu_reset.c @@ -60,8 +60,22 @@ static int ccu_reset_reset(struct reset_controller_dev *rcdev, return 0; } +static int ccu_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); + const struct ccu_reset_map *map = &ccu->reset_map[id]; + + /* + * The reset control API expects 0 if reset is not asserted, + * which is the opposite of what our hardware uses. + */ + return !(map->bit & readl(ccu->base + map->reg)); +} + const struct reset_control_ops ccu_reset_ops = { .assert = ccu_reset_assert, .deassert = ccu_reset_deassert, .reset = ccu_reset_reset, + .status = ccu_reset_status, }; -- cgit v1.2.3 From 8834b0950156de37acccd422263d4da3c94495e6 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 15:46:53 +0200 Subject: clk: samsung: Delete a memory allocation error message in clk-cpu.c Omit an extra message for a memory allocation failure in exynos_register_cpu_clock() function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-cpu.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 6686e8ba61f9..d2c99d8916b8 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -457,8 +457,6 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, cpuclk->cfg = kmemdup(cfg, sizeof(*cfg) * num_cfgs, GFP_KERNEL); if (!cpuclk->cfg) { - pr_err("%s: could not allocate memory for cpuclk data\n", - __func__); ret = -ENOMEM; goto unregister_clk_nb; } -- cgit v1.2.3 From 9edb39d750c0a9a6f7dafb8d9d15e63f6d44b68c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 11:38:17 +0200 Subject: clk: rockchip: Remove superfluous error message in rockchip_clk_register_cpuclk() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 0e09684d43a5..32c19c0f1e14 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -322,8 +322,6 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, sizeof(*rates) * nrates, GFP_KERNEL); if (!cpuclk->rate_table) { - pr_err("%s: could not allocate memory for cpuclk rates\n", - __func__); ret = -ENOMEM; goto unregister_notifier; } -- cgit v1.2.3 From 168bcbcb1c72a4753fc64ef384b46e330bfccd08 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 25 Sep 2017 10:10:51 +0200 Subject: clk: renesas: mstp: Delete error messages for failed memory allocations The script "checkpatch.pl" pointed information out like the following. WARNING: Possible unnecessary 'out of memory' message Thus fix affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-mstp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 500a9e4e03c4..c944cc421e30 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -156,10 +156,8 @@ static struct clk * __init cpg_mstp_clock_register(const char *name, struct clk *clk; clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) { - pr_err("%s: failed to allocate MSTP clock.\n", __func__); + if (!clock) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &cpg_mstp_clock_ops; @@ -196,7 +194,6 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) if (group == NULL || clks == NULL) { kfree(group); kfree(clks); - pr_err("%s: failed to allocate group\n", __func__); return; } -- cgit v1.2.3 From b4021bbe10017d994e5a96ebfd2677bbaf2b37e0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 25 Sep 2017 10:10:51 +0200 Subject: clk: renesas: rcar-gen2: Delete error message for failed memory allocation The script "checkpatch.pl" pointed information out like the following. WARNING: Possible unnecessary 'out of memory' message Thus fix affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-rcar-gen2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 0b2e56d0d94b..d14cbe1ca29a 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -423,7 +423,6 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) /* We're leaking memory on purpose, there's no point in cleaning * up as the system won't boot anyway. */ - pr_err("%s: failed to allocate cpg\n", __func__); return; } -- cgit v1.2.3 From c07c1a0f68d0f2f7ca9aff924e2772526027b019 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Fri, 29 Sep 2017 09:32:53 +0200 Subject: clk: samsung: Fix m2m scaler clock on Exynos542x The TOP "aclk400_mscl" clock should be kept enabled all the time to allow proper access to power management control for MSC power domain and devices that are a part of it. This change is required for the scaler to work properly after domain power on/off sequence. Fixes: 318fa46cc60d ("clk/samsung: exynos542x: mark some clocks as critical") Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 25601967d1cd..038701a2af4c 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -998,7 +998,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(0, "aclk400_isp", "mout_user_aclk400_isp", GATE_BUS_TOP, 16, 0, 0), GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl", - GATE_BUS_TOP, 17, 0, 0), + GATE_BUS_TOP, 17, CLK_IS_CRITICAL, 0), GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1", GATE_BUS_TOP, 18, CLK_IS_CRITICAL, 0), GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24", -- cgit v1.2.3 From 80815004a45fc68b6e34653af4fca47be7fb96ed Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 29 Sep 2017 16:22:53 +0800 Subject: clk: sunxi-ng: sun6i: Export video PLLs The 2x outputs of the 2 video PLL clocks are directly used by the HDMI controller block. Export them so they can be referenced in the device tree. Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.h | 8 ++++++-- include/dt-bindings/clock/sun6i-a31-ccu.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.h b/drivers/clk/sunxi-ng/ccu-sun6i-a31.h index 4e434011e9e7..27e6ad4133ab 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.h +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.h @@ -27,7 +27,9 @@ #define CLK_PLL_AUDIO_4X 4 #define CLK_PLL_AUDIO_8X 5 #define CLK_PLL_VIDEO0 6 -#define CLK_PLL_VIDEO0_2X 7 + +/* The PLL_VIDEO0_2X clock is exported */ + #define CLK_PLL_VE 8 #define CLK_PLL_DDR 9 @@ -35,7 +37,9 @@ #define CLK_PLL_PERIPH_2X 11 #define CLK_PLL_VIDEO1 12 -#define CLK_PLL_VIDEO1_2X 13 + +/* The PLL_VIDEO1_2X clock is exported */ + #define CLK_PLL_GPU 14 #define CLK_PLL_MIPI 15 #define CLK_PLL9 16 diff --git a/include/dt-bindings/clock/sun6i-a31-ccu.h b/include/dt-bindings/clock/sun6i-a31-ccu.h index 4482530fb6f5..c5d13340184a 100644 --- a/include/dt-bindings/clock/sun6i-a31-ccu.h +++ b/include/dt-bindings/clock/sun6i-a31-ccu.h @@ -43,8 +43,12 @@ #ifndef _DT_BINDINGS_CLK_SUN6I_A31_H_ #define _DT_BINDINGS_CLK_SUN6I_A31_H_ +#define CLK_PLL_VIDEO0_2X 7 + #define CLK_PLL_PERIPH 10 +#define CLK_PLL_VIDEO1_2X 13 + #define CLK_CPU 18 #define CLK_AHB1_MIPIDSI 23 -- cgit v1.2.3 From 7f3ed79188f2f094d0ee366fa858857fb7f511ba Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 29 Sep 2017 16:22:54 +0800 Subject: clk: sunxi-ng: sun6i: Rename HDMI DDC clock to avoid name collision The HDMI DDC clock found in the CCU is the parent of the actual DDC clock within the HDMI controller. That clock is also named "hdmi-ddc". Rename the one in the CCU to "ddc". This makes more sense than renaming the one in the HDMI controller to something else. Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 8af434815fba..241fb13f1c06 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -608,7 +608,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", lcd_ch1_parents, 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); -static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", 0x150, BIT(30), 0); +static SUNXI_CCU_GATE(hdmi_ddc_clk, "ddc", "osc24M", 0x150, BIT(30), 0); static SUNXI_CCU_GATE(ps_clk, "ps", "lcd1-ch1", 0x140, BIT(31), 0); -- cgit v1.2.3 From 61a646e1355cf7215ed9a3fef4ba4c2b42bd495f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 14 Sep 2017 16:38:17 +0200 Subject: clk: samsung: Properly propagate flags in __PLL macro All users of __PLL macro already provide flags parameter, so don't overwrite it unconditionally with CLK_GET_RATE_NOCACHE. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index b8ca0dd3a38b..d5f0d3f818b6 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -305,7 +305,7 @@ struct samsung_pll_clock { .dev_name = _dname, \ .name = _name, \ .parent_name = _pname, \ - .flags = CLK_GET_RATE_NOCACHE, \ + .flags = _flags, \ .con_offset = _con, \ .lock_offset = _lock, \ .rate_table = _rtable, \ -- cgit v1.2.3 From 7c4f63ec94a1a45dd90dd3bf4da8de24a0a5a9c0 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 5 Oct 2017 04:33:14 +0200 Subject: clk: sunxi-ng: a83t: Fix invalid csi-mclk mux offset Datasheet specified that parent MUX settings are at bits [10:8], but current implementation specifies incorrect offset at [10:12]. Fix this. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index e43acebdfbcd..c7b51f030eb2 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -506,7 +506,7 @@ static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, csi_mclk_table, 0x134, 0, 5, /* M */ - 10, 3, /* mux */ + 8, 3, /* mux */ BIT(15), /* gate */ 0); -- cgit v1.2.3 From d5cd103b06f9d766295d18798de484528eb120ea Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 4 Oct 2017 08:38:26 +0200 Subject: clk: samsung: Remove support for Exynos4212 SoCs in Exynos CLKOUT driver Support for Exynos4212 SoCs has been removed by commit bca9085e0ae9 ("ARM: dts: exynos: remove Exynos4212 support (dead code)"), so there is no need to keep remaining dead code related to this SoC version. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-clkout.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index a21aea062bae..f29fb5824005 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -144,8 +144,6 @@ static void __init exynos4_clkout_init(struct device_node *node) } CLK_OF_DECLARE_DRIVER(exynos4210_clkout, "samsung,exynos4210-pmu", exynos4_clkout_init); -CLK_OF_DECLARE_DRIVER(exynos4212_clkout, "samsung,exynos4212-pmu", - exynos4_clkout_init); CLK_OF_DECLARE_DRIVER(exynos4412_clkout, "samsung,exynos4412-pmu", exynos4_clkout_init); CLK_OF_DECLARE_DRIVER(exynos3250_clkout, "samsung,exynos3250-pmu", -- cgit v1.2.3 From c9194fb623b0158029a268376df09fe28a2a2b05 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:08 +0200 Subject: clk: samsung: Remove support for obsolete Exynos4212 CPU clock Support for Exynos 4212 SoC has been removed by commit bca9085e0ae9 ("ARM: dts: exynos: remove Exynos4212 support (dead code)"), so there is no need to keep dead code. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index e40b77583c47..9a51ce9a658f 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1401,24 +1401,6 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = { { 0 }, }; -static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = { - { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, - { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, - { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, - { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, - { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), }, - { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), }, - { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, - { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, - { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), }, - { 0 }, -}; - #define E4412_CPU_DIV1(cores, hpm, copy) \ (((cores) << 8) | ((hpm) << 4) | ((copy) << 0)) @@ -1533,17 +1515,10 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); - if (of_machine_is_compatible("samsung,exynos4412")) { - exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, - e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), - CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); - } else { - exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, - e4212_armclk_d, ARRAY_SIZE(e4212_armclk_d), - CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); - } + exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", + mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, + e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), + CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } samsung_clk_register_alias(ctx, exynos4_aliases, -- cgit v1.2.3 From 58f4a5ff3a6248a89c849415cab8089e41425f5e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:09 +0200 Subject: clk: samsung: Remove clkdev alias support in Exynos4 clk driver All Exynos4 boards have been fully converted to device-tree and use generic dt-based CPUfreq driver, so there is no need to create any clkdev aliases for the clocks. Drop all the code related to aliases handling. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 47 +++++++++------------------------------ 1 file changed, 10 insertions(+), 37 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 9a51ce9a658f..3fbfd9ed82b7 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -535,9 +535,8 @@ static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __ /* list of mux clocks supported in all exynos4 soc's */ static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = { - MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, - CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0, - "mout_apll"), + MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), @@ -838,11 +837,6 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { /* list of gate clocks supported in all exynos4 soc's */ static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = { - /* - * After all Exynos4 based platforms are migrated to use device tree, - * the device name and clock alias names specified below for some - * of the clocks can be removed. - */ GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0), GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0), @@ -1190,20 +1184,6 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { 0), }; -static const struct samsung_clock_alias exynos4_aliases[] __initconst = { - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"), - ALIAS(CLK_ARM_CLK, NULL, "armclk"), - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"), -}; - -static const struct samsung_clock_alias exynos4210_aliases[] __initconst = { - ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"), -}; - -static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = { - ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"), -}; - /* * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit * resides in chipid register space, outside of the clock controller memory @@ -1340,14 +1320,14 @@ static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = }; static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = { - [apll] = PLL_A(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll", - APLL_LOCK, APLL_CON0, "fout_apll", NULL), - [mpll] = PLL_A(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", - E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL), - [epll] = PLL_A(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll", - EPLL_LOCK, EPLL_CON0, "fout_epll", NULL), - [vpll] = PLL_A(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", - VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL), + [apll] = PLL(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", + E4210_MPLL_LOCK, E4210_MPLL_CON0, NULL), + [epll] = PLL(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), + [vpll] = PLL(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON0, NULL), }; static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { @@ -1494,8 +1474,6 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4210_div_clks)); samsung_clk_register_gate(ctx, exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); - samsung_clk_register_alias(ctx, exynos4210_aliases, - ARRAY_SIZE(exynos4210_aliases)); samsung_clk_register_fixed_factor(ctx, exynos4210_fixed_factor_clks, ARRAY_SIZE(exynos4210_fixed_factor_clks)); @@ -1510,8 +1488,6 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4x12_div_clks)); samsung_clk_register_gate(ctx, exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); - samsung_clk_register_alias(ctx, exynos4x12_aliases, - ARRAY_SIZE(exynos4x12_aliases)); samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); @@ -1521,9 +1497,6 @@ static void __init exynos4_clk_init(struct device_node *np, CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } - samsung_clk_register_alias(ctx, exynos4_aliases, - ARRAY_SIZE(exynos4_aliases)); - if (soc == EXYNOS4X12) exynos4x12_core_down_clock(); exynos4_clk_sleep_init(); -- cgit v1.2.3 From 6de08891c896d313e6541e5a56e373adcf0bbebc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:10 +0200 Subject: clk: samsung: Remove double assignment of CLK_ARM_CLK in Exynos4 driver CLK_ARM_CLK ("armclk") clock is provided by cpu-clk subdriver, which is instantiated after creating all divider clocks from exynos4_div_clks array. There is no point assigning this id to "div_core2" clock and later overwrite with proper "armcpu" clock by cpu-clk subdriver. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 3fbfd9ed82b7..3bd2d84b2a17 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -721,7 +721,7 @@ static const struct samsung_div_clock exynos4_div_clks[] __initconst = { DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3), DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3), DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3), - DIV(CLK_ARM_CLK, "div_core2", "div_core", DIV_CPU0, 28, 3), + DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3), DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3), DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6), -- cgit v1.2.3 From 29964890f31c2cb98b0aa277d81652e6aecd8bbc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:11 +0200 Subject: clk: samsung: Remove clkdev alias support in Exynos5250 clk driver All Exynos5250 boards have been fully converted to device-tree and use generic dt-based CPUfreq driver, so there is no need to create any clkdev aliases for the clocks. Drop all the code related to aliases handling. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 27a227d6620c..9b073c98a891 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -293,14 +293,14 @@ static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = { /* * CMU_CPU */ - MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, - CLK_SET_RATE_PARENT, 0, "mout_apll"), - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"), + MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + CLK_SET_RATE_PARENT, 0), + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), /* * CMU_CORE */ - MUX_A(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"), + MUX(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1), /* * CMU_TOP @@ -391,7 +391,7 @@ static const struct samsung_div_clock exynos5250_div_clks[] __initconst = { */ DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3), - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"), + DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3), /* * CMU_TOP @@ -743,10 +743,10 @@ static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = { }; static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = { - [apll] = PLL_A(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", - APLL_LOCK, APLL_CON0, "fout_apll", NULL), - [mpll] = PLL_A(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", - MPLL_LOCK, MPLL_CON0, "fout_mpll", NULL), + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, NULL), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0, NULL), [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, BPLL_CON0, NULL), [gpll] = PLL(pll_35xx, CLK_FOUT_GPLL, "fout_gpll", "fin_pll", GPLL_LOCK, -- cgit v1.2.3 From 36ba48240b19395ececd7303bde56f9af4177062 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:12 +0200 Subject: clk: samsung: Drop useless alias in Exynos5420 clk driver Drop clkdev alias for "mout_aclk400_mscl" clock. It was not used at all and it was probably committed by accident. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 038701a2af4c..45d34f601e9e 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -600,8 +600,7 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { TOP_SPARE2, 4, 1), MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2), - MUX_A(0, "mout_aclk400_mscl", mout_group1_p, - SRC_TOP0, 4, 2, "aclk400_mscl"), + MUX(0, "mout_aclk400_mscl", mout_group1_p, SRC_TOP0, 4, 2), MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2), MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2), -- cgit v1.2.3 From efea8d3771843bca26862fabebfa83aa9b497bd2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:13 +0200 Subject: clk: samsung: Rework clkdev alias handling in Exynos5440 driver Exynos5440 still uses old, non-dt CPUfreq driver, which requires clkdev aliases to get access to proper clocks. Create those aliases using samsung_clk_register_alias() function instead of using *_A clock macros, which will be removed soon. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5440.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index a80f3ef20801..b08bd54c5e76 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -53,8 +53,7 @@ static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __ /* mux clocks */ static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = { MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), - MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p, - CPU_CLK_STATUS, 0, 1, "armclk"), + MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1), }; /* divider clocks */ @@ -117,6 +116,13 @@ static const struct samsung_pll_clock exynos5440_plls[] __initconst = { PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL), }; +/* + * Clock aliases for legacy clkdev look-up. + */ +static const struct samsung_clock_alias exynos5440_aliases[] __initconst = { + ALIAS(CLK_ARM_CLK, NULL, "armclk"), +}; + /* register exynos5440 clocks */ static void __init exynos5440_clk_init(struct device_node *np) { @@ -147,6 +153,8 @@ static void __init exynos5440_clk_init(struct device_node *np) ARRAY_SIZE(exynos5440_div_clks)); samsung_clk_register_gate(ctx, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); + samsung_clk_register_alias(ctx, exynos5440_aliases, + ARRAY_SIZE(exynos5440_aliases)); samsung_clk_of_add_provider(np, ctx); -- cgit v1.2.3 From cd05417f728ba914caf5d94fa4a15b2300a268b5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:14 +0200 Subject: clk: samsung: Rework clkdev alias handling in S3C2443 driver S3C2443 SoC still uses old, non-dt CPUfreq driver, which requires clkdev aliases to get access to proper clocks. Create those aliases using samsung_clk_register_alias() function instead of using *_A clock macros, which will be removed soon. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2443.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index abb935c42916..45166033f638 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -117,8 +117,8 @@ struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), - MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"), - MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"), + MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1), + MUX(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1), MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2), }; @@ -189,6 +189,8 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = { }; struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { + ALIAS(MSYSCLK, NULL, "msysclk"), + ALIAS(ARMCLK, NULL, "armclk"), ALIAS(HCLK, NULL, "hclk"), ALIAS(HCLK_SSMC, NULL, "nand"), ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), -- cgit v1.2.3 From 45d882daf88a57ec681254e8a41dd5ba268a097d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:15 +0200 Subject: clk: samsung: Add explicit MPLL, EPLL clkdev aliases in S3C2443 driver S3C2443 platform still use non-dt based lookup in some of its drivers to get MPLL and EPLL clocks. Till now it worked only because PLL() macro implicitly created aliases for all instantiated clocks. This feature will be removed, so explicitly create aliases for MPLL and EPLL clocks. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2443.c | 10 ++++++---- include/dt-bindings/clock/s3c2443.h | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index 45166033f638..d94b85a42356 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -191,6 +191,8 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = { struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { ALIAS(MSYSCLK, NULL, "msysclk"), ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(EPLL, NULL, "epll"), ALIAS(HCLK, NULL, "hclk"), ALIAS(HCLK_SSMC, NULL, "nand"), ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), @@ -223,9 +225,9 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { /* S3C2416 specific clocks */ static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { - [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref", + [mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_6553, 0, "epll", "epllref", + [epll] = PLL(pll_6553, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; @@ -277,9 +279,9 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = { /* S3C2443 specific clocks */ static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { - [mpll] = PLL(pll_3000, 0, "mpll", "mpllref", + [mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_2126, 0, "epll", "epllref", + [epll] = PLL(pll_2126, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; diff --git a/include/dt-bindings/clock/s3c2443.h b/include/dt-bindings/clock/s3c2443.h index 37e66b054d64..f3ba68a25ecb 100644 --- a/include/dt-bindings/clock/s3c2443.h +++ b/include/dt-bindings/clock/s3c2443.h @@ -26,6 +26,8 @@ #define ARMCLK 4 #define HCLK 5 #define PCLK 6 +#define MPLL 7 +#define EPLL 8 /* Special clocks */ #define SCLK_HSSPI0 16 -- cgit v1.2.3 From a4f21e9ceb5c81f5b297cabb98dac0b5c03bd4dc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:16 +0200 Subject: clk: samsung: Remove obsolete clkdev alias support Remove support for obsolete clkdev alias definition in generic helper macros for MUX, DIV, GATE and PLL clocks. clkdev aliases can be still created using samsung_clk_register_alias() function if given platform still needs them. All current drivers have been converted not to use *_A-style macros and checked if there are any clients for the PLL clocks, which had aliases created unconditionally. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-pll.c | 9 ------ drivers/clk/samsung/clk.c | 33 ++------------------ drivers/clk/samsung/clk.h | 71 ++++++++----------------------------------- 3 files changed, 15 insertions(+), 98 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 037c61484098..137882657370 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -1397,15 +1397,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id); - - if (!pll_clk->alias) - return; - - ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias, - pll_clk->dev_name); - if (ret) - pr_err("%s: failed to register lookup for %s : %d", - __func__, pll_clk->name, ret); } void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 7ce0fa86c5ff..484abc84a352 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -181,7 +181,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_mux(NULL, list->name, @@ -195,15 +195,6 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, clk_hw, list->id); - - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } } } @@ -213,7 +204,7 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) @@ -234,15 +225,6 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, clk_hw, list->id); - - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } } } @@ -252,7 +234,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name, @@ -264,15 +246,6 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, continue; } - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } - samsung_clk_add_lookup(ctx, clk_hw, list->id); } } diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index d5f0d3f818b6..1cb03b6e2dfd 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -106,7 +106,6 @@ struct samsung_fixed_factor_clock { /** * struct samsung_mux_clock: information about mux clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this mux clock. * @parent_names: array of pointer to parent clock names. * @num_parents: number of parents listed in @parent_names. @@ -115,11 +114,9 @@ struct samsung_fixed_factor_clock { * @shift: starting bit location of the mux control bit-field in @reg. * @width: width of the mux control bit-field in @reg. * @mux_flags: flags for mux-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_mux_clock { unsigned int id; - const char *dev_name; const char *name; const char *const *parent_names; u8 num_parents; @@ -128,13 +125,11 @@ struct samsung_mux_clock { u8 shift; u8 width; u8 mux_flags; - const char *alias; }; -#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \ +#define __MUX(_id, cname, pnames, o, s, w, f, mf) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_names = pnames, \ .num_parents = ARRAY_SIZE(pnames), \ @@ -143,36 +138,26 @@ struct samsung_mux_clock { .shift = s, \ .width = w, \ .mux_flags = mf, \ - .alias = a, \ } #define MUX(_id, cname, pnames, o, s, w) \ - __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL) - -#define MUX_A(_id, cname, pnames, o, s, w, a) \ - __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a) + __MUX(_id, cname, pnames, o, s, w, 0, 0) #define MUX_F(_id, cname, pnames, o, s, w, f, mf) \ - __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL) - -#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \ - __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a) + __MUX(_id, cname, pnames, o, s, w, f, mf) /** * @id: platform specific id of the clock. * struct samsung_div_clock: information about div clock - * @dev_name: name of the device to which this clock belongs. * @name: name of this div clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @offset: offset of the register for configuring the div. * @shift: starting bit location of the div control bit-field in @reg. * @div_flags: flags for div-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_div_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; @@ -180,14 +165,12 @@ struct samsung_div_clock { u8 shift; u8 width; u8 div_flags; - const char *alias; struct clk_div_table *table; }; -#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \ +#define __DIV(_id, cname, pname, o, s, w, f, df, t) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_name = pname, \ .flags = f, \ @@ -195,70 +178,51 @@ struct samsung_div_clock { .shift = s, \ .width = w, \ .div_flags = df, \ - .alias = a, \ .table = t, \ } #define DIV(_id, cname, pname, o, s, w) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL) - -#define DIV_A(_id, cname, pname, o, s, w, a) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL) + __DIV(_id, cname, pname, o, s, w, 0, 0, NULL) #define DIV_F(_id, cname, pname, o, s, w, f, df) \ - __DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL) + __DIV(_id, cname, pname, o, s, w, f, df, NULL) #define DIV_T(_id, cname, pname, o, s, w, t) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t) + __DIV(_id, cname, pname, o, s, w, 0, 0, t) /** * struct samsung_gate_clock: information about gate clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this gate clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @offset: offset of the register for configuring the gate. * @bit_idx: bit index of the gate control bit-field in @reg. * @gate_flags: flags for gate-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_gate_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; unsigned long offset; u8 bit_idx; u8 gate_flags; - const char *alias; }; -#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \ +#define __GATE(_id, cname, pname, o, b, f, gf) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_name = pname, \ .flags = f, \ .offset = o, \ .bit_idx = b, \ .gate_flags = gf, \ - .alias = a, \ } #define GATE(_id, cname, pname, o, b, f, gf) \ - __GATE(_id, NULL, cname, pname, o, b, f, gf, NULL) - -#define GATE_A(_id, cname, pname, o, b, f, gf, a) \ - __GATE(_id, NULL, cname, pname, o, b, f, gf, a) - -#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \ - __GATE(_id, dname, cname, pname, o, b, f, gf, NULL) - -#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \ - __GATE(_id, dname, cname, pname, o, b, f, gf, a) + __GATE(_id, cname, pname, o, b, f, gf) #define PNAME(x) static const char * const x[] __initconst @@ -275,18 +239,15 @@ struct samsung_clk_reg_dump { /** * struct samsung_pll_clock: information about pll clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this pll clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @con_offset: offset of the register for configuring the PLL. * @lock_offset: offset of the register for locking the PLL. * @type: Type of PLL to be registered. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_pll_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; @@ -294,31 +255,23 @@ struct samsung_pll_clock { int lock_offset; enum samsung_pll_type type; const struct samsung_pll_rate_table *rate_table; - const char *alias; }; -#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \ - _rtable, _alias) \ +#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable) \ { \ .id = _id, \ .type = _typ, \ - .dev_name = _dname, \ .name = _name, \ .parent_name = _pname, \ .flags = _flags, \ .con_offset = _con, \ .lock_offset = _lock, \ .rate_table = _rtable, \ - .alias = _alias, \ } #define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \ - __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, _rtable, _name) - -#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \ - __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, _rtable, _alias) + __PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \ + _con, _rtable) struct samsung_clock_reg_cache { struct list_head node; -- cgit v1.2.3 From 4e8975cbb516c5e4d1a5d026ffab1638409447d5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Oct 2017 11:15:12 +0200 Subject: clk: samsung: exynos5433: mark PM functions as __maybe_unused The suspend/resume functions are referenced conditionally, causing a harmless warning when CONFIG_PM is disabled: drivers/clk/samsung/clk-exynos5433.c:5476:12: error: 'exynos5433_cmu_resume' defined but not used [-Werror=unused-function] drivers/clk/samsung/clk-exynos5433.c:5453:12: error: 'exynos5433_cmu_suspend' defined but not used [-Werror=unused-function] This marks both as __maybe_unused to shut up the warning. Fixes: 523d3de41f02 ("clk: samsung: exynos5433: Add support for runtime PM") Signed-off-by: Arnd Bergmann Acked-by: Marek Szyprowski Acked-by: Chanwoo Choi Acked-by: Ulf Hansson Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index cd9337613dd8..db270908037a 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -5450,7 +5450,7 @@ struct exynos5433_cmu_data { struct samsung_clk_provider ctx; }; -static int exynos5433_cmu_suspend(struct device *dev) +static int __maybe_unused exynos5433_cmu_suspend(struct device *dev) { struct exynos5433_cmu_data *data = dev_get_drvdata(dev); int i; @@ -5473,7 +5473,7 @@ static int exynos5433_cmu_suspend(struct device *dev) return 0; } -static int exynos5433_cmu_resume(struct device *dev) +static int __maybe_unused exynos5433_cmu_resume(struct device *dev) { struct exynos5433_cmu_data *data = dev_get_drvdata(dev); int i; -- cgit v1.2.3 From d51fe3ba9773c8b6fc79f82bbe75d64baf604292 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:57 +0800 Subject: clk: sunxi-ng: sun5i: Fix bit offset of audio PLL post-divider The post-divider for the audio PLL is in bits [29:26], as specified in the user manual, not [19:16] as currently programmed in the code. The post-divider has a default register value of 2, i.e. a divider of 3. This means the clock rate fed to the audio codec would be off. This was discovered when porting sigma-delta modulation for the PLL to sun5i, which needs the post-divider to be 1. Fix the bit offset, so we do actually force the post-divider to a certain value. Fixes: 5e73761786d6 ("clk: sunxi-ng: Add sun5i CCU driver") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun5i.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index ab9e850b3707..2f385a57cd91 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -982,8 +982,8 @@ static void __init sun5i_ccu_init(struct device_node *node, /* Force the PLL-Audio-1x divider to 4 */ val = readl(reg + SUN5I_PLL_AUDIO_REG); - val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN5I_PLL_AUDIO_REG); + val &= ~GENMASK(29, 26); + writel(val | (3 << 26), reg + SUN5I_PLL_AUDIO_REG); /* * Use the peripheral PLL as the AHB parent, instead of CPU / -- cgit v1.2.3 From 4cdbc40d64d4b8303a97e29a52862e4d99502beb Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:58 +0800 Subject: clk: sunxi-ng: nm: Check if requested rate is supported by fractional clock The round_rate callback for N-M-factor style clocks does not check if the requested clock rate is supported by the fractional clock mode. While this doesn't affect usage in practice, since the clock rates are also supported through N-M factors, it does not match the set_rate code. Add a check to the round_rate callback so it matches the set_rate callback. Fixes: 6174a1e24b0d ("clk: sunxi-ng: Add N-M-factor clock support") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_nm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index a32158e8f2e3..84a5e7f17f6f 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -99,6 +99,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nm *nm = hw_to_ccu_nm(hw); struct _ccu_nm _nm; + if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) + return rate; + _nm.min_n = nm->n.min ?: 1; _nm.max_n = nm->n.max ?: 1 << nm->n.width; _nm.min_m = 1; -- cgit v1.2.3 From 05d2eaac96d4284b0967cc522ad22f6f23fdf82a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:59 +0800 Subject: clk: sunxi-ng: Add sigma-delta modulation support Sigma-delta modulation is supported for some PLLs. This allows fractional-N multipliers to be used. In reality we don't know how to configure the individual settings for it. However we can copy existing settings from the vendor kernel to support clock rates that cannot be generated from integer factors, but are really desired. The vendor kernel only uses this for the audio PLL clock, and only on the latest chips. This patch adds a new class of clocks, along with helper functions. It is intended to be merged into N-M-factor style clocks as a feature, much like fractional clocks. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_common.h | 1 + drivers/clk/sunxi-ng/ccu_sdm.c | 158 ++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_sdm.h | 80 +++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_sdm.c create mode 100644 drivers/clk/sunxi-ng/ccu_sdm.h (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 85a0633c1eac..8504d9c6f03a 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -10,6 +10,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_gate.o lib-$(CONFIG_SUNXI_CCU) += ccu_mux.o lib-$(CONFIG_SUNXI_CCU) += ccu_mult.o lib-$(CONFIG_SUNXI_CCU) += ccu_phase.o +lib-$(CONFIG_SUNXI_CCU) += ccu_sdm.o # Multi-factor clocks lib-$(CONFIG_SUNXI_CCU) += ccu_nk.o diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index cadd1a9f93b6..5d684ce77c54 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -24,6 +24,7 @@ #define CCU_FEATURE_ALL_PREDIV BIT(4) #define CCU_FEATURE_LOCK_REG BIT(5) #define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6) +#define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7) /* MMC timing mode switch bit */ #define CCU_MMC_NEW_TIMING_MODE BIT(30) diff --git a/drivers/clk/sunxi-ng/ccu_sdm.c b/drivers/clk/sunxi-ng/ccu_sdm.c new file mode 100644 index 000000000000..3b3dc9bdf2b0 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_sdm.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2017 Chen-Yu Tsai + * + * 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. + */ + +#include +#include + +#include "ccu_sdm.h" + +bool ccu_sdm_helper_is_enabled(struct ccu_common *common, + struct ccu_sdm_internal *sdm) +{ + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return false; + + if (sdm->enable && !(readl(common->base + common->reg) & sdm->enable)) + return false; + + return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable); +} + +void ccu_sdm_helper_enable(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate) +{ + unsigned long flags; + unsigned int i; + u32 reg; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return; + + /* Set the pattern */ + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) + writel(sdm->table[i].pattern, + common->base + sdm->tuning_reg); + + /* Make sure SDM is enabled */ + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + sdm->tuning_reg); + writel(reg | sdm->tuning_enable, common->base + sdm->tuning_reg); + spin_unlock_irqrestore(common->lock, flags); + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg | sdm->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); +} + +void ccu_sdm_helper_disable(struct ccu_common *common, + struct ccu_sdm_internal *sdm) +{ + unsigned long flags; + u32 reg; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return; + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg & ~sdm->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + sdm->tuning_reg); + writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg); + spin_unlock_irqrestore(common->lock, flags); +} + +/* + * Sigma delta modulation provides a way to do fractional-N frequency + * synthesis, in essence allowing the PLL to output any frequency + * within its operational range. On earlier SoCs such as the A10/A20, + * some PLLs support this. On later SoCs, all PLLs support this. + * + * The datasheets do not explain what the "wave top" and "wave bottom" + * parameters mean or do, nor how to calculate the effective output + * frequency. The only examples (and real world usage) are for the audio + * PLL to generate 24.576 and 22.5792 MHz clock rates used by the audio + * peripherals. The author lacks the underlying domain knowledge to + * pursue this. + * + * The goal and function of the following code is to support the two + * clock rates used by the audio subsystem, allowing for proper audio + * playback and capture without any pitch or speed changes. + */ +bool ccu_sdm_helper_has_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate) +{ + unsigned int i; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return false; + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) + return true; + + return false; +} + +unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + u32 m, u32 n) +{ + unsigned int i; + u32 reg; + + pr_debug("%s: Read sigma-delta modulation setting\n", + clk_hw_get_name(&common->hw)); + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return 0; + + pr_debug("%s: clock is sigma-delta modulated\n", + clk_hw_get_name(&common->hw)); + + reg = readl(common->base + sdm->tuning_reg); + + pr_debug("%s: pattern reg is 0x%x", + clk_hw_get_name(&common->hw), reg); + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].pattern == reg && + sdm->table[i].m == m && sdm->table[i].n == n) + return sdm->table[i].rate; + + /* We can't calculate the effective clock rate, so just fail. */ + return 0; +} + +int ccu_sdm_helper_get_factors(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate, + unsigned long *m, unsigned long *n) +{ + unsigned int i; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return -EINVAL; + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) { + *m = sdm->table[i].m; + *n = sdm->table[i].n; + return 0; + } + + /* nothing found */ + return -EINVAL; +} diff --git a/drivers/clk/sunxi-ng/ccu_sdm.h b/drivers/clk/sunxi-ng/ccu_sdm.h new file mode 100644 index 000000000000..2a9b4a2584d6 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_sdm.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved. + * + * 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. + */ + +#ifndef _CCU_SDM_H +#define _CCU_SDM_H + +#include + +#include "ccu_common.h" + +struct ccu_sdm_setting { + unsigned long rate; + + /* + * XXX We don't know what the step and bottom register fields + * mean. Just copy the whole register value from the vendor + * kernel for now. + */ + u32 pattern; + + /* + * M and N factors here should be the values used in + * calculation, not the raw values written to registers + */ + u32 m; + u32 n; +}; + +struct ccu_sdm_internal { + struct ccu_sdm_setting *table; + u32 table_size; + /* early SoCs don't have the SDM enable bit in the PLL register */ + u32 enable; + /* second enable bit in tuning register */ + u32 tuning_enable; + u16 tuning_reg; +}; + +#define _SUNXI_CCU_SDM(_table, _enable, \ + _reg, _reg_enable) \ + { \ + .table = _table, \ + .table_size = ARRAY_SIZE(_table), \ + .enable = _enable, \ + .tuning_enable = _reg_enable, \ + .tuning_reg = _reg, \ + } + +bool ccu_sdm_helper_is_enabled(struct ccu_common *common, + struct ccu_sdm_internal *sdm); +void ccu_sdm_helper_enable(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate); +void ccu_sdm_helper_disable(struct ccu_common *common, + struct ccu_sdm_internal *sdm); + +bool ccu_sdm_helper_has_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate); + +unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + u32 m, u32 n); + +int ccu_sdm_helper_get_factors(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate, + unsigned long *m, unsigned long *n); + +#endif -- cgit v1.2.3 From 392ba5fafcdf1969d1abd9a637cc40c45f4781bc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:00 +0800 Subject: clk: sunxi-ng: nm: Add support for sigma-delta modulation Some of the N-M-style clocks, namely the PLLs, support sigma-delta modulation to do fractional-N frequency synthesis. This is used in the audio PLL to generate the exact frequency the audio blocks need. These frequencies can not be generated with integer N-M factors. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_nm.c | 22 +++++++++++++++++++++- drivers/clk/sunxi-ng/ccu_nm.h | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 84a5e7f17f6f..7620aa973a6e 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -90,6 +90,14 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw, if (!m) m++; + if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) { + unsigned long rate = + ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, + m, n); + if (rate) + return rate; + } + return parent_rate * n / m; } @@ -102,6 +110,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) return rate; + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) + return rate; + _nm.min_n = nm->n.min ?: 1; _nm.max_n = nm->n.max ?: 1 << nm->n.width; _nm.min_m = 1; @@ -143,7 +154,16 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; - ccu_nm_find_best(parent_rate, rate, &_nm); + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) { + ccu_sdm_helper_enable(&nm->common, &nm->sdm, rate); + + /* Sigma delta modulation requires specific N and M factors */ + ccu_sdm_helper_get_factors(&nm->common, &nm->sdm, rate, + &_nm.m, &_nm.n); + } else { + ccu_sdm_helper_disable(&nm->common, &nm->sdm); + ccu_nm_find_best(parent_rate, rate, &_nm); + } spin_lock_irqsave(nm->common.lock, flags); diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h index e87fd186da78..c623b0c7a23c 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.h +++ b/drivers/clk/sunxi-ng/ccu_nm.h @@ -20,6 +20,7 @@ #include "ccu_div.h" #include "ccu_frac.h" #include "ccu_mult.h" +#include "ccu_sdm.h" /* * struct ccu_nm - Definition of an N-M clock @@ -33,10 +34,34 @@ struct ccu_nm { struct ccu_mult_internal n; struct ccu_div_internal m; struct ccu_frac_internal frac; + struct ccu_sdm_internal sdm; struct ccu_common common; }; +#define SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _mshift, _mwidth, \ + _sdm_table, _sdm_en, \ + _sdm_reg, _sdm_reg_en, \ + _gate, _lock, _flags) \ + struct ccu_nm _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .sdm = _SUNXI_CCU_SDM(_sdm_table, _sdm_en, \ + _sdm_reg, _sdm_reg_en),\ + .common = { \ + .reg = _reg, \ + .features = CCU_FEATURE_SIGMA_DELTA_MOD, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nm_ops, \ + _flags), \ + }, \ + } + #define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(_struct, _name, _parent, _reg, \ _nshift, _nwidth, \ _mshift, _mwidth, \ -- cgit v1.2.3 From a5e3e2b2ef85efe213c19b4911042bc2937a1aa6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:01 +0800 Subject: clk: sunxi-ng: sun8i: h3: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. This patch copies the parameters for the H3. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 543c46d0e045..29bc0566b776 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun8i-h3.h" @@ -44,18 +45,29 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_H3_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x0010, @@ -707,9 +719,9 @@ static struct ccu_common *sun50i_h5_ccu_clks[] = { &gpu_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1129,10 +1141,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, desc); -- cgit v1.2.3 From de344851919493033cdaa5736b2bfbcb05b50038 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:02 +0800 Subject: clk: sunxi-ng: sun4i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A10 and A20. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index a48fde191c0a..ffa5dac221e4 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -28,6 +28,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun4i-a10.h" @@ -51,16 +52,29 @@ static struct ccu_nkmp pll_core_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names. + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN4I_PLL_AUDIO_REG 0x008 + +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + static struct ccu_nm pll_audio_base_clk = { .enable = BIT(31), .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, 0, + 0x00c, BIT(31)), .common = { .reg = 0x008, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, .hw.init = CLK_HW_INIT("pll-audio-base", "hosc", &ccu_nm_ops, @@ -1021,9 +1035,9 @@ static struct ccu_common *sun4i_sun7i_ccu_clks[] = { &out_b_clk.common }; -/* Post-divider for pll-audio is hardcoded to 4 */ +/* Post-divider for pll-audio is hardcoded to 1 */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1420,10 +1434,10 @@ static void __init sun4i_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN4I_PLL_AUDIO_REG); val &= ~GENMASK(29, 26); - writel(val | (4 << 26), reg + SUN4I_PLL_AUDIO_REG); + writel(val | (1 << 26), reg + SUN4I_PLL_AUDIO_REG); /* * Use the peripheral PLL6 as the AHB parent, instead of CPU / -- cgit v1.2.3 From 042f7f8f9715096abce42b944d4a23b0e3c31521 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:03 +0800 Subject: clk: sunxi-ng: sun5i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the sun5i family. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun5i.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index 2f385a57cd91..fa2c2dd77102 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun5i.h" @@ -49,11 +50,20 @@ static struct ccu_nkmp pll_core_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN5I_PLL_AUDIO_REG 0x008 +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + static struct ccu_nm pll_audio_base_clk = { .enable = BIT(31), .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), @@ -63,8 +73,11 @@ static struct ccu_nm pll_audio_base_clk = { * offset */ .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, 0, + 0x00c, BIT(31)), .common = { .reg = 0x008, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, .hw.init = CLK_HW_INIT("pll-audio-base", "hosc", &ccu_nm_ops, @@ -597,9 +610,9 @@ static struct ccu_common *sun5i_a10s_ccu_clks[] = { &iep_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -980,10 +993,10 @@ static void __init sun5i_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN5I_PLL_AUDIO_REG); val &= ~GENMASK(29, 26); - writel(val | (3 << 26), reg + SUN5I_PLL_AUDIO_REG); + writel(val | (0 << 26), reg + SUN5I_PLL_AUDIO_REG); /* * Use the peripheral PLL as the AHB parent, instead of CPU / -- cgit v1.2.3 From ee6501d69217a887cb496c42ff97ba43adff4ab1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:04 +0800 Subject: clk: sunxi-ng: sun6i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A31. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 38 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 241fb13f1c06..72b16ed1012b 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -31,6 +31,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun6i-a31.h" @@ -48,18 +49,29 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_cpu_clk, "pll-cpu", * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN6I_A31_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", "osc24M", 0x010, @@ -950,9 +962,9 @@ static struct ccu_common *sun6i_a31_ccu_clks[] = { &out_c_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1221,10 +1233,10 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN6I_A31_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN6I_A31_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN6I_A31_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN6I_A31_PLL_MIPI_REG); -- cgit v1.2.3 From 24ea78a09f8948484e466474c038411a926f670f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:05 +0800 Subject: clk: sunxi-ng: sun8i: a23: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A23. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-a23.c | 38 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index d93b452f0df9..a4fa2945f230 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun8i-a23-a33.h" @@ -52,18 +53,29 @@ static struct ccu_nkmp pll_cpux_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_A23_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x010, @@ -538,9 +550,9 @@ static struct ccu_common *sun8i_a23_ccu_clks[] = { &ats_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -720,10 +732,10 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_A23_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_A23_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_A23_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN8I_A23_PLL_MIPI_REG); -- cgit v1.2.3 From 216ac5297a8083ac4a27a6cbc3d20d13dd17984d Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Mon, 4 Sep 2017 10:51:17 +0200 Subject: clk: rockchip: export clock pclk_efuse_256 for RK3368 SoCs This exports the clock for the pclk gate of the eFuse that is part of the RK3368 SoCs. So we can use it from the dt-bindings. Signed-off-by: Romain Perier Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index fc56565379dd..7c4d242f19c1 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -711,7 +711,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS), GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS), GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS), - GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS), + GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS), GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS), /* -- cgit v1.2.3 From 47e3ec0e4dae1714cc76596e38d16913f0e574e2 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 15 Sep 2017 10:33:50 +0200 Subject: clk: rockchip: use new cif/vdpu clock ids on rk3188 Use the new clock-ids for cif, vdpu, vepu on rk3188 Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 00ad0e5f8d66..67e73fd71f09 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -290,15 +290,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), - COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VEPU, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 9, GFLAGS), - GATE(0, "hclk_vepu", "aclk_vepu", 0, + GATE(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0, RK2928_CLKGATE_CON(3), 10, GFLAGS), - COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VDPU, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), - GATE(0, "hclk_vdpu", "aclk_vdpu", 0, + GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, @@ -644,13 +644,13 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), - GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), + GATE(HCLK_CIF1, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 14, GFLAGS), - GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), + GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS), GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), -- cgit v1.2.3 From 21bffe57f85c24fbb8d54aea4e46d2eac77242f6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:04:28 +0200 Subject: clk: renesas: r8a7795: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car H3 ES2.0 is S0D3. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 762b2f8824f1..b1d9f48eae9e 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -149,7 +149,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1), DEF_MOD("rwdt", 402, R8A7795_CLK_R), DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), - DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3), DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3), DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3), DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), @@ -348,6 +348,7 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = { { MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */ { MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */ { MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */ + { MOD_CLK_ID(408), R8A7795_CLK_S3D1 }, /* INTC-AP */ { MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */ { MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */ { MOD_CLK_ID(523), R8A7795_CLK_S3D4 }, /* PWM */ -- cgit v1.2.3 From 6e7ddf89d67c2b0cdd7a392bece9411789dda49b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:07:45 +0200 Subject: clk: renesas: r8a7796: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car M3-W is S0D3. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index e5e7fb212288..b3767472088a 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -143,7 +143,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1), DEF_MOD("rwdt", 402, R8A7796_CLK_R), DEF_MOD("intc-ex", 407, R8A7796_CLK_CP), - DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3), DEF_MOD("audmac1", 501, R8A7796_CLK_S0D3), DEF_MOD("audmac0", 502, R8A7796_CLK_S0D3), DEF_MOD("drif7", 508, R8A7796_CLK_S3D2), -- cgit v1.2.3 From 0022e4a2ef8f20257b21b8fa27c0cb683485270b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:08:11 +0200 Subject: clk: renesas: r8a77995: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car D3 is S1D2. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77995-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index e594cf8ee63b..ea4cafbe6e85 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -127,7 +127,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1), DEF_MOD("rwdt", 402, R8A77995_CLK_R), DEF_MOD("intc-ex", 407, R8A77995_CLK_CP), - DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2), DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1), DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C), DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C), -- cgit v1.2.3 From 75920aac275a930b4259b46e555d5b90f713e084 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 11 Oct 2017 11:25:11 +0200 Subject: clk: samsung: Instantiate Exynos4412 ISP clocks only when available Some registers for the Exynos 4412 ISP (Camera subsystem) clocks are located in the ISP power domain. Instantiate those clocks only when provided clock registers resource covers those registers. This is a preparation for adding a separate clock driver for ISP clocks, which will be integrated with power domain using runtime PM feature. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index e40b77583c47..bdd68247e054 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -822,6 +822,12 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { DIV(0, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4), DIV(0, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8), DIV(0, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4), + DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), + DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3), + DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3), +}; + +static struct samsung_div_clock exynos4x12_isp_div_clks[] = { DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3, CLK_GET_RATE_NOCACHE, 0), DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3, @@ -831,9 +837,6 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { 4, 3, CLK_GET_RATE_NOCACHE, 0), DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3, CLK_GET_RATE_NOCACHE, 0), - DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), - DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3), - DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3), }; /* list of gate clocks supported in all exynos4 soc's */ @@ -1132,6 +1135,13 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { 0, 0), GATE(CLK_I2S0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3, 0, 0), + GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), + GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0), + GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, + 0), +}; + +static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = { GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, @@ -1184,10 +1194,6 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), - GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), - GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0), - GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, - 0), }; static const struct samsung_clock_alias exynos4_aliases[] __initconst = { @@ -1522,6 +1528,8 @@ static void __init exynos4_clk_init(struct device_node *np, e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d), CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } else { + struct resource res; + samsung_clk_register_mux(ctx, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); samsung_clk_register_div(ctx, exynos4x12_div_clks, @@ -1533,6 +1541,15 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); + + of_address_to_resource(np, 0, &res); + if (resource_size(&res) > 0x18000) { + samsung_clk_register_div(ctx, exynos4x12_isp_div_clks, + ARRAY_SIZE(exynos4x12_isp_div_clks)); + samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks, + ARRAY_SIZE(exynos4x12_isp_gate_clks)); + } + if (of_machine_is_compatible("samsung,exynos4412")) { exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, -- cgit v1.2.3 From 7679eb20353dc74e47fbc97b2d77fd4f88a77c0f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 11 Oct 2017 11:25:13 +0200 Subject: clk: samsung: Add a separate driver for Exynos4412 ISP clocks Some registers for the Exynos 4412 ISP (Camera subsystem) clocks are located in the ISP power domain. Because those registers are also located in a different memory region than the main clock controller, support for them can be provided by a separate clock controller. This in turn allows to almost seamlessly make it aware of the power domain using recently introduced runtime PM support for clocks. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-exynos4412-isp.c | 179 +++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 drivers/clk/samsung/clk-exynos4412-isp.c (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 7afc21dc374e..8a67a3bb6803 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c new file mode 100644 index 000000000000..d5f1ccb36300 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos4412-isp.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Author: Marek Szyprowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos4412 ISP module. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +/* Exynos4x12 specific registers, which belong to ISP power domain */ +#define E4X12_DIV_ISP0 0x0300 +#define E4X12_DIV_ISP1 0x0304 +#define E4X12_GATE_ISP0 0x0800 +#define E4X12_GATE_ISP1 0x0804 + +/* + * Support for CMU save/restore across system suspends + */ +static struct samsung_clk_reg_dump *exynos4x12_save_isp; + +static const unsigned long exynos4x12_clk_isp_save[] __initconst = { + E4X12_DIV_ISP0, + E4X12_DIV_ISP1, + E4X12_GATE_ISP0, + E4X12_GATE_ISP1, +}; + +PNAME(mout_user_aclk400_mcuisp_p4x12) = { "fin_pll", "div_aclk400_mcuisp", }; + +static struct samsung_div_clock exynos4x12_isp_div_clks[] = { + DIV(CLK_ISP_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3), + DIV(CLK_ISP_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3), + DIV(CLK_ISP_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", + E4X12_DIV_ISP1, 4, 3), + DIV(CLK_ISP_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", + E4X12_DIV_ISP1, 8, 3), + DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), +}; + +static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = { + GATE(CLK_ISP_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, 0, 0), + GATE(CLK_ISP_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, 0, 0), + GATE(CLK_ISP_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2, 0, 0), + GATE(CLK_ISP_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, 0, 0), + GATE(CLK_ISP_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, 0, 0), + GATE(CLK_ISP_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, 0, 0), + GATE(CLK_ISP_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, 0, 0), + GATE(CLK_ISP_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, 0, 0), + GATE(CLK_ISP_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, 0, 0), + GATE(CLK_ISP_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, 0, 0), + GATE(CLK_ISP_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, + 0, 0), + GATE(CLK_ISP_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, + 0, 0), + GATE(CLK_ISP_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, + 0, 0), + GATE(CLK_ISP_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21, + 0, 0), + GATE(CLK_ISP_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23, + 0, 0), + GATE(CLK_ISP_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24, + 0, 0), + GATE(CLK_ISP_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25, + 0, 0), + GATE(CLK_ISP_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26, + 0, 0), + GATE(CLK_ISP_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27, + 0, 0), + GATE(CLK_ISP_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, 0, 0), + GATE(CLK_ISP_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, 0, 0), + GATE(CLK_ISP_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31, + 0, 0), + GATE(CLK_ISP_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0, + 0, 0), + GATE(CLK_ISP_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4, + 0, 0), + GATE(CLK_ISP_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12, + 0, 0), + GATE(CLK_ISP_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, + 0, 0), +}; + +static int __maybe_unused exynos4x12_isp_clk_suspend(struct device *dev) +{ + struct samsung_clk_provider *ctx = dev_get_drvdata(dev); + + samsung_clk_save(ctx->reg_base, exynos4x12_save_isp, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + return 0; +} + +static int __maybe_unused exynos4x12_isp_clk_resume(struct device *dev) +{ + struct samsung_clk_provider *ctx = dev_get_drvdata(dev); + + samsung_clk_restore(ctx->reg_base, exynos4x12_save_isp, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + return 0; +} + +static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev) +{ + struct samsung_clk_provider *ctx; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + void __iomem *reg_base; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(reg_base)) { + dev_err(dev, "failed to map registers\n"); + return PTR_ERR(reg_base); + } + + exynos4x12_save_isp = samsung_clk_alloc_reg_dump(exynos4x12_clk_isp_save, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + if (!exynos4x12_save_isp) + return -ENOMEM; + + ctx = samsung_clk_init(np, reg_base, CLK_NR_ISP_CLKS); + ctx->dev = dev; + + platform_set_drvdata(pdev, ctx); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + samsung_clk_register_div(ctx, exynos4x12_isp_div_clks, + ARRAY_SIZE(exynos4x12_isp_div_clks)); + samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks, + ARRAY_SIZE(exynos4x12_isp_gate_clks)); + + samsung_clk_of_add_provider(np, ctx); + pm_runtime_put(dev); + + return 0; +} + +static const struct of_device_id exynos4x12_isp_clk_of_match[] = { + { .compatible = "samsung,exynos4412-isp-clock", }, + { }, +}; + +static const struct dev_pm_ops exynos4x12_isp_pm_ops = { + SET_RUNTIME_PM_OPS(exynos4x12_isp_clk_suspend, + exynos4x12_isp_clk_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos4x12_isp_clk_driver __refdata = { + .driver = { + .name = "exynos4x12-isp-clk", + .of_match_table = exynos4x12_isp_clk_of_match, + .suppress_bind_attrs = true, + .pm = &exynos4x12_isp_pm_ops, + }, + .probe = exynos4x12_isp_clk_probe, +}; + +static int __init exynos4x12_isp_clk_init(void) +{ + return platform_driver_register(&exynos4x12_isp_clk_driver); +} +core_initcall(exynos4x12_isp_clk_init); -- cgit v1.2.3 From 553c7d5ba2fe64cdbfcdf49560ef71ef79810f93 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 17 Oct 2017 11:06:17 +0200 Subject: clk: sunxi-ng: Add A83T display clocks Unfortunately, the A83t display clocks are not children of the de clock, since that clocks doesn't exist at all on the A83t. For now, they are orphans, so let's move them to their true, existing, parent. Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU") Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 5cdaf52669e4..5cc9d9952121 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -41,11 +41,16 @@ static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div", static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4, CLK_SET_RATE_PARENT); -static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4, - CLK_SET_RATE_PARENT); static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4, CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, + CLK_SET_RATE_PARENT); + static struct ccu_common *sun8i_a83t_de2_clks[] = { &mixer0_clk.common, &mixer1_clk.common, @@ -55,9 +60,9 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = { &bus_mixer1_clk.common, &bus_wb_clk.common, - &mixer0_div_clk.common, - &mixer1_div_clk.common, - &wb_div_clk.common, + &mixer0_div_a83_clk.common, + &mixer1_div_a83_clk.common, + &wb_div_a83_clk.common, }; static struct ccu_common *sun8i_v3s_de2_clks[] = { @@ -81,9 +86,9 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, [CLK_BUS_WB] = &bus_wb_clk.common.hw, - [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, - [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, - [CLK_WB_DIV] = &wb_div_clk.common.hw, + [CLK_MIXER0_DIV] = &mixer0_div_a83_clk.common.hw, + [CLK_MIXER1_DIV] = &mixer1_div_a83_clk.common.hw, + [CLK_WB_DIV] = &wb_div_a83_clk.common.hw, }, .num = CLK_NUMBER, }; -- cgit v1.2.3 From 4328a2186e5120cfd34c4f04c6e4b7e74fb8b7b4 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Tue, 17 Oct 2017 20:18:03 +0800 Subject: clk: sunxi-ng: sun4i: Export video PLLs The video PLLs are used directly by the HDMI controller. Export them so that we can use them in our DT node. Signed-off-by: Jonathan Liu Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.h | 4 ++-- include/dt-bindings/clock/sun4i-a10-ccu.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h index c5947c7c050e..23c908ad509f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h @@ -29,7 +29,7 @@ #define CLK_PLL_AUDIO_4X 6 #define CLK_PLL_AUDIO_8X 7 #define CLK_PLL_VIDEO0 8 -#define CLK_PLL_VIDEO0_2X 9 +/* The PLL_VIDEO0_2X clock is exported */ #define CLK_PLL_VE 10 #define CLK_PLL_DDR_BASE 11 #define CLK_PLL_DDR 12 @@ -38,7 +38,7 @@ #define CLK_PLL_PERIPH 15 #define CLK_PLL_PERIPH_SATA 16 #define CLK_PLL_VIDEO1 17 -#define CLK_PLL_VIDEO1_2X 18 +/* The PLL_VIDEO1_2X clock is exported */ #define CLK_PLL_GPU 19 /* The CPU clock is exported */ diff --git a/include/dt-bindings/clock/sun4i-a10-ccu.h b/include/dt-bindings/clock/sun4i-a10-ccu.h index c5a53f38d654..e4fa61be5c75 100644 --- a/include/dt-bindings/clock/sun4i-a10-ccu.h +++ b/include/dt-bindings/clock/sun4i-a10-ccu.h @@ -43,6 +43,8 @@ #define _DT_BINDINGS_CLK_SUN4I_A10_H_ #define CLK_HOSC 1 +#define CLK_PLL_VIDEO0_2X 9 +#define CLK_PLL_VIDEO1_2X 18 #define CLK_CPU 20 /* AHB Gates */ -- cgit v1.2.3 From 231ca2e583be324012212d10ad913f30c2f66adb Mon Sep 17 00:00:00 2001 From: Timo Alho Date: Thu, 7 Sep 2017 12:31:02 +0300 Subject: clk: tegra: Check BPMP response return code Check return code in BPMP response message(s). The typical error case is when a clock operation is attempted with an invalid clock identifier. Also remove error print from call to clk_get_info() as the implementation loops through the range of all possible identifiers, yet the operation is expected to error out when the clock ID is unused. Signed-off-by: Timo Alho Acked-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-bpmp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 638ace64033b..a896692b74ec 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -55,6 +55,7 @@ struct tegra_bpmp_clk_message { struct { void *data; size_t size; + int ret; } rx; }; @@ -64,6 +65,7 @@ static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp, struct mrq_clk_request request; struct tegra_bpmp_message msg; void *req = &request; + int err; memset(&request, 0, sizeof(request)); request.cmd_and_id = (clk->cmd << 24) | clk->id; @@ -84,7 +86,13 @@ static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp, msg.rx.data = clk->rx.data; msg.rx.size = clk->rx.size; - return tegra_bpmp_transfer(bpmp, &msg); + err = tegra_bpmp_transfer(bpmp, &msg); + if (err < 0) + return err; + else if (msg.rx.ret < 0) + return -EINVAL; + + return 0; } static int tegra_bpmp_clk_prepare(struct clk_hw *hw) @@ -414,11 +422,8 @@ static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp, struct tegra_bpmp_clk_info *info = &clocks[count]; err = tegra_bpmp_clk_get_info(bpmp, id, info); - if (err < 0) { - dev_err(bpmp->dev, "failed to query clock %u: %d\n", - id, err); + if (err < 0) continue; - } if (info->num_parents >= U8_MAX) { dev_err(bpmp->dev, -- cgit v1.2.3 From 8be95190dac73a8b6bfc51a7c3ad6ec3d0a4d5f7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:11:53 +0200 Subject: clk: tegra: Add peripheral clock registration helper There is a common pattern that registers individual peripheral clocks from an initialization table. Add a common implementation to remove the duplication from various call sites. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-periph.c | 8 ++++++++ drivers/clk/tegra/clk.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index cf80831de79d..9475c00b7cf9 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -203,3 +203,11 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, return _tegra_clk_register_periph(name, parent_names, num_parents, periph, clk_base, offset, CLK_SET_RATE_PARENT); } + +struct clk *tegra_clk_register_periph_data(void __iomem *clk_base, + struct tegra_periph_init_data *init) +{ + return _tegra_clk_register_periph(init->name, init->p.parent_names, + init->num_parents, &init->periph, + clk_base, init->offset, init->flags); +} diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 872f1189ad7f..3b2763df51c2 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -662,6 +662,9 @@ struct tegra_periph_init_data { _clk_num, _gate_flags, _clk_id,\ NULL, 0, NULL) +struct clk *tegra_clk_register_periph_data(void __iomem *clk_base, + struct tegra_periph_init_data *init); + /** * struct clk_super_mux - super clock * -- cgit v1.2.3 From 1d7e2c8e5431454f65f0b785f3aa8bdba2ff436d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:19:08 +0200 Subject: clk: tegra: Use tegra_clk_register_periph_data() Instead of open-coding the same pattern repeatedly, reuse the newly introduced tegra_clk_register_periph_data() helper that will unpack the initialization structure. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 5 +---- drivers/clk/tegra/clk-tegra114.c | 4 +--- drivers/clk/tegra/clk-tegra20.c | 4 +--- drivers/clk/tegra/clk-tegra30.c | 4 +--- 4 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 848255cc0209..090a5d792341 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -927,10 +927,7 @@ static void __init periph_clk_init(void __iomem *clk_base, continue; data->periph.gate.regs = bank; - clk = tegra_clk_register_periph(data->name, - data->p.parent_names, data->num_parents, - &data->periph, clk_base, data->offset, - data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); *dt_clk = clk; } } diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index fd1a99c05c2d..63087d17c3e2 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1092,9 +1092,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base, for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, - data->p.parent_names, data->num_parents, - &data->periph, clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 837e5cbd60e9..2b839cb24436 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -850,9 +850,7 @@ static void __init tegra20_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->p.parent_names, - data->num_parents, &data->periph, - clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index a2d163f759b4..98e8a55e4e1c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1079,9 +1079,7 @@ static void __init tegra30_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->p.parent_names, - data->num_parents, &data->periph, - clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } -- cgit v1.2.3 From bc2e4d2986e9d2b8a99c16eb8222da2a360a581f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:21:04 +0200 Subject: clk: tegra: Fix sor1_out clock implementation This clock was previously called sor1_src and was modelled as an input to the sor1 module clock. However, it's really an output clock that can be fed either from the safe, the sor1_pad_clkout or the sor1 module clocks. sor1 itself can take input from either of the display PLLs. The same implementation for the sor1_out clock is used on Tegra186, so this nicely lines up both SoC generations to deal with this clock in a uniform way. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 16 ------------ drivers/clk/tegra/clk-tegra210.c | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 090a5d792341..c7694205573f 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -129,7 +129,6 @@ #define CLK_SOURCE_NVDEC 0x698 #define CLK_SOURCE_NVJPG 0x69c #define CLK_SOURCE_APE 0x6c0 -#define CLK_SOURCE_SOR1 0x410 #define CLK_SOURCE_SDMMC_LEGACY 0x694 #define CLK_SOURCE_QSPI 0x6c4 #define CLK_SOURCE_VI_I2C 0x6c8 @@ -278,7 +277,6 @@ static DEFINE_SPINLOCK(PLLP_OUTA_lock); static DEFINE_SPINLOCK(PLLP_OUTB_lock); static DEFINE_SPINLOCK(PLLP_OUTC_lock); static DEFINE_SPINLOCK(sor0_lock); -static DEFINE_SPINLOCK(sor1_lock); #define MUX_I2S_SPDIF(_id) \ static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ @@ -604,18 +602,6 @@ static u32 mux_pllp_plld_plld2_clkm_idx[] = { [0] = 0, [1] = 2, [2] = 5, [3] = 6 }; -static const char *mux_sor_safe_sor1_brick_sor1_src[] = { - /* - * Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the - * sor1_brick parent appears twice in the list below. This is merely - * to support clk_get_parent() if firmware happened to set these bits - * to 0b11. While not an invalid setting, code should always set the - * bits to 0b01 to select sor1_brick. - */ - "sor_safe", "sor1_brick", "sor1_src", "sor1_brick" -}; -#define mux_sor_safe_sor1_brick_sor1_src_idx NULL - static const char *mux_pllp_pllre_clkm[] = { "pll_p", "pll_re_out1", "clk_m" }; @@ -804,8 +790,6 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec), MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), - MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock), - NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 6d7a613f2656..be7b736371f6 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -40,6 +40,7 @@ #define CLK_SOURCE_CSITE 0x1d4 #define CLK_SOURCE_EMC 0x19c +#define CLK_SOURCE_SOR1 0x410 #define PLLC_BASE 0x80 #define PLLC_OUT 0x84 @@ -264,6 +265,7 @@ static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(pll_e_lock); static DEFINE_SPINLOCK(pll_re_lock); static DEFINE_SPINLOCK(pll_u_lock); +static DEFINE_SPINLOCK(sor1_lock); static DEFINE_SPINLOCK(emc_lock); /* possible OSC frequencies in Hz */ @@ -2628,10 +2630,35 @@ static int tegra210_init_pllu(void) return 0; } +static const char * const sor1_out_parents[] = { + /* + * Bit 0 of the mux selects sor1_pad_clkout, irrespective of bit 1, so + * the sor1_pad_clkout parent appears twice in the list below. This is + * merely to support clk_get_parent() if firmware happened to set + * these bits to 0b11. While not an invalid setting, code should + * always set the bits to 0b01 to select sor1_pad_clkout. + */ + "sor_safe", "sor1_pad_clkout", "sor1", "sor1_pad_clkout", +}; + +static const char * const sor1_parents[] = { + "pll_p", "pll_d_out0", "pll_d2_out0", "clk_m", +}; + +static u32 sor1_parents_idx[] = { 0, 2, 5, 6 }; + +static struct tegra_periph_init_data tegra210_periph[] = { + TEGRA_INIT_DATA_TABLE("sor1", NULL, NULL, sor1_parents, + CLK_SOURCE_SOR1, 29, 0x7, 0, 0, 8, 1, + TEGRA_DIVIDER_ROUND_UP, 183, 0, tegra_clk_sor1, + sor1_parents_idx, 0, &sor1_lock), +}; + static __init void tegra210_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { struct clk *clk; + unsigned int i; /* xusb_ss_div2 */ clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0, @@ -2650,6 +2677,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 1, 17, 207); clks[TEGRA210_CLK_DPAUX1] = clk; + clk = clk_register_mux_table(NULL, "sor1_out", sor1_out_parents, + ARRAY_SIZE(sor1_out_parents), 0, + clk_base + CLK_SOURCE_SOR1, 14, 0x3, + 0, NULL, &sor1_lock); + clks[TEGRA210_CLK_SOR1_OUT] = clk; + /* pll_d_dsi_out */ clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); @@ -2694,6 +2727,20 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 0, NULL); clks[TEGRA210_CLK_ACLK] = clk; + for (i = 0; i < ARRAY_SIZE(tegra210_periph); i++) { + struct tegra_periph_init_data *init = &tegra210_periph[i]; + struct clk **clkp; + + clkp = tegra_lookup_dt_id(init->clk_id, tegra210_clks); + if (!clkp) { + pr_warn("clock %u not found\n", init->clk_id); + continue; + } + + clk = tegra_clk_register_periph_data(clk_base, init); + *clkp = clk; + } + tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params); } -- cgit v1.2.3 From d83b26e0f2b013d29cc1431e35eb10c85e76784a Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 3 Oct 2017 01:42:08 +0530 Subject: clk: tegra: Make tegra_clk_pll_params __ro_after_init These structures are only passed to the functions tegra_clk_register_pll, tegra_clk_register_pll{e/u} or tegra_periph_clk_init during the init phase. These functions modify the structures only during the init phase and after that the structures are never modified. Therefore, make them __ro_after_init. Signed-off-by: Bhumika Goyal Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 98e8a55e4e1c..455502a42b20 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -359,7 +359,7 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { }; /* PLL parameters */ -static struct tegra_clk_pll_params pll_c_params = { +static struct tegra_clk_pll_params pll_c_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -388,7 +388,7 @@ static struct div_nmp pllm_nmp = { .override_divp_shift = 15, }; -static struct tegra_clk_pll_params pll_m_params = { +static struct tegra_clk_pll_params pll_m_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -409,7 +409,7 @@ static struct tegra_clk_pll_params pll_m_params = { TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_FIXED, }; -static struct tegra_clk_pll_params pll_p_params = { +static struct tegra_clk_pll_params pll_p_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -444,7 +444,7 @@ static struct tegra_clk_pll_params pll_a_params = { TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_d_params = { +static struct tegra_clk_pll_params pll_d_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -461,7 +461,7 @@ static struct tegra_clk_pll_params pll_d_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_d2_params = { +static struct tegra_clk_pll_params pll_d2_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -478,7 +478,7 @@ static struct tegra_clk_pll_params pll_d2_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_u_params = { +static struct tegra_clk_pll_params pll_u_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -496,7 +496,7 @@ static struct tegra_clk_pll_params pll_u_params = { TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_x_params = { +static struct tegra_clk_pll_params pll_x_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -513,7 +513,7 @@ static struct tegra_clk_pll_params pll_x_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_e_params = { +static struct tegra_clk_pll_params pll_e_params __ro_after_init = { .input_min = 12000000, .input_max = 216000000, .cf_min = 12000000, -- cgit v1.2.3 From 4cf8f811c64ab570d40cb2f4bfc723750aec122f Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 16 Oct 2017 17:34:44 +0200 Subject: clk: meson: gxbb: Add VPU and VAPB clockids Add the clkids for the clocks feeding the Video Processing Unit. Acked-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb.h | 6 +++++- include/dt-bindings/clock/gxbb-clkc.h | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 5b1d4b374d1c..aee6fbba2004 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -190,8 +190,12 @@ #define CLKID_SD_EMMC_B_CLK0_DIV 121 #define CLKID_SD_EMMC_C_CLK0_SEL 123 #define CLKID_SD_EMMC_C_CLK0_DIV 124 +#define CLKID_VPU_0_DIV 127 +#define CLKID_VPU_1_DIV 130 +#define CLKID_VAPB_0_DIV 134 +#define CLKID_VAPB_1_DIV 137 -#define NR_CLKS 126 +#define NR_CLKS 141 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index c04a76d8facf..7c5a6f3825a5 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -113,5 +113,16 @@ #define CLKID_SD_EMMC_A_CLK0 119 #define CLKID_SD_EMMC_B_CLK0 122 #define CLKID_SD_EMMC_C_CLK0 125 +#define CLKID_VPU_0_SEL 126 +#define CLKID_VPU_0 128 +#define CLKID_VPU_1_SEL 129 +#define CLKID_VPU_1 131 +#define CLKID_VPU 132 +#define CLKID_VAPB_0_SEL 133 +#define CLKID_VAPB_0 135 +#define CLKID_VAPB_1_SEL 136 +#define CLKID_VAPB_1 138 +#define CLKID_VAPB_SEL 139 +#define CLKID_VAPB 140 #endif /* __GXBB_CLKC_H */ -- cgit v1.2.3 From 762a1f2098b2fd4f84ccdb62d5747fff1ad7f816 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 16 Oct 2017 17:34:45 +0200 Subject: clk: meson: gxbb: Add VPU and VAPB clocks data The Amlogic Meson GX SoCs needs these two clocks to power up the VPU power domain. These two clocks are similar to the MALI clocks by having a glitch-free mux and two similar clocks with gate, divider and muxes. Acked-by: Jerome Brunet [narmstrong: removed the CLK_IGNORE_UNUSED on muxes and dividers] Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb.c | 292 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index b2d1e8ed7152..ae385310e980 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1131,6 +1131,253 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = { }, }; +/* VPU Clock */ + +static u32 mux_table_vpu[] = {0, 1, 2, 3}; +static const char * const gxbb_vpu_parent_names[] = { + "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +}; + +static struct clk_mux gxbb_vpu_0_sel = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .table = mux_table_vpu, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_sel", + .ops = &clk_mux_ops, + /* + * bits 9:10 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vpu_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vpu_0_div = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vpu_0_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vpu_0 = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vpu_0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vpu_0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vpu_1_sel = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 25, + .lock = &clk_lock, + .table = mux_table_vpu, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_sel", + .ops = &clk_mux_ops, + /* + * bits 25:26 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vpu_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vpu_1_div = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vpu_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vpu_1 = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vpu_1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vpu_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vpu = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 1, + .shift = 31, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu", + .ops = &clk_mux_ops, + /* + * bit 31 selects from 2 possible parents: + * vpu_0 or vpu_1 + */ + .parent_names = (const char *[]){ "vpu_0", "vpu_1" }, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +/* VAPB Clock */ + +static u32 mux_table_vapb[] = {0, 1, 2, 3}; +static const char * const gxbb_vapb_parent_names[] = { + "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +}; + +static struct clk_mux gxbb_vapb_0_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .table = mux_table_vapb, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_sel", + .ops = &clk_mux_ops, + /* + * bits 9:10 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vapb_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vapb_0_div = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vapb_0_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vapb_0 = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb_0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vapb_1_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 25, + .lock = &clk_lock, + .table = mux_table_vapb, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_sel", + .ops = &clk_mux_ops, + /* + * bits 25:26 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vapb_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vapb_1_div = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vapb_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vapb_1 = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb_1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vapb_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 1, + .shift = 31, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_sel", + .ops = &clk_mux_ops, + /* + * bit 31 selects from 2 possible parents: + * vapb_0 or vapb_1 + */ + .parent_names = (const char *[]){ "vapb_0", "vapb_1" }, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_gate gxbb_vapb = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 30, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); @@ -1349,6 +1596,21 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, + [CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw, + [CLKID_VPU_0] = &gxbb_vpu_0.hw, + [CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw, + [CLKID_VPU_1] = &gxbb_vpu_1.hw, + [CLKID_VPU] = &gxbb_vpu.hw, + [CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw, + [CLKID_VAPB_0] = &gxbb_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw, + [CLKID_VAPB_1] = &gxbb_vapb_1.hw, + [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, + [CLKID_VAPB] = &gxbb_vapb.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1481,6 +1743,21 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, + [CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw, + [CLKID_VPU_0] = &gxbb_vpu_0.hw, + [CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw, + [CLKID_VPU_1] = &gxbb_vpu_1.hw, + [CLKID_VPU] = &gxbb_vpu.hw, + [CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw, + [CLKID_VAPB_0] = &gxbb_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw, + [CLKID_VAPB_1] = &gxbb_vapb_1.hw, + [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, + [CLKID_VAPB] = &gxbb_vapb.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1600,6 +1877,11 @@ static struct clk_gate *const gxbb_clk_gates[] = { &gxbb_sd_emmc_a_clk0, &gxbb_sd_emmc_b_clk0, &gxbb_sd_emmc_c_clk0, + &gxbb_vpu_0, + &gxbb_vpu_1, + &gxbb_vapb_0, + &gxbb_vapb_1, + &gxbb_vapb, }; static struct clk_mux *const gxbb_clk_muxes[] = { @@ -1615,6 +1897,12 @@ static struct clk_mux *const gxbb_clk_muxes[] = { &gxbb_sd_emmc_a_clk0_sel, &gxbb_sd_emmc_b_clk0_sel, &gxbb_sd_emmc_c_clk0_sel, + &gxbb_vpu_0_sel, + &gxbb_vpu_1_sel, + &gxbb_vpu, + &gxbb_vapb_0_sel, + &gxbb_vapb_1_sel, + &gxbb_vapb_sel, }; static struct clk_divider *const gxbb_clk_dividers[] = { @@ -1627,6 +1915,10 @@ static struct clk_divider *const gxbb_clk_dividers[] = { &gxbb_sd_emmc_a_clk0_div, &gxbb_sd_emmc_b_clk0_div, &gxbb_sd_emmc_c_clk0_div, + &gxbb_vpu_0_div, + &gxbb_vpu_1_div, + &gxbb_vapb_0_div, + &gxbb_vapb_1_div, }; static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { -- cgit v1.2.3 From d454cecc637b90996ab15b2e61a6cc51b7e1463c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Oct 2017 10:54:22 +0200 Subject: clk: renesas: rz: clk-rz is meant for RZ/A1 The RZ family of Renesas SoCs has several different subfamilies (RZ/A, RZ/G, RZ/N, and RZ/T). Clarify that the renesas,rz-cpg-clocks DT bindings and clk-rz driver apply to RZ/A1 only. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Acked-by: Rob Herring --- Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt | 4 ++-- drivers/clk/renesas/clk-rz.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt index bb5d942075fb..8ff3e2774ed8 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt @@ -1,6 +1,6 @@ -* Renesas RZ Clock Pulse Generator (CPG) +* Renesas RZ/A1 Clock Pulse Generator (CPG) -The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable +The CPG generates core clocks for the RZ/A1 SoCs. It includes the PLL, variable CPU and GPU clocks, and several fixed ratio dividers. The CPG also provides a Clock Domain for SoC devices, in combination with the CPG Module Stop (MSTP) Clocks. diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c index 5adb934326d1..127c58135c8f 100644 --- a/drivers/clk/renesas/clk-rz.c +++ b/drivers/clk/renesas/clk-rz.c @@ -1,5 +1,5 @@ /* - * rz Core CPG Clocks + * RZ/A1 Core CPG Clocks * * Copyright (C) 2013 Ideas On Board SPRL * Copyright (C) 2014 Wolfram Sang, Sang Engineering -- cgit v1.2.3 From 9dc0ddee8d6dcc201b7f9ebc1c0834b0fa306096 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 13 Oct 2017 16:22:21 +0100 Subject: clk: renesas: cpg-mssr: Add du1 clock to R8A7745 Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7745-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c index 9e2360a8e14b..2859504cc866 100644 --- a/drivers/clk/renesas/r8a7745-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c @@ -129,6 +129,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = { DEF_MOD("scif2", 719, R8A7745_CLK_P), DEF_MOD("scif1", 720, R8A7745_CLK_P), DEF_MOD("scif0", 721, R8A7745_CLK_P), + DEF_MOD("du1", 723, R8A7745_CLK_ZX), DEF_MOD("du0", 724, R8A7745_CLK_ZX), DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX), DEF_MOD("vin1", 810, R8A7745_CLK_ZG), -- cgit v1.2.3 From 560869100b99a3daea329efce738a3b7ae357be8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 7 Jun 2017 13:20:06 +0200 Subject: clk: renesas: cpg-mssr: Restore module clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their clock register state is lost. Note that as the boot loader skips most initialization after system resume, clock register state differs from the state encountered during normal system boot, too. Hence after s2ram, some operations may fail because module clocks are disabled, while drivers expect them to be still enabled. E.g. EtherAVB fails when Wake-on-LAN has been enabled using "ethtool -s eth0 wol g": ravb e6800000.ethernet eth0: failed to switch device to config mode ravb e6800000.ethernet eth0: device will be stopped after h/w processes are done. ravb e6800000.ethernet eth0: failed to switch device to config PM: Device e6800000.ethernet failed to resume: error -110 In addition, some module clocks that were disabled by clk_disable_unused() may have been re-enabled, wasting power. To fix this, restore all bits of the SMSTPCR registers that represent clocks under control of Linux. Notes: - While this fixes EtherAVB operation after resume from s2ram, EtherAVB cannot be used as an actual wake-up source from s2ram, only from s2idle, due to PSCI limitations, - To avoid overhead on platforms not needing it, the suspend/resume code has a build time dependency on sleep and PSCI support, and a runtime dependency on PSCI. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/renesas-cpg-mssr.c | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1779b0cc7a2a..15fc8679d342 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,8 @@ static const u16 srcr[] = { * @num_core_clks: Number of Core Clocks in clks[] * @num_mod_clks: Number of Module Clocks in clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control + * @smstpcr_saved[].val: Saved values of SMSTPCR[] */ struct cpg_mssr_priv { #ifdef CONFIG_RESET_CONTROLLER @@ -119,6 +122,11 @@ struct cpg_mssr_priv { unsigned int num_core_clks; unsigned int num_mod_clks; unsigned int last_dt_core_clk; + + struct { + u32 mask; + u32 val; + } smstpcr_saved[ARRAY_SIZE(smstpcr)]; }; @@ -382,6 +390,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); priv->clks[id] = clk; + priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32); return; fail: @@ -700,6 +709,79 @@ static void cpg_mssr_del_clk_provider(void *data) of_clk_del_provider(data); } +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW) +static int cpg_mssr_suspend_noirq(struct device *dev) +{ + struct cpg_mssr_priv *priv = dev_get_drvdata(dev); + unsigned int reg; + + /* This is the best we can do to check for the presence of PSCI */ + if (!psci_ops.cpu_suspend) + return 0; + + /* Save module registers with bits under our control */ + for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { + if (priv->smstpcr_saved[reg].mask) + priv->smstpcr_saved[reg].val = + readl(priv->base + SMSTPCR(reg)); + } + + return 0; +} + +static int cpg_mssr_resume_noirq(struct device *dev) +{ + struct cpg_mssr_priv *priv = dev_get_drvdata(dev); + unsigned int reg, i; + u32 mask, oldval, newval; + + /* This is the best we can do to check for the presence of PSCI */ + if (!psci_ops.cpu_suspend) + return 0; + + /* Restore module clocks */ + for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { + mask = priv->smstpcr_saved[reg].mask; + if (!mask) + continue; + + oldval = readl(priv->base + SMSTPCR(reg)); + newval = oldval & ~mask; + newval |= priv->smstpcr_saved[reg].val & mask; + if (newval == oldval) + continue; + + writel(newval, priv->base + SMSTPCR(reg)); + + /* Wait until enabled clocks are really enabled */ + mask &= ~priv->smstpcr_saved[reg].val; + if (!mask) + continue; + + for (i = 1000; i > 0; --i) { + oldval = readl(priv->base + MSTPSR(reg)); + if (!(oldval & mask)) + break; + cpu_relax(); + } + + if (!i) + dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n", + priv->base + SMSTPCR(reg), oldval & mask); + } + + return 0; +} + +static const struct dev_pm_ops cpg_mssr_pm = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq, + cpg_mssr_resume_noirq) +}; +#define DEV_PM_OPS &cpg_mssr_pm +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ + static int __init cpg_mssr_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -735,6 +817,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) if (!clks) return -ENOMEM; + dev_set_drvdata(dev, priv); priv->clks = clks; priv->num_core_clks = info->num_total_core_clks; priv->num_mod_clks = info->num_hw_mod_clks; @@ -775,6 +858,7 @@ static struct platform_driver cpg_mssr_driver = { .driver = { .name = "renesas-cpg-mssr", .of_match_table = cpg_mssr_match, + .pm = DEV_PM_OPS, }, }; -- cgit v1.2.3 From 1f4023cdd1bdbe6cb01d0b2cbd1f46207189e3cf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:24:15 +0200 Subject: clk: renesas: cpg-mssr: Add support to restore core clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, possibly losing clock configuration. Hence add a notifier chain that can be used by core clocks to save/restore clock state during system suspend/resume. The implementation of the actual clock state save/restore operations is clock-specific, and to be registered with the notifier chain in the SoC or family-specific cpg_mssr_info.cpg_clk_register() callback. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen2-cpg.c | 7 +++---- drivers/clk/renesas/rcar-gen2-cpg.h | 6 +++--- drivers/clk/renesas/rcar-gen3-cpg.c | 3 ++- drivers/clk/renesas/rcar-gen3-cpg.h | 3 ++- drivers/clk/renesas/renesas-cpg-mssr.c | 12 +++++++++++- drivers/clk/renesas/renesas-cpg-mssr.h | 3 ++- 6 files changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c index 123b1e622179..feb14579a71b 100644 --- a/drivers/clk/renesas/rcar-gen2-cpg.c +++ b/drivers/clk/renesas/rcar-gen2-cpg.c @@ -262,10 +262,9 @@ static unsigned int cpg_pll0_div __initdata; static u32 cpg_mode __initdata; struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, - void __iomem *base) + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) { const struct clk_div_table *table = NULL; const struct clk *parent; diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h index 9eba07ff8b11..020a3baad015 100644 --- a/drivers/clk/renesas/rcar-gen2-cpg.h +++ b/drivers/clk/renesas/rcar-gen2-cpg.h @@ -34,9 +34,9 @@ struct rcar_gen2_cpg_pll_config { }; struct clk *rcar_gen2_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config, unsigned int pll0_div, u32 mode); diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 951105816547..139985257003 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -265,7 +265,8 @@ static const struct soc_device_attribute cpg_quirks_match[] __initconst = { struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base) + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) { const struct clk *parent; unsigned int mult = 1; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index d756ef8b78eb..2e4284399f53 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -44,7 +44,8 @@ struct rcar_gen3_cpg_pll_config { struct clk *rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, unsigned int clk_extalr, u32 mode); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 15fc8679d342..485dce00a562 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -107,6 +107,7 @@ static const u16 srcr[] = { * @num_core_clks: Number of Core Clocks in clks[] * @num_mod_clks: Number of Module Clocks in clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @notifiers: Notifier chain to save/restore clock state for system resume * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control * @smstpcr_saved[].val: Saved values of SMSTPCR[] */ @@ -123,6 +124,7 @@ struct cpg_mssr_priv { unsigned int num_mod_clks; unsigned int last_dt_core_clk; + struct raw_notifier_head notifiers; struct { u32 mask; u32 val; @@ -312,7 +314,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, default: if (info->cpg_clk_register) clk = info->cpg_clk_register(dev, core, info, - priv->clks, priv->base); + priv->clks, priv->base, + &priv->notifiers); else dev_err(dev, "%s has unsupported core clock type %u\n", core->name, core->type); @@ -726,6 +729,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev) readl(priv->base + SMSTPCR(reg)); } + /* Save core clocks */ + raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL); + return 0; } @@ -739,6 +745,9 @@ static int cpg_mssr_resume_noirq(struct device *dev) if (!psci_ops.cpu_suspend) return 0; + /* Restore core clocks */ + raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL); + /* Restore module clocks */ for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { mask = priv->smstpcr_saved[reg].mask; @@ -822,6 +831,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) priv->num_core_clks = info->num_total_core_clks; priv->num_mod_clks = info->num_hw_mod_clks; priv->last_dt_core_clk = info->last_dt_core_clk; + RAW_INIT_NOTIFIER_HEAD(&priv->notifiers); for (i = 0; i < nclks; i++) clks[i] = ERR_PTR(-ENOENT); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 66528ce3eb37..0745b0930308 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -127,7 +127,8 @@ struct cpg_mssr_info { struct clk *(*cpg_clk_register)(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); }; extern const struct cpg_mssr_info r8a7743_cpg_mssr_info; -- cgit v1.2.3 From 9f8c71e5134982cdf8ee35acb204715a2a47ba2e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:34:33 +0200 Subject: clk: renesas: div6: Restore clock state during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register an (optional) notifier to restore the DIV6 clock state during system resume. As DIV6 clocks can be picky w.r.t. modifying multiple register fields at once, restore is not implemented by blindly restoring the register value, but by using the existing cpg_div6_clock_{en,dis}able() helpers. Note that this does not yet support DIV6 clocks with multiple parents, which do not exist on R-Car Gen3 SoCs. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/clk-div6.c | 38 ++++++++++++++++++++++++++++++++-- drivers/clk/renesas/clk-div6.h | 3 ++- drivers/clk/renesas/renesas-cpg-mssr.c | 3 ++- 3 files changed, 40 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 3e0040c0ac87..151336d2ba59 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include "clk-div6.h" @@ -32,6 +34,7 @@ * @src_shift: Shift to access the register bits to select the parent clock * @src_width: Number of register bits to select the parent clock (may be 0) * @parents: Array to map from valid parent clocks indices to hardware indices + * @nb: Notifier block to save/restore clock state for system resume */ struct div6_clock { struct clk_hw hw; @@ -40,6 +43,7 @@ struct div6_clock { u32 src_shift; u32 src_width; u8 *parents; + struct notifier_block nb; }; #define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) @@ -176,6 +180,29 @@ static const struct clk_ops cpg_div6_clock_ops = { .set_rate = cpg_div6_clock_set_rate, }; +static int cpg_div6_clock_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct div6_clock *clock = container_of(nb, struct div6_clock, nb); + + switch (action) { + case PM_EVENT_RESUME: + /* + * TODO: This does not yet support DIV6 clocks with multiple + * parents, as the parent selection bits are not restored. + * Fortunately so far such DIV6 clocks are found only on + * R/SH-Mobile SoCs, while the resume functionality is only + * needed on R-Car Gen3. + */ + if (__clk_get_enable_count(clock->hw.clk)) + cpg_div6_clock_enable(&clock->hw); + else + cpg_div6_clock_disable(&clock->hw); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} /** * cpg_div6_register - Register a DIV6 clock @@ -183,11 +210,13 @@ static const struct clk_ops cpg_div6_clock_ops = { * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8) * @parent_names: Array containing the names of the parent clocks * @reg: Mapped register used to control the DIV6 clock + * @notifiers: Optional notifier chain to save/restore state for system resume */ struct clk * __init cpg_div6_register(const char *name, unsigned int num_parents, const char **parent_names, - void __iomem *reg) + void __iomem *reg, + struct raw_notifier_head *notifiers) { unsigned int valid_parents; struct clk_init_data init; @@ -258,6 +287,11 @@ struct clk * __init cpg_div6_register(const char *name, if (IS_ERR(clk)) goto free_parents; + if (notifiers) { + clock->nb.notifier_call = cpg_div6_clock_notifier_call; + raw_notifier_chain_register(notifiers, &clock->nb); + } + return clk; free_parents: @@ -301,7 +335,7 @@ static void __init cpg_div6_clock_init(struct device_node *np) for (i = 0; i < num_parents; i++) parent_names[i] = of_clk_get_parent_name(np, i); - clk = cpg_div6_register(clk_name, num_parents, parent_names, reg); + clk = cpg_div6_register(clk_name, num_parents, parent_names, reg, NULL); if (IS_ERR(clk)) { pr_err("%s: failed to register %s DIV6 clock (%ld)\n", __func__, np->name, PTR_ERR(clk)); diff --git a/drivers/clk/renesas/clk-div6.h b/drivers/clk/renesas/clk-div6.h index 567b31d2bfa5..da4807299dda 100644 --- a/drivers/clk/renesas/clk-div6.h +++ b/drivers/clk/renesas/clk-div6.h @@ -2,6 +2,7 @@ #define __RENESAS_CLK_DIV6_H__ struct clk *cpg_div6_register(const char *name, unsigned int num_parents, - const char **parent_names, void __iomem *reg); + const char **parent_names, void __iomem *reg, + struct raw_notifier_head *notifiers); #endif diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 485dce00a562..e3d03ffea4bc 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -303,7 +303,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, if (core->type == CLK_TYPE_DIV6P1) { clk = cpg_div6_register(core->name, 1, &parent_name, - priv->base + core->offset); + priv->base + core->offset, + &priv->notifiers); } else { clk = clk_register_fixed_factor(NULL, core->name, parent_name, 0, -- cgit v1.2.3 From 9f55b17ff6387ab9c4caa9280e2e194bb03ad532 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:51:21 +0200 Subject: clk: renesas: rcar-gen3: Restore SDHI clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register a notifier to save/restore SDHI clock registers during system suspend/resume. This is implemented using the cpg_simple_notifier abstraction, which can be reused for others clocks that just need to save/restore a single register. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen3-cpg.c | 63 +++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 139985257003..267b5629e3bd 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,36 @@ #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 +struct cpg_simple_notifier { + struct notifier_block nb; + void __iomem *reg; + u32 saved; +}; + +static int cpg_simple_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct cpg_simple_notifier *csn = + container_of(nb, struct cpg_simple_notifier, nb); + + switch (action) { + case PM_EVENT_SUSPEND: + csn->saved = readl(csn->reg); + return NOTIFY_OK; + + case PM_EVENT_RESUME: + writel(csn->saved, csn->reg); + return NOTIFY_OK; + } + return NOTIFY_DONE; +} + +static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn) +{ + csn->nb.notifier_call = cpg_simple_notifier_call; + raw_notifier_chain_register(notifiers, &csn->nb); +} /* * SDn Clock @@ -55,8 +86,8 @@ struct sd_div_table { struct sd_clock { struct clk_hw hw; - void __iomem *reg; const struct sd_div_table *div_table; + struct cpg_simple_notifier csn; unsigned int div_num; unsigned int div_min; unsigned int div_max; @@ -97,12 +128,12 @@ static const struct sd_div_table cpg_sd_div_table[] = { static int cpg_sd_clock_enable(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - u32 val = readl(clock->reg); + u32 val = readl(clock->csn.reg); val &= ~(CPG_SD_STP_MASK); val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK; - writel(val, clock->reg); + writel(val, clock->csn.reg); return 0; } @@ -111,14 +142,14 @@ static void cpg_sd_clock_disable(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); + writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg); } static int cpg_sd_clock_is_enabled(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - return !(readl(clock->reg) & CPG_SD_STP_MASK); + return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); } static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, @@ -170,10 +201,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, clock->cur_div_idx = i; - val = readl(clock->reg); + val = readl(clock->csn.reg); val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); - writel(val, clock->reg); + writel(val, clock->csn.reg); return 0; } @@ -188,8 +219,8 @@ static const struct clk_ops cpg_sd_clock_ops = { }; static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, - void __iomem *base, - const char *parent_name) + void __iomem *base, const char *parent_name, + struct raw_notifier_head *notifiers) { struct clk_init_data init; struct sd_clock *clock; @@ -207,12 +238,12 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, init.parent_names = &parent_name; init.num_parents = 1; - clock->reg = base + core->offset; + clock->csn.reg = base + core->offset; clock->hw.init = &init; clock->div_table = cpg_sd_div_table; clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - sd_fc = readl(clock->reg) & CPG_SD_FC_MASK; + sd_fc = readl(clock->csn.reg) & CPG_SD_FC_MASK; for (i = 0; i < clock->div_num; i++) if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) break; @@ -233,8 +264,13 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, clk = clk_register(NULL, &clock->hw); if (IS_ERR(clk)) - kfree(clock); + goto free_clock; + + cpg_simple_notifier_register(notifiers, &clock->csn); + return clk; +free_clock: + kfree(clock); return clk; } @@ -332,7 +368,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, break; case CLK_TYPE_GEN3_SD: - return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + return cpg_sd_clk_register(core, base, __clk_get_name(parent), + notifiers); case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { -- cgit v1.2.3 From 3f7a4d084159c52513d1ff77f3b3b880bcf517d9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 28 Jun 2017 21:15:49 +0200 Subject: clk: renesas: rcar-gen3: Restore R clock during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register a notifier to save/restore the RCKCR register during system suspend/resume. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen3-cpg.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 267b5629e3bd..0904886f5501 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -373,18 +373,27 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { + struct cpg_simple_notifier *csn; + + csn = kzalloc(sizeof(*csn), GFP_KERNEL); + if (!csn) + return ERR_PTR(-ENOMEM); + + csn->reg = base + CPG_RCKCR; + /* * RINT is default. * Only if EXTALR is populated, we switch to it. */ - value = readl(base + CPG_RCKCR) & 0x3f; + value = readl(csn->reg) & 0x3f; if (clk_get_rate(clks[cpg_clk_extalr])) { parent = clks[cpg_clk_extalr]; value |= BIT(15); } - writel(value, base + CPG_RCKCR); + writel(value, csn->reg); + cpg_simple_notifier_register(notifiers, csn); break; } -- cgit v1.2.3 From 109eba2eb61ab92fc1f92e02d69ee0aa16e10c6a Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 23 Oct 2017 12:12:52 +0100 Subject: clk: tegra: Mark APB clock as critical Currently, the APB clock is registered with the CLK_IGNORE_UNUSED flag to prevent the clock from being disabled if unused on boot. However, even if it is used, it still needs to be always kept enabled so that it doesn't get inadvertently disabled when all of its children are, and so update the flag for the APB clock to be CLK_IS_CRITICAL. Suggested-by: Peter De Schrijver Signed-off-by: Jon Hunter Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-super-gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 4f6fd307cb70..10047107c1dc 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -166,7 +166,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base, clk_base + SYSTEM_CLK_RATE, 0, 2, 0, &sysrate_lock); clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | - CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, + CLK_IS_CRITICAL, clk_base + SYSTEM_CLK_RATE, 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); *dt_clk = clk; } -- cgit v1.2.3 From 899f8095e66c562888ff617686e46019b758611b Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:38 +0300 Subject: clk: tegra: Add AHB DMA clock entry AHB DMA engine presents on Tegra20/30. Add missing clock entries, so that driver for the AHB DMA controller could be implemented. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-id.h | 1 + drivers/clk/tegra/clk-tegra-periph.c | 1 + drivers/clk/tegra/clk-tegra20.c | 1 + drivers/clk/tegra/clk-tegra30.c | 1 + 4 files changed, 4 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 689f344377a7..c1661b47bbda 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -12,6 +12,7 @@ enum clk_id { tegra_clk_amx, tegra_clk_amx1, tegra_clk_apb2ape, + tegra_clk_ahbdma, tegra_clk_apbdma, tegra_clk_apbif, tegra_clk_ape, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index c7694205573f..f5232d6d203d 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -807,6 +807,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("timer", "clk_m", 5, 0, tegra_clk_timer, CLK_IS_CRITICAL), GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), + GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0), GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 2b839cb24436..02b7ab292e97 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -522,6 +522,7 @@ static struct tegra_devclk devclks[] __initdata = { }; static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { + [tegra_clk_ahbdma] = { .dt_id = TEGRA20_CLK_AHBDMA, .present = true }, [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true }, [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true }, [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true }, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 455502a42b20..40ffab0f94e1 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -788,6 +788,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_extern3] = { .dt_id = TEGRA30_CLK_EXTERN3, .present = true }, [tegra_clk_disp1] = { .dt_id = TEGRA30_CLK_DISP1, .present = true }, [tegra_clk_disp2] = { .dt_id = TEGRA30_CLK_DISP2, .present = true }, + [tegra_clk_ahbdma] = { .dt_id = TEGRA30_CLK_AHBDMA, .present = true }, [tegra_clk_apbdma] = { .dt_id = TEGRA30_CLK_APBDMA, .present = true }, [tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true }, [tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true }, -- cgit v1.2.3 From 3ff46fd0b22abbb8d921d7e5657912bfbd41b6f0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:39 +0300 Subject: clk: tegra: Correct parent of the APBDMA clock APBDMA represents a clock gate to the APB DMA controller, the actual clock source for the controller is PCLK. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index f5232d6d203d..c02711927d79 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -808,7 +808,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0), - GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), + GATE("apbdma", "pclk", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), -- cgit v1.2.3 From 5a6b184a36b8f5ff01ce93c9251996e4f96310d7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:40 +0300 Subject: clk: tegra: Use common definition of APBDMA clock gate The APBDMA clock is defined in the common clock gates table that is used by Tegra30+. Tegra20 can use it too, let's remove the custom definition and use the common one. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 02b7ab292e97..57a1387ea992 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -523,6 +523,7 @@ static struct tegra_devclk devclks[] __initdata = { static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { [tegra_clk_ahbdma] = { .dt_id = TEGRA20_CLK_AHBDMA, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA20_CLK_APBDMA, .present = true }, [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true }, [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true }, [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true }, @@ -807,11 +808,6 @@ static void __init tegra20_periph_clk_init(void) clk_base, 0, 3, periph_clk_enb_refcnt); clks[TEGRA20_CLK_AC97] = clk; - /* apbdma */ - clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, - 0, 34, periph_clk_enb_refcnt); - clks[TEGRA20_CLK_APBDMA] = clk; - /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, ARRAY_SIZE(mux_pllmcp_clkm), -- cgit v1.2.3 From d80a32fe98b7ce428669b774c3d10ecae3bc6e6d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:41 +0300 Subject: clk: tegra: Bump SCLK clock rate to 216 MHz AHB DMA is a running on 1/2 of SCLK rate, APB DMA on 1/4. Increasing SCLK rate results in an increased DMA transfer rate. Signed-off-by: Dmitry Osipenko Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 57a1387ea992..cbd5a2e5c569 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1020,7 +1020,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 1 }, { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 }, { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 }, -- cgit v1.2.3 From 54eff2264d3e9fd7e3987de1d7eba1d3581c631e Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Tue, 19 Sep 2017 04:48:10 +0200 Subject: clk: tegra: Fix cclk_lp divisor register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to comments in code and common sense, cclk_lp uses its own divisor, not cclk_g's. Fixes: b08e8c0ecc42 ("clk: tegra: add clock support for Tegra30") Signed-off-by: Michał Mirosław Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 40ffab0f94e1..bee84c554932 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -965,7 +965,7 @@ static void __init tegra30_super_clk_init(void) * U71 divider of cclk_lp. */ clk = tegra_clk_register_divider("pll_p_out3_cclklp", "pll_p_out3", - clk_base + SUPER_CCLKG_DIVIDER, 0, + clk_base + SUPER_CCLKLP_DIVIDER, 0, TEGRA_DIVIDER_INT, 16, 8, 1, NULL); clk_register_clkdev(clk, "pll_p_out3_cclklp", NULL); -- cgit v1.2.3 From 1752c9ee23fb20e5bfdbedf677e91f927f2b8d80 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 12 Oct 2017 16:09:59 -0700 Subject: clk: tegra: dfll: Fix drvdata overwriting issue Both tegra124-dfll and clk-dfll are using platform_set_drvdata to set drvdata of the exact same pdev while they use different pointers for the drvdata. Once the drvdata has been overwritten by tegra124-dfll, clk-dfll will never get its td pointer as it expects. Since tegra124-dfll merely needs its soc pointer in its remove function, this patch fixes the bug by removing the overwriting in the tegra124-dfll file and letting the tegra_dfll_unregister return an soc pointer for it. Signed-off-by: Nicolin Chen Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-dfll.c | 10 +++++----- drivers/clk/tegra/clk-dfll.h | 2 +- drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 12 +++++------- 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 2c44aeb0b97c..0a7deee74eea 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -1728,10 +1728,10 @@ EXPORT_SYMBOL(tegra_dfll_register); * @pdev: DFLL platform_device * * * Unbind this driver from the DFLL hardware device represented by - * @pdev. The DFLL must be disabled for this to succeed. Returns 0 - * upon success or -EBUSY if the DFLL is still active. + * @pdev. The DFLL must be disabled for this to succeed. Returns a + * soc pointer upon success or -EBUSY if the DFLL is still active. */ -int tegra_dfll_unregister(struct platform_device *pdev) +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev) { struct tegra_dfll *td = platform_get_drvdata(pdev); @@ -1739,7 +1739,7 @@ int tegra_dfll_unregister(struct platform_device *pdev) if (td->mode != DFLL_DISABLED) { dev_err(&pdev->dev, "must disable DFLL before removing driver\n"); - return -EBUSY; + return ERR_PTR(-EBUSY); } debugfs_remove_recursive(td->debugfs_dir); @@ -1753,6 +1753,6 @@ int tegra_dfll_unregister(struct platform_device *pdev) reset_control_assert(td->dvco_rst); - return 0; + return td->soc; } EXPORT_SYMBOL(tegra_dfll_unregister); diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index ed2ad888268f..83352c8078f2 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h @@ -43,7 +43,7 @@ struct tegra_dfll_soc_data { int tegra_dfll_register(struct platform_device *pdev, struct tegra_dfll_soc_data *soc); -int tegra_dfll_unregister(struct platform_device *pdev); +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev); int tegra_dfll_runtime_suspend(struct device *dev); int tegra_dfll_runtime_resume(struct device *dev); diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index ad1c1cc829cb..269d3595758b 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -125,19 +125,17 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) return err; } - platform_set_drvdata(pdev, soc); - return 0; } static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) { - struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev); - int err; + struct tegra_dfll_soc_data *soc; - err = tegra_dfll_unregister(pdev); - if (err < 0) - dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err); + soc = tegra_dfll_unregister(pdev); + if (IS_ERR(soc)) + dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n", + PTR_ERR(soc)); tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); -- cgit v1.2.3 From 22ef01a203d27fee8b7694020b7e722db7efd2a7 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Fri, 15 Sep 2017 12:10:13 -0700 Subject: clk: tegra: Use readl_relaxed_poll_timeout_atomic() in tegra210_clock_init() Below is the call trace of tegra210_init_pllu() function: start_kernel() -> time_init() --> of_clk_init() ---> tegra210_clock_init() ----> tegra210_pll_init() -----> tegra210_init_pllu() Because the preemption is disabled in the start_kernel before calling time_init, tegra210_init_pllu is actually in an atomic context while it includes a readl_relaxed_poll_timeout that might sleep. So this patch just changes this readl_relaxed_poll_timeout() to its atomic version. Signed-off-by: Nicolin Chen Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index be7b736371f6..9e6260869eb9 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2568,8 +2568,8 @@ static int tegra210_enable_pllu(void) reg |= PLL_ENABLE; writel(reg, clk_base + PLLU_BASE); - readl_relaxed_poll_timeout(clk_base + PLLU_BASE, reg, - reg & PLL_BASE_LOCK, 2, 1000); + readl_relaxed_poll_timeout_atomic(clk_base + PLLU_BASE, reg, + reg & PLL_BASE_LOCK, 2, 1000); if (!(reg & PLL_BASE_LOCK)) { pr_err("Timed out waiting for PLL_U to lock\n"); return -ETIMEDOUT; -- cgit v1.2.3 From d2a3671ebe6479483a12f94fcca63c058d95ad64 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Fri, 1 Sep 2017 08:47:14 +0800 Subject: clk: hi6220: mark clock cs_atb_syspll as critical Clock cs_atb_syspll is pll used for coresight trace bus; when clock cs_atb_syspll is disabled and operates its child clock node cs_atb results in system hang. So mark clock cs_atb_syspll as critical to keep it enabled. Cc: Guodong Xu Cc: Zhangfei Gao Cc: Haojian Zhuang Signed-off-by: Leo Yan Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1504226835-2115-2-git-send-email-leo.yan@linaro.org --- drivers/clk/hisilicon/clk-hi6220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index e786d717f75d..a87809d4bd52 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -145,7 +145,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = { { HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, }, { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, }, { HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, }, - { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, }, + { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x270, 12, 0, }, }; static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = { -- cgit v1.2.3 From 02e0114ae1eb776b22f0744762fb0137208c4850 Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Tue, 24 Oct 2017 19:06:16 +0200 Subject: clk: sunxi: fix build warning This patch fix the following build warning: drivers/clk/sunxi/clk-factors.c:279:14: warning: variable 'name' set but not used [-Wunused-but-set-variable] Fixes: 4cbeaebb8af1 ("clk: sunxi: factors: Add unregister function") Acked-by: Maxime Ripard Signed-off-by: Corentin Labbe Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-factors.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index dfe5e3e32d28..856fef65433b 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -276,13 +276,11 @@ void sunxi_factors_unregister(struct device_node *node, struct clk *clk) { struct clk_hw *hw = __clk_get_hw(clk); struct clk_factors *factors; - const char *name; if (!hw) return; factors = to_clk_factors(hw); - name = clk_hw_get_name(hw); of_clk_del_provider(node); /* TODO: The composite clock stuff will leak a bit here. */ -- cgit v1.2.3 From cb92a19b9977706ac69e26c67dcccb69ae6deeb0 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:13 +0200 Subject: clk: sunxi: explicitly request exclusive reset control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: "Emilio López" Cc: Michael Turquette Cc: Stephen Boyd Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: linux-clk@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-sun9i-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index 6041bdba2e97..a1a634253d6f 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -124,7 +124,7 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) return PTR_ERR(data->clk); } - data->reset = devm_reset_control_get(&pdev->dev, NULL); + data->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(data->reset)) { dev_err(&pdev->dev, "Could not get reset control\n"); return PTR_ERR(data->reset); -- cgit v1.2.3 From 71bf5ab8638fe333ac8a984b46fc3f4ea0c5120a Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 17 Oct 2017 16:38:33 +0200 Subject: CLK: SPEAr: make structure field and function argument as const Make the masks field of clk_aux structure const as it do not modify the fields of the aux_clk_masks structure it points to. Make the struct aux_clk_masks *aux argument of the function clk_register_aux as const as the argument is only stored in the masks field of a clk_aux structure which is now made const. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/clk.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index f271c350ef94..8bea5dfc770b 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -136,7 +136,7 @@ static struct clk_ops clk_aux_ops = { struct clk *clk_register_aux(const char *aux_name, const char *gate_name, const char *parent_name, unsigned long flags, void __iomem *reg, - struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, + const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk) { struct clk_aux *aux; diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h index 9834944f08b1..af0e25f496c1 100644 --- a/drivers/clk/spear/clk.h +++ b/drivers/clk/spear/clk.h @@ -49,7 +49,7 @@ struct aux_rate_tbl { struct clk_aux { struct clk_hw hw; void __iomem *reg; - struct aux_clk_masks *masks; + const struct aux_clk_masks *masks; struct aux_rate_tbl *rtbl; u8 rtbl_cnt; spinlock_t *lock; @@ -112,7 +112,7 @@ typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate, /* clk register routines */ struct clk *clk_register_aux(const char *aux_name, const char *gate_name, const char *parent_name, unsigned long flags, void __iomem *reg, - struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, + const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk); struct clk *clk_register_frac(const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, -- cgit v1.2.3 From 37d2f45d940bfdd7c9a5323f3d3462bea3a3e957 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 17 Oct 2017 16:38:34 +0200 Subject: CLK: SPEAr: make aux_clk_masks structures const Make these const as they are either stored in the masks 'const' field of a clk_aux structure or passed to the function clk_register_aux having the argument as const. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/spear1310_clock.c | 2 +- drivers/clk/spear/spear1340_clock.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index 8bea5dfc770b..2f145e398a10 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -29,7 +29,7 @@ #define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw) -static struct aux_clk_masks default_aux_masks = { +static const struct aux_clk_masks default_aux_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = AUX_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c index 2f86e3f94efa..591248c9a88e 100644 --- a/drivers/clk/spear/spear1310_clock.c +++ b/drivers/clk/spear/spear1310_clock.c @@ -284,7 +284,7 @@ static struct frac_rate_tbl clcd_rtbl[] = { }; /* i2s prescaler1 masks */ -static struct aux_clk_masks i2s_prs1_masks = { +static const struct aux_clk_masks i2s_prs1_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = SPEAR1310_I2S_PRS1_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index cbb19a90f2d6..e5bc8c828cf0 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -323,7 +323,7 @@ static struct frac_rate_tbl clcd_rtbl[] = { }; /* i2s prescaler1 masks */ -static struct aux_clk_masks i2s_prs1_masks = { +static const struct aux_clk_masks i2s_prs1_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = SPEAR1340_I2S_PRS1_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, -- cgit v1.2.3 From ba3892df525b9ff203d0ad116a41306bf5081215 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 18:44:50 +0530 Subject: clk: spear: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/clk-frac-synth.c | 2 +- drivers/clk/spear/clk-gpt-synth.c | 2 +- drivers/clk/spear/clk-vco-pll.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index 2f145e398a10..23a6b10e1d6a 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -128,7 +128,7 @@ static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_aux_ops = { +static const struct clk_ops clk_aux_ops = { .recalc_rate = clk_aux_recalc_rate, .round_rate = clk_aux_round_rate, .set_rate = clk_aux_set_rate, diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c index 58d678b5b40a..eaf970bda5d9 100644 --- a/drivers/clk/spear/clk-frac-synth.c +++ b/drivers/clk/spear/clk-frac-synth.c @@ -116,7 +116,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_frac_ops = { +static const struct clk_ops clk_frac_ops = { .recalc_rate = clk_frac_recalc_rate, .round_rate = clk_frac_round_rate, .set_rate = clk_frac_set_rate, diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c index 1a722e99e76e..3641799d4f6f 100644 --- a/drivers/clk/spear/clk-gpt-synth.c +++ b/drivers/clk/spear/clk-gpt-synth.c @@ -105,7 +105,7 @@ static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_gpt_ops = { +static const struct clk_ops clk_gpt_ops = { .recalc_rate = clk_gpt_recalc_rate, .round_rate = clk_gpt_round_rate, .set_rate = clk_gpt_set_rate, diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index dc21ca4601aa..069b48a44f80 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -165,7 +165,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_pll_ops = { +static const struct clk_ops clk_pll_ops = { .recalc_rate = clk_pll_recalc_rate, .round_rate = clk_pll_round_rate, .set_rate = clk_pll_set_rate, @@ -266,7 +266,7 @@ static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_vco_ops = { +static const struct clk_ops clk_vco_ops = { .recalc_rate = clk_vco_recalc_rate, .round_rate = clk_vco_round_rate, .set_rate = clk_vco_set_rate, -- cgit v1.2.3 From 8f435057e9c5eca9da7c02ab398971280ba80056 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:32:21 +0530 Subject: clk: sirf: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/sirf/clk-common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c index 77e1e2491689..f9ef6fa84f0b 100644 --- a/drivers/clk/sirf/clk-common.c +++ b/drivers/clk/sirf/clk-common.c @@ -184,7 +184,7 @@ static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw, return clk_hw_get_rate(parent_clk); } -static struct clk_ops std_pll_ops = { +static const struct clk_ops std_pll_ops = { .recalc_rate = pll_clk_recalc_rate, .round_rate = pll_clk_round_rate, .set_rate = pll_clk_set_rate, @@ -265,7 +265,7 @@ static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long pa return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; } -static struct clk_ops usb_pll_ops = { +static const struct clk_ops usb_pll_ops = { .enable = usb_pll_clk_enable, .disable = usb_pll_clk_disable, .recalc_rate = usb_pll_clk_recalc_rate, @@ -437,7 +437,7 @@ static int cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate, return ret2 ? ret2 : ret1; } -static struct clk_ops msi_ops = { +static const struct clk_ops msi_ops = { .set_rate = dmn_clk_set_rate, .round_rate = dmn_clk_round_rate, .recalc_rate = dmn_clk_recalc_rate, @@ -488,7 +488,7 @@ static struct clk_dmn clk_io = { }, }; -static struct clk_ops cpu_ops = { +static const struct clk_ops cpu_ops = { .set_parent = dmn_clk_set_parent, .get_parent = dmn_clk_get_parent, .set_rate = cpu_clk_set_rate, @@ -511,7 +511,7 @@ static struct clk_dmn clk_cpu = { }, }; -static struct clk_ops dmn_ops = { +static const struct clk_ops dmn_ops = { .is_enabled = std_clk_is_enabled, .enable = std_clk_enable, .disable = std_clk_disable, @@ -679,7 +679,7 @@ static const char * const std_clk_io_parents[] = { "io", }; -static struct clk_ops ios_ops = { +static const struct clk_ops ios_ops = { .is_enabled = std_clk_is_enabled, .enable = std_clk_enable, .disable = std_clk_disable, -- cgit v1.2.3 From ed3f2d12213b3d13ca0b941199c250c66a318b72 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:22:47 +0530 Subject: clk: mxs: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/mxs/clk-div.c | 2 +- drivers/clk/mxs/clk-frac.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c index f75e989c578f..ccebd014fc1e 100644 --- a/drivers/clk/mxs/clk-div.c +++ b/drivers/clk/mxs/clk-div.c @@ -67,7 +67,7 @@ static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static struct clk_ops clk_div_ops = { +static const struct clk_ops clk_div_ops = { .recalc_rate = clk_div_recalc_rate, .round_rate = clk_div_round_rate, .set_rate = clk_div_set_rate, diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c index f8dd10f6df3d..27b3372adc37 100644 --- a/drivers/clk/mxs/clk-frac.c +++ b/drivers/clk/mxs/clk-frac.c @@ -107,7 +107,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, return mxs_clk_wait(frac->reg, frac->busy); } -static struct clk_ops clk_frac_ops = { +static const struct clk_ops clk_frac_ops = { .recalc_rate = clk_frac_recalc_rate, .round_rate = clk_frac_round_rate, .set_rate = clk_frac_set_rate, -- cgit v1.2.3 From 9108620d2d52d7a58bbf6192e56903355eace907 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:12:07 +0530 Subject: clk: hisilicon: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/hisilicon/clk-hix5hd2.c | 4 ++-- drivers/clk/hisilicon/clkgate-separated.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index fa0fba653898..77072c7778b9 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -415,7 +415,7 @@ static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate, return mmc_clk_set_timing(hw, rate); } -static struct clk_ops clk_mmc_ops = { +static const struct clk_ops clk_mmc_ops = { .prepare = mmc_clk_prepare, .determine_rate = mmc_clk_determine_rate, .set_rate = mmc_clk_set_rate, diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c index 14b05efa3c2a..9584f0c32dda 100644 --- a/drivers/clk/hisilicon/clk-hix5hd2.c +++ b/drivers/clk/hisilicon/clk-hix5hd2.c @@ -208,7 +208,7 @@ static void clk_ether_unprepare(struct clk_hw *hw) writel_relaxed(val, clk->ctrl_reg); } -static struct clk_ops clk_ether_ops = { +static const struct clk_ops clk_ether_ops = { .prepare = clk_ether_prepare, .unprepare = clk_ether_unprepare, }; @@ -247,7 +247,7 @@ static void clk_complex_disable(struct clk_hw *hw) writel_relaxed(val, clk->phy_reg); } -static struct clk_ops clk_complex_ops = { +static const struct clk_ops clk_complex_ops = { .enable = clk_complex_enable, .disable = clk_complex_disable, }; diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c index 7908bc3c9ec7..1172b0982b77 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -88,7 +88,7 @@ static int clkgate_separated_is_enabled(struct clk_hw *hw) return reg ? 1 : 0; } -static struct clk_ops clkgate_separated_ops = { +static const struct clk_ops clkgate_separated_ops = { .enable = clkgate_separated_enable, .disable = clkgate_separated_disable, .is_enabled = clkgate_separated_is_enabled, -- cgit v1.2.3 From e90a7da4f75435ba0e5fcb12ed65fa6d4bd7a364 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:05:55 +0530 Subject: clk: mmp: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-apbc.c | 2 +- drivers/clk/mmp/clk-apmu.c | 2 +- drivers/clk/mmp/clk-frac.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c index 4c717db05f2d..fb294ada0b03 100644 --- a/drivers/clk/mmp/clk-apbc.c +++ b/drivers/clk/mmp/clk-apbc.c @@ -114,7 +114,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw) spin_unlock_irqrestore(apbc->lock, flags); } -static struct clk_ops clk_apbc_ops = { +static const struct clk_ops clk_apbc_ops = { .prepare = clk_apbc_prepare, .unprepare = clk_apbc_unprepare, }; diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c index 47b5542ce50f..b7ce8f52026e 100644 --- a/drivers/clk/mmp/clk-apmu.c +++ b/drivers/clk/mmp/clk-apmu.c @@ -60,7 +60,7 @@ static void clk_apmu_disable(struct clk_hw *hw) spin_unlock_irqrestore(apmu->lock, flags); } -static struct clk_ops clk_apmu_ops = { +static const struct clk_ops clk_apmu_ops = { .enable = clk_apmu_enable, .disable = clk_apmu_disable, }; diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 584a9927993b..ea47a968ad9b 100644 --- a/drivers/clk/mmp/clk-frac.c +++ b/drivers/clk/mmp/clk-frac.c @@ -149,7 +149,7 @@ static void clk_factor_init(struct clk_hw *hw) spin_unlock_irqrestore(factor->lock, flags); } -static struct clk_ops clk_factor_ops = { +static const struct clk_ops clk_factor_ops = { .recalc_rate = clk_factor_recalc_rate, .round_rate = clk_factor_round_rate, .set_rate = clk_factor_set_rate, -- cgit v1.2.3 From fa1da981f5ee603610bd8f8920c4ec393e95ceeb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 18:48:29 +0530 Subject: clk: imx: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-busy.c | 4 ++-- drivers/clk/imx/clk-gate2.c | 2 +- drivers/clk/imx/clk-pllv1.c | 2 +- drivers/clk/imx/clk-pllv2.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index 5cc99590f9a3..6df3389687bc 100644 --- a/drivers/clk/imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c @@ -72,7 +72,7 @@ static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static struct clk_ops clk_busy_divider_ops = { +static const struct clk_ops clk_busy_divider_ops = { .recalc_rate = clk_busy_divider_recalc_rate, .round_rate = clk_busy_divider_round_rate, .set_rate = clk_busy_divider_set_rate, @@ -147,7 +147,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index) return ret; } -static struct clk_ops clk_busy_mux_ops = { +static const struct clk_ops clk_busy_mux_ops = { .get_parent = clk_busy_mux_get_parent, .set_parent = clk_busy_mux_set_parent, }; diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index db44a198a0d9..60fc9d7a9723 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -118,7 +118,7 @@ static void clk_gate2_disable_unused(struct clk_hw *hw) spin_unlock_irqrestore(gate->lock, flags); } -static struct clk_ops clk_gate2_ops = { +static const struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable, .disable_unused = clk_gate2_disable_unused, diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c index 82fe3662b5f6..703818e9001a 100644 --- a/drivers/clk/imx/clk-pllv1.c +++ b/drivers/clk/imx/clk-pllv1.c @@ -106,7 +106,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, return ull; } -static struct clk_ops clk_pllv1_ops = { +static const struct clk_ops clk_pllv1_ops = { .recalc_rate = clk_pllv1_recalc_rate, }; diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c index 4aeda56ce372..c845b8c773a6 100644 --- a/drivers/clk/imx/clk-pllv2.c +++ b/drivers/clk/imx/clk-pllv2.c @@ -226,7 +226,7 @@ static void clk_pllv2_unprepare(struct clk_hw *hw) __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); } -static struct clk_ops clk_pllv2_ops = { +static const struct clk_ops clk_pllv2_ops = { .prepare = clk_pllv2_prepare, .unprepare = clk_pllv2_unprepare, .recalc_rate = clk_pllv2_recalc_rate, -- cgit v1.2.3 From 0777066dcee8a4f16db09fd21dfd58b6d83b12f9 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 18 Aug 2017 15:38:17 +0530 Subject: clk: make clk_init_data const Make these const as they are only stored in the init field of a clk_hw structure, which is const. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/clk-twl6040.c | 2 +- drivers/clk/clk-wm831x.c | 6 ++-- drivers/clk/sirf/clk-atlas6.c | 2 +- drivers/clk/sirf/clk-atlas7.c | 18 +++++----- drivers/clk/sirf/clk-common.c | 80 +++++++++++++++++++++---------------------- drivers/clk/sirf/clk-prima2.c | 2 +- 6 files changed, 55 insertions(+), 55 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c index 7b222a5db931..25dfe050ae9f 100644 --- a/drivers/clk/clk-twl6040.c +++ b/drivers/clk/clk-twl6040.c @@ -82,7 +82,7 @@ static const struct clk_ops twl6040_pdmclk_ops = { .recalc_rate = twl6040_pdmclk_recalc_rate, }; -static struct clk_init_data twl6040_pdmclk_init = { +static const struct clk_init_data twl6040_pdmclk_init = { .name = "pdmclk", .ops = &twl6040_pdmclk_ops, .flags = CLK_GET_RATE_NOCACHE, diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index a47960aacfa5..146769532325 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -52,7 +52,7 @@ static const struct clk_ops wm831x_xtal_ops = { .recalc_rate = wm831x_xtal_recalc_rate, }; -static struct clk_init_data wm831x_xtal_init = { +static const struct clk_init_data wm831x_xtal_init = { .name = "xtal", .ops = &wm831x_xtal_ops, }; @@ -225,7 +225,7 @@ static const struct clk_ops wm831x_fll_ops = { .get_parent = wm831x_fll_get_parent, }; -static struct clk_init_data wm831x_fll_init = { +static const struct clk_init_data wm831x_fll_init = { .name = "fll", .ops = &wm831x_fll_ops, .parent_names = wm831x_fll_parents, @@ -338,7 +338,7 @@ static const struct clk_ops wm831x_clkout_ops = { .set_parent = wm831x_clkout_set_parent, }; -static struct clk_init_data wm831x_clkout_init = { +static const struct clk_init_data wm831x_clkout_init = { .name = "clkout", .ops = &wm831x_clkout_ops, .parent_names = wm831x_clkout_parents, diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index 665fa681b2e1..0cd11e6893af 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c @@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = { }, }; -static struct clk_init_data clk_nand_init = { +static const struct clk_init_data clk_nand_init = { .name = "nand", .ops = &dmn_ops, .parent_names = dmn_clk_parents, diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c index d0c6c9a2d06a..be012b4bab46 100644 --- a/drivers/clk/sirf/clk-atlas7.c +++ b/drivers/clk/sirf/clk-atlas7.c @@ -392,7 +392,7 @@ static const char * const pll_clk_parents[] = { "xin", }; -static struct clk_init_data clk_cpupll_init = { +static const struct clk_init_data clk_cpupll_init = { .name = "cpupll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -406,7 +406,7 @@ static struct clk_pll clk_cpupll = { }, }; -static struct clk_init_data clk_mempll_init = { +static const struct clk_init_data clk_mempll_init = { .name = "mempll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -420,7 +420,7 @@ static struct clk_pll clk_mempll = { }, }; -static struct clk_init_data clk_sys0pll_init = { +static const struct clk_init_data clk_sys0pll_init = { .name = "sys0pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -434,7 +434,7 @@ static struct clk_pll clk_sys0pll = { }, }; -static struct clk_init_data clk_sys1pll_init = { +static const struct clk_init_data clk_sys1pll_init = { .name = "sys1pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -448,7 +448,7 @@ static struct clk_pll clk_sys1pll = { }, }; -static struct clk_init_data clk_sys2pll_init = { +static const struct clk_init_data clk_sys2pll_init = { .name = "sys2pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -462,7 +462,7 @@ static struct clk_pll clk_sys2pll = { }, }; -static struct clk_init_data clk_sys3pll_init = { +static const struct clk_init_data clk_sys3pll_init = { .name = "sys3pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -596,7 +596,7 @@ static const char * const audiodto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_audiodto_init = { +static const struct clk_init_data clk_audiodto_init = { .name = "audio_dto", .ops = &dto_ops, .parent_names = audiodto_clk_parents, @@ -617,7 +617,7 @@ static const char * const disp0dto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_disp0dto_init = { +static const struct clk_init_data clk_disp0dto_init = { .name = "disp0_dto", .ops = &dto_ops, .parent_names = disp0dto_clk_parents, @@ -638,7 +638,7 @@ static const char * const disp1dto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_disp1dto_init = { +static const struct clk_init_data clk_disp1dto_init = { .name = "disp1_dto", .ops = &dto_ops, .parent_names = disp1dto_clk_parents, diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c index f9ef6fa84f0b..d8f9efa5129a 100644 --- a/drivers/clk/sirf/clk-common.c +++ b/drivers/clk/sirf/clk-common.c @@ -194,21 +194,21 @@ static const char * const pll_clk_parents[] = { "osc", }; -static struct clk_init_data clk_pll1_init = { +static const struct clk_init_data clk_pll1_init = { .name = "pll1", .ops = &std_pll_ops, .parent_names = pll_clk_parents, .num_parents = ARRAY_SIZE(pll_clk_parents), }; -static struct clk_init_data clk_pll2_init = { +static const struct clk_init_data clk_pll2_init = { .name = "pll2", .ops = &std_pll_ops, .parent_names = pll_clk_parents, .num_parents = ARRAY_SIZE(pll_clk_parents), }; -static struct clk_init_data clk_pll3_init = { +static const struct clk_init_data clk_pll3_init = { .name = "pll3", .ops = &std_pll_ops, .parent_names = pll_clk_parents, @@ -271,7 +271,7 @@ static const struct clk_ops usb_pll_ops = { .recalc_rate = usb_pll_clk_recalc_rate, }; -static struct clk_init_data clk_usb_pll_init = { +static const struct clk_init_data clk_usb_pll_init = { .name = "usb_pll", .ops = &usb_pll_ops, .parent_names = pll_clk_parents, @@ -445,7 +445,7 @@ static const struct clk_ops msi_ops = { .get_parent = dmn_clk_get_parent, }; -static struct clk_init_data clk_mem_init = { +static const struct clk_init_data clk_mem_init = { .name = "mem", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -459,7 +459,7 @@ static struct clk_dmn clk_mem = { }, }; -static struct clk_init_data clk_sys_init = { +static const struct clk_init_data clk_sys_init = { .name = "sys", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -474,7 +474,7 @@ static struct clk_dmn clk_sys = { }, }; -static struct clk_init_data clk_io_init = { +static const struct clk_init_data clk_io_init = { .name = "io", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -496,7 +496,7 @@ static const struct clk_ops cpu_ops = { .recalc_rate = cpu_clk_recalc_rate, }; -static struct clk_init_data clk_cpu_init = { +static const struct clk_init_data clk_cpu_init = { .name = "cpu", .ops = &cpu_ops, .parent_names = dmn_clk_parents, @@ -524,7 +524,7 @@ static const struct clk_ops dmn_ops = { /* dsp, gfx, mm, lcd and vpp domain */ -static struct clk_init_data clk_dsp_init = { +static const struct clk_init_data clk_dsp_init = { .name = "dsp", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -539,7 +539,7 @@ static struct clk_dmn clk_dsp = { }, }; -static struct clk_init_data clk_gfx_init = { +static const struct clk_init_data clk_gfx_init = { .name = "gfx", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -554,7 +554,7 @@ static struct clk_dmn clk_gfx = { }, }; -static struct clk_init_data clk_mm_init = { +static const struct clk_init_data clk_mm_init = { .name = "mm", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -574,7 +574,7 @@ static struct clk_dmn clk_mm = { */ #define clk_gfx2d clk_mm -static struct clk_init_data clk_lcd_init = { +static const struct clk_init_data clk_lcd_init = { .name = "lcd", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -589,7 +589,7 @@ static struct clk_dmn clk_lcd = { }, }; -static struct clk_init_data clk_vpp_init = { +static const struct clk_init_data clk_vpp_init = { .name = "vpp", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -604,21 +604,21 @@ static struct clk_dmn clk_vpp = { }, }; -static struct clk_init_data clk_mmc01_init = { +static const struct clk_init_data clk_mmc01_init = { .name = "mmc01", .ops = &dmn_ops, .parent_names = dmn_clk_parents, .num_parents = ARRAY_SIZE(dmn_clk_parents), }; -static struct clk_init_data clk_mmc23_init = { +static const struct clk_init_data clk_mmc23_init = { .name = "mmc23", .ops = &dmn_ops, .parent_names = dmn_clk_parents, .num_parents = ARRAY_SIZE(dmn_clk_parents), }; -static struct clk_init_data clk_mmc45_init = { +static const struct clk_init_data clk_mmc45_init = { .name = "mmc45", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -685,7 +685,7 @@ static const struct clk_ops ios_ops = { .disable = std_clk_disable, }; -static struct clk_init_data clk_cphif_init = { +static const struct clk_init_data clk_cphif_init = { .name = "cphif", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -699,7 +699,7 @@ static struct clk_std clk_cphif = { }, }; -static struct clk_init_data clk_dmac0_init = { +static const struct clk_init_data clk_dmac0_init = { .name = "dmac0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -713,7 +713,7 @@ static struct clk_std clk_dmac0 = { }, }; -static struct clk_init_data clk_dmac1_init = { +static const struct clk_init_data clk_dmac1_init = { .name = "dmac1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -727,7 +727,7 @@ static struct clk_std clk_dmac1 = { }, }; -static struct clk_init_data clk_audio_init = { +static const struct clk_init_data clk_audio_init = { .name = "audio", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -741,7 +741,7 @@ static struct clk_std clk_audio = { }, }; -static struct clk_init_data clk_uart0_init = { +static const struct clk_init_data clk_uart0_init = { .name = "uart0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -755,7 +755,7 @@ static struct clk_std clk_uart0 = { }, }; -static struct clk_init_data clk_uart1_init = { +static const struct clk_init_data clk_uart1_init = { .name = "uart1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -769,7 +769,7 @@ static struct clk_std clk_uart1 = { }, }; -static struct clk_init_data clk_uart2_init = { +static const struct clk_init_data clk_uart2_init = { .name = "uart2", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -783,7 +783,7 @@ static struct clk_std clk_uart2 = { }, }; -static struct clk_init_data clk_usp0_init = { +static const struct clk_init_data clk_usp0_init = { .name = "usp0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -797,7 +797,7 @@ static struct clk_std clk_usp0 = { }, }; -static struct clk_init_data clk_usp1_init = { +static const struct clk_init_data clk_usp1_init = { .name = "usp1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -811,7 +811,7 @@ static struct clk_std clk_usp1 = { }, }; -static struct clk_init_data clk_usp2_init = { +static const struct clk_init_data clk_usp2_init = { .name = "usp2", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -825,7 +825,7 @@ static struct clk_std clk_usp2 = { }, }; -static struct clk_init_data clk_vip_init = { +static const struct clk_init_data clk_vip_init = { .name = "vip", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -839,7 +839,7 @@ static struct clk_std clk_vip = { }, }; -static struct clk_init_data clk_spi0_init = { +static const struct clk_init_data clk_spi0_init = { .name = "spi0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -853,7 +853,7 @@ static struct clk_std clk_spi0 = { }, }; -static struct clk_init_data clk_spi1_init = { +static const struct clk_init_data clk_spi1_init = { .name = "spi1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -867,7 +867,7 @@ static struct clk_std clk_spi1 = { }, }; -static struct clk_init_data clk_tsc_init = { +static const struct clk_init_data clk_tsc_init = { .name = "tsc", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -881,7 +881,7 @@ static struct clk_std clk_tsc = { }, }; -static struct clk_init_data clk_i2c0_init = { +static const struct clk_init_data clk_i2c0_init = { .name = "i2c0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -895,7 +895,7 @@ static struct clk_std clk_i2c0 = { }, }; -static struct clk_init_data clk_i2c1_init = { +static const struct clk_init_data clk_i2c1_init = { .name = "i2c1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -909,7 +909,7 @@ static struct clk_std clk_i2c1 = { }, }; -static struct clk_init_data clk_pwmc_init = { +static const struct clk_init_data clk_pwmc_init = { .name = "pwmc", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -923,7 +923,7 @@ static struct clk_std clk_pwmc = { }, }; -static struct clk_init_data clk_efuse_init = { +static const struct clk_init_data clk_efuse_init = { .name = "efuse", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -937,7 +937,7 @@ static struct clk_std clk_efuse = { }, }; -static struct clk_init_data clk_pulse_init = { +static const struct clk_init_data clk_pulse_init = { .name = "pulse", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -955,7 +955,7 @@ static const char * const std_clk_dsp_parents[] = { "dsp", }; -static struct clk_init_data clk_gps_init = { +static const struct clk_init_data clk_gps_init = { .name = "gps", .ops = &ios_ops, .parent_names = std_clk_dsp_parents, @@ -969,7 +969,7 @@ static struct clk_std clk_gps = { }, }; -static struct clk_init_data clk_mf_init = { +static const struct clk_init_data clk_mf_init = { .name = "mf", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -987,7 +987,7 @@ static const char * const std_clk_sys_parents[] = { "sys", }; -static struct clk_init_data clk_security_init = { +static const struct clk_init_data clk_security_init = { .name = "security", .ops = &ios_ops, .parent_names = std_clk_sys_parents, @@ -1005,7 +1005,7 @@ static const char * const std_clk_usb_parents[] = { "usb_pll", }; -static struct clk_init_data clk_usb0_init = { +static const struct clk_init_data clk_usb0_init = { .name = "usb0", .ops = &ios_ops, .parent_names = std_clk_usb_parents, @@ -1019,7 +1019,7 @@ static struct clk_std clk_usb0 = { }, }; -static struct clk_init_data clk_usb1_init = { +static const struct clk_init_data clk_usb1_init = { .name = "usb1", .ops = &ios_ops, .parent_names = std_clk_usb_parents, diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index aac1c8ec151a..2f824320c318 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c @@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = { }, }; -static struct clk_init_data clk_nand_init = { +static const struct clk_init_data clk_nand_init = { .name = "nand", .ops = &ios_ops, .parent_names = std_clk_io_parents, -- cgit v1.2.3 From aa795c41d9cd41dc9c915dd1956ddd0e4ae44485 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 1 Sep 2017 16:16:40 -0700 Subject: clk: Add devm_of_clk_add_hw_provider()/del_provider() APIs Sometimes we only have one of_clk_del_provider() call in driver error and remove paths, because we're missing a devm_of_clk_add_hw_provider() API. Introduce the API so we can convert drivers to use this and potentially reduce the amount of code needed to remove providers in drivers. Signed-off-by: Stephen Boyd --- Documentation/driver-model/devres.txt | 1 + drivers/clk/clk.c | 52 +++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 13 +++++++++ 3 files changed, 66 insertions(+) (limited to 'drivers/clk') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 69f08c0f23a8..c180045eb43b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -237,6 +237,7 @@ CLOCK devm_clk_get() devm_clk_put() devm_clk_hw_register() + devm_of_clk_add_hw_provider() DMA dmam_alloc_coherent() diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c8d83acda006..856d4858ae27 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3177,6 +3177,37 @@ int of_clk_add_hw_provider(struct device_node *np, } EXPORT_SYMBOL_GPL(of_clk_add_hw_provider); +static void devm_of_clk_release_provider(struct device *dev, void *res) +{ + of_clk_del_provider(*(struct device_node **)res); +} + +int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + struct device_node **ptr, *np; + int ret; + + ptr = devres_alloc(devm_of_clk_release_provider, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + np = dev->of_node; + ret = of_clk_add_hw_provider(np, get, data); + if (!ret) { + *ptr = np; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_clk_add_hw_provider); + /** * of_clk_del_provider() - Remove a previously registered clock provider * @np: Device node pointer associated with clock provider @@ -3198,6 +3229,27 @@ void of_clk_del_provider(struct device_node *np) } EXPORT_SYMBOL_GPL(of_clk_del_provider); +static int devm_clk_provider_match(struct device *dev, void *res, void *data) +{ + struct device_node **np = res; + + if (WARN_ON(!np || !*np)) + return 0; + + return *np == data; +} + +void devm_of_clk_del_provider(struct device *dev) +{ + int ret; + + ret = devres_release(dev, devm_of_clk_release_provider, + devm_clk_provider_match, dev->of_node); + + WARN_ON(ret); +} +EXPORT_SYMBOL(devm_of_clk_del_provider); + static struct clk_hw * __of_clk_get_hw_from_provider(struct of_clk_provider *provider, struct of_phandle_args *clkspec) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5100ec1b5d55..ba79d6186133 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -815,7 +815,12 @@ int of_clk_add_hw_provider(struct device_node *np, struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data), void *data); +int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data); void of_clk_del_provider(struct device_node *np); +void devm_of_clk_del_provider(struct device *dev); struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, @@ -847,7 +852,15 @@ static inline int of_clk_add_hw_provider(struct device_node *np, { return 0; } +static inline int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + return 0; +} static inline void of_clk_del_provider(struct device_node *np) {} +static inline void devm_of_clk_del_provider(struct device *dev) {} static inline struct clk *of_clk_src_simple_get( struct of_phandle_args *clkspec, void *data) { -- cgit v1.2.3 From b87206f8addc52b07e0aba30f8c8ee1a5093cfa9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 1 Sep 2017 16:16:41 -0700 Subject: clk: qcom: common: Migrate to devm_* APIs for resets and clk providers Now that we have devm APIs for the reset controller and of clk hw provider APIs we can remove the custom code here. Signed-off-by: Stephen Boyd --- drivers/clk/qcom/common.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index d523991c945f..b35564c0493f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -111,16 +111,6 @@ qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count) } EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode); -static void qcom_cc_del_clk_provider(void *data) -{ - of_clk_del_provider(data); -} - -static void qcom_cc_reset_unregister(void *data) -{ - reset_controller_unregister(data); -} - static void qcom_cc_gdsc_unregister(void *data) { gdsc_unregister(data); @@ -248,13 +238,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, return ret; } - ret = of_clk_add_hw_provider(dev->of_node, qcom_cc_clk_hw_get, cc); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, qcom_cc_del_clk_provider, - pdev->dev.of_node); - + ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc); if (ret) return ret; @@ -266,13 +250,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, reset->regmap = regmap; reset->reset_map = desc->resets; - ret = reset_controller_register(&reset->rcdev); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, qcom_cc_reset_unregister, - &reset->rcdev); - + ret = devm_reset_controller_register(dev, &reset->rcdev); if (ret) return ret; -- cgit v1.2.3 From 92041a9ff003858f117009501c14f2d075dd68ce Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 6 Sep 2017 11:51:59 +0200 Subject: clk: at91: utmi: set the mainck rate By default, it is assumed that the UTMI clock is generated from a 12 MHz reference clock (MAINCK). If it's not the case, the FREQ field of the SFR_UTMICKTRIM has to be updated to generate the UTMI clock in the proper way. The UTMI clock has a fixed rate of 480 MHz. In fact, there is no multiplier we can configure. The multiplier is managed internally, depending on the reference clock frequency, to achieve the target of 480 MHz. Signed-off-by: Ludovic Desroches Acked-by: Ingo van Lil Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-utmi.c | 95 +++++++++++++++++++++++++++++++++++++------- include/soc/at91/atmel-sfr.h | 2 + 2 files changed, 83 insertions(+), 14 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index aadabd9d1e2b..cd8d689138ff 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -14,14 +14,20 @@ #include #include #include +#include #include "pmc.h" -#define UTMI_FIXED_MUL 40 +/* + * The purpose of this clock is to generate a 480 MHz signal. A different + * rate can't be configured. + */ +#define UTMI_RATE 480000000 struct clk_utmi { struct clk_hw hw; - struct regmap *regmap; + struct regmap *regmap_pmc; + struct regmap *regmap_sfr; }; #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) @@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap) static int clk_utmi_prepare(struct clk_hw *hw) { + struct clk_hw *hw_parent; struct clk_utmi *utmi = to_clk_utmi(hw); unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + unsigned int utmi_ref_clk_freq; + unsigned long parent_rate; + + /* + * If mainck rate is different from 12 MHz, we have to configure the + * FREQ field of the SFR_UTMICKTRIM register to generate properly + * the utmi clock. + */ + hw_parent = clk_hw_get_parent(hw); + parent_rate = clk_hw_get_rate(hw_parent); + + switch (parent_rate) { + case 12000000: + utmi_ref_clk_freq = 0; + break; + case 16000000: + utmi_ref_clk_freq = 1; + break; + case 24000000: + utmi_ref_clk_freq = 2; + break; + /* + * Not supported on SAMA5D2 but it's not an issue since MAINCK + * maximum value is 24 MHz. + */ + case 48000000: + utmi_ref_clk_freq = 3; + break; + default: + pr_err("UTMICK: unsupported mainck rate\n"); + return -EINVAL; + } - regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr); + if (utmi->regmap_sfr) { + regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM, + AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq); + } else if (utmi_ref_clk_freq) { + pr_err("UTMICK: sfr node required\n"); + return -EINVAL; + } - while (!clk_utmi_ready(utmi->regmap)) + regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr); + + while (!clk_utmi_ready(utmi->regmap_pmc)) cpu_relax(); return 0; @@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); - return clk_utmi_ready(utmi->regmap); + return clk_utmi_ready(utmi->regmap_pmc); } static void clk_utmi_unprepare(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); - regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0); + regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, + AT91_PMC_UPLLEN, 0); } static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - /* UTMI clk is a fixed clk multiplier */ - return parent_rate * UTMI_FIXED_MUL; + /* UTMI clk rate is fixed. */ + return UTMI_RATE; } static const struct clk_ops utmi_ops = { @@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = { }; static struct clk_hw * __init -at91_clk_register_utmi(struct regmap *regmap, +at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, const char *name, const char *parent_name) { struct clk_utmi *utmi; @@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap, init.flags = CLK_SET_RATE_GATE; utmi->hw.init = &init; - utmi->regmap = regmap; + utmi->regmap_pmc = regmap_pmc; + utmi->regmap_sfr = regmap_sfr; hw = &utmi->hw; ret = clk_hw_register(NULL, &utmi->hw); @@ -114,17 +163,35 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) struct clk_hw *hw; const char *parent_name; const char *name = np->name; - struct regmap *regmap; + struct regmap *regmap_pmc, *regmap_sfr; parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); - if (IS_ERR(regmap)) + regmap_pmc = syscon_node_to_regmap(of_get_parent(np)); + if (IS_ERR(regmap_pmc)) return; - hw = at91_clk_register_utmi(regmap, name, parent_name); + /* + * If the device supports different mainck rates, this value has to be + * set in the UTMI Clock Trimming register. + * - 9x5: mainck supports several rates but it is indicated that a + * 12 MHz is needed in case of USB. + * - sama5d3 and sama5d2: mainck supports several rates. Configuring + * the FREQ field of the UTMI Clock Trimming register is mandatory. + * - sama5d4: mainck is at 12 MHz. + * + * We only need to retrieve sama5d3 or sama5d2 sfr regmap. + */ + regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr"); + if (IS_ERR(regmap_sfr)) { + regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); + if (IS_ERR(regmap_sfr)) + regmap_sfr = NULL; + } + + hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name); if (IS_ERR(hw)) return; diff --git a/include/soc/at91/atmel-sfr.h b/include/soc/at91/atmel-sfr.h index 506ea8ffda19..482337af06b8 100644 --- a/include/soc/at91/atmel-sfr.h +++ b/include/soc/at91/atmel-sfr.h @@ -17,6 +17,7 @@ /* 0x08 ~ 0x0c: Reserved */ #define AT91_SFR_OHCIICR 0x10 /* OHCI INT Configuration Register */ #define AT91_SFR_OHCIISR 0x14 /* OHCI INT Status Register */ +#define AT91_SFR_UTMICKTRIM 0x30 /* UTMI Clock Trimming Register */ #define AT91_SFR_I2SCLKSEL 0x90 /* I2SC Register */ /* Field definitions */ @@ -28,5 +29,6 @@ AT91_OHCIICR_SUSPEND_B | \ AT91_OHCIICR_SUSPEND_C) +#define AT91_UTMICKTRIM_FREQ GENMASK(1, 0) #endif /* _LINUX_MFD_SYSCON_ATMEL_SFR_H */ -- cgit v1.2.3 From a49580ec9af037b932d04f48ae83fc4a3bd9b0a4 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 24 Aug 2017 20:36:44 +0300 Subject: clk: qcom: Remove unused RCG ops The RCGs ops for shared branches are not used now, so remove it. Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg.h | 3 -- drivers/clk/qcom/clk-rcg2.c | 79 --------------------------------------------- 2 files changed, 82 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 1b3e8d265bdb..a2495457e564 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -156,7 +156,6 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @hid_width: number of bits in half integer divider * @parent_map: map from software's parent index to hardware's src_sel field * @freq_tbl: frequency table - * @current_freq: last cached frequency when using branches with shared RCGs * @clkr: regmap clock handle * */ @@ -166,7 +165,6 @@ struct clk_rcg2 { u8 hid_width; const struct parent_map *parent_map; const struct freq_tbl *freq_tbl; - unsigned long current_freq; struct clk_regmap clkr; }; @@ -174,7 +172,6 @@ struct clk_rcg2 { extern const struct clk_ops clk_rcg2_ops; extern const struct clk_ops clk_rcg2_floor_ops; -extern const struct clk_ops clk_rcg2_shared_ops; extern const struct clk_ops clk_edp_pixel_ops; extern const struct clk_ops clk_byte_ops; extern const struct clk_ops clk_byte2_ops; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 1a0985ae20d2..bbeaf9c09dbb 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -358,85 +358,6 @@ const struct clk_ops clk_rcg2_floor_ops = { }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); -static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - const char *name = clk_hw_get_name(hw); - int ret, count; - - /* force enable RCG */ - ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, - CMD_ROOT_EN, CMD_ROOT_EN); - if (ret) - return ret; - - /* wait for RCG to turn ON */ - for (count = 500; count > 0; count--) { - ret = clk_rcg2_is_enabled(hw); - if (ret) - break; - udelay(1); - } - if (!count) - pr_err("%s: RCG did not turn on\n", name); - - /* set clock rate */ - ret = __clk_rcg2_set_rate(hw, rate, CEIL); - if (ret) - return ret; - - /* clear force enable RCG */ - return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, - CMD_ROOT_EN, 0); -} - -static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - /* cache the rate */ - rcg->current_freq = rate; - - if (!__clk_is_enabled(hw->clk)) - return 0; - - return clk_rcg2_shared_force_enable(hw, rcg->current_freq); -} - -static unsigned long -clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate); -} - -static int clk_rcg2_shared_enable(struct clk_hw *hw) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - return clk_rcg2_shared_force_enable(hw, rcg->current_freq); -} - -static void clk_rcg2_shared_disable(struct clk_hw *hw) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - /* switch to XO, which is the lowest entry in the freq table */ - clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0); -} - -const struct clk_ops clk_rcg2_shared_ops = { - .enable = clk_rcg2_shared_enable, - .disable = clk_rcg2_shared_disable, - .get_parent = clk_rcg2_get_parent, - .recalc_rate = clk_rcg2_shared_recalc_rate, - .determine_rate = clk_rcg2_determine_rate, - .set_rate = clk_rcg2_shared_set_rate, -}; -EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops); - struct frac_entry { int num; int den; -- cgit v1.2.3 From d4a69583dee775826c02fa64e20fbf6ab193a3fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Oct 2017 13:59:17 +0200 Subject: clk: qcom: Implement RPM clocks for MSM8660/APQ8060 The RPM clocks were missing for MSM8660/APQ8060. For this to be completed we need to add a special fixed rate RPM clock that is used for the PLL4 on these SoCs. The rest of the clocks are pretty similar to the other supported platforms. The "active" clock pattern is mirrored in all the clocks. I guess that the PLL4 that clocks the LPASS is actually never used as "active only" since the low-power audio subsystem should be left on when the CPU goes to idle, so that it can be used as a stand-alone MP3 player type of device. The PLL4 seems to be enabled only on behalf of the booting LPASS Hexagon - which will cast its own vote once its booted - and as such we only configure the active state (meaning both states will have same configuration). The result is that PLL4 will be on from prepare() to unprepare() regardless of what the application CPU does. Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpm.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c index df3e5fe8442a..c60f61b10c7f 100644 --- a/drivers/clk/qcom/clk-rpm.c +++ b/drivers/clk/qcom/clk-rpm.c @@ -56,6 +56,18 @@ }, \ } +#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \ + static struct clk_rpm _platform##_##_name = { \ + .rpm_clk_id = (r_id), \ + .rate = (r), \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_rpm_fixed_ops, \ + .name = #_name, \ + .parent_names = (const char *[]){ "pxo" }, \ + .num_parents = 1, \ + }, \ + } + #define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \ static struct clk_rpm _platform##_##_active; \ static struct clk_rpm _platform##_##_name = { \ @@ -143,6 +155,13 @@ static int clk_rpm_handoff(struct clk_rpm *r) int ret; u32 value = INT_MAX; + /* + * The vendor tree simply reads the status for this + * RPM clock. + */ + if (r->rpm_clk_id == QCOM_RPM_PLL_4) + return 0; + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, r->rpm_clk_id, &value, 1); if (ret) @@ -269,6 +288,32 @@ out: mutex_unlock(&rpm_clk_lock); } +static int clk_rpm_fixed_prepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + u32 value = 1; + int ret; + + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, + r->rpm_clk_id, &value, 1); + if (!ret) + r->enabled = true; + + return ret; +} + +static void clk_rpm_fixed_unprepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + u32 value = 0; + int ret; + + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, + r->rpm_clk_id, &value, 1); + if (!ret) + r->enabled = false; +} + static int clk_rpm_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -333,6 +378,13 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw, return r->rate; } +static const struct clk_ops clk_rpm_fixed_ops = { + .prepare = clk_rpm_fixed_prepare, + .unprepare = clk_rpm_fixed_unprepare, + .round_rate = clk_rpm_round_rate, + .recalc_rate = clk_rpm_recalc_rate, +}; + static const struct clk_ops clk_rpm_ops = { .prepare = clk_rpm_prepare, .unprepare = clk_rpm_unprepare, @@ -348,6 +400,45 @@ static const struct clk_ops clk_rpm_branch_ops = { .recalc_rate = clk_rpm_recalc_rate, }; +/* MSM8660/APQ8060 */ +DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK); +DEFINE_CLK_RPM(msm8660, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK); +DEFINE_CLK_RPM(msm8660, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK); +DEFINE_CLK_RPM(msm8660, smi_clk, smi_a_clk, QCOM_RPM_SMI_CLK); +DEFINE_CLK_RPM(msm8660, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK); +DEFINE_CLK_RPM_FIXED(msm8660, pll4_clk, pll4_a_clk, QCOM_RPM_PLL_4, 540672000); + +static struct clk_rpm *msm8660_clks[] = { + [RPM_APPS_FABRIC_CLK] = &msm8660_afab_clk, + [RPM_APPS_FABRIC_A_CLK] = &msm8660_afab_a_clk, + [RPM_SYS_FABRIC_CLK] = &msm8660_sfab_clk, + [RPM_SYS_FABRIC_A_CLK] = &msm8660_sfab_a_clk, + [RPM_MM_FABRIC_CLK] = &msm8660_mmfab_clk, + [RPM_MM_FABRIC_A_CLK] = &msm8660_mmfab_a_clk, + [RPM_DAYTONA_FABRIC_CLK] = &msm8660_daytona_clk, + [RPM_DAYTONA_FABRIC_A_CLK] = &msm8660_daytona_a_clk, + [RPM_SFPB_CLK] = &msm8660_sfpb_clk, + [RPM_SFPB_A_CLK] = &msm8660_sfpb_a_clk, + [RPM_CFPB_CLK] = &msm8660_cfpb_clk, + [RPM_CFPB_A_CLK] = &msm8660_cfpb_a_clk, + [RPM_MMFPB_CLK] = &msm8660_mmfpb_clk, + [RPM_MMFPB_A_CLK] = &msm8660_mmfpb_a_clk, + [RPM_SMI_CLK] = &msm8660_smi_clk, + [RPM_SMI_A_CLK] = &msm8660_smi_a_clk, + [RPM_EBI1_CLK] = &msm8660_ebi1_clk, + [RPM_EBI1_A_CLK] = &msm8660_ebi1_a_clk, + [RPM_PLL4_CLK] = &msm8660_pll4_clk, +}; + +static const struct rpm_clk_desc rpm_clk_msm8660 = { + .clks = msm8660_clks, + .num_clks = ARRAY_SIZE(msm8660_clks), +}; + /* apq8064 */ DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK); DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK); @@ -386,6 +477,8 @@ static const struct rpm_clk_desc rpm_clk_apq8064 = { }; static const struct of_device_id rpm_clk_match_table[] = { + { .compatible = "qcom,rpmcc-msm8660", .data = &rpm_clk_msm8660 }, + { .compatible = "qcom,rpmcc-apq8060", .data = &rpm_clk_msm8660 }, { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 }, { } }; -- cgit v1.2.3 From 7066fdd0d7427f1ba455d186e75213c442c9663b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 10 Oct 2017 14:27:13 +0530 Subject: clk: qcom: clk-smd-rpm: add msm8996 rpmclks Add all RPM controlled clocks on msm8996 platform [srini: Fixed various issues with offsets and made names specific to msm8996] Signed-off-by: Srinivas Kandagatla Signed-off-by: Rajendra Nayak Acked-by: Rob Herring Acked-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,rpmcc.txt | 1 + drivers/clk/qcom/clk-smd-rpm.c | 82 ++++++++++++++++++++++ include/dt-bindings/clock/qcom,rpmcc.h | 14 ++++ include/linux/soc/qcom/smd-rpm.h | 4 ++ 4 files changed, 101 insertions(+) (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 833a89f06ae0..4491d1c104aa 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -15,6 +15,7 @@ Required properties : "qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" + "qcom,rpmcc-msm8996", "qcom,rpmcc" - #clock-cells : shall contain 1 diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index cc03d5508627..c26d9007bfc4 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -530,9 +530,91 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .clks = msm8974_clks, .num_clks = ARRAY_SIZE(msm8974_clks), }; + +/* msm8996 */ +DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, + QCOM_SMD_RPM_MMAXI_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); +DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk, + QCOM_SMD_RPM_AGGR_CLK, 1, 1000); +DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk, + QCOM_SMD_RPM_AGGR_CLK, 2, 1000); +DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5); + +static struct clk_smd_rpm *msm8996_clks[] = { + [RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk, + [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_IPA_CLK] = &msm8996_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8996_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk, + [RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk, + [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk, + [RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk, + [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8996_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8996_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8996_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8996_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a, + [RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8996_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a, + [RPM_SMD_DIV_CLK2] = &msm8996_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a, + [RPM_SMD_DIV_CLK3] = &msm8996_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { + .clks = msm8996_clks, + .num_clks = ARRAY_SIZE(msm8996_clks), +}; + static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, + { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { } }; MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index 29dad206a74b..b8337a5fa347 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -104,5 +104,19 @@ #define RPM_SMD_CXO_A1_A_PIN 59 #define RPM_SMD_CXO_A2_PIN 60 #define RPM_SMD_CXO_A2_A_PIN 61 +#define RPM_SMD_AGGR1_NOC_CLK 62 +#define RPM_SMD_AGGR1_NOC_A_CLK 63 +#define RPM_SMD_AGGR2_NOC_CLK 64 +#define RPM_SMD_AGGR2_NOC_A_CLK 65 +#define RPM_SMD_MMAXI_CLK 66 +#define RPM_SMD_MMAXI_A_CLK 67 +#define RPM_SMD_IPA_CLK 68 +#define RPM_SMD_IPA_A_CLK 69 +#define RPM_SMD_CE1_CLK 70 +#define RPM_SMD_CE1_A_CLK 71 +#define RPM_SMD_DIV_CLK3 72 +#define RPM_SMD_DIV_A_CLK3 73 +#define RPM_SMD_LN_BB_CLK 74 +#define RPM_SMD_LN_BB_A_CLK 75 #endif diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h index 2a53dcaeeeed..ebdabd669d93 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -26,6 +26,10 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_SMPB 0x62706d73 #define QCOM_SMD_RPM_SPDM 0x63707362 #define QCOM_SMD_RPM_VSA 0x00617376 +#define QCOM_SMD_RPM_MMAXI_CLK 0x69786d6d +#define QCOM_SMD_RPM_IPA_CLK 0x617069 +#define QCOM_SMD_RPM_CE_CLK 0x6563 +#define QCOM_SMD_RPM_AGGR_CLK 0x72676761 int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, int state, -- cgit v1.2.3 From c68ee58d9ee7b856ac722f18f4f26579c8fbd2b4 Mon Sep 17 00:00:00 2001 From: Sébastien Szymanski Date: Tue, 1 Aug 2017 12:40:07 +0200 Subject: clk: imx6: refine hdmi_isfr's parent to make HDMI work on i.MX6 SoCs w/o VPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX6 SoCs without VPU (in my case MCIMX6D4AVT10AC), the hdmi driver fails to probe: [ 2.540030] dwhdmi-imx 120000.hdmi: Unsupported HDMI controller (0000:00:00) [ 2.548199] imx-drm display-subsystem: failed to bind 120000.hdmi (ops dw_hdmi_imx_ops): -19 [ 2.557403] imx-drm display-subsystem: master bind failed: -19 That's because hdmi_isfr's parent, video_27m, is not correctly ungated. As explained in commit 5ccc248cc537 ("ARM: imx6q: clk: Add support for mipi_core_cfg clock as a shared clock gate"), video_27m is gated by CCM_CCGR3[CG8]. On i.MX6 SoCs with VPU, the hdmi is working thanks to the CCM_CMEOR[mod_en_ov_vpu] bit which makes the video_27m ungated whatever is in CCM_CCGR3[CG8]. The issue can be reproduced by setting CCMEOR[mod_en_ov_vpu] to 0. Make the HDMI work in every case by setting hdmi_isfr's parent to mipi_core_cfg. Signed-off-by: Sébastien Szymanski Reviewed-by: Fabio Estevam Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx6q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index c07df719b8a3..8d518ad5dc13 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -761,7 +761,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24); clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26); clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0); - clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "video_27m", base + 0x70, 4); + clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", base + 0x70, 4); clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6); clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8); clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10); -- cgit v1.2.3 From 7f218065c136cc643e4773cad5e742f2c597988c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 12 Oct 2017 15:29:35 +0200 Subject: clk: imx: clk-imx6ul: allow lcdif_pre_sel to change parent rate Allowing the lcdif_pre_sel to propagate rate changes to its parent PLL allows more fine grained control over the LCDIF pixel clock rate. For example, the Innovision AT043TN24 LCD panel described in the imx6ul-14x14-evk device tree requires a 9 MHz pixel clock. Before this patch, the lcdif_pre_sel clock rate is fixed, and just setting the lcdif_pred and lcdif_podf dividers only allows to get as close as about 8.44 MHz: pll3 1 1 480000000 0 0 pll3_bypass 1 1 480000000 0 0 pll3_usb_otg 1 1 480000000 0 0 pll3_pfd1_540m 1 1 540000000 0 0 lcdif_pre_sel 1 1 540000000 0 0 lcdif_pred 1 1 67500000 0 0 lcdif_podf 1 1 8437500 0 0 lcdif_pix 1 1 8437500 0 0 Once lcdif_pre_sel is allowed to propagate rate requests to its parent, the actual pixel clock matches the requested value: pll3 1 1 480000000 0 0 pll3_bypass 1 1 480000000 0 0 pll3_usb_otg 1 1 480000000 0 0 pll3_pfd1_540m 1 1 288000000 0 0 lcdif_pre_sel 1 1 288000000 0 0 lcdif_pred 1 1 36000000 0 0 lcdif_podf 1 1 9000000 0 0 lcdif_pix 1 1 9000000 0 0 Signed-off-by: Philipp Zabel Reviewed-by: Fabio Estevam Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx6ul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 5e8c18afce9a..85c118164469 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -267,7 +267,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6ULL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels)); } clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); - clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels)); + clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT); clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels)); clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); -- cgit v1.2.3 From edc5a8e754aba9c6eaeddd18cb1e72462f99b16c Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Mon, 2 Oct 2017 13:32:10 +0300 Subject: clk: imx: imx7d: Fix parent clock for OCRAM_CLK The parent of OCRAM_CLK should be axi_main_root_clk and not axi_post_div. before: axi_src 1 1 332307692 0 0 axi_cg 1 1 332307692 0 0 axi_pre_div 1 1 332307692 0 0 axi_post_div 1 1 332307692 0 0 ocram_clk 0 0 332307692 0 0 main_axi_root_clk 1 1 332307692 0 0 after: axi_src 1 1 332307692 0 0 axi_cg 1 1 332307692 0 0 axi_pre_div 1 1 332307692 0 0 axi_post_div 1 1 332307692 0 0 main_axi_root_clk 1 1 332307692 0 0 ocram_clk 0 0 332307692 0 0 Reference Doc: i.MX 7D Reference Manual - Chap 5, p 516 (https://www.nxp.com/docs/en/reference-manual/IMX7DRM.pdf) Fixes: 8f6d8094b215 ("ARM: imx: add imx7d clk tree support") Signed-off-by: Adriana Reus Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 2305699db467..0ac9b30c8b90 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -797,7 +797,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); - clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0); + clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0); clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0); clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); -- cgit v1.2.3 From 259bc283069975004067c51cc09525a50db4b470 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Mon, 2 Oct 2017 13:32:11 +0300 Subject: clk: imx: imx7d: Remove ARM_M0 clock IMX7d does not have an M0 Core and this particular clock doesn't seem connected to anything else. Remove this entry from the CCM driver. Signed-off-by: Adriana Reus Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 9 --------- include/dt-bindings/clock/imx7d-clock.h | 8 ++++---- 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 0ac9b30c8b90..80dc211eb74b 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -54,11 +54,6 @@ static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk", "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk", }; -static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk", - "pll_enet_125m_clk", "pll_sys_pfd2_135m_clk", - "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk", - "pll_usb_main_clk", }; - static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk", "pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", }; @@ -510,7 +505,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); - clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); @@ -582,7 +576,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); - clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28); clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); @@ -721,7 +714,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); - clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); @@ -793,7 +785,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); - clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h index de62a83b6c80..e2f99ae72d5c 100644 --- a/include/dt-bindings/clock/imx7d-clock.h +++ b/include/dt-bindings/clock/imx7d-clock.h @@ -80,10 +80,10 @@ #define IMX7D_ARM_M4_ROOT_SRC 67 #define IMX7D_ARM_M4_ROOT_CG 68 #define IMX7D_ARM_M4_ROOT_DIV 69 -#define IMX7D_ARM_M0_ROOT_CLK 70 -#define IMX7D_ARM_M0_ROOT_SRC 71 -#define IMX7D_ARM_M0_ROOT_CG 72 -#define IMX7D_ARM_M0_ROOT_DIV 73 +#define IMX7D_ARM_M0_ROOT_CLK 70 /* unused */ +#define IMX7D_ARM_M0_ROOT_SRC 71 /* unused */ +#define IMX7D_ARM_M0_ROOT_CG 72 /* unused */ +#define IMX7D_ARM_M0_ROOT_DIV 73 /* unused */ #define IMX7D_MAIN_AXI_ROOT_CLK 74 #define IMX7D_MAIN_AXI_ROOT_SRC 75 #define IMX7D_MAIN_AXI_ROOT_CG 76 -- cgit v1.2.3 From e2f744a82d725ab55091cccfb8e527b4220471f0 Mon Sep 17 00:00:00 2001 From: "weiyi.lu@mediatek.com" Date: Mon, 23 Oct 2017 12:10:34 +0800 Subject: clk: mediatek: Add MT2712 clock support Add MT2712 clock support, include topckgen, apmixedsys, infracfg, pericfg, mcucfg and subsystem clocks. Signed-off-by: Weiyi Lu [sboyd@codeaurora.org: Static on top_clk_data] Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/Kconfig | 50 ++ drivers/clk/mediatek/Makefile | 8 + drivers/clk/mediatek/clk-mt2712-bdp.c | 102 +++ drivers/clk/mediatek/clk-mt2712-img.c | 80 ++ drivers/clk/mediatek/clk-mt2712-jpgdec.c | 76 ++ drivers/clk/mediatek/clk-mt2712-mfg.c | 75 ++ drivers/clk/mediatek/clk-mt2712-mm.c | 170 ++++ drivers/clk/mediatek/clk-mt2712-vdec.c | 94 ++ drivers/clk/mediatek/clk-mt2712-venc.c | 77 ++ drivers/clk/mediatek/clk-mt2712.c | 1435 ++++++++++++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 2 + drivers/clk/mediatek/clk-pll.c | 13 +- 12 files changed, 2180 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/mediatek/clk-mt2712-bdp.c create mode 100644 drivers/clk/mediatek/clk-mt2712-img.c create mode 100644 drivers/clk/mediatek/clk-mt2712-jpgdec.c create mode 100644 drivers/clk/mediatek/clk-mt2712-mfg.c create mode 100644 drivers/clk/mediatek/clk-mt2712-mm.c create mode 100644 drivers/clk/mediatek/clk-mt2712-vdec.c create mode 100644 drivers/clk/mediatek/clk-mt2712-venc.c create mode 100644 drivers/clk/mediatek/clk-mt2712.c (limited to 'drivers/clk') diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 28739a9a6e37..300dbb551bf7 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS ---help--- This driver supports Mediatek MT2701 bdpsys clocks. +config COMMON_CLK_MT2712 + bool "Clock driver for Mediatek MT2712" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + ---help--- + This driver supports Mediatek MT2712 basic clocks. + +config COMMON_CLK_MT2712_BDPSYS + bool "Clock driver for Mediatek MT2712 bdpsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 bdpsys clocks. + +config COMMON_CLK_MT2712_IMGSYS + bool "Clock driver for Mediatek MT2712 imgsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 imgsys clocks. + +config COMMON_CLK_MT2712_JPGDECSYS + bool "Clock driver for Mediatek MT2712 jpgdecsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 jpgdecsys clocks. + +config COMMON_CLK_MT2712_MFGCFG + bool "Clock driver for Mediatek MT2712 mfgcfg" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 mfgcfg clocks. + +config COMMON_CLK_MT2712_MMSYS + bool "Clock driver for Mediatek MT2712 mmsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 mmsys clocks. + +config COMMON_CLK_MT2712_VDECSYS + bool "Clock driver for Mediatek MT2712 vdecsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 vdecsys clocks. + +config COMMON_CLK_MT2712_VENCSYS + bool "Clock driver for Mediatek MT2712 vencsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 vencsys clocks. + config COMMON_CLK_MT6797 bool "Clock driver for Mediatek MT6797" depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 2a755b5fb51b..a4e5c47c73a4 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -12,5 +12,13 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o +obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o +obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o +obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o +obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o +obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c new file mode 100644 index 000000000000..5fe4728c076e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-bdp.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs bdp_cg_regs = { + .set_ofs = 0x100, + .clr_ofs = 0x100, + .sta_ofs = 0x100, +}; + +#define GATE_BDP(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &bdp_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate bdp_clks[] = { + GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0), + GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1), + GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5), + GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9), + GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10), + GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11), + GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12), + GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13), + GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14), + GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15), + GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16), + GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17), + GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21), + GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22), + GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23), + GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24), + GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25), + GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26), + GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27), + GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28), + GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29), + GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30), +}; + +static int clk_mt2712_bdp_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK); + + mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_bdp[] = { + { .compatible = "mediatek,mt2712-bdpsys", }, + {} +}; + +static struct platform_driver clk_mt2712_bdp_drv = { + .probe = clk_mt2712_bdp_probe, + .driver = { + .name = "clk-mt2712-bdp", + .of_match_table = of_match_clk_mt2712_bdp, + }, +}; + +builtin_platform_driver(clk_mt2712_bdp_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c new file mode 100644 index 000000000000..139ff55d495e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-img.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &img_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0), + GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3), + GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8), + GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9), + GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10), + GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11), +}; + +static int clk_mt2712_img_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); + + mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_img[] = { + { .compatible = "mediatek,mt2712-imgsys", }, + {} +}; + +static struct platform_driver clk_mt2712_img_drv = { + .probe = clk_mt2712_img_probe, + .driver = { + .name = "clk-mt2712-img", + .of_match_table = of_match_clk_mt2712_img, + }, +}; + +builtin_platform_driver(clk_mt2712_img_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c new file mode 100644 index 000000000000..c7d4aada4892 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs jpgdec_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_JPGDEC(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &jpgdec_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate jpgdec_clks[] = { + GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0), + GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4), +}; + +static int clk_mt2712_jpgdec_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK); + + mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_jpgdec[] = { + { .compatible = "mediatek,mt2712-jpgdecsys", }, + {} +}; + +static struct platform_driver clk_mt2712_jpgdec_drv = { + .probe = clk_mt2712_jpgdec_probe, + .driver = { + .name = "clk-mt2712-jpgdec", + .of_match_table = of_match_clk_mt2712_jpgdec, + }, +}; + +builtin_platform_driver(clk_mt2712_jpgdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c new file mode 100644 index 000000000000..570f72d48d4d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mfg.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mfg_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0), +}; + +static int clk_mt2712_mfg_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); + + mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_mfg[] = { + { .compatible = "mediatek,mt2712-mfgcfg", }, + {} +}; + +static struct platform_driver clk_mt2712_mfg_drv = { + .probe = clk_mt2712_mfg_probe, + .driver = { + .name = "clk-mt2712-mfg", + .of_match_table = of_match_clk_mt2712_mfg, + }, +}; + +builtin_platform_driver(clk_mt2712_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c new file mode 100644 index 000000000000..a8b4b6d42488 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mm.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs mm2_cg_regs = { + .set_ofs = 0x224, + .clr_ofs = 0x228, + .sta_ofs = 0x220, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_MM1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_MM2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1), + GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3), + GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), + GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5), + GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), + GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7), + GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8), + GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), + GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11), + GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17), + GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18), + GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21), + GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22), + GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23), + GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24), + GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25), + GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26), + GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27), + GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28), + GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29), + GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30), + GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31), + /* MM2 */ + GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0), + GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1), + GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2), + GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3), + GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4), + GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5), + GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6), +}; + +static int clk_mt2712_mm_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_mm[] = { + { .compatible = "mediatek,mt2712-mmsys", }, + {} +}; + +static struct platform_driver clk_mt2712_mm_drv = { + .probe = clk_mt2712_mm_probe, + .driver = { + .name = "clk-mt2712-mm", + .of_match_table = of_match_clk_mt2712_mm, + }, +}; + +builtin_platform_driver(clk_mt2712_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c new file mode 100644 index 000000000000..55c64ee8cc91 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-vdec.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_VDEC1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1), +}; + +static int clk_mt2712_vdec_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); + + mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_vdec[] = { + { .compatible = "mediatek,mt2712-vdecsys", }, + {} +}; + +static struct platform_driver clk_mt2712_vdec_drv = { + .probe = clk_mt2712_vdec_probe, + .driver = { + .name = "clk-mt2712-vdec", + .of_match_table = of_match_clk_mt2712_vdec, + }, +}; + +builtin_platform_driver(clk_mt2712_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c new file mode 100644 index 000000000000..ccbfe98777c8 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-venc.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &venc_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0), + GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4), + GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12), +}; + +static int clk_mt2712_venc_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); + + mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_venc[] = { + { .compatible = "mediatek,mt2712-vencsys", }, + {} +}; + +static struct platform_driver clk_mt2712_venc_drv = { + .probe = clk_mt2712_venc_probe, + .driver = { + .name = "clk-mt2712-venc", + .of_match_table = of_match_clk_mt2712_venc, + }, +}; + +builtin_platform_driver(clk_mt2712_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c new file mode 100644 index 000000000000..498d13799388 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static DEFINE_SPINLOCK(mt2712_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_VPLL3_DPIX, "vpll3_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_LTEPLL_FS26M, "ltepll_fs26m", NULL, 26000000), + FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 350000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC, "dsi0_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_DSI1_LNTC, "dsi1_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_LVDSTX3_CLKDIG_CTS, "lvdstx3", NULL, 140000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx", NULL, 140000000), + FIXED_CLK(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", NULL, 32768), + FIXED_CLK(CLK_TOP_CLKRTC_INT, "clkrtc_int", NULL, 32747), + FIXED_CLK(CLK_TOP_CSI0, "csi0", NULL, 26000000), + FIXED_CLK(CLK_TOP_CVBSPLL, "cvbspll", NULL, 108000000), +}; + +static const struct mtk_fixed_factor top_early_divs[] = { + FACTOR(CLK_TOP_SYS_26M, "sys_26m", "clk26m", 1, + 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "sys_26m", 1, + 2), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_ARMCA35PLL, "armca35pll_ck", "armca35pll", 1, + 1), + FACTOR(CLK_TOP_ARMCA35PLL_600M, "armca35pll_600m", "armca35pll_ck", 1, + 2), + FACTOR(CLK_TOP_ARMCA35PLL_400M, "armca35pll_400m", "armca35pll_ck", 1, + 3), + FACTOR(CLK_TOP_ARMCA72PLL, "armca72pll_ck", "armca72pll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, + 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, + 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, + 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "syspll_ck", 1, + 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, + 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "syspll_ck", 1, + 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, + 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "syspll_ck", 1, + 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, + 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, + 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_ck", 1, + 7), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_ck", 1, + 26), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll_ck", 1, + 52), + FACTOR(CLK_TOP_UNIVPLL_D104, "univpll_d104", "univpll_ck", 1, + 104), + FACTOR(CLK_TOP_UNIVPLL_D208, "univpll_d208", "univpll_ck", 1, + 208), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_ck", 1, + 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_ck", 1, + 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, + 8), + FACTOR(CLK_TOP_F_MP0_PLL1, "f_mp0_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_MP0_PLL2, "f_mp0_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL1, "f_big_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL2, "f_big_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL1, "f_bus_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL2, "f_bus_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, + 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, + 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, + 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, + 8), + FACTOR(CLK_TOP_APLL1_D16, "apll1_d16", "apll1_ck", 1, + 16), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, + 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, + 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1, + 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1, + 8), + FACTOR(CLK_TOP_APLL2_D16, "apll2_d16", "apll2_ck", 1, + 16), + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll_ck", 1, + 8), + FACTOR(CLK_TOP_LVDSPLL2, "lvdspll2_ck", "lvdspll2", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL2_D2, "lvdspll2_d2", "lvdspll2_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL2_D4, "lvdspll2_d4", "lvdspll2_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL2_D8, "lvdspll2_d8", "lvdspll2_ck", 1, + 8), + FACTOR(CLK_TOP_ETHERPLL_125M, "etherpll_125m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_ETHERPLL_50M, "etherpll_50m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_CVBS, "cvbs", "cvbspll", 1, + 1), + FACTOR(CLK_TOP_CVBS_D2, "cvbs_d2", "cvbs", 1, + 2), + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, + 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, + 2), + FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, + 1), + FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll_ck", 1, + 2), + FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, + 1), + FACTOR(CLK_TOP_VCODECPLL_D2, "vcodecpll_d2", "vcodecpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, + 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, + 8), + FACTOR(CLK_TOP_TVDPLL_429M, "tvdpll_429m", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_429M_D2, "tvdpll_429m_d2", "tvdpll_429m", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_429M_D4, "tvdpll_429m_d4", "tvdpll_429m", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2_ck", 1, + 4), + FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1, + 4), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "msdcpll2_ck" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck" +}; + +static const char * const mm_parents[] = { + "clk26m", + "vencpll_ck", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vcodecpll_ck", + "tvdpll_429m", + "univpll_d3", + "vencpll_ck", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "syspll3_d2", + "tvdpll_ck" +}; + +static const char * const venc_parents[] = { + "clk26m", + "univpll1_d2", + "mmpll_d2", + "tvdpll_d2", + "syspll1_d2", + "univpll_d5", + "vcodecpll_d2", + "univpll2_d2", + "syspll3_d2" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d52", + "univpll_d208", + "univpll_d104", + "clk26m_d2", + "univpll_d26", + "univpll2_d8", + "syspll3_d4", + "syspll3_d2", + "univpll1_d4", + "univpll2_d2" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8" +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const usb30_parents[] = { + "clk26m", + "univpll3_d2", + "univpll3_d4", + "univpll2_d4" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "msdcpll_d4", + "vencpll_d2", + "univpll1_d2", + "msdcpll2_ck", + "msdcpll2_d2", + "msdcpll2_d4" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "univpll_d7", + "vencpll_d2" +}; + +static const char * const msdc30_3_parents[] = { + "clk26m", + "msdcpll2_ck", + "msdcpll2_d2", + "univpll2_d2", + "msdcpll2_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2", + "msdcpll_ck", + "msdcpll_d2", + "msdcpll_d4" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "syspll3_d2", + "syspll3_d4" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "syspll3_d4" +}; + +static const char * const dpilvds1_parents[] = { + "clk26m", + "lvdspll2_ck", + "lvdspll2_d2", + "lvdspll2_d4", + "lvdspll2_d8", + "clkfpc" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5" +}; + +static const char * const nr_parents[] = { + "clk26m", + "univpll1_d4", + "syspll2_d2", + "syspll1_d4", + "univpll1_d8", + "univpll3_d2", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const nfi2x_parents[] = { + "clk26m", + "syspll4_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll3_d2", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "syspll_d5", + "syspll1_d2" +}; + +static const char * const irda_parents[] = { + "clk26m", + "univpll2_d4", + "syspll2_d4", + "univpll2_d8" +}; + +static const char * const cci400_parents[] = { + "clk26m", + "vencpll_ck", + "armca35pll_600m", + "armca35pll_400m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "univpll_d3" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const mem_mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3" +}; + +static const char * const axi_mfg_parents[] = { + "clk26m", + "axi_sel", + "univpll_d5" +}; + +static const char * const scam_parents[] = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "syspll2_d4" +}; + +static const char * const nfiecc_parents[] = { + "clk26m", + "nfi2x_sel", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "univpll_d5", + "syspll1_d2" +}; + +static const char * const pe2_mac_p0_parents[] = { + "clk26m", + "syspll1_d8", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "syspll3_d2" +}; + +static const char * const dpilvds_parents[] = { + "clk26m", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "clkfpc" +}; + +static const char * const hdcp_parents[] = { + "clk26m", + "syspll4_d2", + "syspll3_d4", + "univpll2_d4" +}; + +static const char * const hdcp_24m_parents[] = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll2_d8" +}; + +static const char * const rtc_parents[] = { + "clkrtc_int", + "clkrtc_ext", + "clk26m", + "univpll3_d8" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk26m_d2", + "syspll4_d4", + "univpll2_d8", + "univpll3_d4", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "etherpll_125m", + "syspll1_d4" +}; + +static const char * const apll_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8", + "apll1_d16", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8", + "apll2_d16", + "clk26m", + "clk26m" +}; + +static const char * const a1sys_hp_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const a2sys_hp_parents[] = { + "clk26m", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const asm_l_parents[] = { + "clk26m", + "univpll2_d4", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const i2so1_parents[] = { + "clk26m", + "apll1_ck", + "apll2_ck" +}; + +static const char * const ether_125m_parents[] = { + "clk26m", + "etherpll_125m", + "univpll3_d2" +}; + +static const char * const ether_50m_parents[] = { + "clk26m", + "etherpll_50m", + "univpll_d26", + "univpll3_d4" +}; + +static const char * const jpgdec_parents[] = { + "clk26m", + "univpll_d3", + "tvdpll_429m", + "vencpll_ck", + "syspll_d3", + "vcodecpll_ck", + "univpll1_d2", + "armca35pll_400m", + "tvdpll_429m_d2", + "tvdpll_429m_d4" +}; + +static const char * const spislv_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8", + "univpll1_d2", + "univpll_d5" +}; + +static const char * const ether_parents[] = { + "clk26m", + "etherpll_50m", + "univpll_d26" +}; + +static const char * const di_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "vencpll_ck", + "vencpll_d2", + "cvbs", + "cvbs_d2" +}; + +static const char * const tvd_parents[] = { + "clk26m", + "cvbs_d2", + "univpll2_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll_d26", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const msdc0p_aes_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll_d3", + "vcodecpll_ck" +}; + +static const char * const cmsys_parents[] = { + "clk26m", + "univpll_d3", + "syspll_d3", + "syspll1_d2", + "syspll2_d2" +}; + +static const char * const gcpu_parents[] = { + "clk26m", + "syspll_d3", + "syspll1_d2", + "univpll1_d2", + "univpll_d5", + "univpll3_d2", + "univpll_d3" +}; + +static const char * const aud_apll1_parents[] = { + "apll1", + "clkaud_ext_i_1" +}; + +static const char * const aud_apll2_parents[] = { + "apll2", + "clkaud_ext_i_2" +}; + +static const char * const audull_vtx_parents[] = { + "d2a_ulclk_6p5m", + "clkaud_ext_i_0" +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3, + 7, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1, + 15, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", + mm_parents, 0x040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", + pwm_parents, 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", + vdec_parents, 0x050, 8, 4, 15), + MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", + venc_parents, 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", + mfg_parents, 0x050, 24, 4, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", + camtg_parents, 0x060, 0, 4, 7), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", + uart_parents, 0x060, 8, 1, 15), + MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", + spi_parents, 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", + usb20_parents, 0x060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", + usb30_parents, 0x070, 0, 2, 7), + MUX_GATE(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc50_0_h_sel", + msdc50_0_h_parents, 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x070, 16, 4, 23), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, 0x070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", + msdc30_1_parents, 0x080, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", + msdc30_3_parents, 0x080, 8, 4, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", + audio_parents, 0x080, 16, 2, 23), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, 0x080, 24, 3, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", + pmicspi_parents, 0x090, 0, 3, 7), + MUX_GATE(CLK_TOP_DPILVDS1_SEL, "dpilvds1_sel", + dpilvds1_parents, 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", + atb_parents, 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", + nr_parents, 0x090, 24, 3, 31), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", + nfi2x_parents, 0x0a0, 0, 4, 7), + MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", + irda_parents, 0x0a0, 8, 2, 15), + MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", + cci400_parents, 0x0a0, 16, 3, 23), + MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", + aud_1_parents, 0x0a0, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", + aud_2_parents, 0x0b0, 0, 2, 7), + MUX_GATE(CLK_TOP_MEM_MFG_IN_AS_SEL, "mem_mfg_sel", + mem_mfg_parents, 0x0b0, 8, 2, 15), + MUX_GATE(CLK_TOP_AXI_MFG_IN_AS_SEL, "axi_mfg_sel", + axi_mfg_parents, 0x0b0, 16, 2, 23), + MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", + scam_parents, 0x0b0, 24, 2, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_NFIECC_SEL, "nfiecc_sel", + nfiecc_parents, 0x0c0, 0, 3, 7), + MUX_GATE(CLK_TOP_PE2_MAC_P0_SEL, "pe2_mac_p0_sel", + pe2_mac_p0_parents, 0x0c0, 8, 3, 15), + MUX_GATE(CLK_TOP_PE2_MAC_P1_SEL, "pe2_mac_p1_sel", + pe2_mac_p0_parents, 0x0c0, 16, 3, 23), + MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", + dpilvds_parents, 0x0c0, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(CLK_TOP_MSDC50_3_HCLK_SEL, "msdc50_3_h_sel", + msdc50_0_h_parents, 0x0d0, 0, 3, 7), + MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", + hdcp_parents, 0x0d0, 8, 2, 15), + MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", + hdcp_24m_parents, 0x0d0, 16, 2, 23), + MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x0d0, 24, 2, + 31, CLK_IS_CRITICAL), + /* CLK_CFG_10 */ + MUX_GATE(CLK_TOP_SPINOR_SEL, "spinor_sel", + spinor_parents, 0x500, 0, 4, 7), + MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", + apll_parents, 0x500, 8, 4, 15), + MUX_GATE(CLK_TOP_APLL2_SEL, "apll2_sel", + apll_parents, 0x500, 16, 4, 23), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", + a1sys_hp_parents, 0x500, 24, 3, 31), + /* CLK_CFG_11 */ + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", + a2sys_hp_parents, 0x510, 0, 3, 7), + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", + asm_l_parents, 0x510, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", + asm_l_parents, 0x510, 16, 2, 23), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", + asm_l_parents, 0x510, 24, 2, 31), + /* CLK_CFG_12 */ + MUX_GATE(CLK_TOP_I2SO1_SEL, "i2so1_sel", + i2so1_parents, 0x520, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SO2_SEL, "i2so2_sel", + i2so1_parents, 0x520, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SO3_SEL, "i2so3_sel", + i2so1_parents, 0x520, 16, 2, 23), + MUX_GATE(CLK_TOP_TDMO0_SEL, "tdmo0_sel", + i2so1_parents, 0x520, 24, 2, 31), + /* CLK_CFG_13 */ + MUX_GATE(CLK_TOP_TDMO1_SEL, "tdmo1_sel", + i2so1_parents, 0x530, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SI1_SEL, "i2si1_sel", + i2so1_parents, 0x530, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SI2_SEL, "i2si2_sel", + i2so1_parents, 0x530, 16, 2, 23), + MUX_GATE(CLK_TOP_I2SI3_SEL, "i2si3_sel", + i2so1_parents, 0x530, 24, 2, 31), + /* CLK_CFG_14 */ + MUX_GATE(CLK_TOP_ETHER_125M_SEL, "ether_125m_sel", + ether_125m_parents, 0x540, 0, 2, 7), + MUX_GATE(CLK_TOP_ETHER_50M_SEL, "ether_50m_sel", + ether_50m_parents, 0x540, 8, 2, 15), + MUX_GATE(CLK_TOP_JPGDEC_SEL, "jpgdec_sel", + jpgdec_parents, 0x540, 16, 4, 23), + MUX_GATE(CLK_TOP_SPISLV_SEL, "spislv_sel", + spislv_parents, 0x540, 24, 3, 31), + /* CLK_CFG_15 */ + MUX_GATE(CLK_TOP_ETHER_50M_RMII_SEL, "ether_sel", + ether_parents, 0x550, 0, 2, 7), + MUX_GATE(CLK_TOP_CAM2TG_SEL, "cam2tg_sel", + camtg_parents, 0x550, 8, 4, 15), + MUX_GATE(CLK_TOP_DI_SEL, "di_sel", + di_parents, 0x550, 16, 3, 23), + MUX_GATE(CLK_TOP_TVD_SEL, "tvd_sel", + tvd_parents, 0x550, 24, 2, 31), + /* CLK_CFG_16 */ + MUX_GATE(CLK_TOP_I2C_SEL, "i2c_sel", + i2c_parents, 0x560, 0, 3, 7), + MUX_GATE(CLK_TOP_PWM_INFRA_SEL, "pwm_infra_sel", + pwm_parents, 0x560, 8, 2, 15), + MUX_GATE(CLK_TOP_MSDC0P_AES_SEL, "msdc0p_aes_sel", + msdc0p_aes_parents, 0x560, 16, 2, 23), + MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", + cmsys_parents, 0x560, 24, 3, 31), + /* CLK_CFG_17 */ + MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", + gcpu_parents, 0x570, 0, 3, 7), + /* CLK_AUDDIV_4 */ + MUX(CLK_TOP_AUD_APLL1_SEL, "aud_apll1_sel", + aud_apll1_parents, 0x134, 0, 1), + MUX(CLK_TOP_AUD_APLL2_SEL, "aud_apll2_sel", + aud_apll2_parents, 0x134, 1, 1), + MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel", + audull_vtx_parents, 0x134, 31, 1), +}; + +static const char * const mcu_mp0_parents[] = { + "clk26m", + "armca35pll_ck", + "f_mp0_pll1_ck", + "f_mp0_pll2_ck" +}; + +static const char * const mcu_mp2_parents[] = { + "clk26m", + "armca72pll_ck", + "f_big_pll1_ck", + "f_big_pll2_ck" +}; + +static const char * const mcu_bus_parents[] = { + "clk26m", + "cci400_sel", + "f_bus_pll1_ck", + "f_bus_pll2_ck" +}; + +static struct mtk_composite mcu_muxes[] = { + /* mp0_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, + 9, 2, -1, CLK_IS_CRITICAL), + /* mp2_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, + 9, 2, -1, CLK_IS_CRITICAL), + /* bus_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, + 9, 2, -1, CLK_IS_CRITICAL), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL_DIV0, "apll_div0", "i2so1_sel", 0x124, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV1, "apll_div1", "i2so2_sel", 0x124, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV2, "apll_div2", "i2so3_sel", 0x124, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV3, "apll_div3", "tdmo0_sel", 0x124, 24, 8), + DIV_ADJ(CLK_TOP_APLL_DIV4, "apll_div4", "tdmo1_sel", 0x128, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV5, "apll_div5", "i2si1_sel", 0x128, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV6, "apll_div6", "i2si2_sel", 0x128, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8), +}; + +static const struct mtk_gate_regs top_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +#define GATE_TOP(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate top_clks[] = { + GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), + GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), + GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), + GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), + GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), + GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), + GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), + GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x40, +}; + +#define GATE_INFRA(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), + GATE_INFRA(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "spi_sel", 24), + GATE_INFRA(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "spislv_sel", 25), + GATE_INFRA(CLK_INFRA_AO_UART5, "infra_ao_uart5", "axi_sel", 26), +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xc, + .clr_ofs = 0x14, + .sta_ofs = 0x1c, +}; + +static const struct mtk_gate_regs peri2_cg_regs = { + .set_ofs = 0x42c, + .clr_ofs = 0x42c, + .sta_ofs = 0x42c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_NFI, "per_nfi", + "axi_sel", 0), + GATE_PERI0(CLK_PERI_THERM, "per_therm", + "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM0, "per_pwm0", + "pwm_sel", 2), + GATE_PERI0(CLK_PERI_PWM1, "per_pwm1", + "pwm_sel", 3), + GATE_PERI0(CLK_PERI_PWM2, "per_pwm2", + "pwm_sel", 4), + GATE_PERI0(CLK_PERI_PWM3, "per_pwm3", + "pwm_sel", 5), + GATE_PERI0(CLK_PERI_PWM4, "per_pwm4", + "pwm_sel", 6), + GATE_PERI0(CLK_PERI_PWM5, "per_pwm5", + "pwm_sel", 7), + GATE_PERI0(CLK_PERI_PWM6, "per_pwm6", + "pwm_sel", 8), + GATE_PERI0(CLK_PERI_PWM7, "per_pwm7", + "pwm_sel", 9), + GATE_PERI0(CLK_PERI_PWM, "per_pwm", + "pwm_sel", 10), + GATE_PERI0(CLK_PERI_AP_DMA, "per_ap_dma", + "axi_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_0, "per_msdc30_0", + "msdc50_0_sel", 14), + GATE_PERI0(CLK_PERI_MSDC30_1, "per_msdc30_1", + "msdc30_1_sel", 15), + GATE_PERI0(CLK_PERI_MSDC30_2, "per_msdc30_2", + "msdc30_2_sel", 16), + GATE_PERI0(CLK_PERI_MSDC30_3, "per_msdc30_3", + "msdc30_3_sel", 17), + GATE_PERI0(CLK_PERI_UART0, "per_uart0", + "uart_sel", 20), + GATE_PERI0(CLK_PERI_UART1, "per_uart1", + "uart_sel", 21), + GATE_PERI0(CLK_PERI_UART2, "per_uart2", + "uart_sel", 22), + GATE_PERI0(CLK_PERI_UART3, "per_uart3", + "uart_sel", 23), + GATE_PERI0(CLK_PERI_I2C0, "per_i2c0", + "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C1, "per_i2c1", + "axi_sel", 25), + GATE_PERI0(CLK_PERI_I2C2, "per_i2c2", + "axi_sel", 26), + GATE_PERI0(CLK_PERI_I2C3, "per_i2c3", + "axi_sel", 27), + GATE_PERI0(CLK_PERI_I2C4, "per_i2c4", + "axi_sel", 28), + GATE_PERI0(CLK_PERI_AUXADC, "per_auxadc", + "ltepll_fs26m", 29), + GATE_PERI0(CLK_PERI_SPI0, "per_spi0", + "spi_sel", 30), + /* PERI1 */ + GATE_PERI1(CLK_PERI_SPI, "per_spi", + "spinor_sel", 1), + GATE_PERI1(CLK_PERI_I2C5, "per_i2c5", + "axi_sel", 3), + GATE_PERI1(CLK_PERI_SPI2, "per_spi2", + "spi_sel", 5), + GATE_PERI1(CLK_PERI_SPI3, "per_spi3", + "spi_sel", 6), + GATE_PERI1(CLK_PERI_SPI5, "per_spi5", + "spi_sel", 8), + GATE_PERI1(CLK_PERI_UART4, "per_uart4", + "uart_sel", 9), + GATE_PERI1(CLK_PERI_SFLASH, "per_sflash", + "uart_sel", 11), + GATE_PERI1(CLK_PERI_GMAC, "per_gmac", + "uart_sel", 12), + GATE_PERI1(CLK_PERI_PCIE0, "per_pcie0", + "uart_sel", 14), + GATE_PERI1(CLK_PERI_PCIE1, "per_pcie1", + "uart_sel", 15), + GATE_PERI1(CLK_PERI_GMAC_PCLK, "per_gmac_pclk", + "uart_sel", 16), + /* PERI2 */ + GATE_PERI2(CLK_PERI_MSDC50_0_EN, "per_msdc50_0_en", + "msdc50_0_sel", 0), + GATE_PERI2(CLK_PERI_MSDC30_1_EN, "per_msdc30_1_en", + "msdc30_1_sel", 1), + GATE_PERI2(CLK_PERI_MSDC30_2_EN, "per_msdc30_2_en", + "msdc30_2_sel", 2), + GATE_PERI2(CLK_PERI_MSDC30_3_EN, "per_msdc30_3_en", + "msdc30_3_sel", 3), + GATE_PERI2(CLK_PERI_MSDC50_0_HCLK_EN, "per_msdc50_0_h", + "msdc50_0_h_sel", 4), + GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h", + "msdc50_3_h_sel", 5), +}; + +#define MT2712_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT2712_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT2712_RST_BAR, \ + .fmax = MT2712_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, \ + _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ + _pcw_shift, NULL) + +static const struct mtk_pll_div_table armca35pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1202500000 }, + { .div = 2, .freq = 500500000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table armca72pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 994500000 }, + { .div = 2, .freq = 520000000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1001000000 }, + { .div = 2, .freq = 601250000 }, + { .div = 3, .freq = 250250000 }, + { .div = 4, .freq = 125125000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000101, + HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000101, + HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000101, + 0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000101, + 0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000101, + 0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000101, + 0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000101, + 0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0), + PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000101, + 0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000101, + 0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0), + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000101, + 0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000101, + 0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000101, + 0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, + mmpll_div_table), + PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000101, + HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, + armca35pll_div_table), + PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000101, + 0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, + armca72pll_div_table), + PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000101, + 0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0), +}; + +static int clk_mt2712_apmixed_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static struct clk_onecell_data *top_clk_data; + +static void clk_mt2712_top_init_early(struct device_node *node) +{ + int r, i; + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + for (i = 0; i < CLK_TOP_NR_CLK; i++) + top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + } + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} + +CLK_OF_DECLARE_DRIVER(mt2712_topckgen, "mediatek,mt2712-topckgen", + clk_mt2712_top_init_early); + +static int clk_mt2712_top_probe(struct platform_device *pdev) +{ + int r, i; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + } else { + for (i = 0; i < CLK_TOP_NR_CLK; i++) { + if (top_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) + top_clk_data->clks[i] = ERR_PTR(-ENOENT); + } + } + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + top_clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static int clk_mt2712_infra_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0x30); + + return r; +} + +static int clk_mt2712_peri_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0); + + return r; +} + +static int clk_mt2712_mcu_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + + mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + &mt2712_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712[] = { + { + .compatible = "mediatek,mt2712-apmixedsys", + .data = clk_mt2712_apmixed_probe, + }, { + .compatible = "mediatek,mt2712-topckgen", + .data = clk_mt2712_top_probe, + }, { + .compatible = "mediatek,mt2712-infracfg", + .data = clk_mt2712_infra_probe, + }, { + .compatible = "mediatek,mt2712-pericfg", + .data = clk_mt2712_peri_probe, + }, { + .compatible = "mediatek,mt2712-mcucfg", + .data = clk_mt2712_mcu_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt2712_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r != 0) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2712_drv = { + .probe = clk_mt2712_probe, + .driver = { + .name = "clk-mt2712", + .owner = THIS_MODULE, + .of_match_table = of_match_clk_mt2712, + }, +}; + +static int __init clk_mt2712_init(void) +{ + return platform_driver_register(&clk_mt2712_drv); +} + +arch_initcall(clk_mt2712_init); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index f5d6b70ce189..f48df75cc901 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -207,6 +207,8 @@ struct mtk_pll_data { uint32_t en_mask; uint32_t pd_reg; uint32_t tuner_reg; + uint32_t tuner_en_reg; + uint8_t tuner_en_bit; int pd_shift; unsigned int flags; const struct clk_ops *ops; diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index a409142e9346..3c546bae6955 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -47,6 +47,7 @@ struct mtk_clk_pll { void __iomem *pd_addr; void __iomem *pwr_addr; void __iomem *tuner_addr; + void __iomem *tuner_en_addr; void __iomem *pcw_addr; const struct mtk_pll_data *data; }; @@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw) r |= pll->data->en_mask; writel(r, pll->base_addr + REG_CON0); - if (pll->tuner_addr) { + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; writel(r, pll->tuner_addr); } @@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw) writel(r, pll->base_addr + REG_CON0); } - if (pll->tuner_addr) { + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; writel(r, pll->tuner_addr); } @@ -297,6 +304,8 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, pll->pcw_addr = base + data->pcw_reg; if (data->tuner_reg) pll->tuner_addr = base + data->tuner_reg; + if (data->tuner_en_reg) + pll->tuner_en_addr = base + data->tuner_en_reg; pll->hw.init = &init; pll->data = data; -- cgit v1.2.3 From 5ef288d42aefef63f728116818a097b3caf000a5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 15 Sep 2017 21:28:30 +0200 Subject: clk: mediatek: mark mtk_infrasys_init_early __init On gcc-4.6, we get a harmless link-time warning: WARNING: vmlinux.o(.text.unlikely+0x196a0): Section mismatch in reference from the function mtk_infrasys_init_early() to the function .init.text:mtk_clk_register_cpumuxes() The function mtk_infrasys_init_early() references the function __init mtk_clk_register_cpumuxes(). This is often because mtk_infrasys_init_early lacks a __init annotation or the annotation of mtk_clk_register_cpumuxes is wrong. Newer compilers inline this function so they don't warn, but marking it __init is the right solution for all versions. Fixes: e9862118272a ("clk: mediatek: Add MT2701 clock support") Signed-off-by: Arnd Bergmann Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt2701.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index 9598889f972b..8e7f16fd87c9 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -750,7 +750,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = { static struct clk_onecell_data *infra_clk_data; -static void mtk_infrasys_init_early(struct device_node *node) +static void __init mtk_infrasys_init_early(struct device_node *node) { int r, i; -- cgit v1.2.3 From c955bf3998efa3355790a4d8c82874582f1bc727 Mon Sep 17 00:00:00 2001 From: Chen Zhong Date: Thu, 5 Oct 2017 11:50:23 +0800 Subject: clk: mediatek: add the option for determining PLL source clock Since the previous setup always sets the PLL using crystal 26MHz, this doesn't always happen in every MediaTek platform. So the patch added flexibility for assigning extra member for determining the PLL source clock. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mtk.h | 1 + drivers/clk/mediatek/clk-pll.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index f48df75cc901..f10250dcece4 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -218,6 +218,7 @@ struct mtk_pll_data { uint32_t pcw_reg; int pcw_shift; const struct mtk_pll_div_table *div_table; + const char *parent_name; }; void mtk_clk_register_plls(struct device_node *node, diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 3c546bae6955..f54e4015b0b1 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -312,7 +312,10 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, init.name = data->name; init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; init.ops = &mtk_pll_ops; - init.parent_names = &parent_name; + if (data->parent_name) + init.parent_names = &data->parent_name; + else + init.parent_names = &parent_name; init.num_parents = 1; clk = clk_register(NULL, &pll->hw); -- cgit v1.2.3 From 2fc0a509e4ee858a450f28a4efb430835004dd70 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 5 Oct 2017 11:50:24 +0800 Subject: clk: mediatek: add clock support for MT7622 SoC Add all supported clocks exported from every susbystem found on MT7622 SoC such as topckgen, apmixedsys, infracfg, pericfg , pciessys, ssusbsys, ethsys and audsys. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/Kconfig | 30 ++ drivers/clk/mediatek/Makefile | 4 + drivers/clk/mediatek/clk-mt7622-aud.c | 195 +++++++++ drivers/clk/mediatek/clk-mt7622-eth.c | 156 +++++++ drivers/clk/mediatek/clk-mt7622-hif.c | 169 ++++++++ drivers/clk/mediatek/clk-mt7622.c | 780 ++++++++++++++++++++++++++++++++++ 6 files changed, 1334 insertions(+) create mode 100644 drivers/clk/mediatek/clk-mt7622-aud.c create mode 100644 drivers/clk/mediatek/clk-mt7622-eth.c create mode 100644 drivers/clk/mediatek/clk-mt7622-hif.c create mode 100644 drivers/clk/mediatek/clk-mt7622.c (limited to 'drivers/clk') diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 300dbb551bf7..59dc0aad553c 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -132,6 +132,36 @@ config COMMON_CLK_MT6797_VENCSYS ---help--- This driver supports Mediatek MT6797 vencsys clocks. +config COMMON_CLK_MT7622 + bool "Clock driver for MediaTek MT7622" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + ---help--- + This driver supports MediaTek MT7622 basic clocks and clocks + required for various periperals found on MediaTek. + +config COMMON_CLK_MT7622_ETHSYS + bool "Clock driver for MediaTek MT7622 ETHSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver add support for clocks for Ethernet and SGMII + required on MediaTek MT7622 SoC. + +config COMMON_CLK_MT7622_HIFSYS + bool "Clock driver for MediaTek MT7622 HIFSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver supports MediaTek MT7622 HIFSYS clocks providing + to PCI-E and USB. + +config COMMON_CLK_MT7622_AUDSYS + bool "Clock driver for MediaTek MT7622 AUDSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver supports MediaTek MT7622 AUDSYS clocks providing + to audio consumers such as I2S and TDM. + config COMMON_CLK_MT8135 bool "Clock driver for Mediatek MT8135" depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index a4e5c47c73a4..de8c3d0bb4ca 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -20,5 +20,9 @@ obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o +obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o +obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o +obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o +obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c new file mode 100644 index 000000000000..fad7d9fc53ba --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_AUDIO0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs audio2_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +static const struct mtk_gate_regs audio3_cg_regs = { + .set_ofs = 0x634, + .clr_ofs = 0x634, + .sta_ofs = 0x634, +}; + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2), + GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20), + GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21), + GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0), + GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1), + GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2), + GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3), + GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6), + GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7), + GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8), + GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9), + GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12), + GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13), + GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14), + GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15), + GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), + GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), + GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), + GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2), + GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3), + GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4), + GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5), + GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6), + GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7), + GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8), + GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9), + GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10), + GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11), + GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12), + GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13), + GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14), + GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15), + GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16), + GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17), + /* AUDIO3 */ + GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2), + GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3), + GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6), + GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), +}; + +static int clk_mt7622_audiosys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_aud[] = { + { + .compatible = "mediatek,mt7622-audsys", + .data = clk_mt7622_audiosys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_aud_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_aud_drv = { + .probe = clk_mt7622_aud_probe, + .driver = { + .name = "clk-mt7622-aud", + .of_match_table = of_match_clk_mt7622_aud, + }, +}; + +builtin_platform_driver(clk_mt7622_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c new file mode 100644 index 000000000000..6328127bbb3c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-eth.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_ETH(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = ð_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate eth_clks[] = { + GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5), + GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8), + GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9), +}; + +static const struct mtk_gate_regs sgmii_cg_regs = { + .set_ofs = 0xE4, + .clr_ofs = 0xE4, + .sta_ofs = 0xE4, +}; + +#define GATE_SGMII(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &sgmii_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii_clks[] = { + GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", + "ssusb_tx250m", 2), + GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", + "ssusb_eq_rx250m", 3), + GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", + "ssusb_cdr_ref", 4), + GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", + "ssusb_cdr_fb", 5), +}; + +static int clk_mt7622_ethsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + + mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_eth[] = { + { + .compatible = "mediatek,mt7622-ethsys", + .data = clk_mt7622_ethsys_init, + }, { + .compatible = "mediatek,mt7622-sgmiisys", + .data = clk_mt7622_sgmiisys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_eth_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_eth_drv = { + .probe = clk_mt7622_eth_probe, + .driver = { + .name = "clk-mt7622-eth", + .of_match_table = of_match_clk_mt7622_eth, + }, +}; + +builtin_platform_driver(clk_mt7622_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c new file mode 100644 index 000000000000..a6e8534276c6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-hif.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_PCIE(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &pcie_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +#define GATE_SSUSB(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ssusb_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate_regs pcie_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate_regs ssusb_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate ssusb_clks[] = { + GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", + "to_u2_phy_1p", 0), + GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1), + GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5), + GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6), + GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7), + GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8), +}; + +static const struct mtk_gate pcie_clks[] = { + GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12), + GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13), + GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14), + GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15), + GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16), + GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17), + GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18), + GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19), + GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20), + GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21), + GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22), + GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23), + GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26), + GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27), + GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28), + GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29), + GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30), +}; + +static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + + mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static int clk_mt7622_pciesys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + + mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_hif[] = { + { + .compatible = "mediatek,mt7622-pciesys", + .data = clk_mt7622_pciesys_init, + }, { + .compatible = "mediatek,mt7622-ssusbsys", + .data = clk_mt7622_ssusbsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_hif_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_hif_drv = { + .probe = clk_mt7622_hif_probe, + .driver = { + .name = "clk-mt7622-hif", + .of_match_table = of_match_clk_mt7622_hif, + }, +}; + +builtin_platform_driver(clk_mt7622_hif_drv); diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c new file mode 100644 index 000000000000..92f7e32770c6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-cpumux.h" + +#include +#include /* for consumer */ + +#define MT7622_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7622_RST_BAR BIT(27) + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table, _parent_name) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT7622_RST_BAR, \ + .fmax = MT7622_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL, "clkxtal") + +#define GATE_APMIXED(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &apmixed_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +#define GATE_INFRA(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_TOP1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static DEFINE_SPINLOCK(mt7622_clk_lock); + +static const char * const infra_mux1_parents[] = { + "clkxtal", + "armpll", + "main_core_en", + "armpll" +}; + +static const char * const axi_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7" +}; + +static const char * const mem_parents[] = { + "clkxtal", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clkxtal", + "syspll1_d8" +}; + +static const char * const eth_parents[] = { + "clkxtal", + "syspll1_d2", + "univpll1_d2", + "syspll1_d4", + "univpll_d5", + "clk_null", + "univpll_d7" +}; + +static const char * const pwm_parents[] = { + "clkxtal", + "univpll2_d4" +}; + +static const char * const f10m_ref_parents[] = { + "clkxtal", + "syspll4_d16" +}; + +static const char * const nfi_infra_parents[] = { + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "univpll2_d8", + "syspll1_d8", + "univpll1_d8", + "syspll4_d2", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4" +}; + +static const char * const flash_parents[] = { + "clkxtal", + "univpll_d80_d4", + "syspll2_d8", + "syspll3_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll2_d4" +}; + +static const char * const uart_parents[] = { + "clkxtal", + "univpll2_d8" +}; + +static const char * const spi0_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll2_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const spi1_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll4_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const msdc30_0_parents[] = { + "clkxtal", + "univpll2_d16", + "univ48m" +}; + +static const char * const a1sys_hp_parents[] = { + "clkxtal", + "aud1pll_ck", + "aud2pll_ck", + "clkxtal" +}; + +static const char * const intdir_parents[] = { + "clkxtal", + "syspll_d2", + "univpll_d2", + "sgmiipll_ck" +}; + +static const char * const aud_intbus_parents[] = { + "clkxtal", + "syspll1_d4", + "syspll4_d2", + "syspll3_d2" +}; + +static const char * const pmicspi_parents[] = { + "clkxtal", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "univpll2_d16" +}; + +static const char * const atb_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5" +}; + +static const char * const audio_parents[] = { + "clkxtal", + "syspll3_d4", + "syspll4_d4", + "univpll1_d16" +}; + +static const char * const usb20_parents[] = { + "clkxtal", + "univpll3_d4", + "syspll1_d8", + "clkxtal" +}; + +static const char * const aud1_parents[] = { + "clkxtal", + "aud1pll_ck" +}; + +static const char * const aud2_parents[] = { + "clkxtal", + "aud2pll_ck" +}; + +static const char * const asm_l_parents[] = { + "clkxtal", + "syspll_d5", + "univpll2_d2", + "univpll2_d4" +}; + +static const char * const apll1_ck_parents[] = { + "aud1_sel", + "aud2_sel" +}; + +static const char * const peribus_ck_parents[] = { + "syspll1_d8", + "syspll1_d4" +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x128, + .clr_ofs = 0x128, + .sta_ofs = 0x128, +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xC, + .clr_ofs = 0x14, + .sta_ofs = 0x1C, +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, + PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001, + HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001, + HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001, + 0, 21, 0x0300, 1, 0, 0x0304, 0), + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001, + 0, 21, 0x0314, 1, 0, 0x0318, 0), + PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001, + 0, 31, 0x0324, 1, 0, 0x0328, 0), + PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001, + 0, 31, 0x0334, 1, 0, 0x0338, 0), + PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001, + 0, 21, 0x0344, 1, 0, 0x0348, 0), + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001, + 0, 21, 0x0358, 1, 0, 0x035C, 0), +}; + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5), +}; + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2), + GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5), + GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16), + GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18), + GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22), +}; + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", + 33333333), + FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", + 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4), + FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125), + FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1), + FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024), + FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1), + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), + FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), + FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320), + FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25), + FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1), + FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2), + FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1), + FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1), + FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2), + FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4), + FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1), +}; + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0), + GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1), + GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div", + 2), + GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div", + 3), + GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div", + 4), + GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div", + 5), + + /* TOP1 */ + GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0), + GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel", + 0x120, 24, 3), + DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel", + 0x120, 28, 3), + DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel", + 0x124, 0, 7), + DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel", + 0x124, 8, 7), + DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck", + 0x124, 16, 7), + DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel", + 0x124, 24, 7), + DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel", + 0x128, 8, 7), + DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel", + 0x128, 24, 7), +}; + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2), + GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3), + GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4), + GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5), + GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6), + GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7), + GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8), + GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9), + GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12), + GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17), + GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18), + GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19), + GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20), + GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21), + GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22), + GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23), + GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25), + GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26), + GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27), + GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28), + GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29), + GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30), + GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31), + + /* PERI1 */ + GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1), + GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2), +}; + +static struct mtk_composite infra_muxes[] __initdata = { + MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, + 0x000, 2, 2), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x040, 0, 3, 7), + MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x040, 8, 1, 15), + MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x040, 16, 1, 23), + MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 24, 3, 31), + + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, + 0x050, 8, 1, 15), + MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, + 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, + 0x050, 24, 3, 31), + + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + 0x060, 0, 1, 7), + MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, + 0x060, 8, 3, 15), + MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, + 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, + 0x060, 24, 3, 31), + + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, + 0x070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents, + 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents, + 0x070, 16, 2, 23), + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents, + 0x070, 24, 2, 31), + + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, + 0x080, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x080, 8, 2, 15), + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x080, 16, 3, 23), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents, + 0x080, 24, 2, 31), + + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, + 0x090, 0, 2, 7), + MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents, + 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, + 0x090, 24, 2, 31), + + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x0A0, 0, 1, 7), + MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x0A0, 8, 1, 15), + MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents, + 0x0A0, 16, 1, 23), + MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents, + 0x0A0, 24, 1, 31), + + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents, + 0x0B0, 0, 2, 7), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents, + 0x0B0, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents, + 0x0B0, 16, 2, 23), + + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents, + 0x120, 6, 1), + MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents, + 0x120, 7, 1), + MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents, + 0x120, 8, 1), + MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents, + 0x120, 9, 1), + MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents, + 0x120, 10, 1), + MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents, + 0x120, 11, 1), +}; + +static struct mtk_composite peri_muxes[] = { + /* PERI_GLOBALCON_CKSEL */ + MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1), +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + clk_data); + + clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + + return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +static int __init mtk_infrasys_init(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, + clk_data); + if (r) + return r; + + mtk_register_reset_controller(node, 1, 0x30); + + return 0; +} + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); + clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]); + + return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +static int mtk_pericfg_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7622_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + return r; + + clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]); + + mtk_register_reset_controller(node, 2, 0x0); + + return 0; +} + +static const struct of_device_id of_match_clk_mt7622[] = { + { + .compatible = "mediatek,mt7622-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + .compatible = "mediatek,mt7622-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt7622-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt7622-pericfg", + .data = mtk_pericfg_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_drv = { + .probe = clk_mt7622_probe, + .driver = { + .name = "clk-mt7622", + .of_match_table = of_match_clk_mt7622, + }, +}; + +static int clk_mt7622_init(void) +{ + return platform_driver_register(&clk_mt7622_drv); +} + +arch_initcall(clk_mt7622_init); -- cgit v1.2.3 From 908a543ac7cdf3aa8a283ec42cab3c16e2fc45a2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Sep 2017 18:19:18 +0200 Subject: clk: clk-gpio: Make GPIO clock provider use descriptors only After som grep:ing it turns out nothing in the kernel is really calling clk_[hw_]_register_gpio_[gate|mux](). All existing instances are just created directly from the device tree probe functions at the bottom of the clk-gpio.c clock provider file. This means we can change the signature of the function without any consequences! Everyone should be using GPIO descriptors now, so let's just go in and enforce that. This saves a bit of code since GPIO descriptors know inherently if they are active low so no need for the code keeping track of that. We leave it to the caller to come up with the GPIO descriptor. It is nowadays possible to do that even without a corresponding device, so no excuse not to pass them around. The one in-kernel user lifecycles it using devm_gpiod_get() in gpio_clk_driver_probe(). Cc: Sergej Sawazki Cc: Jyri Sarha Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 90 +++++++++++++++++--------------------------- include/linux/clk-provider.h | 12 +++--- 2 files changed, 41 insertions(+), 61 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 86b245746a6b..9d057073e110 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -95,14 +93,12 @@ const struct clk_ops clk_gpio_mux_ops = { EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags, - const struct clk_ops *clk_gpio_ops) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags, const struct clk_ops *clk_gpio_ops) { struct clk_gpio *clk_gpio; struct clk_hw *hw; struct clk_init_data init = {}; - unsigned long gpio_flags; int err; if (dev) @@ -113,24 +109,13 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, if (!clk_gpio) return ERR_PTR(-ENOMEM); - if (active_low) - gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH; - else - gpio_flags = GPIOF_OUT_INIT_LOW; - - if (dev) - err = devm_gpio_request_one(dev, gpio, gpio_flags, name); - else - err = gpio_request_one(gpio, gpio_flags, name); - if (err) { - if (err != -EPROBE_DEFER) - pr_err("%s: %s: Error requesting clock control gpio %u\n", - __func__, name, gpio); - if (!dev) - kfree(clk_gpio); - - return ERR_PTR(err); - } + /* + * Set to disabled no matter what: NOTE if the GPIO line is active low + * the GPIO descriptor knows this and will set it high to deassert the + * line. This assumes the GPIO descriptor has been requested using + * GPIOD_ASIS by the callers so we need to initialize it as disabled here. + */ + gpiod_set_value(gpiod, 0); init.name = name; init.ops = clk_gpio_ops; @@ -138,7 +123,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, init.parent_names = parent_names; init.num_parents = num_parents; - clk_gpio->gpiod = gpio_to_desc(gpio); + clk_gpio->gpiod = gpiod; clk_gpio->hw.init = &init; hw = &clk_gpio->hw; @@ -151,7 +136,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, return hw; if (!dev) { - gpiod_put(clk_gpio->gpiod); kfree(clk_gpio); } @@ -164,29 +148,27 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of this clock's parent - * @gpio: gpio number to gate this clock - * @active_low: true if gpio should be set to 0 to enable clock + * @gpiod: gpio descriptor to gate this clock * @flags: clock flags */ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags) { return clk_register_gpio(dev, name, (parent_name ? &parent_name : NULL), - (parent_name ? 1 : 0), gpio, active_low, flags, + (parent_name ? 1 : 0), gpiod, flags, &clk_gpio_gate_ops); } EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate); struct clk *clk_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags) { struct clk_hw *hw; - hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low, - flags); + hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags); if (IS_ERR(hw)) return ERR_CAST(hw); return hw->clk; @@ -199,13 +181,12 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate); * @name: name of this clock * @parent_names: names of this clock's parents * @num_parents: number of parents listed in @parent_names - * @gpio: gpio number to gate this clock - * @active_low: true if gpio should be set to 0 to enable clock + * @gpiod: gpio descriptor to gate this clock * @flags: clock flags */ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags) { if (num_parents != 2) { pr_err("mux-clock %s must have 2 parents\n", name); @@ -213,18 +194,18 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, } return clk_register_gpio(dev, name, parent_names, num_parents, - gpio, active_low, flags, &clk_gpio_mux_ops); + gpiod, flags, &clk_gpio_mux_ops); } EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux); struct clk *clk_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags) { struct clk_hw *hw; hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents, - gpio, active_low, flags); + gpiod, flags); if (IS_ERR(hw)) return ERR_CAST(hw); return hw->clk; @@ -236,10 +217,10 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; const char **parent_names, *gpio_name; unsigned int num_parents; - int gpio; - enum of_gpio_flags of_flags; + struct gpio_desc *gpiod; struct clk *clk; - bool active_low, is_mux; + bool is_mux; + int ret; num_parents = of_clk_get_parent_count(node); if (num_parents) { @@ -255,28 +236,27 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) is_mux = of_device_is_compatible(node, "gpio-mux-clock"); - gpio_name = is_mux ? "select-gpios" : "enable-gpios"; - gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags); - if (gpio < 0) { - if (gpio == -EPROBE_DEFER) + gpio_name = is_mux ? "select" : "enable"; + gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_ASIS); + if (IS_ERR(gpiod)) { + ret = PTR_ERR(gpiod); + if (ret == -EPROBE_DEFER) pr_debug("%s: %s: GPIOs not yet available, retry later\n", node->name, __func__); else - pr_err("%s: %s: Can't get '%s' DT property\n", + pr_err("%s: %s: Can't get '%s' named GPIO property\n", node->name, __func__, gpio_name); - return gpio; + return ret; } - active_low = of_flags & OF_GPIO_ACTIVE_LOW; - if (is_mux) clk = clk_register_gpio_mux(&pdev->dev, node->name, - parent_names, num_parents, gpio, active_low, 0); + parent_names, num_parents, gpiod, 0); else clk = clk_register_gpio_gate(&pdev->dev, node->name, - parent_names ? parent_names[0] : NULL, gpio, - active_low, 0); + parent_names ? parent_names[0] : NULL, gpiod, + 0); if (IS_ERR(clk)) return PTR_ERR(clk); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5100ec1b5d55..063d8cb9926f 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -682,10 +682,10 @@ struct clk_gpio { extern const struct clk_ops clk_gpio_gate_ops; struct clk *clk_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags); struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags); void clk_hw_unregister_gpio_gate(struct clk_hw *hw); @@ -701,11 +701,11 @@ void clk_hw_unregister_gpio_gate(struct clk_hw *hw); extern const struct clk_ops clk_gpio_mux_ops; struct clk *clk_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags); + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags); struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags); + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags); void clk_hw_unregister_gpio_mux(struct clk_hw *hw); /** -- cgit v1.2.3 From 1b5d1a58a51324b1b6c851abec3bf40bd539cbb2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Sep 2017 18:19:19 +0200 Subject: clk: clk-gpio: Request GPIO descriptor as LOW Requesting the GPIOD_OUT_LOW low will make sure the GPIO is deasserted when requested. The gpiolib core will make sure that if the GPIO line is active low, it will be logically driven high when deasserted, see drivers/gpiolib.c gpiod_configure_flags(). Cc: Sergej Sawazki Cc: Jyri Sarha Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 9d057073e110..151513c655c3 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -109,14 +109,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, if (!clk_gpio) return ERR_PTR(-ENOMEM); - /* - * Set to disabled no matter what: NOTE if the GPIO line is active low - * the GPIO descriptor knows this and will set it high to deassert the - * line. This assumes the GPIO descriptor has been requested using - * GPIOD_ASIS by the callers so we need to initialize it as disabled here. - */ - gpiod_set_value(gpiod, 0); - init.name = name; init.ops = clk_gpio_ops; init.flags = flags | CLK_IS_BASIC; @@ -237,7 +229,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) is_mux = of_device_is_compatible(node, "gpio-mux-clock"); gpio_name = is_mux ? "select" : "enable"; - gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_ASIS); + gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW); if (IS_ERR(gpiod)) { ret = PTR_ERR(gpiod); if (ret == -EPROBE_DEFER) -- cgit v1.2.3 From 0b910402cfa0d3b3de666d68d107b30bf13e164e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 17:23:04 +0200 Subject: clk: clk-mux: Delete an error message for a failed memory allocation Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring [sboyd@codeaurora.org: Cleanup commit text] Signed-off-by: Stephen Boyd --- drivers/clk/clk-mux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 16a3d5717f4e..1746dbf2f7ea 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -135,10 +135,8 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, /* allocate the mux */ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); - if (!mux) { - pr_err("%s: could not allocate mux clk\n", __func__); + if (!mux) return ERR_PTR(-ENOMEM); - } init.name = name; if (clk_mux_flags & CLK_MUX_READ_ONLY) -- cgit v1.2.3 From 1e28733e315e9ede15896600a475408d2a203a32 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 17:30:06 +0200 Subject: clk: clk-mux: Improve a size determination in clk_hw_register_mux_table() Replace the specification of a data structure by a pointer dereference as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 1746dbf2f7ea..39cabe157163 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -134,7 +134,7 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, } /* allocate the mux */ - mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); + mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From de8cd467e413906265eaa1f8af8d2da0f0d63c40 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 19:30:46 +0200 Subject: clk: clk-u300: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-u300.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index ec8aafda6e24..e524c3775264 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -703,11 +703,9 @@ syscon_clk_register(struct device *dev, const char *name, int ret; sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL); - if (!sclk) { - pr_err("could not allocate syscon clock %s\n", - name); + if (!sclk) return ERR_PTR(-ENOMEM); - } + init.name = name; init.ops = &syscon_clk_ops; init.flags = flags; @@ -1124,11 +1122,9 @@ mclk_clk_register(struct device *dev, const char *name, int ret; mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL); - if (!mclk) { - pr_err("could not allocate MMC/SD clock %s\n", - name); + if (!mclk) return ERR_PTR(-ENOMEM); - } + init.name = "mclk"; init.ops = &mclk_ops; init.flags = 0; -- cgit v1.2.3 From 27f8a53a9decfd7ad785543eb4e2c3d44434c01e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 19:33:02 +0200 Subject: clk: clk-u300: Improve sizeof() usage Replace the specification of data structures by pointer dereferences as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-u300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index e524c3775264..ae78461c7836 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -702,7 +702,7 @@ syscon_clk_register(struct device *dev, const char *name, struct clk_init_data init; int ret; - sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL); + sclk = kzalloc(sizeof(*sclk), GFP_KERNEL); if (!sclk) return ERR_PTR(-ENOMEM); @@ -1121,7 +1121,7 @@ mclk_clk_register(struct device *dev, const char *name, struct clk_init_data init; int ret; - mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL); + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL); if (!mclk) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From e6b332ab7dcfb3119dcd513b973c182249c33717 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 19:46:51 +0200 Subject: clk: clk-u300: Add some spaces for better code readability Use space characters at some source code places according to the Linux coding style convention. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-u300.c | 64 +++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index ae78461c7836..b36ca3a14c42 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -229,15 +229,15 @@ #define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0) #define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E) #define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S0CCR_SEL_MCLK (0x8<<1) -#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA<<1) -#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC<<1) -#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD<<1) -#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE<<1) -#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0<<1) -#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2<<1) -#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4<<1) -#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6<<1) +#define U300_SYSCON_S0CCR_SEL_MCLK (0x8 << 1) +#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA << 1) +#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC << 1) +#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD << 1) +#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE << 1) +#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0 << 1) +#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2 << 1) +#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4 << 1) +#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6 << 1) /* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */ #define U300_SYSCON_S1CCR (0x124) #define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF) @@ -247,15 +247,15 @@ #define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0) #define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E) #define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S1CCR_SEL_MCLK (0x8<<1) -#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA<<1) -#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC<<1) -#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD<<1) -#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE<<1) -#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0<<1) -#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2<<1) -#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4<<1) -#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6<<1) +#define U300_SYSCON_S1CCR_SEL_MCLK (0x8 << 1) +#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA << 1) +#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC << 1) +#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD << 1) +#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE << 1) +#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0 << 1) +#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2 << 1) +#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4 << 1) +#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6 << 1) /* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */ #define U300_SYSCON_S2CCR (0x128) #define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF) @@ -266,15 +266,15 @@ #define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0) #define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E) #define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S2CCR_SEL_MCLK (0x8<<1) -#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA<<1) -#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC<<1) -#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD<<1) -#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE<<1) -#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0<<1) -#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2<<1) -#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4<<1) -#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6<<1) +#define U300_SYSCON_S2CCR_SEL_MCLK (0x8 << 1) +#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA << 1) +#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC << 1) +#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD << 1) +#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE << 1) +#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0 << 1) +#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2 << 1) +#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4 << 1) +#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6 << 1) /* SC_PLL_IRQ_CONTROL 16bit (R/W) */ #define U300_SYSCON_PICR (0x0130) #define U300_SYSCON_PICR_MASK (0x00FF) @@ -568,14 +568,14 @@ syscon_clk_recalc_rate(struct clk_hw *hw, struct clk_syscon *sclk = to_syscon(hw); u16 perf = syscon_get_perf(); - switch(sclk->clk_val) { + switch (sclk->clk_val) { case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN: case U300_SYSCON_SBCER_I2C0_CLK_EN: case U300_SYSCON_SBCER_I2C1_CLK_EN: case U300_SYSCON_SBCER_MMC_CLK_EN: case U300_SYSCON_SBCER_SPI_CLK_EN: /* The FAST clocks have one progression */ - switch(perf) { + switch (perf) { case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: return 13000000; @@ -586,7 +586,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw, case U300_SYSCON_SBCER_NANDIF_CLK_EN: case U300_SYSCON_SBCER_XGAM_CLK_EN: /* AMBA interconnect peripherals */ - switch(perf) { + switch (perf) { case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: return 6500000; @@ -598,7 +598,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw, case U300_SYSCON_SBCER_SEMI_CLK_EN: case U300_SYSCON_SBCER_EMIF_CLK_EN: /* EMIF speeds */ - switch(perf) { + switch (perf) { case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: return 13000000; @@ -609,7 +609,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw, } case U300_SYSCON_SBCER_CPU_CLK_EN: /* And the fast CPU clock */ - switch(perf) { + switch (perf) { case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: return 13000000; -- cgit v1.2.3 From bb208f211c152d3d398eed95b4e5e5d8345457cb Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 19:57:50 +0200 Subject: clk: clk-u300: Fix a typo in two comment lines Add a missing character in these descriptions. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-u300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index b36ca3a14c42..7b3e1921771f 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -256,7 +256,7 @@ #define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2 << 1) #define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4 << 1) #define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6 << 1) -/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */ +/* SYS_2_CLK_CONTROL third clock control 16 bit (R/W) */ #define U300_SYSCON_S2CCR (0x128) #define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF) #define U300_SYSCON_S2CCR_CLK_STEAL (0x8000) @@ -378,7 +378,7 @@ * +- ISP Image Signal Processor (U335 only) * +- CDS (U335 only) * +- DMA Direct Memory Access Controller - * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL) + * +- AAIF APP/ACC Interface (Mobile Scalable Link, MSL) * +- APEX * +- VIDEO_ENC AVE2/3 Video Encoder * +- XGAM Graphics Accelerator Controller -- cgit v1.2.3 From e335545f5d864c47768e932e08667480667d9e97 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 21:19:19 +0200 Subject: clk: clk-xgene: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 4c75821a3933..3cc84a65f686 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -146,10 +146,8 @@ static struct clk *xgene_register_clk_pll(struct device *dev, /* allocate the APM clock structure */ apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL); - if (!apmclk) { - pr_err("%s: could not allocate APM clk\n", __func__); + if (!apmclk) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &xgene_clk_pll_ops; @@ -650,10 +648,8 @@ static struct clk *xgene_register_clk(struct device *dev, /* allocate the APM clock structure */ apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL); - if (!apmclk) { - pr_err("%s: could not allocate APM clk\n", __func__); + if (!apmclk) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &xgene_clk_ops; -- cgit v1.2.3 From 62c73ed5bf6372bd8417897ea9dcaf1d50d50de6 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 21:27:52 +0200 Subject: clk: clk-xgene: Adjust six checks for null pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script “checkpatch.pl” pointed information out like the following. Comparison to NULL could be written ... Thus fix the affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 3cc84a65f686..531b030d4d4e 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -189,7 +189,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty int version = xgene_pllclk_version(np); reg = of_iomap(np, 0); - if (reg == NULL) { + if (!reg) { pr_err("Unable to map CSR register for %pOF\n", np); return; } @@ -465,7 +465,7 @@ static int xgene_clk_enable(struct clk_hw *hw) if (pclk->lock) spin_lock_irqsave(pclk->lock, flags); - if (pclk->param.csr_reg != NULL) { + if (pclk->param.csr_reg) { pr_debug("%s clock enabled\n", clk_hw_get_name(hw)); /* First enable the clock */ data = xgene_clk_read(pclk->param.csr_reg + @@ -505,7 +505,7 @@ static void xgene_clk_disable(struct clk_hw *hw) if (pclk->lock) spin_lock_irqsave(pclk->lock, flags); - if (pclk->param.csr_reg != NULL) { + if (pclk->param.csr_reg) { pr_debug("%s clock disabled\n", clk_hw_get_name(hw)); /* First put the CSR in reset */ data = xgene_clk_read(pclk->param.csr_reg + @@ -531,7 +531,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw) struct xgene_clk *pclk = to_xgene_clk(hw); u32 data = 0; - if (pclk->param.csr_reg != NULL) { + if (pclk->param.csr_reg) { pr_debug("%s clock checking\n", clk_hw_get_name(hw)); data = xgene_clk_read(pclk->param.csr_reg + pclk->param.reg_clk_offset); @@ -540,7 +540,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw) "disabled"); } - if (pclk->param.csr_reg == NULL) + if (!pclk->param.csr_reg) return 1; return data & pclk->param.reg_clk_mask ? 1 : 0; } @@ -705,7 +705,7 @@ static void __init xgene_devclk_init(struct device_node *np) break; } map_res = of_iomap(np, i); - if (map_res == NULL) { + if (!map_res) { pr_err("Unable to map resource %d for %pOF\n", i, np); goto err; } -- cgit v1.2.3 From 1cc36f73005427c7a74b0fdf0177cd0bf981e9ff Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 22:25:38 +0200 Subject: clk: mmp: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-frac.c | 4 +--- drivers/clk/mmp/clk-gate.c | 4 +--- drivers/clk/mmp/clk-mix.c | 9 +-------- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 584a9927993b..98dfb9568d4f 100644 --- a/drivers/clk/mmp/clk-frac.c +++ b/drivers/clk/mmp/clk-frac.c @@ -172,10 +172,8 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name, } factor = kzalloc(sizeof(*factor), GFP_KERNEL); - if (!factor) { - pr_err("%s: could not allocate factor clk\n", __func__); + if (!factor) return ERR_PTR(-ENOMEM); - } /* struct clk_aux assignments */ factor->base = base; diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c index d20cd3431ac2..7355595c42e2 100644 --- a/drivers/clk/mmp/clk-gate.c +++ b/drivers/clk/mmp/clk-gate.c @@ -103,10 +103,8 @@ struct clk *mmp_clk_register_gate(struct device *dev, const char *name, /* allocate the gate */ gate = kzalloc(sizeof(*gate), GFP_KERNEL); - if (!gate) { - pr_err("%s:%s could not allocate gate clk\n", __func__, name); + if (!gate) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &mmp_clk_gate_ops; diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c index c554833cffc5..1ae532df20f7 100644 --- a/drivers/clk/mmp/clk-mix.c +++ b/drivers/clk/mmp/clk-mix.c @@ -451,11 +451,8 @@ struct clk *mmp_clk_register_mix(struct device *dev, size_t table_bytes; mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (!mix) { - pr_err("%s:%s: could not allocate mmp mix clk\n", - __func__, name); + if (!mix) return ERR_PTR(-ENOMEM); - } init.name = name; init.flags = flags | CLK_GET_RATE_NOCACHE; @@ -468,8 +465,6 @@ struct clk *mmp_clk_register_mix(struct device *dev, table_bytes = sizeof(*config->table) * config->table_size; mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL); if (!mix->table) { - pr_err("%s:%s: could not allocate mmp mix table\n", - __func__, name); kfree(mix); return ERR_PTR(-ENOMEM); } @@ -481,8 +476,6 @@ struct clk *mmp_clk_register_mix(struct device *dev, mix->mux_table = kmemdup(config->mux_table, table_bytes, GFP_KERNEL); if (!mix->mux_table) { - pr_err("%s:%s: could not allocate mmp mix mux-table\n", - __func__, name); kfree(mix->table); kfree(mix); return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From e9baa279949fff9f78f3ad0e1606f7b148746765 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 22:33:18 +0200 Subject: clk: mmp: Use common error handling code in mmp_clk_register_mix() Add a jump target so that a bit of exception handling can be better reused at the end of this function. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-mix.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c index 1ae532df20f7..b2471fb369f1 100644 --- a/drivers/clk/mmp/clk-mix.c +++ b/drivers/clk/mmp/clk-mix.c @@ -464,10 +464,9 @@ struct clk *mmp_clk_register_mix(struct device *dev, if (config->table) { table_bytes = sizeof(*config->table) * config->table_size; mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL); - if (!mix->table) { - kfree(mix); - return ERR_PTR(-ENOMEM); - } + if (!mix->table) + goto free_mix; + mix->table_size = config->table_size; } @@ -477,8 +476,7 @@ struct clk *mmp_clk_register_mix(struct device *dev, GFP_KERNEL); if (!mix->mux_table) { kfree(mix->table); - kfree(mix); - return ERR_PTR(-ENOMEM); + goto free_mix; } } @@ -502,4 +500,8 @@ struct clk *mmp_clk_register_mix(struct device *dev, } return clk; + +free_mix: + kfree(mix); + return ERR_PTR(-ENOMEM); } -- cgit v1.2.3 From 7a3aad90d331de9b78ea8d292bb4fd4f9ecdfd75 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 09:00:21 +0200 Subject: clk: mmp: Adjust checks for NULL pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script “checkpatch.pl” pointed information out like the following: Comparison to NULL could be written !... Thus fix the affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-mix.c | 4 ++-- drivers/clk/mmp/clk-mmp2.c | 6 +++--- drivers/clk/mmp/clk-pxa168.c | 6 +++--- drivers/clk/mmp/clk-pxa910.c | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c index b2471fb369f1..90814b2613c0 100644 --- a/drivers/clk/mmp/clk-mix.c +++ b/drivers/clk/mmp/clk-mix.c @@ -229,7 +229,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw, parent_rate = clk_hw_get_rate(parent); mix_rate = parent_rate / item->divisor; gap = abs(mix_rate - req->rate); - if (parent_best == NULL || gap < gap_best) { + if (!parent_best || gap < gap_best) { parent_best = parent; parent_rate_best = parent_rate; mix_rate_best = mix_rate; @@ -247,7 +247,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw, div = _get_div(mix, j); mix_rate = parent_rate / div; gap = abs(mix_rate - req->rate); - if (parent_best == NULL || gap < gap_best) { + if (!parent_best || gap < gap_best) { parent_best = parent; parent_rate_best = parent_rate; mix_rate_best = mix_rate; diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c index 038023483b98..7460031714da 100644 --- a/drivers/clk/mmp/clk-mmp2.c +++ b/drivers/clk/mmp/clk-mmp2.c @@ -83,19 +83,19 @@ void __init mmp2_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, void __iomem *apbc_base; mpmu_base = ioremap(mpmu_phys, SZ_4K); - if (mpmu_base == NULL) { + if (!mpmu_base) { pr_err("error to ioremap MPMU base\n"); return; } apmu_base = ioremap(apmu_phys, SZ_4K); - if (apmu_base == NULL) { + if (!apmu_base) { pr_err("error to ioremap APMU base\n"); return; } apbc_base = ioremap(apbc_phys, SZ_4K); - if (apbc_base == NULL) { + if (!apbc_base) { pr_err("error to ioremap APBC base\n"); return; } diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c index a9ef9209532a..8e2551ab8462 100644 --- a/drivers/clk/mmp/clk-pxa168.c +++ b/drivers/clk/mmp/clk-pxa168.c @@ -75,19 +75,19 @@ void __init pxa168_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, void __iomem *apbc_base; mpmu_base = ioremap(mpmu_phys, SZ_4K); - if (mpmu_base == NULL) { + if (!mpmu_base) { pr_err("error to ioremap MPMU base\n"); return; } apmu_base = ioremap(apmu_phys, SZ_4K); - if (apmu_base == NULL) { + if (!apmu_base) { pr_err("error to ioremap APMU base\n"); return; } apbc_base = ioremap(apbc_phys, SZ_4K); - if (apbc_base == NULL) { + if (!apbc_base) { pr_err("error to ioremap APBC base\n"); return; } diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c index a520cf7702a1..7a7965141918 100644 --- a/drivers/clk/mmp/clk-pxa910.c +++ b/drivers/clk/mmp/clk-pxa910.c @@ -74,25 +74,25 @@ void __init pxa910_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, void __iomem *apbc_base; mpmu_base = ioremap(mpmu_phys, SZ_4K); - if (mpmu_base == NULL) { + if (!mpmu_base) { pr_err("error to ioremap MPMU base\n"); return; } apmu_base = ioremap(apmu_phys, SZ_4K); - if (apmu_base == NULL) { + if (!apmu_base) { pr_err("error to ioremap APMU base\n"); return; } apbcp_base = ioremap(apbcp_phys, SZ_4K); - if (apbcp_base == NULL) { + if (!apbcp_base) { pr_err("error to ioremap APBC extension base\n"); return; } apbc_base = ioremap(apbc_phys, SZ_4K); - if (apbc_base == NULL) { + if (!apbc_base) { pr_err("error to ioremap APBC base\n"); return; } -- cgit v1.2.3 From f80c8a29f94faf6d4a2a3b25d4473d62edbd7aab Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 19:14:01 +0200 Subject: clk: ti: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Stephen Boyd --- drivers/clk/ti/divider.c | 4 +--- drivers/clk/ti/mux.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 88f04a4cb890..77f93f6d2806 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -292,10 +292,8 @@ static struct clk *_register_divider(struct device *dev, const char *name, /* allocate the divider */ div = kzalloc(sizeof(*div), GFP_KERNEL); - if (!div) { - pr_err("%s: could not allocate divider clk\n", __func__); + if (!div) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &ti_clk_divider_ops; diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index 18c267b38461..d4705803f3d3 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -108,10 +108,8 @@ static struct clk *_register_mux(struct device *dev, const char *name, /* allocate the mux */ mux = kzalloc(sizeof(*mux), GFP_KERNEL); - if (!mux) { - pr_err("%s: could not allocate mux clk\n", __func__); + if (!mux) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &ti_clk_mux_ops; -- cgit v1.2.3 From 63b1a5d75090ac41369d06d609d3268dbf16d41f Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 18:00:21 +0200 Subject: clk: spear: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 4 +--- drivers/clk/spear/clk-frac-synth.c | 4 +--- drivers/clk/spear/clk-gpt-synth.c | 4 +--- drivers/clk/spear/clk-vco-pll.c | 8 ++------ 4 files changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index f271c350ef94..ee7a7c043e3b 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -149,10 +149,8 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name, } aux = kzalloc(sizeof(*aux), GFP_KERNEL); - if (!aux) { - pr_err("could not allocate aux clk\n"); + if (!aux) return ERR_PTR(-ENOMEM); - } /* struct clk_aux assignments */ if (!masks) diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c index 58d678b5b40a..c48f3ed2d570 100644 --- a/drivers/clk/spear/clk-frac-synth.c +++ b/drivers/clk/spear/clk-frac-synth.c @@ -136,10 +136,8 @@ struct clk *clk_register_frac(const char *name, const char *parent_name, } frac = kzalloc(sizeof(*frac), GFP_KERNEL); - if (!frac) { - pr_err("could not allocate frac clk\n"); + if (!frac) return ERR_PTR(-ENOMEM); - } /* struct clk_frac assignments */ frac->reg = reg; diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c index 1a722e99e76e..6e95d7f3ade9 100644 --- a/drivers/clk/spear/clk-gpt-synth.c +++ b/drivers/clk/spear/clk-gpt-synth.c @@ -125,10 +125,8 @@ struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned } gpt = kzalloc(sizeof(*gpt), GFP_KERNEL); - if (!gpt) { - pr_err("could not allocate gpt clk\n"); + if (!gpt) return ERR_PTR(-ENOMEM); - } /* struct clk_gpt assignments */ gpt->reg = reg; diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index dc21ca4601aa..e06b821fa60e 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -292,16 +292,12 @@ struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name, } vco = kzalloc(sizeof(*vco), GFP_KERNEL); - if (!vco) { - pr_err("could not allocate vco clk\n"); + if (!vco) return ERR_PTR(-ENOMEM); - } pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("could not allocate pll clk\n"); + if (!pll) goto free_vco; - } /* struct clk_vco assignments */ vco->mode_reg = mode_reg; -- cgit v1.2.3 From 7a294dc6c85d6cea181055c5412bb44a499e3816 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 20:23:58 +0200 Subject: clk: ux500: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Ulf Hansson Signed-off-by: Stephen Boyd --- drivers/clk/ux500/clk-prcc.c | 4 +--- drivers/clk/ux500/clk-prcmu.c | 4 +--- drivers/clk/ux500/clk-sysctrl.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c index f50592775c9d..5ca07e6d1f64 100644 --- a/drivers/clk/ux500/clk-prcc.c +++ b/drivers/clk/ux500/clk-prcc.c @@ -108,10 +108,8 @@ static struct clk *clk_reg_prcc(const char *name, } clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL); - if (!clk) { - pr_err("clk_prcc: %s could not allocate clk\n", __func__); + if (!clk) return ERR_PTR(-ENOMEM); - } clk->base = ioremap(phy_base, SZ_4K); if (!clk->base) diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 6e3e16b2e5ca..c137934f23ab 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c @@ -259,10 +259,8 @@ static struct clk *clk_reg_prcmu(const char *name, } clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL); - if (!clk) { - pr_err("clk_prcmu: %s could not allocate clk\n", __func__); + if (!clk) return ERR_PTR(-ENOMEM); - } clk->cg_sel = cg_sel; clk->is_prepared = 1; diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c index 8a4e93ce1e42..e0a834c08a04 100644 --- a/drivers/clk/ux500/clk-sysctrl.c +++ b/drivers/clk/ux500/clk-sysctrl.c @@ -140,10 +140,8 @@ static struct clk *clk_reg_sysctrl(struct device *dev, } clk = devm_kzalloc(dev, sizeof(struct clk_sysctrl), GFP_KERNEL); - if (!clk) { - dev_err(dev, "clk_sysctrl: could not allocate clk\n"); + if (!clk) return ERR_PTR(-ENOMEM); - } /* set main clock registers */ clk->reg_sel[0] = reg_sel[0]; -- cgit v1.2.3 From 0b10adbae303ecdb78c779eabb7ab587c91d324c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 20:30:53 +0200 Subject: clk: ux500: Improve sizeof() usage Replace the specification of data structures by pointer dereferences as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Ulf Hansson Signed-off-by: Stephen Boyd --- drivers/clk/ux500/clk-prcc.c | 2 +- drivers/clk/ux500/clk-prcmu.c | 2 +- drivers/clk/ux500/clk-sysctrl.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c index 5ca07e6d1f64..7cfb59c9136d 100644 --- a/drivers/clk/ux500/clk-prcc.c +++ b/drivers/clk/ux500/clk-prcc.c @@ -107,7 +107,7 @@ static struct clk *clk_reg_prcc(const char *name, return ERR_PTR(-EINVAL); } - clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL); + clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) return ERR_PTR(-ENOMEM); diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index c137934f23ab..9d1f2d4550ad 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c @@ -258,7 +258,7 @@ static struct clk *clk_reg_prcmu(const char *name, return ERR_PTR(-EINVAL); } - clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL); + clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) return ERR_PTR(-ENOMEM); diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c index e0a834c08a04..7c0403b733ae 100644 --- a/drivers/clk/ux500/clk-sysctrl.c +++ b/drivers/clk/ux500/clk-sysctrl.c @@ -139,7 +139,7 @@ static struct clk *clk_reg_sysctrl(struct device *dev, return ERR_PTR(-EINVAL); } - clk = devm_kzalloc(dev, sizeof(struct clk_sysctrl), GFP_KERNEL); + clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); if (!clk) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From e343b81e4d9d1551ec3a651a7d30630a268fd35e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 21:21:23 +0200 Subject: clk: versatile: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/versatile/clk-icst.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 09fbe66f1f11..20ab4ceffb28 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -360,15 +360,12 @@ static struct clk *icst_clk_setup(struct device *dev, struct icst_params *pclone; icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); - if (!icst) { - pr_err("could not allocate ICST clock!\n"); + if (!icst) return ERR_PTR(-ENOMEM); - } pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL); if (!pclone) { kfree(icst); - pr_err("could not clone ICST params\n"); return ERR_PTR(-ENOMEM); } -- cgit v1.2.3 From a72da43c92dc09488ac2944b103de037c435302a Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 21:24:43 +0200 Subject: clk: versatile: Improve sizeof() usage Replace the specification of a data structure by a pointer dereference as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/versatile/clk-icst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 20ab4ceffb28..dafe7a45875d 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -359,7 +359,7 @@ static struct clk *icst_clk_setup(struct device *dev, struct clk_init_data init; struct icst_params *pclone; - icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); + icst = kzalloc(sizeof(*icst), GFP_KERNEL); if (!icst) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 9416a5f8842a37dc356b7855867d20db6dfa9e3a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 5 Sep 2017 16:03:48 +0100 Subject: clk: cdce925: remove redundant check for non-null parent_name The check for a non-null parent_name is always true as there is an earlier check for a null parent_name that returns -ENODEV. Remove this redundant check and always set init.num_parents to 1. Detected by CoverityScan CID#1309477 ("Logically dead code") Signed-off-by: Colin Ian King Signed-off-by: Stephen Boyd --- drivers/clk/clk-cdce925.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index c933be01c7db..0a7e7d5a7506 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -665,7 +665,7 @@ static int cdce925_probe(struct i2c_client *client, init.ops = &cdce925_pll_ops; init.flags = 0; init.parent_names = &parent_name; - init.num_parents = parent_name ? 1 : 0; + init.num_parents = 1; /* Register PLL clocks */ for (i = 0; i < data->chip_info->num_plls; ++i) { -- cgit v1.2.3 From 658af6cbd4e4f62395d8dad7f76871de8159ee92 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 4 Sep 2017 10:37:50 +0100 Subject: ARC: clk: fix spelling mistake: "configurarion" -> "configuration" Trivial fix to spelling mistake in dev_dbg message Signed-off-by: Colin Ian King Signed-off-by: Stephen Boyd --- drivers/clk/clk-hsdk-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-hsdk-pll.c b/drivers/clk/clk-hsdk-pll.c index bbf237173b37..c4ee280f454d 100644 --- a/drivers/clk/clk-hsdk-pll.c +++ b/drivers/clk/clk-hsdk-pll.c @@ -139,7 +139,7 @@ static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk, val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; - dev_dbg(clk->dev, "write configurarion: %#x\n", val); + dev_dbg(clk->dev, "write configuration: %#x\n", val); hsdk_pll_write(clk, CGU_PLL_CTRL, val); } @@ -169,7 +169,7 @@ static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw, val = hsdk_pll_read(clk, CGU_PLL_CTRL); - dev_dbg(clk->dev, "current configurarion: %#x\n", val); + dev_dbg(clk->dev, "current configuration: %#x\n", val); /* Check if PLL is disabled */ if (val & CGU_PLL_CTRL_PD) -- cgit v1.2.3 From 98c58f7d176a025365219bf51079a004cb70cc7c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 16:54:20 +0200 Subject: clk: kona-setup: Delete error messages for failed memory allocations Omit extra messages for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Scott Branden Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-kona-setup.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index c37a7f0e83aa..281f4322355c 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c @@ -579,18 +579,13 @@ static u32 *parent_process(const char *clocks[], */ parent_names = kmalloc_array(parent_count, sizeof(*parent_names), GFP_KERNEL); - if (!parent_names) { - pr_err("%s: error allocating %u parent names\n", __func__, - parent_count); + if (!parent_names) return ERR_PTR(-ENOMEM); - } /* There is at least one parent, so allocate a selector array */ parent_sel = kmalloc_array(parent_count, sizeof(*parent_sel), GFP_KERNEL); if (!parent_sel) { - pr_err("%s: error allocating %u parent selectors\n", __func__, - parent_count); kfree(parent_names); return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From d33fb1b9f0fcb67f2b9f8b1891465a088a9480f8 Mon Sep 17 00:00:00 2001 From: Zhong Kaihua Date: Mon, 7 Aug 2017 22:51:56 +0800 Subject: clk: hi3660: fix incorrect uart3 clock freqency UART3 clock rate is doubled in previous commit. This error is not detected until recently a mezzanine board which makes real use of uart3 port (through LS connector of 96boards) was setup and tested on hi3660-hikey960 board. This patch changes clock source rate of clk_factor_uart3 to 100000000. Signed-off-by: Zhong Kaihua Signed-off-by: Guodong Xu Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi3660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/hisilicon/clk-hi3660.c b/drivers/clk/hisilicon/clk-hi3660.c index a18258eb89cb..f40419959656 100644 --- a/drivers/clk/hisilicon/clk-hi3660.c +++ b/drivers/clk/hisilicon/clk-hi3660.c @@ -34,7 +34,7 @@ static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = { /* crgctrl */ static const struct hisi_fixed_factor_clock hi3660_crg_fixed_factor_clks[] = { - { HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 8, 0, }, + { HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 16, 0, }, { HI3660_CLK_FACTOR_MMC, "clk_factor_mmc", "clkin_sys", 1, 6, 0, }, { HI3660_CLK_GATE_I2C0, "clk_gate_i2c0", "clk_i2c0_iomcu", 1, 4, 0, }, { HI3660_CLK_GATE_I2C1, "clk_gate_i2c1", "clk_i2c1_iomcu", 1, 4, 0, }, -- cgit v1.2.3 From 90c42090c0da3a77057ba777e2d3f8d16e55aabc Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 26 Sep 2017 22:00:05 +0200 Subject: clk: hisilicon: Delete an error message for a failed memory allocation in hisi_register_clkgate_sep() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Reviewed-by: Leo Yan Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clkgate-separated.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c index 7908bc3c9ec7..f028bcffe12c 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -105,10 +105,8 @@ struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name, struct clk_init_data init; sclk = kzalloc(sizeof(*sclk), GFP_KERNEL); - if (!sclk) { - pr_err("%s: fail to allocate separated gated clk\n", __func__); + if (!sclk) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &clkgate_separated_ops; -- cgit v1.2.3 From 3320f39bee899b68d4f35220764b2ab213374708 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 27 Sep 2017 11:59:40 -0700 Subject: clk: hi3798cv200: correct parent mux clock for 'clk_sdio0_ciu' Other than 'mmc_mux', 'clk_sdio0_ciu' uses a different parent mux clock. Let's add this mux clock as 'sdio0_mux', and correct the parent of 'clk_sdio0_ciu' to be it. Signed-off-by: Shawn Guo Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/crg-hi3798cv200.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/hisilicon/crg-hi3798cv200.c b/drivers/clk/hisilicon/crg-hi3798cv200.c index ed8bb5f7507f..8478948e858e 100644 --- a/drivers/clk/hisilicon/crg-hi3798cv200.c +++ b/drivers/clk/hisilicon/crg-hi3798cv200.c @@ -47,6 +47,8 @@ #define HI3798CV200_FIXED_12M 81 #define HI3798CV200_FIXED_48M 82 #define HI3798CV200_FIXED_60M 83 +#define HI3798CV200_FIXED_166P5M 84 +#define HI3798CV200_SDIO0_MUX 85 #define HI3798CV200_CRG_NR_CLKS 128 @@ -63,6 +65,7 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = { { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, }, { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, }, { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, }, + { HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, }, { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, }, { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, }, }; @@ -75,12 +78,19 @@ static const char *const comphy1_mux_p[] = { "100m", "25m"}; static u32 comphy1_mux_table[] = {2, 3}; +static const char *const sdio_mux_p[] = { + "100m", "50m", "150m", "166p5m" }; +static u32 sdio_mux_table[] = {0, 1, 2, 3}; + static struct hisi_mux_clock hi3798cv200_mux_clks[] = { { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, }, { HI3798CV200_COMBPHY1_MUX, "combphy1_mux", comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p), CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, }, + { HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p, + ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT, + 0x9c, 8, 2, 0, sdio_mux_table, }, }; static const struct hisi_gate_clock hi3798cv200_gate_clks[] = { @@ -104,7 +114,7 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = { /* SDIO */ { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m", CLK_SET_RATE_PARENT, 0x9c, 0, 0, }, - { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux", + { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux", CLK_SET_RATE_PARENT, 0x9c, 1, 0, }, /* EMMC */ { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m", -- cgit v1.2.3 From 3a5dfa7d78976fd712b63b3db4357d94dcd3c5ba Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 19 Oct 2017 09:52:46 +0900 Subject: clk: uniphier: fix parent of miodmac clock data The "miodmac" is not a child of "stdmac". They are independent from each other. Fix it. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/uniphier/clk-uniphier-mio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index 16e4d303f535..badc478a86c6 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -13,6 +13,8 @@ * GNU General Public License for more details. */ +#include + #include "clk-uniphier.h" #define UNIPHIER_MIO_CLK_SD_FIXED \ @@ -73,15 +75,12 @@ #define UNIPHIER_MIO_CLK_USB2_PHY(idx, ch) \ UNIPHIER_CLK_GATE("usb2" #ch "-phy", (idx), "usb2", 0x20 + 0x200 * (ch), 29) -#define UNIPHIER_MIO_CLK_DMAC(idx) \ - UNIPHIER_CLK_GATE("miodmac", (idx), "stdmac", 0x20, 25) - const struct uniphier_clk_data uniphier_ld4_mio_clk_data[] = { UNIPHIER_MIO_CLK_SD_FIXED, UNIPHIER_MIO_CLK_SD(0, 0), UNIPHIER_MIO_CLK_SD(1, 1), UNIPHIER_MIO_CLK_SD(2, 2), - UNIPHIER_MIO_CLK_DMAC(7), + UNIPHIER_CLK_GATE("miodmac", 7, NULL, 0x20, 25), UNIPHIER_MIO_CLK_USB2(8, 0), UNIPHIER_MIO_CLK_USB2(9, 1), UNIPHIER_MIO_CLK_USB2(10, 2), -- cgit v1.2.3 From 67affb78a4e4feb837953e3434c8402a5c3b272f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 Oct 2017 11:32:59 +0900 Subject: clk: uniphier: fix DAPLL2 clock rate of Pro5 The parent of DAPLL2 should be DAPLL1. Fix the clock connection. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/uniphier/clk-uniphier-sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index 0e396f3da526..bffe095e603a 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -123,7 +123,7 @@ const struct uniphier_clk_data uniphier_sld8_sys_clk_data[] = { const struct uniphier_clk_data uniphier_pro5_sys_clk_data[] = { UNIPHIER_CLK_FACTOR("spll", -1, "ref", 120, 1), /* 2400 MHz */ UNIPHIER_CLK_FACTOR("dapll1", -1, "ref", 128, 1), /* 2560 MHz */ - UNIPHIER_CLK_FACTOR("dapll2", -1, "ref", 144, 125), /* 2949.12 MHz */ + UNIPHIER_CLK_FACTOR("dapll2", -1, "dapll1", 144, 125), /* 2949.12 MHz */ UNIPHIER_CLK_FACTOR("uart", 0, "dapll2", 1, 40), UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), UNIPHIER_PRO5_SYS_CLK_NAND(2), -- cgit v1.2.3 From 43a51019cc8ff1b1cd2ba72e86563beb40d356fc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 11 Nov 2017 17:29:28 +0100 Subject: clk: qcom: common: fix legacy board-clock registration Make sure to search only the child nodes of "/clocks", rather than the whole device-tree depth-first starting at "/clocks" when determining whether to register a fixed clock in the legacy board-clock registration helper. Fixes: ee15faffef11 ("clk: qcom: common: Add API to register board clocks backwards compatibly") Signed-off-by: Johan Hovold Signed-off-by: Stephen Boyd --- drivers/clk/qcom/common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index b35564c0493f..b8064a336d46 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -133,8 +133,10 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path, int ret; clocks_node = of_find_node_by_path("/clocks"); - if (clocks_node) - node = of_find_node_by_name(clocks_node, path); + if (clocks_node) { + node = of_get_child_by_name(clocks_node, path); + of_node_put(clocks_node); + } if (!node) { fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL); -- cgit v1.2.3 From 33ec6dbc5a02677509d97fe36cd2105753f0f0ea Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 11 Nov 2017 17:29:29 +0100 Subject: clk: ti: dra7-atl-clock: fix child-node lookups Fix child node-lookup during probe, which ended up searching the whole device tree depth-first starting at parent rather than just matching on its children. Note that the original premature free of the parent node has already been fixed separately, but that fix was apparently never backported to stable. Fixes: 9ac33b0ce81f ("CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic)") Fixes: 660e15519399 ("clk: ti: dra7-atl-clock: Fix of_node reference counting") Cc: stable # 3.16: 660e15519399 Cc: Peter Ujfalusi Signed-off-by: Johan Hovold Acked-by: Peter Ujfalusi Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk-dra7-atl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 13eb04f72389..148815470431 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -274,8 +274,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) /* Get configuration for the ATL instances */ snprintf(prop, sizeof(prop), "atl%u", i); - of_node_get(node); - cfg_node = of_find_node_by_name(node, prop); + cfg_node = of_get_child_by_name(node, prop); if (cfg_node) { ret = of_property_read_u32(cfg_node, "bws", &cdesc->bws); -- cgit v1.2.3 From cc54c0955d6f8618a38a999eecdc3d95306b90de Mon Sep 17 00:00:00 2001 From: Mylene JOSSERAND Date: Sun, 5 Nov 2017 17:51:34 +0100 Subject: clk: sunxi-ng: a83t: Fix i2c buses bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i2c1 and i2c2 bits for CCU are not bit 0 but bit 1 and bit 2. Because of that, the i2c0 (bit 0) was not correctly configured. Fixed the correct bits for i2c1 and i2c2. Fixes: 05359be1176b ("clk: sunxi-ng: Add driver for A83T CCU") Signed-off-by: Mylène Josserand Acked-by: Maxime Ripard Signed-off-by: Stephen Boyd --- drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index c7b51f030eb2..5cedcd0d8be8 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -354,9 +354,9 @@ static SUNXI_CCU_GATE(bus_tdm_clk, "bus-tdm", "apb1", static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x06c, BIT(0), 0); static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", - 0x06c, BIT(0), 0); + 0x06c, BIT(1), 0); static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", - 0x06c, BIT(0), 0); + 0x06c, BIT(2), 0); static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x06c, BIT(16), 0); static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", -- cgit v1.2.3 From c82a2cb85973707671f1428b05f65243baf85da7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 15 Sep 2017 21:53:47 +0200 Subject: clk: pxa: fix building on older compilers gcc-4.4 got confused by the inline assembler statement: drivers/clk/pxa/clk-pxa.c: In function 'pxa2xx_core_turbo_switch': drivers/clk/pxa/clk-pxa.c:152: error: expected string literal before ')' token This removes the extraneous ':' to let all compilers parse the driver correctly. Signed-off-by: Arnd Bergmann Acked-by: Robert Jarzmik Signed-off-by: Stephen Boyd --- drivers/clk/pxa/clk-pxa.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c index 74f64c3c4290..b80dc9d5855c 100644 --- a/drivers/clk/pxa/clk-pxa.c +++ b/drivers/clk/pxa/clk-pxa.c @@ -147,9 +147,7 @@ void pxa2xx_core_turbo_switch(bool on) " b 3f\n" "2: b 1b\n" "3: nop\n" - : "=&r" (unused) - : "r" (clkcfg) - : ); + : "=&r" (unused) : "r" (clkcfg)); local_irq_restore(flags); } -- cgit v1.2.3 From c1ea839c41d049604a3f64ef72712d1c7c6639d0 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Wed, 11 Oct 2017 08:57:24 +0200 Subject: clk: stm32h7: fix test of clock config fix test of composite clock config (bad copy / past) Signed-off-by: Gabriel Fernandez Fixes: 3e4d618b0722 ("clk: stm32h7: Add stm32h743 clock driver") Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32h7.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c index a94c3f56c590..61c3e40507d3 100644 --- a/drivers/clk/clk-stm32h7.c +++ b/drivers/clk/clk-stm32h7.c @@ -384,7 +384,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg, mux_ops = div_ops = gate_ops = NULL; mux_hw = div_hw = gate_hw = NULL; - if (gcfg->mux && gcfg->mux) { + if (gcfg->mux && cfg->mux) { mux = _get_cmux(base + cfg->mux->offset, cfg->mux->shift, cfg->mux->width, @@ -410,7 +410,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg, } } - if (gcfg->gate && gcfg->gate) { + if (gcfg->gate && cfg->gate) { gate = _get_cgate(base + cfg->gate->offset, cfg->gate->bit_idx, gcfg->gate->flags, lock); -- cgit v1.2.3