summaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/applesmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/applesmc.c')
-rw-r--r--drivers/hwmon/applesmc.c207
1 files changed, 115 insertions, 92 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index f082e48ab113..282708860517 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -8,7 +8,7 @@
8 * 8 *
9 * Based on hdaps.c driver: 9 * Based on hdaps.c driver:
10 * Copyright (C) 2005 Robert Love <rml@novell.com> 10 * Copyright (C) 2005 Robert Love <rml@novell.com>
11 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> 11 * Copyright (C) 2005 Jesper Juhl <jj@chaosbits.net>
12 * 12 *
13 * Fan control based on smcFanControl: 13 * Fan control based on smcFanControl:
14 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com> 14 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
@@ -54,10 +54,10 @@
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_RETRY_WAIT 0x0100
58#define APPLESMC_MAX_WAIT 0x8000 59#define APPLESMC_MAX_WAIT 0x8000
59 60
60#define APPLESMC_STATUS_MASK 0x0f
61#define APPLESMC_READ_CMD 0x10 61#define APPLESMC_READ_CMD 0x10
62#define APPLESMC_WRITE_CMD 0x11 62#define APPLESMC_WRITE_CMD 0x11
63#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 63#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
@@ -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};
@@ -162,51 +162,68 @@ static unsigned int key_at_index;
162static struct workqueue_struct *applesmc_led_wq; 162static struct workqueue_struct *applesmc_led_wq;
163 163
164/* 164/*
165 * __wait_status - Wait up to 32ms for the status port to get a certain value 165 * wait_read - Wait for a byte to appear on SMC port. Callers must
166 * (masked with 0x0f), returning zero if the value is obtained. Callers must
167 * hold applesmc_lock. 166 * hold applesmc_lock.
168 */ 167 */
169static int __wait_status(u8 val) 168static int wait_read(void)
170{ 169{
170 u8 status;
171 int us; 171 int us;
172
173 val = val & APPLESMC_STATUS_MASK;
174
175 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { 172 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
176 udelay(us); 173 udelay(us);
177 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) 174 status = inb(APPLESMC_CMD_PORT);
175 /* read: wait for smc to settle */
176 if (status & 0x01)
178 return 0; 177 return 0;
179 } 178 }
180 179
180 pr_warn("wait_read() fail: 0x%02x\n", status);
181 return -EIO; 181 return -EIO;
182} 182}
183 183
184/* 184/*
185 * special treatment of command port - on newer macbooks, it seems necessary 185 * send_byte - Write to SMC port, retrying when necessary. Callers
186 * to resend the command byte before polling the status again. Callers must 186 * must hold applesmc_lock.
187 * hold applesmc_lock.
188 */ 187 */
189static int send_command(u8 cmd) 188static int send_byte(u8 cmd, u16 port)
190{ 189{
190 u8 status;
191 int us; 191 int us;
192
193 outb(cmd, port);
192 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { 194 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
193 outb(cmd, APPLESMC_CMD_PORT);
194 udelay(us); 195 udelay(us);
195 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) 196 status = inb(APPLESMC_CMD_PORT);
197 /* write: wait for smc to settle */
198 if (status & 0x02)
199 continue;
200 /* ready: cmd accepted, return */
201 if (status & 0x04)
196 return 0; 202 return 0;
203 /* timeout: give up */
204 if (us << 1 == APPLESMC_MAX_WAIT)
205 break;
206 /* busy: long wait and resend */
207 udelay(APPLESMC_RETRY_WAIT);
208 outb(cmd, port);
197 } 209 }
210
211 pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
198 return -EIO; 212 return -EIO;
199} 213}
200 214
215static int send_command(u8 cmd)
216{
217 return send_byte(cmd, APPLESMC_CMD_PORT);
218}
219
201static int send_argument(const char *key) 220static int send_argument(const char *key)
202{ 221{
203 int i; 222 int i;
204 223
205 for (i = 0; i < 4; i++) { 224 for (i = 0; i < 4; i++)
206 outb(key[i], APPLESMC_DATA_PORT); 225 if (send_byte(key[i], APPLESMC_DATA_PORT))
207 if (__wait_status(0x04))
208 return -EIO; 226 return -EIO;
209 }
210 return 0; 227 return 0;
211} 228}
212 229
@@ -215,15 +232,18 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
215 int i; 232 int i;
216 233
217 if (send_command(cmd) || send_argument(key)) { 234 if (send_command(cmd) || send_argument(key)) {
218 pr_warn("%s: read arg fail\n", key); 235 pr_warn("%.4s: read arg fail\n", key);
219 return -EIO; 236 return -EIO;
220 } 237 }
221 238
222 outb(len, APPLESMC_DATA_PORT); 239 if (send_byte(len, APPLESMC_DATA_PORT)) {
240 pr_warn("%.4s: read len fail\n", key);
241 return -EIO;
242 }
223 243
224 for (i = 0; i < len; i++) { 244 for (i = 0; i < len; i++) {
225 if (__wait_status(0x05)) { 245 if (wait_read()) {
226 pr_warn("%s: read data fail\n", key); 246 pr_warn("%.4s: read data[%d] fail\n", key, i);
227 return -EIO; 247 return -EIO;
228 } 248 }
229 buffer[i] = inb(APPLESMC_DATA_PORT); 249 buffer[i] = inb(APPLESMC_DATA_PORT);
@@ -241,14 +261,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
241 return -EIO; 261 return -EIO;
242 } 262 }
243 263
244 outb(len, APPLESMC_DATA_PORT); 264 if (send_byte(len, APPLESMC_DATA_PORT)) {
265 pr_warn("%.4s: write len fail\n", key);
266 return -EIO;
267 }
245 268
246 for (i = 0; i < len; i++) { 269 for (i = 0; i < len; i++) {
247 if (__wait_status(0x04)) { 270 if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
248 pr_warn("%s: write data fail\n", key); 271 pr_warn("%s: write data fail\n", key);
249 return -EIO; 272 return -EIO;
250 } 273 }
251 outb(buffer[i], APPLESMC_DATA_PORT);
252 } 274 }
253 275
254 return 0; 276 return 0;
@@ -432,30 +454,19 @@ static int applesmc_has_key(const char *key, bool *value)
432} 454}
433 455
434/* 456/*
435 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). 457 * applesmc_read_s16 - Read 16-bit signed big endian register
436 */ 458 */
437static int applesmc_read_motion_sensor(int index, s16 *value) 459static int applesmc_read_s16(const char *key, s16 *value)
438{ 460{
439 u8 buffer[2]; 461 u8 buffer[2];
440 int ret; 462 int ret;
441 463
442 switch (index) { 464 ret = applesmc_read_key(key, buffer, 2);
443 case SENSOR_X: 465 if (ret)
444 ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2); 466 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 467
456 *value = ((s16)buffer[0] << 8) | buffer[1]; 468 *value = ((s16)buffer[0] << 8) | buffer[1];
457 469 return 0;
458 return ret;
459} 470}
460 471
461/* 472/*
@@ -482,6 +493,30 @@ static void applesmc_device_init(void)
482 pr_warn("failed to init the device\n"); 493 pr_warn("failed to init the device\n");
483} 494}
484 495
496static int applesmc_init_index(struct applesmc_registers *s)
497{
498 const struct applesmc_entry *entry;
499 unsigned int i;
500
501 if (s->index)
502 return 0;
503
504 s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL);
505 if (!s->index)
506 return -ENOMEM;
507
508 for (i = s->temp_begin; i < s->temp_end; i++) {
509 entry = applesmc_get_entry_by_index(i);
510 if (IS_ERR(entry))
511 continue;
512 if (strcmp(entry->type, TEMP_SENSOR_TYPE))
513 continue;
514 s->index[s->index_count++] = entry->key;
515 }
516
517 return 0;
518}
519
485/* 520/*
486 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. 521 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
487 */ 522 */
@@ -517,6 +552,10 @@ static int applesmc_init_smcreg_try(void)
517 return ret; 552 return ret;
518 s->temp_count = s->temp_end - s->temp_begin; 553 s->temp_count = s->temp_end - s->temp_begin;
519 554
555 ret = applesmc_init_index(s);
556 if (ret)
557 return ret;
558
520 ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); 559 ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
521 if (ret) 560 if (ret)
522 return ret; 561 return ret;
@@ -533,8 +572,8 @@ static int applesmc_init_smcreg_try(void)
533 s->num_light_sensors = left_light_sensor + right_light_sensor; 572 s->num_light_sensors = left_light_sensor + right_light_sensor;
534 s->init_complete = true; 573 s->init_complete = true;
535 574
536 pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", 575 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, 576 s->key_count, s->fan_count, s->temp_count, s->index_count,
538 s->has_accelerometer, 577 s->has_accelerometer,
539 s->num_light_sensors, 578 s->num_light_sensors,
540 s->has_key_backlight); 579 s->has_key_backlight);
@@ -542,6 +581,15 @@ static int applesmc_init_smcreg_try(void)
542 return 0; 581 return 0;
543} 582}
544 583
584static void applesmc_destroy_smcreg(void)
585{
586 kfree(smcreg.index);
587 smcreg.index = NULL;
588 kfree(smcreg.cache);
589 smcreg.cache = NULL;
590 smcreg.init_complete = false;
591}
592
545/* 593/*
546 * applesmc_init_smcreg - Initialize register cache. 594 * applesmc_init_smcreg - Initialize register cache.
547 * 595 *
@@ -562,19 +610,11 @@ static int applesmc_init_smcreg(void)
562 msleep(INIT_WAIT_MSECS); 610 msleep(INIT_WAIT_MSECS);
563 } 611 }
564 612
565 kfree(smcreg.cache); 613 applesmc_destroy_smcreg();
566 smcreg.cache = NULL;
567 614
568 return ret; 615 return ret;
569} 616}
570 617
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 */ 618/* Device model stuff */
579static int applesmc_probe(struct platform_device *dev) 619static int applesmc_probe(struct platform_device *dev)
580{ 620{
@@ -624,8 +664,8 @@ static struct platform_driver applesmc_driver = {
624 */ 664 */
625static void applesmc_calibrate(void) 665static void applesmc_calibrate(void)
626{ 666{
627 applesmc_read_motion_sensor(SENSOR_X, &rest_x); 667 applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x);
628 applesmc_read_motion_sensor(SENSOR_Y, &rest_y); 668 applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y);
629 rest_x = -rest_x; 669 rest_x = -rest_x;
630} 670}
631 671
@@ -634,9 +674,9 @@ static void applesmc_idev_poll(struct input_polled_dev *dev)
634 struct input_dev *idev = dev->input; 674 struct input_dev *idev = dev->input;
635 s16 x, y; 675 s16 x, y;
636 676
637 if (applesmc_read_motion_sensor(SENSOR_X, &x)) 677 if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x))
638 return; 678 return;
639 if (applesmc_read_motion_sensor(SENSOR_Y, &y)) 679 if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y))
640 return; 680 return;
641 681
642 x = -x; 682 x = -x;
@@ -659,13 +699,13 @@ static ssize_t applesmc_position_show(struct device *dev,
659 int ret; 699 int ret;
660 s16 x, y, z; 700 s16 x, y, z;
661 701
662 ret = applesmc_read_motion_sensor(SENSOR_X, &x); 702 ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x);
663 if (ret) 703 if (ret)
664 goto out; 704 goto out;
665 ret = applesmc_read_motion_sensor(SENSOR_Y, &y); 705 ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y);
666 if (ret) 706 if (ret)
667 goto out; 707 goto out;
668 ret = applesmc_read_motion_sensor(SENSOR_Z, &z); 708 ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z);
669 if (ret) 709 if (ret)
670 goto out; 710 goto out;
671 711
@@ -718,44 +758,27 @@ out:
718static ssize_t applesmc_show_sensor_label(struct device *dev, 758static ssize_t applesmc_show_sensor_label(struct device *dev,
719 struct device_attribute *devattr, char *sysfsbuf) 759 struct device_attribute *devattr, char *sysfsbuf)
720{ 760{
721 int index = smcreg.temp_begin + to_index(devattr); 761 const char *key = smcreg.index[to_index(devattr)];
722 const struct applesmc_entry *entry;
723
724 entry = applesmc_get_entry_by_index(index);
725 if (IS_ERR(entry))
726 return PTR_ERR(entry);
727 762
728 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); 763 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
729} 764}
730 765
731/* Displays degree Celsius * 1000 */ 766/* Displays degree Celsius * 1000 */
732static ssize_t applesmc_show_temperature(struct device *dev, 767static ssize_t applesmc_show_temperature(struct device *dev,
733 struct device_attribute *devattr, char *sysfsbuf) 768 struct device_attribute *devattr, char *sysfsbuf)
734{ 769{
735 int index = smcreg.temp_begin + to_index(devattr); 770 const char *key = smcreg.index[to_index(devattr)];
736 const struct applesmc_entry *entry;
737 int ret; 771 int ret;
738 u8 buffer[2]; 772 s16 value;
739 unsigned int temp; 773 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 774
747 ret = applesmc_read_entry(entry, buffer, entry->len); 775 ret = applesmc_read_s16(key, &value);
748 if (ret) 776 if (ret)
749 return ret; 777 return ret;
750 778
751 if (entry->len == 2) { 779 temp = 250 * (value >> 6);
752 temp = buffer[0] * 1000;
753 temp += (buffer[1] >> 6) * 250;
754 } else {
755 temp = buffer[0] * 4000;
756 }
757 780
758 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); 781 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp);
759} 782}
760 783
761static ssize_t applesmc_show_fan_speed(struct device *dev, 784static ssize_t applesmc_show_fan_speed(struct device *dev,
@@ -1265,7 +1288,7 @@ static int __init applesmc_init(void)
1265 if (ret) 1288 if (ret)
1266 goto out_info; 1289 goto out_info;
1267 1290
1268 ret = applesmc_create_nodes(temp_group, smcreg.temp_count); 1291 ret = applesmc_create_nodes(temp_group, smcreg.index_count);
1269 if (ret) 1292 if (ret)
1270 goto out_fans; 1293 goto out_fans;
1271 1294