Skip to content

Commit b1924c2

Browse files
author
Michael Turquette
committed
Merge tag 'for-v3.19/omap-a' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into tmp
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/
2 parents 89f7e9d + 79005fb commit b1924c2

File tree

9 files changed

+238
-63
lines changed

9 files changed

+238
-63
lines changed

arch/arm/mach-omap2/cclock3xxx_data.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ static const struct clk_ops dpll1_ck_ops = {
257257
.get_parent = &omap2_init_dpll_parent,
258258
.recalc_rate = &omap3_dpll_recalc,
259259
.set_rate = &omap3_noncore_dpll_set_rate,
260+
.set_parent = &omap3_noncore_dpll_set_parent,
261+
.set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent,
262+
.determine_rate = &omap3_noncore_dpll_determine_rate,
260263
.round_rate = &omap2_dpll_round_rate,
261264
};
262265

@@ -367,6 +370,9 @@ static const struct clk_ops dpll4_ck_ops = {
367370
.get_parent = &omap2_init_dpll_parent,
368371
.recalc_rate = &omap3_dpll_recalc,
369372
.set_rate = &omap3_dpll4_set_rate,
373+
.set_parent = &omap3_noncore_dpll_set_parent,
374+
.set_rate_and_parent = &omap3_dpll4_set_rate_and_parent,
375+
.determine_rate = &omap3_noncore_dpll_determine_rate,
370376
.round_rate = &omap2_dpll_round_rate,
371377
};
372378

arch/arm/mach-omap2/clock.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,4 +771,8 @@ void __init ti_clk_init_features(void)
771771
ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
772772
else if (cpu_is_omap34xx())
773773
ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
774+
775+
/* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
776+
if (omap_rev() == OMAP3430_REV_ES1_0)
777+
ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
774778
}

arch/arm/mach-omap2/clock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ struct ti_clk_features {
234234
};
235235

236236
#define TI_CLK_DPLL_HAS_FREQSEL (1 << 0)
237+
#define TI_CLK_DPLL4_DENY_REPROGRAM (1 << 1)
237238

238239
extern struct ti_clk_features ti_clk_features;
239240

arch/arm/mach-omap2/clock3xxx.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@
3838

3939
/* needed by omap3_core_dpll_m2_set_rate() */
4040
struct clk *sdrc_ick_p, *arm_fck_p;
41+
42+
/**
43+
* omap3_dpll4_set_rate - set rate for omap3 per-dpll
44+
* @hw: clock to change
45+
* @rate: target rate for clock
46+
* @parent_rate: rate of the parent clock
47+
*
48+
* Check if the current SoC supports the per-dpll reprogram operation
49+
* or not, and then do the rate change if supported. Returns -EINVAL
50+
* if not supported, 0 for success, and potential error codes from the
51+
* clock rate change.
52+
*/
4153
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
4254
unsigned long parent_rate)
4355
{
@@ -46,14 +58,38 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
4658
* on 3430ES1 prevents us from changing DPLL multipliers or dividers
4759
* on DPLL4.
4860
*/
49-
if (omap_rev() == OMAP3430_REV_ES1_0) {
61+
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
5062
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
5163
return -EINVAL;
5264
}
5365

5466
return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
5567
}
5668

