aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/applesmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/applesmc.c')
-rw-r--r--drivers/hwmon/applesmc.c133
1 files changed, 67 insertions, 66 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 2cde9ecf7731..4d937a18fadb 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -54,7 +54,7 @@
54#define APPLESMC_MAX_DATA_LENGTH 32 54#define APPLESMC_MAX_DATA_LENGTH 32
55 55
56/* wait up to 32 ms for a status change. */ 56/* wait up to 32 ms for a status change. */
57#define APPLESMC_MIN_WAIT 0x0040 57#define APPLESMC_MIN_WAIT 0x0010
58#define APPLESMC_MAX_WAIT 0x8000 58#define APPLESMC_MAX_WAIT 0x8000
59 59
60#define APPLESMC_STATUS_MASK 0x0f 60#define APPLESMC_STATUS_MASK 0x0f
@@ -80,6 +80,8 @@
80#define FANS_MANUAL "FS! " /* r-w ui16 */ 80#define FANS_MANUAL "FS! " /* r-w ui16 */
81#define FAN_ID_FMT "F%dID" /* r-o char[16] */ 81#define FAN_ID_FMT "F%dID" /* r-o char[16] */
82 82
83#define TEMP_SENSOR_TYPE "sp78"
84
83/* List of keys used to read/write fan speeds */ 85/* List of keys used to read/write fan speeds */
84static const char *const fan_speed_fmt[] = { 86static const char *const fan_speed_fmt[] = {
85 "F%dAc", /* actual speed */ 87 "F%dAc", /* actual speed */
@@ -96,10 +98,6 @@ static const char *const fan_speed_fmt[] = {
96#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ 98#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
97#define APPLESMC_INPUT_FLAT 4 99#define APPLESMC_INPUT_FLAT 4
98 100
99#define SENSOR_X 0
100#define SENSOR_Y 1
101#define SENSOR_Z 2
102
103#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) 101#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
104#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) 102#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
105 103
@@ -135,11 +133,13 @@ static struct applesmc_registers {
135 unsigned int temp_count; /* number of temperature registers */ 133 unsigned int temp_count; /* number of temperature registers */
136 unsigned int temp_begin; /* temperature lower index bound */ 134 unsigned int temp_begin; /* temperature lower index bound */
137 unsigned int temp_end; /* temperature upper index bound */ 135 unsigned int temp_end; /* temperature upper index bound */
136 unsigned int index_count; /* size of temperature index array */
138 int num_light_sensors; /* number of light sensors */ 137 int num_light_sensors; /* number of light sensors */
139 bool has_accelerometer; /* has motion sensor */ 138 bool has_accelerometer; /* has motion sensor */
140 bool has_key_backlight; /* has keyboard backlight */ 139 bool has_key_backlight; /* has keyboard backlight */
141 bool init_complete; /* true when fully initialized */ 140 bool init_complete; /* true when fully initialized */
142 struct applesmc_entry *cache; /* cached key entries */ 141 struct applesmc_entry *cache; /* cached key entries */
142 const char **index; /* temperature key index */
143} smcreg = { 143} smcreg = {
144 .mutex = __MUTEX_INITIALIZER(smcreg.mutex), 144 .mutex = __MUTEX_INITIALIZER(smcreg.mutex),
145}; 145};
@@ -432,30 +432,19 @@ static int applesmc_has_key(const char *key, bool *value)
432} 432}
433 433
434/* 434/*
435 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). 435 * applesmc_read_s16 - Read 16-bit signed big endian register
436 */ 436 */
437static int applesmc_read_motion_sensor(int index, s16 *value) 437static int applesmc_read_s16(const char *key, s16 *value)
438{ 438{
439 u8 buffer[2]; 439 u8 buffer[2];
440 int ret; 440 int ret;
441 441
442 switch (index) { 442 ret = applesmc_read_key(key, buffer, 2);
443 case SENSOR_X: 443 if (ret)
444 ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2); 444 return ret;
445 break;
446 case SENSOR_Y:
447 ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
448 break;
449 case SENSOR_Z:
450 ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
451 break;
452 default:
453 ret = -EINVAL;
454 }
455 445
456 *value = ((s16)buffer[0] << 8) | buffer[1]; 446 *value = ((s16)buffer[0] << 8) | buffer[1];
457 447 return 0;
458 return ret;
459} 448}
460 449
461/* 450/*
@@ -482,6 +471,30 @@ static void applesmc_device_init(void)
482 pr_warn("failed to init the device\n"); 471 pr_warn("failed to init the device\n");
483} 472}
484 473
474static int applesmc_init_index(struct applesmc_registers *s)
475{
476 const struct applesmc_entry *entry;
477 unsigned int i;
478
479 if (s->index)
480 return 0;
481
482 s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL);
483 if (!s->index)
484 return -ENOMEM;
485
486 for (i = s->temp_begin; i < s->temp_end; i++) {
487 entry = applesmc_get_entry_by_index(i);
488 if (IS_ERR(entry))
489 continue;
490 if (strcmp(entry->type, TEMP_SENSOR_TYPE))
491 continue;
492 s->index[s->index_count++] = entry->key;
493 }
494
495 return 0;
496}
497
485/* 498/*
486 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. 499 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
487 */ 500 */
@@ -517,6 +530,10 @@ static int applesmc_init_smcreg_try(void)
517 return ret; 530 return ret;
518 s->temp_count = s->temp_end - s->temp_begin; 531 s->temp_count = s->temp_end - s->temp_begin;
519 532
533 ret = applesmc_init_index(s);
534 if (ret)
535 return ret;
536
520 ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); 537 ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
521 if (ret) 538 if (ret)
522 return ret; 539 return ret;
@@ -533,8 +550,8 @@ static int applesmc_init_smcreg_try(void)
533 s->num_light_sensors = left_light_sensor + right_light_sensor; 550 s->num_light_sensors = left_light_sensor + right_light_sensor;
534 s->init_complete = true; 551 s->init_complete = true;
535 552
536 pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", 553 pr_info("key=%d fan=%d temp=%d index=%d acc=%d lux=%d kbd=%d\n",
537 s->key_count, s->fan_count, s->temp_count, 554 s->key_count, s->fan_count, s->temp_count, s->index_count,
538 s->has_accelerometer, 555 s->has_accelerometer,
539 s->num_light_sensors, 556 s->num_light_sensors,
540 s->has_key_backlight); 557 s->has_key_backlight);
@@ -542,6 +559,15 @@ static int applesmc_init_smcreg_try(void)
542 return 0; 559 return 0;
543} 560}
544 561
562static void applesmc_destroy_smcreg(void)
563{
564 kfree(smcreg.index);
565 smcreg.index = NULL;
566 kfree(smcreg.cache);
567 smcreg.cache = NULL;
568 smcreg.init_complete = false;
569}
570
545/* 571/*
546 * applesmc_init_smcreg - Initialize register cache. 572 * applesmc_init_smcreg - Initialize register cache.
547 * 573 *
@@ -562,19 +588,11 @@ static int applesmc_init_smcreg(void)
562 msleep(INIT_WAIT_MSECS); 588 msleep(INIT_WAIT_MSECS);
563 } 589 }
564 590
565 kfree(smcreg.cache); 591 applesmc_destroy_smcreg();
566 smcreg.cache = NULL;
567 592
568 return ret; 593 return ret;
569} 594}
570 595
571static void applesmc_destroy_smcreg(void)
572{
573 kfree(smcreg.cache);
574 smcreg.cache = NULL;
575 smcreg.init_complete = false;
576}
577
578/* Device model stuff */ 596/* Device model stuff */
579static int applesmc_probe(struct platform_device *dev) 597static int applesmc_probe(struct platform_device *dev)
580{ 598{
@@ -624,8 +642,8 @@ static struct platform_driver applesmc_driver = {
624 */ 642 */
625static void applesmc_calibrate(void) 643static void applesmc_calibrate(void)
626{ 644{
627 applesmc_read_motion_sensor(SENSOR_X, &rest_x); 645 applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x);
628 applesmc_read_motion_sensor(SENSOR_Y, &rest_y); 646 applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y);
629 rest_x = -rest_x; 647 rest_x = -rest_x;
630} 648}
631 649
@@ -634,9 +652,9 @@ static void applesmc_idev_poll(struct input_polled_dev *dev)
634 struct input_dev *idev = dev->input; 652 struct input_dev *idev = dev->input;
635 s16 x, y; 653 s16 x, y;
636 654
637 if (applesmc_read_motion_sensor(SENSOR_X, &x)) 655 if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x))
638 return; 656 return;
639 if (applesmc_read_motion_sensor(SENSOR_Y, &y)) 657 if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y))
640 return; 658 return;
641 659
642 x = -x; 660 x = -x;
@@ -659,13 +677,13 @@ static ssize_t applesmc_position_show(struct device *dev,
659 int ret; 677 int ret;
660 s16 x, y, z; 678 s16 x, y, z;
661 679
662 ret = applesmc_read_motion_sensor(SENSOR_X, &x); 680 ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x);
663 if (ret) 681 if (ret)
664 goto out; 682 goto out;
665 ret = applesmc_read_motion_sensor(SENSOR_Y, &y); 683 ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y);
666 if (ret) 684 if (ret)
667 goto out; 685 goto out;
668 ret = applesmc_read_motion_sensor(SENSOR_Z, &z); 686 ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z);
669 if (ret) 687 if (ret)
670 goto out; 688 goto out;
671 689
@@ -718,44 +736,27 @@ out:
718static ssize_t applesmc_show_sensor_label(struct device *dev, 736static ssize_t applesmc_show_sensor_label(struct device *dev,
719 struct device_attribute *devattr, char *sysfsbuf) 737 struct device_attribute *devattr, char *sysfsbuf)
720{ 738{
721 int index = smcreg.temp_begin + to_index(devattr); 739 const char *key = smcreg.index[to_index(devattr)];
722 const struct applesmc_entry *entry;
723 740
724 entry = applesmc_get_entry_by_index(index); 741 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
725 if (IS_ERR(entry))
726 return PTR_ERR(entry);
727
728 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
729} 742}
730 743
731/* Displays degree Celsius * 1000 */ 744/* Displays degree Celsius * 1000 */
732static ssize_t applesmc_show_temperature(struct device *dev, 745static ssize_t applesmc_show_temperature(struct device *dev,
733 struct device_attribute *devattr, char *sysfsbuf) 746 struct device_attribute *devattr, char *sysfsbuf)
734{ 747{
735 int index = smcreg.temp_begin + to_index(devattr); 748 const char *key = smcreg.index[to_index(devattr)];
736 const struct applesmc_entry *entry;
737 int ret; 749 int ret;
738 u8 buffer[2]; 750 s16 value;
739 unsigned int temp; 751 int temp;
740
741 entry = applesmc_get_entry_by_index(index);
742 if (IS_ERR(entry))
743 return PTR_ERR(entry);
744 if (entry->len > 2)
745 return -EINVAL;
746 752
747 ret = applesmc_read_entry(entry, buffer, entry->len); 753 ret = applesmc_read_s16(key, &value);
748 if (ret) 754 if (ret)
749 return ret; 755 return ret;
750 756
751 if (entry->len == 2) { 757 temp = 250 * (value >> 6);
752 temp = buffer[0] * 1000;
753 temp += (buffer[1] >> 6) * 250;
754 } else {
755 temp = buffer[0] * 4000;
756 }
757 758
758 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); 759 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp);
759} 760}
760 761
761static ssize_t applesmc_show_fan_speed(struct device *dev, 762static ssize_t applesmc_show_fan_speed(struct device *dev,
@@ -1265,7 +1266,7 @@ static int __init applesmc_init(void)
1265 if (ret) 1266 if (ret)
1266 goto out_info; 1267 goto out_info;
1267 1268
1268 ret = applesmc_create_nodes(temp_group, smcreg.temp_count); 1269 ret = applesmc_create_nodes(temp_group, smcreg.index_count);
1269 if (ret) 1270 if (ret)
1270 goto out_fans; 1271 goto out_fans;
1271 1272