@@ -107,9 +107,6 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
107
107
if (bypass )
108
108
return parent_rate ;
109
109
110
- if (!enable )
111
- return 0 ;
112
-
113
110
for (od = 0 ; od < pll_info -> od_max ; od ++ ) {
114
111
if (pll_info -> od_encoding [od ] == od_enc )
115
112
break ;
@@ -153,37 +150,40 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
153
150
return div_u64 ((u64 )parent_rate * m , n * od );
154
151
}
155
152
156
- static long
157
- ingenic_pll_round_rate (struct clk_hw * hw , unsigned long req_rate ,
158
- unsigned long * prate )
153
+ static inline const struct ingenic_cgu_clk_info * to_clk_info (
154
+ struct ingenic_clk * ingenic_clk )
159
155
{
160
- struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
161
156
struct ingenic_cgu * cgu = ingenic_clk -> cgu ;
162
157
const struct ingenic_cgu_clk_info * clk_info ;
163
158
164
159
clk_info = & cgu -> clock_info [ingenic_clk -> idx ];
165
160
BUG_ON (clk_info -> type != CGU_CLK_PLL );
166
161
162
+ return clk_info ;
163
+ }
164
+
165
+ static long
166
+ ingenic_pll_round_rate (struct clk_hw * hw , unsigned long req_rate ,
167
+ unsigned long * prate )
168
+ {
169
+ struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
170
+ const struct ingenic_cgu_clk_info * clk_info = to_clk_info (ingenic_clk );
171
+
167
172
return ingenic_pll_calc (clk_info , req_rate , * prate , NULL , NULL , NULL );
168
173
}
169
174
170
175
static int
171
176
ingenic_pll_set_rate (struct clk_hw * hw , unsigned long req_rate ,
172
177
unsigned long parent_rate )
173
178
{
174
- const unsigned timeout = 100 ;
175
179
struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
176
180
struct ingenic_cgu * cgu = ingenic_clk -> cgu ;
177
- const struct ingenic_cgu_clk_info * clk_info ;
178
- const struct ingenic_cgu_pll_info * pll_info ;
181
+ const struct ingenic_cgu_clk_info * clk_info = to_clk_info ( ingenic_clk ) ;
182
+ const struct ingenic_cgu_pll_info * pll_info = & clk_info -> pll ;
179
183
unsigned long rate , flags ;
180
- unsigned m , n , od , i ;
184
+ unsigned int m , n , od ;
181
185
u32 ctl ;
182
186
183
- clk_info = & cgu -> clock_info [ingenic_clk -> idx ];
184
- BUG_ON (clk_info -> type != CGU_CLK_PLL );
185
- pll_info = & clk_info -> pll ;
186
-
187
187
rate = ingenic_pll_calc (clk_info , req_rate , parent_rate ,
188
188
& m , & n , & od );
189
189
if (rate != req_rate )
@@ -202,6 +202,26 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
202
202
ctl &= ~(GENMASK (pll_info -> od_bits - 1 , 0 ) << pll_info -> od_shift );
203
203
ctl |= pll_info -> od_encoding [od - 1 ] << pll_info -> od_shift ;
204
204
205
+ writel (ctl , cgu -> base + pll_info -> reg );
206
+ spin_unlock_irqrestore (& cgu -> lock , flags );
207
+
208
+ return 0 ;
209
+ }
210
+
211
+ static int ingenic_pll_enable (struct clk_hw * hw )
212
+ {
213
+ struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
214
+ struct ingenic_cgu * cgu = ingenic_clk -> cgu ;
215
+ const struct ingenic_cgu_clk_info * clk_info = to_clk_info (ingenic_clk );
216
+ const struct ingenic_cgu_pll_info * pll_info = & clk_info -> pll ;
217
+ const unsigned int timeout = 100 ;
218
+ unsigned long flags ;
219
+ unsigned int i ;
220
+ u32 ctl ;
221
+
222
+ spin_lock_irqsave (& cgu -> lock , flags );
223
+ ctl = readl (cgu -> base + pll_info -> reg );
224
+
205
225
ctl &= ~BIT (pll_info -> bypass_bit );
206
226
ctl |= BIT (pll_info -> enable_bit );
207
227
@@ -223,10 +243,48 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
223
243
return 0 ;
224
244
}
225
245
246
+ static void ingenic_pll_disable (struct clk_hw * hw )
247
+ {
248
+ struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
249
+ struct ingenic_cgu * cgu = ingenic_clk -> cgu ;
250
+ const struct ingenic_cgu_clk_info * clk_info = to_clk_info (ingenic_clk );
251
+ const struct ingenic_cgu_pll_info * pll_info = & clk_info -> pll ;
252
+ unsigned long flags ;
253
+ u32 ctl ;
254
+
255
+ spin_lock_irqsave (& cgu -> lock , flags );
256
+ ctl = readl (cgu -> base + pll_info -> reg );
257
+
258
+ ctl &= ~BIT (pll_info -> enable_bit );
259
+
260
+ writel (ctl , cgu -> base + pll_info -> reg );
261
+ spin_unlock_irqrestore (& cgu -> lock , flags );
262
+ }
263
+
264
+ static int ingenic_pll_is_enabled (struct clk_hw * hw )
265
+ {
266
+ struct ingenic_clk * ingenic_clk = to_ingenic_clk (hw );
267
+ struct ingenic_cgu * cgu = ingenic_clk -> cgu ;
268
+ const struct ingenic_cgu_clk_info * clk_info = to_clk_info (ingenic_clk );
269
+ const struct ingenic_cgu_pll_info * pll_info = & clk_info -> pll ;
270
+ unsigned long flags ;
271
+ u32 ctl ;
272
+
273
+ spin_lock_irqsave (& cgu -> lock , flags );
274
+ ctl = readl (cgu -> base + pll_info -> reg );
275
+ spin_unlock_irqrestore (& cgu -> lock , flags );
276
+
277
+ return !!(ctl & BIT (pll_info -> enable_bit ));
278
+ }
279
+
226
280
static const struct clk_ops ingenic_pll_ops = {
227
281
.recalc_rate = ingenic_pll_recalc_rate ,
228
282
.round_rate = ingenic_pll_round_rate ,
229
283
.set_rate = ingenic_pll_set_rate ,
284
+
285
+ .enable = ingenic_pll_enable ,
286
+ .disable = ingenic_pll_disable ,
287
+ .is_enabled = ingenic_pll_is_enabled ,
230
288
};
231
289
232
290
/*
@@ -601,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
601
659
}
602
660
} else if (caps & CGU_CLK_PLL ) {
603
661
clk_init .ops = & ingenic_pll_ops ;
662
+ clk_init .flags |= CLK_SET_RATE_GATE ;
604
663
605
664
caps &= ~CGU_CLK_PLL ;
606
665
0 commit comments