Skip to content

Commit c823378

Browse files
larspmgroeck
authored andcommitted
hwmon: (emc1403) Add support for EMC1428 and EMC1438.
EMC1428 and EMC1438 are similar to EMC14xx, but have eight temperature channels, as well as signed data and limit registers. Chips currently supported by this driver have unsigned registers only. Signed-off-by: Lars Petter Mostad <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 2fa3659 commit c823378

File tree

2 files changed

+124
-14
lines changed

2 files changed

+124
-14
lines changed

Documentation/hwmon/emc1403.rst

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ Supported chips:
4545

4646
- https://ww1.microchip.com/downloads/en/DeviceDoc/1423_1424.pdf
4747

48+
* SMSC / Microchip EMC1428, EMC1438
49+
50+
Addresses scanned: I2C 0x18, 0x4c, 0x4d
51+
52+
Prefix: 'emc1428', 'emc1438'
53+
54+
Datasheets:
55+
56+
- https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005275A.pdf
57+
- https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf
58+
4859
Author:
4960
Kalhan Trisal <[email protected]
5061

@@ -53,10 +64,10 @@ Description
5364
-----------
5465

5566
The Standard Microsystems Corporation (SMSC) / Microchip EMC14xx chips
56-
contain up to four temperature sensors. EMC14x2 support two sensors
67+
contain up to eight temperature sensors. EMC14x2 support two sensors
5768
(one internal, one external). EMC14x3 support three sensors (one internal,
58-
two external), and EMC14x4 support four sensors (one internal, three
59-
external).
69+
two external), EMC14x4 support four sensors (one internal, three external),
70+
and EMC14x8 support eight sensors (one internal, seven external).
6071

6172
The chips implement three limits for each sensor: low (tempX_min), high
6273
(tempX_max) and critical (tempX_crit.) The chips also implement an

drivers/hwmon/emc1403.c

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#define THERMAL_SMSC_ID_REG 0xfe
2626
#define THERMAL_REVISION_REG 0xff
2727

28-
enum emc1403_chip { emc1402, emc1403, emc1404 };
28+
enum emc1403_chip { emc1402, emc1403, emc1404, emc1428 };
2929

3030
struct thermal_data {
3131
enum emc1403_chip chip;
@@ -100,6 +100,12 @@ static int emc1403_detect(struct i2c_client *client,
100100
case 0x27:
101101
strscpy(info->type, "emc1424", I2C_NAME_SIZE);
102102
break;
103+
case 0x29:
104+
strscpy(info->type, "emc1428", I2C_NAME_SIZE);
105+
break;
106+
case 0x59:
107+
strscpy(info->type, "emc1438", I2C_NAME_SIZE);
108+
break;
103109
case 0x60:
104110
strscpy(info->type, "emc1442", I2C_NAME_SIZE);
105111
break;
@@ -130,6 +136,14 @@ static bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg)
130136
case 0x35: /* high limit status */
131137
case 0x36: /* low limit status */
132138
case 0x37: /* therm limit status */
139+
case 0x41: /* external diode 4 high byte */
140+
case 0x42: /* external diode 4 low byte */
141+
case 0x43: /* external diode 5 high byte */
142+
case 0x44: /* external diode 5 low byte */
143+
case 0x45: /* external diode 6 high byte */
144+
case 0x46: /* external diode 6 low byte */
145+
case 0x47: /* external diode 7 high byte */
146+
case 0x48: /* external diode 7 low byte */
133147
return true;
134148
default:
135149
return false;
@@ -177,6 +191,30 @@ static u8 emc1403_temp_regs[][4] = {
177191
[temp_crit] = 0x30,
178192
[temp_input] = 0x2a,
179193
},
194+
[4] = {
195+
[temp_min] = 0x51,
196+
[temp_max] = 0x50,
197+
[temp_crit] = 0x64,
198+
[temp_input] = 0x41,
199+
},
200+
[5] = {
201+
[temp_min] = 0x55,
202+
[temp_max] = 0x54,
203+
[temp_crit] = 0x65,
204+
[temp_input] = 0x43
205+
},
206+
[6] = {
207+
[temp_min] = 0x59,
208+
[temp_max] = 0x58,
209+
[temp_crit] = 0x66,
210+
[temp_input] = 0x45,
211+
},
212+
[7] = {
213+
[temp_min] = 0x5d,
214+
[temp_max] = 0x5c,
215+
[temp_crit] = 0x67,
216+
[temp_input] = 0x47,
217+
},
180218
};
181219

