@@ -917,6 +917,26 @@ static ssize_t bypass_show(struct device *dev,
917917}
918918static DEVICE_ATTR_RO (bypass );
919919
920+ static ssize_t power_budget_milliwatt_show (struct device * dev ,
921+ struct device_attribute * attr ,
922+ char * buf )
923+ {
924+ struct regulator_dev * rdev = dev_get_drvdata (dev );
925+
926+ return sprintf (buf , "%d\n" , rdev -> constraints -> pw_budget_mW );
927+ }
928+ static DEVICE_ATTR_RO (power_budget_milliwatt );
929+
930+ static ssize_t power_requested_milliwatt_show (struct device * dev ,
931+ struct device_attribute * attr ,
932+ char * buf )
933+ {
934+ struct regulator_dev * rdev = dev_get_drvdata (dev );
935+
936+ return sprintf (buf , "%d\n" , rdev -> pw_requested_mW );
937+ }
938+ static DEVICE_ATTR_RO (power_requested_milliwatt );
939+
920940#define REGULATOR_ERROR_ATTR (name , bit ) \
921941 static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
922942 char *buf) \
@@ -1149,6 +1169,10 @@ static void print_constraints_debug(struct regulator_dev *rdev)
11491169 if (constraints -> valid_modes_mask & REGULATOR_MODE_STANDBY )
11501170 count += scnprintf (buf + count , len - count , "standby " );
11511171
1172+ if (constraints -> pw_budget_mW )
1173+ count += scnprintf (buf + count , len - count , "%d mW budget" ,
1174+ constraints -> pw_budget_mW );
1175+
11521176 if (!count )
11531177 count = scnprintf (buf , len , "no parameters" );
11541178 else
@@ -1627,6 +1651,9 @@ static int set_machine_constraints(struct regulator_dev *rdev)
16271651 rdev -> last_off = ktime_get ();
16281652 }
16291653
1654+ if (!rdev -> constraints -> pw_budget_mW )
1655+ rdev -> constraints -> pw_budget_mW = INT_MAX ;
1656+
16301657 print_constraints (rdev );
16311658 return 0 ;
16321659}
@@ -4601,6 +4628,87 @@ int regulator_get_current_limit(struct regulator *regulator)
46014628}
46024629EXPORT_SYMBOL_GPL (regulator_get_current_limit );
46034630
4631+ /**
4632+ * regulator_get_unclaimed_power_budget - get regulator unclaimed power budget
4633+ * @regulator: regulator source
4634+ *
4635+ * Return: Unclaimed power budget of the regulator in mW.
4636+ */
4637+ int regulator_get_unclaimed_power_budget (struct regulator * regulator )
4638+ {
4639+ return regulator -> rdev -> constraints -> pw_budget_mW -
4640+ regulator -> rdev -> pw_requested_mW ;
4641+ }
4642+ EXPORT_SYMBOL_GPL (regulator_get_unclaimed_power_budget );
4643+
4644+ /**
4645+ * regulator_request_power_budget - request power budget on a regulator
4646+ * @regulator: regulator source
4647+ * @pw_req: Power requested
4648+ *
4649+ * Return: 0 on success or a negative error number on failure.
4650+ */
4651+ int regulator_request_power_budget (struct regulator * regulator ,
4652+ unsigned int pw_req )
4653+ {
4654+ struct regulator_dev * rdev = regulator -> rdev ;
4655+ int ret = 0 , pw_tot_req ;
4656+
4657+ regulator_lock (rdev );
4658+ if (rdev -> supply ) {
4659+ ret = regulator_request_power_budget (rdev -> supply , pw_req );
4660+ if (ret < 0 )
4661+ goto out ;
4662+ }
4663+
4664+ pw_tot_req = rdev -> pw_requested_mW + pw_req ;
4665+ if (pw_tot_req > rdev -> constraints -> pw_budget_mW ) {
4666+ rdev_warn (rdev , "power requested %d mW out of budget %d mW" ,
4667+ pw_req ,
4668+ rdev -> constraints -> pw_budget_mW - rdev -> pw_requested_mW );
4669+ regulator_notifier_call_chain (rdev ,
4670+ REGULATOR_EVENT_OVER_CURRENT_WARN ,
4671+ NULL );
4672+ ret = - ERANGE ;
4673+ goto out ;
4674+ }
4675+
4676+ rdev -> pw_requested_mW = pw_tot_req ;
4677+ out :
4678+ regulator_unlock (rdev );
4679+ return ret ;
4680+ }
4681+ EXPORT_SYMBOL_GPL (regulator_request_power_budget );
4682+
4683+ /**
4684+ * regulator_free_power_budget - free power budget on a regulator
4685+ * @regulator: regulator source
4686+ * @pw: Power to be released.
4687+ *
4688+ * Return: Power budget of the regulator in mW.
4689+ */
4690+ void regulator_free_power_budget (struct regulator * regulator ,
4691+ unsigned int pw )
4692+ {
4693+ struct regulator_dev * rdev = regulator -> rdev ;
4694+ int pw_tot_req ;
4695+
4696+ regulator_lock (rdev );
4697+ if (rdev -> supply )
4698+ regulator_free_power_budget (rdev -> supply , pw );
4699+
4700+ pw_tot_req = rdev -> pw_requested_mW - pw ;
4701+ if (pw_tot_req >= 0 )
4702+ rdev -> pw_requested_mW = pw_tot_req ;
4703+ else
4704+ rdev_warn (rdev ,
4705+ "too much power freed %d mW (already requested %d mW)" ,
4706+ pw , rdev -> pw_requested_mW );
4707+
4708+ regulator_unlock (rdev );
4709+ }
4710+ EXPORT_SYMBOL_GPL (regulator_free_power_budget );
4711+
46044712/**
46054713 * regulator_set_mode - set regulator operating mode
46064714 * @regulator: regulator source
@@ -5239,6 +5347,8 @@ static struct attribute *regulator_dev_attrs[] = {
52395347 & dev_attr_suspend_standby_mode .attr ,
52405348 & dev_attr_suspend_mem_mode .attr ,
52415349 & dev_attr_suspend_disk_mode .attr ,
5350+ & dev_attr_power_budget_milliwatt .attr ,
5351+ & dev_attr_power_requested_milliwatt .attr ,
52425352 NULL
52435353};
52445354
@@ -5320,6 +5430,10 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
53205430 attr == & dev_attr_suspend_disk_mode .attr )
53215431 return ops -> set_suspend_mode ? mode : 0 ;
53225432
5433+ if (attr == & dev_attr_power_budget_milliwatt .attr ||
5434+ attr == & dev_attr_power_requested_milliwatt .attr )
5435+ return rdev -> constraints -> pw_budget_mW != INT_MAX ? mode : 0 ;
5436+
53235437 return mode ;
53245438}
53255439
0 commit comments