@@ -306,7 +306,7 @@ static int ina2xx_read_init(struct device *dev, int reg, long *val)
306306 * Turns alert limit values into register values.
307307 * Opposite of the formula in ina2xx_get_value().
308308 */
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 )
310310{
311311 switch (reg ) {
312312 case INA2XX_SHUNT_VOLTAGE :
@@ -322,6 +322,11 @@ static u16 ina226_alert_to_reg(struct ina2xx_data *data, int reg, unsigned long
322322 val = clamp_val (val , 0 , UINT_MAX - data -> power_lsb_uW );
323323 val = DIV_ROUND_CLOSEST (val , data -> power_lsb_uW );
324324 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 );
325330 default :
326331 /* programmer goofed */
327332 WARN_ON_ONCE (1 );
@@ -473,9 +478,31 @@ static int ina2xx_power_read(struct device *dev, u32 attr, long *val)
473478
474479static int ina2xx_curr_read (struct device * dev , u32 attr , long * val )
475480{
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+ */
476493 switch (attr ) {
477494 case hwmon_curr_input :
478495 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 );
479506 default :
480507 return - EOPNOTSUPP ;
481508 }
@@ -547,6 +574,23 @@ static int ina2xx_power_write(struct device *dev, u32 attr, long val)
547574 return 0 ;
548575}
549576
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+
550594static int ina2xx_write (struct device * dev , enum hwmon_sensor_types type ,
551595 u32 attr , int channel , long val )
552596{
@@ -557,6 +601,8 @@ static int ina2xx_write(struct device *dev, enum hwmon_sensor_types type,
557601 return ina2xx_in_write (dev , attr , channel , val );
558602 case hwmon_power :
559603 return ina2xx_power_write (dev , attr , val );
604+ case hwmon_curr :
605+ return ina2xx_curr_write (dev , attr , val );
560606 default :
561607 return - EOPNOTSUPP ;
562608 }
@@ -591,6 +637,16 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
591637 switch (attr ) {
592638 case hwmon_curr_input :
593639 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 ;
594650 default :
595651 break ;
596652 }
@@ -636,7 +692,8 @@ static const struct hwmon_channel_info * const ina2xx_info[] = {
636692 HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
637693 HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM
638694 ),
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 ),
640697 HWMON_CHANNEL_INFO (power ,
641698 HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM ),
642699 NULL
0 commit comments