Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f120d902 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: introduce CLK_ENABLE_HAND_OFF flag"

parents 6aca0717 cc6ef92a
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ struct clk_core {
	unsigned int		enable_count;
	unsigned int		prepare_count;
	unsigned int		protect_count;
	bool			need_handoff_enable;
	bool			need_handoff_prepare;
	unsigned long		min_rate;
	unsigned long		max_rate;
	unsigned long		accuracy;
@@ -1078,6 +1080,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);
@@ -1205,6 +1220,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);
@@ -3423,6 +3451,50 @@ static int __clk_core_init(struct clk_core *core)
		}
	}

	/*
	 * optional platform-specific magic
	 *
	 * The .init callback is not used by any of the basic clock types, but
	 * exists for weird hardware that must perform initialization magic.
	 * Please consider other ways of solving initialization problems before
	 * using this callback, as its use is discouraged.
	 */
	if (core->ops->init)
		core->ops->init(core->hw);

	if (core->flags & CLK_IS_CRITICAL) {
		unsigned long flags;

		clk_core_prepare(core);

		flags = clk_enable_lock();
		clk_core_enable(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_pm_runtime_put(core);
+5 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@
#define CLK_OPS_PARENT_ENABLE	BIT(12)
/* duty cycle call may be forwarded to the parent clock */
#define CLK_DUTY_CYCLE_PARENT	BIT(13)
#define CLK_ENABLE_HAND_OFF	BIT(14) /* enable clock when registered. */
					/*
					 * hand-off enable_count & prepare_count
					 * to first consumer that enables clk
					 */

struct clk;
struct clk_hw;