@@ -265,10 +265,113 @@ static int pse_pi_disable(struct regulator_dev *rdev)
265
265
return ret ;
266
266
}
267
267
268
+ static int _pse_pi_get_voltage (struct regulator_dev * rdev )
269
+ {
270
+ struct pse_controller_dev * pcdev = rdev_get_drvdata (rdev );
271
+ const struct pse_controller_ops * ops ;
272
+ int id ;
273
+
274
+ ops = pcdev -> ops ;
275
+ if (!ops -> pi_get_voltage )
276
+ return - EOPNOTSUPP ;
277
+
278
+ id = rdev_get_id (rdev );
279
+ return ops -> pi_get_voltage (pcdev , id );
280
+ }
281
+
282
+ static int pse_pi_get_voltage (struct regulator_dev * rdev )
283
+ {
284
+ struct pse_controller_dev * pcdev = rdev_get_drvdata (rdev );
285
+ int ret ;
286
+
287
+ mutex_lock (& pcdev -> lock );
288
+ ret = _pse_pi_get_voltage (rdev );
289
+ mutex_unlock (& pcdev -> lock );
290
+
291
+ return ret ;
292
+ }
293
+
294
+ static int _pse_ethtool_get_status (struct pse_controller_dev * pcdev ,
295
+ int id ,
296
+ struct netlink_ext_ack * extack ,
297
+ struct pse_control_status * status );
298
+
299
+ static int pse_pi_get_current_limit (struct regulator_dev * rdev )
300
+ {
301
+ struct pse_controller_dev * pcdev = rdev_get_drvdata (rdev );
302
+ const struct pse_controller_ops * ops ;
303
+ struct netlink_ext_ack extack = {};
304
+ struct pse_control_status st = {};
305
+ int id , uV , ret ;
306
+ s64 tmp_64 ;
307
+
308
+ ops = pcdev -> ops ;
309
+ id = rdev_get_id (rdev );
310
+ mutex_lock (& pcdev -> lock );
311
+ if (ops -> pi_get_current_limit ) {
312
+ ret = ops -> pi_get_current_limit (pcdev , id );
313
+ goto out ;
314
+ }
315
+
316
+ /* If pi_get_current_limit() callback not populated get voltage
317
+ * from pi_get_voltage() and power limit from ethtool_get_status()
318
+ * to calculate current limit.
319
+ */
320
+ ret = _pse_pi_get_voltage (rdev );
321
+ if (!ret ) {
322
+ dev_err (pcdev -> dev , "Voltage null\n" );
323
+ ret = - ERANGE ;
324
+ goto out ;
325
+ }
326
+ if (ret < 0 )
327
+ goto out ;
328
+ uV = ret ;
329
+
330
+ ret = _pse_ethtool_get_status (pcdev , id , & extack , & st );
331
+ if (ret )
332
+ goto out ;
333
+
334
+ if (!st .c33_avail_pw_limit ) {
335
+ ret = - ENODATA ;
336
+ goto out ;
337
+ }
338
+
339
+ tmp_64 = st .c33_avail_pw_limit ;
340
+ tmp_64 *= 1000000000ull ;
341
+ /* uA = mW * 1000000000 / uV */
342
+ ret = DIV_ROUND_CLOSEST_ULL (tmp_64 , uV );
343
+
344
+ out :
345
+ mutex_unlock (& pcdev -> lock );
346
+ return ret ;
347
+ }
348
+
349
+ static int pse_pi_set_current_limit (struct regulator_dev * rdev , int min_uA ,
350
+ int max_uA )
351
+ {
352
+ struct pse_controller_dev * pcdev = rdev_get_drvdata (rdev );
353
+ const struct pse_controller_ops * ops ;
354
+ int id , ret ;
355
+
356
+ ops = pcdev -> ops ;
357
+ if (!ops -> pi_set_current_limit )
358
+ return - EOPNOTSUPP ;
359
+
360
+ id = rdev_get_id (rdev );
361
+ mutex_lock (& pcdev -> lock );
362
+ ret = ops -> pi_set_current_limit (pcdev , id , max_uA );
363
+ mutex_unlock (& pcdev -> lock );
364
+
365
+ return ret ;
366
+ }
367
+
268
368
static const struct regulator_ops pse_pi_ops = {
269
369
.is_enabled = pse_pi_is_enabled ,
270
370
.enable = pse_pi_enable ,
271
371
.disable = pse_pi_disable ,
372
+ .get_voltage = pse_pi_get_voltage ,
373
+ .get_current_limit = pse_pi_get_current_limit ,
374
+ .set_current_limit = pse_pi_set_current_limit ,
272
375
};
273
376
274
377
static int
@@ -298,7 +401,9 @@ devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev,
298
401
rdesc -> ops = & pse_pi_ops ;
299
402
rdesc -> owner = pcdev -> owner ;
300
403
301
- rinit_data -> constraints .valid_ops_mask = REGULATOR_CHANGE_STATUS ;
404
+ rinit_data -> constraints .valid_ops_mask = REGULATOR_CHANGE_STATUS |
405
+ REGULATOR_CHANGE_CURRENT ;
406
+ rinit_data -> constraints .max_uA = MAX_PI_CURRENT ;
302
407
rinit_data -> supply_regulator = "vpwr" ;
303
408
304
409
rconfig .dev = pcdev -> dev ;
@@ -626,6 +731,23 @@ struct pse_control *of_pse_control_get(struct device_node *node)
626
731
}
627
732
EXPORT_SYMBOL_GPL (of_pse_control_get );
628
733
734
+ static int _pse_ethtool_get_status (struct pse_controller_dev * pcdev ,
735
+ int id ,
736
+ struct netlink_ext_ack * extack ,
737
+ struct pse_control_status * status )
738
+ {
739
+ const struct pse_controller_ops * ops ;
740
+
741
+ ops = pcdev -> ops ;
742
+ if (!ops -> ethtool_get_status ) {
743
+ NL_SET_ERR_MSG (extack ,
744
+ "PSE driver does not support status report" );
745
+ return - EOPNOTSUPP ;
746
+ }
747
+
748
+ return ops -> ethtool_get_status (pcdev , id , extack , status );
749
+ }
750
+
629
751
/**
630
752
* pse_ethtool_get_status - get status of PSE control
631
753
* @psec: PSE control pointer
@@ -638,19 +760,10 @@ int pse_ethtool_get_status(struct pse_control *psec,
638
760
struct netlink_ext_ack * extack ,
639
761
struct pse_control_status * status )
640
762
{
641
- const struct pse_controller_ops * ops ;
642
763
int err ;
643
764
644
- ops = psec -> pcdev -> ops ;
645
-
646
- if (!ops -> ethtool_get_status ) {
647
- NL_SET_ERR_MSG (extack ,
648
- "PSE driver does not support status report" );
649
- return - EOPNOTSUPP ;
650
- }
651
-
652
765
mutex_lock (& psec -> pcdev -> lock );
653
- err = ops -> ethtool_get_status (psec -> pcdev , psec -> id , extack , status );
766
+ err = _pse_ethtool_get_status (psec -> pcdev , psec -> id , extack , status );
654
767
mutex_unlock (& psec -> pcdev -> lock );
655
768
656
769
return err ;
@@ -732,6 +845,43 @@ int pse_ethtool_set_config(struct pse_control *psec,
732
845
}
733
846
EXPORT_SYMBOL_GPL (pse_ethtool_set_config );
734
847
848
+ /**
849
+ * pse_ethtool_set_pw_limit - set PSE control power limit
850
+ * @psec: PSE control pointer
851
+ * @extack: extack for reporting useful error messages
852
+ * @pw_limit: power limit value in mW
853
+ *
854
+ * Return: 0 on success and failure value on error
855
+ */
856
+ int pse_ethtool_set_pw_limit (struct pse_control * psec ,
857
+ struct netlink_ext_ack * extack ,
858
+ const unsigned int pw_limit )
859
+ {
860
+ int uV , uA , ret ;
861
+ s64 tmp_64 ;
862
+
863
+ ret = regulator_get_voltage (psec -> ps );
864
+ if (!ret ) {
865
+ NL_SET_ERR_MSG (extack ,
866
+ "Can't calculate the current, PSE voltage read is 0" );
867
+ return - ERANGE ;
868
+ }
869
+ if (ret < 0 ) {
870
+ NL_SET_ERR_MSG (extack ,
871
+ "Error reading PSE voltage" );
872
+ return ret ;
873
+ }
874
+ uV = ret ;
875
+
876
+ tmp_64 = pw_limit ;
877
+ tmp_64 *= 1000000000ull ;
878
+ /* uA = mW * 1000000000 / uV */
879
+ uA = DIV_ROUND_CLOSEST_ULL (tmp_64 , uV );
880
+
881
+ return regulator_set_current_limit (psec -> ps , 0 , uA );
882
+ }
883
+ EXPORT_SYMBOL_GPL (pse_ethtool_set_pw_limit );
884
+
735
885
bool pse_has_podl (struct pse_control * psec )
736
886
{
737
887
return psec -> pcdev -> types & ETHTOOL_PSE_PODL ;
0 commit comments