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)
unsigned long parent_rate)
{
struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+ unsigned long rate;
unsigned int m, p;
u32 reg;
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,
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);
struct ccu_div_internal m;
struct ccu_div_internal p;
struct ccu_mux_internal mux;
+
+ unsigned int fixed_post_div;
+
struct ccu_common common;
};
+#define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
+ _mshift, _mwidth, \
+ _pshift, _pwidth, \
+ _muxshift, _muxwidth, \
+ _gate, _postdiv, _flags) \
+ struct ccu_mp _struct = { \
+ .enable = _gate, \
+ .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
+ .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
+ .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
+ .fixed_post_div = _postdiv, \
+ .common = { \
+ .reg = _reg, \
+ .features = CCU_FEATURE_FIXED_POSTDIV, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parents, \
+ &ccu_mp_ops, \
+ _flags), \
+ } \
+ }
+
#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \