@@ -578,169 +578,140 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
578578 return false;
579579}
580580
581- static int opp_parse_supplies (struct dev_pm_opp * opp , struct device * dev ,
582- struct opp_table * opp_table )
581+ static u32 * _parse_named_prop (struct dev_pm_opp * opp , struct device * dev ,
582+ struct opp_table * opp_table ,
583+ const char * prop_type , bool * triplet )
583584{
584- u32 * microvolt , * microamp = NULL , * microwatt = NULL ;
585- int supplies = opp_table -> regulator_count ;
586- int vcount , icount , pcount , ret , i , j ;
587585 struct property * prop = NULL ;
588586 char name [NAME_MAX ];
587+ int count , ret ;
588+ u32 * out ;
589589
590- /* Search for "opp-microvolt -<name>" */
590+ /* Search for "opp-<prop_type> -<name>" */
591591 if (opp_table -> prop_name ) {
592- snprintf (name , sizeof (name ), "opp-microvolt -%s" ,
592+ snprintf (name , sizeof (name ), "opp-%s -%s" , prop_type ,
593593 opp_table -> prop_name );
594594 prop = of_find_property (opp -> np , name , NULL );
595595 }
596596
597597 if (!prop ) {
598- /* Search for "opp-microvolt " */
599- sprintf (name , "opp-microvolt" );
598+ /* Search for "opp-<prop_type> " */
599+ snprintf (name , sizeof ( name ), "opp-%s" , prop_type );
600600 prop = of_find_property (opp -> np , name , NULL );
601-
602- /* Missing property isn't a problem, but an invalid entry is */
603- if (!prop ) {
604- if (unlikely (supplies == -1 )) {
605- /* Initialize regulator_count */
606- opp_table -> regulator_count = 0 ;
607- return 0 ;
608- }
609-
610- if (!supplies )
611- return 0 ;
612-
613- dev_err (dev , "%s: opp-microvolt missing although OPP managing regulators\n" ,
614- __func__ );
615- return - EINVAL ;
616- }
601+ if (!prop )
602+ return NULL ;
617603 }
618604
619- if (unlikely (supplies == -1 )) {
620- /* Initialize regulator_count */
621- supplies = opp_table -> regulator_count = 1 ;
622- } else if (unlikely (!supplies )) {
623- dev_err (dev , "%s: opp-microvolt wasn't expected\n" , __func__ );
624- return - EINVAL ;
605+ count = of_property_count_u32_elems (opp -> np , name );
606+ if (count < 0 ) {
607+ dev_err (dev , "%s: Invalid %s property (%d)\n" , __func__ , name ,
608+ count );
609+ return ERR_PTR (count );
625610 }
626611
627- vcount = of_property_count_u32_elems (opp -> np , name );
628- if (vcount < 0 ) {
629- dev_err (dev , "%s: Invalid %s property (%d)\n" ,
630- __func__ , name , vcount );
631- return vcount ;
632- }
633-
634- /* There can be one or three elements per supply */
635- if (vcount != supplies && vcount != supplies * 3 ) {
636- dev_err (dev , "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n" ,
637- __func__ , name , vcount , supplies );
638- return - EINVAL ;
612+ /*
613+ * Initialize regulator_count, if regulator information isn't provided
614+ * by the platform. Now that one of the properties is available, fix the
615+ * regulator_count to 1.
616+ */
617+ if (unlikely (opp_table -> regulator_count == -1 ))
618+ opp_table -> regulator_count = 1 ;
619+
620+ if (count != opp_table -> regulator_count &&
621+ (!triplet || count != opp_table -> regulator_count * 3 )) {
622+ dev_err (dev , "%s: Invalid number of elements in %s property (%u) with supplies (%d)\n" ,
623+ __func__ , prop_type , count , opp_table -> regulator_count );
624+ return ERR_PTR (- EINVAL );
639625 }
640626
641- microvolt = kmalloc_array (vcount , sizeof (* microvolt ), GFP_KERNEL );
642- if (!microvolt )
643- return - ENOMEM ;
627+ out = kmalloc_array (count , sizeof (* out ), GFP_KERNEL );
628+ if (!out )
629+ return ERR_PTR ( - EINVAL ) ;
644630
645- ret = of_property_read_u32_array (opp -> np , name , microvolt , vcount );
631+ ret = of_property_read_u32_array (opp -> np , name , out , count );
646632 if (ret ) {
647633 dev_err (dev , "%s: error parsing %s: %d\n" , __func__ , name , ret );
648- ret = - EINVAL ;
649- goto free_microvolt ;
650- }
651-
652- /* Search for "opp-microamp-<name>" */
653- prop = NULL ;
654- if (opp_table -> prop_name ) {
655- snprintf (name , sizeof (name ), "opp-microamp-%s" ,
656- opp_table -> prop_name );
657- prop = of_find_property (opp -> np , name , NULL );
634+ kfree (out );
635+ return ERR_PTR (- EINVAL );
658636 }
659637
660- if (!prop ) {
661- /* Search for "opp-microamp" */
662- sprintf (name , "opp-microamp" );
663- prop = of_find_property (opp -> np , name , NULL );
664- }
638+ if (triplet )
639+ * triplet = count != opp_table -> regulator_count ;
665640
666- if (prop ) {
667- icount = of_property_count_u32_elems (opp -> np , name );
668- if (icount < 0 ) {
669- dev_err (dev , "%s: Invalid %s property (%d)\n" , __func__ ,
670- name , icount );
671- ret = icount ;
672- goto free_microvolt ;
673- }
641+ return out ;
642+ }
674643
675- if (icount != supplies ) {
676- dev_err (dev , "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n" ,
677- __func__ , name , icount , supplies );
678- ret = - EINVAL ;
679- goto free_microvolt ;
680- }
644+ static u32 * opp_parse_microvolt (struct dev_pm_opp * opp , struct device * dev ,
645+ struct opp_table * opp_table , bool * triplet )
646+ {
647+ u32 * microvolt ;
681648
682- microamp = kmalloc_array (icount , sizeof (* microamp ), GFP_KERNEL );
683- if (!microamp ) {
684- ret = - EINVAL ;
685- goto free_microvolt ;
686- }
649+ microvolt = _parse_named_prop (opp , dev , opp_table , "microvolt" , triplet );
650+ if (IS_ERR (microvolt ))
651+ return microvolt ;
687652
688- ret = of_property_read_u32_array (opp -> np , name , microamp ,
689- icount );
690- if (ret ) {
691- dev_err (dev , "%s: error parsing %s: %d\n" , __func__ ,
692- name , ret );
693- ret = - EINVAL ;
694- goto free_microamp ;
653+ if (!microvolt ) {
654+ /*
655+ * Missing property isn't a problem, but an invalid
656+ * entry is. This property isn't optional if regulator
657+ * information is provided. Check only for the first OPP, as
658+ * regulator_count may get initialized after that to a valid
659+ * value.
660+ */
661+ if (list_empty (& opp_table -> opp_list ) &&
662+ opp_table -> regulator_count > 0 ) {
663+ dev_err (dev , "%s: opp-microvolt missing although OPP managing regulators\n" ,
664+ __func__ );
665+ return ERR_PTR (- EINVAL );
695666 }
696667 }
697668
698- /* Search for "opp-microwatt" */
699- sprintf (name , "opp-microwatt" );
700- prop = of_find_property (opp -> np , name , NULL );
701-
702- if (prop ) {
703- pcount = of_property_count_u32_elems (opp -> np , name );
704- if (pcount < 0 ) {
705- dev_err (dev , "%s: Invalid %s property (%d)\n" , __func__ ,
706- name , pcount );
707- ret = pcount ;
708- goto free_microamp ;
709- }
669+ return microvolt ;
670+ }
710671
711- if ( pcount != supplies ) {
712- dev_err ( dev , "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n" ,
713- __func__ , name , pcount , supplies );
714- ret = - EINVAL ;
715- goto free_microamp ;
716- }
672+ static int opp_parse_supplies ( struct dev_pm_opp * opp , struct device * dev ,
673+ struct opp_table * opp_table )
674+ {
675+ u32 * microvolt , * microamp , * microwatt ;
676+ int ret = 0 , i , j ;
677+ bool triplet ;
717678
718- microwatt = kmalloc_array (pcount , sizeof (* microwatt ),
719- GFP_KERNEL );
720- if (!microwatt ) {
721- ret = - EINVAL ;
722- goto free_microamp ;
723- }
679+ microvolt = opp_parse_microvolt (opp , dev , opp_table , & triplet );
680+ if (IS_ERR (microvolt ))
681+ return PTR_ERR (microvolt );
724682
725- ret = of_property_read_u32_array (opp -> np , name , microwatt ,
726- pcount );
727- if (ret ) {
728- dev_err (dev , "%s: error parsing %s: %d\n" , __func__ ,
729- name , ret );
730- ret = - EINVAL ;
731- goto free_microwatt ;
732- }
683+ microamp = _parse_named_prop (opp , dev , opp_table , "microamp" , NULL );
684+ if (IS_ERR (microamp )) {
685+ ret = PTR_ERR (microamp );
686+ goto free_microvolt ;
733687 }
734688
735- for (i = 0 , j = 0 ; i < supplies ; i ++ ) {
736- opp -> supplies [i ].u_volt = microvolt [j ++ ];
689+ microwatt = _parse_named_prop (opp , dev , opp_table , "microwatt" , NULL );
690+ if (IS_ERR (microwatt )) {
691+ ret = PTR_ERR (microwatt );
692+ goto free_microamp ;
693+ }
737694
738- if (vcount == supplies ) {
739- opp -> supplies [i ].u_volt_min = opp -> supplies [i ].u_volt ;
740- opp -> supplies [i ].u_volt_max = opp -> supplies [i ].u_volt ;
741- } else {
742- opp -> supplies [i ].u_volt_min = microvolt [j ++ ];
743- opp -> supplies [i ].u_volt_max = microvolt [j ++ ];
695+ /*
696+ * Initialize regulator_count if it is uninitialized and no properties
697+ * are found.
698+ */
699+ if (unlikely (opp_table -> regulator_count == -1 )) {
700+ opp_table -> regulator_count = 0 ;
701+ return 0 ;
702+ }
703+
704+ for (i = 0 , j = 0 ; i < opp_table -> regulator_count ; i ++ ) {
705+ if (microvolt ) {
706+ opp -> supplies [i ].u_volt = microvolt [j ++ ];
707+
708+ if (triplet ) {
709+ opp -> supplies [i ].u_volt_min = microvolt [j ++ ];
710+ opp -> supplies [i ].u_volt_max = microvolt [j ++ ];
711+ } else {
712+ opp -> supplies [i ].u_volt_min = opp -> supplies [i ].u_volt ;
713+ opp -> supplies [i ].u_volt_max = opp -> supplies [i ].u_volt ;
714+ }
744715 }
745716
746717 if (microamp )
@@ -750,7 +721,6 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
750721 opp -> supplies [i ].u_watt = microwatt [i ];
751722 }
752723
753- free_microwatt :
754724 kfree (microwatt );
755725free_microamp :
756726 kfree (microamp );
0 commit comments