Skip to content

Commit 62c11e4

Browse files
madscientist159groeck
authored andcommitted
hwmon: (adt7475) Add support for Imon readout on ADT7490
Add support for the ADT7490's Imon voltage readout. It is handled largely the same way as the existing Vtt readout. Signed-off-by: Timothy Pearson <[email protected]> Co-developed-by: Shawn Anastasio <[email protected]> Signed-off-by: Shawn Anastasio <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 2232f10 commit 62c11e4

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

Documentation/hwmon/adt7475.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ADT7476:
9090

9191
ADT7490:
9292
* 6 voltage inputs
93-
* 1 Imon input (not implemented)
93+
* 1 Imon input
9494
* PECI support (not implemented)
9595
* 2 GPIO pins (not implemented)
9696
* system acoustics optimizations (not implemented)
@@ -107,6 +107,7 @@ in2 VCC (4) VCC (4) VCC (4) VCC (3)
107107
in3 5VIN (20) 5VIN (20)
108108
in4 12VIN (21) 12VIN (21)
109109
in5 VTT (8)
110+
in6 Imon (19)
110111
==== =========== =========== ========= ==========
111112

112113
Special Features

drivers/hwmon/adt7475.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
/* 7475 Common Registers */
4444

4545
#define REG_DEVREV2 0x12 /* ADT7490 only */
46+
#define REG_IMON 0x1D /* ADT7490 only */
4647

4748
#define REG_VTT 0x1E /* ADT7490 only */
4849
#define REG_EXTEND3 0x1F /* ADT7490 only */
@@ -103,6 +104,9 @@
103104
#define REG_VTT_MIN 0x84 /* ADT7490 only */
104105
#define REG_VTT_MAX 0x86 /* ADT7490 only */
105106

107+
#define REG_IMON_MIN 0x85 /* ADT7490 only */
108+
#define REG_IMON_MAX 0x87 /* ADT7490 only */
109+
106110
#define VID_VIDSEL 0x80 /* ADT7476 only */
107111

108112
#define CONFIG2_ATTN 0x20
@@ -123,7 +127,7 @@
123127

124128
/* ADT7475 Settings */
125129

126-
#define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt */
130+
#define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt or Imon */
127131
#define ADT7475_TEMP_COUNT 3
128132
#define ADT7475_TACH_COUNT 4
129133
#define ADT7475_PWM_COUNT 3
@@ -204,7 +208,7 @@ struct adt7475_data {
204208
u8 has_fan4:1;
205209
u8 has_vid:1;
206210
u32 alarms;
207-
u16 voltage[3][6];
211+
u16 voltage[3][7];
208212
u16 temp[7][3];
209213
u16 tach[2][4];
210214
u8 pwm[4][3];
@@ -215,7 +219,7 @@ struct adt7475_data {
215219

216220
u8 vid;
217221
u8 vrm;
218-
const struct attribute_group *groups[9];
222+
const struct attribute_group *groups[10];
219223
};
220224

221225
static struct i2c_driver adt7475_driver;
@@ -273,13 +277,14 @@ static inline u16 rpm2tach(unsigned long rpm)
273277
}
274278

275279
/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
276-
static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = {
280+
static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 2][2] = {
277281
{ 45, 94 }, /* +2.5V */
278282
{ 175, 525 }, /* Vccp */
279283
{ 68, 71 }, /* Vcc */
280284
{ 93, 47 }, /* +5V */
281285
{ 120, 20 }, /* +12V */
282286
{ 45, 45 }, /* Vtt */
287+
{ 45, 45 }, /* Imon */
283288
};
284289

285290
static inline int reg2volt(int channel, u16 reg, u8 bypass_attn)
@@ -369,11 +374,16 @@ static ssize_t voltage_store(struct device *dev,
369374
reg = VOLTAGE_MIN_REG(sattr->index);
370375
else
371376
reg = VOLTAGE_MAX_REG(sattr->index);
372-
} else {
377+
} else if (sattr->index == 5) {
373378
if (sattr->nr == MIN)
374379
reg = REG_VTT_MIN;
375380
else
376381
reg = REG_VTT_MAX;
382+
} else {
383+
if (sattr->nr == MIN)
384+
reg = REG_IMON_MIN;
385+
else
386+
reg = REG_IMON_MAX;
377387
}
378388