69+
/**
70+
* omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
71+
* @hw: clock to change
72+
* @rate: target rate for clock
73+
* @parent_rate: rate of the parent clock
74+
* @index: parent index, 0 - reference clock, 1 - bypass clock
75+
*
76+
* Check if the current SoC support the per-dpll reprogram operation
77+
* or not, and then do the rate + parent change if supported. Returns
78+
* -EINVAL if not supported, 0 for success, and potential error codes
79+
* from the clock rate change.
80+
*/
81+
int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
82+
unsigned long parent_rate, u8 index)
83+
{
84+
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
85+
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
86+
return -EINVAL;
87+
}
88+
89+
return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
90+
index);
91+
}
92+
5793
void __init omap3_clk_lock_dpll5(void)
5894
{
5995
struct clk *dpll5_clk;

arch/arm/mach-omap2/dpll3xxx.c

Lines changed: 119 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -460,25 +460,24 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
460460
/* Non-CORE DPLL rate set code */
461461

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

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

490489
if (__clk_get_rate(dd->clk_bypass) == rate &&
491490
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
492-
pr_debug("%s: %s: set rate: entering bypass.\n",
493-
__func__, __clk_get_name(hw->clk));
491+
*best_parent_clk = dd->clk_bypass;
492+
} else {
493+
rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
494+
*best_parent_clk = dd->clk_ref;
495+
}
496+
497+
*best_parent_rate = rate;
498+
499+
return rate;
500+
}
501+
502+
/**
503+
* omap3_noncore_dpll_set_parent - set parent for a DPLL clock
504+
* @hw: pointer to the clock to set parent for
505+
* @index: parent index to select
506+
*
507+
* Sets parent for a DPLL clock. This sets the DPLL into bypass or
508+
* locked mode. Returns 0 with success, negative error value otherwise.
509+
*/
510+
int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
511+
{
512+
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
513+
int ret;
494514

495-
__clk_prepare(dd->clk_bypass);
496-
clk_enable(dd->clk_bypass);
515+
if (!hw)
516+
return -EINVAL;
517+
518+
if (index)
497519
ret = _omap3_noncore_dpll_bypass(clk);
498-
if (!ret)
499-
new_parent = dd->clk_bypass;
500-
clk_disable(dd->clk_bypass);
501-
__clk_unprepare(dd->clk_bypass);
502-
} else {
503-
__clk_prepare(dd->clk_ref);
504-
clk_enable(dd->clk_ref);
505-
506-
/* XXX this check is probably pointless in the CCF context */
507-
if (dd->last_rounded_rate != rate) {
508-
rrate = __clk_round_rate(hw->clk, rate);
509-
if (rrate != rate) {
510-
pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
511-
__func__, __clk_get_name(hw->clk),
512-
rrate, rate);
513-
rate = rrate;
514-
}
515-
}
520+
else
521+
ret = _omap3_noncore_dpll_lock(clk);
516522

517-
if (dd->last_rounded_rate == 0)
518-
return -EINVAL;
523+
return ret;
524+
}
519525

520-
/* Freqsel is available only on OMAP343X devices */
521-
if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
522-
freqsel = _omap3_dpll_compute_freqsel(clk,
523-
dd->last_rounded_n);
524-
WARN_ON(!freqsel);
525-
}
526+
/**
527+
* omap3_noncore_dpll_set_rate - set rate for a DPLL clock
528+
* @hw: pointer to the clock to set parent for
529+
* @rate: target rate for the clock
530+
* @parent_rate: rate of the parent clock
531+
*
532+
* Sets rate for a DPLL clock. First checks if the clock parent is
533+
* reference clock (in bypass mode, the rate of the clock can't be
534+
* changed) and proceeds with the rate change operation. Returns 0
535+
* with success, negative error value otherwise.
536+
*/
537+
int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
538+
unsigned long parent_rate)
539+
{
540+
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
541+
struct dpll_data *dd;
542+
u16 freqsel = 0;
543+
int ret;
544+
545+
if (!hw || !rate)
546+
return -EINVAL;
547+
548+
dd = clk->dpll_data;
549+
if (!dd)
550+
return -EINVAL;
526551

527-
pr_debug("%s: %s: set rate: locking rate to %lu.\n",
528-
__func__, __clk_get_name(hw->clk), rate);
552+
if (__clk_get_parent(hw->clk) != dd->clk_ref)
553+
return -EINVAL;
554+
555+
if (dd->last_rounded_rate == 0)
556+
return -EINVAL;
529557

530-
ret = omap3_noncore_dpll_program(clk, freqsel);
531-
if (!ret)
532-
new_parent = dd->clk_ref;
533-
clk_disable(dd->clk_ref);
534-
__clk_unprepare(dd->clk_ref);
558+
/* Freqsel is available only on OMAP343X devices */
559+
if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
560+
freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
561+
WARN_ON(!freqsel);
535562
}
536-
/*
537-
* FIXME - this is all wrong. common code handles reparenting and
538-
* migrating prepare/enable counts. dplls should be a multiplexer
539-
* clock and this should be a set_parent operation so that all of that
540-
* stuff is inherited for free
541-
*/
542563

543-
if (!ret && clk_get_parent(hw->clk) != new_parent)
544-
__clk_reparent(hw->clk, new_parent);
564+
pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
565+
__clk_get_name(hw->clk), rate);
545566

546-
return 0;
567+
ret = omap3_noncore_dpll_program(clk, freqsel);
568+
569+
return ret;
570+
}
571+
572+
/**
573+
* omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
574+
* @hw: pointer to the clock to set rate and parent for
575+
* @rate: target rate for the DPLL
576+
* @parent_rate: clock rate of the DPLL parent
577+
* @index: new parent index for the DPLL, 0 - reference, 1 - bypass
578+
*
579+
* Sets rate and parent for a DPLL clock. If new parent is the bypass
580+
* clock, only selects the parent. Otherwise proceeds with a rate
581+
* change, as this will effectively also change the parent as the
582+
* DPLL is put into locked mode. Returns 0 with success, negative error
583+
* value otherwise.
584+
*/
585+
int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
586+
unsigned long rate,
587+
unsigned long parent_rate,
588+
u8 index)
589+
{
590+
int ret;
591+
592+
if (!hw || !rate)
593+
return -EINVAL;
594+
595+
/*
596+
* clk-ref at index[0], in which case we only need to set rate,
597+
* the parent will be changed automatically with the lock sequence.
598+
* With clk-bypass case we only need to change parent.
599+
*/
600+
if (index)
601+
ret = omap3_noncore_dpll_set_parent(hw, index);
602+
else
603+
ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
604+
605+
return ret;
547606
}
548607

549608
/* DPLL autoidle read/set code */

arch/arm/mach-omap2/dpll44xx.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,44 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
207207

208208
return dd->last_rounded_rate;
209209
}
210+
211+
/**
212+
* omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
213+
* @hw: pointer to the clock to determine rate for
214+
* @rate: target rate for the DPLL
215+
* @best_parent_rate: pointer for returning best parent rate
216+
* @best_parent_clk: pointer for returning best parent clock
217+
*
218+
* Determines which DPLL mode to use for reaching a desired rate.
219+
* Checks whether the DPLL shall be in bypass or locked mode, and if
220+
* locked, calculates the M,N values for the DPLL via round-rate.
221+
* Returns a positive clock rate with success, negative error value
222+
* in failure.
223+
*/
224+
long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
225+
unsigned long *best_parent_rate,
226+
struct clk **best_parent_clk)
227+
{
228+
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
229+
struct dpll_data *dd;
230+
231+
if (!hw || !rate)
232+
return -EINVAL;
233+
234+
dd = clk->dpll_data;
235+
if (!dd)
236+
return -EINVAL;
237+
238+
if (__clk_get_rate(dd->clk_bypass) == rate &&
239+
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
240+
*best_parent_clk = dd->clk_bypass;
241+
} else {
242+
rate = omap4_dpll_regm4xen_round_rate(hw, rate,
243+
best_parent_rate);
244+
*best_parent_clk = dd->clk_ref;
245+
}
246+
247+
*best_parent_rate = rate;
248+
249+
return rate;
250+
}

arch/arm/mach-omap2/omap_hwmod.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,12 +2832,10 @@ static int __init _add_link(struct omap_hwmod_ocp_if *oi)
28322832
_alloc_links(&ml, &sl);
28332833

28342834
ml->ocp_if = oi;
2835-
INIT_LIST_HEAD(&ml->node);
28362835
list_add(&ml->node, &oi->master->master_ports);
28372836
oi->master->masters_cnt++;
28382837

28392838
sl->ocp_if = oi;
2840-
INIT_LIST_HEAD(&sl->node);
28412839
list_add(&sl->node, &oi->slave->slave_ports);
28422840
oi->slave->slaves_cnt++;
28432841

0 commit comments

Comments
 (0)