@@ -480,6 +480,242 @@ clk_multiple_parents_mux_test_suite = {
480480 .test_cases = clk_multiple_parents_mux_test_cases ,
481481};
482482
483+ static int
484+ clk_orphan_transparent_multiple_parent_mux_test_init (struct kunit * test )
485+ {
486+ struct clk_multiple_parent_ctx * ctx ;
487+ const char * parents [2 ] = { "missing-parent" , "proper-parent" };
488+ int ret ;
489+
490+ ctx = kunit_kzalloc (test , sizeof (* ctx ), GFP_KERNEL );
491+ if (!ctx )
492+ return - ENOMEM ;
493+ test -> priv = ctx ;
494+
495+ ctx -> parents_ctx [1 ].hw .init = CLK_HW_INIT_NO_PARENT ("proper-parent" ,
496+ & clk_dummy_rate_ops ,
497+ 0 );
498+ ctx -> parents_ctx [1 ].rate = DUMMY_CLOCK_INIT_RATE ;
499+ ret = clk_hw_register (NULL , & ctx -> parents_ctx [1 ].hw );
500+ if (ret )
501+ return ret ;
502+
503+ ctx -> hw .init = CLK_HW_INIT_PARENTS ("test-orphan-mux" , parents ,
504+ & clk_multiple_parents_mux_ops ,
505+ CLK_SET_RATE_PARENT );
506+ ret = clk_hw_register (NULL , & ctx -> hw );
507+ if (ret )
508+ return ret ;
509+
510+ return 0 ;
511+ }
512+
513+ static void
514+ clk_orphan_transparent_multiple_parent_mux_test_exit (struct kunit * test )
515+ {
516+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
517+
518+ clk_hw_unregister (& ctx -> hw );
519+ clk_hw_unregister (& ctx -> parents_ctx [1 ].hw );
520+ }
521+
522+ /*
523+ * Test that, for a mux whose current parent hasn't been registered yet and is
524+ * thus orphan, clk_get_parent() will return NULL.
525+ */
526+ static void
527+ clk_test_orphan_transparent_multiple_parent_mux_get_parent (struct kunit * test )
528+ {
529+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
530+ struct clk_hw * hw = & ctx -> hw ;
531+ struct clk * clk = clk_hw_get_clk (hw , NULL );
532+
533+ KUNIT_EXPECT_PTR_EQ (test , clk_get_parent (clk ), NULL );
534+
535+ clk_put (clk );
536+ }
537+
538+ /*
539+ * Test that, for a mux whose current parent hasn't been registered yet,
540+ * calling clk_set_parent() to a valid parent will properly update the
541+ * mux parent and its orphan status.
542+ */
543+ static void
544+ clk_test_orphan_transparent_multiple_parent_mux_set_parent (struct kunit * test )
545+ {
546+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
547+ struct clk_hw * hw = & ctx -> hw ;
548+ struct clk * clk = clk_hw_get_clk (hw , NULL );
549+ struct clk * parent , * new_parent ;
550+ int ret ;
551+
552+ parent = clk_hw_get_clk (& ctx -> parents_ctx [1 ].hw , NULL );
553+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , parent );
554+
555+ ret = clk_set_parent (clk , parent );
556+ KUNIT_ASSERT_EQ (test , ret , 0 );
557+
558+ new_parent = clk_get_parent (clk );
559+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , parent );
560+ KUNIT_EXPECT_TRUE (test , clk_is_match (parent , new_parent ));
561+
562+ clk_put (parent );
563+ clk_put (clk );
564+ }
565+
566+ /*
567+ * Test that, for a mux that started orphan but got switched to a valid
568+ * parent, the rate of the mux and its new parent are consistent.
569+ */
570+ static void
571+ clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate (struct kunit * test )
572+ {
573+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
574+ struct clk_hw * hw = & ctx -> hw ;
575+ struct clk * clk = clk_hw_get_clk (hw , NULL );
576+ struct clk * parent ;
577+ unsigned long parent_rate , rate ;
578+ int ret ;
579+
580+ parent = clk_hw_get_clk (& ctx -> parents_ctx [1 ].hw , NULL );
581+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , parent );
582+
583+ parent_rate = clk_get_rate (parent );
584+ KUNIT_ASSERT_GT (test , parent_rate , 0 );
585+
586+ ret = clk_set_parent (clk , parent );
587+ KUNIT_ASSERT_EQ (test , ret , 0 );
588+
589+ rate = clk_get_rate (clk );
590+ KUNIT_ASSERT_GT (test , rate , 0 );
591+ KUNIT_EXPECT_EQ (test , parent_rate , rate );
592+
593+ clk_put (parent );
594+ clk_put (clk );
595+ }
596+
597+ /*
598+ * Test that, for a mux that started orphan but got switched to a valid
599+ * parent, calling clk_set_rate_range() will affect the parent state if
600+ * its rate is out of range.
601+ */
602+ static void
603+ clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified (struct kunit * test )
604+ {
605+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
606+ struct clk_hw * hw = & ctx -> hw ;
607+ struct clk * clk = clk_hw_get_clk (hw , NULL );
608+ struct clk * parent ;
609+ unsigned long rate ;
610+ int ret ;
611+
612+ parent = clk_hw_get_clk (& ctx -> parents_ctx [1 ].hw , NULL );
613+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , parent );
614+
615+ ret = clk_set_parent (clk , parent );
616+ KUNIT_ASSERT_EQ (test , ret , 0 );
617+
618+ ret = clk_set_rate_range (clk , DUMMY_CLOCK_RATE_1 , DUMMY_CLOCK_RATE_2 );
619+ KUNIT_ASSERT_EQ (test , ret , 0 );
620+
621+ rate = clk_get_rate (clk );
622+ KUNIT_ASSERT_GT (test , rate , 0 );
623+ KUNIT_EXPECT_GE (test , rate , DUMMY_CLOCK_RATE_1 );
624+ KUNIT_EXPECT_LE (test , rate , DUMMY_CLOCK_RATE_2 );
625+
626+ clk_put (parent );
627+ clk_put (clk );
628+ }
629+
630+ /*
631+ * Test that, for a mux whose current parent hasn't been registered yet,
632+ * calling clk_set_rate_range() will succeed, and will be taken into
633+ * account when rounding a rate.
634+ */
635+ static void
636+ clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate (struct kunit * test )
637+ {
638+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
639+ struct clk_hw * hw = & ctx -> hw ;
640+ struct clk * clk = clk_hw_get_clk (hw , NULL );
641+ unsigned long rate ;
642+ int ret ;
643+
644+ ret = clk_set_rate_range (clk , DUMMY_CLOCK_RATE_1 , DUMMY_CLOCK_RATE_2 );
645+ KUNIT_ASSERT_EQ (test , ret , 0 );
646+
647+ rate = clk_round_rate (clk , DUMMY_CLOCK_RATE_1 - 1000 );
648+ KUNIT_ASSERT_GT (test , rate , 0 );
649+ KUNIT_EXPECT_GE (test , rate , DUMMY_CLOCK_RATE_1 );
650+ KUNIT_EXPECT_LE (test , rate , DUMMY_CLOCK_RATE_2 );
651+
652+ clk_put (clk );
653+ }
654+
655+ /*
656+ * Test that, for a mux that started orphan, was assigned and rate and
657+ * then got switched to a valid parent, its rate is eventually within
658+ * range.
659+ *
660+ * FIXME: Even though we update the rate as part of clk_set_parent(), we
661+ * don't evaluate whether that new rate is within range and needs to be
662+ * adjusted.
663+ */
664+ static void
665+ clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate (struct kunit * test )
666+ {
667+ struct clk_multiple_parent_ctx * ctx = test -> priv ;
668+ struct clk_hw * hw = & ctx -> hw ;
669+ struct clk * clk = clk_hw_get_clk (hw , NULL );
670+ struct clk * parent ;
671+ unsigned long rate ;
672+ int ret ;
673+
674+ kunit_skip (test , "This needs to be fixed in the core." );
675+
676+ clk_hw_set_rate_range (hw , DUMMY_CLOCK_RATE_1 , DUMMY_CLOCK_RATE_2 );
677+
678+ parent = clk_hw_get_clk (& ctx -> parents_ctx [1 ].hw , NULL );
679+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , parent );
680+
681+ ret = clk_set_parent (clk , parent );
682+ KUNIT_ASSERT_EQ (test , ret , 0 );
683+
684+ rate = clk_get_rate (clk );
685+ KUNIT_ASSERT_GT (test , rate , 0 );
686+ KUNIT_EXPECT_GE (test , rate , DUMMY_CLOCK_RATE_1 );
687+ KUNIT_EXPECT_LE (test , rate , DUMMY_CLOCK_RATE_2 );
688+
689+ clk_put (parent );
690+ clk_put (clk );
691+ }
692+
693+ static struct kunit_case clk_orphan_transparent_multiple_parent_mux_test_cases [] = {
694+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_get_parent ),
695+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_set_parent ),
696+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate ),
697+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified ),
698+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate ),
699+ KUNIT_CASE (clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate ),
700+ {}
701+ };
702+
703+ /*
704+ * Test suite for a basic mux clock with two parents. The default parent
705+ * isn't registered, only the second parent is. By default, the clock
706+ * will thus be orphan.
707+ *
708+ * These tests exercise the behaviour of the consumer API when dealing
709+ * with an orphan clock, and how we deal with the transition to a valid
710+ * parent.
711+ */
712+ static struct kunit_suite clk_orphan_transparent_multiple_parent_mux_test_suite = {
713+ .name = "clk-orphan-transparent-multiple-parent-mux-test" ,
714+ .init = clk_orphan_transparent_multiple_parent_mux_test_init ,
715+ .exit = clk_orphan_transparent_multiple_parent_mux_test_exit ,
716+ .test_cases = clk_orphan_transparent_multiple_parent_mux_test_cases ,
717+ };
718+
483719struct clk_single_parent_ctx {
484720 struct clk_dummy_context parent_ctx ;
485721 struct clk_hw hw ;
@@ -1460,6 +1696,7 @@ static struct kunit_suite clk_range_minimize_test_suite = {
14601696kunit_test_suites (
14611697 & clk_test_suite ,
14621698 & clk_multiple_parents_mux_test_suite ,
1699+ & clk_orphan_transparent_multiple_parent_mux_test_suite ,
14631700 & clk_orphan_transparent_single_parent_test_suite ,
14641701 & clk_range_test_suite ,
14651702 & clk_range_maximize_test_suite ,
0 commit comments