379389
i2c_smbus_write_byte_data(client, reg,
@@ -1104,6 +1114,10 @@ static SENSOR_DEVICE_ATTR_2_RO(in5_input, voltage, INPUT, 5);
11041114
static SENSOR_DEVICE_ATTR_2_RW(in5_max, voltage, MAX, 5);
11051115
static SENSOR_DEVICE_ATTR_2_RW(in5_min, voltage, MIN, 5);
11061116
static SENSOR_DEVICE_ATTR_2_RO(in5_alarm, voltage, ALARM, 31);
1117+
static SENSOR_DEVICE_ATTR_2_RO(in6_input, voltage, INPUT, 6);
1118+
static SENSOR_DEVICE_ATTR_2_RW(in6_max, voltage, MAX, 6);
1119+
static SENSOR_DEVICE_ATTR_2_RW(in6_min, voltage, MIN, 6);
1120+
static SENSOR_DEVICE_ATTR_2_RO(in6_alarm, voltage, ALARM, 30);
11071121
static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, INPUT, 0);
11081122
static SENSOR_DEVICE_ATTR_2_RO(temp1_alarm, temp, ALARM, 0);
11091123
static SENSOR_DEVICE_ATTR_2_RO(temp1_fault, temp, FAULT, 0);
@@ -1294,6 +1308,14 @@ static struct attribute *in5_attrs[] = {
12941308
NULL
12951309
};
12961310

1311+
static struct attribute *in6_attrs[] = {
1312+
&sensor_dev_attr_in6_input.dev_attr.attr,
1313+
&sensor_dev_attr_in6_max.dev_attr.attr,
1314+
&sensor_dev_attr_in6_min.dev_attr.attr,
1315+
&sensor_dev_attr_in6_alarm.dev_attr.attr,
1316+
NULL
1317+
};
1318+
12971319
static struct attribute *vid_attrs[] = {
12981320
&dev_attr_cpu0_vid.attr,
12991321
&dev_attr_vrm.attr,
@@ -1307,6 +1329,7 @@ static const struct attribute_group in0_attr_group = { .attrs = in0_attrs };
13071329
static const struct attribute_group in3_attr_group = { .attrs = in3_attrs };
13081330
static const struct attribute_group in4_attr_group = { .attrs = in4_attrs };
13091331
static const struct attribute_group in5_attr_group = { .attrs = in5_attrs };
1332+
static const struct attribute_group in6_attr_group = { .attrs = in6_attrs };
13101333
static const struct attribute_group vid_attr_group = { .attrs = vid_attrs };
13111334

13121335
static int adt7475_detect(struct i2c_client *client,
@@ -1389,6 +1412,18 @@ static int adt7475_update_limits(struct i2c_client *client)
13891412
data->voltage[MAX][5] = ret << 2;
13901413
}
13911414

1415+
if (data->has_voltage & (1 << 6)) {
1416+
ret = adt7475_read(REG_IMON_MIN);
1417+
if (ret < 0)
1418+
return ret;
1419+
data->voltage[MIN][6] = ret << 2;
1420+
1421+
ret = adt7475_read(REG_IMON_MAX);
1422+
if (ret < 0)
1423+
return ret;
1424+
data->voltage[MAX][6] = ret << 2;
1425+
}
1426+
13921427
for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
13931428
/* Adjust values so they match the input precision */
13941429
ret = adt7475_read(TEMP_MIN_REG(i));
@@ -1663,7 +1698,7 @@ static int adt7475_probe(struct i2c_client *client)
16631698
revision = adt7475_read(REG_DEVID2) & 0x07;
16641699
break;
16651700
case adt7490:
1666-
data->has_voltage = 0x3e; /* in1 to in5 */
1701+
data->has_voltage = 0x7e; /* in1 to in6 */
16671702
revision = adt7475_read(REG_DEVID2) & 0x03;
16681703
if (revision == 0x03)
16691704
revision += adt7475_read(REG_DEVREV2);
@@ -1775,6 +1810,9 @@ static int adt7475_probe(struct i2c_client *client)
17751810
if (data->has_voltage & (1 << 5)) {
17761811
data->groups[group_num++] = &in5_attr_group;
17771812
}
1813+
if (data->has_voltage & (1 << 6)) {
1814+
data->groups[group_num++] = &in6_attr_group;
1815+
}
17781816
if (data->has_vid) {
17791817
data->vrm = vid_which_vrm();
17801818
data->groups[group_num] = &vid_attr_group;
@@ -1960,6 +1998,24 @@ static int adt7475_update_measure(struct device *dev)
19601998
((ext >> 4) & 3);
19611999
}
19622000

2001+
if (data->has_voltage & (1 << 6)) {
2002+
ret = adt7475_read(REG_STATUS4);
2003+
if (ret < 0)
2004+
return ret;
2005+
data->alarms |= ret << 24;
2006+
2007+
ret = adt7475_read(REG_EXTEND3);
2008+
if (ret < 0)
2009+
return ret;
2010+
ext = ret;
2011+
2012+
ret = adt7475_read(REG_IMON);
2013+
if (ret < 0)
2014+
return ret;
2015+
data->voltage[INPUT][6] = ret << 2 |
2016+
((ext >> 6) & 3);
2017+
}
2018+
19632019
for (i = 0; i < ADT7475_TACH_COUNT; i++) {
19642020
if (i == 3 && !data->has_fan4)
19652021
continue;

0 commit comments

Comments
 (0)