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

Commit 98892781 authored by Tony Lindgren's avatar Tony Lindgren
Browse files

Merge tag 'for-v3.19/omap-a' of...

Merge tag 'for-v3.19/omap-a' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.19/soc

Some OMAP clock/hwmod patches for v3.19.

Most of the patches are clock-related.  The DPLL implementation is
changed to better align to the common clock framework.
There is also a patch that removes a few lines from the hwmod code -
this patch should have no functional effect.

Basic build, boot, and PM test logs for these patches can be found here:

http://www.pwsan.com/omap/testlogs/omap-a-for-v3.19/20141113094101/
parents a30d81b9 79005fbd
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -257,6 +257,9 @@ static const struct clk_ops dpll1_ck_ops = {
	.get_parent	= &omap2_init_dpll_parent,
	.get_parent	= &omap2_init_dpll_parent,
	.recalc_rate	= &omap3_dpll_recalc,
	.recalc_rate	= &omap3_dpll_recalc,
	.set_rate	= &omap3_noncore_dpll_set_rate,
	.set_rate	= &omap3_noncore_dpll_set_rate,
	.set_parent	= &omap3_noncore_dpll_set_parent,
	.set_rate_and_parent	= &omap3_noncore_dpll_set_rate_and_parent,
	.determine_rate	= &omap3_noncore_dpll_determine_rate,
	.round_rate	= &omap2_dpll_round_rate,
	.round_rate	= &omap2_dpll_round_rate,
};
};


@@ -367,6 +370,9 @@ static const struct clk_ops dpll4_ck_ops = {
	.get_parent	= &omap2_init_dpll_parent,
	.get_parent	= &omap2_init_dpll_parent,
	.recalc_rate	= &omap3_dpll_recalc,
	.recalc_rate	= &omap3_dpll_recalc,
	.set_rate	= &omap3_dpll4_set_rate,
	.set_rate	= &omap3_dpll4_set_rate,
	.set_parent	= &omap3_noncore_dpll_set_parent,
	.set_rate_and_parent	= &omap3_dpll4_set_rate_and_parent,
	.determine_rate	= &omap3_noncore_dpll_determine_rate,
	.round_rate	= &omap2_dpll_round_rate,
	.round_rate	= &omap2_dpll_round_rate,
};
};


+4 −0
Original line number Original line Diff line number Diff line
@@ -771,4 +771,8 @@ void __init ti_clk_init_features(void)
		ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
		ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
	else if (cpu_is_omap34xx())
	else if (cpu_is_omap34xx())
		ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
		ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;

	/* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
	if (omap_rev() == OMAP3430_REV_ES1_0)
		ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -234,6 +234,7 @@ struct ti_clk_features {
};
};


#define TI_CLK_DPLL_HAS_FREQSEL		(1 << 0)
#define TI_CLK_DPLL_HAS_FREQSEL		(1 << 0)
#define TI_CLK_DPLL4_DENY_REPROGRAM	(1 << 1)


extern struct ti_clk_features ti_clk_features;
extern struct ti_clk_features ti_clk_features;


+37 −1
Original line number Original line Diff line number Diff line
@@ -38,6 +38,18 @@


/* needed by omap3_core_dpll_m2_set_rate() */
/* needed by omap3_core_dpll_m2_set_rate() */
struct clk *sdrc_ick_p, *arm_fck_p;
struct clk *sdrc_ick_p, *arm_fck_p;

/**
 * omap3_dpll4_set_rate - set rate for omap3 per-dpll
 * @hw: clock to change
 * @rate: target rate for clock
 * @parent_rate: rate of the parent clock
 *
 * Check if the current SoC supports the per-dpll reprogram operation
 * or not, and then do the rate change if supported. Returns -EINVAL
 * if not supported, 0 for success, and potential error codes from the
 * clock rate change.
 */
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
				unsigned long parent_rate)
{
{
@@ -46,7 +58,7 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
	 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
	 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
	 * on DPLL4.
	 * on DPLL4.
	 */
	 */
	if (omap_rev() == OMAP3430_REV_ES1_0) {
	if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
		pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
		pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -54,6 +66,30 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
	return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
	return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
}
}


/**
 * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
 * @hw: clock to change
 * @rate: target rate for clock
 * @parent_rate: rate of the parent clock
 * @index: parent index, 0 - reference clock, 1 - bypass clock
 *
 * Check if the current SoC support the per-dpll reprogram operation
 * or not, and then do the rate + parent change if supported. Returns
 * -EINVAL if not supported, 0 for success, and potential error codes
 * from the clock rate change.
 */
int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
				    unsigned long parent_rate, u8 index)
{
	if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
		pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
		return -EINVAL;
	}

	return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
						      index);
}

