1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * corsair-psu.c - Linux driver for Corsair power supplies with HID sensors interface 4 * Copyright (C) 2020 Wilken Gottwalt <wilken.gottwalt@posteo.net> 5 */ 6 7 #include <linux/completion.h> 8 #include <linux/debugfs.h> 9 #include <linux/errno.h> 10 #include <linux/hid.h> 11 #include <linux/hwmon.h> 12 #include <linux/jiffies.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/types.h> 17 18 /* 19 * Corsair protocol for PSUs 20 * 21 * message size = 64 bytes (request and response, little endian) 22 * request: 23 * [length][command][param0][param1][paramX]... 24 * reply: 25 * [echo of length][echo of command][data0][data1][dataX]... 26 * 27 * - commands are byte sized opcodes 28 * - length is the sum of all bytes of the commands/params 29 * - the micro-controller of most of these PSUs support concatenation in the request and reply, 30 * but it is better to not rely on this (it is also hard to parse) 31 * - the driver uses raw events to be accessible from userspace (though this is not really 32 * supported, it is just there for convenience, may be removed in the future) 33 * - a reply always starts with the length and command in the same order the request used it 34 * - length of the reply data is specific to the command used 35 * - some of the commands work on a rail and can be switched to a specific rail (0 = 12v, 36 * 1 = 5v, 2 = 3.3v) 37 * - the format of the init command 0xFE is swapped length/command bytes 38 * - parameter bytes amount and values are specific to the command (rail setting is the only 39 * one for now that uses non-zero values) 40 * - the driver supports debugfs for values not fitting into the hwmon class 41 * - not every device class (HXi or RMi) supports all commands 42 * - if configured wrong the PSU resets or shuts down, often before actually hitting the 43 * reported critical temperature 44 * - new models like HX1500i Series 2023 have changes in the reported vendor and product 45 * strings, both are slightly longer now, report vendor and product in one string and are 46 * the same now 47 */ 48 49 #define DRIVER_NAME "corsair-psu" 50 51 #define REPLY_SIZE 24 /* max length of a reply to a single command */ 52 #define CMD_BUFFER_SIZE 64 53 #define CMD_TIMEOUT_MS 250 54 #define SECONDS_PER_HOUR (60 * 60) 55 #define SECONDS_PER_DAY (SECONDS_PER_HOUR * 24) 56 #define RAIL_COUNT 3 /* 3v3 + 5v + 12v */ 57 #define TEMP_COUNT 2 58 #define OCP_MULTI_RAIL 0x02 59 60 #define PSU_CMD_SELECT_RAIL 0x00 /* expects length 2 */ 61 #define PSU_CMD_FAN_PWM 0x3B /* the rest of the commands expect length 3 */ 62 #define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 63 #define PSU_CMD_RAIL_VOLTS_LCRIT 0x44 64 #define PSU_CMD_RAIL_AMPS_HCRIT 0x46 65 #define PSU_CMD_TEMP_HCRIT 0x4F 66 #define PSU_CMD_IN_VOLTS 0x88 67 #define PSU_CMD_IN_AMPS 0x89 68 #define PSU_CMD_RAIL_VOLTS 0x8B 69 #define PSU_CMD_RAIL_AMPS 0x8C 70 #define PSU_CMD_TEMP0 0x8D 71 #define PSU_CMD_TEMP1 0x8E 72 #define PSU_CMD_FAN 0x90 73 #define PSU_CMD_RAIL_WATTS 0x96 74 #define PSU_CMD_VEND_STR 0x99 75 #define PSU_CMD_PROD_STR 0x9A 76 #define PSU_CMD_TOTAL_UPTIME 0xD1 77 #define PSU_CMD_UPTIME 0xD2 78 #define PSU_CMD_OCPMODE 0xD8 79 #define PSU_CMD_TOTAL_WATTS 0xEE 80 #define PSU_CMD_FAN_PWM_ENABLE 0xF0 81 #define PSU_CMD_INIT 0xFE 82 83 #define L_IN_VOLTS "v_in" 84 #define L_OUT_VOLTS_12V "v_out +12v" 85 #define L_OUT_VOLTS_5V "v_out +5v" 86 #define L_OUT_VOLTS_3_3V "v_out +3.3v" 87 #define L_IN_AMPS "curr in" 88 #define L_AMPS_12V "curr +12v" 89 #define L_AMPS_5V "curr +5v" 90 #define L_AMPS_3_3V "curr +3.3v" 91 #define L_FAN "psu fan" 92 #define L_TEMP0 "vrm temp" 93 #define L_TEMP1 "case temp" 94 #define L_WATTS "power total" 95 #define L_WATTS_12V "power +12v" 96 #define L_WATTS_5V "power +5v" 97 #define L_WATTS_3_3V "power +3.3v" 98 99 static const char *const label_watts[] = { 100 L_WATTS, 101 L_WATTS_12V, 102 L_WATTS_5V, 103 L_WATTS_3_3V 104 }; 105 106 static const char *const label_volts[] = { 107 L_IN_VOLTS, 108 L_OUT_VOLTS_12V, 109 L_OUT_VOLTS_5V, 110 L_OUT_VOLTS_3_3V 111 }; 112 113 static const char *const label_amps[] = { 114 L_IN_AMPS, 115 L_AMPS_12V, 116 L_AMPS_5V, 117 L_AMPS_3_3V 118 }; 119 120 struct corsairpsu_data { 121 struct hid_device *hdev; 122 struct device *hwmon_dev; 123 struct dentry *debugfs; 124 struct completion wait_completion; 125 u8 *cmd_buffer; 126 char vendor[REPLY_SIZE]; 127 char product[REPLY_SIZE]; 128 long temp_crit[TEMP_COUNT]; 129 long in_crit[RAIL_COUNT]; 130 long in_lcrit[RAIL_COUNT]; 131 long curr_crit[RAIL_COUNT]; 132 u8 temp_crit_support; 133 u8 in_crit_support; 134 u8 in_lcrit_support; 135 u8 curr_crit_support; 136 bool in_curr_cmd_support; /* not all commands are supported on every PSU */ 137 }; 138 139 /* some values are SMBus LINEAR11 data which need a conversion */ 140 static int corsairpsu_linear11_to_int(const u16 val, const int scale) 141 { 142 const int exp = ((s16)val) >> 11; 143 const int mant = (((s16)(val & 0x7ff)) << 5) >> 5; 144 const int result = mant * scale; 145 146 return (exp >= 0) ? (result << exp) : (result >> -exp); 147 } 148 149 /* the micro-controller uses percentage values to control pwm */ 150 static int corsairpsu_dutycycle_to_pwm(const long dutycycle) 151 { 152 const int result = (256 << 16) / 100; 153 154 return (result * dutycycle) >> 16; 155 } 156 157 static int corsairpsu_usb_cmd(struct corsairpsu_data *priv, u8 p0, u8 p1, u8 p2, void *data) 158 { 159 unsigned long time; 160 int ret; 161 162 memset(priv->cmd_buffer, 0, CMD_BUFFER_SIZE); 163 priv->cmd_buffer[0] = p0; 164 priv->cmd_buffer[1] = p1; 165 priv->cmd_buffer[2] = p2; 166 167 reinit_completion(&priv->wait_completion); 168 169 ret = hid_hw_output_report(priv->hdev, priv->cmd_buffer, CMD_BUFFER_SIZE); 170 if (ret < 0) 171 return ret; 172 173 time = wait_for_completion_timeout(&priv->wait_completion, 174 msecs_to_jiffies(CMD_TIMEOUT_MS)); 175 if (!time) 176 return -ETIMEDOUT; 177 178 /* 179 * at the start of the reply is an echo of the send command/length in the same order it 180 * was send, not every command is supported on every device class, if a command is not 181 * supported, the length value in the reply is okay, but the command value is set to 0 182 */ 183 if (p0 != priv->cmd_buffer[0] || p1 != priv->cmd_buffer[1]) 184 return -EOPNOTSUPP; 185 186 if (data) 187 memcpy(data, priv->cmd_buffer + 2, REPLY_SIZE); 188 189 return 0; 190 } 191 192 static int corsairpsu_init(struct corsairpsu_data *priv) 193 { 194 /* 195 * PSU_CMD_INIT uses swapped length/command and expects 2 parameter bytes, this command 196 * actually generates a reply, but we don't need it 197 */ 198 return corsairpsu_usb_cmd(priv, PSU_CMD_INIT, 3, 0, NULL); 199 } 200 201 static int corsairpsu_fwinfo(struct corsairpsu_data *priv) 202 { 203 int ret; 204 205 ret = corsairpsu_usb_cmd(priv, 3, PSU_CMD_VEND_STR, 0, priv->vendor); 206 if (ret < 0) 207 return ret; 208 209 ret = corsairpsu_usb_cmd(priv, 3, PSU_CMD_PROD_STR, 0, priv->product); 210 if (ret < 0) 211 return ret; 212 213 return 0; 214 } 215 216 static int corsairpsu_request(struct corsairpsu_data *priv, u8 cmd, u8 rail, void *data) 217 { 218 int ret; 219 220 switch (cmd) { 221 case PSU_CMD_RAIL_VOLTS_HCRIT: 222 case PSU_CMD_RAIL_VOLTS_LCRIT: 223 case PSU_CMD_RAIL_AMPS_HCRIT: 224 case PSU_CMD_RAIL_VOLTS: 225 case PSU_CMD_RAIL_AMPS: 226 case PSU_CMD_RAIL_WATTS: 227 ret = corsairpsu_usb_cmd(priv, 2, PSU_CMD_SELECT_RAIL, rail, NULL); 228 if (ret < 0) 229 return ret; 230 break; 231 default: 232 break; 233 } 234 235 return corsairpsu_usb_cmd(priv, 3, cmd, 0, data); 236 } 237 238 static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, long *val) 239 { 240 u8 data[REPLY_SIZE]; 241 long tmp; 242 int ret; 243 244 ret = corsairpsu_request(priv, cmd, rail, data); 245 if (ret < 0) 246 return ret; 247 248 /* 249 * the biggest value here comes from the uptime command and to exceed MAXINT total uptime 250 * needs to be about 68 years, the rest are u16 values and the biggest value coming out of 251 * the LINEAR11 conversion are the watts values which are about 1500 for the strongest psu 252 * supported (HX1500i) 253 */ 254 tmp = ((long)data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; 255 switch (cmd) { 256 case PSU_CMD_RAIL_VOLTS_HCRIT: 257 case PSU_CMD_RAIL_VOLTS_LCRIT: 258 case PSU_CMD_RAIL_AMPS_HCRIT: 259 case PSU_CMD_TEMP_HCRIT: 260 case PSU_CMD_IN_VOLTS: 261 case PSU_CMD_IN_AMPS: 262 case PSU_CMD_RAIL_VOLTS: 263 case PSU_CMD_RAIL_AMPS: 264 case PSU_CMD_TEMP0: 265 case PSU_CMD_TEMP1: 266 *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000); 267 break; 268 case PSU_CMD_FAN: 269 *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); 270 break; 271 case PSU_CMD_FAN_PWM_ENABLE: 272 *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); 273 /* 274 * 0 = automatic mode, means the micro-controller controls the fan using a plan 275 * which can be modified, but changing this plan is not supported by this 276 * driver, the matching PWM mode is automatic fan speed control = PWM 2 277 * 1 = fixed mode, fan runs at a fixed speed represented by a percentage 278 * value 0-100, this matches the PWM manual fan speed control = PWM 1 279 * technically there is no PWM no fan speed control mode, it would be a combination 280 * of 1 at 100% 281 */ 282 if (*val == 0) 283 *val = 2; 284 break; 285 case PSU_CMD_FAN_PWM: 286 *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); 287 *val = corsairpsu_dutycycle_to_pwm(*val); 288 break; 289 case PSU_CMD_RAIL_WATTS: 290 case PSU_CMD_TOTAL_WATTS: 291 *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000000); 292 break; 293 case PSU_CMD_TOTAL_UPTIME: 294 case PSU_CMD_UPTIME: 295 case PSU_CMD_OCPMODE: 296 *val = tmp; 297 break; 298 default: 299 ret = -EOPNOTSUPP; 300 break; 301 } 302 303 return ret; 304 } 305 306 static void corsairpsu_get_criticals(struct corsairpsu_data *priv) 307 { 308 long tmp; 309 int rail; 310 311 for (rail = 0; rail < TEMP_COUNT; ++rail) { 312 if (!corsairpsu_get_value(priv, PSU_CMD_TEMP_HCRIT, rail, &tmp)) { 313 priv->temp_crit_support |= BIT(rail); 314 priv->temp_crit[rail] = tmp; 315 } 316 } 317 318 for (rail = 0; rail < RAIL_COUNT; ++rail) { 319 if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS_HCRIT, rail, &tmp)) { 320 priv->in_crit_support |= BIT(rail); 321 priv->in_crit[rail] = tmp; 322 } 323 324 if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS_LCRIT, rail, &tmp)) { 325 priv->in_lcrit_support |= BIT(rail); 326 priv->in_lcrit[rail] = tmp; 327 } 328 329 if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_AMPS_HCRIT, rail, &tmp)) { 330 priv->curr_crit_support |= BIT(rail); 331 priv->curr_crit[rail] = tmp; 332 } 333 } 334 } 335 336 static void corsairpsu_check_cmd_support(struct corsairpsu_data *priv) 337 { 338 long tmp; 339 340 priv->in_curr_cmd_support = !corsairpsu_get_value(priv, PSU_CMD_IN_AMPS, 0, &tmp); 341 } 342 343 static umode_t corsairpsu_hwmon_temp_is_visible(const struct corsairpsu_data *priv, u32 attr, 344 int channel) 345 { 346 umode_t res = 0444; 347 348 switch (attr) { 349 case hwmon_temp_input: 350 case hwmon_temp_label: 351 case hwmon_temp_crit: 352 if (channel > 0 && !(priv->temp_crit_support & BIT(channel - 1))) 353 res = 0; 354 break; 355 default: 356 break; 357 } 358 359 return res; 360 } 361 362 static umode_t corsairpsu_hwmon_fan_is_visible(const struct corsairpsu_data *priv, u32 attr, 363 int channel) 364 { 365 switch (attr) { 366 case hwmon_fan_input: 367 case hwmon_fan_label: 368 return 0444; 369 default: 370 return 0; 371 } 372 } 373 374 static umode_t corsairpsu_hwmon_pwm_is_visible(const struct corsairpsu_data *priv, u32 attr, 375 int channel) 376 { 377 switch (attr) { 378 case hwmon_pwm_input: 379 case hwmon_pwm_enable: 380 return 0444; 381 default: 382 return 0; 383 } 384 } 385 386 static umode_t corsairpsu_hwmon_power_is_visible(const struct corsairpsu_data *priv, u32 attr, 387 int channel) 388 { 389 switch (attr) { 390 case hwmon_power_input: 391 case hwmon_power_label: 392 return 0444; 393 default: 394 return 0; 395 } 396 } 397 398 static umode_t corsairpsu_hwmon_in_is_visible(const struct corsairpsu_data *priv, u32 attr, 399 int channel) 400 { 401 umode_t res = 0444; 402 403 switch (attr) { 404 case hwmon_in_input: 405 case hwmon_in_label: 406 case hwmon_in_crit: 407 if (channel > 0 && !(priv->in_crit_support & BIT(channel - 1))) 408 res = 0; 409 break; 410 case hwmon_in_lcrit: 411 if (channel > 0 && !(priv->in_lcrit_support & BIT(channel - 1))) 412 res = 0; 413 break; 414 default: 415 break; 416 } 417 418 return res; 419 } 420 421 static umode_t corsairpsu_hwmon_curr_is_visible(const struct corsairpsu_data *priv, u32 attr, 422 int channel) 423 { 424 umode_t res = 0444; 425 426 switch (attr) { 427 case hwmon_curr_input: 428 if (channel == 0 && !priv->in_curr_cmd_support) 429 res = 0; 430 break; 431 case hwmon_curr_label: 432 case hwmon_curr_crit: 433 if (channel > 0 && !(priv->curr_crit_support & BIT(channel - 1))) 434 res = 0; 435 break; 436 default: 437 break; 438 } 439 440 return res; 441 } 442 443 static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum hwmon_sensor_types type, 444 u32 attr, int channel) 445 { 446 const struct corsairpsu_data *priv = data; 447 448 switch (type) { 449 case hwmon_temp: 450 return corsairpsu_hwmon_temp_is_visible(priv, attr, channel); 451 case hwmon_fan: 452 return corsairpsu_hwmon_fan_is_visible(priv, attr, channel); 453 case hwmon_pwm: 454 return corsairpsu_hwmon_pwm_is_visible(priv, attr, channel); 455 case hwmon_power: 456 return corsairpsu_hwmon_power_is_visible(priv, attr, channel); 457 case hwmon_in: 458 return corsairpsu_hwmon_in_is_visible(priv, attr, channel); 459 case hwmon_curr: 460 return corsairpsu_hwmon_curr_is_visible(priv, attr, channel); 461 default: 462 return 0; 463 } 464 } 465 466 static int corsairpsu_hwmon_temp_read(struct corsairpsu_data *priv, u32 attr, int channel, 467 long *val) 468 { 469 int err = -EOPNOTSUPP; 470 471 switch (attr) { 472 case hwmon_temp_input: 473 return corsairpsu_get_value(priv, channel ? PSU_CMD_TEMP1 : PSU_CMD_TEMP0, 474 channel, val); 475 case hwmon_temp_crit: 476 *val = priv->temp_crit[channel]; 477 err = 0; 478 break; 479 default: 480 break; 481 } 482 483 return err; 484 } 485 486 static int corsairpsu_hwmon_pwm_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val) 487 { 488 switch (attr) { 489 case hwmon_pwm_input: 490 return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM, 0, val); 491 case hwmon_pwm_enable: 492 return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM_ENABLE, 0, val); 493 default: 494 break; 495 } 496 497 return -EOPNOTSUPP; 498 } 499 500 static int corsairpsu_hwmon_power_read(struct corsairpsu_data *priv, u32 attr, int channel, 501 long *val) 502 { 503 if (attr == hwmon_power_input) { 504 switch (channel) { 505 case 0: 506 return corsairpsu_get_value(priv, PSU_CMD_TOTAL_WATTS, 0, val); 507 case 1 ... 3: 508 return corsairpsu_get_value(priv, PSU_CMD_RAIL_WATTS, channel - 1, val); 509 default: 510 break; 511 } 512 } 513 514 return -EOPNOTSUPP; 515 } 516 517 static int corsairpsu_hwmon_in_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val) 518 { 519 int err = -EOPNOTSUPP; 520 521 switch (attr) { 522 case hwmon_in_input: 523 switch (channel) { 524 case 0: 525 return corsairpsu_get_value(priv, PSU_CMD_IN_VOLTS, 0, val); 526 case 1 ... 3: 527 return corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS, channel - 1, val); 528 default: 529 break; 530 } 531 break; 532 case hwmon_in_crit: 533 *val = priv->in_crit[channel - 1]; 534 err = 0; 535 break; 536 case hwmon_in_lcrit: 537 *val = priv->in_lcrit[channel - 1]; 538 err = 0; 539 break; 540 } 541 542 return err; 543 } 544 545 static int corsairpsu_hwmon_curr_read(struct corsairpsu_data *priv, u32 attr, int channel, 546 long *val) 547 { 548 int err = -EOPNOTSUPP; 549 550 switch (attr) { 551 case hwmon_curr_input: 552 switch (channel) { 553 case 0: 554 return corsairpsu_get_value(priv, PSU_CMD_IN_AMPS, 0, val); 555 case 1 ... 3: 556 return corsairpsu_get_value(priv, PSU_CMD_RAIL_AMPS, channel - 1, val); 557 default: 558 break; 559 } 560 break; 561 case hwmon_curr_crit: 562 *val = priv->curr_crit[channel - 1]; 563 err = 0; 564 break; 565 default: 566 break; 567 } 568 569 return err; 570 } 571 572 static int corsairpsu_hwmon_ops_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, 573 int channel, long *val) 574 { 575 struct corsairpsu_data *priv = dev_get_drvdata(dev); 576 577 switch (type) { 578 case hwmon_temp: 579 return corsairpsu_hwmon_temp_read(priv, attr, channel, val); 580 case hwmon_fan: 581 if (attr == hwmon_fan_input) 582 return corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val); 583 return -EOPNOTSUPP; 584 case hwmon_pwm: 585 return corsairpsu_hwmon_pwm_read(priv, attr, channel, val); 586 case hwmon_power: 587 return corsairpsu_hwmon_power_read(priv, attr, channel, val); 588 case hwmon_in: 589 return corsairpsu_hwmon_in_read(priv, attr, channel, val); 590 case hwmon_curr: 591 return corsairpsu_hwmon_curr_read(priv, attr, channel, val); 592 default: 593 return -EOPNOTSUPP; 594 } 595 } 596 597 static int corsairpsu_hwmon_ops_read_string(struct device *dev, enum hwmon_sensor_types type, 598 u32 attr, int channel, const char **str) 599 { 600 if (type == hwmon_temp && attr == hwmon_temp_label) { 601 *str = channel ? L_TEMP1 : L_TEMP0; 602 return 0; 603 } else if (type == hwmon_fan && attr == hwmon_fan_label) { 604 *str = L_FAN; 605 return 0; 606 } else if (type == hwmon_power && attr == hwmon_power_label && channel < 4) { 607 *str = label_watts[channel]; 608 return 0; 609 } else if (type == hwmon_in && attr == hwmon_in_label && channel < 4) { 610 *str = label_volts[channel]; 611 return 0; 612 } else if (type == hwmon_curr && attr == hwmon_curr_label && channel < 4) { 613 *str = label_amps[channel]; 614 return 0; 615 } 616 617 return -EOPNOTSUPP; 618 } 619 620 static const struct hwmon_ops corsairpsu_hwmon_ops = { 621 .is_visible = corsairpsu_hwmon_ops_is_visible, 622 .read = corsairpsu_hwmon_ops_read, 623 .read_string = corsairpsu_hwmon_ops_read_string, 624 }; 625 626 static const struct hwmon_channel_info *const corsairpsu_info[] = { 627 HWMON_CHANNEL_INFO(chip, 628 HWMON_C_REGISTER_TZ), 629 HWMON_CHANNEL_INFO(temp, 630 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT, 631 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT), 632 HWMON_CHANNEL_INFO(fan, 633 HWMON_F_INPUT | HWMON_F_LABEL), 634 HWMON_CHANNEL_INFO(pwm, 635 HWMON_PWM_INPUT | HWMON_PWM_ENABLE), 636 HWMON_CHANNEL_INFO(power, 637 HWMON_P_INPUT | HWMON_P_LABEL, 638 HWMON_P_INPUT | HWMON_P_LABEL, 639 HWMON_P_INPUT | HWMON_P_LABEL, 640 HWMON_P_INPUT | HWMON_P_LABEL), 641 HWMON_CHANNEL_INFO(in, 642 HWMON_I_INPUT | HWMON_I_LABEL, 643 HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | HWMON_I_CRIT, 644 HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | HWMON_I_CRIT, 645 HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | HWMON_I_CRIT), 646 HWMON_CHANNEL_INFO(curr, 647 HWMON_C_INPUT | HWMON_C_LABEL, 648 HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT, 649 HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT, 650 HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT), 651 NULL 652 }; 653 654 static const struct hwmon_chip_info corsairpsu_chip_info = { 655 .ops = &corsairpsu_hwmon_ops, 656 .info = corsairpsu_info, 657 }; 658 659 #ifdef CONFIG_DEBUG_FS 660 661 static void print_uptime(struct seq_file *seqf, u8 cmd) 662 { 663 struct corsairpsu_data *priv = seqf->private; 664 long val; 665 int ret; 666 667 ret = corsairpsu_get_value(priv, cmd, 0, &val); 668 if (ret < 0) { 669 seq_puts(seqf, "N/A\n"); 670 return; 671 } 672 673 if (val > SECONDS_PER_DAY) { 674 seq_printf(seqf, "%ld day(s), %02ld:%02ld:%02ld\n", val / SECONDS_PER_DAY, 675 val % SECONDS_PER_DAY / SECONDS_PER_HOUR, val % SECONDS_PER_HOUR / 60, 676 val % 60); 677 return; 678 } 679 680 seq_printf(seqf, "%02ld:%02ld:%02ld\n", val % SECONDS_PER_DAY / SECONDS_PER_HOUR, 681 val % SECONDS_PER_HOUR / 60, val % 60); 682 } 683 684 static int uptime_show(struct seq_file *seqf, void *unused) 685 { 686 print_uptime(seqf, PSU_CMD_UPTIME); 687 688 return 0; 689 } 690 DEFINE_SHOW_ATTRIBUTE(uptime); 691 692 static int uptime_total_show(struct seq_file *seqf, void *unused) 693 { 694 print_uptime(seqf, PSU_CMD_TOTAL_UPTIME); 695 696 return 0; 697 } 698 DEFINE_SHOW_ATTRIBUTE(uptime_total); 699 700 static int vendor_show(struct seq_file *seqf, void *unused) 701 { 702 struct corsairpsu_data *priv = seqf->private; 703 704 seq_printf(seqf, "%s\n", priv->vendor); 705 706 return 0; 707 } 708 DEFINE_SHOW_ATTRIBUTE(vendor); 709 710 static int product_show(struct seq_file *seqf, void *unused) 711 { 712 struct corsairpsu_data *priv = seqf->private; 713 714 seq_printf(seqf, "%s\n", priv->product); 715 716 return 0; 717 } 718 DEFINE_SHOW_ATTRIBUTE(product); 719 720 static int ocpmode_show(struct seq_file *seqf, void *unused) 721 { 722 struct corsairpsu_data *priv = seqf->private; 723 long val; 724 int ret; 725 726 /* 727 * The rail mode is switchable on the fly. The RAW interface can be used for this. But it 728 * will not be included here, because I consider it somewhat dangerous for the health of the 729 * PSU. The returned value can be a bogus one, if the PSU is in the process of switching and 730 * getting of the value itself can also fail during this. Because of this every other value 731 * than OCP_MULTI_RAIL can be considered as "single rail". 732 */ 733 ret = corsairpsu_get_value(priv, PSU_CMD_OCPMODE, 0, &val); 734 if (ret < 0) 735 seq_puts(seqf, "N/A\n"); 736 else 737 seq_printf(seqf, "%s\n", (val == OCP_MULTI_RAIL) ? "multi rail" : "single rail"); 738 739 return 0; 740 } 741 DEFINE_SHOW_ATTRIBUTE(ocpmode); 742 743 static void corsairpsu_debugfs_init(struct corsairpsu_data *priv) 744 { 745 char name[32]; 746 747 scnprintf(name, sizeof(name), "%s-%s", DRIVER_NAME, dev_name(&priv->hdev->dev)); 748 749 priv->debugfs = debugfs_create_dir(name, NULL); 750 debugfs_create_file("uptime", 0444, priv->debugfs, priv, &uptime_fops); 751 debugfs_create_file("uptime_total", 0444, priv->debugfs, priv, &uptime_total_fops); 752 debugfs_create_file("vendor", 0444, priv->debugfs, priv, &vendor_fops); 753 debugfs_create_file("product", 0444, priv->debugfs, priv, &product_fops); 754 debugfs_create_file("ocpmode", 0444, priv->debugfs, priv, &ocpmode_fops); 755 } 756 757 #else 758 759 static void corsairpsu_debugfs_init(struct corsairpsu_data *priv) 760 { 761 } 762 763 #endif 764 765 static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id *id) 766 { 767 struct corsairpsu_data *priv; 768 int ret; 769 770 priv = devm_kzalloc(&hdev->dev, sizeof(struct corsairpsu_data), GFP_KERNEL); 771 if (!priv) 772 return -ENOMEM; 773 774 priv->cmd_buffer = devm_kmalloc(&hdev->dev, CMD_BUFFER_SIZE, GFP_KERNEL); 775 if (!priv->cmd_buffer) 776 return -ENOMEM; 777 778 ret = hid_parse(hdev); 779 if (ret) 780 return ret; 781 782 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 783 if (ret) 784 return ret; 785 786 ret = hid_hw_open(hdev); 787 if (ret) 788 goto fail_and_stop; 789 790 priv->hdev = hdev; 791 hid_set_drvdata(hdev, priv); 792 init_completion(&priv->wait_completion); 793 794 hid_device_io_start(hdev); 795 796 ret = corsairpsu_init(priv); 797 if (ret < 0) { 798 dev_err(&hdev->dev, "unable to initialize device (%d)\n", ret); 799 goto fail_and_stop; 800 } 801 802 ret = corsairpsu_fwinfo(priv); 803 if (ret < 0) { 804 dev_err(&hdev->dev, "unable to query firmware (%d)\n", ret); 805 goto fail_and_stop; 806 } 807 808 corsairpsu_get_criticals(priv); 809 corsairpsu_check_cmd_support(priv); 810 811 priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsairpsu", priv, 812 &corsairpsu_chip_info, NULL); 813 814 if (IS_ERR(priv->hwmon_dev)) { 815 ret = PTR_ERR(priv->hwmon_dev); 816 goto fail_and_close; 817 } 818 819 corsairpsu_debugfs_init(priv); 820 821 return 0; 822 823 fail_and_close: 824 hid_hw_close(hdev); 825 fail_and_stop: 826 hid_hw_stop(hdev); 827 return ret; 828 } 829 830 static void corsairpsu_remove(struct hid_device *hdev) 831 { 832 struct corsairpsu_data *priv = hid_get_drvdata(hdev); 833 834 debugfs_remove_recursive(priv->debugfs); 835 hwmon_device_unregister(priv->hwmon_dev); 836 hid_hw_close(hdev); 837 hid_hw_stop(hdev); 838 } 839 840 static int corsairpsu_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, 841 int size) 842 { 843 struct corsairpsu_data *priv = hid_get_drvdata(hdev); 844 845 if (completion_done(&priv->wait_completion)) 846 return 0; 847 848 memcpy(priv->cmd_buffer, data, min(CMD_BUFFER_SIZE, size)); 849 complete(&priv->wait_completion); 850 851 return 0; 852 } 853 854 #ifdef CONFIG_PM 855 static int corsairpsu_resume(struct hid_device *hdev) 856 { 857 struct corsairpsu_data *priv = hid_get_drvdata(hdev); 858 859 /* some PSUs turn off the microcontroller during standby, so a reinit is required */ 860 return corsairpsu_init(priv); 861 } 862 #endif 863 864 static const struct hid_device_id corsairpsu_idtable[] = { 865 { HID_USB_DEVICE(0x1b1c, 0x1c03) }, /* Corsair HX550i */ 866 { HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */ 867 { HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */ 868 { HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */ 869 { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Legacy */ 870 { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i Legacy */ 871 { HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */ 872 { HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */ 873 { HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */ 874 { HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */ 875 { HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */ 876 { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */ 877 { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */ 878 { HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */ 879 { HID_USB_DEVICE(0x1b1c, 0x1c27) }, /* Corsair HX1200i Series 2025 */ 880 { }, 881 }; 882 MODULE_DEVICE_TABLE(hid, corsairpsu_idtable); 883 884 static struct hid_driver corsairpsu_driver = { 885 .name = DRIVER_NAME, 886 .id_table = corsairpsu_idtable, 887 .probe = corsairpsu_probe, 888 .remove = corsairpsu_remove, 889 .raw_event = corsairpsu_raw_event, 890 #ifdef CONFIG_PM 891 .resume = corsairpsu_resume, 892 .reset_resume = corsairpsu_resume, 893 #endif 894 }; 895 896 static int __init corsair_init(void) 897 { 898 return hid_register_driver(&corsairpsu_driver); 899 } 900 901 static void __exit corsair_exit(void) 902 { 903 hid_unregister_driver(&corsairpsu_driver); 904 } 905 906 /* 907 * With module_init() the driver would load before the HID bus when 908 * built-in, so use late_initcall() instead. 909 */ 910 late_initcall(corsair_init); 911 module_exit(corsair_exit); 912 913 MODULE_LICENSE("GPL"); 914 MODULE_AUTHOR("Wilken Gottwalt <wilken.gottwalt@posteo.net>"); 915 MODULE_DESCRIPTION("Linux driver for Corsair power supplies with HID sensors interface"); 916