21
21
#define INA238_CONFIG 0x0
22
22
#define INA238_ADC_CONFIG 0x1
23
23
#define INA238_SHUNT_CALIBRATION 0x2
24
+ #define SQ52206_SHUNT_TEMPCO 0x3
24
25
#define INA238_SHUNT_VOLTAGE 0x4
25
26
#define INA238_BUS_VOLTAGE 0x5
26
27
#define INA238_DIE_TEMP 0x6
27
28
#define INA238_CURRENT 0x7
28
29
#define INA238_POWER 0x8
30
+ #define SQ52206_ENERGY 0x9
31
+ #define SQ52206_CHARGE 0xa
29
32
#define INA238_DIAG_ALERT 0xb
30
33
#define INA238_SHUNT_OVER_VOLTAGE 0xc
31
34
#define INA238_SHUNT_UNDER_VOLTAGE 0xd
32
35
#define INA238_BUS_OVER_VOLTAGE 0xe
33
36
#define INA238_BUS_UNDER_VOLTAGE 0xf
34
37
#define INA238_TEMP_LIMIT 0x10
35
38
#define INA238_POWER_LIMIT 0x11
39
+ #define SQ52206_POWER_PEAK 0x20
36
40
#define INA238_DEVICE_ID 0x3f /* not available on INA237 */
37
41
38
42
#define INA238_CONFIG_ADCRANGE BIT(4)
43
+ #define SQ52206_CONFIG_ADCRANGE_HIGH BIT(4)
44
+ #define SQ52206_CONFIG_ADCRANGE_LOW BIT(3)
39
45
40
46
#define INA238_DIAG_ALERT_TMPOL BIT(7)
41
47
#define INA238_DIAG_ALERT_SHNTOL BIT(6)
44
50
#define INA238_DIAG_ALERT_BUSUL BIT(3)
45
51
#define INA238_DIAG_ALERT_POL BIT(2)
46
52
47
- #define INA238_REGISTERS 0x11
53
+ #define INA238_REGISTERS 0x20
48
54
49
55
#define INA238_RSHUNT_DEFAULT 10000 /* uOhm */
50
56
51
57
/* Default configuration of device on reset. */
52
58
#define INA238_CONFIG_DEFAULT 0
59
+ #define SQ52206_CONFIG_DEFAULT 0x0005
53
60
/* 16 sample averaging, 1052us conversion time, continuous mode */
54
61
#define INA238_ADC_CONFIG_DEFAULT 0xfb6a
55
62
/* Configure alerts to be based on averaged value (SLOWALERT) */
87
94
* shunt = 0x4000 / (819.2 * 10^6) / 0.001 = 20000 uOhms (with 1mA/lsb)
88
95
*
89
96
* Current (mA) = register value * 20000 / rshunt / 4 * gain
90
- * Power (W) = 0.2 * register value * 20000 / rshunt / 4 * gain
97
+ * Power (mW) = 0.2 * register value * 20000 / rshunt / 4 * gain
98
+ * (Specific for SQ52206)
99
+ * Power (mW) = 0.24 * register value * 20000 / rshunt / 4 * gain
100
+ * Energy (mJ) = 16 * 0.24 * register value * 20000 / rshunt / 4 * gain
91
101
*/
92
102
#define INA238_CALIBRATION_VALUE 16384
93
103
#define INA238_FIXED_SHUNT 20000
94
104
95
105
#define INA238_SHUNT_VOLTAGE_LSB 5 /* 5 uV/lsb */
96
106
#define INA238_BUS_VOLTAGE_LSB 3125 /* 3.125 mV/lsb */
97
- #define INA238_DIE_TEMP_LSB 125 /* 125 mC/lsb */
107
+ #define INA238_DIE_TEMP_LSB 1250000 /* 125.0000 mC/lsb */
108
+ #define SQ52206_BUS_VOLTAGE_LSB 3750 /* 3.75 mV/lsb */
109
+ #define SQ52206_DIE_TEMP_LSB 78125 /* 7.8125 mC/lsb */
98
110
99
111
static const struct regmap_config ina238_regmap_config = {
100
112
.max_register = INA238_REGISTERS ,
101
113
.reg_bits = 8 ,
102
114
.val_bits = 16 ,
103
115
};
104
116
105
- enum ina238_ids { ina238 , ina237 };
117
+ enum ina238_ids { ina238 , ina237 , sq52206 };
106
118
107
119
struct ina238_config {
108
120
bool has_power_highest ; /* chip detection power peak */
@@ -142,6 +154,15 @@ static const struct ina238_config ina238_config[] = {
142
154
.bus_voltage_lsb = INA238_BUS_VOLTAGE_LSB ,
143
155
.temp_lsb = INA238_DIE_TEMP_LSB ,
144
156
},
157
+ [sq52206 ] = {
158
+ .has_energy = true,
159
+ .has_power_highest = true,
160
+ .temp_shift = 0 ,
161
+ .power_calculate_factor = 24 ,
162
+ .config_default = SQ52206_CONFIG_DEFAULT ,
163
+ .bus_voltage_lsb = SQ52206_BUS_VOLTAGE_LSB ,
164
+ .temp_lsb = SQ52206_DIE_TEMP_LSB ,
165
+ },
145
166
};
146
167
147
168
static int ina238_read_reg24 (const struct i2c_client * client , u8 reg , u32 * val )
@@ -160,6 +181,24 @@ static int ina238_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
160
181
return 0 ;
161
182
}
162
183
184
+ static int ina238_read_reg40 (const struct i2c_client * client , u8 reg , u64 * val )
185
+ {
186
+ u8 data [5 ];
187
+ u32 low ;
188
+ int err ;
189
+
190
+ /* 40-bit register read */
191
+ err = i2c_smbus_read_i2c_block_data (client , reg , 5 , data );
192
+ if (err < 0 )
193
+ return err ;
194
+ if (err != 5 )
195
+ return - EIO ;
196
+ low = (data [1 ] << 24 ) | (data [2 ] << 16 ) | (data [3 ] << 8 ) | data [4 ];
197
+ * val = ((long long )data [0 ] << 32 ) | low ;
198
+
199
+ return 0 ;
200
+ }
201
+
163
202
static int ina238_read_in (struct device * dev , u32 attr , int channel ,
164
203
long * val )
165
204
{
@@ -330,6 +369,17 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val)
330
369
if (err )
331
370
return err ;
332
371
372
+ /* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
373
+ power = div_u64 (regval * 1000ULL * INA238_FIXED_SHUNT *
374
+ data -> gain , 20 * data -> rshunt );
375
+ /* Clamp value to maximum value of long */
376
+ * val = clamp_val (power , 0 , LONG_MAX );
377
+ break ;
378
+ case hwmon_power_input_highest :
379
+ err = ina238_read_reg24 (data -> client , SQ52206_POWER_PEAK , & regval );
380
+ if (err )
381
+ return err ;
382
+
333
383
/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
334
384
power = div_u64 (regval * 1000ULL * INA238_FIXED_SHUNT *
335
385
data -> gain , 20 * data -> rshunt );
@@ -437,6 +487,25 @@ static int ina238_write_temp(struct device *dev, u32 attr, long val)
437
487
return regmap_write (data -> regmap , INA238_TEMP_LIMIT , regval );
438
488
}
439
489
490
+ static ssize_t energy1_input_show (struct device * dev ,
491
+ struct device_attribute * da , char * buf )
492
+ {
493
+ struct ina238_data * data = dev_get_drvdata (dev );
494
+ int ret ;
495
+ u64 regval ;
496
+ u64 energy ;
497
+
498
+ ret = ina238_read_reg40 (data -> client , SQ52206_ENERGY , & regval );
499
+ if (ret )
500
+ return ret ;
501
+
502
+ /* result in mJ */
503
+ energy = div_u64 (regval * INA238_FIXED_SHUNT * data -> gain * 16 *
504
+ data -> config -> power_calculate_factor , 4 * 100 * data -> rshunt );
505
+
506
+ return sysfs_emit (buf , "%llu\n" , energy );
507
+ }
508
+
440
509
static int ina238_read (struct device * dev , enum hwmon_sensor_types type ,
441
510
u32 attr , int channel , long * val )
442
511
{
@@ -456,7 +525,7 @@ static int ina238_read(struct device *dev, enum hwmon_sensor_types type,
456
525
}
457
526
458
527
static int ina238_write (struct device * dev , enum hwmon_sensor_types type ,
459
- u32 attr , int channel , long val )
528
+ u32 attr , int channel , long val )
460
529
{
461
530
struct ina238_data * data = dev_get_drvdata (dev );
462
531
int err ;
@@ -486,6 +555,9 @@ static umode_t ina238_is_visible(const void *drvdata,
486
555
enum hwmon_sensor_types type ,
487
556
u32 attr , int channel )
488
557
{
558
+ const struct ina238_data * data = drvdata ;
559
+ bool has_power_highest = data -> config -> has_power_highest ;
560
+
489
561
switch (type ) {
490
562
case hwmon_in :
491
563
switch (attr ) {
@@ -513,6 +585,10 @@ static umode_t ina238_is_visible(const void *drvdata,
513
585
return 0444 ;
514
586
case hwmon_power_max :
515
587
return 0644 ;
588
+ case hwmon_power_input_highest :
589
+ if (has_power_highest )
590
+ return 0444 ;
591
+ return 0 ;
516
592
default :
517
593
return 0 ;
518
594
}
@@ -546,7 +622,8 @@ static const struct hwmon_channel_info * const ina238_info[] = {
546
622
HWMON_C_INPUT ),
547
623
HWMON_CHANNEL_INFO (power ,
548
624
/* 0: power */
549
- HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM ),
625
+ HWMON_P_INPUT | HWMON_P_MAX |
626
+ HWMON_P_MAX_ALARM | HWMON_P_INPUT_HIGHEST ),
550
627
HWMON_CHANNEL_INFO (temp ,
551
628
/* 0: die temperature */
552
629
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM ),
@@ -564,6 +641,15 @@ static const struct hwmon_chip_info ina238_chip_info = {
564
641
.info = ina238_info ,
565
642
};
566
643
644
+ /* energy attributes are 5 bytes wide so we need u64 */
645
+ static DEVICE_ATTR_RO (energy1_input );
646
+
647
+ static struct attribute * ina238_attrs [] = {
648
+ & dev_attr_energy1_input .attr ,
649
+ NULL ,
650
+ };
651
+ ATTRIBUTE_GROUPS (ina238 );
652
+
567
653
static int ina238_probe (struct i2c_client * client )
568
654
{
569
655
struct ina2xx_platform_data * pdata = dev_get_platdata (& client -> dev );
@@ -604,15 +690,21 @@ static int ina238_probe(struct i2c_client *client)
604
690
/* load shunt gain value */
605
691
if (device_property_read_u32 (dev , "ti,shunt-gain" , & data -> gain ) < 0 )
606
692
data -> gain = 4 ; /* Default of ADCRANGE = 0 */
607
- if (data -> gain != 1 && data -> gain != 4 ) {
693
+ if (data -> gain != 1 && data -> gain != 2 && data -> gain != 4 ) {
608
694
dev_err (dev , "invalid shunt gain value %u\n" , data -> gain );
609
695
return - EINVAL ;
610
696
}
611
697
612
698
/* Setup CONFIG register */
613
699
config = data -> config -> config_default ;
614
- if (data -> gain == 1 )
700
+ if (chip == sq52206 ) {
701
+ if (data -> gain == 1 )
702
+ config |= SQ52206_CONFIG_ADCRANGE_HIGH ; /* ADCRANGE = 10/11 is /1 */
703
+ else if (data -> gain == 2 )
704
+ config |= SQ52206_CONFIG_ADCRANGE_LOW ; /* ADCRANGE = 01 is /2 */
705
+ } else if (data -> gain == 1 ) {
615
706
config |= INA238_CONFIG_ADCRANGE ; /* ADCRANGE = 1 is /1 */
707
+ }
616
708
ret = regmap_write (data -> regmap , INA238_CONFIG , config );
617
709
if (ret < 0 ) {
618
710
dev_err (dev , "error configuring the device: %d\n" , ret );
@@ -645,7 +737,8 @@ static int ina238_probe(struct i2c_client *client)
645
737
646
738
hwmon_dev = devm_hwmon_device_register_with_info (dev , client -> name , data ,
647
739
& ina238_chip_info ,
648
- NULL );
740
+ data -> config -> has_energy ?
741
+ ina238_groups : NULL );
649
742
if (IS_ERR (hwmon_dev ))
650
743
return PTR_ERR (hwmon_dev );
651
744
@@ -658,6 +751,7 @@ static int ina238_probe(struct i2c_client *client)
658
751
static const struct i2c_device_id ina238_id [] = {
659
752
{ "ina237" , ina237 },
660
753
{ "ina238" , ina238 },
754
+ { "sq52206" , sq52206 },
661
755
{ }
662
756
};
663
757
MODULE_DEVICE_TABLE (i2c , ina238_id );
@@ -671,6 +765,10 @@ static const struct of_device_id __maybe_unused ina238_of_match[] = {
671
765
.compatible = "ti,ina238" ,
672
766
.data = (void * )ina238
673
767
},
768
+ {
769
+ .compatible = "silergy,sq52206" ,
770
+ .data = (void * )sq52206
771
+ },
674
772
{ }
675
773
};
676
774
MODULE_DEVICE_TABLE (of , ina238_of_match );
0 commit comments