Loading drivers/clk/clk.c +51 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ struct clk_core { bool orphan; unsigned int enable_count; unsigned int prepare_count; bool need_handoff_enable; bool need_handoff_prepare; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; Loading Loading @@ -838,6 +840,19 @@ int clk_prepare(struct clk *clk) if (!clk) return 0; /* * setting CLK_ENABLE_HAND_OFF flag triggers this conditional * * need_handoff_prepare implies this clk was already prepared by * __clk_init. now we have a proper user, so unset the flag in our * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h * for details. */ if (clk->core->need_handoff_prepare) { clk->core->need_handoff_prepare = false; return 0; } return clk_core_prepare_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_prepare); Loading Loading @@ -963,6 +978,19 @@ int clk_enable(struct clk *clk) if (!clk) return 0; /* * setting CLK_ENABLE_HAND_OFF flag triggers this conditional * * need_handoff_enable implies this clk was already enabled by * __clk_init. now we have a proper user, so unset the flag in our * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h * for details. */ if (clk->core->need_handoff_enable) { clk->core->need_handoff_enable = false; return 0; } return clk_core_enable_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_enable); Loading Loading @@ -3140,6 +3168,29 @@ static int __clk_core_init(struct clk_core *core) clk_enable_unlock(flags); } /* * enable clocks with the CLK_ENABLE_HAND_OFF flag set * * This flag causes the framework to enable the clock at registration * time, which is sometimes necessary for clocks that would cause a * system crash when gated (e.g. cpu, memory, etc). The prepare_count * is migrated over to the first clk consumer to call clk_prepare(). * Similarly the clk's enable_count is migrated to the first consumer * to call clk_enable(). */ if (core->flags & CLK_ENABLE_HAND_OFF) { unsigned long flags; core->need_handoff_prepare = true; core->need_handoff_enable = true; ret = clk_core_prepare(core); if (ret) goto out; flags = clk_enable_lock(); clk_core_enable(core); clk_enable_unlock(flags); } kref_init(&core->ref); out: clk_prepare_unlock(); Loading include/linux/clk-provider.h +5 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,11 @@ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE BIT(12) /* unused */ #define CLK_ENABLE_HAND_OFF BIT(13) /* enable clock when registered. */ /* * hand-off enable_count & prepare_count * to first consumer that enables clk */ #define CLK_IS_MEASURE BIT(14) /* measure clock */ struct clk; Loading Loading
drivers/clk/clk.c +51 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ struct clk_core { bool orphan; unsigned int enable_count; unsigned int prepare_count; bool need_handoff_enable; bool need_handoff_prepare; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; Loading Loading @@ -838,6 +840,19 @@ int clk_prepare(struct clk *clk) if (!clk) return 0; /* * setting CLK_ENABLE_HAND_OFF flag triggers this conditional * * need_handoff_prepare implies this clk was already prepared by * __clk_init. now we have a proper user, so unset the flag in our * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h * for details. */ if (clk->core->need_handoff_prepare) { clk->core->need_handoff_prepare = false; return 0; } return clk_core_prepare_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_prepare); Loading Loading @@ -963,6 +978,19 @@ int clk_enable(struct clk *clk) if (!clk) return 0; /* * setting CLK_ENABLE_HAND_OFF flag triggers this conditional * * need_handoff_enable implies this clk was already enabled by * __clk_init. now we have a proper user, so unset the flag in our * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h * for details. */ if (clk->core->need_handoff_enable) { clk->core->need_handoff_enable = false; return 0; } return clk_core_enable_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_enable); Loading Loading @@ -3140,6 +3168,29 @@ static int __clk_core_init(struct clk_core *core) clk_enable_unlock(flags); } /* * enable clocks with the CLK_ENABLE_HAND_OFF flag set * * This flag causes the framework to enable the clock at registration * time, which is sometimes necessary for clocks that would cause a * system crash when gated (e.g. cpu, memory, etc). The prepare_count * is migrated over to the first clk consumer to call clk_prepare(). * Similarly the clk's enable_count is migrated to the first consumer * to call clk_enable(). */ if (core->flags & CLK_ENABLE_HAND_OFF) { unsigned long flags; core->need_handoff_prepare = true; core->need_handoff_enable = true; ret = clk_core_prepare(core); if (ret) goto out; flags = clk_enable_lock(); clk_core_enable(core); clk_enable_unlock(flags); } kref_init(&core->ref); out: clk_prepare_unlock(); Loading
include/linux/clk-provider.h +5 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,11 @@ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE BIT(12) /* unused */ #define CLK_ENABLE_HAND_OFF BIT(13) /* enable clock when registered. */ /* * hand-off enable_count & prepare_count * to first consumer that enables clk */ #define CLK_IS_MEASURE BIT(14) /* measure clock */ struct clk; Loading