Skip to content

Commit 0d67bbc

Browse files
wgottwaltgroeck
authored andcommitted
hwmon: (corsair-psu) add support for reading PWM values and mode
Add support for reading PWM values and mode, and update documentation accordingly. Signed-off-by: Wilken Gottwalt <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent dd5219c commit 0d67bbc

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

Documentation/hwmon/corsair-psu.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ power1_input Total power usage
6969
power2_input Power usage of the 12v psu rail
7070
power3_input Power usage of the 5v psu rail
7171
power4_input Power usage of the 3.3v psu rail
72+
pwm1 PWM value, read only
73+
pwm1_enable PWM mode, read only
7274
temp1_input Temperature of the psu vrm component
7375
temp1_crit Temperature max cirtical value of the psu vrm component
7476
temp2_input Temperature of the psu case

drivers/hwmon/corsair-psu.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
#define OCP_MULTI_RAIL 0x02
5959

6060
#define PSU_CMD_SELECT_RAIL 0x00 /* expects length 2 */
61-
#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 /* the rest of the commands expect length 3 */
61+
#define PSU_CMD_FAN_PWM 0x3B /* the rest of the commands expect length 3 */
62+
#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40
6263
#define PSU_CMD_RAIL_VOLTS_LCRIT 0x44
6364
#define PSU_CMD_RAIL_AMPS_HCRIT 0x46
6465
#define PSU_CMD_TEMP_HCRIT 0x4F
@@ -76,6 +77,7 @@
7677
#define PSU_CMD_UPTIME 0xD2
7778
#define PSU_CMD_OCPMODE 0xD8
7879
#define PSU_CMD_TOTAL_WATTS 0xEE
80+
#define PSU_CMD_FAN_PWM_ENABLE 0xF0
7981
#define PSU_CMD_INIT 0xFE
8082

8183
#define L_IN_VOLTS "v_in"
@@ -145,6 +147,14 @@ static int corsairpsu_linear11_to_int(const u16 val, const int scale)
145147
return (exp >= 0) ? (result << exp) : (result >> -exp);
146148
}
147149

150+
/* the micro-controller uses percentage values to control pwm */
151+
static int corsairpsu_dutycycle_to_pwm(const long dutycycle)
152+
{
153+
const int result = (256 << 16) / 100;
154+
155+
return (result * dutycycle) >> 16;
156+
}
157+
148158
static int corsairpsu_usb_cmd(struct corsairpsu_data *priv, u8 p0, u8 p1, u8 p2, void *data)
149159
{
150160
unsigned long time;
@@ -264,6 +274,24 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l
264274
case PSU_CMD_FAN:
265275
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
266276
break;
277+
case PSU_CMD_FAN_PWM_ENABLE:
278+
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
279+
/*
280+
* 0 = automatic mode, means the micro-controller controls the fan using a plan
281+
* which can be modified, but changing this plan is not supported by this
282+
* driver, the matching PWM mode is automatic fan speed control = PWM 2
283+
* 1 = fixed mode, fan runs at a fixed speed represented by a percentage
284+
* value 0-100, this matches the PWM manual fan speed control = PWM 1
285+
* technically there is no PWM no fan speed control mode, it would be a combination
286+
* of 1 at 100%
287+
*/
288+
if (*val == 0)
289+
*val = 2;
290+
break;
291+
case PSU_CMD_FAN_PWM:
292+
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
293+
*val = corsairpsu_dutycycle_to_pwm(*val);
294+
break;
267295
case PSU_CMD_RAIL_WATTS:
268296
case PSU_CMD_TOTAL_WATTS:
269297
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000000);
@@ -349,6 +377,18 @@ static umode_t corsairpsu_hwmon_fan_is_visible(const struct corsairpsu_data *pri
349377
}
350378
}
351379

380+
static umode_t corsairpsu_hwmon_pwm_is_visible(const struct corsairpsu_data *priv, u32 attr,
381+
int channel)
382+
{
383+
switch (attr) {
384+
case hwmon_pwm_input:
385+
case hwmon_pwm_enable:
386+
return 0444;
387+
default:
388+
return 0;
389+
}
390+
}
391+
352392
static umode_t corsairpsu_hwmon_power_is_visible(const struct corsairpsu_data *priv, u32 attr,
353393
int channel)
354394
{
@@ -416,6 +456,8 @@ static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum hwmon_sens
416456
return corsairpsu_hwmon_temp_is_visible(priv, attr, channel);
417457
case hwmon_fan:
418458
return corsairpsu_hwmon_fan_is_visible(priv, attr, channel);
459+
case hwmon_pwm:
460+
return corsairpsu_hwmon_pwm_is_visible(priv, attr, channel);
419461
case hwmon_power:
420462
return corsairpsu_hwmon_power_is_visible(priv, attr, channel);
421463
case hwmon_in:
@@ -447,6 +489,20 @@ static int corsairpsu_hwmon_temp_read(struct corsairpsu_data *priv, u32 attr, in
447489
return err;
448490
}
449491

492+
static int corsairpsu_hwmon_pwm_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val)
493+
{
494+
switch (attr) {
495+
case hwmon_pwm_input:
496+
return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM, 0, val);
497+
case hwmon_pwm_enable:
498+
return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM_ENABLE, 0, val);
499+
default:
500+
break;
501+
}
502+
503+
return -EOPNOTSUPP;
504+
}
505+
450506
static int corsairpsu_hwmon_power_read(struct corsairpsu_data *priv, u32 attr, int channel,
451507
long *val)
452508
{
@@ -531,6 +587,8 @@ static int corsairpsu_hwmon_ops_read(struct device *dev, enum hwmon_sensor_types
531587
if (attr == hwmon_fan_input)
532588
return corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val);
533589
return -EOPNOTSUPP;
590+
case hwmon_pwm:
591+
return corsairpsu_hwmon_pwm_read(priv, attr, channel, val);
534592
case hwmon_power:
535593
return corsairpsu_hwmon_power_read(priv, attr, channel, val);
536594
case hwmon_in:
@@ -579,6 +637,8 @@ static const struct hwmon_channel_info * const corsairpsu_info[] = {
579637
HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT),
580638
HWMON_CHANNEL_INFO(fan,
581639
HWMON_F_INPUT | HWMON_F_LABEL),
640+
HWMON_CHANNEL_INFO(pwm,
641+
HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
582642
HWMON_CHANNEL_INFO(power,
583643
HWMON_P_INPUT | HWMON_P_LABEL,
584644
HWMON_P_INPUT | HWMON_P_LABEL,

0 commit comments

Comments
 (0)