xref: /linux/drivers/hwmon/qnap-mcu-hwmon.c (revision e78f70bad29c5ae1e1076698b690b15794e9b81e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * Driver for hwmon elements found on QNAP-MCU devices
5  *
6  * Copyright (C) 2024 Heiko Stuebner <heiko@sntech.de>
7  */
8 
9 #include <linux/hwmon.h>
10 #include <linux/mfd/qnap-mcu.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/property.h>
14 #include <linux/thermal.h>
15 
16 struct qnap_mcu_hwmon {
17 	struct qnap_mcu *mcu;
18 	struct device *dev;
19 
20 	unsigned int pwm_min;
21 	unsigned int pwm_max;
22 
23 	struct fwnode_handle *fan_node;
24 	unsigned int fan_state;
25 	unsigned int fan_max_state;
26 	unsigned int *fan_cooling_levels;
27 
28 	struct thermal_cooling_device *cdev;
29 	struct hwmon_chip_info info;
30 };
31 
32 static int qnap_mcu_hwmon_get_rpm(struct qnap_mcu_hwmon *hwm)
33 {
34 	static const u8 cmd[] = { '@', 'F', 'A' };
35 	u8 reply[6];
36 	int ret;
37 
38 	/* poll the fan rpm */
39 	ret = qnap_mcu_exec(hwm->mcu, cmd, sizeof(cmd), reply, sizeof(reply));
40 	if (ret)
41 		return ret;
42 
43 	/* First 2 bytes must mirror the sent command */
44 	if (memcmp(cmd, reply, 2))
45 		return -EIO;
46 
47 	return reply[4] * 30;
48 }
49 
50 static int qnap_mcu_hwmon_get_pwm(struct qnap_mcu_hwmon *hwm)
51 {
52 	static const u8 cmd[] = { '@', 'F', 'Z', '0' }; /* 0 = fan-id? */
53 	u8 reply[4];
54 	int ret;
55 
56 	/* poll the fan pwm */
57 	ret = qnap_mcu_exec(hwm->mcu, cmd, sizeof(cmd), reply, sizeof(reply));
58 	if (ret)
59 		return ret;
60 
61 	/* First 3 bytes must mirror the sent command */
62 	if (memcmp(cmd, reply, 3))
63 		return -EIO;
64 
65 	return reply[3];
66 }
67 
68 static int qnap_mcu_hwmon_set_pwm(struct qnap_mcu_hwmon *hwm, u8 pwm)
69 {
70 	const u8 cmd[] = { '@', 'F', 'W', '0', pwm }; /* 0 = fan-id?, pwm 0-255 */
71 
72 	/* set the fan pwm */
73 	return qnap_mcu_exec_with_ack(hwm->mcu, cmd, sizeof(cmd));
74 }
75 
76 static int qnap_mcu_hwmon_get_temp(struct qnap_mcu_hwmon *hwm)
77 {
78 	static const u8 cmd[] = { '@', 'T', '3' };
79 	u8 reply[4];
80 	int ret;
81 
82 	/* poll the fan rpm */
83 	ret = qnap_mcu_exec(hwm->mcu, cmd, sizeof(cmd), reply, sizeof(reply));
84 	if (ret)
85 		return ret;
86 
87 	/* First bytes must mirror the sent command */
88 	if (memcmp(cmd, reply, sizeof(cmd)))
89 		return -EIO;
90 
91 	/*
92 	 * There is an unknown bit set in bit7.
93 	 * Bits [6:0] report the actual temperature as returned by the
94 	 * original qnap firmware-tools, so just drop bit7 for now.
95 	 */
96 	return (reply[3] & 0x7f) * 1000;
97 }
98 
99 static int qnap_mcu_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
100 				u32 attr, int channel, long val)
101 {
102 	struct qnap_mcu_hwmon *hwm = dev_get_drvdata(dev);
103 
104 	switch (attr) {
105 	case hwmon_pwm_input:
106 		if (val < 0 || val > 255)
107 			return -EINVAL;
108 
109 		if (val != 0)
110 			val = clamp_val(val, hwm->pwm_min, hwm->pwm_max);
111 
112 		return qnap_mcu_hwmon_set_pwm(hwm, val);
113 	default:
114 		return -EOPNOTSUPP;
115 	}
116 
117 	return 0;
118 }
119 
120 static int qnap_mcu_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
121 			       u32 attr, int channel, long *val)
122 {
123 	struct qnap_mcu_hwmon *hwm = dev_get_drvdata(dev);
124 	int ret;
125 
126 	switch (type) {
127 	case hwmon_pwm:
128 		switch (attr) {
129 		case hwmon_pwm_input:
130 			ret = qnap_mcu_hwmon_get_pwm(hwm);
131 			if (ret < 0)
132 				return ret;
133 
134 			*val = ret;
135 			return 0;
136 		default:
137 			return -EOPNOTSUPP;
138 		}
139 	case hwmon_fan:
140 		ret = qnap_mcu_hwmon_get_rpm(hwm);
141 		if (ret < 0)
142 			return ret;
143 
144 		*val = ret;
145 		return 0;
146 	case hwmon_temp:
147 		ret = qnap_mcu_hwmon_get_temp(hwm);
148 		if (ret < 0)
149 			return ret;
150 
151 		*val = ret;
152 		return 0;
153 	default:
154 		return -EOPNOTSUPP;
155 	}
156 }
157 
158 static umode_t qnap_mcu_hwmon_is_visible(const void *data,
159 					 enum hwmon_sensor_types type,
160 					 u32 attr, int channel)
161 {
162 	switch (type) {
163 	case hwmon_temp:
164 		return 0444;
165 
166 	case hwmon_pwm:
167 		return 0644;
168 
169 	case hwmon_fan:
170 		return 0444;
171 
172 	default:
173 		return 0;
174 	}
175 }
176 
177 static const struct hwmon_ops qnap_mcu_hwmon_hwmon_ops = {
178 	.is_visible = qnap_mcu_hwmon_is_visible,
179 	.read = qnap_mcu_hwmon_read,
180 	.write = qnap_mcu_hwmon_write,
181 };
182 
183 /* thermal cooling device callbacks */
184 static int qnap_mcu_hwmon_get_max_state(struct thermal_cooling_device *cdev,
185 					unsigned long *state)
186 {
187 	struct qnap_mcu_hwmon *hwm = cdev->devdata;
188 
189 	if (!hwm)
190 		return -EINVAL;
191 
192 	*state = hwm->fan_max_state;
193 
194 	return 0;
195 }
196 
197 static int qnap_mcu_hwmon_get_cur_state(struct thermal_cooling_device *cdev,
198 					unsigned long *state)
199 {
200 	struct qnap_mcu_hwmon *hwm = cdev->devdata;
201 
202 	if (!hwm)
203 		return -EINVAL;
204 
205 	*state = hwm->fan_state;
206 
207 	return 0;
208 }
209 
210 static int qnap_mcu_hwmon_set_cur_state(struct thermal_cooling_device *cdev,
211 					unsigned long state)
212 {
213 	struct qnap_mcu_hwmon *hwm = cdev->devdata;
214 	int ret;
215 
216 	if (!hwm || state > hwm->fan_max_state)
217 		return -EINVAL;
218 
219 	if (state == hwm->fan_state)
220 		return 0;
221 
222 	ret = qnap_mcu_hwmon_set_pwm(hwm, hwm->fan_cooling_levels[state]);
223 	if (ret)
224 		return ret;
225 
226 	hwm->fan_state = state;
227 
228 	return ret;
229 }
230 
231 static const struct thermal_cooling_device_ops qnap_mcu_hwmon_cooling_ops = {
232 	.get_max_state = qnap_mcu_hwmon_get_max_state,
233 	.get_cur_state = qnap_mcu_hwmon_get_cur_state,
234 	.set_cur_state = qnap_mcu_hwmon_set_cur_state,
235 };
236 
237 static void devm_fan_node_release(void *data)
238 {
239 	struct qnap_mcu_hwmon *hwm = data;
240 
241 	fwnode_handle_put(hwm->fan_node);
242 }
243 
244 static int qnap_mcu_hwmon_get_cooling_data(struct device *dev, struct qnap_mcu_hwmon *hwm)
245 {
246 	struct fwnode_handle *fwnode;
247 	int num, i, ret;
248 
249 	fwnode = device_get_named_child_node(dev->parent, "fan-0");
250 	if (!fwnode)
251 		return 0;
252 
253 	/* if we found the fan-node, we're keeping it until device-unbind */
254 	hwm->fan_node = fwnode;
255 	ret = devm_add_action_or_reset(dev, devm_fan_node_release, hwm);
256 	if (ret)
257 		return ret;
258 
259 	num = fwnode_property_count_u32(fwnode, "cooling-levels");
260 	if (num <= 0)
261 		return dev_err_probe(dev, num ? : -EINVAL,
262 				     "Failed to count elements in 'cooling-levels'\n");
263 
264 	hwm->fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32),
265 					       GFP_KERNEL);
266 	if (!hwm->fan_cooling_levels)
267 		return -ENOMEM;
268 
269 	ret = fwnode_property_read_u32_array(fwnode, "cooling-levels",
270 					     hwm->fan_cooling_levels, num);
271 	if (ret)
272 		return dev_err_probe(dev, ret, "Failed to read 'cooling-levels'\n");
273 
274 	for (i = 0; i < num; i++) {
275 		if (hwm->fan_cooling_levels[i] > hwm->pwm_max)
276 			return dev_err_probe(dev, -EINVAL, "fan state[%d]:%d > %d\n", i,
277 					     hwm->fan_cooling_levels[i], hwm->pwm_max);
278 	}
279 
280 	hwm->fan_max_state = num - 1;
281 
282 	return 0;
283 }
284 
285 static const struct hwmon_channel_info * const qnap_mcu_hwmon_channels[] = {
286 	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT),
287 	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
288 	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
289 	NULL
290 };
291 
292 static int qnap_mcu_hwmon_probe(struct platform_device *pdev)
293 {
294 	struct qnap_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
295 	const struct qnap_mcu_variant *variant = pdev->dev.platform_data;
296 	struct qnap_mcu_hwmon *hwm;
297 	struct thermal_cooling_device *cdev;
298 	struct device *dev = &pdev->dev;
299 	struct device *hwmon;
300 	int ret;
301 
302 	hwm = devm_kzalloc(dev, sizeof(*hwm), GFP_KERNEL);
303 	if (!hwm)
304 		return -ENOMEM;
305 
306 	hwm->mcu = mcu;
307 	hwm->dev = &pdev->dev;
308 	hwm->pwm_min = variant->fan_pwm_min;
309 	hwm->pwm_max = variant->fan_pwm_max;
310 
311 	platform_set_drvdata(pdev, hwm);
312 
313 	/*
314 	 * Set duty cycle to maximum allowed.
315 	 */
316 	ret = qnap_mcu_hwmon_set_pwm(hwm, hwm->pwm_max);
317 	if (ret)
318 		return ret;
319 
320 	hwm->info.ops = &qnap_mcu_hwmon_hwmon_ops;
321 	hwm->info.info = qnap_mcu_hwmon_channels;
322 
323 	ret = qnap_mcu_hwmon_get_cooling_data(dev, hwm);
324 	if (ret)
325 		return ret;
326 
327 	hwm->fan_state = hwm->fan_max_state;
328 
329 	hwmon = devm_hwmon_device_register_with_info(dev, "qnapmcu",
330 						     hwm, &hwm->info, NULL);
331 	if (IS_ERR(hwmon))
332 		return dev_err_probe(dev, PTR_ERR(hwmon), "Failed to register hwmon device\n");
333 
334 	/*
335 	 * Only register cooling device when we found cooling-levels.
336 	 * qnap_mcu_hwmon_get_cooling_data() will fail when reading malformed
337 	 * levels and only succeed with either no or correct cooling levels.
338 	 */
339 	if (IS_ENABLED(CONFIG_THERMAL) && hwm->fan_cooling_levels) {
340 		cdev = devm_thermal_of_cooling_device_register(dev,
341 					to_of_node(hwm->fan_node), "qnap-mcu-hwmon",
342 					hwm, &qnap_mcu_hwmon_cooling_ops);
343 		if (IS_ERR(cdev))
344 			return dev_err_probe(dev, PTR_ERR(cdev),
345 				"Failed to register qnap-mcu-hwmon as cooling device\n");
346 		hwm->cdev = cdev;
347 	}
348 
349 	return 0;
350 }
351 
352 static struct platform_driver qnap_mcu_hwmon_driver = {
353 	.probe = qnap_mcu_hwmon_probe,
354 	.driver = {
355 		.name = "qnap-mcu-hwmon",
356 	},
357 };
358 module_platform_driver(qnap_mcu_hwmon_driver);
359 
360 MODULE_ALIAS("platform:qnap-mcu-hwmon");
361 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
362 MODULE_DESCRIPTION("QNAP MCU hwmon driver");
363 MODULE_LICENSE("GPL");
364