GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / hwmon / gigabyte_waterforce.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * hwmon driver for Gigabyte AORUS Waterforce AIO CPU coolers: X240, X280 and X360.
4  *
5  * Copyright 2023 Aleksa Savic <savicaleksa83@gmail.com>
6  */
7
8 #include <linux/debugfs.h>
9 #include <linux/hid.h>
10 #include <linux/hwmon.h>
11 #include <linux/jiffies.h>
12 #include <linux/module.h>
13 #include <linux/spinlock.h>
14 #include <asm/unaligned.h>
15
16 #define DRIVER_NAME     "gigabyte_waterforce"
17
18 #define USB_VENDOR_ID_GIGABYTE          0x1044
19 #define USB_PRODUCT_ID_WATERFORCE       0x7a4d  /* Gigabyte AORUS WATERFORCE X240, X280 and X360 */
20
21 #define STATUS_VALIDITY         (2 * 1000)      /* ms */
22 #define MAX_REPORT_LENGTH       6144
23
24 #define WATERFORCE_TEMP_SENSOR  0xD
25 #define WATERFORCE_FAN_SPEED    0x02
26 #define WATERFORCE_PUMP_SPEED   0x05
27 #define WATERFORCE_FAN_DUTY     0x08
28 #define WATERFORCE_PUMP_DUTY    0x09
29
30 /* Control commands, inner offsets and lengths */
31 static const u8 get_status_cmd[] = { 0x99, 0xDA };
32
33 #define FIRMWARE_VER_START_OFFSET_1     2
34 #define FIRMWARE_VER_START_OFFSET_2     3
35 static const u8 get_firmware_ver_cmd[] = { 0x99, 0xD6 };
36
37 /* Command lengths */
38 #define GET_STATUS_CMD_LENGTH           2
39 #define GET_FIRMWARE_VER_CMD_LENGTH     2
40
41 static const char *const waterforce_temp_label[] = {
42         "Coolant temp"
43 };
44
45 static const char *const waterforce_speed_label[] = {
46         "Fan speed",
47         "Pump speed"
48 };
49
50 struct waterforce_data {
51         struct hid_device *hdev;
52         struct device *hwmon_dev;
53         struct dentry *debugfs;
54         /* For locking access to buffer */
55         struct mutex buffer_lock;
56         /* For queueing multiple readers */
57         struct mutex status_report_request_mutex;
58         /* For reinitializing the completion below */
59         spinlock_t status_report_request_lock;
60         struct completion status_report_received;
61         struct completion fw_version_processed;
62
63         /* Sensor data */
64         s32 temp_input[1];
65         u16 speed_input[2];     /* Fan and pump speed in RPM */
66         u8 duty_input[2];       /* Fan and pump duty in 0-100% */
67
68         u8 *buffer;
69         int firmware_version;
70         unsigned long updated;  /* jiffies */
71 };
72
73 static umode_t waterforce_is_visible(const void *data,
74                                      enum hwmon_sensor_types type, u32 attr, int channel)
75 {
76         switch (type) {
77         case hwmon_temp:
78                 switch (attr) {
79                 case hwmon_temp_label:
80                 case hwmon_temp_input:
81                         return 0444;
82                 default:
83                         break;
84                 }
85                 break;
86         case hwmon_fan:
87                 switch (attr) {
88                 case hwmon_fan_label:
89                 case hwmon_fan_input:
90                         return 0444;
91                 default:
92                         break;
93                 }
94                 break;
95         case hwmon_pwm:
96                 switch (attr) {
97                 case hwmon_pwm_input:
98                         return 0444;
99                 default:
100                         break;
101                 }
102                 break;
103         default:
104                 break;
105         }
106
107         return 0;
108 }
109
110 /* Writes the command to the device with the rest of the report filled with zeroes */
111 static int waterforce_write_expanded(struct waterforce_data *priv, const u8 *cmd, int cmd_length)
112 {
113         int ret;
114
115         mutex_lock(&priv->buffer_lock);
116
117         memcpy_and_pad(priv->buffer, MAX_REPORT_LENGTH, cmd, cmd_length, 0x00);
118         ret = hid_hw_output_report(priv->hdev, priv->buffer, MAX_REPORT_LENGTH);
119
120         mutex_unlock(&priv->buffer_lock);
121         return ret;
122 }
123
124 static int waterforce_get_status(struct waterforce_data *priv)
125 {
126         int ret = mutex_lock_interruptible(&priv->status_report_request_mutex);
127
128         if (ret < 0)
129                 return ret;
130
131         if (!time_after(jiffies, priv->updated + msecs_to_jiffies(STATUS_VALIDITY))) {
132                 /* Data is up to date */
133                 goto unlock_and_return;
134         }
135
136         /*
137          * Disable raw event parsing for a moment to safely reinitialize the
138          * completion. Reinit is done because hidraw could have triggered
139          * the raw event parsing and marked the priv->status_report_received
140          * completion as done.
141          */
142         spin_lock_bh(&priv->status_report_request_lock);
143         reinit_completion(&priv->status_report_received);
144         spin_unlock_bh(&priv->status_report_request_lock);
145
146         /* Send command for getting status */
147         ret = waterforce_write_expanded(priv, get_status_cmd, GET_STATUS_CMD_LENGTH);
148         if (ret < 0)
149                 goto unlock_and_return;
150
151         ret = wait_for_completion_interruptible_timeout(&priv->status_report_received,
152                                                         msecs_to_jiffies(STATUS_VALIDITY));
153         if (ret == 0)
154                 ret = -ETIMEDOUT;
155
156 unlock_and_return:
157         mutex_unlock(&priv->status_report_request_mutex);
158         if (ret < 0)
159                 return ret;
160
161         return 0;
162 }
163
164 static int waterforce_read(struct device *dev, enum hwmon_sensor_types type,
165                            u32 attr, int channel, long *val)
166 {
167         struct waterforce_data *priv = dev_get_drvdata(dev);
168         int ret = waterforce_get_status(priv);
169
170         if (ret < 0)
171                 return ret;
172
173         switch (type) {
174         case hwmon_temp:
175                 *val = priv->temp_input[channel];
176                 break;
177         case hwmon_fan:
178                 *val = priv->speed_input[channel];
179                 break;
180         case hwmon_pwm:
181                 switch (attr) {
182                 case hwmon_pwm_input:
183                         *val = DIV_ROUND_CLOSEST(priv->duty_input[channel] * 255, 100);
184                         break;
185                 default:
186                         return -EOPNOTSUPP;
187                 }
188                 break;
189         default:
190                 return -EOPNOTSUPP;     /* unreachable */
191         }
192
193         return 0;
194 }
195
196 static int waterforce_read_string(struct device *dev, enum hwmon_sensor_types type,
197                                   u32 attr, int channel, const char **str)
198 {
199         switch (type) {
200         case hwmon_temp:
201                 *str = waterforce_temp_label[channel];
202                 break;
203         case hwmon_fan:
204                 *str = waterforce_speed_label[channel];
205                 break;
206         default:
207                 return -EOPNOTSUPP;     /* unreachable */
208         }
209
210         return 0;
211 }
212
213 static int waterforce_get_fw_ver(struct hid_device *hdev)
214 {
215         struct waterforce_data *priv = hid_get_drvdata(hdev);
216         int ret;
217
218         ret = waterforce_write_expanded(priv, get_firmware_ver_cmd, GET_FIRMWARE_VER_CMD_LENGTH);
219         if (ret < 0)
220                 return ret;
221
222         ret = wait_for_completion_interruptible_timeout(&priv->fw_version_processed,
223                                                         msecs_to_jiffies(STATUS_VALIDITY));
224         if (ret == 0)
225                 return -ETIMEDOUT;
226         else if (ret < 0)
227                 return ret;
228
229         return 0;
230 }
231
232 static const struct hwmon_ops waterforce_hwmon_ops = {
233         .is_visible = waterforce_is_visible,
234         .read = waterforce_read,
235         .read_string = waterforce_read_string
236 };
237
238 static const struct hwmon_channel_info *waterforce_info[] = {
239         HWMON_CHANNEL_INFO(temp,
240                            HWMON_T_INPUT | HWMON_T_LABEL),
241         HWMON_CHANNEL_INFO(fan,
242                            HWMON_F_INPUT | HWMON_F_LABEL,
243                            HWMON_F_INPUT | HWMON_F_LABEL),
244         HWMON_CHANNEL_INFO(pwm,
245                            HWMON_PWM_INPUT,
246                            HWMON_PWM_INPUT),
247         NULL
248 };
249
250 static const struct hwmon_chip_info waterforce_chip_info = {
251         .ops = &waterforce_hwmon_ops,
252         .info = waterforce_info,
253 };
254
255 static int waterforce_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data,
256                                 int size)
257 {
258         struct waterforce_data *priv = hid_get_drvdata(hdev);
259
260         if (data[0] == get_firmware_ver_cmd[0] && data[1] == get_firmware_ver_cmd[1]) {
261                 /* Received a firmware version report */
262                 priv->firmware_version =
263                     data[FIRMWARE_VER_START_OFFSET_1] * 10 + data[FIRMWARE_VER_START_OFFSET_2];
264
265                 if (!completion_done(&priv->fw_version_processed))
266                         complete_all(&priv->fw_version_processed);
267                 return 0;
268         }
269
270         if (data[0] != get_status_cmd[0] || data[1] != get_status_cmd[1])
271                 return 0;
272
273         priv->temp_input[0] = data[WATERFORCE_TEMP_SENSOR] * 1000;
274         priv->speed_input[0] = get_unaligned_le16(data + WATERFORCE_FAN_SPEED);
275         priv->speed_input[1] = get_unaligned_le16(data + WATERFORCE_PUMP_SPEED);
276         priv->duty_input[0] = data[WATERFORCE_FAN_DUTY];
277         priv->duty_input[1] = data[WATERFORCE_PUMP_DUTY];
278
279         spin_lock(&priv->status_report_request_lock);
280         if (!completion_done(&priv->status_report_received))
281                 complete_all(&priv->status_report_received);
282         spin_unlock(&priv->status_report_request_lock);
283
284         priv->updated = jiffies;
285
286         return 0;
287 }
288
289 static int firmware_version_show(struct seq_file *seqf, void *unused)
290 {
291         struct waterforce_data *priv = seqf->private;
292
293         seq_printf(seqf, "%u\n", priv->firmware_version);
294
295         return 0;
296 }
297 DEFINE_SHOW_ATTRIBUTE(firmware_version);
298
299 static void waterforce_debugfs_init(struct waterforce_data *priv)
300 {
301         char name[64];
302
303         if (!priv->firmware_version)
304                 return; /* There's nothing to show in debugfs */
305
306         scnprintf(name, sizeof(name), "%s-%s", DRIVER_NAME, dev_name(&priv->hdev->dev));
307
308         priv->debugfs = debugfs_create_dir(name, NULL);
309         debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops);
310 }
311
312 static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id *id)
313 {
314         struct waterforce_data *priv;
315         int ret;
316
317         priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
318         if (!priv)
319                 return -ENOMEM;
320
321         priv->hdev = hdev;
322         hid_set_drvdata(hdev, priv);
323
324         /*
325          * Initialize priv->updated to STATUS_VALIDITY seconds in the past, making
326          * the initial empty data invalid for waterforce_read() without the need for
327          * a special case there.
328          */
329         priv->updated = jiffies - msecs_to_jiffies(STATUS_VALIDITY);
330
331         ret = hid_parse(hdev);
332         if (ret) {
333                 hid_err(hdev, "hid parse failed with %d\n", ret);
334                 return ret;
335         }
336
337         /*
338          * Enable hidraw so existing user-space tools can continue to work.
339          */
340         ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
341         if (ret) {
342                 hid_err(hdev, "hid hw start failed with %d\n", ret);
343                 return ret;
344         }
345
346         ret = hid_hw_open(hdev);
347         if (ret) {
348                 hid_err(hdev, "hid hw open failed with %d\n", ret);
349                 goto fail_and_stop;
350         }
351
352         priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL);
353         if (!priv->buffer) {
354                 ret = -ENOMEM;
355                 goto fail_and_close;
356         }
357
358         mutex_init(&priv->status_report_request_mutex);
359         mutex_init(&priv->buffer_lock);
360         spin_lock_init(&priv->status_report_request_lock);
361         init_completion(&priv->status_report_received);
362         init_completion(&priv->fw_version_processed);
363
364         hid_device_io_start(hdev);
365         ret = waterforce_get_fw_ver(hdev);
366         if (ret < 0)
367                 hid_warn(hdev, "fw version request failed with %d\n", ret);
368
369         priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "waterforce",
370                                                           priv, &waterforce_chip_info, NULL);
371         if (IS_ERR(priv->hwmon_dev)) {
372                 ret = PTR_ERR(priv->hwmon_dev);
373                 hid_err(hdev, "hwmon registration failed with %d\n", ret);
374                 goto fail_and_close;
375         }
376
377         waterforce_debugfs_init(priv);
378
379         return 0;
380
381 fail_and_close:
382         hid_hw_close(hdev);
383 fail_and_stop:
384         hid_hw_stop(hdev);
385         return ret;
386 }
387
388 static void waterforce_remove(struct hid_device *hdev)
389 {
390         struct waterforce_data *priv = hid_get_drvdata(hdev);
391
392         debugfs_remove_recursive(priv->debugfs);
393         hwmon_device_unregister(priv->hwmon_dev);
394
395         hid_hw_close(hdev);
396         hid_hw_stop(hdev);
397 }
398
399 static const struct hid_device_id waterforce_table[] = {
400         { HID_USB_DEVICE(USB_VENDOR_ID_GIGABYTE, USB_PRODUCT_ID_WATERFORCE) },
401         { }
402 };
403
404 MODULE_DEVICE_TABLE(hid, waterforce_table);
405
406 static struct hid_driver waterforce_driver = {
407         .name = "waterforce",
408         .id_table = waterforce_table,
409         .probe = waterforce_probe,
410         .remove = waterforce_remove,
411         .raw_event = waterforce_raw_event,
412 };
413
414 static int __init waterforce_init(void)
415 {
416         return hid_register_driver(&waterforce_driver);
417 }
418
419 static void __exit waterforce_exit(void)
420 {
421         hid_unregister_driver(&waterforce_driver);
422 }
423
424 /* When compiled into the kernel, initialize after the HID bus */
425 late_initcall(waterforce_init);
426 module_exit(waterforce_exit);
427
428 MODULE_LICENSE("GPL");
429 MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>");
430 MODULE_DESCRIPTION("Hwmon driver for Gigabyte AORUS Waterforce AIO coolers");