@@ -562,6 +562,9 @@ static void _remove_device_opp(struct device_opp *dev_opp)
562562 if (dev_opp -> supported_hw )
563563 return ;
564564
565+ if (dev_opp -> prop_name )
566+ return ;
567+
565568 list_dev = list_first_entry (& dev_opp -> dev_list , struct device_list_opp ,
566569 node );
567570
@@ -794,43 +797,69 @@ static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
794797}
795798
796799/* TODO: Support multiple regulators */
797- static int opp_parse_supplies (struct dev_pm_opp * opp , struct device * dev )
800+ static int opp_parse_supplies (struct dev_pm_opp * opp , struct device * dev ,
801+ struct device_opp * dev_opp )
798802{
799803 u32 microvolt [3 ] = {0 };
800804 u32 val ;
801805 int count , ret ;
806+ struct property * prop = NULL ;
807+ char name [NAME_MAX ];
808+
809+ /* Search for "opp-microvolt-<name>" */
810+ if (dev_opp -> prop_name ) {
811+ sprintf (name , "opp-microvolt-%s" , dev_opp -> prop_name );
812+ prop = of_find_property (opp -> np , name , NULL );
813+ }
814+
815+ if (!prop ) {
816+ /* Search for "opp-microvolt" */
817+ name [13 ] = '\0' ;
818+ prop = of_find_property (opp -> np , name , NULL );
802819
803- /* Missing property isn't a problem, but an invalid entry is */
804- if (!of_find_property (opp -> np , "opp-microvolt" , NULL ))
805- return 0 ;
820+ /* Missing property isn't a problem, but an invalid entry is */
821+ if (!prop )
822+ return 0 ;
823+ }
806824
807- count = of_property_count_u32_elems (opp -> np , "opp-microvolt" );
825+ count = of_property_count_u32_elems (opp -> np , name );
808826 if (count < 0 ) {
809- dev_err (dev , "%s: Invalid opp-microvolt property (%d)\n" ,
810- __func__ , count );
827+ dev_err (dev , "%s: Invalid %s property (%d)\n" ,
828+ __func__ , name , count );
811829 return count ;
812830 }
813831
814832 /* There can be one or three elements here */
815833 if (count != 1 && count != 3 ) {
816- dev_err (dev , "%s: Invalid number of elements in opp-microvolt property (%d)\n" ,
817- __func__ , count );
834+ dev_err (dev , "%s: Invalid number of elements in %s property (%d)\n" ,
835+ __func__ , name , count );
818836 return - EINVAL ;
819837 }
820838
821- ret = of_property_read_u32_array (opp -> np , "opp-microvolt" , microvolt ,
822- count );
839+ ret = of_property_read_u32_array (opp -> np , name , microvolt , count );
823840 if (ret ) {
824- dev_err (dev , "%s: error parsing opp-microvolt: %d\n" , __func__ ,
825- ret );
841+ dev_err (dev , "%s: error parsing %s: %d\n" , __func__ , name , ret );
826842 return - EINVAL ;
827843 }
828844
829845 opp -> u_volt = microvolt [0 ];
830846 opp -> u_volt_min = microvolt [1 ];
831847 opp -> u_volt_max = microvolt [2 ];
832848
833- if (!of_property_read_u32 (opp -> np , "opp-microamp" , & val ))
849+ /* Search for "opp-microamp-<name>" */
850+ prop = NULL ;
851+ if (dev_opp -> prop_name ) {
852+ sprintf (name , "opp-microamp-%s" , dev_opp -> prop_name );
853+ prop = of_find_property (opp -> np , name , NULL );
854+ }
855+
856+ if (!prop ) {
857+ /* Search for "opp-microamp" */
858+ name [12 ] = '\0' ;
859+ prop = of_find_property (opp -> np , name , NULL );
860+ }
861+
862+ if (prop && !of_property_read_u32 (opp -> np , name , & val ))
834863 opp -> u_amp = val ;
835864
836865 return 0 ;
@@ -948,6 +977,112 @@ void dev_pm_opp_put_supported_hw(struct device *dev)
948977}
949978EXPORT_SYMBOL_GPL (dev_pm_opp_put_supported_hw );
950979
980+ /**
981+ * dev_pm_opp_set_prop_name() - Set prop-extn name
982+ * @dev: Device for which the regulator has to be set.
983+ * @name: name to postfix to properties.
984+ *
985+ * This is required only for the V2 bindings, and it enables a platform to
986+ * specify the extn to be used for certain property names. The properties to
987+ * which the extension will apply are opp-microvolt and opp-microamp. OPP core
988+ * should postfix the property name with -<name> while looking for them.
989+ *
990+ * Locking: The internal device_opp and opp structures are RCU protected.
991+ * Hence this function internally uses RCU updater strategy with mutex locks
992+ * to keep the integrity of the internal data structures. Callers should ensure
993+ * that this function is *NOT* called under RCU protection or in contexts where
994+ * mutex cannot be locked.
995+ */
996+ int dev_pm_opp_set_prop_name (struct device * dev , const char * name )
997+ {
998+ struct device_opp * dev_opp ;
999+ int ret = 0 ;
1000+
1001+ /* Hold our list modification lock here */
1002+ mutex_lock (& dev_opp_list_lock );
1003+
1004+ dev_opp = _add_device_opp (dev );
1005+ if (!dev_opp ) {
1006+ ret = - ENOMEM ;
1007+ goto unlock ;
1008+ }
1009+
1010+ /* Make sure there are no concurrent readers while updating dev_opp */
1011+ WARN_ON (!list_empty (& dev_opp -> opp_list ));
1012+
1013+ /* Do we already have a prop-name associated with dev_opp? */
1014+ if (dev_opp -> prop_name ) {
1015+ dev_err (dev , "%s: Already have prop-name %s\n" , __func__ ,
1016+ dev_opp -> prop_name );
1017+ ret = - EBUSY ;
1018+ goto err ;
1019+ }
1020+
1021+ dev_opp -> prop_name = kstrdup (name , GFP_KERNEL );
1022+ if (!dev_opp -> prop_name ) {
1023+ ret = - ENOMEM ;
1024+ goto err ;
1025+ }
1026+
1027+ mutex_unlock (& dev_opp_list_lock );
1028+ return 0 ;
1029+
1030+ err :
1031+ _remove_device_opp (dev_opp );
1032+ unlock :
1033+ mutex_unlock (& dev_opp_list_lock );
1034+
1035+ return ret ;
1036+ }
1037+ EXPORT_SYMBOL_GPL (dev_pm_opp_set_prop_name );
1038+
1039+ /**
1040+ * dev_pm_opp_put_prop_name() - Releases resources blocked for prop-name
1041+ * @dev: Device for which the regulator has to be set.
1042+ *
1043+ * This is required only for the V2 bindings, and is called for a matching
1044+ * dev_pm_opp_set_prop_name(). Until this is called, the device_opp structure
1045+ * will not be freed.
1046+ *
1047+ * Locking: The internal device_opp and opp structures are RCU protected.
1048+ * Hence this function internally uses RCU updater strategy with mutex locks
1049+ * to keep the integrity of the internal data structures. Callers should ensure
1050+ * that this function is *NOT* called under RCU protection or in contexts where
1051+ * mutex cannot be locked.
1052+ */
1053+ void dev_pm_opp_put_prop_name (struct device * dev )
1054+ {
1055+ struct device_opp * dev_opp ;
1056+
1057+ /* Hold our list modification lock here */
1058+ mutex_lock (& dev_opp_list_lock );
1059+
1060+ /* Check for existing list for 'dev' first */
1061+ dev_opp = _find_device_opp (dev );
1062+ if (IS_ERR (dev_opp )) {
1063+ dev_err (dev , "Failed to find dev_opp: %ld\n" , PTR_ERR (dev_opp ));
1064+ goto unlock ;
1065+ }
1066+
1067+ /* Make sure there are no concurrent readers while updating dev_opp */
1068+ WARN_ON (!list_empty (& dev_opp -> opp_list ));
1069+
1070+ if (!dev_opp -> prop_name ) {
1071+ dev_err (dev , "%s: Doesn't have a prop-name\n" , __func__ );
1072+ goto unlock ;
1073+ }
1074+
1075+ kfree (dev_opp -> prop_name );
1076+ dev_opp -> prop_name = NULL ;
1077+
1078+ /* Try freeing device_opp if this was the last blocking resource */
1079+ _remove_device_opp (dev_opp );
1080+
1081+ unlock :
1082+ mutex_unlock (& dev_opp_list_lock );
1083+ }
1084+ EXPORT_SYMBOL_GPL (dev_pm_opp_put_prop_name );
1085+
9511086static bool _opp_is_supported (struct device * dev , struct device_opp * dev_opp ,
9521087 struct device_node * np )
9531088{
@@ -1042,7 +1177,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
10421177 if (!of_property_read_u32 (np , "clock-latency-ns" , & val ))
10431178 new_opp -> clock_latency_ns = val ;
10441179
1045- ret = opp_parse_supplies (new_opp , dev );
1180+ ret = opp_parse_supplies (new_opp , dev , dev_opp );
10461181 if (ret )
10471182 goto free_opp ;
10481183
0 commit comments