aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/applesmc.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-11-09 10:15:08 -0500
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-01-08 13:55:42 -0500
commit3eba2bf7c5fb7863412554cd73646cb80ac293ff (patch)
treecaca1638ca1a022adcc8e77d8a7e23ad805e14ee /drivers/hwmon/applesmc.c
parent40ef06f1120bcc0a2ad483b5cd42f58c4df78a5b (diff)
hwmon: (applesmc) Dynamic creation of fan files
With the dynamic temperature group in place, the setup of fans can be simplified. This patch sets up the fans dynamically, removing a hundred lines of code. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon/applesmc.c')
-rw-r--r--drivers/hwmon/applesmc.c188
1 files changed, 43 insertions, 145 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index d4d647522331..b0792361c52e 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -77,20 +77,15 @@
77 77
78#define FANS_COUNT "FNum" /* r-o ui8 */ 78#define FANS_COUNT "FNum" /* r-o ui8 */
79#define FANS_MANUAL "FS! " /* r-w ui16 */ 79#define FANS_MANUAL "FS! " /* r-w ui16 */
80#define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */ 80#define FAN_ID_FMT "F%dID" /* r-o char[16] */
81#define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 (2 bytes) */
82#define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 (2 bytes) */
83#define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 (2 bytes) */
84#define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 (2 bytes) */
85#define FAN_POSITION "F0ID" /* r-o char[16] */
86 81
87/* List of keys used to read/write fan speeds */ 82/* List of keys used to read/write fan speeds */
88static const char* fan_speed_keys[] = { 83static const char *const fan_speed_fmt[] = {
89 FAN_ACTUAL_SPEED, 84 "F%dAc", /* actual speed */
90 FAN_MIN_SPEED, 85 "F%dMn", /* minimum speed (rw) */
91 FAN_MAX_SPEED, 86 "F%dMx", /* maximum speed */
92 FAN_SAFE_SPEED, 87 "F%dSf", /* safe speed - not all models */
93 FAN_TARGET_SPEED 88 "F%dTg", /* target speed (manual: rw) */
94}; 89};
95 90
96#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ 91#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
@@ -104,7 +99,8 @@ static const char* fan_speed_keys[] = {
104#define SENSOR_Y 1 99#define SENSOR_Y 1
105#define SENSOR_Z 2 100#define SENSOR_Z 2
106 101
107#define to_index(attr) (to_sensor_dev_attr(attr)->index) 102#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
103#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
108 104
109/* Dynamic device node attributes */ 105/* Dynamic device node attributes */
110struct applesmc_dev_attr { 106struct applesmc_dev_attr {
@@ -117,6 +113,7 @@ struct applesmc_node_group {
117 char *format; /* format string */ 113 char *format; /* format string */
118 void *show; /* show function */ 114 void *show; /* show function */
119 void *store; /* store function */ 115 void *store; /* store function */
116 int option; /* function argument */
120 struct applesmc_dev_attr *nodes; /* dynamic node array */ 117 struct applesmc_dev_attr *nodes; /* dynamic node array */
121}; 118};
122 119
@@ -133,6 +130,7 @@ struct applesmc_entry {
133static struct applesmc_registers { 130static struct applesmc_registers {
134 struct mutex mutex; /* register read/write mutex */ 131 struct mutex mutex; /* register read/write mutex */
135 unsigned int key_count; /* number of SMC registers */ 132 unsigned int key_count; /* number of SMC registers */
133 unsigned int fan_count; /* number of fans */
136 unsigned int temp_count; /* number of temperature registers */ 134 unsigned int temp_count; /* number of temperature registers */
137 unsigned int temp_begin; /* temperature lower index bound */ 135 unsigned int temp_begin; /* temperature lower index bound */
138 unsigned int temp_end; /* temperature upper index bound */ 136 unsigned int temp_end; /* temperature upper index bound */
@@ -154,9 +152,6 @@ static u8 backlight_state[2];
154static struct device *hwmon_dev; 152static struct device *hwmon_dev;
155static struct input_polled_dev *applesmc_idev; 153static struct input_polled_dev *applesmc_idev;
156 154
157/* The number of fans handled by the driver */
158static unsigned int fans_handled;
159
160/* 155/*
161 * Last index written to key_at_index sysfs file, and value to use for all other 156 * Last index written to key_at_index sysfs file, and value to use for all other
162 * key_at_index_* sysfs files. 157 * key_at_index_* sysfs files.
@@ -484,28 +479,13 @@ static void applesmc_device_init(void)
484} 479}
485 480
486/* 481/*
487 * applesmc_get_fan_count - get the number of fans.
488 */
489static int applesmc_get_fan_count(void)
490{
491 int ret;
492 u8 buffer[1];
493
494 ret = applesmc_read_key(FANS_COUNT, buffer, 1);
495
496 if (ret)
497 return ret;
498 else
499 return buffer[0];
500}
501
502/*
503 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. 482 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
504 */ 483 */
505static int applesmc_init_smcreg_try(void) 484static int applesmc_init_smcreg_try(void)
506{ 485{
507 struct applesmc_registers *s = &smcreg; 486 struct applesmc_registers *s = &smcreg;
508 bool left_light_sensor, right_light_sensor; 487 bool left_light_sensor, right_light_sensor;
488 u8 tmp[1];
509 int ret; 489 int ret;
510 490
511 if (s->init_complete) 491 if (s->init_complete)
@@ -520,6 +500,11 @@ static int applesmc_init_smcreg_try(void)
520 if (!s->cache) 500 if (!s->cache)
521 return -ENOMEM; 501 return -ENOMEM;
522 502
503 ret = applesmc_read_key(FANS_COUNT, tmp, 1);
504 if (ret)
505 return ret;
506 s->fan_count = tmp[0];
507
523 ret = applesmc_get_lower_bound(&s->temp_begin, "T"); 508 ret = applesmc_get_lower_bound(&s->temp_begin, "T");
524 if (ret) 509 if (ret)
525 return ret; 510 return ret;
@@ -544,8 +529,8 @@ static int applesmc_init_smcreg_try(void)
544 s->num_light_sensors = left_light_sensor + right_light_sensor; 529 s->num_light_sensors = left_light_sensor + right_light_sensor;
545 s->init_complete = true; 530 s->init_complete = true;
546 531
547 pr_info("key=%d temp=%d acc=%d lux=%d kbd=%d\n", 532 pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n",
548 s->key_count, s->temp_count, 533 s->key_count, s->fan_count, s->temp_count,
549 s->has_accelerometer, 534 s->has_accelerometer,
550 s->num_light_sensors, 535 s->num_light_sensors,
551 s->has_key_backlight); 536 s->has_key_backlight);
@@ -776,14 +761,8 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
776 unsigned int speed = 0; 761 unsigned int speed = 0;
777 char newkey[5]; 762 char newkey[5];
778 u8 buffer[2]; 763 u8 buffer[2];
779 struct sensor_device_attribute_2 *sensor_attr =
780 to_sensor_dev_attr_2(attr);
781 764
782 newkey[0] = fan_speed_keys[sensor_attr->nr][0]; 765 sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
783 newkey[1] = '0' + sensor_attr->index;
784 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
785 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
786 newkey[4] = 0;
787 766
788 ret = applesmc_read_key(newkey, buffer, 2); 767 ret = applesmc_read_key(newkey, buffer, 2);
789 speed = ((buffer[0] << 8 | buffer[1]) >> 2); 768 speed = ((buffer[0] << 8 | buffer[1]) >> 2);
@@ -802,19 +781,13 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
802 u32 speed; 781 u32 speed;
803 char newkey[5]; 782 char newkey[5];
804 u8 buffer[2]; 783 u8 buffer[2];
805 struct sensor_device_attribute_2 *sensor_attr =
806 to_sensor_dev_attr_2(attr);
807 784
808 speed = simple_strtoul(sysfsbuf, NULL, 10); 785 speed = simple_strtoul(sysfsbuf, NULL, 10);
809 786
810 if (speed > 0x4000) /* Bigger than a 14-bit value */ 787 if (speed > 0x4000) /* Bigger than a 14-bit value */
811 return -EINVAL; 788 return -EINVAL;
812 789
813 newkey[0] = fan_speed_keys[sensor_attr->nr][0]; 790 sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
814 newkey[1] = '0' + sensor_attr->index;
815 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
816 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
817 newkey[4] = 0;
818 791
819 buffer[0] = (speed >> 6) & 0xff; 792 buffer[0] = (speed >> 6) & 0xff;
820 buffer[1] = (speed << 2) & 0xff; 793 buffer[1] = (speed << 2) & 0xff;
@@ -827,15 +800,14 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
827} 800}
828 801
829static ssize_t applesmc_show_fan_manual(struct device *dev, 802static ssize_t applesmc_show_fan_manual(struct device *dev,
830 struct device_attribute *devattr, char *sysfsbuf) 803 struct device_attribute *attr, char *sysfsbuf)
831{ 804{
832 int ret; 805 int ret;
833 u16 manual = 0; 806 u16 manual = 0;
834 u8 buffer[2]; 807 u8 buffer[2];
835 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
836 808
837 ret = applesmc_read_key(FANS_MANUAL, buffer, 2); 809 ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
838 manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01; 810 manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
839 811
840 if (ret) 812 if (ret)
841 return ret; 813 return ret;
@@ -844,14 +816,13 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
844} 816}
845 817
846static ssize_t applesmc_store_fan_manual(struct device *dev, 818static ssize_t applesmc_store_fan_manual(struct device *dev,
847 struct device_attribute *devattr, 819 struct device_attribute *attr,
848 const char *sysfsbuf, size_t count) 820 const char *sysfsbuf, size_t count)
849{ 821{
850 int ret; 822 int ret;
851 u8 buffer[2]; 823 u8 buffer[2];
852 u32 input; 824 u32 input;
853 u16 val; 825 u16 val;
854 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
855 826
856 input = simple_strtoul(sysfsbuf, NULL, 10); 827 input = simple_strtoul(sysfsbuf, NULL, 10);
857 828
@@ -861,9 +832,9 @@ static ssize_t applesmc_store_fan_manual(struct device *dev,
861 goto out; 832 goto out;
862 833
863 if (input) 834 if (input)
864 val = val | (0x01 << attr->index); 835 val = val | (0x01 << to_index(attr));
865 else 836 else
866 val = val & ~(0x01 << attr->index); 837 val = val & ~(0x01 << to_index(attr));
867 838
868 buffer[0] = (val >> 8) & 0xFF; 839 buffer[0] = (val >> 8) & 0xFF;
869 buffer[1] = val & 0xFF; 840 buffer[1] = val & 0xFF;
@@ -883,14 +854,8 @@ static ssize_t applesmc_show_fan_position(struct device *dev,
883 int ret; 854 int ret;
884 char newkey[5]; 855 char newkey[5];
885 u8 buffer[17]; 856 u8 buffer[17];
886 struct sensor_device_attribute_2 *sensor_attr =
887 to_sensor_dev_attr_2(attr);
888 857
889 newkey[0] = FAN_POSITION[0]; 858 sprintf(newkey, FAN_ID_FMT, to_index(attr));
890 newkey[1] = '0' + sensor_attr->index;
891 newkey[2] = FAN_POSITION[2];
892 newkey[3] = FAN_POSITION[3];
893 newkey[4] = 0;
894 859
895 ret = applesmc_read_key(newkey, buffer, 16); 860 ret = applesmc_read_key(newkey, buffer, 16);
896 buffer[16] = 0; 861 buffer[16] = 0;
@@ -1069,62 +1034,15 @@ static struct attribute *key_enumeration_attributes[] = {
1069static const struct attribute_group key_enumeration_group = 1034static const struct attribute_group key_enumeration_group =
1070 { .attrs = key_enumeration_attributes }; 1035 { .attrs = key_enumeration_attributes };
1071 1036
1072/* 1037static struct applesmc_node_group fan_group[] = {
1073 * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries. 1038 { "fan%d_label", applesmc_show_fan_position },
1074 * - show actual speed 1039 { "fan%d_input", applesmc_show_fan_speed, NULL, 0 },
1075 * - show/store minimum speed 1040 { "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 },
1076 * - show maximum speed 1041 { "fan%d_max", applesmc_show_fan_speed, NULL, 2 },
1077 * - show safe speed 1042 { "fan%d_safe", applesmc_show_fan_speed, NULL, 3 },
1078 * - show/store target speed 1043 { "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 },
1079 * - show/store manual mode 1044 { "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual },
1080 */ 1045 { }
1081#define sysfs_fan_speeds_offset(offset) \
1082static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
1083 applesmc_show_fan_speed, NULL, 0, offset-1); \
1084\
1085static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
1086 applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
1087\
1088static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
1089 applesmc_show_fan_speed, NULL, 2, offset-1); \
1090\
1091static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
1092 applesmc_show_fan_speed, NULL, 3, offset-1); \
1093\
1094static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
1095 applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
1096\
1097static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
1098 applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
1099\
1100static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
1101 applesmc_show_fan_position, NULL, offset-1); \
1102\
1103static struct attribute *fan##offset##_attributes[] = { \
1104 &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
1105 &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
1106 &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
1107 &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
1108 &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
1109 &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
1110 &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
1111 NULL \
1112};
1113
1114/*
1115 * Create the needed functions for each fan using the macro defined above
1116 * (4 fans are supported)
1117 */
1118sysfs_fan_speeds_offset(1);
1119sysfs_fan_speeds_offset(2);
1120sysfs_fan_speeds_offset(3);
1121sysfs_fan_speeds_offset(4);
1122
1123static const struct attribute_group fan_attribute_groups[] = {
1124 { .attrs = fan1_attributes },
1125 { .attrs = fan2_attributes },
1126 { .attrs = fan3_attributes },
1127 { .attrs = fan4_attributes },
1128}; 1046};
1129 1047
1130static struct applesmc_node_group temp_group[] = { 1048static struct applesmc_node_group temp_group[] = {
@@ -1171,7 +1089,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num)
1171 for (i = 0; i < num; i++) { 1089 for (i = 0; i < num; i++) {
1172 node = &grp->nodes[i]; 1090 node = &grp->nodes[i];
1173 sprintf(node->name, grp->format, i + 1); 1091 sprintf(node->name, grp->format, i + 1);
1174 node->sda.index = i; 1092 node->sda.index = (grp->option << 16) | (i & 0xffff);
1175 node->sda.dev_attr.show = grp->show; 1093 node->sda.dev_attr.show = grp->show;
1176 node->sda.dev_attr.store = grp->store; 1094 node->sda.dev_attr.store = grp->store;
1177 attr = &node->sda.dev_attr.attr; 1095 attr = &node->sda.dev_attr.attr;
@@ -1287,7 +1205,6 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
1287static int __init applesmc_init(void) 1205static int __init applesmc_init(void)
1288{ 1206{
1289 int ret; 1207 int ret;
1290 int count;
1291 1208
1292 if (!dmi_check_system(applesmc_whitelist)) { 1209 if (!dmi_check_system(applesmc_whitelist)) {
1293 pr_warn("supported laptop not found!\n"); 1210 pr_warn("supported laptop not found!\n");
@@ -1326,25 +1243,9 @@ static int __init applesmc_init(void)
1326 if (ret) 1243 if (ret)
1327 goto out_name; 1244 goto out_name;
1328 1245
1329 /* create fan files */ 1246 ret = applesmc_create_nodes(fan_group, smcreg.fan_count);
1330 count = applesmc_get_fan_count(); 1247 if (ret)
1331 if (count < 0) 1248 goto out_info;
1332 pr_err("Cannot get the number of fans\n");
1333 else
1334 pr_info("%d fans found\n", count);
1335
1336 if (count > 4) {
1337 count = 4;
1338 pr_warn("A maximum of 4 fans are supported by this driver\n");
1339 }
1340
1341 while (fans_handled < count) {
1342 ret = sysfs_create_group(&pdev->dev.kobj,
1343 &fan_attribute_groups[fans_handled]);
1344 if (ret)
1345 goto out_fans;
1346 fans_handled++;
1347 }
1348 1249
1349 ret = applesmc_create_nodes(temp_group, smcreg.temp_count); 1250 ret = applesmc_create_nodes(temp_group, smcreg.temp_count);
1350 if (ret) 1251 if (ret)
@@ -1402,9 +1303,8 @@ out_accelerometer:
1402out_temperature: 1303out_temperature:
1403 applesmc_destroy_nodes(temp_group); 1304 applesmc_destroy_nodes(temp_group);
1404out_fans: 1305out_fans:
1405 while (fans_handled) 1306 applesmc_destroy_nodes(fan_group);
1406 sysfs_remove_group(&pdev->dev.kobj, 1307out_info:
1407 &fan_attribute_groups[--fans_handled]);
1408 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); 1308 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
1409out_name: 1309out_name:
1410 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); 1310 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
@@ -1433,9 +1333,7 @@ static void __exit applesmc_exit(void)
1433 if (smcreg.has_accelerometer) 1333 if (smcreg.has_accelerometer)
1434 applesmc_release_accelerometer(); 1334 applesmc_release_accelerometer();
1435 applesmc_destroy_nodes(temp_group); 1335 applesmc_destroy_nodes(temp_group);
1436 while (fans_handled) 1336 applesmc_destroy_nodes(fan_group);
1437 sysfs_remove_group(&pdev->dev.kobj,
1438 &fan_attribute_groups[--fans_handled]);
1439 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); 1337 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
1440 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); 1338 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
1441 applesmc_destroy_smcreg(); 1339 applesmc_destroy_smcreg();