Skip to contentSkip to conversation

hwmon: (nct7802) Add device tree support

PATCH New Constantine Shulyupin 2 participants 2 messages Oct 26, 2015 Hardware monitoring

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 hwmon: (nct7802) Add device tree support

From: Constantine Shulyupin <[email protected]>

Introduced nct7802_platform_data, nct7802_parse_dt, nct7802_platform_data_set.

Parsing of DT nodes
- compatible = "nuvoton,nct7802-sensor",

	with "sensor-type" = "thermal-diode" | "thermistor" | "voltage" |
				"local" | "vcc" | "vcore"

- compatible = "nuvoton,nct7802-fan",
with boolen properties "direct-current", "invert", "invert"
- compatible = "nuvoton,nct7802-peci"

---
Changed in v3:
- Removed nuvoton,sensorX-type
- Introduced nct7802_platform_data, new DT parser for sensors, fans, peci, vcc, vcore

Changed in v2:
- removed tempX_type
- introduced nuvoton,sensorX-type with string values

Changed in v1:
- Introduced tempX_type with numerical values

---
 drivers/hwmon/nct7802.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 185 insertions(+), 1 deletion(-)
drivers/hwmon/nct7802.c +183 -1
index 3ce33d2..dee9eb3 100644
@@ -53,6 +53,8 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
 #define REG_PECI_ENABLE		0x23
 #define REG_FAN_ENABLE		0x24
 #define REG_VMON_ENABLE		0x25
+#define REG_FAN_TYPE		0x5e
+#define REG_FAN_MODE		0x5f
 #define REG_PWM(x)		(0x60 + (x))
 #define REG_SMARTFAN_EN(x)      (0x64 + (x) / 2)
 #define SMARTFAN_EN_SHIFT(x)    ((x) % 2 * 4)
@@ -69,6 +71,18 @@ struct nct7802_data {
 	struct mutex access_lock; /* for multi-byte read and write operations */
 };
 
