aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/f71882fg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/f71882fg.c')
-rw-r--r--drivers/hwmon/f71882fg.c231
1 files changed, 121 insertions, 110 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 2d96ed2bf8ed..59dd881c71d8 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -605,7 +605,7 @@ static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
605 605
606/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the 606/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
607 standard models */ 607 standard models */
608static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = { 608static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
609 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, 609 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
610 show_pwm_auto_point_channel, 610 show_pwm_auto_point_channel,
611 store_pwm_auto_point_channel, 0, 0), 611 store_pwm_auto_point_channel, 0, 0),
@@ -627,7 +627,7 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
627 0, 0), 627 0, 0),
628 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, 628 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
629 show_pwm_auto_point_temp_hyst, NULL, 3, 0), 629 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
630 630}, {
631 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, 631 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
632 show_pwm_auto_point_channel, 632 show_pwm_auto_point_channel,
633 store_pwm_auto_point_channel, 0, 1), 633 store_pwm_auto_point_channel, 0, 1),
@@ -649,7 +649,7 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
649 0, 1), 649 0, 1),
650 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, 650 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
651 show_pwm_auto_point_temp_hyst, NULL, 3, 1), 651 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
652 652}, {
653 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, 653 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
654 show_pwm_auto_point_channel, 654 show_pwm_auto_point_channel,
655 store_pwm_auto_point_channel, 0, 2), 655 store_pwm_auto_point_channel, 0, 2),
@@ -671,12 +671,12 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
671 0, 2), 671 0, 2),
672 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, 672 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
673 show_pwm_auto_point_temp_hyst, NULL, 3, 2), 673 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
674}; 674} };
675 675
676/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the 676/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
677 pwm setting when the temperature is above the pwmX_auto_point1_temp can be 677 pwm setting when the temperature is above the pwmX_auto_point1_temp can be
678 programmed instead of being hardcoded to 0xff */ 678 programmed instead of being hardcoded to 0xff */
679static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = { 679static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {
680 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, 680 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
681 show_pwm_auto_point_channel, 681 show_pwm_auto_point_channel,
682 store_pwm_auto_point_channel, 0, 0), 682 store_pwm_auto_point_channel, 0, 0),
@@ -701,7 +701,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
701 0, 0), 701 0, 0),
702 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, 702 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
703 show_pwm_auto_point_temp_hyst, NULL, 3, 0), 703 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
704 704}, {
705 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, 705 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
706 show_pwm_auto_point_channel, 706 show_pwm_auto_point_channel,
707 store_pwm_auto_point_channel, 0, 1), 707 store_pwm_auto_point_channel, 0, 1),
@@ -726,7 +726,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
726 0, 1), 726 0, 1),
727 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, 727 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
728 show_pwm_auto_point_temp_hyst, NULL, 3, 1), 728 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
729 729}, {
730 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, 730 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
731 show_pwm_auto_point_channel, 731 show_pwm_auto_point_channel,
732 store_pwm_auto_point_channel, 0, 2), 732 store_pwm_auto_point_channel, 0, 2),
@@ -751,7 +751,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
751 0, 2), 751 0, 2),
752 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, 752 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
753 show_pwm_auto_point_temp_hyst, NULL, 3, 2), 753 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
754}; 754} };
755 755
756/* PWM attr for the standard models */ 756/* PWM attr for the standard models */
757static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { { 757static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
@@ -928,7 +928,7 @@ static struct sensor_device_attribute_2 f8000_fan_attr[] = {
928/* PWM attr for the f8000, zones mapped to temp instead of to pwm! 928/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
929 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the 929 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
930 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */ 930 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
931static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = { 931static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {
932 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, 932 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
933 show_pwm_auto_point_channel, 933 show_pwm_auto_point_channel,
934 store_pwm_auto_point_channel, 0, 0), 934 store_pwm_auto_point_channel, 0, 0),
@@ -969,7 +969,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
969 show_pwm_auto_point_temp_hyst, NULL, 2, 2), 969 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
970 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO, 970 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
971 show_pwm_auto_point_temp_hyst, NULL, 3, 2), 971 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
972 972}, {
973 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, 973 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
974 show_pwm_auto_point_channel, 974 show_pwm_auto_point_channel,
975 store_pwm_auto_point_channel, 0, 1), 975 store_pwm_auto_point_channel, 0, 1),
@@ -1010,7 +1010,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
1010 show_pwm_auto_point_temp_hyst, NULL, 2, 0), 1010 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
1011 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO, 1011 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
1012 show_pwm_auto_point_temp_hyst, NULL, 3, 0), 1012 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
1013 1013}, {
1014 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, 1014 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
1015 show_pwm_auto_point_channel, 1015 show_pwm_auto_point_channel,
1016 store_pwm_auto_point_channel, 0, 2), 1016 store_pwm_auto_point_channel, 0, 2),
@@ -1051,7 +1051,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
1051 show_pwm_auto_point_temp_hyst, NULL, 2, 1), 1051 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
1052 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO, 1052 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
1053 show_pwm_auto_point_temp_hyst, NULL, 3, 1), 1053 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
1054}; 1054} };
1055 1055
1056/* Super I/O functions */ 1056/* Super I/O functions */
1057static inline int superio_inb(int base, int reg) 1057static inline int superio_inb(int base, int reg)
@@ -2154,6 +2154,104 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2154 device_remove_file(&pdev->dev, &attr[i].dev_attr); 2154 device_remove_file(&pdev->dev, &attr[i].dev_attr);
2155} 2155}
2156 2156
2157static int __devinit f71882fg_create_fan_sysfs_files(
2158 struct platform_device *pdev, int idx)
2159{
2160 struct f71882fg_data *data = platform_get_drvdata(pdev);
2161 int err;
2162
2163 /* Sanity check the pwm setting */
2164 err = 0;
2165 switch (data->type) {
2166 case f71858fg:
2167 if (((data->pwm_enable >> (idx * 2)) & 3) == 3)
2168 err = 1;
2169 break;
2170 case f71862fg:
2171 if (((data->pwm_enable >> (idx * 2)) & 1) != 1)
2172 err = 1;
2173 break;
2174 case f8000:
2175 if (idx == 2)
2176 err = data->pwm_enable & 0x20;
2177 break;
2178 default:
2179 break;
2180 }
2181 if (err) {
2182 dev_err(&pdev->dev,
2183 "Invalid (reserved) pwm settings: 0x%02x, "
2184 "skipping fan %d\n",
2185 (data->pwm_enable >> (idx * 2)) & 3, idx + 1);
2186 return 0; /* This is a non fatal condition */
2187 }
2188
2189 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],
2190 ARRAY_SIZE(fxxxx_fan_attr[0]));
2191 if (err)
2192 return err;
2193
2194 if (f71882fg_fan_has_beep[data->type]) {
2195 err = f71882fg_create_sysfs_files(pdev,
2196 &fxxxx_fan_beep_attr[idx],
2197 1);
2198 if (err)
2199 return err;
2200 }
2201
2202 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,
2203 (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");
2204
2205 /* Check for unsupported auto pwm settings */
2206 switch (data->type) {
2207 case f71808e:
2208 case f71808a:
2209 case f71869:
2210 case f71869a:
2211 case f71889fg:
2212 case f71889ed:
2213 case f71889a:
2214 data->pwm_auto_point_mapping[idx] =
2215 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));
2216 if ((data->pwm_auto_point_mapping[idx] & 0x80) ||
2217 (data->pwm_auto_point_mapping[idx] & 3) == 0) {
2218 dev_warn(&pdev->dev,
2219 "Auto pwm controlled by raw digital "
2220 "data, disabling pwm auto_point "
2221 "sysfs attributes for fan %d\n", idx + 1);
2222 return 0; /* This is a non fatal condition */
2223 }
2224 break;
2225 default:
2226 break;
2227 }
2228
2229 switch (data->type) {
2230 case f71862fg:
2231 err = f71882fg_create_sysfs_files(pdev,
2232 &f71862fg_auto_pwm_attr[idx][0],
2233 ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));
2234 break;
2235 case f71808e:
2236 case f71869:
2237 err = f71882fg_create_sysfs_files(pdev,
2238 &f71869_auto_pwm_attr[idx][0],
2239 ARRAY_SIZE(f71869_auto_pwm_attr[0]));
2240 break;
2241 case f8000:
2242 err = f71882fg_create_sysfs_files(pdev,
2243 &f8000_auto_pwm_attr[idx][0],
2244 ARRAY_SIZE(f8000_auto_pwm_attr[0]));
2245 break;
2246 default:
2247 err = f71882fg_create_sysfs_files(pdev,
2248 &fxxxx_auto_pwm_attr[idx][0],
2249 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));
2250 }
2251
2252 return err;
2253}
2254
2157static int __devinit f71882fg_probe(struct platform_device *pdev) 2255static int __devinit f71882fg_probe(struct platform_device *pdev)
2158{ 2256{
2159 struct f71882fg_data *data; 2257 struct f71882fg_data *data;
@@ -2272,117 +2370,29 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
2272 data->pwm_enable = 2370 data->pwm_enable =
2273 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); 2371 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2274 2372
2275 /* Sanity check the pwm settings */ 2373 for (i = 0; i < nr_fans; i++) {
2276 switch (data->type) { 2374 err = f71882fg_create_fan_sysfs_files(pdev, i);
2277 case f71858fg:
2278 err = 0;
2279 for (i = 0; i < nr_fans; i++)
2280 if (((data->pwm_enable >> (i * 2)) & 3) == 3)
2281 err = 1;
2282 break;
2283 case f71862fg:
2284 err = (data->pwm_enable & 0x15) != 0x15;
2285 break;
2286 case f8000:
2287 err = data->pwm_enable & 0x20;
2288 break;
2289 default:
2290 err = 0;
2291 break;
2292 }
2293 if (err) {
2294 dev_err(&pdev->dev,
2295 "Invalid (reserved) pwm settings: 0x%02x\n",
2296 (unsigned int)data->pwm_enable);
2297 err = -ENODEV;
2298 goto exit_unregister_sysfs;
2299 }
2300
2301 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2302 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
2303 if (err)
2304 goto exit_unregister_sysfs;
2305
2306 if (f71882fg_fan_has_beep[data->type]) {
2307 err = f71882fg_create_sysfs_files(pdev,
2308 fxxxx_fan_beep_attr, nr_fans);
2309 if (err) 2375 if (err)
2310 goto exit_unregister_sysfs; 2376 goto exit_unregister_sysfs;
2311 } 2377 }
2312 2378
2313 switch (data->type) { 2379 /* Some types have 1 extra fan with limited functionality */
2314 case f71808e:
2315 case f71808a:
2316 case f71869:
2317 case f71869a:
2318 case f71889fg:
2319 case f71889ed:
2320 case f71889a:
2321 for (i = 0; i < nr_fans; i++) {
2322 data->pwm_auto_point_mapping[i] =
2323 f71882fg_read8(data,
2324 F71882FG_REG_POINT_MAPPING(i));
2325 if ((data->pwm_auto_point_mapping[i] & 0x80) ||
2326 (data->pwm_auto_point_mapping[i] & 3) == 0)
2327 break;
2328 }
2329 if (i != nr_fans) {
2330 dev_warn(&pdev->dev,
2331 "Auto pwm controlled by raw digital "
2332 "data, disabling pwm auto_point "
2333 "sysfs attributes\n");
2334 goto no_pwm_auto_point;
2335 }
2336 break;
2337 default:
2338 break;
2339 }
2340
2341 switch (data->type) { 2380 switch (data->type) {
2342 case f71808a: 2381 case f71808a:
2343 err = f71882fg_create_sysfs_files(pdev, 2382 err = f71882fg_create_sysfs_files(pdev,
2344 &fxxxx_auto_pwm_attr[0][0],
2345 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2346 if (err)
2347 goto exit_unregister_sysfs;
2348 err = f71882fg_create_sysfs_files(pdev,
2349 f71808a_fan3_attr, 2383 f71808a_fan3_attr,
2350 ARRAY_SIZE(f71808a_fan3_attr)); 2384 ARRAY_SIZE(f71808a_fan3_attr));
2351 break; 2385 break;
2352 case f71862fg:
2353 err = f71882fg_create_sysfs_files(pdev,
2354 f71862fg_auto_pwm_attr,
2355 ARRAY_SIZE(f71862fg_auto_pwm_attr));
2356 break;
2357 case f71808e:
2358 case f71869:
2359 err = f71882fg_create_sysfs_files(pdev,
2360 f71869_auto_pwm_attr,
2361 ARRAY_SIZE(f71869_auto_pwm_attr));
2362 break;
2363 case f8000: 2386 case f8000:
2364 err = f71882fg_create_sysfs_files(pdev, 2387 err = f71882fg_create_sysfs_files(pdev,
2365 f8000_fan_attr, 2388 f8000_fan_attr,
2366 ARRAY_SIZE(f8000_fan_attr)); 2389 ARRAY_SIZE(f8000_fan_attr));
2367 if (err)
2368 goto exit_unregister_sysfs;
2369 err = f71882fg_create_sysfs_files(pdev,
2370 f8000_auto_pwm_attr,
2371 ARRAY_SIZE(f8000_auto_pwm_attr));
2372 break; 2390 break;
2373 default: 2391 default:
2374 err = f71882fg_create_sysfs_files(pdev, 2392 break;
2375 &fxxxx_auto_pwm_attr[0][0],
2376 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2377 } 2393 }
2378 if (err) 2394 if (err)
2379 goto exit_unregister_sysfs; 2395 goto exit_unregister_sysfs;
2380
2381no_pwm_auto_point:
2382 for (i = 0; i < nr_fans; i++)
2383 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
2384 (data->pwm_enable & (1 << 2 * i)) ?
2385 "duty-cycle" : "RPM");
2386 } 2396 }
2387 2397
2388 data->hwmon_dev = hwmon_device_register(&pdev->dev); 2398 data->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -2476,22 +2486,23 @@ static int f71882fg_remove(struct platform_device *pdev)
2476 break; 2486 break;
2477 case f71862fg: 2487 case f71862fg:
2478 f71882fg_remove_sysfs_files(pdev, 2488 f71882fg_remove_sysfs_files(pdev,
2479 f71862fg_auto_pwm_attr, 2489 &f71862fg_auto_pwm_attr[0][0],
2480 ARRAY_SIZE(f71862fg_auto_pwm_attr)); 2490 ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *
2491 nr_fans);
2481 break; 2492 break;
2482 case f71808e: 2493 case f71808e:
2483 case f71869: 2494 case f71869:
2484 f71882fg_remove_sysfs_files(pdev, 2495 f71882fg_remove_sysfs_files(pdev,
2485 f71869_auto_pwm_attr, 2496 &f71869_auto_pwm_attr[0][0],
2486 ARRAY_SIZE(f71869_auto_pwm_attr)); 2497 ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);
2487 break; 2498 break;
2488 case f8000: 2499 case f8000:
2489 f71882fg_remove_sysfs_files(pdev, 2500 f71882fg_remove_sysfs_files(pdev,
2490 f8000_fan_attr, 2501 f8000_fan_attr,
2491 ARRAY_SIZE(f8000_fan_attr)); 2502 ARRAY_SIZE(f8000_fan_attr));
2492 f71882fg_remove_sysfs_files(pdev, 2503 f71882fg_remove_sysfs_files(pdev,
2493 f8000_auto_pwm_attr, 2504 &f8000_auto_pwm_attr[0][0],
2494 ARRAY_SIZE(f8000_auto_pwm_attr)); 2505 ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);
2495 break; 2506 break;
2496 default: 2507 default:
2497 f71882fg_remove_sysfs_files(pdev, 2508 f71882fg_remove_sysfs_files(pdev,