diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-11 14:23:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-11 14:23:33 -0400 |
| commit | 4c274fff4fa03cf2509e1b01d3712de6131bfa50 (patch) | |
| tree | 7a1c32af08c3eb559154f2340431b8de178b167b | |
| parent | 474a503d4bf77ae0cbe484dd0842a2648c0b1c28 (diff) | |
| parent | 384e724b6b396de32c1e9cb0b7ccdd011bcc2beb (diff) | |
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
hwmon: (s3c-hwmon) Disable build for S3C64xx
MAINTAINERS: Fix Riku Voipio's address
hwmon: (asus_atk0110) Enable the EC
hwmon: (asus_atk0110) Refactor the code
hwmon: (sht15) Fix spurious section mismatch warning
| -rw-r--r-- | MAINTAINERS | 2 | ||||
| -rw-r--r-- | drivers/hwmon/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/hwmon/asus_atk0110.c | 339 | ||||
| -rw-r--r-- | drivers/hwmon/sht15.c | 7 |
4 files changed, 292 insertions, 58 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6141bdff3596..69e31aab1308 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2065,7 +2065,7 @@ S: Maintained | |||
| 2065 | F: fs/* | 2065 | F: fs/* |
| 2066 | 2066 | ||
| 2067 | FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER | 2067 | FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER |
| 2068 | M: Riku Voipio <riku.vipio@iki.fi> | 2068 | M: Riku Voipio <riku.voipio@iki.fi> |
| 2069 | L: lm-sensors@lm-sensors.org | 2069 | L: lm-sensors@lm-sensors.org |
| 2070 | S: Maintained | 2070 | S: Maintained |
| 2071 | F: drivers/hwmon/f75375s.c | 2071 | F: drivers/hwmon/f75375s.c |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6857560144bd..700e93adeb33 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -675,7 +675,7 @@ config SENSORS_SHT15 | |||
| 675 | 675 | ||
| 676 | config SENSORS_S3C | 676 | config SENSORS_S3C |
| 677 | tristate "S3C24XX/S3C64XX Inbuilt ADC" | 677 | tristate "S3C24XX/S3C64XX Inbuilt ADC" |
| 678 | depends on ARCH_S3C2410 || ARCH_S3C64XX | 678 | depends on ARCH_S3C2410 |
| 679 | help | 679 | help |
| 680 | If you say yes here you get support for the on-board ADCs of | 680 | If you say yes here you get support for the on-board ADCs of |
| 681 | the Samsung S3C24XX or S3C64XX series of SoC | 681 | the Samsung S3C24XX or S3C64XX series of SoC |
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index fe4fa29c9219..5a3ee00c0e7d 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c | |||
| @@ -35,18 +35,22 @@ | |||
| 35 | #define METHOD_OLD_ENUM_FAN "FSIF" | 35 | #define METHOD_OLD_ENUM_FAN "FSIF" |
| 36 | 36 | ||
| 37 | #define ATK_MUX_HWMON 0x00000006ULL | 37 | #define ATK_MUX_HWMON 0x00000006ULL |
| 38 | #define ATK_MUX_MGMT 0x00000011ULL | ||
| 38 | 39 | ||
| 39 | #define ATK_CLASS_MASK 0xff000000ULL | 40 | #define ATK_CLASS_MASK 0xff000000ULL |
| 40 | #define ATK_CLASS_FREQ_CTL 0x03000000ULL | 41 | #define ATK_CLASS_FREQ_CTL 0x03000000ULL |
| 41 | #define ATK_CLASS_FAN_CTL 0x04000000ULL | 42 | #define ATK_CLASS_FAN_CTL 0x04000000ULL |
| 42 | #define ATK_CLASS_HWMON 0x06000000ULL | 43 | #define ATK_CLASS_HWMON 0x06000000ULL |
| 44 | #define ATK_CLASS_MGMT 0x11000000ULL | ||
| 43 | 45 | ||
| 44 | #define ATK_TYPE_MASK 0x00ff0000ULL | 46 | #define ATK_TYPE_MASK 0x00ff0000ULL |
| 45 | #define HWMON_TYPE_VOLT 0x00020000ULL | 47 | #define HWMON_TYPE_VOLT 0x00020000ULL |
| 46 | #define HWMON_TYPE_TEMP 0x00030000ULL | 48 | #define HWMON_TYPE_TEMP 0x00030000ULL |
| 47 | #define HWMON_TYPE_FAN 0x00040000ULL | 49 | #define HWMON_TYPE_FAN 0x00040000ULL |
| 48 | 50 | ||
| 49 | #define HWMON_SENSOR_ID_MASK 0x0000ffffULL | 51 | #define ATK_ELEMENT_ID_MASK 0x0000ffffULL |
| 52 | |||
| 53 | #define ATK_EC_ID 0x11060004ULL | ||
| 50 | 54 | ||
| 51 | enum atk_pack_member { | 55 | enum atk_pack_member { |
| 52 | HWMON_PACK_FLAGS, | 56 | HWMON_PACK_FLAGS, |
| @@ -89,6 +93,9 @@ struct atk_data { | |||
| 89 | /* new inteface */ | 93 | /* new inteface */ |
| 90 | acpi_handle enumerate_handle; | 94 | acpi_handle enumerate_handle; |
| 91 | acpi_handle read_handle; | 95 | acpi_handle read_handle; |
| 96 | acpi_handle write_handle; | ||
| 97 | |||
| 98 | bool disable_ec; | ||
| 92 | 99 | ||
| 93 | int voltage_count; | 100 | int voltage_count; |
| 94 | int temperature_count; | 101 | int temperature_count; |
| @@ -129,9 +136,22 @@ struct atk_sensor_data { | |||
| 129 | char const *acpi_name; | 136 | char const *acpi_name; |
| 130 | }; | 137 | }; |
| 131 | 138 | ||
| 132 | struct atk_acpi_buffer_u64 { | 139 | /* Return buffer format: |
| 133 | union acpi_object buf; | 140 | * [0-3] "value" is valid flag |
| 134 | u64 value; | 141 | * [4-7] value |
| 142 | * [8- ] unknown stuff on newer mobos | ||
| 143 | */ | ||
| 144 | struct atk_acpi_ret_buffer { | ||
| 145 | u32 flags; | ||
| 146 | u32 value; | ||
| 147 | u8 data[]; | ||
| 148 | }; | ||
| 149 | |||
| 150 | /* Input buffer used for GITM and SITM methods */ | ||
| 151 | struct atk_acpi_input_buf { | ||
| 152 | u32 id; | ||
| 153 | u32 param1; | ||
| 154 | u32 param2; | ||
| 135 | }; | 155 | }; |
| 136 | 156 | ||
| 137 | static int atk_add(struct acpi_device *device); | 157 | static int atk_add(struct acpi_device *device); |
| @@ -439,52 +459,147 @@ static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value) | |||
| 439 | return 0; | 459 | return 0; |
| 440 | } | 460 | } |
| 441 | 461 | ||
| 442 | static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) | 462 | static union acpi_object *atk_ggrp(struct atk_data *data, u16 mux) |
| 443 | { | 463 | { |
| 444 | struct atk_data *data = sensor->data; | ||
| 445 | struct device *dev = &data->acpi_dev->dev; | 464 | struct device *dev = &data->acpi_dev->dev; |
| 465 | struct acpi_buffer buf; | ||
| 466 | acpi_status ret; | ||
| 446 | struct acpi_object_list params; | 467 | struct acpi_object_list params; |
| 447 | struct acpi_buffer ret; | ||
| 448 | union acpi_object id; | 468 | union acpi_object id; |
| 449 | struct atk_acpi_buffer_u64 tmp; | 469 | union acpi_object *pack; |
| 450 | acpi_status status; | ||
| 451 | 470 | ||
| 452 | id.type = ACPI_TYPE_INTEGER; | 471 | id.type = ACPI_TYPE_INTEGER; |
| 453 | id.integer.value = sensor->id; | 472 | id.integer.value = mux; |
| 454 | |||
| 455 | params.count = 1; | 473 | params.count = 1; |
| 456 | params.pointer = &id; | 474 | params.pointer = &id; |
| 457 | 475 | ||
| 458 | tmp.buf.type = ACPI_TYPE_BUFFER; | 476 | buf.length = ACPI_ALLOCATE_BUFFER; |
| 459 | tmp.buf.buffer.pointer = (u8 *)&tmp.value; | 477 | ret = acpi_evaluate_object(data->enumerate_handle, NULL, ¶ms, &buf); |
| 460 | tmp.buf.buffer.length = sizeof(u64); | 478 | if (ret != AE_OK) { |
| 461 | ret.length = sizeof(tmp); | 479 | dev_err(dev, "GGRP[%#x] ACPI exception: %s\n", mux, |
| 462 | ret.pointer = &tmp; | 480 | acpi_format_exception(ret)); |
| 481 | return ERR_PTR(-EIO); | ||
| 482 | } | ||
| 483 | pack = buf.pointer; | ||
| 484 | if (pack->type != ACPI_TYPE_PACKAGE) { | ||
| 485 | /* Execution was successful, but the id was not found */ | ||
| 486 | ACPI_FREE(pack); | ||
| 487 | return ERR_PTR(-ENOENT); | ||
| 488 | } | ||
| 489 | |||
| 490 | if (pack->package.count < 1) { | ||
| 491 | dev_err(dev, "GGRP[%#x] package is too small\n", mux); | ||
| 492 | ACPI_FREE(pack); | ||
| 493 | return ERR_PTR(-EIO); | ||
| 494 | } | ||
| 495 | return pack; | ||
| 496 | } | ||
| 497 | |||
| 498 | static union acpi_object *atk_gitm(struct atk_data *data, u64 id) | ||
| 499 | { | ||
| 500 | struct device *dev = &data->acpi_dev->dev; | ||
| 501 | struct atk_acpi_input_buf buf; | ||
| 502 | union acpi_object tmp; | ||
| 503 | struct acpi_object_list params; | ||
| 504 | struct acpi_buffer ret; | ||
| 505 | union acpi_object *obj; | ||
| 506 | acpi_status status; | ||
| 507 | |||
| 508 | buf.id = id; | ||
| 509 | buf.param1 = 0; | ||
| 510 | buf.param2 = 0; | ||
| 463 | 511 | ||
| 512 | tmp.type = ACPI_TYPE_BUFFER; | ||
| 513 | tmp.buffer.pointer = (u8 *)&buf; | ||
| 514 | tmp.buffer.length = sizeof(buf); | ||
| 515 | |||
| 516 | params.count = 1; | ||
| 517 | params.pointer = (void *)&tmp; | ||
| 518 | |||
| 519 | ret.length = ACPI_ALLOCATE_BUFFER; | ||
| 464 | status = acpi_evaluate_object_typed(data->read_handle, NULL, ¶ms, | 520 | status = acpi_evaluate_object_typed(data->read_handle, NULL, ¶ms, |
| 465 | &ret, ACPI_TYPE_BUFFER); | 521 | &ret, ACPI_TYPE_BUFFER); |
| 466 | if (status != AE_OK) { | 522 | if (status != AE_OK) { |
| 467 | dev_warn(dev, "%s: ACPI exception: %s\n", __func__, | 523 | dev_warn(dev, "GITM[%#llx] ACPI exception: %s\n", id, |
| 468 | acpi_format_exception(status)); | 524 | acpi_format_exception(status)); |
| 469 | return -EIO; | 525 | return ERR_PTR(-EIO); |
| 526 | } | ||
| 527 | obj = ret.pointer; | ||
| 528 | |||
| 529 | /* Sanity check */ | ||
| 530 | if (obj->buffer.length < 8) { | ||
| 531 | dev_warn(dev, "Unexpected ASBF length: %u\n", | ||
| 532 | obj->buffer.length); | ||
| 533 | ACPI_FREE(obj); | ||
| 534 | return ERR_PTR(-EIO); | ||
| 470 | } | 535 | } |
| 536 | return obj; | ||
| 537 | } | ||
| 471 | 538 | ||
| 472 | /* Return buffer format: | 539 | static union acpi_object *atk_sitm(struct atk_data *data, |
| 473 | * [0-3] "value" is valid flag | 540 | struct atk_acpi_input_buf *buf) |
| 474 | * [4-7] value | 541 | { |
| 475 | */ | 542 | struct device *dev = &data->acpi_dev->dev; |
| 476 | if (!(tmp.value & 0xffffffff)) { | 543 | struct acpi_object_list params; |
| 544 | union acpi_object tmp; | ||
| 545 | struct acpi_buffer ret; | ||
| 546 | union acpi_object *obj; | ||
| 547 | acpi_status status; | ||
| 548 | |||
| 549 | tmp.type = ACPI_TYPE_BUFFER; | ||
| 550 | tmp.buffer.pointer = (u8 *)buf; | ||
| 551 | tmp.buffer.length = sizeof(*buf); | ||
| 552 | |||
| 553 | params.count = 1; | ||
| 554 | params.pointer = &tmp; | ||
| 555 | |||
| 556 | ret.length = ACPI_ALLOCATE_BUFFER; | ||
| 557 | status = acpi_evaluate_object_typed(data->write_handle, NULL, ¶ms, | ||
| 558 | &ret, ACPI_TYPE_BUFFER); | ||
| 559 | if (status != AE_OK) { | ||
| 560 | dev_warn(dev, "SITM[%#x] ACPI exception: %s\n", buf->id, | ||
| 561 | acpi_format_exception(status)); | ||
| 562 | return ERR_PTR(-EIO); | ||
| 563 | } | ||
| 564 | obj = ret.pointer; | ||
| 565 | |||
| 566 | /* Sanity check */ | ||
| 567 | if (obj->buffer.length < 8) { | ||
| 568 | dev_warn(dev, "Unexpected ASBF length: %u\n", | ||
| 569 | obj->buffer.length); | ||
| 570 | ACPI_FREE(obj); | ||
| 571 | return ERR_PTR(-EIO); | ||
| 572 | } | ||
| 573 | return obj; | ||
| 574 | } | ||
| 575 | |||
| 576 | static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) | ||
| 577 | { | ||
| 578 | struct atk_data *data = sensor->data; | ||
| 579 | struct device *dev = &data->acpi_dev->dev; | ||
| 580 | union acpi_object *obj; | ||
| 581 | struct atk_acpi_ret_buffer *buf; | ||
| 582 | int err = 0; | ||
| 583 | |||
| 584 | obj = atk_gitm(data, sensor->id); | ||
| 585 | if (IS_ERR(obj)) | ||
| 586 | return PTR_ERR(obj); | ||
| 587 | |||
| 588 | buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; | ||
| 589 | if (buf->flags == 0) { | ||
| 477 | /* The reading is not valid, possible causes: | 590 | /* The reading is not valid, possible causes: |
| 478 | * - sensor failure | 591 | * - sensor failure |
| 479 | * - enumeration was FUBAR (and we didn't notice) | 592 | * - enumeration was FUBAR (and we didn't notice) |
| 480 | */ | 593 | */ |
| 481 | dev_info(dev, "Failure: %#llx\n", tmp.value); | 594 | dev_warn(dev, "Read failed, sensor = %#llx\n", sensor->id); |
| 482 | return -EIO; | 595 | err = -EIO; |
| 596 | goto out; | ||
| 483 | } | 597 | } |
| 484 | 598 | ||
| 485 | *value = (tmp.value & 0xffffffff00000000ULL) >> 32; | 599 | *value = buf->value; |
| 486 | 600 | out: | |
| 487 | return 0; | 601 | ACPI_FREE(obj); |
| 602 | return err; | ||
| 488 | } | 603 | } |
| 489 | 604 | ||
| 490 | static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) | 605 | static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) |
| @@ -713,43 +828,141 @@ cleanup: | |||
| 713 | return ret; | 828 | return ret; |
| 714 | } | 829 | } |
| 715 | 830 | ||
| 716 | static int atk_enumerate_new_hwmon(struct atk_data *data) | 831 | static int atk_ec_present(struct atk_data *data) |
| 717 | { | 832 | { |
| 718 | struct device *dev = &data->acpi_dev->dev; | 833 | struct device *dev = &data->acpi_dev->dev; |
| 719 | struct acpi_buffer buf; | ||
| 720 | acpi_status ret; | ||
| 721 | struct acpi_object_list params; | ||
| 722 | union acpi_object id; | ||
| 723 | union acpi_object *pack; | 834 | union acpi_object *pack; |
| 724 | int err; | 835 | union acpi_object *ec; |
| 836 | int ret; | ||
| 725 | int i; | 837 | int i; |
| 726 | 838 | ||
| 727 | dev_dbg(dev, "Enumerating hwmon sensors\n"); | 839 | pack = atk_ggrp(data, ATK_MUX_MGMT); |
| 840 | if (IS_ERR(pack)) { | ||
| 841 | if (PTR_ERR(pack) == -ENOENT) { | ||
| 842 | /* The MGMT class does not exists - that's ok */ | ||
| 843 | dev_dbg(dev, "Class %#llx not found\n", ATK_MUX_MGMT); | ||
| 844 | return 0; | ||
| 845 | } | ||
| 846 | return PTR_ERR(pack); | ||
| 847 | } | ||
| 728 | 848 | ||
| 729 | id.type = ACPI_TYPE_INTEGER; | 849 | /* Search the EC */ |
| 730 | id.integer.value = ATK_MUX_HWMON; | 850 | ec = NULL; |
| 731 | params.count = 1; | 851 | for (i = 0; i < pack->package.count; i++) { |
| 732 | params.pointer = &id; | 852 | union acpi_object *obj = &pack->package.elements[i]; |
| 853 | union acpi_object *id; | ||
| 733 | 854 | ||
| 734 | buf.length = ACPI_ALLOCATE_BUFFER; | 855 | if (obj->type != ACPI_TYPE_PACKAGE) |
| 735 | ret = acpi_evaluate_object_typed(data->enumerate_handle, NULL, ¶ms, | 856 | continue; |
| 736 | &buf, ACPI_TYPE_PACKAGE); | 857 | |
| 737 | if (ret != AE_OK) { | 858 | id = &obj->package.elements[0]; |
| 738 | dev_warn(dev, METHOD_ENUMERATE ": ACPI exception: %s\n", | 859 | if (id->type != ACPI_TYPE_INTEGER) |
| 739 | acpi_format_exception(ret)); | 860 | continue; |
| 740 | return -ENODEV; | 861 | |
| 862 | if (id->integer.value == ATK_EC_ID) { | ||
| 863 | ec = obj; | ||
| 864 | break; | ||
| 865 | } | ||
| 741 | } | 866 | } |
| 742 | 867 | ||
| 743 | /* Result must be a package */ | 868 | ret = (ec != NULL); |
| 744 | pack = buf.pointer; | 869 | if (!ret) |
| 870 | /* The system has no EC */ | ||
| 871 | dev_dbg(dev, "EC not found\n"); | ||
| 745 | 872 | ||
| 746 | if (pack->package.count < 1) { | 873 | ACPI_FREE(pack); |
| 747 | dev_dbg(dev, "%s: hwmon package is too small: %d\n", __func__, | 874 | return ret; |
| 748 | pack->package.count); | 875 | } |
| 749 | err = -EINVAL; | 876 | |
| 750 | goto out; | 877 | static int atk_ec_enabled(struct atk_data *data) |
| 878 | { | ||
| 879 | struct device *dev = &data->acpi_dev->dev; | ||
| 880 | union acpi_object *obj; | ||
| 881 | struct atk_acpi_ret_buffer *buf; | ||
| 882 | int err; | ||
| 883 | |||
| 884 | obj = atk_gitm(data, ATK_EC_ID); | ||
| 885 | if (IS_ERR(obj)) { | ||
| 886 | dev_err(dev, "Unable to query EC status\n"); | ||
| 887 | return PTR_ERR(obj); | ||
| 888 | } | ||
| 889 | buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; | ||
| 890 | |||
| 891 | if (buf->flags == 0) { | ||
| 892 | dev_err(dev, "Unable to query EC status\n"); | ||
| 893 | err = -EIO; | ||
| 894 | } else { | ||
| 895 | err = (buf->value != 0); | ||
| 896 | dev_dbg(dev, "EC is %sabled\n", | ||
| 897 | err ? "en" : "dis"); | ||
| 898 | } | ||
| 899 | |||
| 900 | ACPI_FREE(obj); | ||
| 901 | return err; | ||
| 902 | } | ||
| 903 | |||
| 904 | static int atk_ec_ctl(struct atk_data *data, int enable) | ||
| 905 | { | ||
| 906 | struct device *dev = &data->acpi_dev->dev; | ||
| 907 | union acpi_object *obj; | ||
| 908 | struct atk_acpi_input_buf sitm; | ||
| 909 | struct atk_acpi_ret_buffer *ec_ret; | ||
| 910 | int err = 0; | ||
| 911 | |||
| 912 | sitm.id = ATK_EC_ID; | ||
| 913 | sitm.param1 = enable; | ||
| 914 | sitm.param2 = 0; | ||
| 915 | |||
| 916 | obj = atk_sitm(data, &sitm); | ||
| 917 | if (IS_ERR(obj)) { | ||
| 918 | dev_err(dev, "Failed to %sable the EC\n", | ||
| 919 | enable ? "en" : "dis"); | ||
| 920 | return PTR_ERR(obj); | ||
| 921 | } | ||
| 922 | ec_ret = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; | ||
| 923 | if (ec_ret->flags == 0) { | ||
| 924 | dev_err(dev, "Failed to %sable the EC\n", | ||
| 925 | enable ? "en" : "dis"); | ||
| 926 | err = -EIO; | ||
| 927 | } else { | ||
| 928 | dev_info(dev, "EC %sabled\n", | ||
| 929 | enable ? "en" : "dis"); | ||
| 930 | } | ||
| 931 | |||
| 932 | ACPI_FREE(obj); | ||
| 933 | return err; | ||
| 934 | } | ||
| 935 | |||
| 936 | static int atk_enumerate_new_hwmon(struct atk_data *data) | ||
| 937 | { | ||
| 938 | struct device *dev = &data->acpi_dev->dev; | ||
| 939 | union acpi_object *pack; | ||
| 940 | int err; | ||
| 941 | int i; | ||
| 942 | |||
| 943 | err = atk_ec_present(data); | ||
| 944 | if (err < 0) | ||
| 945 | return err; | ||
| 946 | if (err) { | ||
| 947 | err = atk_ec_enabled(data); | ||
| 948 | if (err < 0) | ||
| 949 | return err; | ||
| 950 | /* If the EC was disabled we will disable it again on unload */ | ||
| 951 | data->disable_ec = err; | ||
| 952 | |||
| 953 | err = atk_ec_ctl(data, 1); | ||
| 954 | if (err) { | ||
| 955 | data->disable_ec = false; | ||
| 956 | return err; | ||
| 957 | } | ||
| 751 | } | 958 | } |
| 752 | 959 | ||
| 960 | dev_dbg(dev, "Enumerating hwmon sensors\n"); | ||
| 961 | |||
| 962 | pack = atk_ggrp(data, ATK_MUX_HWMON); | ||
| 963 | if (IS_ERR(pack)) | ||
| 964 | return PTR_ERR(pack); | ||
| 965 | |||
| 753 | for (i = 0; i < pack->package.count; i++) { | 966 | for (i = 0; i < pack->package.count; i++) { |
| 754 | union acpi_object *obj = &pack->package.elements[i]; | 967 | union acpi_object *obj = &pack->package.elements[i]; |
| 755 | 968 | ||
| @@ -758,8 +971,7 @@ static int atk_enumerate_new_hwmon(struct atk_data *data) | |||
| 758 | 971 | ||
| 759 | err = data->voltage_count + data->temperature_count + data->fan_count; | 972 | err = data->voltage_count + data->temperature_count + data->fan_count; |
| 760 | 973 | ||
| 761 | out: | 974 | ACPI_FREE(pack); |
| 762 | ACPI_FREE(buf.pointer); | ||
| 763 | return err; | 975 | return err; |
| 764 | } | 976 | } |
| 765 | 977 | ||
| @@ -895,6 +1107,15 @@ static int atk_check_new_if(struct atk_data *data) | |||
| 895 | } | 1107 | } |
| 896 | data->read_handle = ret; | 1108 | data->read_handle = ret; |
| 897 | 1109 | ||
| 1110 | /* De-multiplexer (write) */ | ||
| 1111 | status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret); | ||
| 1112 | if (status != AE_OK) { | ||
| 1113 | dev_dbg(dev, "method " METHOD_READ " not found: %s\n", | ||
| 1114 | acpi_format_exception(status)); | ||
| 1115 | return -ENODEV; | ||
| 1116 | } | ||
| 1117 | data->write_handle = ret; | ||
| 1118 | |||
| 898 | return 0; | 1119 | return 0; |
| 899 | } | 1120 | } |
| 900 | 1121 | ||
| @@ -915,6 +1136,7 @@ static int atk_add(struct acpi_device *device) | |||
| 915 | data->acpi_dev = device; | 1136 | data->acpi_dev = device; |
| 916 | data->atk_handle = device->handle; | 1137 | data->atk_handle = device->handle; |
| 917 | INIT_LIST_HEAD(&data->sensor_list); | 1138 | INIT_LIST_HEAD(&data->sensor_list); |
| 1139 | data->disable_ec = false; | ||
| 918 | 1140 | ||
| 919 | buf.length = ACPI_ALLOCATE_BUFFER; | 1141 | buf.length = ACPI_ALLOCATE_BUFFER; |
| 920 | ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL, | 1142 | ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL, |
| @@ -973,6 +1195,8 @@ static int atk_add(struct acpi_device *device) | |||
| 973 | cleanup: | 1195 | cleanup: |
| 974 | atk_free_sensors(data); | 1196 | atk_free_sensors(data); |
| 975 | out: | 1197 | out: |
| 1198 | if (data->disable_ec) | ||
| 1199 | atk_ec_ctl(data, 0); | ||
| 976 | kfree(data); | 1200 | kfree(data); |
| 977 | return err; | 1201 | return err; |
| 978 | } | 1202 | } |
| @@ -988,6 +1212,11 @@ static int atk_remove(struct acpi_device *device, int type) | |||
| 988 | atk_free_sensors(data); | 1212 | atk_free_sensors(data); |
| 989 | hwmon_device_unregister(data->hwmon_dev); | 1213 | hwmon_device_unregister(data->hwmon_dev); |
| 990 | 1214 | ||
| 1215 | if (data->disable_ec) { | ||
| 1216 | if (atk_ec_ctl(data, 0)) | ||
| 1217 | dev_err(&device->dev, "Failed to disable EC\n"); | ||
| 1218 | } | ||
| 1219 | |||
| 991 | kfree(data); | 1220 | kfree(data); |
| 992 | 1221 | ||
| 993 | return 0; | 1222 | return 0; |
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 2da6fb2c325e..ebe38b680ee3 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c | |||
| @@ -623,7 +623,12 @@ static int __devexit sht15_remove(struct platform_device *pdev) | |||
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | 625 | ||
| 626 | static struct platform_driver sht_drivers[] = { | 626 | /* |
| 627 | * sht_drivers simultaneously refers to __devinit and __devexit function | ||
| 628 | * which causes spurious section mismatch warning. So use __refdata to | ||
| 629 | * get rid from this. | ||
| 630 | */ | ||
| 631 | static struct platform_driver __refdata sht_drivers[] = { | ||
| 627 | { | 632 | { |
| 628 | .driver = { | 633 | .driver = { |
| 629 | .name = "sht10", | 634 | .name = "sht10", |