+struct nct7802_platform_data {
+	s8 sensor_type[3];
+	s8 local_temp_enable;
+	s8 vcc_enable;
+	s8 vcore_enable;
+	s8 fan_enable[3];
+	s8 fan_dc[2];	/* direct current instead PWM */
+	s8 fan_od[3];	/* open drain */
+	s8 fan_inv[3];	/* inverted polarity */
+	s8 peci_enable[2];
+};
+
 static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
 			      char *buf)
 {
@@ -1077,6 +1091,151 @@ static const struct regmap_config nct7802_regmap_config = {
 	.volatile_reg = nct7802_regmap_is_volatile,
 };
 
+static int nct7802_parse_dt(struct device_node *node,
+			    struct nct7802_platform_data *pdata)
+{
+	struct device_node *child;
+	const char *sen_type;
+	int ret;
+	int i;
+
+	for_each_child_of_node(node, child) {
+		u32 reg = 0xFF;
+
+		of_property_read_u32(child, "reg", &reg);
+		if (of_device_is_compatible(child, "nuvoton,nct7802-sensor")) {
+			ret = of_property_read_string(child,
+						      "sensor-type", &sen_type);
+			if (ret < 0) {
+				pr_err("%s: expected property sensor-type\n",
+				       child->full_name);
+				return -EINVAL;
+			}
+			if (!strcmp(sen_type, "local")) {
+				pdata->local_temp_enable = 1;
+				continue;
+			} else if (!strcmp(sen_type, "vcc")) {
+				pdata->vcc_enable = 1;
+				continue;
+			} else if (!strcmp(sen_type, "vcore")) {
+				pdata->vcore_enable = 1;
+				continue;
+			}
+			if (reg >= ARRAY_SIZE(pdata->sensor_type)) {
+				pr_err("%s: invalid value: reg=%d\n",
+				       child->full_name, reg);
+				return -EINVAL;
+			}
+			if (!strcmp(sen_type, "thermal-diode")) {
+				pdata->sensor_type[reg] = 1;
+			} else if (!strcmp(sen_type, "thermistor")) {
+				pdata->sensor_type[reg] = 2;
+			} else if (!strcmp(sen_type, "voltage")) {
+				pdata->sensor_type[reg] = 3;
+			} else {
+				pr_err("%s: invalid sensor-type=\"%s\"\n",
+				       child->full_name, sen_type);
+				return -EINVAL;
+			}
+		} else if (of_device_is_compatible(child,
+						   "nuvoton,nct7802-fan")) {
+			if (reg >= ARRAY_SIZE(pdata->fan_enable)) {
+				pr_err("%s: invalid value: %s=%d\n",
+				       child->full_name, "reg", reg);
+				return -EINVAL;
+			}
+			pdata->fan_enable[reg] = 1;
+			if (of_property_read_bool(child, "direct-current")) {
+				if (reg >= ARRAY_SIZE(pdata->fan_dc)) {
+					pr_err("%s: invalid value: %s=%d\n",
+					       child->full_name, "reg", reg);
+					return -EINVAL;
+				}
+				pdata->fan_dc[reg] = 1;
+			}
+			pdata->fan_od[reg] +				of_property_read_bool(child, "open-drain");
+			pdata->fan_inv[reg] +				of_property_read_bool(child, "invert");
+		} else if (of_device_is_compatible(child,
+						   "nuvoton,nct7802-peci")) {
+			if (reg >= ARRAY_SIZE(pdata->peci_enable)) {
+				pr_err("%s: invalid value: reg=%d\n",
+				       child->full_name, reg);
+				return -EINVAL;
+			}
+			pdata->peci_enable[reg] = 1;
+		}
+	}
+
+	return 0;
+}
+
+static int nct7802_platform_data_set(struct nct7802_data *data,
+				     struct nct7802_platform_data *pdata)
+{
+	int ret;
+	int i;
+
+	/* Enable ADC */
+	ret = regmap_update_bits(data->regmap, REG_START, 1, 1);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->sensor_type); i++) {
+		ret = regmap_update_bits(data->regmap, REG_MODE,
+					 3 << 2 * i,
+					 pdata->sensor_type[i] << 2 * i);
+		if (ret)
+			return ret;
+	}
+	ret = regmap_update_bits(data->regmap, REG_MODE,
+				 1 << 6,
+				 pdata->local_temp_enable << 6);
+	if (ret)
+		return ret;
+	for (i = 0; i < ARRAY_SIZE(pdata->fan_enable); i++) {
+		ret = regmap_update_bits(data->regmap, REG_FAN_ENABLE,
+					 1 << i, pdata->fan_enable[i] << i);
+	}
+	for (i = 0; i < ARRAY_SIZE(pdata->peci_enable); i++) {
+		ret = regmap_update_bits(data->regmap, REG_PECI_ENABLE,
+					 1 << i, pdata->peci_enable[i] << i);
+		if (ret)
+			return ret;
+	}
+	ret = regmap_update_bits(data->regmap, REG_VMON_ENABLE, 1,
+				 pdata->vcc_enable);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(data->regmap, REG_VMON_ENABLE, 1 << 1,
+				 pdata->vcore_enable << 1);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->fan_dc); i++) {
+		ret = regmap_update_bits(data->regmap, REG_FAN_TYPE, 1 << i,
+					 pdata->fan_dc[i] << i);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(pdata->fan_od); i++) {
+		ret = regmap_update_bits(data->regmap, REG_FAN_MODE, 1 << i,
+					 pdata->fan_od[i] << i);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(pdata->fan_inv); i++) {
+		ret = regmap_update_bits(data->regmap, REG_FAN_MODE,
+					 1 << (i + 4),
+					 pdata->fan_inv[i] << (i + 4));
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 static int nct7802_init_chip(struct nct7802_data *data)
 {
 	int err;
@@ -1098,11 +1257,27 @@ static int nct7802_init_chip(struct nct7802_data *data)
 static int nct7802_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct nct7802_platform_data *pdata;
 	struct device *dev = &client->dev;
 	struct nct7802_data *data;
 	struct device *hwmon_dev;
 	int ret;
 
+	pdata = dev_get_platdata(dev);
+#ifdef CONFIG_OF
+	if (dev->of_node) {
+		pdata = devm_kzalloc(dev, sizeof(struct nct7802_platform_data),
+				     GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+		ret = nct7802_parse_dt(dev->of_node, pdata);
+		if (ret < 0) {
+			devm_kfree(dev, pdata);
+			return ret;
+		}
+	}
+#endif
+
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (data = NULL)
 		return -ENOMEM;
@@ -1113,7 +1288,10 @@ static int nct7802_probe(struct i2c_client *client,
 
 	mutex_init(&data->access_lock);
 
-	ret = nct7802_init_chip(data);
+	if (pdata)
+		ret = nct7802_platform_data_set(data, pdata);
+	else
+		ret = nct7802_init_chip(data);
 	if (ret < 0)
 		return ret;
 
@@ -1133,10 +1311,16 @@ static const struct i2c_device_id nct7802_idtable[] = {
 };
 MODULE_DEVICE_TABLE(i2c, nct7802_idtable);
 
+static const struct __maybe_unused of_device_id nct7802_dt_match[] = {
+	{ .compatible = "nuvoton,nct7802" },
+	{ },
+};
+
 static struct i2c_driver nct7802_driver = {
 	.class = I2C_CLASS_HWMON,
 	.driver = {
 		.name = DRVNAME,
+		.of_match_table = of_match_ptr(nct7802_dt_match),
 	},
 	.detect = nct7802_detect,
 	.probe = nct7802_probe,
Signature · 7 lines
1.9.1


_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
#1 lore raw
reproduce:

Hi Constantine,

[auto build test WARNING on hwmon/hwmon-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Constantine-Shulyupin/hwmon-nct7802-Add-device-tree-support/20151027-045621
config: x86_64-randconfig-x019-201543 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

drivers/hwmon/nct7802.c: In function 'nct7802_parse_dt':

>> drivers/hwmon/nct7802.c:1100:6: warning: unused variable 'i' [-Wunused-variable]
     int i;
         ^

drivers/hwmon/nct7802.c: At top level:
drivers/hwmon/nct7802.c:1094:12: warning: 'nct7802_parse_dt' defined but not used [-Wunused-function]
static int nct7802_parse_dt(struct device_node *node,
^

vim +/i +1100 drivers/hwmon/nct7802.c

1084 (reg >= REG_PWM(0) && reg <= REG_PWM(2));
1085 }
1086
1087 static const struct regmap_config nct7802_regmap_config = {
1088 .reg_bits = 8,
1089 .val_bits = 8,
1090 .cache_type = REGCACHE_RBTREE,
1091 .volatile_reg = nct7802_regmap_is_volatile,
1092 };
1093
1094 static int nct7802_parse_dt(struct device_node *node,
1095 struct nct7802_platform_data *pdata)
1096 {
1097 struct device_node *child;
1098 const char *sen_type;
1099 int ret;

> 1100		int i;

1101
1102 for_each_child_of_node(node, child) {
1103 u32 reg = 0xFF;
1104
1105 of_property_read_u32(child, "reg", &reg);
1106 if (of_device_is_compatible(child, "nuvoton,nct7802-sensor")) {
1107 ret = of_property_read_string(child,
1108 "sensor-type", &sen_type);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors