@@ -306,7 +306,7 @@ static int ina2xx_read_init(struct device *dev, int reg, long *val)
306
306
* Turns alert limit values into register values.
307
307
* Opposite of the formula in ina2xx_get_value().
308
308
*/
309
- static u16 ina226_alert_to_reg (struct ina2xx_data * data , int reg , unsigned long val )
309
+ static u16 ina226_alert_to_reg (struct ina2xx_data * data , int reg , long val )
310
310
{
311
311
switch (reg ) {
312
312
case INA2XX_SHUNT_VOLTAGE :
@@ -322,6 +322,11 @@ static u16 ina226_alert_to_reg(struct ina2xx_data *data, int reg, unsigned long
322
322
val = clamp_val (val , 0 , UINT_MAX - data -> power_lsb_uW );
323
323
val = DIV_ROUND_CLOSEST (val , data -> power_lsb_uW );
324
324
return clamp_val (val , 0 , USHRT_MAX );
325
+ case INA2XX_CURRENT :
326
+ val = clamp_val (val , INT_MIN / 1000 , INT_MAX / 1000 );
327
+ /* signed register, result in mA */
328
+ val = DIV_ROUND_CLOSEST (val * 1000 , data -> current_lsb_uA );
329
+ return clamp_val (val , SHRT_MIN , SHRT_MAX );
325
330
default :
326
331
/* programmer goofed */
327
332
WARN_ON_ONCE (1 );
@@ -473,9 +478,31 @@ static int ina2xx_power_read(struct device *dev, u32 attr, long *val)
473
478
474
479
static int ina2xx_curr_read (struct device * dev , u32 attr , long * val )
475
480
{
481
+ struct ina2xx_data * data = dev_get_drvdata (dev );
482
+ struct regmap * regmap = data -> regmap ;
483
+
484
+ /*
485
+ * While the chips supported by this driver do not directly support
486
+ * current limits, they do support setting shunt voltage limits.
487
+ * The shunt voltage divided by the shunt resistor value is the current.
488
+ * On top of that, calibration values are set such that in the shunt
489
+ * voltage register and the current register report the same values.
490
+ * That means we can report and configure current limits based on shunt
491
+ * voltage limits.
492
+ */
476
493
switch (attr ) {
477
494
case hwmon_curr_input :
478
495
return ina2xx_read_init (dev , INA2XX_CURRENT , val );
496
+ case hwmon_curr_lcrit :
497
+ return ina226_alert_limit_read (data , INA226_SHUNT_UNDER_VOLTAGE_MASK ,
498
+ INA2XX_CURRENT , val );
499
+ case hwmon_curr_crit :
500
+ return ina226_alert_limit_read (data , INA226_SHUNT_OVER_VOLTAGE_MASK ,
501
+ INA2XX_CURRENT , val );
502
+ case hwmon_curr_lcrit_alarm :
503
+ return ina226_alert_read (regmap , INA226_SHUNT_UNDER_VOLTAGE_MASK , val );
504
+ case hwmon_curr_crit_alarm :
505
+ return ina226_alert_read (regmap , INA226_SHUNT_OVER_VOLTAGE_MASK , val );
479
506
default :
480
507
return - EOPNOTSUPP ;
481
508
}
@@ -547,6 +574,23 @@ static int ina2xx_power_write(struct device *dev, u32 attr, long val)
547
574
return 0 ;
548
575
}
549
576
577
+ static int ina2xx_curr_write (struct device * dev , u32 attr , long val )
578
+ {
579
+ struct ina2xx_data * data = dev_get_drvdata (dev );
580
+
581
+ switch (attr ) {
582
+ case hwmon_curr_lcrit :
583
+ return ina226_alert_limit_write (data , INA226_SHUNT_UNDER_VOLTAGE_MASK ,
584
+ INA2XX_CURRENT , val );
585
+ case hwmon_curr_crit :
586
+ return ina226_alert_limit_write (data , INA226_SHUNT_OVER_VOLTAGE_MASK ,
587
+ INA2XX_CURRENT , val );
588
+ default :
589
+ return - EOPNOTSUPP ;
590
+ }
591
+ return 0 ;
592
+ }
593
+
550
594
static int ina2xx_write (struct device * dev , enum hwmon_sensor_types type ,
551
595
u32 attr , int channel , long val )
552
596
{
@@ -557,6 +601,8 @@ static int ina2xx_write(struct device *dev, enum hwmon_sensor_types type,
557
601
return ina2xx_in_write (dev , attr , channel , val );
558
602
case hwmon_power :
559
603
return ina2xx_power_write (dev , attr , val );
604
+ case hwmon_curr :
605
+ return ina2xx_curr_write (dev , attr , val );
560
606
default :
561
607
return - EOPNOTSUPP ;
562
608
}
@@ -591,6 +637,16 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
591
637
switch (attr ) {
592
638
case hwmon_curr_input :
593
639
return 0444 ;
640
+ case hwmon_curr_lcrit :
641
+ case hwmon_curr_crit :
642
+ if (chip == ina226 )
643
+ return 0644 ;
644
+ break ;
645
+ case hwmon_curr_lcrit_alarm :
646
+ case hwmon_curr_crit_alarm :
647
+ if (chip == ina226 )
648
+ return 0444 ;
649
+ break ;
594
650
default :
595
651
break ;
596
652
}
@@ -636,7 +692,8 @@ static const struct hwmon_channel_info * const ina2xx_info[] = {
636
692
HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
637
693
HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM
638
694
),
639
- HWMON_CHANNEL_INFO (curr , HWMON_C_INPUT ),
695
+ HWMON_CHANNEL_INFO (curr , HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM |
696
+ HWMON_C_LCRIT | HWMON_C_LCRIT_ALARM ),
640
697
HWMON_CHANNEL_INFO (power ,
641
698
HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM ),
642
699
NULL
0 commit comments