74
74
#define INA226_READ_AVG (reg ) (((reg) & INA226_AVG_RD_MASK) >> 9)
75
75
#define INA226_SHIFT_AVG (val ) ((val) << 9)
76
76
77
+ /* bit number of alert functions in Mask/Enable Register */
78
+ #define INA226_SHUNT_OVER_VOLTAGE_BIT 15
79
+ #define INA226_SHUNT_UNDER_VOLTAGE_BIT 14
80
+ #define INA226_BUS_OVER_VOLTAGE_BIT 13
81
+ #define INA226_BUS_UNDER_VOLTAGE_BIT 12
82
+ #define INA226_POWER_OVER_LIMIT_BIT 11
83
+
84
+ /* bit mask for alert config bits of Mask/Enable Register */
85
+ #define INA226_ALERT_CONFIG_MASK 0xFC00
86
+ #define INA226_ALERT_FUNCTION_FLAG BIT(4)
87
+
77
88
/* common attrs, ina226 attrs and NULL */
78
89
#define INA2XX_MAX_ATTRIBUTE_GROUPS 3
79
90
@@ -303,6 +314,145 @@ static ssize_t ina2xx_value_show(struct device *dev,
303
314
ina2xx_get_value (data , attr -> index , regval ));
304
315
}
305
316
317
+ static int ina226_reg_to_alert (struct ina2xx_data * data , u8 bit , u16 regval )
318
+ {
319
+ int reg ;
320
+
321
+ switch (bit ) {
322
+ case INA226_SHUNT_OVER_VOLTAGE_BIT :
323
+ case INA226_SHUNT_UNDER_VOLTAGE_BIT :
324
+ reg = INA2XX_SHUNT_VOLTAGE ;
325
+ break ;
326
+ case INA226_BUS_OVER_VOLTAGE_BIT :
327
+ case INA226_BUS_UNDER_VOLTAGE_BIT :
328
+ reg = INA2XX_BUS_VOLTAGE ;
329
+ break ;
330
+ case INA226_POWER_OVER_LIMIT_BIT :
331
+ reg = INA2XX_POWER ;
332
+ break ;
333
+ default :
334
+ /* programmer goofed */
335
+ WARN_ON_ONCE (1 );
336
+ return 0 ;
337
+ }
338
+
339
+ return ina2xx_get_value (data , reg , regval );
340
+ }
341
+
342
+ /*
343
+ * Turns alert limit values into register values.
344
+ * Opposite of the formula in ina2xx_get_value().
345
+ */
346
+ static s16 ina226_alert_to_reg (struct ina2xx_data * data , u8 bit , int val )
347
+ {
348
+ switch (bit ) {
349
+ case INA226_SHUNT_OVER_VOLTAGE_BIT :
350
+ case INA226_SHUNT_UNDER_VOLTAGE_BIT :
351
+ val *= data -> config -> shunt_div ;
352
+ return clamp_val (val , SHRT_MIN , SHRT_MAX );
353
+ case INA226_BUS_OVER_VOLTAGE_BIT :
354
+ case INA226_BUS_UNDER_VOLTAGE_BIT :
355
+ val = (val * 1000 ) << data -> config -> bus_voltage_shift ;
356
+ val = DIV_ROUND_CLOSEST (val , data -> config -> bus_voltage_lsb );
357
+ return clamp_val (val , 0 , SHRT_MAX );
358
+ case INA226_POWER_OVER_LIMIT_BIT :
359
+ val = DIV_ROUND_CLOSEST (val , data -> power_lsb_uW );
360
+ return clamp_val (val , 0 , USHRT_MAX );
361
+ default :
362
+ /* programmer goofed */
363
+ WARN_ON_ONCE (1 );
364
+ return 0 ;
365
+ }
366
+ }
367
+
368
+ static ssize_t ina226_alert_show (struct device * dev ,
369
+ struct device_attribute * da , char * buf )
370
+ {
371
+ struct sensor_device_attribute * attr = to_sensor_dev_attr (da );
372
+ struct ina2xx_data * data = dev_get_drvdata (dev );
373
+ int regval ;
374
+ int val = 0 ;
375
+ int ret ;
376
+
377
+ mutex_lock (& data -> config_lock );
378
+ ret = regmap_read (data -> regmap , INA226_MASK_ENABLE , & regval );
379
+ if (ret )
380
+ goto abort ;
381
+
382
+ if (regval & BIT (attr -> index )) {
383
+ ret = regmap_read (data -> regmap , INA226_ALERT_LIMIT , & regval );
384
+ if (ret )
385
+ goto abort ;
386
+ val = ina226_reg_to_alert (data , attr -> index , regval );
387
+ }
388
+
389
+ ret = snprintf (buf , PAGE_SIZE , "%d\n" , val );
390
+ abort :
391
+ mutex_unlock (& data -> config_lock );
392
+ return ret ;
393
+ }
394
+
395
+ static ssize_t ina226_alert_store (struct device * dev ,
396
+ struct device_attribute * da ,
397
+ const char * buf , size_t count )
398
+ {
399
+ struct sensor_device_attribute * attr = to_sensor_dev_attr (da );
400
+ struct ina2xx_data * data = dev_get_drvdata (dev );
401
+ unsigned long val ;
402
+ int ret ;
403
+
404
+ ret = kstrtoul (buf , 10 , & val );
405
+ if (ret < 0 )
406
+ return ret ;
407
+
408
+ /*
409
+ * Clear all alerts first to avoid accidentally triggering ALERT pin
410
+ * due to register write sequence. Then, only enable the alert
411
+ * if the value is non-zero.
412
+ */
413
+ mutex_lock (& data -> config_lock );
414
+ ret = regmap_update_bits (data -> regmap , INA226_MASK_ENABLE ,
415
+ INA226_ALERT_CONFIG_MASK , 0 );
416
+ if (ret < 0 )
417
+ goto abort ;
418
+
419
+ ret = regmap_write (data -> regmap , INA226_ALERT_LIMIT ,
420
+ ina226_alert_to_reg (data , attr -> index , val ));
421
+ if (ret < 0 )
422
+ goto abort ;
423
+
424
+ if (val != 0 ) {
425
+ ret = regmap_update_bits (data -> regmap , INA226_MASK_ENABLE ,
426
+ INA226_ALERT_CONFIG_MASK ,
427
+ BIT (attr -> index ));
428
+ if (ret < 0 )
429
+ goto abort ;
430
+ }
431
+
432
+ ret = count ;
433
+ abort :
434
+ mutex_unlock (& data -> config_lock );
435
+ return ret ;
436
+ }
437
+
438
+ static ssize_t ina226_alarm_show (struct device * dev ,
439
+ struct device_attribute * da , char * buf )
440
+ {
441
+ struct sensor_device_attribute * attr = to_sensor_dev_attr (da );
442
+ struct ina2xx_data * data = dev_get_drvdata (dev );
443
+ int regval ;
444
+ int alarm = 0 ;
445
+ int ret ;
446
+
447
+ ret = regmap_read (data -> regmap , INA226_MASK_ENABLE , & regval );
448
+ if (ret )
449
+ return ret ;
450
+
451
+ alarm = (regval & BIT (attr -> index )) &&
452
+ (regval & INA226_ALERT_FUNCTION_FLAG );
453
+ return snprintf (buf , PAGE_SIZE , "%d\n" , alarm );
454
+ }
455
+
306
456
/*
307
457
* In order to keep calibration register value fixed, the product
308
458
* of current_lsb and shunt_resistor should also be fixed and equal
@@ -392,15 +542,38 @@ static ssize_t ina226_interval_show(struct device *dev,
392
542
393
543
/* shunt voltage */
394
544
static SENSOR_DEVICE_ATTR_RO (in0_input , ina2xx_value , INA2XX_SHUNT_VOLTAGE ) ;
545
+ /* shunt voltage over/under voltage alert setting and alarm */
546
+ static SENSOR_DEVICE_ATTR_RW (in0_crit , ina226_alert ,
547
+ INA226_SHUNT_OVER_VOLTAGE_BIT ) ;
548
+ static SENSOR_DEVICE_ATTR_RW (in0_lcrit , ina226_alert ,
549
+ INA226_SHUNT_UNDER_VOLTAGE_BIT ) ;
550
+ static SENSOR_DEVICE_ATTR_RO (in0_crit_alarm , ina226_alarm ,
551
+ INA226_SHUNT_OVER_VOLTAGE_BIT ) ;
552
+ static SENSOR_DEVICE_ATTR_RO (in0_lcrit_alarm , ina226_alarm ,
553
+ INA226_SHUNT_UNDER_VOLTAGE_BIT ) ;
395
554
396
555
/* bus voltage */
397
556
static SENSOR_DEVICE_ATTR_RO (in1_input , ina2xx_value , INA2XX_BUS_VOLTAGE ) ;
557
+ /* bus voltage over/under voltage alert setting and alarm */
558
+ static SENSOR_DEVICE_ATTR_RW (in1_crit , ina226_alert ,
559
+ INA226_BUS_OVER_VOLTAGE_BIT ) ;
560
+ static SENSOR_DEVICE_ATTR_RW (in1_lcrit , ina226_alert ,
561
+ INA226_BUS_UNDER_VOLTAGE_BIT ) ;
562
+ static SENSOR_DEVICE_ATTR_RO (in1_crit_alarm , ina226_alarm ,
563
+ INA226_BUS_OVER_VOLTAGE_BIT ) ;
564
+ static SENSOR_DEVICE_ATTR_RO (in1_lcrit_alarm , ina226_alarm ,
565
+ INA226_BUS_UNDER_VOLTAGE_BIT ) ;
398
566
399
567
/* calculated current */
400
568
static SENSOR_DEVICE_ATTR_RO (curr1_input , ina2xx_value , INA2XX_CURRENT ) ;
401
569
402
570
/* calculated power */
403
571
static SENSOR_DEVICE_ATTR_RO (power1_input , ina2xx_value , INA2XX_POWER ) ;
572
+ /* over-limit power alert setting and alarm */
573
+ static SENSOR_DEVICE_ATTR_RW (power1_crit , ina226_alert ,
574
+ INA226_POWER_OVER_LIMIT_BIT ) ;
575
+ static SENSOR_DEVICE_ATTR_RO (power1_crit_alarm , ina226_alarm ,
576
+ INA226_POWER_OVER_LIMIT_BIT ) ;
404
577
405
578
/* shunt resistance */
406
579
static SENSOR_DEVICE_ATTR_RW (shunt_resistor , ina2xx_shunt , INA2XX_CALIBRATION ) ;
@@ -423,6 +596,16 @@ static const struct attribute_group ina2xx_group = {
423
596
};
424
597
425
598
static struct attribute * ina226_attrs [] = {
599
+ & sensor_dev_attr_in0_crit .dev_attr .attr ,
600
+ & sensor_dev_attr_in0_lcrit .dev_attr .attr ,
601
+ & sensor_dev_attr_in0_crit_alarm .dev_attr .attr ,
602
+ & sensor_dev_attr_in0_lcrit_alarm .dev_attr .attr ,
603
+ & sensor_dev_attr_in1_crit .dev_attr .attr ,
604
+ & sensor_dev_attr_in1_lcrit .dev_attr .attr ,
605
+ & sensor_dev_attr_in1_crit_alarm .dev_attr .attr ,
606
+ & sensor_dev_attr_in1_lcrit_alarm .dev_attr .attr ,
607
+ & sensor_dev_attr_power1_crit .dev_attr .attr ,
608
+ & sensor_dev_attr_power1_crit_alarm .dev_attr .attr ,
426
609
& sensor_dev_attr_update_interval .dev_attr .attr ,
427
610
NULL ,
428
611
};
0 commit comments