@@ -204,13 +204,114 @@ static const struct aspeed_clk_soc_data ast2400_data = {
204
204
.calc_pll = aspeed_ast2400_calc_pll ,
205
205
};
206
206
207
+ static int aspeed_clk_enable (struct clk_hw * hw )
208
+ {
209
+ struct aspeed_clk_gate * gate = to_aspeed_clk_gate (hw );
210
+ unsigned long flags ;
211
+ u32 clk = BIT (gate -> clock_idx );
212
+ u32 rst = BIT (gate -> reset_idx );
213
+
214
+ spin_lock_irqsave (gate -> lock , flags );
215
+
216
+ if (gate -> reset_idx >= 0 ) {
217
+ /* Put IP in reset */
218
+ regmap_update_bits (gate -> map , ASPEED_RESET_CTRL , rst , rst );
219
+
220
+ /* Delay 100us */
221
+ udelay (100 );
222
+ }
223
+
224
+ /* Enable clock */
225
+ regmap_update_bits (gate -> map , ASPEED_CLK_STOP_CTRL , clk , 0 );
226
+
227
+ if (gate -> reset_idx >= 0 ) {
228
+ /* A delay of 10ms is specified by the ASPEED docs */
229
+ mdelay (10 );
230
+
231
+ /* Take IP out of reset */
232
+ regmap_update_bits (gate -> map , ASPEED_RESET_CTRL , rst , 0 );
233
+ }
234
+
235
+ spin_unlock_irqrestore (gate -> lock , flags );
236
+
237
+ return 0 ;
238
+ }
239
+
240
+ static void aspeed_clk_disable (struct clk_hw * hw )
241
+ {
242
+ struct aspeed_clk_gate * gate = to_aspeed_clk_gate (hw );
243
+ unsigned long flags ;
244
+ u32 clk = BIT (gate -> clock_idx );
245
+
246
+ spin_lock_irqsave (gate -> lock , flags );
247
+
248
+ regmap_update_bits (gate -> map , ASPEED_CLK_STOP_CTRL , clk , clk );
249
+
250
+ spin_unlock_irqrestore (gate -> lock , flags );
251
+ }
252
+
253
+ static int aspeed_clk_is_enabled (struct clk_hw * hw )
254
+ {
255
+ struct aspeed_clk_gate * gate = to_aspeed_clk_gate (hw );
256
+ u32 clk = BIT (gate -> clock_idx );
257
+ u32 reg ;
258
+
259
+ regmap_read (gate -> map , ASPEED_CLK_STOP_CTRL , & reg );
260
+
261
+ return (reg & clk ) ? 0 : 1 ;
262
+ }
263
+
264
+ static const struct clk_ops aspeed_clk_gate_ops = {
265
+ .enable = aspeed_clk_enable ,
266
+ .disable = aspeed_clk_disable ,
267
+ .is_enabled = aspeed_clk_is_enabled ,
268
+ };
269
+
270
+ static struct clk_hw * aspeed_clk_hw_register_gate (struct device * dev ,
271
+ const char * name , const char * parent_name , unsigned long flags ,
272
+ struct regmap * map , u8 clock_idx , u8 reset_idx ,
273
+ u8 clk_gate_flags , spinlock_t * lock )
274
+ {
275
+ struct aspeed_clk_gate * gate ;
276
+ struct clk_init_data init ;
277
+ struct clk_hw * hw ;
278
+ int ret ;
279
+
280
+ gate = kzalloc (sizeof (* gate ), GFP_KERNEL );
281
+ if (!gate )
282
+ return ERR_PTR (- ENOMEM );
283
+
284
+ init .name = name ;
285
+ init .ops = & aspeed_clk_gate_ops ;
286
+ init .flags = flags ;
287
+ init .parent_names = parent_name ? & parent_name : NULL ;
288
+ init .num_parents = parent_name ? 1 : 0 ;
289
+
290
+ gate -> map = map ;
291
+ gate -> clock_idx = clock_idx ;
292
+ gate -> reset_idx = reset_idx ;
293
+ gate -> flags = clk_gate_flags ;
294
+ gate -> lock = lock ;
295
+ gate -> hw .init = & init ;
296
+
297
+ hw = & gate -> hw ;
298
+ ret = clk_hw_register (dev , hw );
299
+ if (ret ) {
300
+ kfree (gate );
301
+ hw = ERR_PTR (ret );
302
+ }
303
+
304
+ return hw ;
305
+ }
306
+
207
307
static int aspeed_clk_probe (struct platform_device * pdev )
208
308
{
209
309
const struct aspeed_clk_soc_data * soc_data ;
210
310
struct device * dev = & pdev -> dev ;
211
311
struct regmap * map ;
212
312
struct clk_hw * hw ;
213
313
u32 val , rate ;
314
+ int i ;
214
315
215
316
map = syscon_node_to_regmap (dev -> of_node );
216
317
if (IS_ERR (map )) {
@@ -283,6 +384,35 @@ static int aspeed_clk_probe(struct platform_device *pdev)
283
384
return PTR_ERR (hw );
284
385
aspeed_clk_data -> hws [ASPEED_CLK_BCLK ] = hw ;
285
386
387
+ /*
388
+ * TODO: There are a number of clocks that not included in this driver
389
+ * as more information is required:
390
+ * D2-PLL
391
+ * D-PLL
392
+ * YCLK
393
+ * RGMII
394
+ * RMII
395
+ * UART[1..5] clock source mux
396
+ * Video Engine (ECLK) mux and clock divider
397
+ */
398
+
399
+ for (i = 0 ; i < ARRAY_SIZE (aspeed_gates ); i ++ ) {
400
+ const struct aspeed_gate_data * gd = & aspeed_gates [i ];
401
+
402
+ hw = aspeed_clk_hw_register_gate (dev ,
403
+ gd -> name ,
404
+ gd -> parent_name ,
405
+ gd -> flags ,
406
+ map ,
407
+ gd -> clock_idx ,
408
+ gd -> reset_idx ,
409
+ CLK_GATE_SET_TO_DISABLE ,
410
+ & aspeed_clk_lock );
411
+ if (IS_ERR (hw ))
412
+ return PTR_ERR (hw );
413
+ aspeed_clk_data -> hws [i ] = hw ;
414
+ }
415
+
286
416
return 0 ;
287
417
};
288
418
0 commit comments