void __init omap3_clk_lock_dpll5(void)
void __init omap3_clk_lock_dpll5(void)
{
{
	struct clk *dpll5_clk;
	struct clk *dpll5_clk;
+119 −60
Original line number Original line Diff line number Diff line
@@ -460,25 +460,24 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
/* Non-CORE DPLL rate set code */
/* Non-CORE DPLL rate set code */


/**
/**
 * omap3_noncore_dpll_set_rate - set non-core DPLL rate
 * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
 * @clk: struct clk * of DPLL to set
 * @hw: pointer to the clock to determine rate for
 * @rate: rounded target rate
 * @rate: target rate for the DPLL
 * @best_parent_rate: pointer for returning best parent rate
 * @best_parent_clk: pointer for returning best parent clock
 *
 *
 * Set the DPLL CLKOUT to the target rate.  If the DPLL can enter
 * Determines which DPLL mode to use for reaching a desired target rate.
 * low-power bypass, and the target rate is the bypass source clock
 * Checks whether the DPLL shall be in bypass or locked mode, and if
 * rate, then configure the DPLL for bypass.  Otherwise, round the
 * locked, calculates the M,N values for the DPLL via round-rate.
 * target rate if it hasn't been done already, then program and lock
 * Returns a positive clock rate with success, negative error value
 * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
 * in failure.
 */
 */
int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
					unsigned long parent_rate)
				       unsigned long *best_parent_rate,
				       struct clk **best_parent_clk)
{
{
	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
	struct clk *new_parent = NULL;
	unsigned long rrate;
	u16 freqsel = 0;
	struct dpll_data *dd;
	struct dpll_data *dd;
	int ret;


	if (!hw || !rate)
	if (!hw || !rate)
		return -EINVAL;
		return -EINVAL;
@@ -489,61 +488,121 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,


	if (__clk_get_rate(dd->clk_bypass) == rate &&
	if (__clk_get_rate(dd->clk_bypass) == rate &&
	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
		pr_debug("%s: %s: set rate: entering bypass.\n",
		*best_parent_clk = dd->clk_bypass;
			 __func__, __clk_get_name(hw->clk));

		__clk_prepare(dd->clk_bypass);
		clk_enable(dd->clk_bypass);
		ret = _omap3_noncore_dpll_bypass(clk);
		if (!ret)
			new_parent = dd->clk_bypass;
		clk_disable(dd->clk_bypass);
		__clk_unprepare(dd->clk_bypass);
	} else {
	} else {
		__clk_prepare(dd->clk_ref);
		rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
		clk_enable(dd->clk_ref);
		*best_parent_clk = dd->clk_ref;

		/* XXX this check is probably pointless in the CCF context */
		if (dd->last_rounded_rate != rate) {
			rrate = __clk_round_rate(hw->clk, rate);
			if (rrate != rate) {
				pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
					__func__, __clk_get_name(hw->clk),
					rrate, rate);
				rate = rrate;
	}
	}

	*best_parent_rate = rate;

	return rate;
}

/**
 * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
 * @hw: pointer to the clock to set parent for
 * @index: parent index to select
 *
 * Sets parent for a DPLL clock. This sets the DPLL into bypass or
 * locked mode. Returns 0 with success, negative error value otherwise.
 */
int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
	int ret;

	if (!hw)
		return -EINVAL;

	if (index)
		ret = _omap3_noncore_dpll_bypass(clk);
	else
		ret = _omap3_noncore_dpll_lock(clk);

	return ret;
}
}


/**
 * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
 * @hw: pointer to the clock to set parent for
 * @rate: target rate for the clock
 * @parent_rate: rate of the parent clock
 *
 * Sets rate for a DPLL clock. First checks if the clock parent is
 * reference clock (in bypass mode, the rate of the clock can't be
 * changed) and proceeds with the rate change operation. Returns 0
 * with success, negative error value otherwise.
 */
int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
{
	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
	struct dpll_data *dd;
	u16 freqsel = 0;
	int ret;

	if (!hw || !rate)
		return -EINVAL;

	dd = clk->dpll_data;
	if (!dd)
		return -EINVAL;

	if (__clk_get_parent(hw->clk) != dd->clk_ref)
		return -EINVAL;

	if (dd->last_rounded_rate == 0)
	if (dd->last_rounded_rate == 0)
		return -EINVAL;
		return -EINVAL;


	/* Freqsel is available only on OMAP343X devices */
	/* Freqsel is available only on OMAP343X devices */
	if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
	if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
			freqsel = _omap3_dpll_compute_freqsel(clk,
		freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
						dd->last_rounded_n);
		WARN_ON(!freqsel);
		WARN_ON(!freqsel);
	}
	}


		pr_debug("%s: %s: set rate: locking rate to %lu.\n",
	pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
			 __func__, __clk_get_name(hw->clk), rate);
		 __clk_get_name(hw->clk), rate);


	ret = omap3_noncore_dpll_program(clk, freqsel);
	ret = omap3_noncore_dpll_program(clk, freqsel);
		if (!ret)

			new_parent = dd->clk_ref;
	return ret;
		clk_disable(dd->clk_ref);
		__clk_unprepare(dd->clk_ref);
}
}
	/*

	* FIXME - this is all wrong.  common code handles reparenting and
/**
	* migrating prepare/enable counts.  dplls should be a multiplexer
 * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
	* clock and this should be a set_parent operation so that all of that
 * @hw: pointer to the clock to set rate and parent for
	* stuff is inherited for free
 * @rate: target rate for the DPLL
 * @parent_rate: clock rate of the DPLL parent
 * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
 *
 * Sets rate and parent for a DPLL clock. If new parent is the bypass
 * clock, only selects the parent. Otherwise proceeds with a rate
 * change, as this will effectively also change the parent as the
 * DPLL is put into locked mode. Returns 0 with success, negative error
 * value otherwise.
 */
 */
int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
					   unsigned long rate,
					   unsigned long parent_rate,
					   u8 index)
{
	int ret;


	if (!ret && clk_get_parent(hw->clk) != new_parent)
	if (!hw || !rate)
		__clk_reparent(hw->clk, new_parent);
		return -EINVAL;


	return 0;
	/*
	 * clk-ref at index[0], in which case we only need to set rate,
	 * the parent will be changed automatically with the lock sequence.
	 * With clk-bypass case we only need to change parent.
	 */
	if (index)
		ret = omap3_noncore_dpll_set_parent(hw, index);
	else
		ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);

	return ret;
}
}


/* DPLL autoidle read/set code */
/* DPLL autoidle read/set code */
Loading