182220
static s8 emc1403_temp_regs_low[][4] = {
@@ -204,27 +242,56 @@ static s8 emc1403_temp_regs_low[][4] = {
204242
[temp_crit] = -1,
205243
[temp_input] = 0x2b,
206244
},
245+
[4] = {
246+
[temp_min] = 0x53,
247+
[temp_max] = 0x52,
248+
[temp_crit] = -1,
249+
[temp_input] = 0x42,
250+
},
251+
[5] = {
252+
[temp_min] = 0x57,
253+
[temp_max] = 0x56,
254+
[temp_crit] = -1,
255+
[temp_input] = 0x44,
256+
},
257+
[6] = {
258+
[temp_min] = 0x5b,
259+
[temp_max] = 0x5a,
260+
[temp_crit] = -1,
261+
[temp_input] = 0x46,
262+
},
263+
[7] = {
264+
[temp_min] = 0x5f,
265+
[temp_max] = 0x5e,
266+
[temp_crit] = -1,
267+
[temp_input] = 0x48,
268+
},
207269
};
208270

209271
static int __emc1403_get_temp(struct thermal_data *data, int channel,
210272
enum emc1403_reg_map map, long *val)
211273
{
212-
unsigned int regval;
274+
unsigned int regvalh;
275+
unsigned int regvall = 0;
213276
int ret;
214277
s8 reg;
215278

216-
ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], &regval);
279+
ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], &regvalh);
217280
if (ret < 0)
218281
return ret;
219-
*val = regval * 1000;
220282

221283
reg = emc1403_temp_regs_low[channel][map];
222284
if (reg >= 0) {
223-
ret = regmap_read(data->regmap, reg, &regval);
285+
ret = regmap_read(data->regmap, reg, &regvall);
224286
if (ret < 0)
225287
return ret;
226-
*val += (regval >> 5) * 125;
227288
}
289+
290+
if (data->chip == emc1428)
291+
*val = sign_extend32((regvalh << 3) | (regvall >> 5), 10) * 125;
292+
else
293+
*val = ((regvalh << 3) | (regvall >> 5)) * 125;
294+
228295
return 0;
229296
}
230297

@@ -379,15 +446,21 @@ static int emc1403_set_hyst(struct thermal_data *data, long val)
379446
int hyst, ret;
380447
long limit;
381448

382-
val = clamp_val(val, 0, 255000);
449+
if (data->chip == emc1428)
450+
val = clamp_val(val, -128000, 127000);
451+
else
452+
val = clamp_val(val, 0, 255000);
383453

384454
mutex_lock(&data->mutex);
385455
ret = __emc1403_get_temp(data, 0, temp_crit, &limit);
386456
if (ret < 0)
387457
goto unlock;
388458

389459
hyst = limit - val;
390-
hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255);
460+
if (data->chip == emc1428)
461+
hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 127);
462+
else
463+
hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255);
391464
ret = regmap_write(data->regmap, 0x21, hyst);
392465
unlock:
393466
mutex_unlock(&data->mutex);
@@ -407,14 +480,20 @@ static int emc1403_set_temp(struct thermal_data *data, int channel,
407480

408481
mutex_lock(&data->mutex);
409482
if (regl >= 0) {
410-
val = clamp_val(val, 0, 255875);
483+
if (data->chip == emc1428)
484+
val = clamp_val(val, -128000, 127875);
485+
else
486+
val = clamp_val(val, 0, 255875);
411487
regval = DIV_ROUND_CLOSEST(val, 125);
412-
ret = regmap_write(data->regmap, regh, regval >> 3);
488+
ret = regmap_write(data->regmap, regh, (regval >> 3) & 0xff);
413489
if (ret < 0)
414490
goto unlock;
415491
ret = regmap_write(data->regmap, regl, (regval & 0x07) << 5);
416492
} else {
417-
val = clamp_val(val, 0, 255000);
493+
if (data->chip == emc1428)
494+
val = clamp_val(val, -128000, 127000);
495+
else
496+
val = clamp_val(val, 0, 255000);
418497
regval = DIV_ROUND_CLOSEST(val, 1000);
419498
ret = regmap_write(data->regmap, regh, regval);
420499
}
@@ -484,6 +563,8 @@ static umode_t emc1403_temp_is_visible(const void *_data, u32 attr, int channel)
484563
return 0;
485564
if (data->chip == emc1403 && channel > 2)
486565
return 0;
566+
if (data->chip != emc1428 && channel > 3)
567+
return 0;
487568

488569
switch (attr) {
489570
case hwmon_temp_input:
@@ -548,6 +629,22 @@ static const struct hwmon_channel_info * const emc1403_info[] = {
548629
HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
549630
HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST |
550631
HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
632+
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT,
633+
HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
634+
HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST |
635+
HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
636+
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT,
637+
HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
638+
HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST |
639+
HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
640+
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT,
641+
HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
642+
HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST |
643+
HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
644+
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT,
645+
HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
646+
HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST |
647+
HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
551648
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT
552649
),
553650
NULL
@@ -575,6 +672,8 @@ static const struct i2c_device_id emc1403_idtable[] = {
575672
{ "emc1422", emc1402 },
576673
{ "emc1423", emc1403 },
577674
{ "emc1424", emc1404 },
675+
{ "emc1428", emc1428 },
676+
{ "emc1438", emc1428 },
578677
{ "emc1442", emc1402 },
579678
{ }
580679
};

0 commit comments

Comments
 (0)