diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/hwmon/max6650.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/hwmon/max6650.c')
-rw-r--r-- | drivers/hwmon/max6650.c | 187 |
1 files changed, 91 insertions, 96 deletions
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index f739f83bafb..ece3aafa54b 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c | |||
@@ -135,7 +135,8 @@ static struct i2c_driver max6650_driver = { | |||
135 | * Client data (each client gets its own) | 135 | * Client data (each client gets its own) |
136 | */ | 136 | */ |
137 | 137 | ||
138 | struct max6650_data { | 138 | struct max6650_data |
139 | { | ||
139 | struct device *hwmon_dev; | 140 | struct device *hwmon_dev; |
140 | struct mutex update_lock; | 141 | struct mutex update_lock; |
141 | int nr_fans; | 142 | int nr_fans; |
@@ -159,13 +160,13 @@ static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, | |||
159 | int rpm; | 160 | int rpm; |
160 | 161 | ||
161 | /* | 162 | /* |
162 | * Calculation details: | 163 | * Calculation details: |
163 | * | 164 | * |
164 | * Each tachometer counts over an interval given by the "count" | 165 | * Each tachometer counts over an interval given by the "count" |
165 | * register (0.25, 0.5, 1 or 2 seconds). This module assumes | 166 | * register (0.25, 0.5, 1 or 2 seconds). This module assumes |
166 | * that the fans produce two pulses per revolution (this seems | 167 | * that the fans produce two pulses per revolution (this seems |
167 | * to be the most common). | 168 | * to be the most common). |
168 | */ | 169 | */ |
169 | 170 | ||
170 | rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); | 171 | rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); |
171 | return sprintf(buf, "%d\n", rpm); | 172 | return sprintf(buf, "%d\n", rpm); |
@@ -219,12 +220,12 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr, | |||
219 | int kscale, ktach, rpm; | 220 | int kscale, ktach, rpm; |
220 | 221 | ||
221 | /* | 222 | /* |
222 | * Use the datasheet equation: | 223 | * Use the datasheet equation: |
223 | * | 224 | * |
224 | * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] | 225 | * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] |
225 | * | 226 | * |
226 | * then multiply by 60 to give rpm. | 227 | * then multiply by 60 to give rpm. |
227 | */ | 228 | */ |
228 | 229 | ||
229 | kscale = DIV_FROM_REG(data->config); | 230 | kscale = DIV_FROM_REG(data->config); |
230 | ktach = data->speed; | 231 | ktach = data->speed; |
@@ -237,22 +238,17 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr, | |||
237 | { | 238 | { |
238 | struct i2c_client *client = to_i2c_client(dev); | 239 | struct i2c_client *client = to_i2c_client(dev); |
239 | struct max6650_data *data = i2c_get_clientdata(client); | 240 | struct max6650_data *data = i2c_get_clientdata(client); |
241 | int rpm = simple_strtoul(buf, NULL, 10); | ||
240 | int kscale, ktach; | 242 | int kscale, ktach; |
241 | unsigned long rpm; | ||
242 | int err; | ||
243 | |||
244 | err = kstrtoul(buf, 10, &rpm); | ||
245 | if (err) | ||
246 | return err; | ||
247 | 243 | ||
248 | rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); | 244 | rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); |
249 | 245 | ||
250 | /* | 246 | /* |
251 | * Divide the required speed by 60 to get from rpm to rps, then | 247 | * Divide the required speed by 60 to get from rpm to rps, then |
252 | * use the datasheet equation: | 248 | * use the datasheet equation: |
253 | * | 249 | * |
254 | * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 | 250 | * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 |
255 | */ | 251 | */ |
256 | 252 | ||
257 | mutex_lock(&data->update_lock); | 253 | mutex_lock(&data->update_lock); |
258 | 254 | ||
@@ -286,10 +282,8 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, | |||
286 | int pwm; | 282 | int pwm; |
287 | struct max6650_data *data = max6650_update_device(dev); | 283 | struct max6650_data *data = max6650_update_device(dev); |
288 | 284 | ||
289 | /* | 285 | /* Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. |
290 | * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. | 286 | Lower DAC values mean higher speeds. */ |
291 | * Lower DAC values mean higher speeds. | ||
292 | */ | ||
293 | if (data->config & MAX6650_CFG_V12) | 287 | if (data->config & MAX6650_CFG_V12) |
294 | pwm = 255 - (255 * (int)data->dac)/180; | 288 | pwm = 255 - (255 * (int)data->dac)/180; |
295 | else | 289 | else |
@@ -306,12 +300,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
306 | { | 300 | { |
307 | struct i2c_client *client = to_i2c_client(dev); | 301 | struct i2c_client *client = to_i2c_client(dev); |
308 | struct max6650_data *data = i2c_get_clientdata(client); | 302 | struct max6650_data *data = i2c_get_clientdata(client); |
309 | unsigned long pwm; | 303 | int pwm = simple_strtoul(buf, NULL, 10); |
310 | int err; | ||
311 | |||
312 | err = kstrtoul(buf, 10, &pwm); | ||
313 | if (err) | ||
314 | return err; | ||
315 | 304 | ||
316 | pwm = SENSORS_LIMIT(pwm, 0, 255); | 305 | pwm = SENSORS_LIMIT(pwm, 0, 255); |
317 | 306 | ||
@@ -352,16 +341,14 @@ static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, | |||
352 | { | 341 | { |
353 | struct i2c_client *client = to_i2c_client(dev); | 342 | struct i2c_client *client = to_i2c_client(dev); |
354 | struct max6650_data *data = i2c_get_clientdata(client); | 343 | struct max6650_data *data = i2c_get_clientdata(client); |
344 | int mode = simple_strtoul(buf, NULL, 10); | ||
355 | int max6650_modes[3] = {0, 3, 2}; | 345 | int max6650_modes[3] = {0, 3, 2}; |
356 | unsigned long mode; | ||
357 | int err; | ||
358 | |||
359 | err = kstrtoul(buf, 10, &mode); | ||
360 | if (err) | ||
361 | return err; | ||
362 | 346 | ||
363 | if (mode > 2) | 347 | if ((mode < 0)||(mode > 2)) { |
348 | dev_err(&client->dev, | ||
349 | "illegal value for pwm1_enable (%d)\n", mode); | ||
364 | return -EINVAL; | 350 | return -EINVAL; |
351 | } | ||
365 | 352 | ||
366 | mutex_lock(&data->update_lock); | 353 | mutex_lock(&data->update_lock); |
367 | 354 | ||
@@ -402,12 +389,7 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr, | |||
402 | { | 389 | { |
403 | struct i2c_client *client = to_i2c_client(dev); | 390 | struct i2c_client *client = to_i2c_client(dev); |
404 | struct max6650_data *data = i2c_get_clientdata(client); | 391 | struct max6650_data *data = i2c_get_clientdata(client); |
405 | unsigned long div; | 392 | int div = simple_strtoul(buf, NULL, 10); |
406 | int err; | ||
407 | |||
408 | err = kstrtoul(buf, 10, &div); | ||
409 | if (err) | ||
410 | return err; | ||
411 | 393 | ||
412 | mutex_lock(&data->update_lock); | 394 | mutex_lock(&data->update_lock); |
413 | switch (div) { | 395 | switch (div) { |
@@ -425,6 +407,8 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr, | |||
425 | break; | 407 | break; |
426 | default: | 408 | default: |
427 | mutex_unlock(&data->update_lock); | 409 | mutex_unlock(&data->update_lock); |
410 | dev_err(&client->dev, | ||
411 | "illegal value for fan divider (%d)\n", div); | ||
428 | return -EINVAL; | 412 | return -EINVAL; |
429 | } | 413 | } |
430 | 414 | ||
@@ -480,7 +464,7 @@ static SENSOR_DEVICE_ATTR(gpio1_alarm, S_IRUGO, get_alarm, NULL, | |||
480 | static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL, | 464 | static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL, |
481 | MAX6650_ALRM_GPIO2); | 465 | MAX6650_ALRM_GPIO2); |
482 | 466 | ||
483 | static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, | 467 | static mode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, |
484 | int n) | 468 | int n) |
485 | { | 469 | { |
486 | struct device *dev = container_of(kobj, struct device, kobj); | 470 | struct device *dev = container_of(kobj, struct device, kobj); |
@@ -545,9 +529,7 @@ static int max6650_probe(struct i2c_client *client, | |||
545 | struct max6650_data *data; | 529 | struct max6650_data *data; |
546 | int err; | 530 | int err; |
547 | 531 | ||
548 | data = devm_kzalloc(&client->dev, sizeof(struct max6650_data), | 532 | if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { |
549 | GFP_KERNEL); | ||
550 | if (!data) { | ||
551 | dev_err(&client->dev, "out of memory.\n"); | 533 | dev_err(&client->dev, "out of memory.\n"); |
552 | return -ENOMEM; | 534 | return -ENOMEM; |
553 | } | 535 | } |
@@ -561,11 +543,11 @@ static int max6650_probe(struct i2c_client *client, | |||
561 | */ | 543 | */ |
562 | err = max6650_init_client(client); | 544 | err = max6650_init_client(client); |
563 | if (err) | 545 | if (err) |
564 | return err; | 546 | goto err_free; |
565 | 547 | ||
566 | err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); | 548 | err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); |
567 | if (err) | 549 | if (err) |
568 | return err; | 550 | goto err_free; |
569 | /* 3 additional fan inputs for the MAX6651 */ | 551 | /* 3 additional fan inputs for the MAX6651 */ |
570 | if (data->nr_fans == 4) { | 552 | if (data->nr_fans == 4) { |
571 | err = sysfs_create_group(&client->dev.kobj, &max6651_attr_grp); | 553 | err = sysfs_create_group(&client->dev.kobj, &max6651_attr_grp); |
@@ -583,6 +565,8 @@ static int max6650_probe(struct i2c_client *client, | |||
583 | sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); | 565 | sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); |
584 | err_remove: | 566 | err_remove: |
585 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | 567 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); |
568 | err_free: | ||
569 | kfree(data); | ||
586 | return err; | 570 | return err; |
587 | } | 571 | } |
588 | 572 | ||
@@ -594,6 +578,7 @@ static int max6650_remove(struct i2c_client *client) | |||
594 | if (data->nr_fans == 4) | 578 | if (data->nr_fans == 4) |
595 | sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); | 579 | sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); |
596 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | 580 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); |
581 | kfree(data); | ||
597 | return 0; | 582 | return 0; |
598 | } | 583 | } |
599 | 584 | ||
@@ -611,54 +596,55 @@ static int max6650_init_client(struct i2c_client *client) | |||
611 | } | 596 | } |
612 | 597 | ||
613 | switch (fan_voltage) { | 598 | switch (fan_voltage) { |
614 | case 0: | 599 | case 0: |
615 | break; | 600 | break; |
616 | case 5: | 601 | case 5: |
617 | config &= ~MAX6650_CFG_V12; | 602 | config &= ~MAX6650_CFG_V12; |
618 | break; | 603 | break; |
619 | case 12: | 604 | case 12: |
620 | config |= MAX6650_CFG_V12; | 605 | config |= MAX6650_CFG_V12; |
621 | break; | 606 | break; |
622 | default: | 607 | default: |
623 | dev_err(&client->dev, "illegal value for fan_voltage (%d)\n", | 608 | dev_err(&client->dev, |
624 | fan_voltage); | 609 | "illegal value for fan_voltage (%d)\n", |
610 | fan_voltage); | ||
625 | } | 611 | } |
626 | 612 | ||
627 | dev_info(&client->dev, "Fan voltage is set to %dV.\n", | 613 | dev_info(&client->dev, "Fan voltage is set to %dV.\n", |
628 | (config & MAX6650_CFG_V12) ? 12 : 5); | 614 | (config & MAX6650_CFG_V12) ? 12 : 5); |
629 | 615 | ||
630 | switch (prescaler) { | 616 | switch (prescaler) { |
631 | case 0: | 617 | case 0: |
632 | break; | 618 | break; |
633 | case 1: | 619 | case 1: |
634 | config &= ~MAX6650_CFG_PRESCALER_MASK; | 620 | config &= ~MAX6650_CFG_PRESCALER_MASK; |
635 | break; | 621 | break; |
636 | case 2: | 622 | case 2: |
637 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | 623 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) |
638 | | MAX6650_CFG_PRESCALER_2; | 624 | | MAX6650_CFG_PRESCALER_2; |
639 | break; | 625 | break; |
640 | case 4: | 626 | case 4: |
641 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | 627 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) |
642 | | MAX6650_CFG_PRESCALER_4; | 628 | | MAX6650_CFG_PRESCALER_4; |
643 | break; | 629 | break; |
644 | case 8: | 630 | case 8: |
645 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | 631 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) |
646 | | MAX6650_CFG_PRESCALER_8; | 632 | | MAX6650_CFG_PRESCALER_8; |
647 | break; | 633 | break; |
648 | case 16: | 634 | case 16: |
649 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | 635 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) |
650 | | MAX6650_CFG_PRESCALER_16; | 636 | | MAX6650_CFG_PRESCALER_16; |
651 | break; | 637 | break; |
652 | default: | 638 | default: |
653 | dev_err(&client->dev, "illegal value for prescaler (%d)\n", | 639 | dev_err(&client->dev, |
654 | prescaler); | 640 | "illegal value for prescaler (%d)\n", |
641 | prescaler); | ||
655 | } | 642 | } |
656 | 643 | ||
657 | dev_info(&client->dev, "Prescaler is set to %d.\n", | 644 | dev_info(&client->dev, "Prescaler is set to %d.\n", |
658 | 1 << (config & MAX6650_CFG_PRESCALER_MASK)); | 645 | 1 << (config & MAX6650_CFG_PRESCALER_MASK)); |
659 | 646 | ||
660 | /* | 647 | /* If mode is set to "full off", we change it to "open loop" and |
661 | * If mode is set to "full off", we change it to "open loop" and | ||
662 | * set DAC to 255, which has the same effect. We do this because | 648 | * set DAC to 255, which has the same effect. We do this because |
663 | * there's no "full off" mode defined in hwmon specifcations. | 649 | * there's no "full off" mode defined in hwmon specifcations. |
664 | */ | 650 | */ |
@@ -712,11 +698,9 @@ static struct max6650_data *max6650_update_device(struct device *dev) | |||
712 | MAX6650_REG_COUNT); | 698 | MAX6650_REG_COUNT); |
713 | data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); | 699 | data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); |
714 | 700 | ||
715 | /* | 701 | /* Alarms are cleared on read in case the condition that |
716 | * Alarms are cleared on read in case the condition that | ||
717 | * caused the alarm is removed. Keep the value latched here | 702 | * caused the alarm is removed. Keep the value latched here |
718 | * for providing the register through different alarm files. | 703 | * for providing the register through different alarm files. */ |
719 | */ | ||
720 | data->alarm |= i2c_smbus_read_byte_data(client, | 704 | data->alarm |= i2c_smbus_read_byte_data(client, |
721 | MAX6650_REG_ALARM); | 705 | MAX6650_REG_ALARM); |
722 | 706 | ||
@@ -729,8 +713,19 @@ static struct max6650_data *max6650_update_device(struct device *dev) | |||
729 | return data; | 713 | return data; |
730 | } | 714 | } |
731 | 715 | ||
732 | module_i2c_driver(max6650_driver); | 716 | static int __init sensors_max6650_init(void) |
717 | { | ||
718 | return i2c_add_driver(&max6650_driver); | ||
719 | } | ||
720 | |||
721 | static void __exit sensors_max6650_exit(void) | ||
722 | { | ||
723 | i2c_del_driver(&max6650_driver); | ||
724 | } | ||
733 | 725 | ||
734 | MODULE_AUTHOR("Hans J. Koch"); | 726 | MODULE_AUTHOR("Hans J. Koch"); |
735 | MODULE_DESCRIPTION("MAX6650 sensor driver"); | 727 | MODULE_DESCRIPTION("MAX6650 sensor driver"); |
736 | MODULE_LICENSE("GPL"); | 728 | MODULE_LICENSE("GPL"); |
729 | |||
730 | module_init(sensors_max6650_init); | ||
731 | module_exit(sensors_max6650_exit); | ||