1010#include "ccu_gate.h"
1111#include "ccu_mp.h"
1212
13+ static unsigned int next_div (unsigned int div , bool shift )
14+ {
15+ if (shift )
16+ return div << 1 ;
17+ return div + 1 ;
18+ }
19+
1320static unsigned long ccu_mp_find_best (unsigned long parent , unsigned long rate ,
1421 unsigned int max_m , unsigned int max_p ,
22+ bool shift ,
1523 unsigned int * m , unsigned int * p )
1624{
1725 unsigned long best_rate = 0 ;
1826 unsigned int best_m = 0 , best_p = 0 ;
1927 unsigned int _m , _p ;
2028
21- for (_p = 1 ; _p <= max_p ; _p <<= 1 ) {
29+ for (_p = 1 ; _p <= max_p ; _p = next_div ( _p , shift ) ) {
2230 for (_m = 1 ; _m <= max_m ; _m ++ ) {
2331 unsigned long tmp_rate = parent / _p / _m ;
2432
@@ -43,7 +51,8 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
4351 unsigned long * parent ,
4452 unsigned long rate ,
4553 unsigned int max_m ,
46- unsigned int max_p )
54+ unsigned int max_p ,
55+ bool shift )
4756{
4857 unsigned long parent_rate_saved ;
4958 unsigned long parent_rate , now ;
@@ -60,7 +69,7 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
6069 maxdiv = max_m * max_p ;
6170 maxdiv = min (ULONG_MAX / rate , maxdiv );
6271
63- for (_p = 1 ; _p <= max_p ; _p <<= 1 ) {
72+ for (_p = 1 ; _p <= max_p ; _p = next_div ( _p , shift ) ) {
6473 for (_m = 1 ; _m <= max_m ; _m ++ ) {
6574 div = _m * _p ;
6675
@@ -103,18 +112,26 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
103112 struct ccu_mp * cmp = data ;
104113 unsigned int max_m , max_p ;
105114 unsigned int m , p ;
115+ bool shift = true;
106116
107117 if (cmp -> common .features & CCU_FEATURE_FIXED_POSTDIV )
108118 rate *= cmp -> fixed_post_div ;
109119
120+ if (cmp -> common .features & CCU_FEATURE_DUAL_DIV )
121+ shift = false;
122+
110123 max_m = cmp -> m .max ?: 1 << cmp -> m .width ;
111- max_p = cmp -> p .max ?: 1 << ((1 << cmp -> p .width ) - 1 );
124+ if (shift )
125+ max_p = cmp -> p .max ?: 1 << ((1 << cmp -> p .width ) - 1 );
126+ else
127+ max_p = cmp -> p .max ?: 1 << cmp -> p .width ;
112128
113129 if (!clk_hw_can_set_rate_parent (& cmp -> common .hw )) {
114- rate = ccu_mp_find_best (* parent_rate , rate , max_m , max_p , & m , & p );
130+ rate = ccu_mp_find_best (* parent_rate , rate , max_m , max_p , shift ,
131+ & m , & p );
115132 } else {
116133 rate = ccu_mp_find_best_with_parent_adj (hw , parent_rate , rate ,
117- max_m , max_p );
134+ max_m , max_p , shift );
118135 }
119136
120137 if (cmp -> common .features & CCU_FEATURE_FIXED_POSTDIV )
@@ -167,7 +184,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
167184 p = reg >> cmp -> p .shift ;
168185 p &= (1 << cmp -> p .width ) - 1 ;
169186
170- rate = (parent_rate >> p ) / m ;
187+ if (cmp -> common .features & CCU_FEATURE_DUAL_DIV )
188+ rate = (parent_rate / p ) / m ;
189+ else
190+ rate = (parent_rate >> p ) / m ;
191+
171192 if (cmp -> common .features & CCU_FEATURE_FIXED_POSTDIV )
172193 rate /= cmp -> fixed_post_div ;
173194
@@ -190,28 +211,38 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
190211 unsigned long flags ;
191212 unsigned int max_m , max_p ;
192213 unsigned int m , p ;
214+ bool shift = true;
193215 u32 reg ;
194216
217+ if (cmp -> common .features & CCU_FEATURE_DUAL_DIV )
218+ shift = false;
219+
195220 /* Adjust parent_rate according to pre-dividers */
196221 parent_rate = ccu_mux_helper_apply_prediv (& cmp -> common , & cmp -> mux , -1 ,
197222 parent_rate );
198223
199224 max_m = cmp -> m .max ?: 1 << cmp -> m .width ;
200- max_p = cmp -> p .max ?: 1 << ((1 << cmp -> p .width ) - 1 );
225+ if (shift )
226+ max_p = cmp -> p .max ?: 1 << ((1 << cmp -> p .width ) - 1 );
227+ else
228+ max_p = cmp -> p .max ?: 1 << cmp -> p .width ;
201229
202230 /* Adjust target rate according to post-dividers */
203231 if (cmp -> common .features & CCU_FEATURE_FIXED_POSTDIV )
204232 rate = rate * cmp -> fixed_post_div ;
205233
206- ccu_mp_find_best (parent_rate , rate , max_m , max_p , & m , & p );
234+ ccu_mp_find_best (parent_rate , rate , max_m , max_p , shift , & m , & p );
207235
208236 spin_lock_irqsave (cmp -> common .lock , flags );
209237
210238 reg = readl (cmp -> common .base + cmp -> common .reg );
211239 reg &= ~GENMASK (cmp -> m .width + cmp -> m .shift - 1 , cmp -> m .shift );
212240 reg &= ~GENMASK (cmp -> p .width + cmp -> p .shift - 1 , cmp -> p .shift );
213241 reg |= (m - cmp -> m .offset ) << cmp -> m .shift ;
214- reg |= ilog2 (p ) << cmp -> p .shift ;
242+ if (shift )
243+ reg |= ilog2 (p ) << cmp -> p .shift ;
244+ else
245+ reg |= (p - cmp -> p .offset ) << cmp -> p .shift ;
215246
216247 writel (reg , cmp -> common .base + cmp -> common .reg );
217248
0 commit comments