|
@@ -50,12 +50,19 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
|
|
|
unsigned int max_m, max_p;
|
|
|
unsigned int m, p;
|
|
|
|
|
|
+ if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
|
|
+ rate *= cmp->fixed_post_div;
|
|
|
+
|
|
|
max_m = cmp->m.max ?: 1 << cmp->m.width;
|
|
|
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
|
|
|
|
|
|
ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
|
|
|
+ rate = *parent_rate / p / m;
|
|
|
+
|
|
|
+ if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
|
|
+ rate /= cmp->fixed_post_div;
|
|
|
|
|
|
- return *parent_rate / p / m;
|
|
|
+ return rate;
|
|
|
}
|
|
|
|
|
|
static void ccu_mp_disable(struct clk_hw *hw)
|
|
@@ -83,6 +90,7 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
|
|
|
unsigned long parent_rate)
|
|
|
{
|
|
|
struct ccu_mp *cmp = hw_to_ccu_mp(hw);
|
|
|
+ unsigned long rate;
|
|
|
unsigned int m, p;
|
|
|
u32 reg;
|
|
|
|
|
@@ -101,7 +109,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
|
|
|
p = reg >> cmp->p.shift;
|
|
|
p &= (1 << cmp->p.width) - 1;
|
|
|
|
|
|
- return (parent_rate >> p) / m;
|
|
|
+ rate = (parent_rate >> p) / m;
|
|
|
+ if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
|
|
+ rate /= cmp->fixed_post_div;
|
|
|
+
|
|
|
+ return rate;
|
|
|
}
|
|
|
|
|
|
static int ccu_mp_determine_rate(struct clk_hw *hw,
|
|
@@ -129,6 +141,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
|
max_m = cmp->m.max ?: 1 << cmp->m.width;
|
|
|
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
|
|
|
|
|
|
+ /* Adjust target rate according to post-dividers */
|
|
|
+ if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
|
|
+ rate = rate * cmp->fixed_post_div;
|
|
|
+
|
|
|
ccu_mp_find_best(parent_rate, rate, max_m, max_p, &m, &p);
|
|
|
|
|
|
spin_lock_irqsave(cmp->common.lock, flags);
|