diff options
Diffstat (limited to 'drivers/hwmon/smsc47m1.c')
-rw-r--r-- | drivers/hwmon/smsc47m1.c | 198 |
1 files changed, 95 insertions, 103 deletions
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 7c16c1c80ef1..1e21c8cc948f 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/hwmon-sysfs.h> | ||
35 | #include <linux/err.h> | 36 | #include <linux/err.h> |
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
@@ -157,11 +158,12 @@ static struct platform_driver smsc47m1_driver = { | |||
157 | .remove = __devexit_p(smsc47m1_remove), | 158 | .remove = __devexit_p(smsc47m1_remove), |
158 | }; | 159 | }; |
159 | 160 | ||
160 | /* nr is 0 or 1 in the callback functions below */ | 161 | static ssize_t get_fan(struct device *dev, struct device_attribute |
161 | 162 | *devattr, char *buf) | |
162 | static ssize_t get_fan(struct device *dev, char *buf, int nr) | ||
163 | { | 163 | { |
164 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
164 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 165 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
166 | int nr = attr->index; | ||
165 | /* This chip (stupidly) stops monitoring fan speed if PWM is | 167 | /* This chip (stupidly) stops monitoring fan speed if PWM is |
166 | enabled and duty cycle is 0%. This is fine if the monitoring | 168 | enabled and duty cycle is 0%. This is fine if the monitoring |
167 | and control concern the same fan, but troublesome if they are | 169 | and control concern the same fan, but troublesome if they are |
@@ -173,42 +175,54 @@ static ssize_t get_fan(struct device *dev, char *buf, int nr) | |||
173 | return sprintf(buf, "%d\n", rpm); | 175 | return sprintf(buf, "%d\n", rpm); |
174 | } | 176 | } |
175 | 177 | ||
176 | static ssize_t get_fan_min(struct device *dev, char *buf, int nr) | 178 | static ssize_t get_fan_min(struct device *dev, struct device_attribute |
179 | *devattr, char *buf) | ||
177 | { | 180 | { |
181 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
178 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 182 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
183 | int nr = attr->index; | ||
179 | int rpm = MIN_FROM_REG(data->fan_preload[nr], | 184 | int rpm = MIN_FROM_REG(data->fan_preload[nr], |
180 | DIV_FROM_REG(data->fan_div[nr])); | 185 | DIV_FROM_REG(data->fan_div[nr])); |
181 | return sprintf(buf, "%d\n", rpm); | 186 | return sprintf(buf, "%d\n", rpm); |
182 | } | 187 | } |
183 | 188 | ||
184 | static ssize_t get_fan_div(struct device *dev, char *buf, int nr) | 189 | static ssize_t get_fan_div(struct device *dev, struct device_attribute |
190 | *devattr, char *buf) | ||
185 | { | 191 | { |
192 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
186 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 193 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
187 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 194 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
188 | } | 195 | } |
189 | 196 | ||
190 | static ssize_t get_pwm(struct device *dev, char *buf, int nr) | 197 | static ssize_t get_pwm(struct device *dev, struct device_attribute |
198 | *devattr, char *buf) | ||
191 | { | 199 | { |
200 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
192 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 201 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
193 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); | 202 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index])); |
194 | } | 203 | } |
195 | 204 | ||
196 | static ssize_t get_pwm_en(struct device *dev, char *buf, int nr) | 205 | static ssize_t get_pwm_en(struct device *dev, struct device_attribute |
206 | *devattr, char *buf) | ||
197 | { | 207 | { |
208 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
198 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 209 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
199 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr])); | 210 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index])); |
200 | } | 211 | } |
201 | 212 | ||
202 | static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 213 | static ssize_t get_alarms(struct device *dev, struct device_attribute |
214 | *devattr, char *buf) | ||
203 | { | 215 | { |
204 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 216 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
205 | return sprintf(buf, "%d\n", data->alarms); | 217 | return sprintf(buf, "%d\n", data->alarms); |
206 | } | 218 | } |
207 | 219 | ||
208 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 220 | static ssize_t set_fan_min(struct device *dev, struct device_attribute |
209 | size_t count, int nr) | 221 | *devattr, const char *buf, size_t count) |
210 | { | 222 | { |
223 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
211 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 224 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
225 | int nr = attr->index; | ||
212 | long rpmdiv, val = simple_strtol(buf, NULL, 10); | 226 | long rpmdiv, val = simple_strtol(buf, NULL, 10); |
213 | 227 | ||
214 | mutex_lock(&data->update_lock); | 228 | mutex_lock(&data->update_lock); |
@@ -231,11 +245,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, | |||
231 | determined in part by the fan clock divider. This follows the principle | 245 | determined in part by the fan clock divider. This follows the principle |
232 | of least surprise; the user doesn't expect the fan minimum to change just | 246 | of least surprise; the user doesn't expect the fan minimum to change just |
233 | because the divider changed. */ | 247 | because the divider changed. */ |
234 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 248 | static ssize_t set_fan_div(struct device *dev, struct device_attribute |
235 | size_t count, int nr) | 249 | *devattr, const char *buf, size_t count) |
236 | { | 250 | { |
251 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
237 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 252 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
238 | 253 | int nr = attr->index; | |
239 | long new_div = simple_strtol(buf, NULL, 10), tmp; | 254 | long new_div = simple_strtol(buf, NULL, 10), tmp; |
240 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); | 255 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); |
241 | 256 | ||
@@ -279,11 +294,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
279 | return count; | 294 | return count; |
280 | } | 295 | } |
281 | 296 | ||
282 | static ssize_t set_pwm(struct device *dev, const char *buf, | 297 | static ssize_t set_pwm(struct device *dev, struct device_attribute |
283 | size_t count, int nr) | 298 | *devattr, const char *buf, size_t count) |
284 | { | 299 | { |
300 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
285 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 301 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
286 | 302 | int nr = attr->index; | |
287 | long val = simple_strtol(buf, NULL, 10); | 303 | long val = simple_strtol(buf, NULL, 10); |
288 | 304 | ||
289 | if (val < 0 || val > 255) | 305 | if (val < 0 || val > 255) |
@@ -299,11 +315,12 @@ static ssize_t set_pwm(struct device *dev, const char *buf, | |||
299 | return count; | 315 | return count; |
300 | } | 316 | } |
301 | 317 | ||
302 | static ssize_t set_pwm_en(struct device *dev, const char *buf, | 318 | static ssize_t set_pwm_en(struct device *dev, struct device_attribute |
303 | size_t count, int nr) | 319 | *devattr, const char *buf, size_t count) |
304 | { | 320 | { |
321 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
305 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 322 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
306 | 323 | int nr = attr->index; | |
307 | long val = simple_strtol(buf, NULL, 10); | 324 | long val = simple_strtol(buf, NULL, 10); |
308 | 325 | ||
309 | if (val != 0 && val != 1) | 326 | if (val != 0 && val != 1) |
@@ -320,56 +337,16 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, | |||
320 | } | 337 | } |
321 | 338 | ||
322 | #define fan_present(offset) \ | 339 | #define fan_present(offset) \ |
323 | static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 340 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \ |
324 | { \ | 341 | NULL, offset - 1); \ |
325 | return get_fan(dev, buf, offset - 1); \ | 342 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
326 | } \ | 343 | get_fan_min, set_fan_min, offset - 1); \ |
327 | static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | 344 | static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ |
328 | { \ | 345 | get_fan_div, set_fan_div, offset - 1); \ |
329 | return get_fan_min(dev, buf, offset - 1); \ | 346 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
330 | } \ | 347 | get_pwm, set_pwm, offset - 1); \ |
331 | static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr, \ | 348 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
332 | const char *buf, size_t count) \ | 349 | get_pwm_en, set_pwm_en, offset - 1) |
333 | { \ | ||
334 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
335 | } \ | ||
336 | static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
337 | { \ | ||
338 | return get_fan_div(dev, buf, offset - 1); \ | ||
339 | } \ | ||
340 | static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr, \ | ||
341 | const char *buf, size_t count) \ | ||
342 | { \ | ||
343 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
344 | } \ | ||
345 | static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
346 | { \ | ||
347 | return get_pwm(dev, buf, offset - 1); \ | ||
348 | } \ | ||
349 | static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr, \ | ||
350 | const char *buf, size_t count) \ | ||
351 | { \ | ||
352 | return set_pwm(dev, buf, count, offset - 1); \ | ||
353 | } \ | ||
354 | static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
355 | { \ | ||
356 | return get_pwm_en(dev, buf, offset - 1); \ | ||
357 | } \ | ||
358 | static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr, \ | ||
359 | const char *buf, size_t count) \ | ||
360 | { \ | ||
361 | return set_pwm_en(dev, buf, count, offset - 1); \ | ||
362 | } \ | ||
363 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset, \ | ||
364 | NULL); \ | ||
365 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
366 | get_fan##offset##_min, set_fan##offset##_min); \ | ||
367 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
368 | get_fan##offset##_div, set_fan##offset##_div); \ | ||
369 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
370 | get_pwm##offset, set_pwm##offset); \ | ||
371 | static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | ||
372 | get_pwm##offset##_en, set_pwm##offset##_en); | ||
373 | 350 | ||
374 | fan_present(1); | 351 | fan_present(1); |
375 | fan_present(2); | 352 | fan_present(2); |
@@ -390,22 +367,22 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |||
390 | setup so we create them individually. It is still convenient to define a | 367 | setup so we create them individually. It is still convenient to define a |
391 | group to remove them all at once. */ | 368 | group to remove them all at once. */ |
392 | static struct attribute *smsc47m1_attributes[] = { | 369 | static struct attribute *smsc47m1_attributes[] = { |
393 | &dev_attr_fan1_input.attr, | 370 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
394 | &dev_attr_fan1_min.attr, | 371 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
395 | &dev_attr_fan1_div.attr, | 372 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
396 | &dev_attr_fan2_input.attr, | 373 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
397 | &dev_attr_fan2_min.attr, | 374 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
398 | &dev_attr_fan2_div.attr, | 375 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
399 | &dev_attr_fan3_input.attr, | 376 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
400 | &dev_attr_fan3_min.attr, | 377 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
401 | &dev_attr_fan3_div.attr, | 378 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
402 | 379 | ||
403 | &dev_attr_pwm1.attr, | 380 | &sensor_dev_attr_pwm1.dev_attr.attr, |
404 | &dev_attr_pwm1_enable.attr, | 381 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
405 | &dev_attr_pwm2.attr, | 382 | &sensor_dev_attr_pwm2.dev_attr.attr, |
406 | &dev_attr_pwm2_enable.attr, | 383 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, |
407 | &dev_attr_pwm3.attr, | 384 | &sensor_dev_attr_pwm3.dev_attr.attr, |
408 | &dev_attr_pwm3_enable.attr, | 385 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, |
409 | 386 | ||
410 | &dev_attr_alarms.attr, | 387 | &dev_attr_alarms.attr, |
411 | &dev_attr_name.attr, | 388 | &dev_attr_name.attr, |
@@ -547,46 +524,61 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) | |||
547 | 524 | ||
548 | /* Register sysfs hooks */ | 525 | /* Register sysfs hooks */ |
549 | if (fan1) { | 526 | if (fan1) { |
550 | if ((err = device_create_file(dev, &dev_attr_fan1_input)) | 527 | if ((err = device_create_file(dev, |
551 | || (err = device_create_file(dev, &dev_attr_fan1_min)) | 528 | &sensor_dev_attr_fan1_input.dev_attr)) |
552 | || (err = device_create_file(dev, &dev_attr_fan1_div))) | 529 | || (err = device_create_file(dev, |
530 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
531 | || (err = device_create_file(dev, | ||
532 | &sensor_dev_attr_fan1_div.dev_attr))) | ||
553 | goto error_remove_files; | 533 | goto error_remove_files; |
554 | } else | 534 | } else |
555 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); | 535 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); |
556 | 536 | ||
557 | if (fan2) { | 537 | if (fan2) { |
558 | if ((err = device_create_file(dev, &dev_attr_fan2_input)) | 538 | if ((err = device_create_file(dev, |
559 | || (err = device_create_file(dev, &dev_attr_fan2_min)) | 539 | &sensor_dev_attr_fan2_input.dev_attr)) |
560 | || (err = device_create_file(dev, &dev_attr_fan2_div))) | 540 | || (err = device_create_file(dev, |
541 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
542 | || (err = device_create_file(dev, | ||
543 | &sensor_dev_attr_fan2_div.dev_attr))) | ||
561 | goto error_remove_files; | 544 | goto error_remove_files; |
562 | } else | 545 | } else |
563 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); | 546 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); |
564 | 547 | ||
565 | if (fan3) { | 548 | if (fan3) { |
566 | if ((err = device_create_file(dev, &dev_attr_fan3_input)) | 549 | if ((err = device_create_file(dev, |
567 | || (err = device_create_file(dev, &dev_attr_fan3_min)) | 550 | &sensor_dev_attr_fan3_input.dev_attr)) |
568 | || (err = device_create_file(dev, &dev_attr_fan3_div))) | 551 | || (err = device_create_file(dev, |
552 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
553 | || (err = device_create_file(dev, | ||
554 | &sensor_dev_attr_fan3_div.dev_attr))) | ||
569 | goto error_remove_files; | 555 | goto error_remove_files; |
570 | } else | 556 | } else |
571 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); | 557 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); |
572 | 558 | ||
573 | if (pwm1) { | 559 | if (pwm1) { |
574 | if ((err = device_create_file(dev, &dev_attr_pwm1)) | 560 | if ((err = device_create_file(dev, |
575 | || (err = device_create_file(dev, &dev_attr_pwm1_enable))) | 561 | &sensor_dev_attr_pwm1.dev_attr)) |
562 | || (err = device_create_file(dev, | ||
563 | &sensor_dev_attr_pwm1_enable.dev_attr))) | ||
576 | goto error_remove_files; | 564 | goto error_remove_files; |
577 | } else | 565 | } else |
578 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); | 566 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); |
579 | 567 | ||
580 | if (pwm2) { | 568 | if (pwm2) { |
581 | if ((err = device_create_file(dev, &dev_attr_pwm2)) | 569 | if ((err = device_create_file(dev, |
582 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) | 570 | &sensor_dev_attr_pwm2.dev_attr)) |
571 | || (err = device_create_file(dev, | ||
572 | &sensor_dev_attr_pwm2_enable.dev_attr))) | ||
583 | goto error_remove_files; | 573 | goto error_remove_files; |
584 | } else | 574 | } else |
585 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); | 575 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); |
586 | 576 | ||
587 | if (pwm3) { | 577 | if (pwm3) { |
588 | if ((err = device_create_file(dev, &dev_attr_pwm3)) | 578 | if ((err = device_create_file(dev, |
589 | || (err = device_create_file(dev, &dev_attr_pwm3_enable))) | 579 | &sensor_dev_attr_pwm3.dev_attr)) |
580 | || (err = device_create_file(dev, | ||
581 | &sensor_dev_attr_pwm3_enable.dev_attr))) | ||
590 | goto error_remove_files; | 582 | goto error_remove_files; |
591 | } else | 583 | } else |
592 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); | 584 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); |