@@ -333,13 +333,17 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
333
333
* @hw: handle between common and hardware-specific interfaces
334
334
* @off: register offset
335
335
* @bit: ON/MON bit
336
+ * @enabled: soft state of the clock, if it is coupled with another clock
336
337
* @priv: CPG/MSTP private data
338
+ * @sibling: pointer to the other coupled clock
337
339
*/
338
340
struct mstp_clock {
339
341
struct clk_hw hw ;
340
342
u16 off ;
341
343
u8 bit ;
344
+ bool enabled ;
342
345
struct rzg2l_cpg_priv * priv ;
346
+ struct mstp_clock * sibling ;
343
347
};
344
348
345
349
#define to_mod_clock (_hw ) container_of(_hw, struct mstp_clock, hw)
@@ -392,11 +396,41 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
392
396
393
397
static int rzg2l_mod_clock_enable (struct clk_hw * hw )
394
398
{
399
+ struct mstp_clock * clock = to_mod_clock (hw );
400
+
401
+ if (clock -> sibling ) {
402
+ struct rzg2l_cpg_priv * priv = clock -> priv ;
403
+ unsigned long flags ;
404
+ bool enabled ;
405
+
406
+ spin_lock_irqsave (& priv -> rmw_lock , flags );
407
+ enabled = clock -> sibling -> enabled ;
408
+ clock -> enabled = true;
409
+ spin_unlock_irqrestore (& priv -> rmw_lock , flags );
410
+ if (enabled )
411
+ return 0 ;
412
+ }
413
+
395
414
return rzg2l_mod_clock_endisable (hw , true);
396
415
}
397
416
398
417
static void rzg2l_mod_clock_disable (struct clk_hw * hw )
399
418
{
419
+ struct mstp_clock * clock = to_mod_clock (hw );
420
+
421
+ if (clock -> sibling ) {
422
+ struct rzg2l_cpg_priv * priv = clock -> priv ;
423
+ unsigned long flags ;
424
+ bool enabled ;
425
+
426
+ spin_lock_irqsave (& priv -> rmw_lock , flags );
427
+ enabled = clock -> sibling -> enabled ;
428
+ clock -> enabled = false;
429
+ spin_unlock_irqrestore (& priv -> rmw_lock , flags );
430
+ if (enabled )
431
+ return ;
432
+ }
433
+
400
434
rzg2l_mod_clock_endisable (hw , false);
401
435
}
402
436
@@ -412,6 +446,9 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw)
412
446
return 1 ;
413
447
}
414
448
449
+ if (clock -> sibling )
450
+ return clock -> enabled ;
451
+
415
452
value = readl (priv -> base + CLK_MON_R (clock -> off ));
416
453
417
454
return value & bitmask ;
@@ -423,6 +460,28 @@ static const struct clk_ops rzg2l_mod_clock_ops = {
423
460
.is_enabled = rzg2l_mod_clock_is_enabled ,
424
461
};
425
462
463
+ static struct mstp_clock
464
+ * rzg2l_mod_clock__get_sibling (struct mstp_clock * clock ,
465
+ struct rzg2l_cpg_priv * priv )
466
+ {
467
+ struct clk_hw * hw ;
468
+ unsigned int i ;
469
+
470
+ for (i = 0 ; i < priv -> num_mod_clks ; i ++ ) {
471
+ struct mstp_clock * clk ;
472
+
473
+ if (priv -> clks [priv -> num_core_clks + i ] == ERR_PTR (- ENOENT ))
474
+ continue ;
475
+
476
+ hw = __clk_get_hw (priv -> clks [priv -> num_core_clks + i ]);
477
+ clk = to_mod_clock (hw );
478
+ if (clock -> off == clk -> off && clock -> bit == clk -> bit )
479
+ return clk ;
480
+ }
481
+
482
+ return NULL ;
483
+ }
484
+
426
485
static void __init
427
486
rzg2l_cpg_register_mod_clk (const struct rzg2l_mod_clk * mod ,
428
487
const struct rzg2l_cpg_info * info ,
@@ -484,6 +543,18 @@ rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
484
543
485
544
dev_dbg (dev , "Module clock %pC at %lu Hz\n" , clk , clk_get_rate (clk ));
486
545
priv -> clks [id ] = clk ;
546
+
547
+ if (mod -> is_coupled ) {
548
+ struct mstp_clock * sibling ;
549
+
550
+ clock -> enabled = rzg2l_mod_clock_is_enabled (& clock -> hw );
551
+ sibling = rzg2l_mod_clock__get_sibling (clock , priv );
552
+ if (sibling ) {
553
+ clock -> sibling = sibling ;
554
+ sibling -> sibling = clock ;
555
+ }
556
+ }
557
+
487
558
return ;
488
559
489
560
fail :
0 commit comments