@@ -917,6 +917,26 @@ static ssize_t bypass_show(struct device *dev,
917
917
}
918
918
static DEVICE_ATTR_RO (bypass );
919
919
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
+
920
940
#define REGULATOR_ERROR_ATTR (name , bit ) \
921
941
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
922
942
char *buf) \
@@ -1149,6 +1169,10 @@ static void print_constraints_debug(struct regulator_dev *rdev)
1149
1169
if (constraints -> valid_modes_mask & REGULATOR_MODE_STANDBY )
1150
1170
count += scnprintf (buf + count , len - count , "standby " );
1151
1171
1172
+ if (constraints -> pw_budget_mW )
1173
+ count += scnprintf (buf + count , len - count , "%d mW budget" ,
1174
+ constraints -> pw_budget_mW );
1175
+
1152
1176
if (!count )
1153
1177
count = scnprintf (buf , len , "no parameters" );
1154
1178
else
@@ -1627,6 +1651,9 @@ static int set_machine_constraints(struct regulator_dev *rdev)
1627
1651
rdev -> last_off = ktime_get ();
1628
1652
}
1629
1653
1654
+ if (!rdev -> constraints -> pw_budget_mW )
1655
+ rdev -> constraints -> pw_budget_mW = INT_MAX ;
1656
+
1630
1657
print_constraints (rdev );
1631
1658
return 0 ;
1632
1659
}
@@ -4601,6 +4628,87 @@ int regulator_get_current_limit(struct regulator *regulator)
4601
4628
}
4602
4629
EXPORT_SYMBOL_GPL (regulator_get_current_limit );
4603
4630
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
+
4604
4712
/**
4605
4713
* regulator_set_mode - set regulator operating mode
4606
4714
* @regulator: regulator source
@@ -5239,6 +5347,8 @@ static struct attribute *regulator_dev_attrs[] = {
5239
5347
& dev_attr_suspend_standby_mode .attr ,
5240
5348
& dev_attr_suspend_mem_mode .attr ,
5241
5349
& dev_attr_suspend_disk_mode .attr ,
5350
+ & dev_attr_power_budget_milliwatt .attr ,
5351
+ & dev_attr_power_requested_milliwatt .attr ,
5242
5352
NULL
5243
5353
};
5244
5354
@@ -5320,6 +5430,10 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
5320
5430
attr == & dev_attr_suspend_disk_mode .attr )
5321
5431
return ops -> set_suspend_mode ? mode : 0 ;
5322
5432
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
+
5323
5437
return mode ;
5324
5438
}
5325
5439
0 commit comments