diff options
| author | Guenter Roeck <linux@roeck-us.net> | 2012-12-04 12:08:29 -0500 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2013-04-08 00:16:39 -0400 |
| commit | bbd8decd4123648ddeba2be485bc7e1a3117bfe4 (patch) | |
| tree | a39d3b3d8a787862b632d8c9ec0545c49a84747c | |
| parent | cdcaeceb74ff3686eb25de6812870fbc765c3c39 (diff) | |
hwmon: (nct6775) Add support for weighted fan control
The NCT677X series support weighted fan control. In this mode, a secondary
temperature source is used in addition to the primary temperature source to
control fan speed. Add support for this feature.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
| -rw-r--r-- | Documentation/hwmon/nct6775 | 19 | ||||
| -rw-r--r-- | drivers/hwmon/nct6775.c | 280 |
2 files changed, 285 insertions, 14 deletions
diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 index b4fe6bc4d371..3f5587e39093 100644 --- a/Documentation/hwmon/nct6775 +++ b/Documentation/hwmon/nct6775 | |||
| @@ -92,6 +92,25 @@ Common fan control attributes | |||
| 92 | 92 | ||
| 93 | pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. | 93 | pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. |
| 94 | For example, select '1' for temp1_input. | 94 | For example, select '1' for temp1_input. |
| 95 | pwm[1-5]_weight_temp_sel | ||
| 96 | Secondary temperature source. Value is temperature | ||
| 97 | sensor index. For example, select '1' for temp1_input. | ||
| 98 | Set to 0 to disable secondary temperature control. | ||
| 99 | |||
| 100 | If secondary temperature functionality is enabled, it is controlled with the | ||
| 101 | following attributes. | ||
| 102 | |||
| 103 | pwm[1-5]_weight_duty_step | ||
| 104 | Duty step size. | ||
| 105 | pwm[1-5]_weight_temp_step | ||
| 106 | Temperature step size. With each step over | ||
| 107 | temp_step_base, the value of weight_duty_step is added | ||
| 108 | to the current pwm value. | ||
| 109 | pwm[1-5]_weight_temp_step_base | ||
| 110 | Temperature at which secondary temperature control kicks | ||
| 111 | in. | ||
| 112 | pwm[1-5]_weight_temp_step_tol | ||
| 113 | Temperature step tolerance. | ||
| 95 | 114 | ||
| 96 | Thermal Cruise mode (2) | 115 | Thermal Cruise mode (2) |
| 97 | ----------------------- | 116 | ----------------------- |
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 47b1d8947e4d..f80ff823c28e 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c | |||
| @@ -255,6 +255,17 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { | |||
| 255 | static const u16 NCT6775_REG_TEMP_SEL[] = { | 255 | static const u16 NCT6775_REG_TEMP_SEL[] = { |
| 256 | 0x100, 0x200, 0x300, 0x800, 0x900 }; | 256 | 0x100, 0x200, 0x300, 0x800, 0x900 }; |
| 257 | 257 | ||
| 258 | static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { | ||
| 259 | 0x139, 0x239, 0x339, 0x839, 0x939 }; | ||
| 260 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { | ||
| 261 | 0x13a, 0x23a, 0x33a, 0x83a, 0x93a }; | ||
| 262 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { | ||
| 263 | 0x13b, 0x23b, 0x33b, 0x83b, 0x93b }; | ||
| 264 | static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { | ||
| 265 | 0x13c, 0x23c, 0x33c, 0x83c, 0x93c }; | ||
| 266 | static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { | ||
| 267 | 0x13d, 0x23d, 0x33d, 0x83d, 0x93d }; | ||
| 268 | |||
| 258 | static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; | 269 | static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; |
| 259 | 270 | ||
| 260 | static const u16 NCT6775_REG_AUTO_TEMP[] = { | 271 | static const u16 NCT6775_REG_AUTO_TEMP[] = { |
| @@ -323,6 +334,9 @@ static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; | |||
| 323 | static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; | 334 | static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; |
| 324 | static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; | 335 | static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; |
| 325 | 336 | ||
| 337 | static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { | ||
| 338 | 0x13e, 0x23e, 0x33e, 0x83e, 0x93e }; | ||
| 339 | |||
| 326 | static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { | 340 | static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { |
| 327 | 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; | 341 | 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; |
| 328 | 342 | ||
| @@ -571,8 +585,9 @@ struct nct6775_data { | |||
| 571 | const u8 *REG_PWM_MODE; | 585 | const u8 *REG_PWM_MODE; |
| 572 | const u8 *PWM_MODE_MASK; | 586 | const u8 *PWM_MODE_MASK; |
| 573 | 587 | ||
| 574 | const u16 *REG_PWM[5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, | 588 | const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, |
| 575 | * [3]=pwm_max, [4]=pwm_step | 589 | * [3]=pwm_max, [4]=pwm_step, |
| 590 | * [5]=weight_duty_step, [6]=weight_duty_base | ||
| 576 | */ | 591 | */ |
| 577 | const u16 *REG_PWM_READ; | 592 | const u16 *REG_PWM_READ; |
| 578 | 593 | ||
| @@ -584,6 +599,9 @@ struct nct6775_data { | |||
| 584 | 599 | ||
| 585 | const u16 *REG_TEMP_SOURCE; /* temp register sources */ | 600 | const u16 *REG_TEMP_SOURCE; /* temp register sources */ |
| 586 | const u16 *REG_TEMP_SEL; | 601 | const u16 *REG_TEMP_SEL; |
| 602 | const u16 *REG_WEIGHT_TEMP_SEL; | ||
| 603 | const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */ | ||
| 604 | |||
| 587 | const u16 *REG_TEMP_OFFSET; | 605 | const u16 *REG_TEMP_OFFSET; |
| 588 | 606 | ||
| 589 | const u16 *REG_ALARM; | 607 | const u16 *REG_ALARM; |
| @@ -625,8 +643,9 @@ struct nct6775_data { | |||
| 625 | * 4->SmartFan III | 643 | * 4->SmartFan III |
| 626 | * 5->enhanced variable thermal cruise (SmartFan IV) | 644 | * 5->enhanced variable thermal cruise (SmartFan IV) |
| 627 | */ | 645 | */ |
| 628 | u8 pwm[5][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, | 646 | u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, |
| 629 | * [3]=pwm_max, [4]=pwm_step | 647 | * [3]=pwm_max, [4]=pwm_step, |
| 648 | * [5]=weight_duty_step, [6]=weight_duty_base | ||
| 630 | */ | 649 | */ |
| 631 | 650 | ||
| 632 | u8 target_temp[5]; | 651 | u8 target_temp[5]; |
| @@ -645,6 +664,10 @@ struct nct6775_data { | |||
| 645 | u8 auto_pwm[5][7]; | 664 | u8 auto_pwm[5][7]; |
| 646 | u8 auto_temp[5][7]; | 665 | u8 auto_temp[5][7]; |
| 647 | u8 pwm_temp_sel[5]; | 666 | u8 pwm_temp_sel[5]; |
| 667 | u8 pwm_weight_temp_sel[5]; | ||
| 668 | u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol, | ||
| 669 | * 2->temp_base | ||
| 670 | */ | ||
| 648 | 671 | ||
| 649 | u8 vid; | 672 | u8 vid; |
| 650 | u8 vrm; | 673 | u8 vrm; |
| @@ -972,6 +995,19 @@ static void nct6775_update_pwm(struct device *dev) | |||
| 972 | /* If fan can stop, report floor as 0 */ | 995 | /* If fan can stop, report floor as 0 */ |
| 973 | if (reg & 0x80) | 996 | if (reg & 0x80) |
| 974 | data->pwm[2][i] = 0; | 997 | data->pwm[2][i] = 0; |
| 998 | |||
| 999 | reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]); | ||
| 1000 | data->pwm_weight_temp_sel[i] = reg & 0x1f; | ||
| 1001 | /* If weight is disabled, report weight source as 0 */ | ||
| 1002 | if (j == 1 && !(reg & 0x80)) | ||
| 1003 | data->pwm_weight_temp_sel[i] = 0; | ||
| 1004 | |||
| 1005 | /* Weight temp data */ | ||
| 1006 | for (j = 0; j < 3; j++) { | ||
| 1007 | data->weight_temp[j][i] | ||
| 1008 | = nct6775_read_value(data, | ||
| 1009 | data->REG_WEIGHT_TEMP[j][i]); | ||
| 1010 | } | ||
| 975 | } | 1011 | } |
| 976 | } | 1012 | } |
| 977 | 1013 | ||
| @@ -1938,9 +1974,9 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 1938 | int nr = sattr->nr; | 1974 | int nr = sattr->nr; |
| 1939 | int index = sattr->index; | 1975 | int index = sattr->index; |
| 1940 | unsigned long val; | 1976 | unsigned long val; |
| 1941 | int minval[5] = { 0, 1, 1, data->pwm[2][nr], 0 }; | 1977 | int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 }; |
| 1942 | int maxval[5] | 1978 | int maxval[7] |
| 1943 | = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255 }; | 1979 | = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 }; |
| 1944 | int err; | 1980 | int err; |
| 1945 | u8 reg; | 1981 | u8 reg; |
| 1946 | 1982 | ||
| @@ -2078,13 +2114,9 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, | |||
| 2078 | } | 2114 | } |
| 2079 | 2115 | ||
| 2080 | static ssize_t | 2116 | static ssize_t |
| 2081 | show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) | 2117 | show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src) |
| 2082 | { | 2118 | { |
| 2083 | struct nct6775_data *data = nct6775_update_device(dev); | 2119 | int i, sel = 0; |
| 2084 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | ||
| 2085 | int i, src, sel = 0; | ||
| 2086 | |||
| 2087 | src = data->pwm_temp_sel[sattr->index]; | ||
| 2088 | 2120 | ||
| 2089 | for (i = 0; i < NUM_TEMP; i++) { | 2121 | for (i = 0; i < NUM_TEMP; i++) { |
| 2090 | if (!(data->have_temp & (1 << i))) | 2122 | if (!(data->have_temp & (1 << i))) |
| @@ -2099,6 +2131,16 @@ show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 2099 | } | 2131 | } |
| 2100 | 2132 | ||
| 2101 | static ssize_t | 2133 | static ssize_t |
| 2134 | show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 2135 | { | ||
| 2136 | struct nct6775_data *data = nct6775_update_device(dev); | ||
| 2137 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | ||
| 2138 | int index = sattr->index; | ||
| 2139 | |||
| 2140 | return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]); | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | static ssize_t | ||
| 2102 | store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, | 2144 | store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, |
| 2103 | const char *buf, size_t count) | 2145 | const char *buf, size_t count) |
| 2104 | { | 2146 | { |
| @@ -2129,6 +2171,56 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, | |||
| 2129 | } | 2171 | } |
| 2130 | 2172 | ||
| 2131 | static ssize_t | 2173 | static ssize_t |
| 2174 | show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, | ||
| 2175 | char *buf) | ||
| 2176 | { | ||
| 2177 | struct nct6775_data *data = nct6775_update_device(dev); | ||
| 2178 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | ||
| 2179 | int index = sattr->index; | ||
| 2180 | |||
| 2181 | return show_pwm_temp_sel_common(data, buf, | ||
| 2182 | data->pwm_weight_temp_sel[index]); | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | static ssize_t | ||
| 2186 | store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, | ||
| 2187 | const char *buf, size_t count) | ||
| 2188 | { | ||
| 2189 | struct nct6775_data *data = nct6775_update_device(dev); | ||
| 2190 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | ||
| 2191 | int nr = sattr->index; | ||
| 2192 | unsigned long val; | ||
| 2193 | int err, reg, src; | ||
| 2194 | |||
| 2195 | err = kstrtoul(buf, 10, &val); | ||
| 2196 | if (err < 0) | ||
| 2197 | return err; | ||
| 2198 | if (val > NUM_TEMP) | ||
| 2199 | return -EINVAL; | ||
| 2200 | if (val && (!(data->have_temp & (1 << (val - 1))) || | ||
| 2201 | !data->temp_src[val - 1])) | ||
| 2202 | return -EINVAL; | ||
| 2203 | |||
| 2204 | mutex_lock(&data->update_lock); | ||
| 2205 | if (val) { | ||
| 2206 | src = data->temp_src[val - 1]; | ||
| 2207 | data->pwm_weight_temp_sel[nr] = src; | ||
| 2208 | reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); | ||
| 2209 | reg &= 0xe0; | ||
| 2210 | reg |= (src | 0x80); | ||
| 2211 | nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); | ||
| 2212 | } else { | ||
| 2213 | data->pwm_weight_temp_sel[nr] = 0; | ||
| 2214 | reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); | ||
| 2215 | reg &= 0x7f; | ||
| 2216 | nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); | ||
| 2217 | } | ||
| 2218 | mutex_unlock(&data->update_lock); | ||
| 2219 | |||
| 2220 | return count; | ||
| 2221 | } | ||
| 2222 | |||
| 2223 | static ssize_t | ||
| 2132 | show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) | 2224 | show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) |
| 2133 | { | 2225 | { |
| 2134 | struct nct6775_data *data = nct6775_update_device(dev); | 2226 | struct nct6775_data *data = nct6775_update_device(dev); |
| @@ -2381,6 +2473,115 @@ static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO, | |||
| 2381 | /* Smart Fan registers */ | 2473 | /* Smart Fan registers */ |
| 2382 | 2474 | ||
| 2383 | static ssize_t | 2475 | static ssize_t |
| 2476 | show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 2477 | { | ||
| 2478 | struct nct6775_data *data = nct6775_update_device(dev); | ||
| 2479 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); | ||
| 2480 | int nr = sattr->nr; | ||
| 2481 | int index = sattr->index; | ||
| 2482 | |||
| 2483 | return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000); | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | static ssize_t | ||
| 2487 | store_weight_temp(struct device *dev, struct device_attribute *attr, | ||
| 2488 | const char *buf, size_t count) | ||
| 2489 | { | ||
| 2490 | struct nct6775_data *data = dev_get_drvdata(dev); | ||
| 2491 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); | ||
| 2492 | int nr = sattr->nr; | ||
| 2493 | int index = sattr->index; | ||
| 2494 | unsigned long val; | ||
| 2495 | int err; | ||
| 2496 | |||
| 2497 | err = kstrtoul(buf, 10, &val); | ||
| 2498 | if (err < 0) | ||
| 2499 | return err; | ||
| 2500 | |||
| 2501 | val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255); | ||
| 2502 | |||
| 2503 | mutex_lock(&data->update_lock); | ||
| 2504 | data->weight_temp[index][nr] = val; | ||
| 2505 | nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); | ||
| 2506 | mutex_unlock(&data->update_lock); | ||
| 2507 | return count; | ||
| 2508 | } | ||
| 2509 | |||
| 2510 | static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO, | ||
| 2511 | show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, | ||
| 2512 | 0); | ||
| 2513 | static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO, | ||
| 2514 | show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, | ||
| 2515 | 1); | ||
| 2516 | static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO, | ||
| 2517 | show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, | ||
| 2518 | 2); | ||
| 2519 | static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO, | ||
| 2520 | show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, | ||
| 2521 | 3); | ||
| 2522 | static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO, | ||
| 2523 | show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, | ||
| 2524 | 4); | ||
| 2525 | |||
| 2526 | static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO, | ||
| 2527 | show_weight_temp, store_weight_temp, 0, 0); | ||
| 2528 | static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO, | ||
| 2529 | show_weight_temp, store_weight_temp, 1, 0); | ||
| 2530 | static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO, | ||
| 2531 | show_weight_temp, store_weight_temp, 2, 0); | ||
| 2532 | static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO, | ||
| 2533 | show_weight_temp, store_weight_temp, 3, 0); | ||
| 2534 | static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO, | ||
| 2535 | show_weight_temp, store_weight_temp, 4, 0); | ||
| 2536 | |||
| 2537 | static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO, | ||
| 2538 | show_weight_temp, store_weight_temp, 0, 1); | ||
| 2539 | static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO, | ||
| 2540 | show_weight_temp, store_weight_temp, 1, 1); | ||
| 2541 | static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO, | ||
| 2542 | show_weight_temp, store_weight_temp, 2, 1); | ||
| 2543 | static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO, | ||
| 2544 | show_weight_temp, store_weight_temp, 3, 1); | ||
| 2545 | static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO, | ||
| 2546 | show_weight_temp, store_weight_temp, 4, 1); | ||
| 2547 | |||
| 2548 | static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO, | ||
| 2549 | show_weight_temp, store_weight_temp, 0, 2); | ||
| 2550 | static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO, | ||
| 2551 | show_weight_temp, store_weight_temp, 1, 2); | ||
| 2552 | static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO, | ||
| 2553 | show_weight_temp, store_weight_temp, 2, 2); | ||
| 2554 | static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO, | ||
| 2555 | show_weight_temp, store_weight_temp, 3, 2); | ||
| 2556 | static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO, | ||
| 2557 | show_weight_temp, store_weight_temp, 4, 2); | ||
| 2558 | |||
| 2559 | static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO, | ||
| 2560 | show_pwm, store_pwm, 0, 5); | ||
| 2561 | static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO, | ||
| 2562 | show_pwm, store_pwm, 1, 5); | ||
| 2563 | static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO, | ||
| 2564 | show_pwm, store_pwm, 2, 5); | ||
| 2565 | static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO, | ||
| 2566 | show_pwm, store_pwm, 3, 5); | ||
| 2567 | static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO, | ||
| 2568 | show_pwm, store_pwm, 4, 5); | ||
| 2569 | |||
| 2570 | /* duty_base is not supported on all chips */ | ||
| 2571 | static struct sensor_device_attribute_2 sda_weight_duty_base[] = { | ||
| 2572 | SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO, | ||
| 2573 | show_pwm, store_pwm, 0, 6), | ||
| 2574 | SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO, | ||
| 2575 | show_pwm, store_pwm, 1, 6), | ||
| 2576 | SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO, | ||
| 2577 | show_pwm, store_pwm, 2, 6), | ||
| 2578 | SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO, | ||
| 2579 | show_pwm, store_pwm, 3, 6), | ||
| 2580 | SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO, | ||
| 2581 | show_pwm, store_pwm, 4, 6), | ||
| 2582 | }; | ||
| 2583 | |||
| 2584 | static ssize_t | ||
| 2384 | show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) | 2585 | show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) |
| 2385 | { | 2586 | { |
| 2386 | struct nct6775_data *data = nct6775_update_device(dev); | 2587 | struct nct6775_data *data = nct6775_update_device(dev); |
| @@ -2526,7 +2727,7 @@ static struct sensor_device_attribute_2 sda_pwm_step[] = { | |||
| 2526 | SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), | 2727 | SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), |
| 2527 | }; | 2728 | }; |
| 2528 | 2729 | ||
| 2529 | static struct attribute *nct6775_attributes_pwm[5][15] = { | 2730 | static struct attribute *nct6775_attributes_pwm[5][20] = { |
| 2530 | { | 2731 | { |
| 2531 | &sensor_dev_attr_pwm1.dev_attr.attr, | 2732 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| 2532 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, | 2733 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, |
| @@ -2542,6 +2743,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { | |||
| 2542 | &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, | 2743 | &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, |
| 2543 | &sensor_dev_attr_pwm1_start.dev_attr.attr, | 2744 | &sensor_dev_attr_pwm1_start.dev_attr.attr, |
| 2544 | &sensor_dev_attr_pwm1_floor.dev_attr.attr, | 2745 | &sensor_dev_attr_pwm1_floor.dev_attr.attr, |
| 2746 | &sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr, | ||
| 2747 | &sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr, | ||
| 2748 | &sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr, | ||
| 2749 | &sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr, | ||
| 2750 | &sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr, | ||
| 2545 | NULL | 2751 | NULL |
| 2546 | }, | 2752 | }, |
| 2547 | { | 2753 | { |
| @@ -2559,6 +2765,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { | |||
| 2559 | &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, | 2765 | &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, |
| 2560 | &sensor_dev_attr_pwm2_start.dev_attr.attr, | 2766 | &sensor_dev_attr_pwm2_start.dev_attr.attr, |
| 2561 | &sensor_dev_attr_pwm2_floor.dev_attr.attr, | 2767 | &sensor_dev_attr_pwm2_floor.dev_attr.attr, |
| 2768 | &sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr, | ||
| 2769 | &sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr, | ||
| 2770 | &sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr, | ||
| 2771 | &sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr, | ||
| 2772 | &sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr, | ||
| 2562 | NULL | 2773 | NULL |
| 2563 | }, | 2774 | }, |
| 2564 | { | 2775 | { |
| @@ -2576,6 +2787,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { | |||
| 2576 | &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, | 2787 | &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, |
| 2577 | &sensor_dev_attr_pwm3_start.dev_attr.attr, | 2788 | &sensor_dev_attr_pwm3_start.dev_attr.attr, |
| 2578 | &sensor_dev_attr_pwm3_floor.dev_attr.attr, | 2789 | &sensor_dev_attr_pwm3_floor.dev_attr.attr, |
| 2790 | &sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr, | ||
| 2791 | &sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr, | ||
| 2792 | &sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr, | ||
| 2793 | &sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr, | ||
| 2794 | &sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr, | ||
| 2579 | NULL | 2795 | NULL |
| 2580 | }, | 2796 | }, |
| 2581 | { | 2797 | { |
| @@ -2593,6 +2809,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { | |||
| 2593 | &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, | 2809 | &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, |
| 2594 | &sensor_dev_attr_pwm4_start.dev_attr.attr, | 2810 | &sensor_dev_attr_pwm4_start.dev_attr.attr, |
| 2595 | &sensor_dev_attr_pwm4_floor.dev_attr.attr, | 2811 | &sensor_dev_attr_pwm4_floor.dev_attr.attr, |
| 2812 | &sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr, | ||
| 2813 | &sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr, | ||
| 2814 | &sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr, | ||
| 2815 | &sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr, | ||
| 2816 | &sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr, | ||
| 2596 | NULL | 2817 | NULL |
| 2597 | }, | 2818 | }, |
| 2598 | { | 2819 | { |
| @@ -2610,6 +2831,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { | |||
| 2610 | &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, | 2831 | &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, |
| 2611 | &sensor_dev_attr_pwm5_start.dev_attr.attr, | 2832 | &sensor_dev_attr_pwm5_start.dev_attr.attr, |
| 2612 | &sensor_dev_attr_pwm5_floor.dev_attr.attr, | 2833 | &sensor_dev_attr_pwm5_floor.dev_attr.attr, |
| 2834 | &sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr, | ||
| 2835 | &sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr, | ||
| 2836 | &sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr, | ||
| 2837 | &sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr, | ||
| 2838 | &sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr, | ||
| 2613 | NULL | 2839 | NULL |
| 2614 | }, | 2840 | }, |
| 2615 | }; | 2841 | }; |
| @@ -2974,6 +3200,9 @@ static void nct6775_device_remove_files(struct device *dev) | |||
| 2974 | for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) | 3200 | for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) |
| 2975 | device_remove_file(dev, &sda_pwm_step[i].dev_attr); | 3201 | device_remove_file(dev, &sda_pwm_step[i].dev_attr); |
| 2976 | 3202 | ||
| 3203 | for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++) | ||
| 3204 | device_remove_file(dev, &sda_weight_duty_base[i].dev_attr); | ||
| 3205 | |||
| 2977 | for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) | 3206 | for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) |
| 2978 | device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); | 3207 | device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); |
| 2979 | 3208 | ||
| @@ -3203,6 +3432,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3203 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; | 3432 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; |
| 3204 | data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; | 3433 | data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; |
| 3205 | data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; | 3434 | data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; |
| 3435 | data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; | ||
| 3206 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; | 3436 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; |
| 3207 | data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; | 3437 | data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; |
| 3208 | data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; | 3438 | data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; |
| @@ -3214,6 +3444,10 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3214 | data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; | 3444 | data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; |
| 3215 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; | 3445 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; |
| 3216 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; | 3446 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; |
| 3447 | data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; | ||
| 3448 | data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; | ||
| 3449 | data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; | ||
| 3450 | data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; | ||
| 3217 | data->REG_ALARM = NCT6775_REG_ALARM; | 3451 | data->REG_ALARM = NCT6775_REG_ALARM; |
| 3218 | 3452 | ||
| 3219 | reg_temp = NCT6775_REG_TEMP; | 3453 | reg_temp = NCT6775_REG_TEMP; |
| @@ -3261,6 +3495,8 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3261 | data->REG_PWM[0] = NCT6775_REG_PWM; | 3495 | data->REG_PWM[0] = NCT6775_REG_PWM; |
| 3262 | data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; | 3496 | data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; |
| 3263 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; | 3497 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; |
| 3498 | data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; | ||
| 3499 | data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; | ||
| 3264 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; | 3500 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; |
| 3265 | data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; | 3501 | data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; |
| 3266 | data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; | 3502 | data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; |
| @@ -3272,6 +3508,10 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3272 | data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; | 3508 | data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; |
| 3273 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; | 3509 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; |
| 3274 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; | 3510 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; |
| 3511 | data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; | ||
| 3512 | data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; | ||
| 3513 | data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; | ||
| 3514 | data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; | ||
| 3275 | data->REG_ALARM = NCT6775_REG_ALARM; | 3515 | data->REG_ALARM = NCT6775_REG_ALARM; |
| 3276 | 3516 | ||
| 3277 | reg_temp = NCT6775_REG_TEMP; | 3517 | reg_temp = NCT6775_REG_TEMP; |
| @@ -3319,6 +3559,8 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3319 | data->REG_PWM[0] = NCT6775_REG_PWM; | 3559 | data->REG_PWM[0] = NCT6775_REG_PWM; |
| 3320 | data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; | 3560 | data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; |
| 3321 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; | 3561 | data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; |
| 3562 | data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; | ||
| 3563 | data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; | ||
| 3322 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; | 3564 | data->REG_PWM_READ = NCT6775_REG_PWM_READ; |
| 3323 | data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; | 3565 | data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; |
| 3324 | data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; | 3566 | data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; |
| @@ -3330,6 +3572,10 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3330 | data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; | 3572 | data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; |
| 3331 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; | 3573 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; |
| 3332 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; | 3574 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; |
| 3575 | data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; | ||
| 3576 | data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; | ||
| 3577 | data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; | ||
| 3578 | data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; | ||
| 3333 | data->REG_ALARM = NCT6779_REG_ALARM; | 3579 | data->REG_ALARM = NCT6779_REG_ALARM; |
| 3334 | 3580 | ||
| 3335 | reg_temp = NCT6779_REG_TEMP; | 3581 | reg_temp = NCT6779_REG_TEMP; |
| @@ -3557,6 +3803,12 @@ static int nct6775_probe(struct platform_device *pdev) | |||
| 3557 | if (err) | 3803 | if (err) |
| 3558 | goto exit_remove; | 3804 | goto exit_remove; |
| 3559 | } | 3805 | } |
| 3806 | if (data->REG_PWM[6]) { | ||
| 3807 | err = device_create_file(dev, | ||
| 3808 | &sda_weight_duty_base[i].dev_attr); | ||
| 3809 | if (err) | ||
| 3810 | goto exit_remove; | ||
| 3811 | } | ||
| 3560 | } | 3812 | } |
| 3561 | for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { | 3813 | for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { |
| 3562 | struct sensor_device_attribute_2 *attr = | 3814 | struct sensor_device_attribute_2 *attr = |
