Skip to content

Commit 0e346a8

Browse files
osenftgroeck
authored andcommitted
hwmon: (nct7802) Make temperature/voltage sensors configurable
This change allows LTD and RTD inputs to be configured via device tree bindings. If the DT bindings are not present or invalid, the input configuration is not modified and left at HW defaults. Signed-off-by: Oskar Senft <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 1bfaa49 commit 0e346a8

File tree

1 file changed

+125
-4
lines changed

1 file changed

+125
-4
lines changed

drivers/hwmon/nct7802.c

Lines changed: 125 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
5151
#define REG_CHIP_ID 0xfe
5252
#define REG_VERSION_ID 0xff
5353

54+
/*
55+
* Resistance temperature detector (RTD) modes according to 7.2.32 Mode
56+
* Selection Register
57+
*/
58+
#define RTD_MODE_CURRENT 0x1
59+
#define RTD_MODE_THERMISTOR 0x2
60+
#define RTD_MODE_VOLTAGE 0x3
61+
62+
#define MODE_RTD_MASK 0x3
63+
#define MODE_LTD_EN 0x40
64+
65+
/*
66+
* Bit offset for sensors modes in REG_MODE.
67+
* Valid for index 0..2, indicating RTD1..3.
68+
*/
69+
#define MODE_BIT_OFFSET_RTD(index) ((index) * 2)
70+
5471
/*
5572
* Data structures and manipulation thereof
5673
*/
@@ -1038,7 +1055,112 @@ static const struct regmap_config nct7802_regmap_config = {
10381055
.volatile_reg = nct7802_regmap_is_volatile,
10391056
};
10401057

1041-
static int nct7802_init_chip(struct nct7802_data *data)
1058+
static int nct7802_get_channel_config(struct device *dev,
1059+
struct device_node *node, u8 *mode_mask,
1060+
u8 *mode_val)
1061+
{
1062+
u32 reg;
1063+
const char *type_str, *md_str;
1064+
u8 md;
1065+
1066+
if (!node->name || of_node_cmp(node->name, "channel"))
1067+
return 0;
1068+
1069+
if (of_property_read_u32(node, "reg", &reg)) {
1070+
dev_err(dev, "Could not read reg value for '%s'\n",
1071+
node->full_name);
1072+
return -EINVAL;
1073+
}
1074+
1075+
if (reg > 3) {
1076+
dev_err(dev, "Invalid reg (%u) in '%s'\n", reg,
1077+
node->full_name);
1078+
return -EINVAL;
1079+
}
1080+
1081+
if (reg == 0) {
1082+
if (!of_device_is_available(node))
1083+
*mode_val &= ~MODE_LTD_EN;
1084+
else
1085+
*mode_val |= MODE_LTD_EN;
1086+
*mode_mask |= MODE_LTD_EN;
1087+
return 0;
1088+
}
1089+
1090+
/* At this point we have reg >= 1 && reg <= 3 */
1091+
1092+
if (!of_device_is_available(node)) {
1093+
*mode_val &= ~(MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1));
1094+
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
1095+
return 0;
1096+
}
1097+
1098+
if (of_property_read_string(node, "sensor-type", &type_str)) {
1099+
dev_err(dev, "No type for '%s'\n", node->full_name);
1100+
return -EINVAL;
1101+
}
1102+
1103+
if (!strcmp(type_str, "voltage")) {
1104+
*mode_val |= (RTD_MODE_VOLTAGE & MODE_RTD_MASK)
1105+
<< MODE_BIT_OFFSET_RTD(reg - 1);
1106+
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
1107+
return 0;
1108+
}
1109+
1110+
if (strcmp(type_str, "temperature")) {
1111+
dev_err(dev, "Invalid type '%s' for '%s'\n", type_str,
1112+
node->full_name);
1113+
return -EINVAL;
1114+
}
1115+
1116+
if (reg == 3) {
1117+
/* RTD3 only supports thermistor mode */
1118+
md = RTD_MODE_THERMISTOR;
1119+
} else {
1120+
if (of_property_read_string(node, "temperature-mode",
1121+
&md_str)) {
1122+
dev_err(dev, "No mode for '%s'\n", node->full_name);
1123+
return -EINVAL;
1124+
}
1125+
1126+
if (!strcmp(md_str, "thermal-diode"))
1127+
md = RTD_MODE_CURRENT;
1128+
else if (!strcmp(md_str, "thermistor"))
1129+
md = RTD_MODE_THERMISTOR;
1130+
else {
1131+
dev_err(dev, "Invalid mode '%s' for '%s'\n", md_str,
1132+
node->full_name);
1133+
return -EINVAL;
1134+
}
1135+
}
1136+
1137+
*mode_val |= (md & MODE_RTD_MASK) << MODE_BIT_OFFSET_RTD(reg - 1);
1138+
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
1139+
1140+
return 0;
1141+
}
1142+
1143+
static int nct7802_configure_channels(struct device *dev,
1144+
struct nct7802_data *data)
1145+
{
1146+
/* Enable local temperature sensor by default */
1147+
u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN;
1148+
struct device_node *node;
1149+
int err;
1150+
1151+
if (dev->of_node) {
1152+
for_each_child_of_node(dev->of_node, node) {
1153+
err = nct7802_get_channel_config(dev, node, &mode_mask,
1154+
&mode_val);
1155+
if (err)
1156+
return err;
1157+
}
1158+
}
1159+
1160+
return regmap_update_bits(data->regmap, REG_MODE, mode_mask, mode_val);
1161+
}
1162+
1163+
static int nct7802_init_chip(struct device *dev, struct nct7802_data *data)
10421164
{
10431165
int err;
10441166

@@ -1047,8 +1169,7 @@ static int nct7802_init_chip(struct nct7802_data *data)
10471169
if (err)
10481170
return err;
10491171

1050-
/* Enable local temperature sensor */
1051-
err = regmap_update_bits(data->regmap, REG_MODE, 0x40, 0x40);
1172+
err = nct7802_configure_channels(dev, data);
10521173
if (err)
10531174
return err;
10541175

@@ -1074,7 +1195,7 @@ static int nct7802_probe(struct i2c_client *client)
10741195
mutex_init(&data->access_lock);
10751196
mutex_init(&data->in_alarm_lock);
10761197

1077-
ret = nct7802_init_chip(data);
1198+
ret = nct7802_init_chip(dev, data);
10781199
if (ret < 0)
10791200
return ret;
10801201

0 commit comments

Comments
 (0)