aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/debugfs-ec20
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt71
-rw-r--r--arch/x86/include/asm/intel_scu_ipc.h20
-rw-r--r--drivers/acpi/Kconfig18
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ec.c107
-rw-r--r--drivers/acpi/ec_sys.c160
-rw-r--r--drivers/acpi/internal.h24
-rw-r--r--drivers/platform/x86/Kconfig44
-rw-r--r--drivers/platform/x86/Makefile4
-rw-r--r--drivers/platform/x86/acer-wmi.c79
-rw-r--r--drivers/platform/x86/acerhdf.c151
-rw-r--r--drivers/platform/x86/asus-laptop.c29
-rw-r--r--drivers/platform/x86/asus_acpi.c7
-rw-r--r--drivers/platform/x86/classmate-laptop.c13
-rw-r--r--drivers/platform/x86/compal-laptop.c929
-rw-r--r--drivers/platform/x86/dell-laptop.c9
-rw-r--r--drivers/platform/x86/dell-wmi.c11
-rw-r--r--drivers/platform/x86/eeepc-laptop.c2
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c16
-rw-r--r--drivers/platform/x86/hp-wmi.c281
-rw-r--r--drivers/platform/x86/intel_ips.c1660
-rw-r--r--drivers/platform/x86/intel_menlow.c33
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c340
-rw-r--r--drivers/platform/x86/intel_rar_register.c (renamed from drivers/staging/rar_register/rar_register.c)8
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c180
-rw-r--r--drivers/platform/x86/msi-laptop.c8
-rw-r--r--drivers/platform/x86/msi-wmi.c2
-rw-r--r--drivers/platform/x86/panasonic-laptop.c7
-rw-r--r--drivers/platform/x86/sony-laptop.c13
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c73
-rw-r--r--drivers/platform/x86/toshiba_acpi.c135
-rw-r--r--drivers/platform/x86/wmi.c28
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/memrar/memrar_handler.c3
-rw-r--r--drivers/staging/rar_register/Kconfig30
-rw-r--r--drivers/staging/rar_register/Makefile2
-rw-r--r--include/drm/i915_drm.h9
-rw-r--r--include/linux/intel_pmic_gpio.h15
-rw-r--r--include/linux/rar_register.h (renamed from drivers/staging/rar_register/rar_register.h)0
-rw-r--r--include/linux/timer.h15
-rw-r--r--kernel/timer.c13
43 files changed, 3830 insertions, 743 deletions
diff --git a/Documentation/ABI/testing/debugfs-ec b/Documentation/ABI/testing/debugfs-ec
new file mode 100644
index 000000000000..6546115a94da
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-ec
@@ -0,0 +1,20 @@
1What: /sys/kernel/debug/ec/*/{gpe,use_global_lock,io}
2Date: July 2010
3Contact: Thomas Renninger <trenn@suse.de>
4Description:
5
6General information like which GPE is assigned to the EC and whether
7the global lock should get used.
8Knowing the EC GPE one can watch the amount of HW events related to
9the EC here (XY -> GPE number from /sys/kernel/debug/ec/*/gpe):
10/sys/firmware/acpi/interrupts/gpeXY
11
12The io file is binary and a userspace tool located here:
13ftp://ftp.suse.com/pub/people/trenn/sources/ec/
14should get used to read out the 256 Embedded Controller registers
15or writing to them.
16
17CAUTION: Do not write to the Embedded Controller if you don't know
18what you are doing! Rebooting afterwards also is a good idea.
19This can influence the way your machine is cooled and fans may
20not get switched on again after you did a wrong write.
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index fc15538d8b46..f6f80257addb 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -960,70 +960,21 @@ Sysfs notes:
960 subsystem, and follow all of the hwmon guidelines at 960 subsystem, and follow all of the hwmon guidelines at
961 Documentation/hwmon. 961 Documentation/hwmon.
962 962
963EXPERIMENTAL: Embedded controller register dump
964-----------------------------------------------
963 965
964EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump 966This feature is not included in the thinkpad driver anymore.
965------------------------------------------------------------------------ 967Instead the EC can be accessed through /sys/kernel/debug/ec with
966 968a userspace tool which can be found here:
967This feature is marked EXPERIMENTAL because the implementation 969ftp://ftp.suse.com/pub/people/trenn/sources/ec
968directly accesses hardware registers and may not work as expected. USE
969WITH CAUTION! To use this feature, you need to supply the
970experimental=1 parameter when loading the module.
971
972This feature dumps the values of 256 embedded controller
973registers. Values which have changed since the last time the registers
974were dumped are marked with a star:
975
976[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
977EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
978EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
979EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
980EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
981EC 0x30: 01 07 1a 00 30 04 00 00 *85 00 00 10 00 50 00 00
982EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
983EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 *bc *02 *bc
984EC 0x60: *02 *bc *02 00 00 00 00 00 00 00 00 00 00 00 00 00
985EC 0x70: 00 00 00 00 00 12 30 40 *24 *26 *2c *27 *20 80 *1f 80
986EC 0x80: 00 00 00 06 *37 *0e 03 00 00 00 0e 07 00 00 00 00
987EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
988EC 0xa0: *ff 09 ff 09 ff ff *64 00 *00 *00 *a2 41 *ff *ff *e0 00
989EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
990EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
991EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
992EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
993EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a
994
995This feature can be used to determine the register holding the fan
996speed on some models. To do that, do the following:
997 970
971Use it to determine the register holding the fan
972speed on some models. To do that, do the following:
998 - make sure the battery is fully charged 973 - make sure the battery is fully charged
999 - make sure the fan is running 974 - make sure the fan is running
1000 - run 'cat /proc/acpi/ibm/ecdump' several times, once per second or so 975 - use above mentioned tool to read out the EC
1001 976
1002The first step makes sure various charging-related values don't 977Often fan and temperature values vary between
1003vary. The second ensures that the fan-related values do vary, since
1004the fan speed fluctuates a bit. The third will (hopefully) mark the
1005fan register with a star:
1006
1007[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
1008EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
1009EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
1010EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
1011EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
1012EC 0x30: 01 07 1a 00 30 04 00 00 85 00 00 10 00 50 00 00
1013EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
1014EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 bc 02 bc
1015EC 0x60: 02 bc 02 00 00 00 00 00 00 00 00 00 00 00 00 00
1016EC 0x70: 00 00 00 00 00 12 30 40 24 27 2c 27 21 80 1f 80
1017EC 0x80: 00 00 00 06 *be 0d 03 00 00 00 0e 07 00 00 00 00
1018EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1019EC 0xa0: ff 09 ff 09 ff ff 64 00 00 00 a2 41 ff ff e0 00
1020EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1021EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1022EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1023EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
1024EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a
1025
1026Another set of values that varies often is the temperature
1027readings. Since temperatures don't change vary fast, you can take 978readings. Since temperatures don't change vary fast, you can take
1028several quick dumps to eliminate them. 979several quick dumps to eliminate them.
1029 980
diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h
index 4470c9ad4a3e..29f66793cc55 100644
--- a/arch/x86/include/asm/intel_scu_ipc.h
+++ b/arch/x86/include/asm/intel_scu_ipc.h
@@ -1,6 +1,12 @@
1#ifndef _ASM_X86_INTEL_SCU_IPC_H_ 1#ifndef _ASM_X86_INTEL_SCU_IPC_H_
2#define _ASM_X86_INTEL_SCU_IPC_H_ 2#define _ASM_X86_INTEL_SCU_IPC_H_
3 3
4#define IPCMSG_VRTC 0xFA /* Set vRTC device */
5
6/* Command id associated with message IPCMSG_VRTC */
7#define IPC_CMD_VRTC_SETTIME 1 /* Set time */
8#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */
9
4/* Read single register */ 10/* Read single register */
5int intel_scu_ipc_ioread8(u16 addr, u8 *data); 11int intel_scu_ipc_ioread8(u16 addr, u8 *data);
6 12
@@ -28,20 +34,6 @@ int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);
28/* Update single register based on the mask */ 34/* Update single register based on the mask */
29int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask); 35int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
30 36
31/*
32 * Indirect register read
33 * Can be used when SCCB(System Controller Configuration Block) register
34 * HRIM(Honor Restricted IPC Messages) is set (bit 23)
35 */
36int intel_scu_ipc_register_read(u32 addr, u32 *data);
37
38/*
39 * Indirect register write
40 * Can be used when SCCB(System Controller Configuration Block) register
41 * HRIM(Honor Restricted IPC Messages) is set (bit 23)
42 */
43int intel_scu_ipc_register_write(u32 addr, u32 data);
44
45/* Issue commands to the SCU with or without data */ 37/* Issue commands to the SCU with or without data */
46int intel_scu_ipc_simple_command(int cmd, int sub); 38int intel_scu_ipc_simple_command(int cmd, int sub);
47int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 39int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 746411518802..08e0140920e1 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -104,6 +104,24 @@ config ACPI_SYSFS_POWER
104 help 104 help
105 Say N to disable power /sys interface 105 Say N to disable power /sys interface
106 106
107config ACPI_EC_DEBUGFS
108 tristate "EC read/write access through /sys/kernel/debug/ec"
109 default n
110 help
111 Say N to disable Embedded Controller /sys/kernel/debug interface
112
113 Be aware that using this interface can confuse your Embedded
114 Controller in a way that a normal reboot is not enough. You then
115 have to power of your system, and remove the laptop battery for
116 some seconds.
117 An Embedded Controller typically is available on laptops and reads
118 sensor values like battery state and temperature.
119 The kernel accesses the EC through ACPI parsed code provided by BIOS
120 tables. This option allows to access the EC directly without ACPI
121 code being involved.
122 Thus this option is a debug option that helps to write ACPI drivers
123 and can be used to identify ACPI code or EC firmware bugs.
124
107config ACPI_PROC_EVENT 125config ACPI_PROC_EVENT
108 bool "Deprecated /proc/acpi/event support" 126 bool "Deprecated /proc/acpi/event support"
109 depends on PROC_FS 127 depends on PROC_FS
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 6ee33169e1dc..833b582d1762 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_ACPI_SBS) += sbshc.o
60obj-$(CONFIG_ACPI_SBS) += sbs.o 60obj-$(CONFIG_ACPI_SBS) += sbs.o
61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o 61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
62obj-$(CONFIG_ACPI_HED) += hed.o 62obj-$(CONFIG_ACPI_HED) += hed.o
63obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
63 64
64# processor has its own "processor." module_param namespace 65# processor has its own "processor." module_param namespace
65processor-y := processor_driver.o processor_throttling.o 66processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 5f2027d782e8..1fa0aafebe2a 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -34,8 +34,6 @@
34#include <linux/init.h> 34#include <linux/init.h>
35#include <linux/types.h> 35#include <linux/types.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/proc_fs.h>
38#include <linux/seq_file.h>
39#include <linux/interrupt.h> 37#include <linux/interrupt.h>
40#include <linux/list.h> 38#include <linux/list.h>
41#include <linux/spinlock.h> 39#include <linux/spinlock.h>
@@ -45,10 +43,13 @@
45#include <acpi/acpi_drivers.h> 43#include <acpi/acpi_drivers.h>
46#include <linux/dmi.h> 44#include <linux/dmi.h>
47 45
46#include "internal.h"
47
48#define ACPI_EC_CLASS "embedded_controller" 48#define ACPI_EC_CLASS "embedded_controller"
49#define ACPI_EC_DEVICE_NAME "Embedded Controller" 49#define ACPI_EC_DEVICE_NAME "Embedded Controller"
50#define ACPI_EC_FILE_INFO "info" 50#define ACPI_EC_FILE_INFO "info"
51 51
52#undef PREFIX
52#define PREFIX "ACPI: EC: " 53#define PREFIX "ACPI: EC: "
53 54
54/* EC status register */ 55/* EC status register */
@@ -106,19 +107,8 @@ struct transaction {
106 bool done; 107 bool done;
107}; 108};
108 109
109static struct acpi_ec { 110struct acpi_ec *boot_ec, *first_ec;
110 acpi_handle handle; 111EXPORT_SYMBOL(first_ec);
111 unsigned long gpe;
112 unsigned long command_addr;
113 unsigned long data_addr;
114 unsigned long global_lock;
115 unsigned long flags;
116 struct mutex lock;
117 wait_queue_head_t wait;
118 struct list_head list;
119 struct transaction *curr;
120 spinlock_t curr_lock;
121} *boot_ec, *first_ec;
122 112
123static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ 113static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
124static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ 114static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
@@ -679,72 +669,6 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
679} 669}
680 670
681/* -------------------------------------------------------------------------- 671/* --------------------------------------------------------------------------
682 FS Interface (/proc)
683 -------------------------------------------------------------------------- */
684
685static struct proc_dir_entry *acpi_ec_dir;
686
687static int acpi_ec_read_info(struct seq_file *seq, void *offset)
688{
689 struct acpi_ec *ec = seq->private;
690
691 if (!ec)
692 goto end;
693
694 seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
695 seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
696 (unsigned)ec->command_addr, (unsigned)ec->data_addr);
697 seq_printf(seq, "use global lock:\t%s\n",
698 ec->global_lock ? "yes" : "no");
699 end:
700 return 0;
701}
702
703static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
704{
705 return single_open(file, acpi_ec_read_info, PDE(inode)->data);
706}
707
708static const struct file_operations acpi_ec_info_ops = {
709 .open = acpi_ec_info_open_fs,
710 .read = seq_read,
711 .llseek = seq_lseek,
712 .release = single_release,
713 .owner = THIS_MODULE,
714};
715
716static int acpi_ec_add_fs(struct acpi_device *device)
717{
718 struct proc_dir_entry *entry = NULL;
719
720 if (!acpi_device_dir(device)) {
721 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
722 acpi_ec_dir);
723 if (!acpi_device_dir(device))
724 return -ENODEV;
725 }
726
727 entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
728 acpi_device_dir(device),
729 &acpi_ec_info_ops, acpi_driver_data(device));
730 if (!entry)
731 return -ENODEV;
732 return 0;
733}
734
735static int acpi_ec_remove_fs(struct acpi_device *device)
736{
737
738 if (acpi_device_dir(device)) {
739 remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
740 remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
741 acpi_device_dir(device) = NULL;
742 }
743
744 return 0;
745}
746
747/* --------------------------------------------------------------------------
748 Driver Interface 672 Driver Interface
749 -------------------------------------------------------------------------- */ 673 -------------------------------------------------------------------------- */
750static acpi_status 674static acpi_status
@@ -894,7 +818,12 @@ static int acpi_ec_add(struct acpi_device *device)
894 if (!first_ec) 818 if (!first_ec)
895 first_ec = ec; 819 first_ec = ec;
896 device->driver_data = ec; 820 device->driver_data = ec;
897 acpi_ec_add_fs(device); 821
822 WARN(!request_region(ec->data_addr, 1, "EC data"),
823 "Could not request EC data io port 0x%lx", ec->data_addr);
824 WARN(!request_region(ec->command_addr, 1, "EC cmd"),
825 "Could not request EC cmd io port 0x%lx", ec->command_addr);
826
898 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 827 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
899 ec->gpe, ec->command_addr, ec->data_addr); 828 ec->gpe, ec->command_addr, ec->data_addr);
900 829
@@ -921,7 +850,8 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
921 kfree(handler); 850 kfree(handler);
922 } 851 }
923 mutex_unlock(&ec->lock); 852 mutex_unlock(&ec->lock);
924 acpi_ec_remove_fs(device); 853 release_region(ec->data_addr, 1);
854 release_region(ec->command_addr, 1);
925 device->driver_data = NULL; 855 device->driver_data = NULL;
926 if (ec == first_ec) 856 if (ec == first_ec)
927 first_ec = NULL; 857 first_ec = NULL;
@@ -1120,16 +1050,10 @@ int __init acpi_ec_init(void)
1120{ 1050{
1121 int result = 0; 1051 int result = 0;
1122 1052
1123 acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
1124 if (!acpi_ec_dir)
1125 return -ENODEV;
1126
1127 /* Now register the driver for the EC */ 1053 /* Now register the driver for the EC */
1128 result = acpi_bus_register_driver(&acpi_ec_driver); 1054 result = acpi_bus_register_driver(&acpi_ec_driver);
1129 if (result < 0) { 1055 if (result < 0)
1130 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1131 return -ENODEV; 1056 return -ENODEV;
1132 }
1133 1057
1134 return result; 1058 return result;
1135} 1059}
@@ -1140,9 +1064,6 @@ static void __exit acpi_ec_exit(void)
1140{ 1064{
1141 1065
1142 acpi_bus_unregister_driver(&acpi_ec_driver); 1066 acpi_bus_unregister_driver(&acpi_ec_driver);
1143
1144 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1145
1146 return; 1067 return;
1147} 1068}
1148#endif /* 0 */ 1069#endif /* 0 */
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
new file mode 100644
index 000000000000..0e869b3f81ca
--- /dev/null
+++ b/drivers/acpi/ec_sys.c
@@ -0,0 +1,160 @@
1/*
2 * ec_sys.c
3 *
4 * Copyright (C) 2010 SUSE Products GmbH/Novell
5 * Author:
6 * Thomas Renninger <trenn@suse.de>
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2.
9 */
10
11#include <linux/kernel.h>
12#include <linux/acpi.h>
13#include <linux/debugfs.h>
14#include "internal.h"
15
16MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
17MODULE_DESCRIPTION("ACPI EC sysfs access driver");
18MODULE_LICENSE("GPL");
19
20static bool write_support;
21module_param(write_support, bool, 0644);
22MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
23 "be needed.");
24
25#define EC_SPACE_SIZE 256
26
27struct sysdev_class acpi_ec_sysdev_class = {
28 .name = "ec",
29};
30
31static struct dentry *acpi_ec_debugfs_dir;
32
33static int acpi_ec_open_io(struct inode *i, struct file *f)
34{
35 f->private_data = i->i_private;
36 return 0;
37}
38
39static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
40 size_t count, loff_t *off)
41{
42 /* Use this if support reading/writing multiple ECs exists in ec.c:
43 * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
44 */
45 unsigned int size = EC_SPACE_SIZE;
46 u8 *data = (u8 *) buf;
47 loff_t init_off = *off;
48 int err = 0;
49
50 if (*off >= size)
51 return 0;
52 if (*off + count >= size) {
53 size -= *off;
54 count = size;
55 } else
56 size = count;
57
58 while (size) {
59 err = ec_read(*off, &data[*off - init_off]);
60 if (err)
61 return err;
62 *off += 1;
63 size--;
64 }
65 return count;
66}
67
68static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
69 size_t count, loff_t *off)
70{
71 /* Use this if support reading/writing multiple ECs exists in ec.c:
72 * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
73 */
74
75 unsigned int size = count;
76 loff_t init_off = *off;
77 u8 *data = (u8 *) buf;
78 int err = 0;
79
80 if (*off >= EC_SPACE_SIZE)
81 return 0;
82 if (*off + count >= EC_SPACE_SIZE) {
83 size = EC_SPACE_SIZE - *off;
84 count = size;
85 }
86
87 while (size) {
88 u8 byte_write = data[*off - init_off];
89 err = ec_write(*off, byte_write);
90 if (err)
91 return err;
92
93 *off += 1;
94 size--;
95 }
96 return count;
97}
98
99static struct file_operations acpi_ec_io_ops = {
100 .owner = THIS_MODULE,
101 .open = acpi_ec_open_io,
102 .read = acpi_ec_read_io,
103 .write = acpi_ec_write_io,
104};
105
106int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
107{
108 struct dentry *dev_dir;
109 char name[64];
110 mode_t mode = 0400;
111
112 if (ec_device_count == 0) {
113 acpi_ec_debugfs_dir = debugfs_create_dir("ec", NULL);
114 if (!acpi_ec_debugfs_dir)
115 return -ENOMEM;
116 }
117
118 sprintf(name, "ec%u", ec_device_count);
119 dev_dir = debugfs_create_dir(name, acpi_ec_debugfs_dir);
120 if (!dev_dir) {
121 if (ec_device_count != 0)
122 goto error;
123 return -ENOMEM;
124 }
125
126 if (!debugfs_create_x32("gpe", 0444, dev_dir, (u32 *)&first_ec->gpe))
127 goto error;
128 if (!debugfs_create_bool("use_global_lock", 0444, dev_dir,
129 (u32 *)&first_ec->global_lock))
130 goto error;
131
132 if (write_support)
133 mode = 0600;
134 if (!debugfs_create_file("io", mode, dev_dir, ec, &acpi_ec_io_ops))
135 goto error;
136
137 return 0;
138
139error:
140 debugfs_remove_recursive(acpi_ec_debugfs_dir);
141 return -ENOMEM;
142}
143
144static int __init acpi_ec_sys_init(void)
145{
146 int err = 0;
147 if (first_ec)
148 err = acpi_ec_add_debugfs(first_ec, 0);
149 else
150 err = -ENODEV;
151 return err;
152}
153
154static void __exit acpi_ec_sys_exit(void)
155{
156 debugfs_remove_recursive(acpi_ec_debugfs_dir);
157}
158
159module_init(acpi_ec_sys_init);
160module_exit(acpi_ec_sys_exit);
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index f8f190ec066e..8ae27264a00e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -18,6 +18,11 @@
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 */ 19 */
20 20
21#ifndef _ACPI_INTERNAL_H_
22#define _ACPI_INTERNAL_H_
23
24#include <linux/sysdev.h>
25
21#define PREFIX "ACPI: " 26#define PREFIX "ACPI: "
22 27
23int init_acpi_device_notify(void); 28int init_acpi_device_notify(void);
@@ -46,6 +51,23 @@ void acpi_early_processor_set_pdc(void);
46/* -------------------------------------------------------------------------- 51/* --------------------------------------------------------------------------
47 Embedded Controller 52 Embedded Controller
48 -------------------------------------------------------------------------- */ 53 -------------------------------------------------------------------------- */
54struct acpi_ec {
55 acpi_handle handle;
56 unsigned long gpe;
57 unsigned long command_addr;
58 unsigned long data_addr;
59 unsigned long global_lock;
60 unsigned long flags;
61 struct mutex lock;
62 wait_queue_head_t wait;
63 struct list_head list;
64 struct transaction *curr;
65 spinlock_t curr_lock;
66 struct sys_device sysdev;
67};
68
69extern struct acpi_ec *first_ec;
70
49int acpi_ec_init(void); 71int acpi_ec_init(void);
50int acpi_ec_ecdt_probe(void); 72int acpi_ec_ecdt_probe(void);
51int acpi_boot_ec_enable(void); 73int acpi_boot_ec_enable(void);
@@ -63,3 +85,5 @@ int acpi_sleep_proc_init(void);
63#else 85#else
64static inline int acpi_sleep_proc_init(void) { return 0; } 86static inline int acpi_sleep_proc_init(void) { return 0; }
65#endif 87#endif
88
89#endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 3e1b8a288719..79baa6368f79 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -5,6 +5,7 @@
5menuconfig X86_PLATFORM_DEVICES 5menuconfig X86_PLATFORM_DEVICES
6 bool "X86 Platform Specific Device Drivers" 6 bool "X86 Platform Specific Device Drivers"
7 default y 7 default y
8 depends on X86
8 ---help--- 9 ---help---
9 Say Y here to get to see options for device drivers for various 10 Say Y here to get to see options for device drivers for various
10 x86 platforms, including vendor-specific laptop extension drivers. 11 x86 platforms, including vendor-specific laptop extension drivers.
@@ -151,6 +152,7 @@ config MSI_LAPTOP
151 depends on ACPI 152 depends on ACPI
152 depends on BACKLIGHT_CLASS_DEVICE 153 depends on BACKLIGHT_CLASS_DEVICE
153 depends on RFKILL 154 depends on RFKILL
155 depends on SERIO_I8042
154 ---help--- 156 ---help---
155 This is a driver for laptops built by MSI (MICRO-STAR 157 This is a driver for laptops built by MSI (MICRO-STAR
156 INTERNATIONAL): 158 INTERNATIONAL):
@@ -181,6 +183,8 @@ config COMPAL_LAPTOP
181 depends on ACPI 183 depends on ACPI
182 depends on BACKLIGHT_CLASS_DEVICE 184 depends on BACKLIGHT_CLASS_DEVICE
183 depends on RFKILL 185 depends on RFKILL
186 depends on HWMON
187 depends on POWER_SUPPLY
184 ---help--- 188 ---help---
185 This is a driver for laptops built by Compal: 189 This is a driver for laptops built by Compal:
186 190
@@ -520,6 +524,7 @@ config TOSHIBA_BT_RFKILL
520config ACPI_CMPC 524config ACPI_CMPC
521 tristate "CMPC Laptop Extras" 525 tristate "CMPC Laptop Extras"
522 depends on X86 && ACPI 526 depends on X86 && ACPI
527 depends on RFKILL || RFKILL=n
523 select INPUT 528 select INPUT
524 select BACKLIGHT_CLASS_DEVICE 529 select BACKLIGHT_CLASS_DEVICE
525 default n 530 default n
@@ -537,4 +542,43 @@ config INTEL_SCU_IPC
537 some embedded Intel x86 platforms. This is not needed for PC-type 542 some embedded Intel x86 platforms. This is not needed for PC-type
538 machines. 543 machines.
539 544
545config GPIO_INTEL_PMIC
546 bool "Intel PMIC GPIO support"
547 depends on INTEL_SCU_IPC && GPIOLIB
548 ---help---
549 Say Y here to support GPIO via the SCU IPC interface
550 on Intel MID platforms.
551
552config RAR_REGISTER
553 bool "Restricted Access Region Register Driver"
554 depends on PCI && X86_MRST
555 default n
556 ---help---
557 This driver allows other kernel drivers access to the
558 contents of the restricted access region control registers.
559
560 The restricted access region control registers
561 (rar_registers) are used to pass address and
562 locking information on restricted access regions
563 to other drivers that use restricted access regions.
564
565 The restricted access regions are regions of memory
566 on the Intel MID Platform that are not accessible to
567 the x86 processor, but are accessible to dedicated
568 processors on board peripheral devices.
569
570 The purpose of the restricted access regions is to
571 protect sensitive data from compromise by unauthorized
572 programs running on the x86 processor.
573
574config INTEL_IPS
575 tristate "Intel Intelligent Power Sharing"
576 depends on ACPI
577 ---help---
578 Intel Calpella platforms support dynamic power sharing between the
579 CPU and GPU, maximizing performance in a given TDP. This driver,
580 along with the CPU frequency and i915 drivers, provides that
581 functionality. If in doubt, say Y here; it will only load on
582 supported platforms.
583
540endif # X86_PLATFORM_DEVICES 584endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 8770bfe71431..4744c7744ffa 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -26,3 +26,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
26obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 26obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
27obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 27obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
28obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 28obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
29obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o
30obj-$(CONFIG_INTEL_IPS) += intel_ips.o
31obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
32
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 1ea6c434d330..2badee2fdeed 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -50,17 +50,6 @@ MODULE_LICENSE("GPL");
50#define ACER_INFO KERN_INFO ACER_LOGPREFIX 50#define ACER_INFO KERN_INFO ACER_LOGPREFIX
51 51
52/* 52/*
53 * The following defines quirks to get some specific functions to work
54 * which are known to not be supported over ACPI-WMI (such as the mail LED
55 * on WMID based Acer's)
56 */
57struct acer_quirks {
58 const char *vendor;
59 const char *model;
60 u16 quirks;
61};
62
63/*
64 * Magic Number 53 * Magic Number
65 * Meaning is unknown - this number is required for writing to ACPI for AMW0 54 * Meaning is unknown - this number is required for writing to ACPI for AMW0
66 * (it's also used in acerhk when directly accessing the BIOS) 55 * (it's also used in acerhk when directly accessing the BIOS)
@@ -200,7 +189,7 @@ static void set_quirks(void)
200static int dmi_matched(const struct dmi_system_id *dmi) 189static int dmi_matched(const struct dmi_system_id *dmi)
201{ 190{
202 quirks = dmi->driver_data; 191 quirks = dmi->driver_data;
203 return 0; 192 return 1;
204} 193}
205 194
206static struct quirk_entry quirk_unknown = { 195static struct quirk_entry quirk_unknown = {
@@ -555,6 +544,7 @@ static acpi_status AMW0_find_mailled(void)
555 obj->buffer.length == sizeof(struct wmab_ret)) { 544 obj->buffer.length == sizeof(struct wmab_ret)) {
556 ret = *((struct wmab_ret *) obj->buffer.pointer); 545 ret = *((struct wmab_ret *) obj->buffer.pointer);
557 } else { 546 } else {
547 kfree(out.pointer);
558 return AE_ERROR; 548 return AE_ERROR;
559 } 549 }
560 550
@@ -570,7 +560,7 @@ static acpi_status AMW0_set_capabilities(void)
570{ 560{
571 struct wmab_args args; 561 struct wmab_args args;
572 struct wmab_ret ret; 562 struct wmab_ret ret;
573 acpi_status status = AE_OK; 563 acpi_status status;
574 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 564 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
575 union acpi_object *obj; 565 union acpi_object *obj;
576 566
@@ -593,12 +583,13 @@ static acpi_status AMW0_set_capabilities(void)
593 if (ACPI_FAILURE(status)) 583 if (ACPI_FAILURE(status))
594 return status; 584 return status;
595 585
596 obj = (union acpi_object *) out.pointer; 586 obj = out.pointer;
597 if (obj && obj->type == ACPI_TYPE_BUFFER && 587 if (obj && obj->type == ACPI_TYPE_BUFFER &&
598 obj->buffer.length == sizeof(struct wmab_ret)) { 588 obj->buffer.length == sizeof(struct wmab_ret)) {
599 ret = *((struct wmab_ret *) obj->buffer.pointer); 589 ret = *((struct wmab_ret *) obj->buffer.pointer);
600 } else { 590 } else {
601 return AE_ERROR; 591 status = AE_ERROR;
592 goto out;
602 } 593 }
603 594
604 if (ret.eax & 0x1) 595 if (ret.eax & 0x1)
@@ -607,23 +598,26 @@ static acpi_status AMW0_set_capabilities(void)
607 args.ebx = 2 << 8; 598 args.ebx = 2 << 8;
608 args.ebx |= ACER_AMW0_BLUETOOTH_MASK; 599 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
609 600
601 /*
602 * It's ok to use existing buffer for next wmab_execute call.
603 * But we need to kfree(out.pointer) if next wmab_execute fail.
604 */
610 status = wmab_execute(&args, &out); 605 status = wmab_execute(&args, &out);
611 if (ACPI_FAILURE(status)) 606 if (ACPI_FAILURE(status))
612 return status; 607 goto out;
613 608
614 obj = (union acpi_object *) out.pointer; 609 obj = (union acpi_object *) out.pointer;
615 if (obj && obj->type == ACPI_TYPE_BUFFER 610 if (obj && obj->type == ACPI_TYPE_BUFFER
616 && obj->buffer.length == sizeof(struct wmab_ret)) { 611 && obj->buffer.length == sizeof(struct wmab_ret)) {
617 ret = *((struct wmab_ret *) obj->buffer.pointer); 612 ret = *((struct wmab_ret *) obj->buffer.pointer);
618 } else { 613 } else {
619 return AE_ERROR; 614 status = AE_ERROR;
615 goto out;
620 } 616 }
621 617
622 if (ret.eax & 0x1) 618 if (ret.eax & 0x1)
623 interface->capability |= ACER_CAP_BLUETOOTH; 619 interface->capability |= ACER_CAP_BLUETOOTH;
624 620
625 kfree(out.pointer);
626
627 /* 621 /*
628 * This appears to be safe to enable, since all Wistron based laptops 622 * This appears to be safe to enable, since all Wistron based laptops
629 * appear to use the same EC register for brightness, even if they 623 * appear to use the same EC register for brightness, even if they
@@ -632,7 +626,10 @@ static acpi_status AMW0_set_capabilities(void)
632 if (quirks->brightness >= 0) 626 if (quirks->brightness >= 0)
633 interface->capability |= ACER_CAP_BRIGHTNESS; 627 interface->capability |= ACER_CAP_BRIGHTNESS;
634 628
635 return AE_OK; 629 status = AE_OK;
630out:
631 kfree(out.pointer);
632 return status;
636} 633}
637 634
638static struct wmi_interface AMW0_interface = { 635static struct wmi_interface AMW0_interface = {
@@ -772,6 +769,7 @@ static acpi_status WMID_set_capabilities(void)
772 obj->buffer.length == sizeof(u32)) { 769 obj->buffer.length == sizeof(u32)) {
773 devices = *((u32 *) obj->buffer.pointer); 770 devices = *((u32 *) obj->buffer.pointer);
774 } else { 771 } else {
772 kfree(out.pointer);
775 return AE_ERROR; 773 return AE_ERROR;
776 } 774 }
777 775
@@ -788,6 +786,7 @@ static acpi_status WMID_set_capabilities(void)
788 if (!(devices & 0x20)) 786 if (!(devices & 0x20))
789 max_brightness = 0x9; 787 max_brightness = 0x9;
790 788
789 kfree(out.pointer);
791 return status; 790 return status;
792} 791}
793 792
@@ -1084,8 +1083,7 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1084 } 1083 }
1085} 1084}
1086 1085
1087static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR, 1086static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
1088 show_interface, NULL);
1089 1087
1090/* 1088/*
1091 * debugfs functions 1089 * debugfs functions
@@ -1095,6 +1093,7 @@ static u32 get_wmid_devices(void)
1095 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 1093 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1096 union acpi_object *obj; 1094 union acpi_object *obj;
1097 acpi_status status; 1095 acpi_status status;
1096 u32 devices = 0;
1098 1097
1099 status = wmi_query_block(WMID_GUID2, 1, &out); 1098 status = wmi_query_block(WMID_GUID2, 1, &out);
1100 if (ACPI_FAILURE(status)) 1099 if (ACPI_FAILURE(status))
@@ -1103,10 +1102,11 @@ static u32 get_wmid_devices(void)
1103 obj = (union acpi_object *) out.pointer; 1102 obj = (union acpi_object *) out.pointer;
1104 if (obj && obj->type == ACPI_TYPE_BUFFER && 1103 if (obj && obj->type == ACPI_TYPE_BUFFER &&
1105 obj->buffer.length == sizeof(u32)) { 1104 obj->buffer.length == sizeof(u32)) {
1106 return *((u32 *) obj->buffer.pointer); 1105 devices = *((u32 *) obj->buffer.pointer);
1107 } else {
1108 return 0;
1109 } 1106 }
1107
1108 kfree(out.pointer);
1109 return devices;
1110} 1110}
1111 1111
1112/* 1112/*
@@ -1327,22 +1327,31 @@ static int __init acer_wmi_init(void)
1327 "generic video driver\n"); 1327 "generic video driver\n");
1328 } 1328 }
1329 1329
1330 if (platform_driver_register(&acer_platform_driver)) { 1330 err = platform_driver_register(&acer_platform_driver);
1331 if (err) {
1331 printk(ACER_ERR "Unable to register platform driver.\n"); 1332 printk(ACER_ERR "Unable to register platform driver.\n");
1332 goto error_platform_register; 1333 goto error_platform_register;
1333 } 1334 }
1335
1334 acer_platform_device = platform_device_alloc("acer-wmi", -1); 1336 acer_platform_device = platform_device_alloc("acer-wmi", -1);
1335 platform_device_add(acer_platform_device); 1337 if (!acer_platform_device) {
1338 err = -ENOMEM;
1339 goto error_device_alloc;
1340 }
1341
1342 err = platform_device_add(acer_platform_device);
1343 if (err)
1344 goto error_device_add;
1336 1345
1337 err = create_sysfs(); 1346 err = create_sysfs();
1338 if (err) 1347 if (err)
1339 return err; 1348 goto error_create_sys;
1340 1349
1341 if (wmi_has_guid(WMID_GUID2)) { 1350 if (wmi_has_guid(WMID_GUID2)) {
1342 interface->debug.wmid_devices = get_wmid_devices(); 1351 interface->debug.wmid_devices = get_wmid_devices();
1343 err = create_debugfs(); 1352 err = create_debugfs();
1344 if (err) 1353 if (err)
1345 return err; 1354 goto error_create_debugfs;
1346 } 1355 }
1347 1356
1348 /* Override any initial settings with values from the commandline */ 1357 /* Override any initial settings with values from the commandline */
@@ -1350,15 +1359,23 @@ static int __init acer_wmi_init(void)
1350 1359
1351 return 0; 1360 return 0;
1352 1361
1362error_create_debugfs:
1363 remove_sysfs(acer_platform_device);
1364error_create_sys:
1365 platform_device_del(acer_platform_device);
1366error_device_add:
1367 platform_device_put(acer_platform_device);
1368error_device_alloc:
1369 platform_driver_unregister(&acer_platform_driver);
1353error_platform_register: 1370error_platform_register:
1354 return -ENODEV; 1371 return err;
1355} 1372}
1356 1373
1357static void __exit acer_wmi_exit(void) 1374static void __exit acer_wmi_exit(void)
1358{ 1375{
1359 remove_sysfs(acer_platform_device); 1376 remove_sysfs(acer_platform_device);
1360 remove_debugfs(); 1377 remove_debugfs();
1361 platform_device_del(acer_platform_device); 1378 platform_device_unregister(acer_platform_device);
1362 platform_driver_unregister(&acer_platform_driver); 1379 platform_driver_unregister(&acer_platform_driver);
1363 1380
1364 printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n"); 1381 printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n");
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 7b2384d674d0..60f9cfcac93f 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
52 */ 52 */
53#undef START_IN_KERNEL_MODE 53#undef START_IN_KERNEL_MODE
54 54
55#define DRV_VER "0.5.22" 55#define DRV_VER "0.5.24"
56 56
57/* 57/*
58 * According to the Atom N270 datasheet, 58 * According to the Atom N270 datasheet,
@@ -92,9 +92,9 @@ static unsigned int fanstate = ACERHDF_FAN_AUTO;
92static char force_bios[16]; 92static char force_bios[16];
93static char force_product[16]; 93static char force_product[16];
94static unsigned int prev_interval; 94static unsigned int prev_interval;
95struct thermal_zone_device *thz_dev; 95static struct thermal_zone_device *thz_dev;
96struct thermal_cooling_device *cl_dev; 96static struct thermal_cooling_device *cl_dev;
97struct platform_device *acerhdf_dev; 97static struct platform_device *acerhdf_dev;
98 98
99module_param(kernelmode, uint, 0); 99module_param(kernelmode, uint, 0);
100MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); 100MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off");
@@ -112,14 +112,12 @@ module_param_string(force_product, force_product, 16, 0);
112MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); 112MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
113 113
114/* 114/*
115 * cmd_off: to switch the fan completely off 115 * cmd_off: to switch the fan completely off and check if the fan is off
116 * chk_off: to check if the fan is off
117 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then 116 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then
118 * the fan speed depending on the temperature 117 * the fan speed depending on the temperature
119 */ 118 */
120struct fancmd { 119struct fancmd {
121 u8 cmd_off; 120 u8 cmd_off;
122 u8 chk_off;
123 u8 cmd_auto; 121 u8 cmd_auto;
124}; 122};
125 123
@@ -136,47 +134,81 @@ struct bios_settings_t {
136/* Register addresses and values for different BIOS versions */ 134/* Register addresses and values for different BIOS versions */
137static const struct bios_settings_t bios_tbl[] = { 135static const struct bios_settings_t bios_tbl[] = {
138 /* AOA110 */ 136 /* AOA110 */
139 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 137 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
140 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 138 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
141 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 139 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
142 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 140 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
143 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 141 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
144 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 142 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} },
145 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} }, 143 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
146 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} }, 144 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
147 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} }, 145 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
148 /* AOA150 */ 146 /* AOA150 */
149 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} }, 147 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
150 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} }, 148 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} },
151 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} }, 149 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
152 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} }, 150 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} },
153 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} }, 151 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} },
154 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} }, 152 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
155 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} }, 153 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
156 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, 154 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
157 /* Acer 1410 */ 155 /* Acer 1410 */
158 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 156 {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
159 {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 157 {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
158 {"Acer", "Aspire 1410", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
159 {"Acer", "Aspire 1410", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
160 {"Acer", "Aspire 1410", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
161 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
162 {"Acer", "Aspire 1410", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
163 {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
164 {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
165 {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
160 /* Acer 1810xx */ 166 /* Acer 1810xx */
161 {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 167 {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
162 {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 168 {"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
163 {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 169 {"Acer", "Aspire 1810TZ", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
164 {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 170 {"Acer", "Aspire 1810T", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
171 {"Acer", "Aspire 1810TZ", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
172 {"Acer", "Aspire 1810T", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
173 {"Acer", "Aspire 1810TZ", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
174 {"Acer", "Aspire 1810T", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
175 {"Acer", "Aspire 1810TZ", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
176 {"Acer", "Aspire 1810T", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
177 {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
178 {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
179 {"Acer", "Aspire 1810TZ", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
180 {"Acer", "Aspire 1810T", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
181 {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
182 {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
183 {"Acer", "Aspire 1810TZ", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
184 {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
185 {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
186 {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
187 /* Acer 531 */
188 {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
165 /* Gateway */ 189 /* Gateway */
166 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, 190 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
167 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, 191 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
168 {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 192 {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} },
169 {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 193 {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
170 {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 194 {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
171 /* Packard Bell */ 195 /* Packard Bell */
172 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, 196 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
173 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 197 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
174 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, 198 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
175 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 199 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
176 {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 200 {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
177 {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 201 {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
202 {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
203 {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
204 {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
205 {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
206 {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
207 {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
208 {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
209 {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
178 /* pewpew-terminator */ 210 /* pewpew-terminator */
179 {"", "", "", 0, 0, {0, 0, 0} } 211 {"", "", "", 0, 0, {0, 0} }
180}; 212};
181 213
182static const struct bios_settings_t *bios_cfg __read_mostly; 214static const struct bios_settings_t *bios_cfg __read_mostly;
@@ -200,7 +232,7 @@ static int acerhdf_get_fanstate(int *state)
200 if (ec_read(bios_cfg->fanreg, &fan)) 232 if (ec_read(bios_cfg->fanreg, &fan))
201 return -EINVAL; 233 return -EINVAL;
202 234
203 if (fan != bios_cfg->cmd.chk_off) 235 if (fan != bios_cfg->cmd.cmd_off)
204 *state = ACERHDF_FAN_AUTO; 236 *state = ACERHDF_FAN_AUTO;
205 else 237 else
206 *state = ACERHDF_FAN_OFF; 238 *state = ACERHDF_FAN_OFF;
@@ -374,7 +406,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
374} 406}
375 407
376/* bind callback functions to thermalzone */ 408/* bind callback functions to thermalzone */
377struct thermal_zone_device_ops acerhdf_dev_ops = { 409static struct thermal_zone_device_ops acerhdf_dev_ops = {
378 .bind = acerhdf_bind, 410 .bind = acerhdf_bind,
379 .unbind = acerhdf_unbind, 411 .unbind = acerhdf_unbind,
380 .get_temp = acerhdf_get_ec_temp, 412 .get_temp = acerhdf_get_ec_temp,
@@ -449,7 +481,7 @@ err_out:
449} 481}
450 482
451/* bind fan callbacks to fan device */ 483/* bind fan callbacks to fan device */
452struct thermal_cooling_device_ops acerhdf_cooling_ops = { 484static struct thermal_cooling_device_ops acerhdf_cooling_ops = {
453 .get_max_state = acerhdf_get_max_state, 485 .get_max_state = acerhdf_get_max_state,
454 .get_cur_state = acerhdf_get_cur_state, 486 .get_cur_state = acerhdf_get_cur_state,
455 .set_cur_state = acerhdf_set_cur_state, 487 .set_cur_state = acerhdf_set_cur_state,
@@ -518,6 +550,10 @@ static int acerhdf_check_hardware(void)
518 version = dmi_get_system_info(DMI_BIOS_VERSION); 550 version = dmi_get_system_info(DMI_BIOS_VERSION);
519 product = dmi_get_system_info(DMI_PRODUCT_NAME); 551 product = dmi_get_system_info(DMI_PRODUCT_NAME);
520 552
553 if (!vendor || !version || !product) {
554 pr_err("error getting hardware information\n");
555 return -EINVAL;
556 }
521 557
522 pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); 558 pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER);
523 559
@@ -579,17 +615,26 @@ static int acerhdf_register_platform(void)
579 return err; 615 return err;
580 616
581 acerhdf_dev = platform_device_alloc("acerhdf", -1); 617 acerhdf_dev = platform_device_alloc("acerhdf", -1);
582 platform_device_add(acerhdf_dev); 618 if (!acerhdf_dev) {
619 err = -ENOMEM;
620 goto err_device_alloc;
621 }
622 err = platform_device_add(acerhdf_dev);
623 if (err)
624 goto err_device_add;
583 625
584 return 0; 626 return 0;
627
628err_device_add:
629 platform_device_put(acerhdf_dev);
630err_device_alloc:
631 platform_driver_unregister(&acerhdf_driver);
632 return err;
585} 633}
586 634
587static void acerhdf_unregister_platform(void) 635static void acerhdf_unregister_platform(void)
588{ 636{
589 if (!acerhdf_dev) 637 platform_device_unregister(acerhdf_dev);
590 return;
591
592 platform_device_del(acerhdf_dev);
593 platform_driver_unregister(&acerhdf_driver); 638 platform_driver_unregister(&acerhdf_driver);
594} 639}
595 640
@@ -633,7 +678,7 @@ static int __init acerhdf_init(void)
633 678
634 err = acerhdf_register_platform(); 679 err = acerhdf_register_platform();
635 if (err) 680 if (err)
636 goto err_unreg; 681 goto out_err;
637 682
638 err = acerhdf_register_thermal(); 683 err = acerhdf_register_thermal();
639 if (err) 684 if (err)
@@ -646,7 +691,7 @@ err_unreg:
646 acerhdf_unregister_platform(); 691 acerhdf_unregister_platform();
647 692
648out_err: 693out_err:
649 return -ENODEV; 694 return err;
650} 695}
651 696
652static void __exit acerhdf_exit(void) 697static void __exit acerhdf_exit(void)
@@ -662,11 +707,13 @@ MODULE_DESCRIPTION("Aspire One temperature and fan driver");
662MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); 707MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
663MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); 708MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
664MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); 709MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
710MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
665MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); 711MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
666MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); 712MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
667MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); 713MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
668MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); 714MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
669MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); 715MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:");
716MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:");
670 717
671module_init(acerhdf_init); 718module_init(acerhdf_init);
672module_exit(acerhdf_exit); 719module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index efe8f6388906..b756e07d41b4 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -76,18 +76,18 @@ MODULE_LICENSE("GPL");
76 * So, if something doesn't work as you want, just try other values =) 76 * So, if something doesn't work as you want, just try other values =)
77 */ 77 */
78static uint wapf = 1; 78static uint wapf = 1;
79module_param(wapf, uint, 0644); 79module_param(wapf, uint, 0444);
80MODULE_PARM_DESC(wapf, "WAPF value"); 80MODULE_PARM_DESC(wapf, "WAPF value");
81 81
82static int wlan_status = 1; 82static int wlan_status = 1;
83static int bluetooth_status = 1; 83static int bluetooth_status = 1;
84 84
85module_param(wlan_status, int, 0644); 85module_param(wlan_status, int, 0444);
86MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " 86MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
87 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 87 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
88 "default is 1"); 88 "default is 1");
89 89
90module_param(bluetooth_status, int, 0644); 90module_param(bluetooth_status, int, 0444);
91MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " 91MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
92 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 92 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
93 "default is 1"); 93 "default is 1");
@@ -297,7 +297,7 @@ static int write_acpi_int_ret(acpi_handle handle, const char *method, int val,
297 acpi_status status; 297 acpi_status status;
298 298
299 if (!handle) 299 if (!handle)
300 return 0; 300 return -1;
301 301
302 params.count = 1; 302 params.count = 1;
303 params.pointer = &in_obj; 303 params.pointer = &in_obj;
@@ -796,10 +796,11 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
796 796
797 rv = parse_arg(buf, count, &value); 797 rv = parse_arg(buf, count, &value);
798 if (rv > 0) { 798 if (rv > 0) {
799 if (write_acpi_int(asus->handle, METHOD_LEDD, value)) 799 if (write_acpi_int(asus->handle, METHOD_LEDD, value)) {
800 pr_warning("LED display write failed\n"); 800 pr_warning("LED display write failed\n");
801 else 801 return -ENODEV;
802 asus->ledd_status = (u32) value; 802 }
803 asus->ledd_status = (u32) value;
803 } 804 }
804 return rv; 805 return rv;
805} 806}
@@ -1123,7 +1124,7 @@ static int asus_input_init(struct asus_laptop *asus)
1123 input = input_allocate_device(); 1124 input = input_allocate_device();
1124 if (!input) { 1125 if (!input) {
1125 pr_info("Unable to allocate input device\n"); 1126 pr_info("Unable to allocate input device\n");
1126 return 0; 1127 return -ENOMEM;
1127 } 1128 }
1128 input->name = "Asus Laptop extra buttons"; 1129 input->name = "Asus Laptop extra buttons";
1129 input->phys = ASUS_LAPTOP_FILE "/input0"; 1130 input->phys = ASUS_LAPTOP_FILE "/input0";
@@ -1134,20 +1135,20 @@ static int asus_input_init(struct asus_laptop *asus)
1134 error = sparse_keymap_setup(input, asus_keymap, NULL); 1135 error = sparse_keymap_setup(input, asus_keymap, NULL);
1135 if (error) { 1136 if (error) {
1136 pr_err("Unable to setup input device keymap\n"); 1137 pr_err("Unable to setup input device keymap\n");
1137 goto err_keymap; 1138 goto err_free_dev;
1138 } 1139 }
1139 error = input_register_device(input); 1140 error = input_register_device(input);
1140 if (error) { 1141 if (error) {
1141 pr_info("Unable to register input device\n"); 1142 pr_info("Unable to register input device\n");
1142 goto err_device; 1143 goto err_free_keymap;
1143 } 1144 }
1144 1145
1145 asus->inputdev = input; 1146 asus->inputdev = input;
1146 return 0; 1147 return 0;
1147 1148
1148err_keymap: 1149err_free_keymap:
1149 sparse_keymap_free(input); 1150 sparse_keymap_free(input);
1150err_device: 1151err_free_dev:
1151 input_free_device(input); 1152 input_free_device(input);
1152 return error; 1153 return error;
1153} 1154}
@@ -1397,8 +1398,10 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1397 } 1398 }
1398 } 1399 }
1399 asus->name = kstrdup(string, GFP_KERNEL); 1400 asus->name = kstrdup(string, GFP_KERNEL);
1400 if (!asus->name) 1401 if (!asus->name) {
1402 kfree(buffer.pointer);
1401 return -ENOMEM; 1403 return -ENOMEM;
1404 }
1402 1405
1403 if (*string) 1406 if (*string)
1404 pr_notice(" %s model detected\n", string); 1407 pr_notice(" %s model detected\n", string);
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index 92fd30c9379c..e058c2ba2a15 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -1330,6 +1330,9 @@ static int asus_hotk_get_info(void)
1330 hotk->model = P30; 1330 hotk->model = P30;
1331 printk(KERN_NOTICE 1331 printk(KERN_NOTICE
1332 " Samsung P30 detected, supported\n"); 1332 " Samsung P30 detected, supported\n");
1333 hotk->methods = &model_conf[hotk->model];
1334 kfree(model);
1335 return 0;
1333 } else { 1336 } else {
1334 hotk->model = M2E; 1337 hotk->model = M2E;
1335 printk(KERN_NOTICE " unsupported model %s, trying " 1338 printk(KERN_NOTICE " unsupported model %s, trying "
@@ -1339,8 +1342,6 @@ static int asus_hotk_get_info(void)
1339 kfree(model); 1342 kfree(model);
1340 return -ENODEV; 1343 return -ENODEV;
1341 } 1344 }
1342 hotk->methods = &model_conf[hotk->model];
1343 return AE_OK;
1344 } 1345 }
1345 hotk->methods = &model_conf[hotk->model]; 1346 hotk->methods = &model_conf[hotk->model];
1346 printk(KERN_NOTICE " %s model detected, supported\n", string); 1347 printk(KERN_NOTICE " %s model detected, supported\n", string);
@@ -1374,7 +1375,7 @@ static int asus_hotk_get_info(void)
1374 1375
1375 kfree(model); 1376 kfree(model);
1376 1377
1377 return AE_OK; 1378 return 0;
1378} 1379}
1379 1380
1380static int asus_hotk_check(void) 1381static int asus_hotk_check(void)
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 3bf399fe2bbc..341cbfef93ee 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -208,7 +208,7 @@ static ssize_t cmpc_accel_sensitivity_store(struct device *dev,
208 return strnlen(buf, count); 208 return strnlen(buf, count);
209} 209}
210 210
211struct device_attribute cmpc_accel_sensitivity_attr = { 211static struct device_attribute cmpc_accel_sensitivity_attr = {
212 .attr = { .name = "sensitivity", .mode = 0660 }, 212 .attr = { .name = "sensitivity", .mode = 0660 },
213 .show = cmpc_accel_sensitivity_show, 213 .show = cmpc_accel_sensitivity_show,
214 .store = cmpc_accel_sensitivity_store 214 .store = cmpc_accel_sensitivity_store
@@ -573,16 +573,17 @@ static int cmpc_ipml_add(struct acpi_device *acpi)
573 573
574 ipml->rf = rfkill_alloc("cmpc_rfkill", &acpi->dev, RFKILL_TYPE_WLAN, 574 ipml->rf = rfkill_alloc("cmpc_rfkill", &acpi->dev, RFKILL_TYPE_WLAN,
575 &cmpc_rfkill_ops, acpi->handle); 575 &cmpc_rfkill_ops, acpi->handle);
576 /* rfkill_alloc may fail if RFKILL is disabled. We should still work 576 /*
577 * anyway. */ 577 * If RFKILL is disabled, rfkill_alloc will return ERR_PTR(-ENODEV).
578 if (!IS_ERR(ipml->rf)) { 578 * This is OK, however, since all other uses of the device will not
579 * derefence it.
580 */
581 if (ipml->rf) {
579 retval = rfkill_register(ipml->rf); 582 retval = rfkill_register(ipml->rf);
580 if (retval) { 583 if (retval) {
581 rfkill_destroy(ipml->rf); 584 rfkill_destroy(ipml->rf);
582 ipml->rf = NULL; 585 ipml->rf = NULL;
583 } 586 }
584 } else {
585 ipml->rf = NULL;
586 } 587 }
587 588
588 dev_set_drvdata(&acpi->dev, ipml); 589 dev_set_drvdata(&acpi->dev, ipml);
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 71ff1545a93e..d071ce056322 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -24,17 +24,50 @@
24 */ 24 */
25 25
26/* 26/*
27 * comapl-laptop.c - Compal laptop support. 27 * compal-laptop.c - Compal laptop support.
28 *
29 * This driver exports a few files in /sys/devices/platform/compal-laptop/:
30 * wake_up_XXX Whether or not we listen to such wake up events (rw)
31 *
32 * In addition to these platform device attributes the driver
33 * registers itself in the Linux backlight control, power_supply, rfkill
34 * and hwmon subsystem and is available to userspace under:
35 *
36 * /sys/class/backlight/compal-laptop/
37 * /sys/class/power_supply/compal-laptop/
38 * /sys/class/rfkill/rfkillX/
39 * /sys/class/hwmon/hwmonX/
40 *
41 * Notes on the power_supply battery interface:
42 * - the "minimum" design voltage is *the* design voltage
43 * - the ambient temperature is the average battery temperature
44 * and the value is an educated guess (see commented code below)
28 * 45 *
29 * The driver registers itself with the rfkill subsystem and
30 * the Linux backlight control subsystem.
31 * 46 *
32 * This driver might work on other laptops produced by Compal. If you 47 * This driver might work on other laptops produced by Compal. If you
33 * want to try it you can pass force=1 as argument to the module which 48 * want to try it you can pass force=1 as argument to the module which
34 * will force it to load even when the DMI data doesn't identify the 49 * will force it to load even when the DMI data doesn't identify the
35 * laptop as FL9x. 50 * laptop as compatible.
51 *
52 * Lots of data available at:
53 * http://service1.marasst.com/Compal/JHL90_91/Service%20Manual/
54 * JHL90%20service%20manual-Final-0725.pdf
55 *
56 *
57 *
58 * Support for the Compal JHL90 added by Roald Frederickx
59 * (roald.frederickx@gmail.com):
60 * Driver got large revision. Added functionalities: backlight
61 * power, wake_on_XXX, a hwmon and power_supply interface.
62 *
63 * In case this gets merged into the kernel source: I want to dedicate this
64 * to Kasper Meerts, the awesome guy who showed me Linux and C!
36 */ 65 */
37 66
67/* NOTE: currently the wake_on_XXX, hwmon and power_supply interfaces are
68 * only enabled on a JHL90 board until it is verified that they work on the
69 * other boards too. See the extra_features variable. */
70
38#include <linux/module.h> 71#include <linux/module.h>
39#include <linux/kernel.h> 72#include <linux/kernel.h>
40#include <linux/init.h> 73#include <linux/init.h>
@@ -43,71 +76,296 @@
43#include <linux/backlight.h> 76#include <linux/backlight.h>
44#include <linux/platform_device.h> 77#include <linux/platform_device.h>
45#include <linux/rfkill.h> 78#include <linux/rfkill.h>
79#include <linux/hwmon.h>
80#include <linux/hwmon-sysfs.h>
81#include <linux/power_supply.h>
82#include <linux/fb.h>
83
84
85/* ======= */
86/* Defines */
87/* ======= */
88#define DRIVER_NAME "compal-laptop"
89#define DRIVER_VERSION "0.2.7"
90
91#define BACKLIGHT_LEVEL_ADDR 0xB9
92#define BACKLIGHT_LEVEL_MAX 7
93#define BACKLIGHT_STATE_ADDR 0x59
94#define BACKLIGHT_STATE_ON_DATA 0xE1
95#define BACKLIGHT_STATE_OFF_DATA 0xE2
96
97#define WAKE_UP_ADDR 0xA4
98#define WAKE_UP_PME (1 << 0)
99#define WAKE_UP_MODEM (1 << 1)
100#define WAKE_UP_LAN (1 << 2)
101#define WAKE_UP_WLAN (1 << 4)
102#define WAKE_UP_KEY (1 << 6)
103#define WAKE_UP_MOUSE (1 << 7)
104
105#define WIRELESS_ADDR 0xBB
106#define WIRELESS_WLAN (1 << 0)
107#define WIRELESS_BT (1 << 1)
108#define WIRELESS_WLAN_EXISTS (1 << 2)
109#define WIRELESS_BT_EXISTS (1 << 3)
110#define WIRELESS_KILLSWITCH (1 << 4)
111
112#define PWM_ADDRESS 0x46
113#define PWM_DISABLE_ADDR 0x59
114#define PWM_DISABLE_DATA 0xA5
115#define PWM_ENABLE_ADDR 0x59
116#define PWM_ENABLE_DATA 0xA8
117
118#define FAN_ADDRESS 0x46
119#define FAN_DATA 0x81
120#define FAN_FULL_ON_CMD 0x59 /* Doesn't seem to work. Just */
121#define FAN_FULL_ON_ENABLE 0x76 /* force the pwm signal to its */
122#define FAN_FULL_ON_DISABLE 0x77 /* maximum value instead */
123
124#define TEMP_CPU 0xB0
125#define TEMP_CPU_LOCAL 0xB1
126#define TEMP_CPU_DTS 0xB5
127#define TEMP_NORTHBRIDGE 0xB6
128#define TEMP_VGA 0xB4
129#define TEMP_SKIN 0xB2
130
131#define BAT_MANUFACTURER_NAME_ADDR 0x10
132#define BAT_MANUFACTURER_NAME_LEN 9
133#define BAT_MODEL_NAME_ADDR 0x19
134#define BAT_MODEL_NAME_LEN 6
135#define BAT_SERIAL_NUMBER_ADDR 0xC4
136#define BAT_SERIAL_NUMBER_LEN 5
137#define BAT_CHARGE_NOW 0xC2
138#define BAT_CHARGE_DESIGN 0xCA
139#define BAT_VOLTAGE_NOW 0xC6
140#define BAT_VOLTAGE_DESIGN 0xC8
141#define BAT_CURRENT_NOW 0xD0
142#define BAT_CURRENT_AVG 0xD2
143#define BAT_POWER 0xD4
144#define BAT_CAPACITY 0xCE
145#define BAT_TEMP 0xD6
146#define BAT_TEMP_AVG 0xD7
147#define BAT_STATUS0 0xC1
148#define BAT_STATUS1 0xF0
149#define BAT_STATUS2 0xF1
150#define BAT_STOP_CHARGE1 0xF2
151#define BAT_STOP_CHARGE2 0xF3
152
153#define BAT_S0_DISCHARGE (1 << 0)
154#define BAT_S0_DISCHRG_CRITICAL (1 << 2)
155#define BAT_S0_LOW (1 << 3)
156#define BAT_S0_CHARGING (1 << 1)
157#define BAT_S0_AC (1 << 7)
158#define BAT_S1_EXISTS (1 << 0)
159#define BAT_S1_FULL (1 << 1)
160#define BAT_S1_EMPTY (1 << 2)
161#define BAT_S1_LiION_OR_NiMH (1 << 7)
162#define BAT_S2_LOW_LOW (1 << 0)
163#define BAT_STOP_CHRG1_BAD_CELL (1 << 1)
164#define BAT_STOP_CHRG1_COMM_FAIL (1 << 2)
165#define BAT_STOP_CHRG1_OVERVOLTAGE (1 << 6)
166#define BAT_STOP_CHRG1_OVERTEMPERATURE (1 << 7)
167
168
169/* ======= */
170/* Structs */
171/* ======= */
172struct compal_data{
173 /* Fan control */
174 struct device *hwmon_dev;
175 int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by moterboard */
176 unsigned char curr_pwm;
177
178 /* Power supply */
179 struct power_supply psy;
180 struct power_supply_info psy_info;
181 char bat_model_name[BAT_MODEL_NAME_LEN + 1];
182 char bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN + 1];
183 char bat_serial_number[BAT_SERIAL_NUMBER_LEN + 1];
184};
46 185
47#define COMPAL_DRIVER_VERSION "0.2.6"
48 186
49#define COMPAL_LCD_LEVEL_MAX 8 187/* =============== */
188/* General globals */
189/* =============== */
190static int force;
191module_param(force, bool, 0);
192MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
50 193
51#define COMPAL_EC_COMMAND_WIRELESS 0xBB 194/* Support for the wake_on_XXX, hwmon and power_supply interface. Currently
52#define COMPAL_EC_COMMAND_LCD_LEVEL 0xB9 195 * only gets enabled on a JHL90 board. Might work with the others too */
196static bool extra_features;
197
198/* Nasty stuff. For some reason the fan control is very un-linear. I've
199 * come up with these values by looping through the possible inputs and
200 * watching the output of address 0x4F (do an ec_transaction writing 0x33
201 * into 0x4F and read a few bytes from the output, like so:
202 * u8 writeData = 0x33;
203 * ec_transaction(0x4F, &writeData, 1, buffer, 32, 0);
204 * That address is labled "fan1 table information" in the service manual.
205 * It should be clear which value in 'buffer' changes). This seems to be
206 * related to fan speed. It isn't a proper 'realtime' fan speed value
207 * though, because physically stopping or speeding up the fan doesn't
208 * change it. It might be the average voltage or current of the pwm output.
209 * Nevertheless, it is more fine-grained than the actual RPM reading */
210static const unsigned char pwm_lookup_table[256] = {
211 0, 0, 0, 1, 1, 1, 2, 253, 254, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6,
212 7, 7, 7, 8, 86, 86, 9, 9, 9, 10, 10, 10, 11, 92, 92, 12, 12, 95,
213 13, 66, 66, 14, 14, 98, 15, 15, 15, 16, 16, 67, 17, 17, 72, 18, 70,
214 75, 19, 90, 90, 73, 73, 73, 21, 21, 91, 91, 91, 96, 23, 94, 94, 94,
215 94, 94, 94, 94, 94, 94, 94, 141, 141, 238, 223, 192, 139, 139, 139,
216 139, 139, 142, 142, 142, 142, 142, 78, 78, 78, 78, 78, 76, 76, 76,
217 76, 76, 79, 79, 79, 79, 79, 79, 79, 20, 20, 20, 20, 20, 22, 22, 22,
218 22, 22, 24, 24, 24, 24, 24, 24, 219, 219, 219, 219, 219, 219, 219,
219 219, 27, 27, 188, 188, 28, 28, 28, 29, 186, 186, 186, 186, 186,
220 186, 186, 186, 186, 186, 31, 31, 31, 31, 31, 32, 32, 32, 41, 33,
221 33, 33, 33, 33, 252, 252, 34, 34, 34, 43, 35, 35, 35, 36, 36, 38,
222 206, 206, 206, 206, 206, 206, 206, 206, 206, 37, 37, 37, 46, 46,
223 47, 47, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 48, 48,
224 48, 48, 48, 40, 40, 40, 49, 42, 42, 42, 42, 42, 42, 42, 42, 44,
225 189, 189, 189, 189, 54, 54, 45, 45, 45, 45, 45, 45, 45, 45, 251,
226 191, 199, 199, 199, 199, 199, 215, 215, 215, 215, 187, 187, 187,
227 187, 187, 193, 50
228};
53 229
54#define KILLSWITCH_MASK 0x10
55#define WLAN_MASK 0x01
56#define BT_MASK 0x02
57 230
58static struct rfkill *wifi_rfkill;
59static struct rfkill *bt_rfkill;
60static struct platform_device *compal_device;
61 231
62static int force;
63module_param(force, bool, 0);
64MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
65 232
66/* Hardware access */ 233/* ========================= */
234/* Hardware access functions */
235/* ========================= */
236/* General access */
237static u8 ec_read_u8(u8 addr)
238{
239 u8 value;
240 ec_read(addr, &value);
241 return value;
242}
243
244static s8 ec_read_s8(u8 addr)
245{
246 return (s8)ec_read_u8(addr);
247}
248
249static u16 ec_read_u16(u8 addr)
250{
251 int hi, lo;
252 lo = ec_read_u8(addr);
253 hi = ec_read_u8(addr + 1);
254 return (hi << 8) + lo;
255}
256
257static s16 ec_read_s16(u8 addr)
258{
259 return (s16) ec_read_u16(addr);
260}
67 261
68static int set_lcd_level(int level) 262static void ec_read_sequence(u8 addr, u8 *buf, int len)
69{ 263{
70 if (level < 0 || level >= COMPAL_LCD_LEVEL_MAX) 264 int i;
265 for (i = 0; i < len; i++)
266 ec_read(addr + i, buf + i);
267}
268
269
270/* Backlight access */
271static int set_backlight_level(int level)
272{
273 if (level < 0 || level > BACKLIGHT_LEVEL_MAX)
71 return -EINVAL; 274 return -EINVAL;
72 275
73 ec_write(COMPAL_EC_COMMAND_LCD_LEVEL, level); 276 ec_write(BACKLIGHT_LEVEL_ADDR, level);
74 277
75 return 0; 278 return 1;
279}
280
281static int get_backlight_level(void)
282{
283 return (int) ec_read_u8(BACKLIGHT_LEVEL_ADDR);
76} 284}
77 285
78static int get_lcd_level(void) 286static void set_backlight_state(bool on)
79{ 287{
80 u8 result; 288 u8 data = on ? BACKLIGHT_STATE_ON_DATA : BACKLIGHT_STATE_OFF_DATA;
289 ec_transaction(BACKLIGHT_STATE_ADDR, &data, 1, NULL, 0, 0);
290}
291
292
293/* Fan control access */
294static void pwm_enable_control(void)
295{
296 unsigned char writeData = PWM_ENABLE_DATA;
297 ec_transaction(PWM_ENABLE_ADDR, &writeData, 1, NULL, 0, 0);
298}
299
300static void pwm_disable_control(void)
301{
302 unsigned char writeData = PWM_DISABLE_DATA;
303 ec_transaction(PWM_DISABLE_ADDR, &writeData, 1, NULL, 0, 0);
304}
81 305
82 ec_read(COMPAL_EC_COMMAND_LCD_LEVEL, &result); 306static void set_pwm(int pwm)
307{
308 ec_transaction(PWM_ADDRESS, &pwm_lookup_table[pwm], 1, NULL, 0, 0);
309}
310
311static int get_fan_rpm(void)
312{
313 u8 value, data = FAN_DATA;
314 ec_transaction(FAN_ADDRESS, &data, 1, &value, 1, 0);
315 return 100 * (int)value;
316}
317
318
319
320
321/* =================== */
322/* Interface functions */
323/* =================== */
324
325/* Backlight interface */
326static int bl_get_brightness(struct backlight_device *b)
327{
328 return get_backlight_level();
329}
330
331static int bl_update_status(struct backlight_device *b)
332{
333 int ret = set_backlight_level(b->props.brightness);
334 if (ret)
335 return ret;
83 336
84 return (int) result; 337 set_backlight_state((b->props.power == FB_BLANK_UNBLANK)
338 && !(b->props.state & BL_CORE_SUSPENDED)
339 && !(b->props.state & BL_CORE_FBBLANK));
340 return 0;
85} 341}
86 342
343static const struct backlight_ops compalbl_ops = {
344 .get_brightness = bl_get_brightness,
345 .update_status = bl_update_status,
346};
347
348
349/* Wireless interface */
87static int compal_rfkill_set(void *data, bool blocked) 350static int compal_rfkill_set(void *data, bool blocked)
88{ 351{
89 unsigned long radio = (unsigned long) data; 352 unsigned long radio = (unsigned long) data;
90 u8 result, value; 353 u8 result = ec_read_u8(WIRELESS_ADDR);
91 354 u8 value;
92 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
93 355
94 if (!blocked) 356 if (!blocked)
95 value = (u8) (result | radio); 357 value = (u8) (result | radio);
96 else 358 else
97 value = (u8) (result & ~radio); 359 value = (u8) (result & ~radio);
98 ec_write(COMPAL_EC_COMMAND_WIRELESS, value); 360 ec_write(WIRELESS_ADDR, value);
99 361
100 return 0; 362 return 0;
101} 363}
102 364
103static void compal_rfkill_poll(struct rfkill *rfkill, void *data) 365static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
104{ 366{
105 u8 result; 367 u8 result = ec_read_u8(WIRELESS_ADDR);
106 bool hw_blocked; 368 bool hw_blocked = !(result & WIRELESS_KILLSWITCH);
107
108 ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
109
110 hw_blocked = !(result & KILLSWITCH_MASK);
111 rfkill_set_hw_state(rfkill, hw_blocked); 369 rfkill_set_hw_state(rfkill, hw_blocked);
112} 370}
113 371
@@ -116,80 +374,404 @@ static const struct rfkill_ops compal_rfkill_ops = {
116 .set_block = compal_rfkill_set, 374 .set_block = compal_rfkill_set,
117}; 375};
118 376
119static int setup_rfkill(void) 377
378/* Wake_up interface */
379#define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK) \
380static ssize_t NAME##_show(struct device *dev, \
381 struct device_attribute *attr, char *buf) \
382{ \
383 return sprintf(buf, "%d\n", ((ec_read_u8(ADDR) & MASK) != 0)); \
384} \
385static ssize_t NAME##_store(struct device *dev, \
386 struct device_attribute *attr, const char *buf, size_t count) \
387{ \
388 int state; \
389 u8 old_val = ec_read_u8(ADDR); \
390 if (sscanf(buf, "%d", &state) != 1 || (state < 0 || state > 1)) \
391 return -EINVAL; \
392 ec_write(ADDR, state ? (old_val | MASK) : (old_val & ~MASK)); \
393 return count; \
394}
395
396SIMPLE_MASKED_STORE_SHOW(wake_up_pme, WAKE_UP_ADDR, WAKE_UP_PME)
397SIMPLE_MASKED_STORE_SHOW(wake_up_modem, WAKE_UP_ADDR, WAKE_UP_MODEM)
398SIMPLE_MASKED_STORE_SHOW(wake_up_lan, WAKE_UP_ADDR, WAKE_UP_LAN)
399SIMPLE_MASKED_STORE_SHOW(wake_up_wlan, WAKE_UP_ADDR, WAKE_UP_WLAN)
400SIMPLE_MASKED_STORE_SHOW(wake_up_key, WAKE_UP_ADDR, WAKE_UP_KEY)
401SIMPLE_MASKED_STORE_SHOW(wake_up_mouse, WAKE_UP_ADDR, WAKE_UP_MOUSE)
402
403
404/* General hwmon interface */
405static ssize_t hwmon_name_show(struct device *dev,
406 struct device_attribute *attr, char *buf)
120{ 407{
121 int ret; 408 return sprintf(buf, "%s\n", DRIVER_NAME);
409}
122 410
123 wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
124 RFKILL_TYPE_WLAN, &compal_rfkill_ops,
125 (void *) WLAN_MASK);
126 if (!wifi_rfkill)
127 return -ENOMEM;
128 411
129 ret = rfkill_register(wifi_rfkill); 412/* Fan control interface */
130 if (ret) 413static ssize_t pwm_enable_show(struct device *dev,
131 goto err_wifi; 414 struct device_attribute *attr, char *buf)
415{
416 struct compal_data *data = dev_get_drvdata(dev);
417 return sprintf(buf, "%d\n", data->pwm_enable);
418}
132 419
133 bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev, 420static ssize_t pwm_enable_store(struct device *dev,
134 RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops, 421 struct device_attribute *attr, const char *buf, size_t count)
135 (void *) BT_MASK); 422{
136 if (!bt_rfkill) { 423 struct compal_data *data = dev_get_drvdata(dev);
137 ret = -ENOMEM; 424 long val;
138 goto err_allocate_bt; 425 int err;
426 err = strict_strtol(buf, 10, &val);
427 if (err)
428 return err;
429 if (val < 0)
430 return -EINVAL;
431
432 data->pwm_enable = val;
433
434 switch (val) {
435 case 0: /* Full speed */
436 pwm_enable_control();
437 set_pwm(255);
438 break;
439 case 1: /* As set by pwm1 */
440 pwm_enable_control();
441 set_pwm(data->curr_pwm);
442 break;
443 default: /* Control by motherboard */
444 pwm_disable_control();
445 break;
139 } 446 }
140 ret = rfkill_register(bt_rfkill);
141 if (ret)
142 goto err_register_bt;
143 447
144 return 0; 448 return count;
449}
145 450
146err_register_bt: 451static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
147 rfkill_destroy(bt_rfkill); 452 char *buf)
453{
454 struct compal_data *data = dev_get_drvdata(dev);
455 return sprintf(buf, "%hhu\n", data->curr_pwm);
456}
148 457
149err_allocate_bt: 458static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
150 rfkill_unregister(wifi_rfkill); 459 const char *buf, size_t count)
460{
461 struct compal_data *data = dev_get_drvdata(dev);
462 long val;
463 int err;
464 err = strict_strtol(buf, 10, &val);
465 if (err)
466 return err;
467 if (val < 0 || val > 255)
468 return -EINVAL;
151 469
152err_wifi: 470 data->curr_pwm = val;
153 rfkill_destroy(wifi_rfkill);
154 471
155 return ret; 472 if (data->pwm_enable != 1)
473 return count;
474 set_pwm(val);
475
476 return count;
156} 477}
157 478
158/* Backlight device stuff */ 479static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
480 char *buf)
481{
482 return sprintf(buf, "%d\n", get_fan_rpm());
483}
159 484
160static int bl_get_brightness(struct backlight_device *b) 485
486/* Temperature interface */
487#define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL) \
488static ssize_t temp_##POSTFIX(struct device *dev, \
489 struct device_attribute *attr, char *buf) \
490{ \
491 return sprintf(buf, "%d\n", 1000 * (int)ec_read_s8(ADDRESS)); \
492} \
493static ssize_t label_##POSTFIX(struct device *dev, \
494 struct device_attribute *attr, char *buf) \
495{ \
496 return sprintf(buf, "%s\n", LABEL); \
497}
498
499/* Labels as in service guide */
500TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu, TEMP_CPU, "CPU_TEMP");
501TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_local, TEMP_CPU_LOCAL, "CPU_TEMP_LOCAL");
502TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_DTS, TEMP_CPU_DTS, "CPU_DTS");
503TEMPERATURE_SHOW_TEMP_AND_LABEL(northbridge,TEMP_NORTHBRIDGE,"NorthBridge");
504TEMPERATURE_SHOW_TEMP_AND_LABEL(vga, TEMP_VGA, "VGA_TEMP");
505TEMPERATURE_SHOW_TEMP_AND_LABEL(SKIN, TEMP_SKIN, "SKIN_TEMP90");
506
507
508/* Power supply interface */
509static int bat_status(void)
510{
511 u8 status0 = ec_read_u8(BAT_STATUS0);
512 u8 status1 = ec_read_u8(BAT_STATUS1);
513
514 if (status0 & BAT_S0_CHARGING)
515 return POWER_SUPPLY_STATUS_CHARGING;
516 if (status0 & BAT_S0_DISCHARGE)
517 return POWER_SUPPLY_STATUS_DISCHARGING;
518 if (status1 & BAT_S1_FULL)
519 return POWER_SUPPLY_STATUS_FULL;
520 return POWER_SUPPLY_STATUS_NOT_CHARGING;
521}
522
523static int bat_health(void)
161{ 524{
162 return get_lcd_level(); 525 u8 status = ec_read_u8(BAT_STOP_CHARGE1);
526
527 if (status & BAT_STOP_CHRG1_OVERTEMPERATURE)
528 return POWER_SUPPLY_HEALTH_OVERHEAT;
529 if (status & BAT_STOP_CHRG1_OVERVOLTAGE)
530 return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
531 if (status & BAT_STOP_CHRG1_BAD_CELL)
532 return POWER_SUPPLY_HEALTH_DEAD;
533 if (status & BAT_STOP_CHRG1_COMM_FAIL)
534 return POWER_SUPPLY_HEALTH_UNKNOWN;
535 return POWER_SUPPLY_HEALTH_GOOD;
163} 536}
164 537
538static int bat_is_present(void)
539{
540 u8 status = ec_read_u8(BAT_STATUS2);
541 return ((status & BAT_S1_EXISTS) != 0);
542}
165 543
166static int bl_update_status(struct backlight_device *b) 544static int bat_technology(void)
167{ 545{
168 return set_lcd_level(b->props.brightness); 546 u8 status = ec_read_u8(BAT_STATUS1);
547
548 if (status & BAT_S1_LiION_OR_NiMH)
549 return POWER_SUPPLY_TECHNOLOGY_LION;
550 return POWER_SUPPLY_TECHNOLOGY_NiMH;
169} 551}
170 552
171static struct backlight_ops compalbl_ops = { 553static int bat_capacity_level(void)
172 .get_brightness = bl_get_brightness, 554{
173 .update_status = bl_update_status, 555 u8 status0 = ec_read_u8(BAT_STATUS0);
174}; 556 u8 status1 = ec_read_u8(BAT_STATUS1);
557 u8 status2 = ec_read_u8(BAT_STATUS2);
558
559 if (status0 & BAT_S0_DISCHRG_CRITICAL
560 || status1 & BAT_S1_EMPTY
561 || status2 & BAT_S2_LOW_LOW)
562 return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
563 if (status0 & BAT_S0_LOW)
564 return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
565 if (status1 & BAT_S1_FULL)
566 return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
567 return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
568}
569
570static int bat_get_property(struct power_supply *psy,
571 enum power_supply_property psp,
572 union power_supply_propval *val)
573{
574 struct compal_data *data;
575 data = container_of(psy, struct compal_data, psy);
576
577 switch (psp) {
578 case POWER_SUPPLY_PROP_STATUS:
579 val->intval = bat_status();
580 break;
581 case POWER_SUPPLY_PROP_HEALTH:
582 val->intval = bat_health();
583 break;
584 case POWER_SUPPLY_PROP_PRESENT:
585 val->intval = bat_is_present();
586 break;
587 case POWER_SUPPLY_PROP_TECHNOLOGY:
588 val->intval = bat_technology();
589 break;
590 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: /* THE design voltage... */
591 val->intval = ec_read_u16(BAT_VOLTAGE_DESIGN) * 1000;
592 break;
593 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
594 val->intval = ec_read_u16(BAT_VOLTAGE_NOW) * 1000;
595 break;
596 case POWER_SUPPLY_PROP_CURRENT_NOW:
597 val->intval = ec_read_s16(BAT_CURRENT_NOW) * 1000;
598 break;
599 case POWER_SUPPLY_PROP_CURRENT_AVG:
600 val->intval = ec_read_s16(BAT_CURRENT_AVG) * 1000;
601 break;
602 case POWER_SUPPLY_PROP_POWER_NOW:
603 val->intval = ec_read_u8(BAT_POWER) * 1000000;
604 break;
605 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
606 val->intval = ec_read_u16(BAT_CHARGE_DESIGN) * 1000;
607 break;
608 case POWER_SUPPLY_PROP_CHARGE_NOW:
609 val->intval = ec_read_u16(BAT_CHARGE_NOW) * 1000;
610 break;
611 case POWER_SUPPLY_PROP_CAPACITY:
612 val->intval = ec_read_u8(BAT_CAPACITY);
613 break;
614 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
615 val->intval = bat_capacity_level();
616 break;
617 /* It smees that BAT_TEMP_AVG is a (2's complement?) value showing
618 * the number of degrees, whereas BAT_TEMP is somewhat more
619 * complicated. It looks like this is a negative nember with a
620 * 100/256 divider and an offset of 222. Both were determined
621 * experimentally by comparing BAT_TEMP and BAT_TEMP_AVG. */
622 case POWER_SUPPLY_PROP_TEMP:
623 val->intval = ((222 - (int)ec_read_u8(BAT_TEMP)) * 1000) >> 8;
624 break;
625 case POWER_SUPPLY_PROP_TEMP_AMBIENT: /* Ambient, Avg, ... same thing */
626 val->intval = ec_read_s8(BAT_TEMP_AVG) * 10;
627 break;
628 /* Neither the model name nor manufacturer name work for me. */
629 case POWER_SUPPLY_PROP_MODEL_NAME:
630 val->strval = data->bat_model_name;
631 break;
632 case POWER_SUPPLY_PROP_MANUFACTURER:
633 val->strval = data->bat_manufacturer_name;
634 break;
635 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
636 val->strval = data->bat_serial_number;
637 break;
638 default:
639 break;
640 }
641 return 0;
642}
175 643
176static struct backlight_device *compalbl_device;
177 644
178 645
646
647
648/* ============== */
649/* Driver Globals */
650/* ============== */
651static DEVICE_ATTR(wake_up_pme,
652 0644, wake_up_pme_show, wake_up_pme_store);
653static DEVICE_ATTR(wake_up_modem,
654 0644, wake_up_modem_show, wake_up_modem_store);
655static DEVICE_ATTR(wake_up_lan,
656 0644, wake_up_lan_show, wake_up_lan_store);
657static DEVICE_ATTR(wake_up_wlan,
658 0644, wake_up_wlan_show, wake_up_wlan_store);
659static DEVICE_ATTR(wake_up_key,
660 0644, wake_up_key_show, wake_up_key_store);
661static DEVICE_ATTR(wake_up_mouse,
662 0644, wake_up_mouse_show, wake_up_mouse_store);
663
664static SENSOR_DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL, 1);
665static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL, 1);
666static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL, 1);
667static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL, 1);
668static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL, 1);
669static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL, 1);
670static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL, 1);
671static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL, 1);
672static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL, 1);
673static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL, 1);
674static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL, 1);
675static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL, 1);
676static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL, 1);
677static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL, 1);
678static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store, 1);
679static SENSOR_DEVICE_ATTR(pwm1_enable,
680 S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store, 0);
681
682static struct attribute *compal_attributes[] = {
683 &dev_attr_wake_up_pme.attr,
684 &dev_attr_wake_up_modem.attr,
685 &dev_attr_wake_up_lan.attr,
686 &dev_attr_wake_up_wlan.attr,
687 &dev_attr_wake_up_key.attr,
688 &dev_attr_wake_up_mouse.attr,
689 /* Maybe put the sensor-stuff in a separate hwmon-driver? That way,
690 * the hwmon sysfs won't be cluttered with the above files. */
691 &sensor_dev_attr_name.dev_attr.attr,
692 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
693 &sensor_dev_attr_pwm1.dev_attr.attr,
694 &sensor_dev_attr_fan1_input.dev_attr.attr,
695 &sensor_dev_attr_temp1_input.dev_attr.attr,
696 &sensor_dev_attr_temp2_input.dev_attr.attr,
697 &sensor_dev_attr_temp3_input.dev_attr.attr,
698 &sensor_dev_attr_temp4_input.dev_attr.attr,
699 &sensor_dev_attr_temp5_input.dev_attr.attr,
700 &sensor_dev_attr_temp6_input.dev_attr.attr,
701 &sensor_dev_attr_temp1_label.dev_attr.attr,
702 &sensor_dev_attr_temp2_label.dev_attr.attr,
703 &sensor_dev_attr_temp3_label.dev_attr.attr,
704 &sensor_dev_attr_temp4_label.dev_attr.attr,
705 &sensor_dev_attr_temp5_label.dev_attr.attr,
706 &sensor_dev_attr_temp6_label.dev_attr.attr,
707 NULL
708};
709
710static struct attribute_group compal_attribute_group = {
711 .attrs = compal_attributes
712};
713
714static int __devinit compal_probe(struct platform_device *);
715static int __devexit compal_remove(struct platform_device *);
179static struct platform_driver compal_driver = { 716static struct platform_driver compal_driver = {
180 .driver = { 717 .driver = {
181 .name = "compal-laptop", 718 .name = DRIVER_NAME,
182 .owner = THIS_MODULE, 719 .owner = THIS_MODULE,
183 } 720 },
721 .probe = compal_probe,
722 .remove = __devexit_p(compal_remove)
184}; 723};
185 724
186/* Initialization */ 725static enum power_supply_property compal_bat_properties[] = {
726 POWER_SUPPLY_PROP_STATUS,
727 POWER_SUPPLY_PROP_HEALTH,
728 POWER_SUPPLY_PROP_PRESENT,
729 POWER_SUPPLY_PROP_TECHNOLOGY,
730 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
731 POWER_SUPPLY_PROP_VOLTAGE_NOW,
732 POWER_SUPPLY_PROP_CURRENT_NOW,
733 POWER_SUPPLY_PROP_CURRENT_AVG,
734 POWER_SUPPLY_PROP_POWER_NOW,
735 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
736 POWER_SUPPLY_PROP_CHARGE_NOW,
737 POWER_SUPPLY_PROP_CAPACITY,
738 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
739 POWER_SUPPLY_PROP_TEMP,
740 POWER_SUPPLY_PROP_TEMP_AMBIENT,
741 POWER_SUPPLY_PROP_MODEL_NAME,
742 POWER_SUPPLY_PROP_MANUFACTURER,
743 POWER_SUPPLY_PROP_SERIAL_NUMBER,
744};
745
746static struct backlight_device *compalbl_device;
747
748static struct platform_device *compal_device;
749
750static struct rfkill *wifi_rfkill;
751static struct rfkill *bt_rfkill;
752
753
754
755
756
757/* =================================== */
758/* Initialization & clean-up functions */
759/* =================================== */
187 760
188static int dmi_check_cb(const struct dmi_system_id *id) 761static int dmi_check_cb(const struct dmi_system_id *id)
189{ 762{
190 printk(KERN_INFO "compal-laptop: Identified laptop model '%s'.\n", 763 printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s'\n",
191 id->ident); 764 id->ident);
765 extra_features = false;
766 return 0;
767}
192 768
769static int dmi_check_cb_extra(const struct dmi_system_id *id)
770{
771 printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s', "
772 "enabling extra features\n",
773 id->ident);
774 extra_features = true;
193 return 0; 775 return 0;
194} 776}
195 777
@@ -274,27 +856,106 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
274 }, 856 },
275 .callback = dmi_check_cb 857 .callback = dmi_check_cb
276 }, 858 },
277 859 {
860 .ident = "JHL90",
861 .matches = {
862 DMI_MATCH(DMI_BOARD_NAME, "JHL90"),
863 DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
864 },
865 .callback = dmi_check_cb_extra
866 },
278 { } 867 { }
279}; 868};
280 869
870static void initialize_power_supply_data(struct compal_data *data)
871{
872 data->psy.name = DRIVER_NAME;
873 data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
874 data->psy.properties = compal_bat_properties;
875 data->psy.num_properties = ARRAY_SIZE(compal_bat_properties);
876 data->psy.get_property = bat_get_property;
877
878 ec_read_sequence(BAT_MANUFACTURER_NAME_ADDR,
879 data->bat_manufacturer_name,
880 BAT_MANUFACTURER_NAME_LEN);
881 data->bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN] = 0;
882
883 ec_read_sequence(BAT_MODEL_NAME_ADDR,
884 data->bat_model_name,
885 BAT_MODEL_NAME_LEN);
886 data->bat_model_name[BAT_MODEL_NAME_LEN] = 0;
887
888 scnprintf(data->bat_serial_number, BAT_SERIAL_NUMBER_LEN + 1, "%d",
889 ec_read_u16(BAT_SERIAL_NUMBER_ADDR));
890}
891
892static void initialize_fan_control_data(struct compal_data *data)
893{
894 data->pwm_enable = 2; /* Keep motherboard in control for now */
895 data->curr_pwm = 255; /* Try not to cause a CPU_on_fire exception
896 if we take over... */
897}
898
899static int setup_rfkill(void)
900{
901 int ret;
902
903 wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
904 RFKILL_TYPE_WLAN, &compal_rfkill_ops,
905 (void *) WIRELESS_WLAN);
906 if (!wifi_rfkill)
907 return -ENOMEM;
908
909 ret = rfkill_register(wifi_rfkill);
910 if (ret)
911 goto err_wifi;
912
913 bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
914 RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
915 (void *) WIRELESS_BT);
916 if (!bt_rfkill) {
917 ret = -ENOMEM;
918 goto err_allocate_bt;
919 }
920 ret = rfkill_register(bt_rfkill);
921 if (ret)
922 goto err_register_bt;
923
924 return 0;
925
926err_register_bt:
927 rfkill_destroy(bt_rfkill);
928
929err_allocate_bt:
930 rfkill_unregister(wifi_rfkill);
931
932err_wifi:
933 rfkill_destroy(wifi_rfkill);
934
935 return ret;
936}
937
281static int __init compal_init(void) 938static int __init compal_init(void)
282{ 939{
283 int ret; 940 int ret;
284 941
285 if (acpi_disabled) 942 if (acpi_disabled) {
943 printk(KERN_ERR DRIVER_NAME": ACPI needs to be enabled for "
944 "this driver to work!\n");
286 return -ENODEV; 945 return -ENODEV;
946 }
287 947
288 if (!force && !dmi_check_system(compal_dmi_table)) 948 if (!force && !dmi_check_system(compal_dmi_table)) {
949 printk(KERN_ERR DRIVER_NAME": Motherboard not recognized (You "
950 "could try the module's force-parameter)");
289 return -ENODEV; 951 return -ENODEV;
290 952 }
291 /* Register backlight stuff */
292 953
293 if (!acpi_video_backlight_support()) { 954 if (!acpi_video_backlight_support()) {
294 struct backlight_properties props; 955 struct backlight_properties props;
295 memset(&props, 0, sizeof(struct backlight_properties)); 956 memset(&props, 0, sizeof(struct backlight_properties));
296 props.max_brightness = COMPAL_LCD_LEVEL_MAX - 1; 957 props.max_brightness = BACKLIGHT_LEVEL_MAX;
297 compalbl_device = backlight_device_register("compal-laptop", 958 compalbl_device = backlight_device_register(DRIVER_NAME,
298 NULL, NULL, 959 NULL, NULL,
299 &compalbl_ops, 960 &compalbl_ops,
300 &props); 961 &props);
@@ -304,67 +965,122 @@ static int __init compal_init(void)
304 965
305 ret = platform_driver_register(&compal_driver); 966 ret = platform_driver_register(&compal_driver);
306 if (ret) 967 if (ret)
307 goto fail_backlight; 968 goto err_backlight;
308 969
309 /* Register platform stuff */ 970 compal_device = platform_device_alloc(DRIVER_NAME, -1);
310
311 compal_device = platform_device_alloc("compal-laptop", -1);
312 if (!compal_device) { 971 if (!compal_device) {
313 ret = -ENOMEM; 972 ret = -ENOMEM;
314 goto fail_platform_driver; 973 goto err_platform_driver;
315 } 974 }
316 975
317 ret = platform_device_add(compal_device); 976 ret = platform_device_add(compal_device); /* This calls compal_probe */
318 if (ret) 977 if (ret)
319 goto fail_platform_device; 978 goto err_platform_device;
320 979
321 ret = setup_rfkill(); 980 ret = setup_rfkill();
322 if (ret) 981 if (ret)
323 goto fail_rfkill; 982 goto err_rfkill;
324
325 printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
326 " successfully loaded.\n");
327 983
984 printk(KERN_INFO DRIVER_NAME": Driver "DRIVER_VERSION
985 " successfully loaded\n");
328 return 0; 986 return 0;
329 987
330fail_rfkill: 988err_rfkill:
331 platform_device_del(compal_device); 989 platform_device_del(compal_device);
332 990
333fail_platform_device: 991err_platform_device:
334
335 platform_device_put(compal_device); 992 platform_device_put(compal_device);
336 993
337fail_platform_driver: 994err_platform_driver:
338
339 platform_driver_unregister(&compal_driver); 995 platform_driver_unregister(&compal_driver);
340 996
341fail_backlight: 997err_backlight:
342
343 backlight_device_unregister(compalbl_device); 998 backlight_device_unregister(compalbl_device);
344 999
345 return ret; 1000 return ret;
346} 1001}
347 1002
348static void __exit compal_cleanup(void) 1003static int __devinit compal_probe(struct platform_device *pdev)
349{ 1004{
1005 int err;
1006 struct compal_data *data;
1007
1008 if (!extra_features)
1009 return 0;
1010
1011 /* Fan control */
1012 data = kzalloc(sizeof(struct compal_data), GFP_KERNEL);
1013 if (!data)
1014 return -ENOMEM;
1015
1016 initialize_fan_control_data(data);
1017
1018 err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group);
1019 if (err)
1020 return err;
1021
1022 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1023 if (IS_ERR(data->hwmon_dev)) {
1024 err = PTR_ERR(data->hwmon_dev);
1025 sysfs_remove_group(&pdev->dev.kobj,
1026 &compal_attribute_group);
1027 kfree(data);
1028 return err;
1029 }
1030
1031 /* Power supply */
1032 initialize_power_supply_data(data);
1033 power_supply_register(&compal_device->dev, &data->psy);
1034
1035 platform_set_drvdata(pdev, data);
1036
1037 return 0;
1038}
350 1039
1040static void __exit compal_cleanup(void)
1041{
351 platform_device_unregister(compal_device); 1042 platform_device_unregister(compal_device);
352 platform_driver_unregister(&compal_driver); 1043 platform_driver_unregister(&compal_driver);
353 backlight_device_unregister(compalbl_device); 1044 backlight_device_unregister(compalbl_device);
354 rfkill_unregister(wifi_rfkill); 1045 rfkill_unregister(wifi_rfkill);
355 rfkill_destroy(wifi_rfkill);
356 rfkill_unregister(bt_rfkill); 1046 rfkill_unregister(bt_rfkill);
1047 rfkill_destroy(wifi_rfkill);
357 rfkill_destroy(bt_rfkill); 1048 rfkill_destroy(bt_rfkill);
358 1049
359 printk(KERN_INFO "compal-laptop: driver unloaded.\n"); 1050 printk(KERN_INFO DRIVER_NAME": Driver unloaded\n");
360} 1051}
361 1052
1053static int __devexit compal_remove(struct platform_device *pdev)
1054{
1055 struct compal_data *data;
1056
1057 if (!extra_features)
1058 return 0;
1059
1060 printk(KERN_INFO DRIVER_NAME": Unloading: resetting fan control "
1061 "to motherboard\n");
1062 pwm_disable_control();
1063
1064 data = platform_get_drvdata(pdev);
1065 hwmon_device_unregister(data->hwmon_dev);
1066 power_supply_unregister(&data->psy);
1067
1068 platform_set_drvdata(pdev, NULL);
1069 kfree(data);
1070
1071 sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group);
1072
1073 return 0;
1074}
1075
1076
362module_init(compal_init); 1077module_init(compal_init);
363module_exit(compal_cleanup); 1078module_exit(compal_cleanup);
364 1079
365MODULE_AUTHOR("Cezary Jackiewicz"); 1080MODULE_AUTHOR("Cezary Jackiewicz");
1081MODULE_AUTHOR("Roald Frederickx (roald.frederickx@gmail.com)");
366MODULE_DESCRIPTION("Compal Laptop Support"); 1082MODULE_DESCRIPTION("Compal Laptop Support");
367MODULE_VERSION(COMPAL_DRIVER_VERSION); 1083MODULE_VERSION(DRIVER_VERSION);
368MODULE_LICENSE("GPL"); 1084MODULE_LICENSE("GPL");
369 1085
370MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*"); 1086MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*");
@@ -372,6 +1088,7 @@ MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
372MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*"); 1088MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
373MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*"); 1089MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
374MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); 1090MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
1091MODULE_ALIAS("dmi:*:rnJHL90:rvrREFERENCE:*");
375MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*"); 1092MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
376MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*"); 1093MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
377MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*"); 1094MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 661e3ac4d5b1..b41ed5cab3e7 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -83,6 +83,12 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
83 }, 83 },
84 }, 84 },
85 { 85 {
86 .matches = {
87 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
88 DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/
89 },
90 },
91 {
86 .ident = "Dell Computer Corporation", 92 .ident = "Dell Computer Corporation",
87 .matches = { 93 .matches = {
88 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 94 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
@@ -467,7 +473,7 @@ static struct backlight_ops dell_ops = {
467 .update_status = dell_send_intensity, 473 .update_status = dell_send_intensity,
468}; 474};
469 475
470bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, 476static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
471 struct serio *port) 477 struct serio *port)
472{ 478{
473 static bool extended; 479 static bool extended;
@@ -621,4 +627,5 @@ MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
621MODULE_DESCRIPTION("Dell laptop driver"); 627MODULE_DESCRIPTION("Dell laptop driver");
622MODULE_LICENSE("GPL"); 628MODULE_LICENSE("GPL");
623MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); 629MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
630MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*");
624MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*"); 631MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 66f53c3c35e8..08fb70f6d9bf 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -221,7 +221,7 @@ static void dell_wmi_notify(u32 value, void *context)
221 return; 221 return;
222 } 222 }
223 223
224 if (dell_new_hk_type) 224 if (dell_new_hk_type || buffer_entry[1] == 0x0)
225 reported_key = (int)buffer_entry[2]; 225 reported_key = (int)buffer_entry[2];
226 else 226 else
227 reported_key = (int)buffer_entry[1] & 0xffff; 227 reported_key = (int)buffer_entry[1] & 0xffff;
@@ -339,13 +339,18 @@ static int __init dell_wmi_init(void)
339 acpi_video = acpi_video_backlight_support(); 339 acpi_video = acpi_video_backlight_support();
340 340
341 err = dell_wmi_input_setup(); 341 err = dell_wmi_input_setup();
342 if (err) 342 if (err) {
343 if (dell_new_hk_type)
344 kfree(dell_wmi_keymap);
343 return err; 345 return err;
346 }
344 347
345 status = wmi_install_notify_handler(DELL_EVENT_GUID, 348 status = wmi_install_notify_handler(DELL_EVENT_GUID,
346 dell_wmi_notify, NULL); 349 dell_wmi_notify, NULL);
347 if (ACPI_FAILURE(status)) { 350 if (ACPI_FAILURE(status)) {
348 input_unregister_device(dell_wmi_input_dev); 351 input_unregister_device(dell_wmi_input_dev);
352 if (dell_new_hk_type)
353 kfree(dell_wmi_keymap);
349 printk(KERN_ERR 354 printk(KERN_ERR
350 "dell-wmi: Unable to register notify handler - %d\n", 355 "dell-wmi: Unable to register notify handler - %d\n",
351 status); 356 status);
@@ -359,6 +364,8 @@ static void __exit dell_wmi_exit(void)
359{ 364{
360 wmi_remove_notify_handler(DELL_EVENT_GUID); 365 wmi_remove_notify_handler(DELL_EVENT_GUID);
361 input_unregister_device(dell_wmi_input_dev); 366 input_unregister_device(dell_wmi_input_dev);
367 if (dell_new_hk_type)
368 kfree(dell_wmi_keymap);
362} 369}
363 370
364module_init(dell_wmi_init); 371module_init(dell_wmi_init);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 0306174ba875..6b8e06206c46 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -53,7 +53,7 @@ MODULE_LICENSE("GPL");
53 53
54static bool hotplug_disabled; 54static bool hotplug_disabled;
55 55
56module_param(hotplug_disabled, bool, 0644); 56module_param(hotplug_disabled, bool, 0444);
57MODULE_PARM_DESC(hotplug_disabled, 57MODULE_PARM_DESC(hotplug_disabled,
58 "Disable hotplug for wireless device. " 58 "Disable hotplug for wireless device. "
59 "If your laptop need that, please report to " 59 "If your laptop need that, please report to "
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index e325aeb37d2e..f44cd2620ff9 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -182,7 +182,7 @@ static enum led_brightness logolamp_get(struct led_classdev *cdev);
182static void logolamp_set(struct led_classdev *cdev, 182static void logolamp_set(struct led_classdev *cdev,
183 enum led_brightness brightness); 183 enum led_brightness brightness);
184 184
185struct led_classdev logolamp_led = { 185static struct led_classdev logolamp_led = {
186 .name = "fujitsu::logolamp", 186 .name = "fujitsu::logolamp",
187 .brightness_get = logolamp_get, 187 .brightness_get = logolamp_get,
188 .brightness_set = logolamp_set 188 .brightness_set = logolamp_set
@@ -192,7 +192,7 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev);
192static void kblamps_set(struct led_classdev *cdev, 192static void kblamps_set(struct led_classdev *cdev,
193 enum led_brightness brightness); 193 enum led_brightness brightness);
194 194
195struct led_classdev kblamps_led = { 195static struct led_classdev kblamps_led = {
196 .name = "fujitsu::kblamps", 196 .name = "fujitsu::kblamps",
197 .brightness_get = kblamps_get, 197 .brightness_get = kblamps_get,
198 .brightness_set = kblamps_set 198 .brightness_set = kblamps_set
@@ -603,7 +603,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
603 dmi_check_cb_common(id); 603 dmi_check_cb_common(id);
604 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 604 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
605 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 605 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
606 return 0; 606 return 1;
607} 607}
608 608
609static int dmi_check_cb_s6420(const struct dmi_system_id *id) 609static int dmi_check_cb_s6420(const struct dmi_system_id *id)
@@ -611,7 +611,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id)
611 dmi_check_cb_common(id); 611 dmi_check_cb_common(id);
612 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 612 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
613 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 613 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
614 return 0; 614 return 1;
615} 615}
616 616
617static int dmi_check_cb_p8010(const struct dmi_system_id *id) 617static int dmi_check_cb_p8010(const struct dmi_system_id *id)
@@ -620,7 +620,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id)
620 fujitsu->keycode1 = KEY_HELP; /* "Support" */ 620 fujitsu->keycode1 = KEY_HELP; /* "Support" */
621 fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ 621 fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */
622 fujitsu->keycode4 = KEY_WWW; /* "Internet" */ 622 fujitsu->keycode4 = KEY_WWW; /* "Internet" */
623 return 0; 623 return 1;
624} 624}
625 625
626static struct dmi_system_id fujitsu_dmi_table[] = { 626static struct dmi_system_id fujitsu_dmi_table[] = {
@@ -725,6 +725,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
725 725
726err_unregister_input_dev: 726err_unregister_input_dev:
727 input_unregister_device(input); 727 input_unregister_device(input);
728 input = NULL;
728err_free_input_dev: 729err_free_input_dev:
729 input_free_device(input); 730 input_free_device(input);
730err_stop: 731err_stop:
@@ -738,8 +739,6 @@ static int acpi_fujitsu_remove(struct acpi_device *device, int type)
738 739
739 input_unregister_device(input); 740 input_unregister_device(input);
740 741
741 input_free_device(input);
742
743 fujitsu->acpi_handle = NULL; 742 fujitsu->acpi_handle = NULL;
744 743
745 return 0; 744 return 0;
@@ -930,6 +929,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
930 929
931err_unregister_input_dev: 930err_unregister_input_dev:
932 input_unregister_device(input); 931 input_unregister_device(input);
932 input = NULL;
933err_free_input_dev: 933err_free_input_dev:
934 input_free_device(input); 934 input_free_device(input);
935err_free_fifo: 935err_free_fifo:
@@ -953,8 +953,6 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
953 953
954 input_unregister_device(input); 954 input_unregister_device(input);
955 955
956 input_free_device(input);
957
958 kfifo_free(&fujitsu_hotkey->fifo); 956 kfifo_free(&fujitsu_hotkey->fifo);
959 957
960 fujitsu_hotkey->acpi_handle = NULL; 958 fujitsu_hotkey->acpi_handle = NULL;
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 51c07a05a7bc..f15516374987 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -29,7 +29,6 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/input.h> 31#include <linux/input.h>
32#include <acpi/acpi_drivers.h>
33#include <linux/platform_device.h> 32#include <linux/platform_device.h>
34#include <linux/acpi.h> 33#include <linux/acpi.h>
35#include <linux/rfkill.h> 34#include <linux/rfkill.h>
@@ -52,12 +51,25 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
52#define HPWMI_WIRELESS_QUERY 0x5 51#define HPWMI_WIRELESS_QUERY 0x5
53#define HPWMI_HOTKEY_QUERY 0xc 52#define HPWMI_HOTKEY_QUERY 0xc
54 53
54#define PREFIX "HP WMI: "
55#define UNIMP "Unimplemented "
56
55enum hp_wmi_radio { 57enum hp_wmi_radio {
56 HPWMI_WIFI = 0, 58 HPWMI_WIFI = 0,
57 HPWMI_BLUETOOTH = 1, 59 HPWMI_BLUETOOTH = 1,
58 HPWMI_WWAN = 2, 60 HPWMI_WWAN = 2,
59}; 61};
60 62
63enum hp_wmi_event_ids {
64 HPWMI_DOCK_EVENT = 1,
65 HPWMI_PARK_HDD = 2,
66 HPWMI_SMART_ADAPTER = 3,
67 HPWMI_BEZEL_BUTTON = 4,
68 HPWMI_WIRELESS = 5,
69 HPWMI_CPU_BATTERY_THROTTLE = 6,
70 HPWMI_LOCK_SWITCH = 7,
71};
72
61static int __devinit hp_wmi_bios_setup(struct platform_device *device); 73static int __devinit hp_wmi_bios_setup(struct platform_device *device);
62static int __exit hp_wmi_bios_remove(struct platform_device *device); 74static int __exit hp_wmi_bios_remove(struct platform_device *device);
63static int hp_wmi_resume_handler(struct device *device); 75static int hp_wmi_resume_handler(struct device *device);
@@ -67,13 +79,12 @@ struct bios_args {
67 u32 command; 79 u32 command;
68 u32 commandtype; 80 u32 commandtype;
69 u32 datasize; 81 u32 datasize;
70 u32 data; 82 char *data;
71}; 83};
72 84
73struct bios_return { 85struct bios_return {
74 u32 sigpass; 86 u32 sigpass;
75 u32 return_code; 87 u32 return_code;
76 u32 value;
77}; 88};
78 89
79struct key_entry { 90struct key_entry {
@@ -88,6 +99,7 @@ static struct key_entry hp_wmi_keymap[] = {
88 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 99 {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
89 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, 100 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
90 {KE_KEY, 0x20e6, KEY_PROG1}, 101 {KE_KEY, 0x20e6, KEY_PROG1},
102 {KE_KEY, 0x20e8, KEY_MEDIA},
91 {KE_KEY, 0x2142, KEY_MEDIA}, 103 {KE_KEY, 0x2142, KEY_MEDIA},
92 {KE_KEY, 0x213b, KEY_INFO}, 104 {KE_KEY, 0x213b, KEY_INFO},
93 {KE_KEY, 0x2169, KEY_DIRECTION}, 105 {KE_KEY, 0x2169, KEY_DIRECTION},
@@ -117,7 +129,27 @@ static struct platform_driver hp_wmi_driver = {
117 .remove = hp_wmi_bios_remove, 129 .remove = hp_wmi_bios_remove,
118}; 130};
119 131
120static int hp_wmi_perform_query(int query, int write, int value) 132/*
133 * hp_wmi_perform_query
134 *
135 * query: The commandtype -> What should be queried
136 * write: The command -> 0 read, 1 write, 3 ODM specific
137 * buffer: Buffer used as input and/or output
138 * buffersize: Size of buffer
139 *
140 * returns zero on success
141 * an HP WMI query specific error code (which is positive)
142 * -EINVAL if the query was not successful at all
143 * -EINVAL if the output buffer size exceeds buffersize
144 *
145 * Note: The buffersize must at least be the maximum of the input and output
146 * size. E.g. Battery info query (0x7) is defined to have 1 byte input
147 * and 128 byte output. The caller would do:
148 * buffer = kzalloc(128, GFP_KERNEL);
149 * ret = hp_wmi_perform_query(0x7, 0, buffer, 128)
150 */
151static int hp_wmi_perform_query(int query, int write, char *buffer,
152 int buffersize)
121{ 153{
122 struct bios_return bios_return; 154 struct bios_return bios_return;
123 acpi_status status; 155 acpi_status status;
@@ -126,8 +158,8 @@ static int hp_wmi_perform_query(int query, int write, int value)
126 .signature = 0x55434553, 158 .signature = 0x55434553,
127 .command = write ? 0x2 : 0x1, 159 .command = write ? 0x2 : 0x1,
128 .commandtype = query, 160 .commandtype = query,
129 .datasize = write ? 0x4 : 0, 161 .datasize = buffersize,
130 .data = value, 162 .data = buffer,
131 }; 163 };
132 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 164 struct acpi_buffer input = { sizeof(struct bios_args), &args };
133 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 165 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -144,54 +176,90 @@ static int hp_wmi_perform_query(int query, int write, int value)
144 } 176 }
145 177
146 bios_return = *((struct bios_return *)obj->buffer.pointer); 178 bios_return = *((struct bios_return *)obj->buffer.pointer);
179
180 if (bios_return.return_code) {
181 printk(KERN_WARNING PREFIX "Query %d returned %d\n", query,
182 bios_return.return_code);
183 kfree(obj);
184 return bios_return.return_code;
185 }
186 if (obj->buffer.length - sizeof(bios_return) > buffersize) {
187 kfree(obj);
188 return -EINVAL;
189 }
190
191 memset(buffer, 0, buffersize);
192 memcpy(buffer,
193 ((char *)obj->buffer.pointer) + sizeof(struct bios_return),
194 obj->buffer.length - sizeof(bios_return));
147 kfree(obj); 195 kfree(obj);
148 if (bios_return.return_code > 0) 196 return 0;
149 return bios_return.return_code * -1;
150 else
151 return bios_return.value;
152} 197}
153 198
154static int hp_wmi_display_state(void) 199static int hp_wmi_display_state(void)
155{ 200{
156 return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0); 201 int state;
202 int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, (char *)&state,
203 sizeof(state));
204 if (ret)
205 return -EINVAL;
206 return state;
157} 207}
158 208
159static int hp_wmi_hddtemp_state(void) 209static int hp_wmi_hddtemp_state(void)
160{ 210{
161 return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0); 211 int state;
212 int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, (char *)&state,
213 sizeof(state));
214 if (ret)
215 return -EINVAL;
216 return state;
162} 217}
163 218
164static int hp_wmi_als_state(void) 219static int hp_wmi_als_state(void)
165{ 220{
166 return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0); 221 int state;
222 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, (char *)&state,
223 sizeof(state));
224 if (ret)
225 return -EINVAL;
226 return state;
167} 227}
168 228
169static int hp_wmi_dock_state(void) 229static int hp_wmi_dock_state(void)
170{ 230{
171 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); 231 int state;
232 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state,
233 sizeof(state));
172 234
173 if (ret < 0) 235 if (ret)
174 return ret; 236 return -EINVAL;
175 237
176 return ret & 0x1; 238 return state & 0x1;
177} 239}
178 240
179static int hp_wmi_tablet_state(void) 241static int hp_wmi_tablet_state(void)
180{ 242{
181 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); 243 int state;
182 244 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state,
183 if (ret < 0) 245 sizeof(state));
246 if (ret)
184 return ret; 247 return ret;
185 248
186 return (ret & 0x4) ? 1 : 0; 249 return (state & 0x4) ? 1 : 0;
187} 250}
188 251
189static int hp_wmi_set_block(void *data, bool blocked) 252static int hp_wmi_set_block(void *data, bool blocked)
190{ 253{
191 enum hp_wmi_radio r = (enum hp_wmi_radio) data; 254 enum hp_wmi_radio r = (enum hp_wmi_radio) data;
192 int query = BIT(r + 8) | ((!blocked) << r); 255 int query = BIT(r + 8) | ((!blocked) << r);
256 int ret;
193 257
194 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 258 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
259 (char *)&query, sizeof(query));
260 if (ret)
261 return -EINVAL;
262 return 0;
195} 263}
196 264
197static const struct rfkill_ops hp_wmi_rfkill_ops = { 265static const struct rfkill_ops hp_wmi_rfkill_ops = {
@@ -200,8 +268,13 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
200 268
201static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 269static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
202{ 270{
203 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 271 int wireless;
204 int mask = 0x200 << (r * 8); 272 int mask;
273 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
274 (char *)&wireless, sizeof(wireless));
275 /* TBD: Pass error */
276
277 mask = 0x200 << (r * 8);
205 278
206 if (wireless & mask) 279 if (wireless & mask)
207 return false; 280 return false;
@@ -211,8 +284,13 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
211 284
212static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 285static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
213{ 286{
214 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 287 int wireless;
215 int mask = 0x800 << (r * 8); 288 int mask;
289 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
290 (char *)&wireless, sizeof(wireless));
291 /* TBD: Pass error */
292
293 mask = 0x800 << (r * 8);
216 294
217 if (wireless & mask) 295 if (wireless & mask)
218 return false; 296 return false;
@@ -269,7 +347,11 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr,
269 const char *buf, size_t count) 347 const char *buf, size_t count)
270{ 348{
271 u32 tmp = simple_strtoul(buf, NULL, 10); 349 u32 tmp = simple_strtoul(buf, NULL, 10);
272 hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp); 350 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, (char *)&tmp,
351 sizeof(tmp));
352 if (ret)
353 return -EINVAL;
354
273 return count; 355 return count;
274} 356}
275 357
@@ -338,47 +420,82 @@ static void hp_wmi_notify(u32 value, void *context)
338 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 420 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
339 static struct key_entry *key; 421 static struct key_entry *key;
340 union acpi_object *obj; 422 union acpi_object *obj;
341 int eventcode; 423 u32 event_id, event_data;
424 int key_code, ret;
425 u32 *location;
342 acpi_status status; 426 acpi_status status;
343 427
344 status = wmi_get_event_data(value, &response); 428 status = wmi_get_event_data(value, &response);
345 if (status != AE_OK) { 429 if (status != AE_OK) {
346 printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); 430 printk(KERN_INFO PREFIX "bad event status 0x%x\n", status);
347 return; 431 return;
348 } 432 }
349 433
350 obj = (union acpi_object *)response.pointer; 434 obj = (union acpi_object *)response.pointer;
351 435
352 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { 436 if (!obj)
353 printk(KERN_INFO "HP WMI: Unknown response received\n"); 437 return;
438 if (obj->type != ACPI_TYPE_BUFFER) {
439 printk(KERN_INFO "hp-wmi: Unknown response received %d\n",
440 obj->type);
354 kfree(obj); 441 kfree(obj);
355 return; 442 return;
356 } 443 }
357 444
358 eventcode = *((u8 *) obj->buffer.pointer); 445 /*
446 * Depending on ACPI version the concatenation of id and event data
447 * inside _WED function will result in a 8 or 16 byte buffer.
448 */
449 location = (u32 *)obj->buffer.pointer;
450 if (obj->buffer.length == 8) {
451 event_id = *location;
452 event_data = *(location + 1);
453 } else if (obj->buffer.length == 16) {
454 event_id = *location;
455 event_data = *(location + 2);
456 } else {
457 printk(KERN_INFO "hp-wmi: Unknown buffer length %d\n",
458 obj->buffer.length);
459 kfree(obj);
460 return;
461 }
359 kfree(obj); 462 kfree(obj);
360 if (eventcode == 0x4) 463
361 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 464 switch (event_id) {
362 0); 465 case HPWMI_DOCK_EVENT:
363 key = hp_wmi_get_entry_by_scancode(eventcode);
364 if (key) {
365 switch (key->type) {
366 case KE_KEY:
367 input_report_key(hp_wmi_input_dev,
368 key->keycode, 1);
369 input_sync(hp_wmi_input_dev);
370 input_report_key(hp_wmi_input_dev,
371 key->keycode, 0);
372 input_sync(hp_wmi_input_dev);
373 break;
374 }
375 } else if (eventcode == 0x1) {
376 input_report_switch(hp_wmi_input_dev, SW_DOCK, 466 input_report_switch(hp_wmi_input_dev, SW_DOCK,
377 hp_wmi_dock_state()); 467 hp_wmi_dock_state());
378 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 468 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
379 hp_wmi_tablet_state()); 469 hp_wmi_tablet_state());
380 input_sync(hp_wmi_input_dev); 470 input_sync(hp_wmi_input_dev);
381 } else if (eventcode == 0x5) { 471 break;
472 case HPWMI_PARK_HDD:
473 break;
474 case HPWMI_SMART_ADAPTER:
475 break;
476 case HPWMI_BEZEL_BUTTON:
477 ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
478 (char *)&key_code,
479 sizeof(key_code));
480 if (ret)
481 break;
482 key = hp_wmi_get_entry_by_scancode(key_code);
483 if (key) {
484 switch (key->type) {
485 case KE_KEY:
486 input_report_key(hp_wmi_input_dev,
487 key->keycode, 1);
488 input_sync(hp_wmi_input_dev);
489 input_report_key(hp_wmi_input_dev,
490 key->keycode, 0);
491 input_sync(hp_wmi_input_dev);
492 break;
493 }
494 } else
495 printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
496 key_code);
497 break;
498 case HPWMI_WIRELESS:
382 if (wifi_rfkill) 499 if (wifi_rfkill)
383 rfkill_set_states(wifi_rfkill, 500 rfkill_set_states(wifi_rfkill,
384 hp_wmi_get_sw_state(HPWMI_WIFI), 501 hp_wmi_get_sw_state(HPWMI_WIFI),
@@ -391,9 +508,18 @@ static void hp_wmi_notify(u32 value, void *context)
391 rfkill_set_states(wwan_rfkill, 508 rfkill_set_states(wwan_rfkill,
392 hp_wmi_get_sw_state(HPWMI_WWAN), 509 hp_wmi_get_sw_state(HPWMI_WWAN),
393 hp_wmi_get_hw_state(HPWMI_WWAN)); 510 hp_wmi_get_hw_state(HPWMI_WWAN));
394 } else 511 break;
395 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 512 case HPWMI_CPU_BATTERY_THROTTLE:
396 eventcode); 513 printk(KERN_INFO PREFIX UNIMP "CPU throttle because of 3 Cell"
514 " battery event detected\n");
515 break;
516 case HPWMI_LOCK_SWITCH:
517 break;
518 default:
519 printk(KERN_INFO PREFIX "Unknown event_id - %d - 0x%x\n",
520 event_id, event_data);
521 break;
522 }
397} 523}
398 524
399static int __init hp_wmi_input_setup(void) 525static int __init hp_wmi_input_setup(void)
@@ -402,6 +528,8 @@ static int __init hp_wmi_input_setup(void)
402 int err; 528 int err;
403 529
404 hp_wmi_input_dev = input_allocate_device(); 530 hp_wmi_input_dev = input_allocate_device();
531 if (!hp_wmi_input_dev)
532 return -ENOMEM;
405 533
406 hp_wmi_input_dev->name = "HP WMI hotkeys"; 534 hp_wmi_input_dev->name = "HP WMI hotkeys";
407 hp_wmi_input_dev->phys = "wmi/input0"; 535 hp_wmi_input_dev->phys = "wmi/input0";
@@ -450,7 +578,12 @@ static void cleanup_sysfs(struct platform_device *device)
450static int __devinit hp_wmi_bios_setup(struct platform_device *device) 578static int __devinit hp_wmi_bios_setup(struct platform_device *device)
451{ 579{
452 int err; 580 int err;
453 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 581 int wireless;
582
583 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, (char *)&wireless,
584 sizeof(wireless));
585 if (err)
586 return err;
454 587
455 err = device_create_file(&device->dev, &dev_attr_display); 588 err = device_create_file(&device->dev, &dev_attr_display);
456 if (err) 589 if (err)
@@ -581,27 +714,51 @@ static int hp_wmi_resume_handler(struct device *device)
581static int __init hp_wmi_init(void) 714static int __init hp_wmi_init(void)
582{ 715{
583 int err; 716 int err;
717 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
718 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
584 719
585 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 720 if (event_capable) {
586 err = wmi_install_notify_handler(HPWMI_EVENT_GUID, 721 err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
587 hp_wmi_notify, NULL); 722 hp_wmi_notify, NULL);
588 if (ACPI_SUCCESS(err)) 723 if (ACPI_FAILURE(err))
589 hp_wmi_input_setup(); 724 return -EINVAL;
725 err = hp_wmi_input_setup();
726 if (err) {
727 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
728 return err;
729 }
590 } 730 }
591 731
592 if (wmi_has_guid(HPWMI_BIOS_GUID)) { 732 if (bios_capable) {
593 err = platform_driver_register(&hp_wmi_driver); 733 err = platform_driver_register(&hp_wmi_driver);
594 if (err) 734 if (err)
595 return 0; 735 goto err_driver_reg;
596 hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1); 736 hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1);
597 if (!hp_wmi_platform_dev) { 737 if (!hp_wmi_platform_dev) {
598 platform_driver_unregister(&hp_wmi_driver); 738 err = -ENOMEM;
599 return 0; 739 goto err_device_alloc;
600 } 740 }
601 platform_device_add(hp_wmi_platform_dev); 741 err = platform_device_add(hp_wmi_platform_dev);
742 if (err)
743 goto err_device_add;
602 } 744 }
603 745
746 if (!bios_capable && !event_capable)
747 return -ENODEV;
748
604 return 0; 749 return 0;
750
751err_device_add:
752 platform_device_put(hp_wmi_platform_dev);
753err_device_alloc:
754 platform_driver_unregister(&hp_wmi_driver);
755err_driver_reg:
756 if (wmi_has_guid(HPWMI_EVENT_GUID)) {
757 input_unregister_device(hp_wmi_input_dev);
758 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
759 }
760
761 return err;
605} 762}
606 763
607static void __exit hp_wmi_exit(void) 764static void __exit hp_wmi_exit(void)
@@ -611,7 +768,7 @@ static void __exit hp_wmi_exit(void)
611 input_unregister_device(hp_wmi_input_dev); 768 input_unregister_device(hp_wmi_input_dev);
612 } 769 }
613 if (hp_wmi_platform_dev) { 770 if (hp_wmi_platform_dev) {
614 platform_device_del(hp_wmi_platform_dev); 771 platform_device_unregister(hp_wmi_platform_dev);
615 platform_driver_unregister(&hp_wmi_driver); 772 platform_driver_unregister(&hp_wmi_driver);
616 } 773 }
617} 774}
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
new file mode 100644
index 000000000000..afe82e50dfea
--- /dev/null
+++ b/drivers/platform/x86/intel_ips.c
@@ -0,0 +1,1660 @@
1/*
2 * Copyright (c) 2009-2010 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
19 *
20 * Authors:
21 * Jesse Barnes <jbarnes@virtuousgeek.org>
22 */
23
24/*
25 * Some Intel Ibex Peak based platforms support so-called "intelligent
26 * power sharing", which allows the CPU and GPU to cooperate to maximize
27 * performance within a given TDP (thermal design point). This driver
28 * performs the coordination between the CPU and GPU, monitors thermal and
29 * power statistics in the platform, and initializes power monitoring
30 * hardware. It also provides a few tunables to control behavior. Its
31 * primary purpose is to safely allow CPU and GPU turbo modes to be enabled
32 * by tracking power and thermal budget; secondarily it can boost turbo
33 * performance by allocating more power or thermal budget to the CPU or GPU
34 * based on available headroom and activity.
35 *
36 * The basic algorithm is driven by a 5s moving average of tempurature. If
37 * thermal headroom is available, the CPU and/or GPU power clamps may be
38 * adjusted upwards. If we hit the thermal ceiling or a thermal trigger,
39 * we scale back the clamp. Aside from trigger events (when we're critically
40 * close or over our TDP) we don't adjust the clamps more than once every
41 * five seconds.
42 *
43 * The thermal device (device 31, function 6) has a set of registers that
44 * are updated by the ME firmware. The ME should also take the clamp values
45 * written to those registers and write them to the CPU, but we currently
46 * bypass that functionality and write the CPU MSR directly.
47 *
48 * UNSUPPORTED:
49 * - dual MCP configs
50 *
51 * TODO:
52 * - handle CPU hotplug
53 * - provide turbo enable/disable api
54 * - make sure we can write turbo enable/disable reg based on MISC_EN
55 *
56 * Related documents:
57 * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2
58 * - CDI 401376 - Ibex Peak EDS
59 * - ref 26037, 26641 - IPS BIOS spec
60 * - ref 26489 - Nehalem BIOS writer's guide
61 * - ref 26921 - Ibex Peak BIOS Specification
62 */
63
64#include <linux/debugfs.h>
65#include <linux/delay.h>
66#include <linux/interrupt.h>
67#include <linux/kernel.h>
68#include <linux/kthread.h>
69#include <linux/module.h>
70#include <linux/pci.h>
71#include <linux/sched.h>
72#include <linux/seq_file.h>
73#include <linux/string.h>
74#include <linux/tick.h>
75#include <linux/timer.h>
76#include <drm/i915_drm.h>
77#include <asm/msr.h>
78#include <asm/processor.h>
79
80#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
81
82/*
83 * Package level MSRs for monitor/control
84 */
85#define PLATFORM_INFO 0xce
86#define PLATFORM_TDP (1<<29)
87#define PLATFORM_RATIO (1<<28)
88
89#define IA32_MISC_ENABLE 0x1a0
90#define IA32_MISC_TURBO_EN (1ULL<<38)
91
92#define TURBO_POWER_CURRENT_LIMIT 0x1ac
93#define TURBO_TDC_OVR_EN (1UL<<31)
94#define TURBO_TDC_MASK (0x000000007fff0000UL)
95#define TURBO_TDC_SHIFT (16)
96#define TURBO_TDP_OVR_EN (1UL<<15)
97#define TURBO_TDP_MASK (0x0000000000003fffUL)
98
99/*
100 * Core/thread MSRs for monitoring
101 */
102#define IA32_PERF_CTL 0x199
103#define IA32_PERF_TURBO_DIS (1ULL<<32)
104
105/*
106 * Thermal PCI device regs
107 */
108#define THM_CFG_TBAR 0x10
109#define THM_CFG_TBAR_HI 0x14
110
111#define THM_TSIU 0x00
112#define THM_TSE 0x01
113#define TSE_EN 0xb8
114#define THM_TSS 0x02
115#define THM_TSTR 0x03
116#define THM_TSTTP 0x04
117#define THM_TSCO 0x08
118#define THM_TSES 0x0c
119#define THM_TSGPEN 0x0d
120#define TSGPEN_HOT_LOHI (1<<1)
121#define TSGPEN_CRIT_LOHI (1<<2)
122#define THM_TSPC 0x0e
123#define THM_PPEC 0x10
124#define THM_CTA 0x12
125#define THM_PTA 0x14
126#define PTA_SLOPE_MASK (0xff00)
127#define PTA_SLOPE_SHIFT 8
128#define PTA_OFFSET_MASK (0x00ff)
129#define THM_MGTA 0x16
130#define MGTA_SLOPE_MASK (0xff00)
131#define MGTA_SLOPE_SHIFT 8
132#define MGTA_OFFSET_MASK (0x00ff)
133#define THM_TRC 0x1a
134#define TRC_CORE2_EN (1<<15)
135#define TRC_THM_EN (1<<12)
136#define TRC_C6_WAR (1<<8)
137#define TRC_CORE1_EN (1<<7)
138#define TRC_CORE_PWR (1<<6)
139#define TRC_PCH_EN (1<<5)
140#define TRC_MCH_EN (1<<4)
141#define TRC_DIMM4 (1<<3)
142#define TRC_DIMM3 (1<<2)
143#define TRC_DIMM2 (1<<1)
144#define TRC_DIMM1 (1<<0)
145#define THM_TES 0x20
146#define THM_TEN 0x21
147#define TEN_UPDATE_EN 1
148#define THM_PSC 0x24
149#define PSC_NTG (1<<0) /* No GFX turbo support */
150#define PSC_NTPC (1<<1) /* No CPU turbo support */
151#define PSC_PP_DEF (0<<2) /* Perf policy up to driver */
152#define PSP_PP_PC (1<<2) /* BIOS prefers CPU perf */
153#define PSP_PP_BAL (2<<2) /* BIOS wants balanced perf */
154#define PSP_PP_GFX (3<<2) /* BIOS prefers GFX perf */
155#define PSP_PBRT (1<<4) /* BIOS run time support */
156#define THM_CTV1 0x30
157#define CTV_TEMP_ERROR (1<<15)
158#define CTV_TEMP_MASK 0x3f
159#define CTV_
160#define THM_CTV2 0x32
161#define THM_CEC 0x34 /* undocumented power accumulator in joules */
162#define THM_AE 0x3f
163#define THM_HTS 0x50 /* 32 bits */
164#define HTS_PCPL_MASK (0x7fe00000)
165#define HTS_PCPL_SHIFT 21
166#define HTS_GPL_MASK (0x001ff000)
167#define HTS_GPL_SHIFT 12
168#define HTS_PP_MASK (0x00000c00)
169#define HTS_PP_SHIFT 10
170#define HTS_PP_DEF 0
171#define HTS_PP_PROC 1
172#define HTS_PP_BAL 2
173#define HTS_PP_GFX 3
174#define HTS_PCTD_DIS (1<<9)
175#define HTS_GTD_DIS (1<<8)
176#define HTS_PTL_MASK (0x000000fe)
177#define HTS_PTL_SHIFT 1
178#define HTS_NVV (1<<0)
179#define THM_HTSHI 0x54 /* 16 bits */
180#define HTS2_PPL_MASK (0x03ff)
181#define HTS2_PRST_MASK (0x3c00)
182#define HTS2_PRST_SHIFT 10
183#define HTS2_PRST_UNLOADED 0
184#define HTS2_PRST_RUNNING 1
185#define HTS2_PRST_TDISOP 2 /* turbo disabled due to power */
186#define HTS2_PRST_TDISHT 3 /* turbo disabled due to high temp */
187#define HTS2_PRST_TDISUSR 4 /* user disabled turbo */
188#define HTS2_PRST_TDISPLAT 5 /* platform disabled turbo */
189#define HTS2_PRST_TDISPM 6 /* power management disabled turbo */
190#define HTS2_PRST_TDISERR 7 /* some kind of error disabled turbo */
191#define THM_PTL 0x56
192#define THM_MGTV 0x58
193#define TV_MASK 0x000000000000ff00
194#define TV_SHIFT 8
195#define THM_PTV 0x60
196#define PTV_MASK 0x00ff
197#define THM_MMGPC 0x64
198#define THM_MPPC 0x66
199#define THM_MPCPC 0x68
200#define THM_TSPIEN 0x82
201#define TSPIEN_AUX_LOHI (1<<0)
202#define TSPIEN_HOT_LOHI (1<<1)
203#define TSPIEN_CRIT_LOHI (1<<2)
204#define TSPIEN_AUX2_LOHI (1<<3)
205#define THM_TSLOCK 0x83
206#define THM_ATR 0x84
207#define THM_TOF 0x87
208#define THM_STS 0x98
209#define STS_PCPL_MASK (0x7fe00000)
210#define STS_PCPL_SHIFT 21
211#define STS_GPL_MASK (0x001ff000)
212#define STS_GPL_SHIFT 12
213#define STS_PP_MASK (0x00000c00)
214#define STS_PP_SHIFT 10
215#define STS_PP_DEF 0
216#define STS_PP_PROC 1
217#define STS_PP_BAL 2
218#define STS_PP_GFX 3
219#define STS_PCTD_DIS (1<<9)
220#define STS_GTD_DIS (1<<8)
221#define STS_PTL_MASK (0x000000fe)
222#define STS_PTL_SHIFT 1
223#define STS_NVV (1<<0)
224#define THM_SEC 0x9c
225#define SEC_ACK (1<<0)
226#define THM_TC3 0xa4
227#define THM_TC1 0xa8
228#define STS_PPL_MASK (0x0003ff00)
229#define STS_PPL_SHIFT 16
230#define THM_TC2 0xac
231#define THM_DTV 0xb0
232#define THM_ITV 0xd8
233#define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */
234#define ITV_ME_SEQNO_SHIFT (16)
235#define ITV_MCH_TEMP_MASK 0x0000ff00
236#define ITV_MCH_TEMP_SHIFT (8)
237#define ITV_PCH_TEMP_MASK 0x000000ff
238
239#define thm_readb(off) readb(ips->regmap + (off))
240#define thm_readw(off) readw(ips->regmap + (off))
241#define thm_readl(off) readl(ips->regmap + (off))
242#define thm_readq(off) readq(ips->regmap + (off))
243
244#define thm_writeb(off, val) writeb((val), ips->regmap + (off))
245#define thm_writew(off, val) writew((val), ips->regmap + (off))
246#define thm_writel(off, val) writel((val), ips->regmap + (off))
247
248static const int IPS_ADJUST_PERIOD = 5000; /* ms */
249
250/* For initial average collection */
251static const int IPS_SAMPLE_PERIOD = 200; /* ms */
252static const int IPS_SAMPLE_WINDOW = 5000; /* 5s moving window of samples */
253#define IPS_SAMPLE_COUNT (IPS_SAMPLE_WINDOW / IPS_SAMPLE_PERIOD)
254
255/* Per-SKU limits */
256struct ips_mcp_limits {
257 int cpu_family;
258 int cpu_model; /* includes extended model... */
259 int mcp_power_limit; /* mW units */
260 int core_power_limit;
261 int mch_power_limit;
262 int core_temp_limit; /* degrees C */
263 int mch_temp_limit;
264};
265
266/* Max temps are -10 degrees C to avoid PROCHOT# */
267
268struct ips_mcp_limits ips_sv_limits = {
269 .mcp_power_limit = 35000,
270 .core_power_limit = 29000,
271 .mch_power_limit = 20000,
272 .core_temp_limit = 95,
273 .mch_temp_limit = 90
274};
275
276struct ips_mcp_limits ips_lv_limits = {
277 .mcp_power_limit = 25000,
278 .core_power_limit = 21000,
279 .mch_power_limit = 13000,
280 .core_temp_limit = 95,
281 .mch_temp_limit = 90
282};
283
284struct ips_mcp_limits ips_ulv_limits = {
285 .mcp_power_limit = 18000,
286 .core_power_limit = 14000,
287 .mch_power_limit = 11000,
288 .core_temp_limit = 95,
289 .mch_temp_limit = 90
290};
291
292struct ips_driver {
293 struct pci_dev *dev;
294 void *regmap;
295 struct task_struct *monitor;
296 struct task_struct *adjust;
297 struct dentry *debug_root;
298
299 /* Average CPU core temps (all averages in .01 degrees C for precision) */
300 u16 ctv1_avg_temp;
301 u16 ctv2_avg_temp;
302 /* GMCH average */
303 u16 mch_avg_temp;
304 /* Average for the CPU (both cores?) */
305 u16 mcp_avg_temp;
306 /* Average power consumption (in mW) */
307 u32 cpu_avg_power;
308 u32 mch_avg_power;
309
310 /* Offset values */
311 u16 cta_val;
312 u16 pta_val;
313 u16 mgta_val;
314
315 /* Maximums & prefs, protected by turbo status lock */
316 spinlock_t turbo_status_lock;
317 u16 mcp_temp_limit;
318 u16 mcp_power_limit;
319 u16 core_power_limit;
320 u16 mch_power_limit;
321 bool cpu_turbo_enabled;
322 bool __cpu_turbo_on;
323 bool gpu_turbo_enabled;
324 bool __gpu_turbo_on;
325 bool gpu_preferred;
326 bool poll_turbo_status;
327 bool second_cpu;
328 struct ips_mcp_limits *limits;
329
330 /* Optional MCH interfaces for if i915 is in use */
331 unsigned long (*read_mch_val)(void);
332 bool (*gpu_raise)(void);
333 bool (*gpu_lower)(void);
334 bool (*gpu_busy)(void);
335 bool (*gpu_turbo_disable)(void);
336
337 /* For restoration at unload */
338 u64 orig_turbo_limit;
339 u64 orig_turbo_ratios;
340};
341
342/**
343 * ips_cpu_busy - is CPU busy?
344 * @ips: IPS driver struct
345 *
346 * Check CPU for load to see whether we should increase its thermal budget.
347 *
348 * RETURNS:
349 * True if the CPU could use more power, false otherwise.
350 */
351static bool ips_cpu_busy(struct ips_driver *ips)
352{
353 if ((avenrun[0] >> FSHIFT) > 1)
354 return true;
355
356 return false;
357}
358
359/**
360 * ips_cpu_raise - raise CPU power clamp
361 * @ips: IPS driver struct
362 *
363 * Raise the CPU power clamp by %IPS_CPU_STEP, in accordance with TDP for
364 * this platform.
365 *
366 * We do this by adjusting the TURBO_POWER_CURRENT_LIMIT MSR upwards (as
367 * long as we haven't hit the TDP limit for the SKU).
368 */
369static void ips_cpu_raise(struct ips_driver *ips)
370{
371 u64 turbo_override;
372 u16 cur_tdp_limit, new_tdp_limit;
373
374 if (!ips->cpu_turbo_enabled)
375 return;
376
377 rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
378
379 cur_tdp_limit = turbo_override & TURBO_TDP_MASK;
380 new_tdp_limit = cur_tdp_limit + 8; /* 1W increase */
381
382 /* Clamp to SKU TDP limit */
383 if (((new_tdp_limit * 10) / 8) > ips->core_power_limit)
384 new_tdp_limit = cur_tdp_limit;
385
386 thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
387
388 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
389 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
390
391 turbo_override &= ~TURBO_TDP_MASK;
392 turbo_override |= new_tdp_limit;
393
394 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
395}
396
397/**
398 * ips_cpu_lower - lower CPU power clamp
399 * @ips: IPS driver struct
400 *
401 * Lower CPU power clamp b %IPS_CPU_STEP if possible.
402 *
403 * We do this by adjusting the TURBO_POWER_CURRENT_LIMIT MSR down, going
404 * as low as the platform limits will allow (though we could go lower there
405 * wouldn't be much point).
406 */
407static void ips_cpu_lower(struct ips_driver *ips)
408{
409 u64 turbo_override;
410 u16 cur_limit, new_limit;
411
412 rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
413
414 cur_limit = turbo_override & TURBO_TDP_MASK;
415 new_limit = cur_limit - 8; /* 1W decrease */
416
417 /* Clamp to SKU TDP limit */
418 if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK))
419 new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK;
420
421 thm_writew(THM_MPCPC, (new_limit * 10) / 8);
422
423 turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
424 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
425
426 turbo_override &= ~TURBO_TDP_MASK;
427 turbo_override |= new_limit;
428
429 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
430}
431
432/**
433 * do_enable_cpu_turbo - internal turbo enable function
434 * @data: unused
435 *
436 * Internal function for actually updating MSRs. When we enable/disable
437 * turbo, we need to do it on each CPU; this function is the one called
438 * by on_each_cpu() when needed.
439 */
440static void do_enable_cpu_turbo(void *data)
441{
442 u64 perf_ctl;
443
444 rdmsrl(IA32_PERF_CTL, perf_ctl);
445 if (perf_ctl & IA32_PERF_TURBO_DIS) {
446 perf_ctl &= ~IA32_PERF_TURBO_DIS;
447 wrmsrl(IA32_PERF_CTL, perf_ctl);
448 }
449}
450
451/**
452 * ips_enable_cpu_turbo - enable turbo mode on all CPUs
453 * @ips: IPS driver struct
454 *
455 * Enable turbo mode by clearing the disable bit in IA32_PERF_CTL on
456 * all logical threads.
457 */
458static void ips_enable_cpu_turbo(struct ips_driver *ips)
459{
460 /* Already on, no need to mess with MSRs */
461 if (ips->__cpu_turbo_on)
462 return;
463
464 on_each_cpu(do_enable_cpu_turbo, ips, 1);
465
466 ips->__cpu_turbo_on = true;
467}
468
469/**
470 * do_disable_cpu_turbo - internal turbo disable function
471 * @data: unused
472 *
473 * Internal function for actually updating MSRs. When we enable/disable
474 * turbo, we need to do it on each CPU; this function is the one called
475 * by on_each_cpu() when needed.
476 */
477static void do_disable_cpu_turbo(void *data)
478{
479 u64 perf_ctl;
480
481 rdmsrl(IA32_PERF_CTL, perf_ctl);
482 if (!(perf_ctl & IA32_PERF_TURBO_DIS)) {
483 perf_ctl |= IA32_PERF_TURBO_DIS;
484 wrmsrl(IA32_PERF_CTL, perf_ctl);
485 }
486}
487
488/**
489 * ips_disable_cpu_turbo - disable turbo mode on all CPUs
490 * @ips: IPS driver struct
491 *
492 * Disable turbo mode by setting the disable bit in IA32_PERF_CTL on
493 * all logical threads.
494 */
495static void ips_disable_cpu_turbo(struct ips_driver *ips)
496{
497 /* Already off, leave it */
498 if (!ips->__cpu_turbo_on)
499 return;
500
501 on_each_cpu(do_disable_cpu_turbo, ips, 1);
502
503 ips->__cpu_turbo_on = false;
504}
505
506/**
507 * ips_gpu_busy - is GPU busy?
508 * @ips: IPS driver struct
509 *
510 * Check GPU for load to see whether we should increase its thermal budget.
511 * We need to call into the i915 driver in this case.
512 *
513 * RETURNS:
514 * True if the GPU could use more power, false otherwise.
515 */
516static bool ips_gpu_busy(struct ips_driver *ips)
517{
518 if (!ips->gpu_turbo_enabled)
519 return false;
520
521 return ips->gpu_busy();
522}
523
524/**
525 * ips_gpu_raise - raise GPU power clamp
526 * @ips: IPS driver struct
527 *
528 * Raise the GPU frequency/power if possible. We need to call into the
529 * i915 driver in this case.
530 */
531static void ips_gpu_raise(struct ips_driver *ips)
532{
533 if (!ips->gpu_turbo_enabled)
534 return;
535
536 if (!ips->gpu_raise())
537 ips->gpu_turbo_enabled = false;
538
539 return;
540}
541
542/**
543 * ips_gpu_lower - lower GPU power clamp
544 * @ips: IPS driver struct
545 *
546 * Lower GPU frequency/power if possible. Need to call i915.
547 */
548static void ips_gpu_lower(struct ips_driver *ips)
549{
550 if (!ips->gpu_turbo_enabled)
551 return;
552
553 if (!ips->gpu_lower())
554 ips->gpu_turbo_enabled = false;
555
556 return;
557}
558
559/**
560 * ips_enable_gpu_turbo - notify the gfx driver turbo is available
561 * @ips: IPS driver struct
562 *
563 * Call into the graphics driver indicating that it can safely use
564 * turbo mode.
565 */
566static void ips_enable_gpu_turbo(struct ips_driver *ips)
567{
568 if (ips->__gpu_turbo_on)
569 return;
570 ips->__gpu_turbo_on = true;
571}
572
573/**
574 * ips_disable_gpu_turbo - notify the gfx driver to disable turbo mode
575 * @ips: IPS driver struct
576 *
577 * Request that the graphics driver disable turbo mode.
578 */
579static void ips_disable_gpu_turbo(struct ips_driver *ips)
580{
581 /* Avoid calling i915 if turbo is already disabled */
582 if (!ips->__gpu_turbo_on)
583 return;
584
585 if (!ips->gpu_turbo_disable())
586 dev_err(&ips->dev->dev, "failed to disable graphis turbo\n");
587 else
588 ips->__gpu_turbo_on = false;
589}
590
591/**
592 * mcp_exceeded - check whether we're outside our thermal & power limits
593 * @ips: IPS driver struct
594 *
595 * Check whether the MCP is over its thermal or power budget.
596 */
597static bool mcp_exceeded(struct ips_driver *ips)
598{
599 unsigned long flags;
600 bool ret = false;
601
602 spin_lock_irqsave(&ips->turbo_status_lock, flags);
603 if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100))
604 ret = true;
605 if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit)
606 ret = true;
607 spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
608
609 if (ret)
610 dev_info(&ips->dev->dev,
611 "MCP power or thermal limit exceeded\n");
612
613 return ret;
614}
615
616/**
617 * cpu_exceeded - check whether a CPU core is outside its limits
618 * @ips: IPS driver struct
619 * @cpu: CPU number to check
620 *
621 * Check a given CPU's average temp or power is over its limit.
622 */
623static bool cpu_exceeded(struct ips_driver *ips, int cpu)
624{
625 unsigned long flags;
626 int avg;
627 bool ret = false;
628
629 spin_lock_irqsave(&ips->turbo_status_lock, flags);
630 avg = cpu ? ips->ctv2_avg_temp : ips->ctv1_avg_temp;
631 if (avg > (ips->limits->core_temp_limit * 100))
632 ret = true;
633 if (ips->cpu_avg_power > ips->core_power_limit * 100)
634 ret = true;
635 spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
636
637 if (ret)
638 dev_info(&ips->dev->dev,
639 "CPU power or thermal limit exceeded\n");
640
641 return ret;
642}
643
644/**
645 * mch_exceeded - check whether the GPU is over budget
646 * @ips: IPS driver struct
647 *
648 * Check the MCH temp & power against their maximums.
649 */
650static bool mch_exceeded(struct ips_driver *ips)
651{
652 unsigned long flags;
653 bool ret = false;
654
655 spin_lock_irqsave(&ips->turbo_status_lock, flags);
656 if (ips->mch_avg_temp > (ips->limits->mch_temp_limit * 100))
657 ret = true;
658 if (ips->mch_avg_power > ips->mch_power_limit)
659 ret = true;
660 spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
661
662 return ret;
663}
664
665/**
666 * update_turbo_limits - get various limits & settings from regs
667 * @ips: IPS driver struct
668 *
669 * Update the IPS power & temp limits, along with turbo enable flags,
670 * based on latest register contents.
671 *
672 * Used at init time and for runtime BIOS support, which requires polling
673 * the regs for updates (as a result of AC->DC transition for example).
674 *
675 * LOCKING:
676 * Caller must hold turbo_status_lock (outside of init)
677 */
678static void update_turbo_limits(struct ips_driver *ips)
679{
680 u32 hts = thm_readl(THM_HTS);
681
682 ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS);
683 ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
684 ips->core_power_limit = thm_readw(THM_MPCPC);
685 ips->mch_power_limit = thm_readw(THM_MMGPC);
686 ips->mcp_temp_limit = thm_readw(THM_PTL);
687 ips->mcp_power_limit = thm_readw(THM_MPPC);
688
689 /* Ignore BIOS CPU vs GPU pref */
690}
691
692/**
693 * ips_adjust - adjust power clamp based on thermal state
694 * @data: ips driver structure
695 *
696 * Wake up every 5s or so and check whether we should adjust the power clamp.
697 * Check CPU and GPU load to determine which needs adjustment. There are
698 * several things to consider here:
699 * - do we need to adjust up or down?
700 * - is CPU busy?
701 * - is GPU busy?
702 * - is CPU in turbo?
703 * - is GPU in turbo?
704 * - is CPU or GPU preferred? (CPU is default)
705 *
706 * So, given the above, we do the following:
707 * - up (TDP available)
708 * - CPU not busy, GPU not busy - nothing
709 * - CPU busy, GPU not busy - adjust CPU up
710 * - CPU not busy, GPU busy - adjust GPU up
711 * - CPU busy, GPU busy - adjust preferred unit up, taking headroom from
712 * non-preferred unit if necessary
713 * - down (at TDP limit)
714 * - adjust both CPU and GPU down if possible
715 *
716 cpu+ gpu+ cpu+gpu- cpu-gpu+ cpu-gpu-
717cpu < gpu < cpu+gpu+ cpu+ gpu+ nothing
718cpu < gpu >= cpu+gpu-(mcp<) cpu+gpu-(mcp<) gpu- gpu-
719cpu >= gpu < cpu-gpu+(mcp<) cpu- cpu-gpu+(mcp<) cpu-
720cpu >= gpu >= cpu-gpu- cpu-gpu- cpu-gpu- cpu-gpu-
721 *
722 */
723static int ips_adjust(void *data)
724{
725 struct ips_driver *ips = data;
726 unsigned long flags;
727
728 dev_dbg(&ips->dev->dev, "starting ips-adjust thread\n");
729
730 /*
731 * Adjust CPU and GPU clamps every 5s if needed. Doing it more
732 * often isn't recommended due to ME interaction.
733 */
734 do {
735 bool cpu_busy = ips_cpu_busy(ips);
736 bool gpu_busy = ips_gpu_busy(ips);
737
738 spin_lock_irqsave(&ips->turbo_status_lock, flags);
739 if (ips->poll_turbo_status)
740 update_turbo_limits(ips);
741 spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
742
743 /* Update turbo status if necessary */
744 if (ips->cpu_turbo_enabled)
745 ips_enable_cpu_turbo(ips);
746 else
747 ips_disable_cpu_turbo(ips);
748
749 if (ips->gpu_turbo_enabled)
750 ips_enable_gpu_turbo(ips);
751 else
752 ips_disable_gpu_turbo(ips);
753
754 /* We're outside our comfort zone, crank them down */
755 if (mcp_exceeded(ips)) {
756 ips_cpu_lower(ips);
757 ips_gpu_lower(ips);
758 goto sleep;
759 }
760
761 if (!cpu_exceeded(ips, 0) && cpu_busy)
762 ips_cpu_raise(ips);
763 else
764 ips_cpu_lower(ips);
765
766 if (!mch_exceeded(ips) && gpu_busy)
767 ips_gpu_raise(ips);
768 else
769 ips_gpu_lower(ips);
770
771sleep:
772 schedule_timeout_interruptible(msecs_to_jiffies(IPS_ADJUST_PERIOD));
773 } while (!kthread_should_stop());
774
775 dev_dbg(&ips->dev->dev, "ips-adjust thread stopped\n");
776
777 return 0;
778}
779
780/*
781 * Helpers for reading out temp/power values and calculating their
782 * averages for the decision making and monitoring functions.
783 */
784
785static u16 calc_avg_temp(struct ips_driver *ips, u16 *array)
786{
787 u64 total = 0;
788 int i;
789 u16 avg;
790
791 for (i = 0; i < IPS_SAMPLE_COUNT; i++)
792 total += (u64)(array[i] * 100);
793
794 do_div(total, IPS_SAMPLE_COUNT);
795
796 avg = (u16)total;
797
798 return avg;
799}
800
801static u16 read_mgtv(struct ips_driver *ips)
802{
803 u16 ret;
804 u64 slope, offset;
805 u64 val;
806
807 val = thm_readq(THM_MGTV);
808 val = (val & TV_MASK) >> TV_SHIFT;
809
810 slope = offset = thm_readw(THM_MGTA);
811 slope = (slope & MGTA_SLOPE_MASK) >> MGTA_SLOPE_SHIFT;
812 offset = offset & MGTA_OFFSET_MASK;
813
814 ret = ((val * slope + 0x40) >> 7) + offset;
815
816 return 0; /* MCH temp reporting buggy */
817}
818
819static u16 read_ptv(struct ips_driver *ips)
820{
821 u16 val, slope, offset;
822
823 slope = (ips->pta_val & PTA_SLOPE_MASK) >> PTA_SLOPE_SHIFT;
824 offset = ips->pta_val & PTA_OFFSET_MASK;
825
826 val = thm_readw(THM_PTV) & PTV_MASK;
827
828 return val;
829}
830
831static u16 read_ctv(struct ips_driver *ips, int cpu)
832{
833 int reg = cpu ? THM_CTV2 : THM_CTV1;
834 u16 val;
835
836 val = thm_readw(reg);
837 if (!(val & CTV_TEMP_ERROR))
838 val = (val) >> 6; /* discard fractional component */
839 else
840 val = 0;
841
842 return val;
843}
844
845static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period)
846{
847 u32 val;
848 u32 ret;
849
850 /*
851 * CEC is in joules/65535. Take difference over time to
852 * get watts.
853 */
854 val = thm_readl(THM_CEC);
855
856 /* period is in ms and we want mW */
857 ret = (((val - *last) * 1000) / period);
858 ret = (ret * 1000) / 65535;
859 *last = val;
860
861 return ret;
862}
863
864static const u16 temp_decay_factor = 2;
865static u16 update_average_temp(u16 avg, u16 val)
866{
867 u16 ret;
868
869 /* Multiply by 100 for extra precision */
870 ret = (val * 100 / temp_decay_factor) +
871 (((temp_decay_factor - 1) * avg) / temp_decay_factor);
872 return ret;
873}
874
875static const u16 power_decay_factor = 2;
876static u16 update_average_power(u32 avg, u32 val)
877{
878 u32 ret;
879
880 ret = (val / power_decay_factor) +
881 (((power_decay_factor - 1) * avg) / power_decay_factor);
882
883 return ret;
884}
885
886static u32 calc_avg_power(struct ips_driver *ips, u32 *array)
887{
888 u64 total = 0;
889 u32 avg;
890 int i;
891
892 for (i = 0; i < IPS_SAMPLE_COUNT; i++)
893 total += array[i];
894
895 do_div(total, IPS_SAMPLE_COUNT);
896 avg = (u32)total;
897
898 return avg;
899}
900
901static void monitor_timeout(unsigned long arg)
902{
903 wake_up_process((struct task_struct *)arg);
904}
905
906/**
907 * ips_monitor - temp/power monitoring thread
908 * @data: ips driver structure
909 *
910 * This is the main function for the IPS driver. It monitors power and
911 * tempurature in the MCP and adjusts CPU and GPU power clams accordingly.
912 *
913 * We keep a 5s moving average of power consumption and tempurature. Using
914 * that data, along with CPU vs GPU preference, we adjust the power clamps
915 * up or down.
916 */
917static int ips_monitor(void *data)
918{
919 struct ips_driver *ips = data;
920 struct timer_list timer;
921 unsigned long seqno_timestamp, expire, last_msecs, last_sample_period;
922 int i;
923 u32 *cpu_samples, *mchp_samples, old_cpu_power;
924 u16 *mcp_samples, *ctv1_samples, *ctv2_samples, *mch_samples;
925 u8 cur_seqno, last_seqno;
926
927 mcp_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
928 ctv1_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
929 ctv2_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
930 mch_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
931 cpu_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL);
932 mchp_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL);
933 if (!mcp_samples || !ctv1_samples || !ctv2_samples || !mch_samples ||
934 !cpu_samples || !mchp_samples) {
935 dev_err(&ips->dev->dev,
936 "failed to allocate sample array, ips disabled\n");
937 kfree(mcp_samples);
938 kfree(ctv1_samples);
939 kfree(ctv2_samples);
940 kfree(mch_samples);
941 kfree(cpu_samples);
942 kfree(mchp_samples);
943 kthread_stop(ips->adjust);
944 return -ENOMEM;
945 }
946
947 last_seqno = (thm_readl(THM_ITV) & ITV_ME_SEQNO_MASK) >>
948 ITV_ME_SEQNO_SHIFT;
949 seqno_timestamp = get_jiffies_64();
950
951 old_cpu_power = thm_readl(THM_CEC) / 65535;
952 schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
953
954 /* Collect an initial average */
955 for (i = 0; i < IPS_SAMPLE_COUNT; i++) {
956 u32 mchp, cpu_power;
957 u16 val;
958
959 mcp_samples[i] = read_ptv(ips);
960
961 val = read_ctv(ips, 0);
962 ctv1_samples[i] = val;
963
964 val = read_ctv(ips, 1);
965 ctv2_samples[i] = val;
966
967 val = read_mgtv(ips);
968 mch_samples[i] = val;
969
970 cpu_power = get_cpu_power(ips, &old_cpu_power,
971 IPS_SAMPLE_PERIOD);
972 cpu_samples[i] = cpu_power;
973
974 if (ips->read_mch_val) {
975 mchp = ips->read_mch_val();
976 mchp_samples[i] = mchp;
977 }
978
979 schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
980 if (kthread_should_stop())
981 break;
982 }
983
984 ips->mcp_avg_temp = calc_avg_temp(ips, mcp_samples);
985 ips->ctv1_avg_temp = calc_avg_temp(ips, ctv1_samples);
986 ips->ctv2_avg_temp = calc_avg_temp(ips, ctv2_samples);
987 ips->mch_avg_temp = calc_avg_temp(ips, mch_samples);
988 ips->cpu_avg_power = calc_avg_power(ips, cpu_samples);
989 ips->mch_avg_power = calc_avg_power(ips, mchp_samples);
990 kfree(mcp_samples);
991 kfree(ctv1_samples);
992 kfree(ctv2_samples);
993 kfree(mch_samples);
994 kfree(cpu_samples);
995 kfree(mchp_samples);
996
997 /* Start the adjustment thread now that we have data */
998 wake_up_process(ips->adjust);
999
1000 /*
1001 * Ok, now we have an initial avg. From here on out, we track the
1002 * running avg using a decaying average calculation. This allows
1003 * us to reduce the sample frequency if the CPU and GPU are idle.
1004 */
1005 old_cpu_power = thm_readl(THM_CEC);
1006 schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
1007 last_sample_period = IPS_SAMPLE_PERIOD;
1008
1009 setup_deferrable_timer_on_stack(&timer, monitor_timeout,
1010 (unsigned long)current);
1011 do {
1012 u32 cpu_val, mch_val;
1013 u16 val;
1014
1015 /* MCP itself */
1016 val = read_ptv(ips);
1017 ips->mcp_avg_temp = update_average_temp(ips->mcp_avg_temp, val);
1018
1019 /* Processor 0 */
1020 val = read_ctv(ips, 0);
1021 ips->ctv1_avg_temp =
1022 update_average_temp(ips->ctv1_avg_temp, val);
1023 /* Power */
1024 cpu_val = get_cpu_power(ips, &old_cpu_power,
1025 last_sample_period);
1026 ips->cpu_avg_power =
1027 update_average_power(ips->cpu_avg_power, cpu_val);
1028
1029 if (ips->second_cpu) {
1030 /* Processor 1 */
1031 val = read_ctv(ips, 1);
1032 ips->ctv2_avg_temp =
1033 update_average_temp(ips->ctv2_avg_temp, val);
1034 }
1035
1036 /* MCH */
1037 val = read_mgtv(ips);
1038 ips->mch_avg_temp = update_average_temp(ips->mch_avg_temp, val);
1039 /* Power */
1040 if (ips->read_mch_val) {
1041 mch_val = ips->read_mch_val();
1042 ips->mch_avg_power =
1043 update_average_power(ips->mch_avg_power,
1044 mch_val);
1045 }
1046
1047 /*
1048 * Make sure ME is updating thermal regs.
1049 * Note:
1050 * If it's been more than a second since the last update,
1051 * the ME is probably hung.
1052 */
1053 cur_seqno = (thm_readl(THM_ITV) & ITV_ME_SEQNO_MASK) >>
1054 ITV_ME_SEQNO_SHIFT;
1055 if (cur_seqno == last_seqno &&
1056 time_after(jiffies, seqno_timestamp + HZ)) {
1057 dev_warn(&ips->dev->dev, "ME failed to update for more than 1s, likely hung\n");
1058 } else {
1059 seqno_timestamp = get_jiffies_64();
1060 last_seqno = cur_seqno;
1061 }
1062
1063 last_msecs = jiffies_to_msecs(jiffies);
1064 expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD);
1065
1066 __set_current_state(TASK_UNINTERRUPTIBLE);
1067 mod_timer(&timer, expire);
1068 schedule();
1069
1070 /* Calculate actual sample period for power averaging */
1071 last_sample_period = jiffies_to_msecs(jiffies) - last_msecs;
1072 if (!last_sample_period)
1073 last_sample_period = 1;
1074 } while (!kthread_should_stop());
1075
1076 del_timer_sync(&timer);
1077 destroy_timer_on_stack(&timer);
1078
1079 dev_dbg(&ips->dev->dev, "ips-monitor thread stopped\n");
1080
1081 return 0;
1082}
1083
1084#if 0
1085#define THM_DUMPW(reg) \
1086 { \
1087 u16 val = thm_readw(reg); \
1088 dev_dbg(&ips->dev->dev, #reg ": 0x%04x\n", val); \
1089 }
1090#define THM_DUMPL(reg) \
1091 { \
1092 u32 val = thm_readl(reg); \
1093 dev_dbg(&ips->dev->dev, #reg ": 0x%08x\n", val); \
1094 }
1095#define THM_DUMPQ(reg) \
1096 { \
1097 u64 val = thm_readq(reg); \
1098 dev_dbg(&ips->dev->dev, #reg ": 0x%016x\n", val); \
1099 }
1100
1101static void dump_thermal_info(struct ips_driver *ips)
1102{
1103 u16 ptl;
1104
1105 ptl = thm_readw(THM_PTL);
1106 dev_dbg(&ips->dev->dev, "Processor temp limit: %d\n", ptl);
1107
1108 THM_DUMPW(THM_CTA);
1109 THM_DUMPW(THM_TRC);
1110 THM_DUMPW(THM_CTV1);
1111 THM_DUMPL(THM_STS);
1112 THM_DUMPW(THM_PTV);
1113 THM_DUMPQ(THM_MGTV);
1114}
1115#endif
1116
1117/**
1118 * ips_irq_handler - handle temperature triggers and other IPS events
1119 * @irq: irq number
1120 * @arg: unused
1121 *
1122 * Handle temperature limit trigger events, generally by lowering the clamps.
1123 * If we're at a critical limit, we clamp back to the lowest possible value
1124 * to prevent emergency shutdown.
1125 */
1126static irqreturn_t ips_irq_handler(int irq, void *arg)
1127{
1128 struct ips_driver *ips = arg;
1129 u8 tses = thm_readb(THM_TSES);
1130 u8 tes = thm_readb(THM_TES);
1131
1132 if (!tses && !tes)
1133 return IRQ_NONE;
1134
1135 dev_info(&ips->dev->dev, "TSES: 0x%02x\n", tses);
1136 dev_info(&ips->dev->dev, "TES: 0x%02x\n", tes);
1137
1138 /* STS update from EC? */
1139 if (tes & 1) {
1140 u32 sts, tc1;
1141
1142 sts = thm_readl(THM_STS);
1143 tc1 = thm_readl(THM_TC1);
1144
1145 if (sts & STS_NVV) {
1146 spin_lock(&ips->turbo_status_lock);
1147 ips->core_power_limit = (sts & STS_PCPL_MASK) >>
1148 STS_PCPL_SHIFT;
1149 ips->mch_power_limit = (sts & STS_GPL_MASK) >>
1150 STS_GPL_SHIFT;
1151 /* ignore EC CPU vs GPU pref */
1152 ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS);
1153 ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
1154 ips->mcp_temp_limit = (sts & STS_PTL_MASK) >>
1155 STS_PTL_SHIFT;
1156 ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >>
1157 STS_PPL_SHIFT;
1158 spin_unlock(&ips->turbo_status_lock);
1159
1160 thm_writeb(THM_SEC, SEC_ACK);
1161 }
1162 thm_writeb(THM_TES, tes);
1163 }
1164
1165 /* Thermal trip */
1166 if (tses) {
1167 dev_warn(&ips->dev->dev,
1168 "thermal trip occurred, tses: 0x%04x\n", tses);
1169 thm_writeb(THM_TSES, tses);
1170 }
1171
1172 return IRQ_HANDLED;
1173}
1174
1175#ifndef CONFIG_DEBUG_FS
1176static void ips_debugfs_init(struct ips_driver *ips) { return; }
1177static void ips_debugfs_cleanup(struct ips_driver *ips) { return; }
1178#else
1179
1180/* Expose current state and limits in debugfs if possible */
1181
1182struct ips_debugfs_node {
1183 struct ips_driver *ips;
1184 char *name;
1185 int (*show)(struct seq_file *m, void *data);
1186};
1187
1188static int show_cpu_temp(struct seq_file *m, void *data)
1189{
1190 struct ips_driver *ips = m->private;
1191
1192 seq_printf(m, "%d.%02d\n", ips->ctv1_avg_temp / 100,
1193 ips->ctv1_avg_temp % 100);
1194
1195 return 0;
1196}
1197
1198static int show_cpu_power(struct seq_file *m, void *data)
1199{
1200 struct ips_driver *ips = m->private;
1201
1202 seq_printf(m, "%dmW\n", ips->cpu_avg_power);
1203
1204 return 0;
1205}
1206
1207static int show_cpu_clamp(struct seq_file *m, void *data)
1208{
1209 u64 turbo_override;
1210 int tdp, tdc;
1211
1212 rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
1213
1214 tdp = (int)(turbo_override & TURBO_TDP_MASK);
1215 tdc = (int)((turbo_override & TURBO_TDC_MASK) >> TURBO_TDC_SHIFT);
1216
1217 /* Convert to .1W/A units */
1218 tdp = tdp * 10 / 8;
1219 tdc = tdc * 10 / 8;
1220
1221 /* Watts Amperes */
1222 seq_printf(m, "%d.%dW %d.%dA\n", tdp / 10, tdp % 10,
1223 tdc / 10, tdc % 10);
1224
1225 return 0;
1226}
1227
1228static int show_mch_temp(struct seq_file *m, void *data)
1229{
1230 struct ips_driver *ips = m->private;
1231
1232 seq_printf(m, "%d.%02d\n", ips->mch_avg_temp / 100,
1233 ips->mch_avg_temp % 100);
1234
1235 return 0;
1236}
1237
1238static int show_mch_power(struct seq_file *m, void *data)
1239{
1240 struct ips_driver *ips = m->private;
1241
1242 seq_printf(m, "%dmW\n", ips->mch_avg_power);
1243
1244 return 0;
1245}
1246
1247static struct ips_debugfs_node ips_debug_files[] = {
1248 { NULL, "cpu_temp", show_cpu_temp },
1249 { NULL, "cpu_power", show_cpu_power },
1250 { NULL, "cpu_clamp", show_cpu_clamp },
1251 { NULL, "mch_temp", show_mch_temp },
1252 { NULL, "mch_power", show_mch_power },
1253};
1254
1255static int ips_debugfs_open(struct inode *inode, struct file *file)
1256{
1257 struct ips_debugfs_node *node = inode->i_private;
1258
1259 return single_open(file, node->show, node->ips);
1260}
1261
1262static const struct file_operations ips_debugfs_ops = {
1263 .owner = THIS_MODULE,
1264 .open = ips_debugfs_open,
1265 .read = seq_read,
1266 .llseek = seq_lseek,
1267 .release = single_release,
1268};
1269
1270static void ips_debugfs_cleanup(struct ips_driver *ips)
1271{
1272 if (ips->debug_root)
1273 debugfs_remove_recursive(ips->debug_root);
1274 return;
1275}
1276
1277static void ips_debugfs_init(struct ips_driver *ips)
1278{
1279 int i;
1280
1281 ips->debug_root = debugfs_create_dir("ips", NULL);
1282 if (!ips->debug_root) {
1283 dev_err(&ips->dev->dev,
1284 "failed to create debugfs entries: %ld\n",
1285 PTR_ERR(ips->debug_root));
1286 return;
1287 }
1288
1289 for (i = 0; i < ARRAY_SIZE(ips_debug_files); i++) {
1290 struct dentry *ent;
1291 struct ips_debugfs_node *node = &ips_debug_files[i];
1292
1293 node->ips = ips;
1294 ent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1295 ips->debug_root, node,
1296 &ips_debugfs_ops);
1297 if (!ent) {
1298 dev_err(&ips->dev->dev,
1299 "failed to create debug file: %ld\n",
1300 PTR_ERR(ent));
1301 goto err_cleanup;
1302 }
1303 }
1304
1305 return;
1306
1307err_cleanup:
1308 ips_debugfs_cleanup(ips);
1309 return;
1310}
1311#endif /* CONFIG_DEBUG_FS */
1312
1313/**
1314 * ips_detect_cpu - detect whether CPU supports IPS
1315 *
1316 * Walk our list and see if we're on a supported CPU. If we find one,
1317 * return the limits for it.
1318 */
1319static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
1320{
1321 u64 turbo_power, misc_en;
1322 struct ips_mcp_limits *limits = NULL;
1323 u16 tdp;
1324
1325 if (!(boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 37)) {
1326 dev_info(&ips->dev->dev, "Non-IPS CPU detected.\n");
1327 goto out;
1328 }
1329
1330 rdmsrl(IA32_MISC_ENABLE, misc_en);
1331 /*
1332 * If the turbo enable bit isn't set, we shouldn't try to enable/disable
1333 * turbo manually or we'll get an illegal MSR access, even though
1334 * turbo will still be available.
1335 */
1336 if (!(misc_en & IA32_MISC_TURBO_EN))
1337 ; /* add turbo MSR write allowed flag if necessary */
1338
1339 if (strstr(boot_cpu_data.x86_model_id, "CPU M"))
1340 limits = &ips_sv_limits;
1341 else if (strstr(boot_cpu_data.x86_model_id, "CPU L"))
1342 limits = &ips_lv_limits;
1343 else if (strstr(boot_cpu_data.x86_model_id, "CPU U"))
1344 limits = &ips_ulv_limits;
1345 else
1346 dev_info(&ips->dev->dev, "No CPUID match found.\n");
1347
1348 rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_power);
1349 tdp = turbo_power & TURBO_TDP_MASK;
1350
1351 /* Sanity check TDP against CPU */
1352 if (limits->mcp_power_limit != (tdp / 8) * 1000) {
1353 dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n",
1354 tdp / 8, limits->mcp_power_limit / 1000);
1355 }
1356
1357out:
1358 return limits;
1359}
1360
1361/**
1362 * ips_get_i915_syms - try to get GPU control methods from i915 driver
1363 * @ips: IPS driver
1364 *
1365 * The i915 driver exports several interfaces to allow the IPS driver to
1366 * monitor and control graphics turbo mode. If we can find them, we can
1367 * enable graphics turbo, otherwise we must disable it to avoid exceeding
1368 * thermal and power limits in the MCP.
1369 */
1370static bool ips_get_i915_syms(struct ips_driver *ips)
1371{
1372 ips->read_mch_val = symbol_get(i915_read_mch_val);
1373 if (!ips->read_mch_val)
1374 goto out_err;
1375 ips->gpu_raise = symbol_get(i915_gpu_raise);
1376 if (!ips->gpu_raise)
1377 goto out_put_mch;
1378 ips->gpu_lower = symbol_get(i915_gpu_lower);
1379 if (!ips->gpu_lower)
1380 goto out_put_raise;
1381 ips->gpu_busy = symbol_get(i915_gpu_busy);
1382 if (!ips->gpu_busy)
1383 goto out_put_lower;
1384 ips->gpu_turbo_disable = symbol_get(i915_gpu_turbo_disable);
1385 if (!ips->gpu_turbo_disable)
1386 goto out_put_busy;
1387
1388 return true;
1389
1390out_put_busy:
1391 symbol_put(i915_gpu_turbo_disable);
1392out_put_lower:
1393 symbol_put(i915_gpu_lower);
1394out_put_raise:
1395 symbol_put(i915_gpu_raise);
1396out_put_mch:
1397 symbol_put(i915_read_mch_val);
1398out_err:
1399 return false;
1400}
1401
1402static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
1403 { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
1404 PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
1405 { 0, }
1406};
1407
1408MODULE_DEVICE_TABLE(pci, ips_id_table);
1409
1410static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
1411{
1412 u64 platform_info;
1413 struct ips_driver *ips;
1414 u32 hts;
1415 int ret = 0;
1416 u16 htshi, trc, trc_required_mask;
1417 u8 tse;
1418
1419 ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL);
1420 if (!ips)
1421 return -ENOMEM;
1422
1423 pci_set_drvdata(dev, ips);
1424 ips->dev = dev;
1425
1426 ips->limits = ips_detect_cpu(ips);
1427 if (!ips->limits) {
1428 dev_info(&dev->dev, "IPS not supported on this CPU\n");
1429 ret = -ENXIO;
1430 goto error_free;
1431 }
1432
1433 spin_lock_init(&ips->turbo_status_lock);
1434
1435 if (!pci_resource_start(dev, 0)) {
1436 dev_err(&dev->dev, "TBAR not assigned, aborting\n");
1437 ret = -ENXIO;
1438 goto error_free;
1439 }
1440
1441 ret = pci_request_regions(dev, "ips thermal sensor");
1442 if (ret) {
1443 dev_err(&dev->dev, "thermal resource busy, aborting\n");
1444 goto error_free;
1445 }
1446
1447 ret = pci_enable_device(dev);
1448 if (ret) {
1449 dev_err(&dev->dev, "can't enable PCI device, aborting\n");
1450 goto error_free;
1451 }
1452
1453 ips->regmap = ioremap(pci_resource_start(dev, 0),
1454 pci_resource_len(dev, 0));
1455 if (!ips->regmap) {
1456 dev_err(&dev->dev, "failed to map thermal regs, aborting\n");
1457 ret = -EBUSY;
1458 goto error_release;
1459 }
1460
1461 tse = thm_readb(THM_TSE);
1462 if (tse != TSE_EN) {
1463 dev_err(&dev->dev, "thermal device not enabled (0x%02x), aborting\n", tse);
1464 ret = -ENXIO;
1465 goto error_unmap;
1466 }
1467
1468 trc = thm_readw(THM_TRC);
1469 trc_required_mask = TRC_CORE1_EN | TRC_CORE_PWR | TRC_MCH_EN;
1470 if ((trc & trc_required_mask) != trc_required_mask) {
1471 dev_err(&dev->dev, "thermal reporting for required devices not enabled, aborting\n");
1472 ret = -ENXIO;
1473 goto error_unmap;
1474 }
1475
1476 if (trc & TRC_CORE2_EN)
1477 ips->second_cpu = true;
1478
1479 update_turbo_limits(ips);
1480 dev_dbg(&dev->dev, "max cpu power clamp: %dW\n",
1481 ips->mcp_power_limit / 10);
1482 dev_dbg(&dev->dev, "max core power clamp: %dW\n",
1483 ips->core_power_limit / 10);
1484 /* BIOS may update limits at runtime */
1485 if (thm_readl(THM_PSC) & PSP_PBRT)
1486 ips->poll_turbo_status = true;
1487
1488 if (!ips_get_i915_syms(ips)) {
1489 dev_err(&dev->dev, "failed to get i915 symbols, graphics turbo disabled\n");
1490 ips->gpu_turbo_enabled = false;
1491 } else {
1492 dev_dbg(&dev->dev, "graphics turbo enabled\n");
1493 ips->gpu_turbo_enabled = true;
1494 }
1495
1496 /*
1497 * Check PLATFORM_INFO MSR to make sure this chip is
1498 * turbo capable.
1499 */
1500 rdmsrl(PLATFORM_INFO, platform_info);
1501 if (!(platform_info & PLATFORM_TDP)) {
1502 dev_err(&dev->dev, "platform indicates TDP override unavailable, aborting\n");
1503 ret = -ENODEV;
1504 goto error_unmap;
1505 }
1506
1507 /*
1508 * IRQ handler for ME interaction
1509 * Note: don't use MSI here as the PCH has bugs.
1510 */
1511 pci_disable_msi(dev);
1512 ret = request_irq(dev->irq, ips_irq_handler, IRQF_SHARED, "ips",
1513 ips);
1514 if (ret) {
1515 dev_err(&dev->dev, "request irq failed, aborting\n");
1516 goto error_unmap;
1517 }
1518
1519 /* Enable aux, hot & critical interrupts */
1520 thm_writeb(THM_TSPIEN, TSPIEN_AUX2_LOHI | TSPIEN_CRIT_LOHI |
1521 TSPIEN_HOT_LOHI | TSPIEN_AUX_LOHI);
1522 thm_writeb(THM_TEN, TEN_UPDATE_EN);
1523
1524 /* Collect adjustment values */
1525 ips->cta_val = thm_readw(THM_CTA);
1526 ips->pta_val = thm_readw(THM_PTA);
1527 ips->mgta_val = thm_readw(THM_MGTA);
1528
1529 /* Save turbo limits & ratios */
1530 rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit);
1531
1532 ips_enable_cpu_turbo(ips);
1533 ips->cpu_turbo_enabled = true;
1534
1535 /* Set up the work queue and monitor/adjust threads */
1536 ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
1537 if (IS_ERR(ips->monitor)) {
1538 dev_err(&dev->dev,
1539 "failed to create thermal monitor thread, aborting\n");
1540 ret = -ENOMEM;
1541 goto error_free_irq;
1542 }
1543
1544 ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
1545 if (IS_ERR(ips->adjust)) {
1546 dev_err(&dev->dev,
1547 "failed to create thermal adjust thread, aborting\n");
1548 ret = -ENOMEM;
1549 goto error_thread_cleanup;
1550 }
1551
1552 hts = (ips->core_power_limit << HTS_PCPL_SHIFT) |
1553 (ips->mcp_temp_limit << HTS_PTL_SHIFT) | HTS_NVV;
1554 htshi = HTS2_PRST_RUNNING << HTS2_PRST_SHIFT;
1555
1556 thm_writew(THM_HTSHI, htshi);
1557 thm_writel(THM_HTS, hts);
1558
1559 ips_debugfs_init(ips);
1560
1561 dev_info(&dev->dev, "IPS driver initialized, MCP temp limit %d\n",
1562 ips->mcp_temp_limit);
1563 return ret;
1564
1565error_thread_cleanup:
1566 kthread_stop(ips->monitor);
1567error_free_irq:
1568 free_irq(ips->dev->irq, ips);
1569error_unmap:
1570 iounmap(ips->regmap);
1571error_release:
1572 pci_release_regions(dev);
1573error_free:
1574 kfree(ips);
1575 return ret;
1576}
1577
1578static void ips_remove(struct pci_dev *dev)
1579{
1580 struct ips_driver *ips = pci_get_drvdata(dev);
1581 u64 turbo_override;
1582
1583 if (!ips)
1584 return;
1585
1586 ips_debugfs_cleanup(ips);
1587
1588 /* Release i915 driver */
1589 if (ips->read_mch_val)
1590 symbol_put(i915_read_mch_val);
1591 if (ips->gpu_raise)
1592 symbol_put(i915_gpu_raise);
1593 if (ips->gpu_lower)
1594 symbol_put(i915_gpu_lower);
1595 if (ips->gpu_busy)
1596 symbol_put(i915_gpu_busy);
1597 if (ips->gpu_turbo_disable)
1598 symbol_put(i915_gpu_turbo_disable);
1599
1600 rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
1601 turbo_override &= ~(TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN);
1602 wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
1603 wrmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit);
1604
1605 free_irq(ips->dev->irq, ips);
1606 if (ips->adjust)
1607 kthread_stop(ips->adjust);
1608 if (ips->monitor)
1609 kthread_stop(ips->monitor);
1610 iounmap(ips->regmap);
1611 pci_release_regions(dev);
1612 kfree(ips);
1613 dev_dbg(&dev->dev, "IPS driver removed\n");
1614}
1615
1616#ifdef CONFIG_PM
1617static int ips_suspend(struct pci_dev *dev, pm_message_t state)
1618{
1619 return 0;
1620}
1621
1622static int ips_resume(struct pci_dev *dev)
1623{
1624 return 0;
1625}
1626#else
1627#define ips_suspend NULL
1628#define ips_resume NULL
1629#endif /* CONFIG_PM */
1630
1631static void ips_shutdown(struct pci_dev *dev)
1632{
1633}
1634
1635static struct pci_driver ips_pci_driver = {
1636 .name = "intel ips",
1637 .id_table = ips_id_table,
1638 .probe = ips_probe,
1639 .remove = ips_remove,
1640 .suspend = ips_suspend,
1641 .resume = ips_resume,
1642 .shutdown = ips_shutdown,
1643};
1644
1645static int __init ips_init(void)
1646{
1647 return pci_register_driver(&ips_pci_driver);
1648}
1649module_init(ips_init);
1650
1651static void ips_exit(void)
1652{
1653 pci_unregister_driver(&ips_pci_driver);
1654 return;
1655}
1656module_exit(ips_exit);
1657
1658MODULE_LICENSE("GPL");
1659MODULE_AUTHOR("Jesse Barnes <jbarnes@virtuousgeek.org>");
1660MODULE_DESCRIPTION("Intelligent Power Sharing Driver");
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 2f795ce2b939..eacd5da7dd24 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -53,6 +53,8 @@ MODULE_LICENSE("GPL");
53#define MEMORY_ARG_CUR_BANDWIDTH 1 53#define MEMORY_ARG_CUR_BANDWIDTH 1
54#define MEMORY_ARG_MAX_BANDWIDTH 0 54#define MEMORY_ARG_MAX_BANDWIDTH 0
55 55
56static void intel_menlow_unregister_sensor(void);
57
56/* 58/*
57 * GTHS returning 'n' would mean that [0,n-1] states are supported 59 * GTHS returning 'n' would mean that [0,n-1] states are supported
58 * In that case max_cstate would be n-1 60 * In that case max_cstate would be n-1
@@ -406,8 +408,10 @@ static int intel_menlow_add_one_attribute(char *name, int mode, void *show,
406 attr->handle = handle; 408 attr->handle = handle;
407 409
408 result = device_create_file(dev, &attr->attr); 410 result = device_create_file(dev, &attr->attr);
409 if (result) 411 if (result) {
412 kfree(attr);
410 return result; 413 return result;
414 }
411 415
412 mutex_lock(&intel_menlow_attr_lock); 416 mutex_lock(&intel_menlow_attr_lock);
413 list_add_tail(&attr->node, &intel_menlow_attr_list); 417 list_add_tail(&attr->node, &intel_menlow_attr_list);
@@ -431,11 +435,11 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
431 /* _TZ must have the AUX0/1 methods */ 435 /* _TZ must have the AUX0/1 methods */
432 status = acpi_get_handle(handle, GET_AUX0, &dummy); 436 status = acpi_get_handle(handle, GET_AUX0, &dummy);
433 if (ACPI_FAILURE(status)) 437 if (ACPI_FAILURE(status))
434 goto not_found; 438 return (status == AE_NOT_FOUND) ? AE_OK : status;
435 439
436 status = acpi_get_handle(handle, SET_AUX0, &dummy); 440 status = acpi_get_handle(handle, SET_AUX0, &dummy);
437 if (ACPI_FAILURE(status)) 441 if (ACPI_FAILURE(status))
438 goto not_found; 442 return (status == AE_NOT_FOUND) ? AE_OK : status;
439 443
440 result = intel_menlow_add_one_attribute("aux0", 0644, 444 result = intel_menlow_add_one_attribute("aux0", 0644,
441 aux0_show, aux0_store, 445 aux0_show, aux0_store,
@@ -445,17 +449,19 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
445 449
446 status = acpi_get_handle(handle, GET_AUX1, &dummy); 450 status = acpi_get_handle(handle, GET_AUX1, &dummy);
447 if (ACPI_FAILURE(status)) 451 if (ACPI_FAILURE(status))
448 goto not_found; 452 goto aux1_not_found;
449 453
450 status = acpi_get_handle(handle, SET_AUX1, &dummy); 454 status = acpi_get_handle(handle, SET_AUX1, &dummy);
451 if (ACPI_FAILURE(status)) 455 if (ACPI_FAILURE(status))
452 goto not_found; 456 goto aux1_not_found;
453 457
454 result = intel_menlow_add_one_attribute("aux1", 0644, 458 result = intel_menlow_add_one_attribute("aux1", 0644,
455 aux1_show, aux1_store, 459 aux1_show, aux1_store,
456 &thermal->device, handle); 460 &thermal->device, handle);
457 if (result) 461 if (result) {
462 intel_menlow_unregister_sensor();
458 return AE_ERROR; 463 return AE_ERROR;
464 }
459 465
460 /* 466 /*
461 * create the "dabney_enabled" attribute which means the user app 467 * create the "dabney_enabled" attribute which means the user app
@@ -465,14 +471,17 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
465 result = intel_menlow_add_one_attribute("bios_enabled", 0444, 471 result = intel_menlow_add_one_attribute("bios_enabled", 0444,
466 bios_enabled_show, NULL, 472 bios_enabled_show, NULL,
467 &thermal->device, handle); 473 &thermal->device, handle);
468 if (result) 474 if (result) {
475 intel_menlow_unregister_sensor();
469 return AE_ERROR; 476 return AE_ERROR;
477 }
470 478
471 not_found: 479 aux1_not_found:
472 if (status == AE_NOT_FOUND) 480 if (status == AE_NOT_FOUND)
473 return AE_OK; 481 return AE_OK;
474 else 482
475 return status; 483 intel_menlow_unregister_sensor();
484 return status;
476} 485}
477 486
478static void intel_menlow_unregister_sensor(void) 487static void intel_menlow_unregister_sensor(void)
@@ -513,8 +522,10 @@ static int __init intel_menlow_module_init(void)
513 status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT, 522 status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT,
514 ACPI_UINT32_MAX, 523 ACPI_UINT32_MAX,
515 intel_menlow_register_sensor, NULL, NULL, NULL); 524 intel_menlow_register_sensor, NULL, NULL, NULL);
516 if (ACPI_FAILURE(status)) 525 if (ACPI_FAILURE(status)) {
526 acpi_bus_unregister_driver(&intel_menlow_memory_driver);
517 return -ENODEV; 527 return -ENODEV;
528 }
518 529
519 return 0; 530 return 0;
520} 531}
diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c
new file mode 100644
index 000000000000..5cdcff653918
--- /dev/null
+++ b/drivers/platform/x86/intel_pmic_gpio.c
@@ -0,0 +1,340 @@
1/* Moorestown PMIC GPIO (access through IPC) driver
2 * Copyright (c) 2008 - 2009, Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18/* Supports:
19 * Moorestown platform PMIC chip
20 */
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/stddef.h>
27#include <linux/slab.h>
28#include <linux/ioport.h>
29#include <linux/init.h>
30#include <linux/io.h>
31#include <linux/gpio.h>
32#include <linux/interrupt.h>
33#include <asm/intel_scu_ipc.h>
34#include <linux/device.h>
35#include <linux/intel_pmic_gpio.h>
36#include <linux/platform_device.h>
37
38#define DRIVER_NAME "pmic_gpio"
39
40/* register offset that IPC driver should use
41 * 8 GPIO + 8 GPOSW (6 controllable) + 8GPO
42 */
43enum pmic_gpio_register {
44 GPIO0 = 0xE0,
45 GPIO7 = 0xE7,
46 GPIOINT = 0xE8,
47 GPOSWCTL0 = 0xEC,
48 GPOSWCTL5 = 0xF1,
49 GPO = 0xF4,
50};
51
52/* bits definition for GPIO & GPOSW */
53#define GPIO_DRV 0x01
54#define GPIO_DIR 0x02
55#define GPIO_DIN 0x04
56#define GPIO_DOU 0x08
57#define GPIO_INTCTL 0x30
58#define GPIO_DBC 0xc0
59
60#define GPOSW_DRV 0x01
61#define GPOSW_DOU 0x08
62#define GPOSW_RDRV 0x30
63
64
65#define NUM_GPIO 24
66
67struct pmic_gpio_irq {
68 spinlock_t lock;
69 u32 trigger[NUM_GPIO];
70 u32 dirty;
71 struct work_struct work;
72};
73
74
75struct pmic_gpio {
76 struct gpio_chip chip;
77 struct pmic_gpio_irq irqtypes;
78 void *gpiointr;
79 int irq;
80 unsigned irq_base;
81};
82
83static void pmic_program_irqtype(int gpio, int type)
84{
85 if (type & IRQ_TYPE_EDGE_RISING)
86 intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20);
87 else
88 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20);
89
90 if (type & IRQ_TYPE_EDGE_FALLING)
91 intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10);
92 else
93 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10);
94};
95
96static void pmic_irqtype_work(struct work_struct *work)
97{
98 struct pmic_gpio_irq *t =
99 container_of(work, struct pmic_gpio_irq, work);
100 unsigned long flags;
101 int i;
102 u16 type;
103
104 spin_lock_irqsave(&t->lock, flags);
105 /* As we drop the lock, we may need multiple scans if we race the
106 pmic_irq_type function */
107 while (t->dirty) {
108 /*
109 * For each pin that has the dirty bit set send an IPC
110 * message to configure the hardware via the PMIC
111 */
112 for (i = 0; i < NUM_GPIO; i++) {
113 if (!(t->dirty & (1 << i)))
114 continue;
115 t->dirty &= ~(1 << i);
116 /* We can't trust the array entry or dirty
117 once the lock is dropped */
118 type = t->trigger[i];
119 spin_unlock_irqrestore(&t->lock, flags);
120 pmic_program_irqtype(i, type);
121 spin_lock_irqsave(&t->lock, flags);
122 }
123 }
124 spin_unlock_irqrestore(&t->lock, flags);
125}
126
127static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
128{
129 if (offset > 8) {
130 printk(KERN_ERR
131 "%s: only pin 0-7 support input\n", __func__);
132 return -1;/* we only have 8 GPIO can use as input */
133 }
134 return intel_scu_ipc_update_register(GPIO0 + offset,
135 GPIO_DIR, GPIO_DIR);
136}
137
138static int pmic_gpio_direction_output(struct gpio_chip *chip,
139 unsigned offset, int value)
140{
141 int rc = 0;
142
143 if (offset < 8)/* it is GPIO */
144 rc = intel_scu_ipc_update_register(GPIO0 + offset,
145 GPIO_DRV | GPIO_DOU | GPIO_DIR,
146 GPIO_DRV | (value ? GPIO_DOU : 0));
147 else if (offset < 16)/* it is GPOSW */
148 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
149 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
150 GPOSW_DRV | (value ? GPOSW_DOU : 0));
151 else if (offset > 15 && offset < 24)/* it is GPO */
152 rc = intel_scu_ipc_update_register(GPO,
153 1 << (offset - 16),
154 value ? 1 << (offset - 16) : 0);
155 else {
156 printk(KERN_ERR
157 "%s: invalid PMIC GPIO pin %d!\n", __func__, offset);
158 WARN_ON(1);
159 }
160
161 return rc;
162}
163
164static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset)
165{
166 u8 r;
167 int ret;
168
169 /* we only have 8 GPIO pins we can use as input */
170 if (offset > 8)
171 return -EOPNOTSUPP;
172 ret = intel_scu_ipc_ioread8(GPIO0 + offset, &r);
173 if (ret < 0)
174 return ret;
175 return r & GPIO_DIN;
176}
177
178static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
179{
180 if (offset < 8)/* it is GPIO */
181 intel_scu_ipc_update_register(GPIO0 + offset,
182 GPIO_DRV | GPIO_DOU,
183 GPIO_DRV | (value ? GPIO_DOU : 0));
184 else if (offset < 16)/* it is GPOSW */
185 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
186 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
187 GPOSW_DRV | (value ? GPOSW_DOU : 0));
188 else if (offset > 15 && offset < 24) /* it is GPO */
189 intel_scu_ipc_update_register(GPO,
190 1 << (offset - 16),
191 value ? 1 << (offset - 16) : 0);
192}
193
194static int pmic_irq_type(unsigned irq, unsigned type)
195{
196 struct pmic_gpio *pg = get_irq_chip_data(irq);
197 u32 gpio = irq - pg->irq_base;
198 unsigned long flags;
199
200 if (gpio > pg->chip.ngpio)
201 return -EINVAL;
202
203 spin_lock_irqsave(&pg->irqtypes.lock, flags);
204 pg->irqtypes.trigger[gpio] = type;
205 pg->irqtypes.dirty |= (1 << gpio);
206 spin_unlock_irqrestore(&pg->irqtypes.lock, flags);
207 schedule_work(&pg->irqtypes.work);
208 return 0;
209}
210
211
212
213static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
214{
215 struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip);
216
217 return pg->irq_base + offset;
218}
219
220/* the gpiointr register is read-clear, so just do nothing. */
221static void pmic_irq_unmask(unsigned irq)
222{
223};
224
225static void pmic_irq_mask(unsigned irq)
226{
227};
228
229static struct irq_chip pmic_irqchip = {
230 .name = "PMIC-GPIO",
231 .mask = pmic_irq_mask,
232 .unmask = pmic_irq_unmask,
233 .set_type = pmic_irq_type,
234};
235
236static void pmic_irq_handler(unsigned irq, struct irq_desc *desc)
237{
238 struct pmic_gpio *pg = (struct pmic_gpio *)get_irq_data(irq);
239 u8 intsts = *((u8 *)pg->gpiointr + 4);
240 int gpio;
241
242 for (gpio = 0; gpio < 8; gpio++) {
243 if (intsts & (1 << gpio)) {
244 pr_debug("pmic pin %d triggered\n", gpio);
245 generic_handle_irq(pg->irq_base + gpio);
246 }
247 }
248 desc->chip->eoi(irq);
249}
250
251static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
252{
253 struct device *dev = &pdev->dev;
254 int irq = platform_get_irq(pdev, 0);
255 struct intel_pmic_gpio_platform_data *pdata = dev->platform_data;
256
257 struct pmic_gpio *pg;
258 int retval;
259 int i;
260
261 if (irq < 0) {
262 dev_dbg(dev, "no IRQ line\n");
263 return -EINVAL;
264 }
265
266 if (!pdata || !pdata->gpio_base || !pdata->irq_base) {
267 dev_dbg(dev, "incorrect or missing platform data\n");
268 return -EINVAL;
269 }
270
271 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
272 if (!pg)
273 return -ENOMEM;
274
275 dev_set_drvdata(dev, pg);
276
277 pg->irq = irq;
278 /* setting up SRAM mapping for GPIOINT register */
279 pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8);
280 if (!pg->gpiointr) {
281 printk(KERN_ERR "%s: Can not map GPIOINT.\n", __func__);
282 retval = -EINVAL;
283 goto err2;
284 }
285 pg->irq_base = pdata->irq_base;
286 pg->chip.label = "intel_pmic";
287 pg->chip.direction_input = pmic_gpio_direction_input;
288 pg->chip.direction_output = pmic_gpio_direction_output;
289 pg->chip.get = pmic_gpio_get;
290 pg->chip.set = pmic_gpio_set;
291 pg->chip.to_irq = pmic_gpio_to_irq;
292 pg->chip.base = pdata->gpio_base;
293 pg->chip.ngpio = NUM_GPIO;
294 pg->chip.can_sleep = 1;
295 pg->chip.dev = dev;
296
297 INIT_WORK(&pg->irqtypes.work, pmic_irqtype_work);
298 spin_lock_init(&pg->irqtypes.lock);
299
300 pg->chip.dev = dev;
301 retval = gpiochip_add(&pg->chip);
302 if (retval) {
303 printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__);
304 goto err;
305 }
306 set_irq_data(pg->irq, pg);
307 set_irq_chained_handler(pg->irq, pmic_irq_handler);
308 for (i = 0; i < 8; i++) {
309 set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip,
310 handle_simple_irq, "demux");
311 set_irq_chip_data(i + pg->irq_base, pg);
312 }
313 return 0;
314err:
315 iounmap(pg->gpiointr);
316err2:
317 kfree(pg);
318 return retval;
319}
320
321/* at the same time, register a platform driver
322 * this supports the sfi 0.81 fw */
323static struct platform_driver platform_pmic_gpio_driver = {
324 .driver = {
325 .name = DRIVER_NAME,
326 .owner = THIS_MODULE,
327 },
328 .probe = platform_pmic_gpio_probe,
329};
330
331static int __init platform_pmic_gpio_init(void)
332{
333 return platform_driver_register(&platform_pmic_gpio_driver);
334}
335
336subsys_initcall(platform_pmic_gpio_init);
337
338MODULE_AUTHOR("Alek Du <alek.du@intel.com>");
339MODULE_DESCRIPTION("Intel Moorestown PMIC GPIO driver");
340MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/rar_register/rar_register.c b/drivers/platform/x86/intel_rar_register.c
index 618503f422ef..73f8e6d72669 100644
--- a/drivers/staging/rar_register/rar_register.c
+++ b/drivers/platform/x86/intel_rar_register.c
@@ -40,15 +40,12 @@
40 * Initial publish 40 * Initial publish
41 */ 41 */
42 42
43#define DEBUG 1
44
45#include "rar_register.h"
46
47#include <linux/module.h> 43#include <linux/module.h>
48#include <linux/pci.h> 44#include <linux/pci.h>
49#include <linux/spinlock.h> 45#include <linux/spinlock.h>
50#include <linux/device.h> 46#include <linux/device.h>
51#include <linux/kernel.h> 47#include <linux/kernel.h>
48#include <linux/rar_register.h>
52 49
53/* === Lincroft Message Bus Interface === */ 50/* === Lincroft Message Bus Interface === */
54#define LNC_MCR_OFFSET 0xD0 /* Message Control Register */ 51#define LNC_MCR_OFFSET 0xD0 /* Message Control Register */
@@ -155,7 +152,6 @@ static struct rar_device *_rar_to_device(int rar, int *off)
155 return NULL; 152 return NULL;
156} 153}
157 154
158
159/** 155/**
160 * rar_to_device - return the device handling this RAR 156 * rar_to_device - return the device handling this RAR
161 * @rar: RAR number 157 * @rar: RAR number
@@ -496,7 +492,7 @@ EXPORT_SYMBOL(rar_lock);
496 * a driver that do require a valid RAR address. One of those 492 * a driver that do require a valid RAR address. One of those
497 * steps would be to call rar_get_address() 493 * steps would be to call rar_get_address()
498 * 494 *
499 * This function return 0 on success an error code on failure. 495 * This function return 0 on success or an error code on failure.
500 */ 496 */
501int register_rar(int num, int (*callback)(unsigned long data), 497int register_rar(int num, int (*callback)(unsigned long data),
502 unsigned long data) 498 unsigned long data)
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index bb2f1fba637b..943f9084dcb1 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -23,7 +23,7 @@
23#include <linux/pm.h> 23#include <linux/pm.h>
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <asm/setup.h> 26#include <asm/mrst.h>
27#include <asm/intel_scu_ipc.h> 27#include <asm/intel_scu_ipc.h>
28 28
29/* IPC defines the following message types */ 29/* IPC defines the following message types */
@@ -38,10 +38,6 @@
38#define IPC_CMD_PCNTRL_R 1 /* Register read */ 38#define IPC_CMD_PCNTRL_R 1 /* Register read */
39#define IPC_CMD_PCNTRL_M 2 /* Register read-modify-write */ 39#define IPC_CMD_PCNTRL_M 2 /* Register read-modify-write */
40 40
41/* Miscelaneous Command ids */
42#define IPC_CMD_INDIRECT_RD 2 /* 32bit indirect read */
43#define IPC_CMD_INDIRECT_WR 5 /* 32bit indirect write */
44
45/* 41/*
46 * IPC register summary 42 * IPC register summary
47 * 43 *
@@ -62,8 +58,8 @@
62 58
63#define IPC_BASE_ADDR 0xFF11C000 /* IPC1 base register address */ 59#define IPC_BASE_ADDR 0xFF11C000 /* IPC1 base register address */
64#define IPC_MAX_ADDR 0x100 /* Maximum IPC regisers */ 60#define IPC_MAX_ADDR 0x100 /* Maximum IPC regisers */
65#define IPC_WWBUF_SIZE 16 /* IPC Write buffer Size */ 61#define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */
66#define IPC_RWBUF_SIZE 16 /* IPC Read buffer Size */ 62#define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */
67#define IPC_I2C_BASE 0xFF12B000 /* I2C control register base address */ 63#define IPC_I2C_BASE 0xFF12B000 /* I2C control register base address */
68#define IPC_I2C_MAX_ADDR 0x10 /* Maximum I2C regisers */ 64#define IPC_I2C_MAX_ADDR 0x10 /* Maximum I2C regisers */
69 65
@@ -78,12 +74,7 @@ struct intel_scu_ipc_dev {
78 74
79static struct intel_scu_ipc_dev ipcdev; /* Only one for now */ 75static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
80 76
81static int platform = 1; 77static int platform; /* Platform type */
82module_param(platform, int, 0);
83MODULE_PARM_DESC(platform, "1 for moorestown platform");
84
85
86
87 78
88/* 79/*
89 * IPC Read Buffer (Read Only): 80 * IPC Read Buffer (Read Only):
@@ -119,24 +110,6 @@ static inline void ipc_data_writel(u32 data, u32 offset) /* Write ipc data */
119} 110}
120 111
121/* 112/*
122 * IPC destination Pointer (Write Only):
123 * Use content as pointer for destination write
124 */
125static inline void ipc_write_dptr(u32 data) /* Write dptr data */
126{
127 writel(data, ipcdev.ipc_base + 0x0C);
128}
129
130/*
131 * IPC Source Pointer (Write Only):
132 * Use content as pointer for read location
133*/
134static inline void ipc_write_sptr(u32 data) /* Write dptr data */
135{
136 writel(data, ipcdev.ipc_base + 0x08);
137}
138
139/*
140 * Status Register (Read Only): 113 * Status Register (Read Only):
141 * Driver will read this register to get the ready/busy status of the IPC 114 * Driver will read this register to get the ready/busy status of the IPC
142 * block and error status of the IPC command that was just processed by SCU 115 * block and error status of the IPC command that was just processed by SCU
@@ -154,7 +127,7 @@ static inline u8 ipc_data_readb(u32 offset) /* Read ipc byte data */
154 return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 127 return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
155} 128}
156 129
157static inline u8 ipc_data_readl(u32 offset) /* Read ipc u32 data */ 130static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */
158{ 131{
159 return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 132 return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
160} 133}
@@ -175,62 +148,73 @@ static inline int busy_loop(void) /* Wait till scu status is busy */
175 return -ETIMEDOUT; 148 return -ETIMEDOUT;
176 } 149 }
177 } 150 }
178 return (status >> 1) & 1; 151 if ((status >> 1) & 1)
152 return -EIO;
153
154 return 0;
179} 155}
180 156
181/* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ 157/* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
182static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) 158static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
183{ 159{
184 int nc; 160 int i, nc, bytes, d;
185 u32 offset = 0; 161 u32 offset = 0;
186 u32 err = 0; 162 u32 err = 0;
187 u8 cbuf[IPC_WWBUF_SIZE] = { '\0' }; 163 u8 cbuf[IPC_WWBUF_SIZE] = { };
188 u32 *wbuf = (u32 *)&cbuf; 164 u32 *wbuf = (u32 *)&cbuf;
189 165
190 mutex_lock(&ipclock); 166 mutex_lock(&ipclock);
167
168 memset(cbuf, 0, sizeof(cbuf));
169
191 if (ipcdev.pdev == NULL) { 170 if (ipcdev.pdev == NULL) {
192 mutex_unlock(&ipclock); 171 mutex_unlock(&ipclock);
193 return -ENODEV; 172 return -ENODEV;
194 } 173 }
195 174
196 if (platform == 1) { 175 if (platform != MRST_CPU_CHIP_PENWELL) {
197 /* Entry is 4 bytes for read/write, 5 bytes for read modify */ 176 bytes = 0;
198 for (nc = 0; nc < count; nc++) { 177 d = 0;
178 for (i = 0; i < count; i++) {
179 cbuf[bytes++] = addr[i];
180 cbuf[bytes++] = addr[i] >> 8;
181 if (id != IPC_CMD_PCNTRL_R)
182 cbuf[bytes++] = data[d++];
183 if (id == IPC_CMD_PCNTRL_M)
184 cbuf[bytes++] = data[d++];
185 }
186 for (i = 0; i < bytes; i += 4)
187 ipc_data_writel(wbuf[i/4], i);
188 ipc_command(bytes << 16 | id << 12 | 0 << 8 | op);
189 } else {
190 for (nc = 0; nc < count; nc++, offset += 2) {
199 cbuf[offset] = addr[nc]; 191 cbuf[offset] = addr[nc];
200 cbuf[offset + 1] = addr[nc] >> 8; 192 cbuf[offset + 1] = addr[nc] >> 8;
201 if (id != IPC_CMD_PCNTRL_R)
202 cbuf[offset + 2] = data[nc];
203 if (id == IPC_CMD_PCNTRL_M) {
204 cbuf[offset + 3] = data[nc + 1];
205 offset += 1;
206 }
207 offset += 3;
208 } 193 }
209 for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
210 ipc_data_writel(wbuf[nc], offset); /* Write wbuff */
211 194
212 } else { 195 if (id == IPC_CMD_PCNTRL_R) {
213 for (nc = 0, offset = 0; nc < count; nc++, offset += 2) 196 for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
214 ipc_data_writel(addr[nc], offset); /* Write addresses */ 197 ipc_data_writel(wbuf[nc], offset);
215 if (id != IPC_CMD_PCNTRL_R) { 198 ipc_command((count*2) << 16 | id << 12 | 0 << 8 | op);
216 for (nc = 0; nc < count; nc++, offset++) 199 } else if (id == IPC_CMD_PCNTRL_W) {
217 ipc_data_writel(data[nc], offset); /* Write data */ 200 for (nc = 0; nc < count; nc++, offset += 1)
218 if (id == IPC_CMD_PCNTRL_M) 201 cbuf[offset] = data[nc];
219 ipc_data_writel(data[nc + 1], offset); /* Mask value*/ 202 for (nc = 0, offset = 0; nc < count; nc++, offset += 4)
203 ipc_data_writel(wbuf[nc], offset);
204 ipc_command((count*3) << 16 | id << 12 | 0 << 8 | op);
205 } else if (id == IPC_CMD_PCNTRL_M) {
206 cbuf[offset] = data[0];
207 cbuf[offset + 1] = data[1];
208 ipc_data_writel(wbuf[0], 0); /* Write wbuff */
209 ipc_command(4 << 16 | id << 12 | 0 << 8 | op);
220 } 210 }
221 } 211 }
222 212
223 if (id != IPC_CMD_PCNTRL_M)
224 ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op);
225 else
226 ipc_command((count * 4) << 16 | id << 12 | 0 << 8 | op);
227
228 err = busy_loop(); 213 err = busy_loop();
229
230 if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ 214 if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
231 /* Workaround: values are read as 0 without memcpy_fromio */ 215 /* Workaround: values are read as 0 without memcpy_fromio */
232 memcpy_fromio(cbuf, ipcdev.ipc_base + IPC_READ_BUFFER, 16); 216 memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16);
233 if (platform == 1) { 217 if (platform != MRST_CPU_CHIP_PENWELL) {
234 for (nc = 0, offset = 2; nc < count; nc++, offset += 3) 218 for (nc = 0, offset = 2; nc < count; nc++, offset += 3)
235 data[nc] = ipc_data_readb(offset); 219 data[nc] = ipc_data_readb(offset);
236 } else { 220 } else {
@@ -405,70 +389,6 @@ int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask)
405EXPORT_SYMBOL(intel_scu_ipc_update_register); 389EXPORT_SYMBOL(intel_scu_ipc_update_register);
406 390
407/** 391/**
408 * intel_scu_ipc_register_read - 32bit indirect read
409 * @addr: register address
410 * @value: 32bit value return
411 *
412 * Performs IA 32 bit indirect read, returns 0 on success, or an
413 * error code.
414 *
415 * Can be used when SCCB(System Controller Configuration Block) register
416 * HRIM(Honor Restricted IPC Messages) is set (bit 23)
417 *
418 * This function may sleep. Locking for SCU accesses is handled for
419 * the caller.
420 */
421int intel_scu_ipc_register_read(u32 addr, u32 *value)
422{
423 u32 err = 0;
424
425 mutex_lock(&ipclock);
426 if (ipcdev.pdev == NULL) {
427 mutex_unlock(&ipclock);
428 return -ENODEV;
429 }
430 ipc_write_sptr(addr);
431 ipc_command(4 << 16 | IPC_CMD_INDIRECT_RD);
432 err = busy_loop();
433 *value = ipc_data_readl(0);
434 mutex_unlock(&ipclock);
435 return err;
436}
437EXPORT_SYMBOL(intel_scu_ipc_register_read);
438
439/**
440 * intel_scu_ipc_register_write - 32bit indirect write
441 * @addr: register address
442 * @value: 32bit value to write
443 *
444 * Performs IA 32 bit indirect write, returns 0 on success, or an
445 * error code.
446 *
447 * Can be used when SCCB(System Controller Configuration Block) register
448 * HRIM(Honor Restricted IPC Messages) is set (bit 23)
449 *
450 * This function may sleep. Locking for SCU accesses is handled for
451 * the caller.
452 */
453int intel_scu_ipc_register_write(u32 addr, u32 value)
454{
455 u32 err = 0;
456
457 mutex_lock(&ipclock);
458 if (ipcdev.pdev == NULL) {
459 mutex_unlock(&ipclock);
460 return -ENODEV;
461 }
462 ipc_write_dptr(addr);
463 ipc_data_writel(value, 0);
464 ipc_command(4 << 16 | IPC_CMD_INDIRECT_WR);
465 err = busy_loop();
466 mutex_unlock(&ipclock);
467 return err;
468}
469EXPORT_SYMBOL(intel_scu_ipc_register_write);
470
471/**
472 * intel_scu_ipc_simple_command - send a simple command 392 * intel_scu_ipc_simple_command - send a simple command
473 * @cmd: command 393 * @cmd: command
474 * @sub: sub type 394 * @sub: sub type
@@ -524,7 +444,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
524 for (i = 0; i < inlen; i++) 444 for (i = 0; i < inlen; i++)
525 ipc_data_writel(*in++, 4 * i); 445 ipc_data_writel(*in++, 4 * i);
526 446
527 ipc_command((sub << 12) | cmd | (inlen << 18)); 447 ipc_command((inlen << 16) | (sub << 12) | cmd);
528 err = busy_loop(); 448 err = busy_loop();
529 449
530 for (i = 0; i < outlen; i++) 450 for (i = 0; i < outlen; i++)
@@ -803,6 +723,7 @@ static void ipc_remove(struct pci_dev *pdev)
803 723
804static const struct pci_device_id pci_ids[] = { 724static const struct pci_device_id pci_ids[] = {
805 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, 725 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
726 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
806 { 0,} 727 { 0,}
807}; 728};
808MODULE_DEVICE_TABLE(pci, pci_ids); 729MODULE_DEVICE_TABLE(pci, pci_ids);
@@ -817,6 +738,9 @@ static struct pci_driver ipc_driver = {
817 738
818static int __init intel_scu_ipc_init(void) 739static int __init intel_scu_ipc_init(void)
819{ 740{
741 platform = mrst_identify_cpu();
742 if (platform == 0)
743 return -ENODEV;
820 return pci_register_driver(&ipc_driver); 744 return pci_register_driver(&ipc_driver);
821} 745}
822 746
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index afd762b58ad9..7e9bb6df9d39 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -434,7 +434,7 @@ static int dmi_check_cb(const struct dmi_system_id *id)
434{ 434{
435 printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n", 435 printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n",
436 id->ident); 436 id->ident);
437 return 0; 437 return 1;
438} 438}
439 439
440static struct dmi_system_id __initdata msi_dmi_table[] = { 440static struct dmi_system_id __initdata msi_dmi_table[] = {
@@ -562,15 +562,15 @@ static int rfkill_threeg_set(void *data, bool blocked)
562 return 0; 562 return 0;
563} 563}
564 564
565static struct rfkill_ops rfkill_bluetooth_ops = { 565static const struct rfkill_ops rfkill_bluetooth_ops = {
566 .set_block = rfkill_bluetooth_set 566 .set_block = rfkill_bluetooth_set
567}; 567};
568 568
569static struct rfkill_ops rfkill_wlan_ops = { 569static const struct rfkill_ops rfkill_wlan_ops = {
570 .set_block = rfkill_wlan_set 570 .set_block = rfkill_wlan_set
571}; 571};
572 572
573static struct rfkill_ops rfkill_threeg_ops = { 573static const struct rfkill_ops rfkill_threeg_ops = {
574 .set_block = rfkill_threeg_set 574 .set_block = rfkill_threeg_set
575}; 575};
576 576
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index d1736009636f..42a5469a2459 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -57,7 +57,7 @@ static struct key_entry msi_wmi_keymap[] = {
57}; 57};
58static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; 58static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
59 59
60struct backlight_device *backlight; 60static struct backlight_device *backlight;
61 61
62static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF }; 62static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
63 63
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 2fb9a32926f8..ec01c3d8fc5a 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -248,7 +248,7 @@ static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
248 status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET, 248 status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
249 &params, NULL); 249 &params, NULL);
250 250
251 return status == AE_OK; 251 return (status == AE_OK) ? 0 : -EIO;
252} 252}
253 253
254static inline int acpi_pcc_get_sqty(struct acpi_device *device) 254static inline int acpi_pcc_get_sqty(struct acpi_device *device)
@@ -586,7 +586,6 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
586static int acpi_pcc_hotkey_resume(struct acpi_device *device) 586static int acpi_pcc_hotkey_resume(struct acpi_device *device)
587{ 587{
588 struct pcc_acpi *pcc = acpi_driver_data(device); 588 struct pcc_acpi *pcc = acpi_driver_data(device);
589 acpi_status status = AE_OK;
590 589
591 if (device == NULL || pcc == NULL) 590 if (device == NULL || pcc == NULL)
592 return -EINVAL; 591 return -EINVAL;
@@ -594,9 +593,7 @@ static int acpi_pcc_hotkey_resume(struct acpi_device *device)
594 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", 593 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",
595 pcc->sticky_mode)); 594 pcc->sticky_mode));
596 595
597 status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); 596 return acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode);
598
599 return status == AE_OK ? 0 : -EINVAL;
600} 597}
601 598
602static int acpi_pcc_hotkey_add(struct acpi_device *device) 599static int acpi_pcc_hotkey_add(struct acpi_device *device)
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 1387c5f9c24d..e3154ff7a39f 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -561,8 +561,7 @@ static void sony_pf_remove(void)
561 if (!atomic_dec_and_test(&sony_pf_users)) 561 if (!atomic_dec_and_test(&sony_pf_users))
562 return; 562 return;
563 563
564 platform_device_del(sony_pf_device); 564 platform_device_unregister(sony_pf_device);
565 platform_device_put(sony_pf_device);
566 platform_driver_unregister(&sony_pf_driver); 565 platform_driver_unregister(&sony_pf_driver);
567} 566}
568 567
@@ -1196,9 +1195,13 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)
1196 } 1195 }
1197 1196
1198 device_enum = (union acpi_object *) buffer.pointer; 1197 device_enum = (union acpi_object *) buffer.pointer;
1199 if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { 1198 if (!device_enum) {
1200 printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", 1199 pr_err("Invalid SN06 return object\n");
1201 device_enum->type); 1200 goto out_no_enum;
1201 }
1202 if (device_enum->type != ACPI_TYPE_BUFFER) {
1203 pr_err("Invalid SN06 return object type 0x%.2x\n",
1204 device_enum->type);
1202 goto out_no_enum; 1205 goto out_no_enum;
1203 } 1206 }
1204 1207
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 4bdb13796e24..5d6119bed00c 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -5838,75 +5838,6 @@ static struct ibm_struct thermal_driver_data = {
5838}; 5838};
5839 5839
5840/************************************************************************* 5840/*************************************************************************
5841 * EC Dump subdriver
5842 */
5843
5844static u8 ecdump_regs[256];
5845
5846static int ecdump_read(struct seq_file *m)
5847{
5848 int i, j;
5849 u8 v;
5850
5851 seq_printf(m, "EC "
5852 " +00 +01 +02 +03 +04 +05 +06 +07"
5853 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
5854 for (i = 0; i < 256; i += 16) {
5855 seq_printf(m, "EC 0x%02x:", i);
5856 for (j = 0; j < 16; j++) {
5857 if (!acpi_ec_read(i + j, &v))
5858 break;
5859 if (v != ecdump_regs[i + j])
5860 seq_printf(m, " *%02x", v);
5861 else
5862 seq_printf(m, " %02x", v);
5863 ecdump_regs[i + j] = v;
5864 }
5865 seq_putc(m, '\n');
5866 if (j != 16)
5867 break;
5868 }
5869
5870 /* These are way too dangerous to advertise openly... */
5871#if 0
5872 seq_printf(m, "commands:\t0x<offset> 0x<value>"
5873 " (<offset> is 00-ff, <value> is 00-ff)\n");
5874 seq_printf(m, "commands:\t0x<offset> <value> "
5875 " (<offset> is 00-ff, <value> is 0-255)\n");
5876#endif
5877 return 0;
5878}
5879
5880static int ecdump_write(char *buf)
5881{
5882 char *cmd;
5883 int i, v;
5884
5885 while ((cmd = next_cmd(&buf))) {
5886 if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
5887 /* i and v set */
5888 } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
5889 /* i and v set */
5890 } else
5891 return -EINVAL;
5892 if (i >= 0 && i < 256 && v >= 0 && v < 256) {
5893 if (!acpi_ec_write(i, v))
5894 return -EIO;
5895 } else
5896 return -EINVAL;
5897 }
5898
5899 return 0;
5900}
5901
5902static struct ibm_struct ecdump_driver_data = {
5903 .name = "ecdump",
5904 .read = ecdump_read,
5905 .write = ecdump_write,
5906 .flags.experimental = 1,
5907};
5908
5909/*************************************************************************
5910 * Backlight/brightness subdriver 5841 * Backlight/brightness subdriver
5911 */ 5842 */
5912 5843
@@ -8883,9 +8814,6 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8883 .data = &thermal_driver_data, 8814 .data = &thermal_driver_data,
8884 }, 8815 },
8885 { 8816 {
8886 .data = &ecdump_driver_data,
8887 },
8888 {
8889 .init = brightness_init, 8817 .init = brightness_init,
8890 .data = &brightness_driver_data, 8818 .data = &brightness_driver_data,
8891 }, 8819 },
@@ -8993,7 +8921,6 @@ TPACPI_PARAM(light);
8993TPACPI_PARAM(cmos); 8921TPACPI_PARAM(cmos);
8994TPACPI_PARAM(led); 8922TPACPI_PARAM(led);
8995TPACPI_PARAM(beep); 8923TPACPI_PARAM(beep);
8996TPACPI_PARAM(ecdump);
8997TPACPI_PARAM(brightness); 8924TPACPI_PARAM(brightness);
8998TPACPI_PARAM(volume); 8925TPACPI_PARAM(volume);
8999TPACPI_PARAM(fan); 8926TPACPI_PARAM(fan);
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 37aa14798551..7d67a45bb2b0 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (C) 2002-2004 John Belmonte 5 * Copyright (C) 2002-2004 John Belmonte
6 * Copyright (C) 2008 Philip Langdale 6 * Copyright (C) 2008 Philip Langdale
7 * Copyright (C) 2010 Pierre Ducroquet
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -47,6 +48,7 @@
47#include <linux/platform_device.h> 48#include <linux/platform_device.h>
48#include <linux/rfkill.h> 49#include <linux/rfkill.h>
49#include <linux/input.h> 50#include <linux/input.h>
51#include <linux/leds.h>
50#include <linux/slab.h> 52#include <linux/slab.h>
51 53
52#include <asm/uaccess.h> 54#include <asm/uaccess.h>
@@ -129,6 +131,8 @@ enum {KE_KEY, KE_END};
129 131
130static struct key_entry toshiba_acpi_keymap[] = { 132static struct key_entry toshiba_acpi_keymap[] = {
131 {KE_KEY, 0x101, KEY_MUTE}, 133 {KE_KEY, 0x101, KEY_MUTE},
134 {KE_KEY, 0x102, KEY_ZOOMOUT},
135 {KE_KEY, 0x103, KEY_ZOOMIN},
132 {KE_KEY, 0x13b, KEY_COFFEE}, 136 {KE_KEY, 0x13b, KEY_COFFEE},
133 {KE_KEY, 0x13c, KEY_BATTERY}, 137 {KE_KEY, 0x13c, KEY_BATTERY},
134 {KE_KEY, 0x13d, KEY_SLEEP}, 138 {KE_KEY, 0x13d, KEY_SLEEP},
@@ -285,6 +289,7 @@ struct toshiba_acpi_dev {
285 struct platform_device *p_dev; 289 struct platform_device *p_dev;
286 struct rfkill *bt_rfk; 290 struct rfkill *bt_rfk;
287 struct input_dev *hotkey_dev; 291 struct input_dev *hotkey_dev;
292 int illumination_installed;
288 acpi_handle handle; 293 acpi_handle handle;
289 294
290 const char *bt_name; 295 const char *bt_name;
@@ -292,6 +297,110 @@ struct toshiba_acpi_dev {
292 struct mutex mutex; 297 struct mutex mutex;
293}; 298};
294 299
300/* Illumination support */
301static int toshiba_illumination_available(void)
302{
303 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
304 u32 out[HCI_WORDS];
305 acpi_status status;
306
307 in[0] = 0xf100;
308 status = hci_raw(in, out);
309 if (ACPI_FAILURE(status)) {
310 printk(MY_INFO "Illumination device not available\n");
311 return 0;
312 }
313 in[0] = 0xf400;
314 status = hci_raw(in, out);
315 return 1;
316}
317
318static void toshiba_illumination_set(struct led_classdev *cdev,
319 enum led_brightness brightness)
320{
321 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
322 u32 out[HCI_WORDS];
323 acpi_status status;
324
325 /* First request : initialize communication. */
326 in[0] = 0xf100;
327 status = hci_raw(in, out);
328 if (ACPI_FAILURE(status)) {
329 printk(MY_INFO "Illumination device not available\n");
330 return;
331 }
332
333 if (brightness) {
334 /* Switch the illumination on */
335 in[0] = 0xf400;
336 in[1] = 0x14e;
337 in[2] = 1;
338 status = hci_raw(in, out);
339 if (ACPI_FAILURE(status)) {
340 printk(MY_INFO "ACPI call for illumination failed.\n");
341 return;
342 }
343 } else {
344 /* Switch the illumination off */
345 in[0] = 0xf400;
346 in[1] = 0x14e;
347 in[2] = 0;
348 status = hci_raw(in, out);
349 if (ACPI_FAILURE(status)) {
350 printk(MY_INFO "ACPI call for illumination failed.\n");
351 return;
352 }
353 }
354
355 /* Last request : close communication. */
356 in[0] = 0xf200;
357 in[1] = 0;
358 in[2] = 0;
359 hci_raw(in, out);
360}
361
362static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
363{
364 u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
365 u32 out[HCI_WORDS];
366 acpi_status status;
367 enum led_brightness result;
368
369 /* First request : initialize communication. */
370 in[0] = 0xf100;
371 status = hci_raw(in, out);
372 if (ACPI_FAILURE(status)) {
373 printk(MY_INFO "Illumination device not available\n");
374 return LED_OFF;
375 }
376
377 /* Check the illumination */
378 in[0] = 0xf300;
379 in[1] = 0x14e;
380 status = hci_raw(in, out);
381 if (ACPI_FAILURE(status)) {
382 printk(MY_INFO "ACPI call for illumination failed.\n");
383 return LED_OFF;
384 }
385
386 result = out[2] ? LED_FULL : LED_OFF;
387
388 /* Last request : close communication. */
389 in[0] = 0xf200;
390 in[1] = 0;
391 in[2] = 0;
392 hci_raw(in, out);
393
394 return result;
395}
396
397static struct led_classdev toshiba_led = {
398 .name = "toshiba::illumination",
399 .max_brightness = 1,
400 .brightness_set = toshiba_illumination_set,
401 .brightness_get = toshiba_illumination_get,
402};
403
295static struct toshiba_acpi_dev toshiba_acpi = { 404static struct toshiba_acpi_dev toshiba_acpi = {
296 .bt_name = "Toshiba Bluetooth", 405 .bt_name = "Toshiba Bluetooth",
297}; 406};
@@ -720,25 +829,22 @@ static const struct file_operations version_proc_fops = {
720 829
721#define PROC_TOSHIBA "toshiba" 830#define PROC_TOSHIBA "toshiba"
722 831
723static acpi_status __init add_device(void) 832static void __init create_toshiba_proc_entries(void)
724{ 833{
725 proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); 834 proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
726 proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); 835 proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
727 proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); 836 proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
728 proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); 837 proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
729 proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); 838 proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
730
731 return AE_OK;
732} 839}
733 840
734static acpi_status remove_device(void) 841static void remove_toshiba_proc_entries(void)
735{ 842{
736 remove_proc_entry("lcd", toshiba_proc_dir); 843 remove_proc_entry("lcd", toshiba_proc_dir);
737 remove_proc_entry("video", toshiba_proc_dir); 844 remove_proc_entry("video", toshiba_proc_dir);
738 remove_proc_entry("fan", toshiba_proc_dir); 845 remove_proc_entry("fan", toshiba_proc_dir);
739 remove_proc_entry("keys", toshiba_proc_dir); 846 remove_proc_entry("keys", toshiba_proc_dir);
740 remove_proc_entry("version", toshiba_proc_dir); 847 remove_proc_entry("version", toshiba_proc_dir);
741 return AE_OK;
742} 848}
743 849
744static struct backlight_ops toshiba_backlight_data = { 850static struct backlight_ops toshiba_backlight_data = {
@@ -906,7 +1012,7 @@ static void toshiba_acpi_exit(void)
906 if (toshiba_backlight_device) 1012 if (toshiba_backlight_device)
907 backlight_device_unregister(toshiba_backlight_device); 1013 backlight_device_unregister(toshiba_backlight_device);
908 1014
909 remove_device(); 1015 remove_toshiba_proc_entries();
910 1016
911 if (toshiba_proc_dir) 1017 if (toshiba_proc_dir)
912 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 1018 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
@@ -914,6 +1020,9 @@ static void toshiba_acpi_exit(void)
914 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY, 1020 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
915 toshiba_acpi_notify); 1021 toshiba_acpi_notify);
916 1022
1023 if (toshiba_acpi.illumination_installed)
1024 led_classdev_unregister(&toshiba_led);
1025
917 platform_device_unregister(toshiba_acpi.p_dev); 1026 platform_device_unregister(toshiba_acpi.p_dev);
918 1027
919 return; 1028 return;
@@ -921,7 +1030,6 @@ static void toshiba_acpi_exit(void)
921 1030
922static int __init toshiba_acpi_init(void) 1031static int __init toshiba_acpi_init(void)
923{ 1032{
924 acpi_status status = AE_OK;
925 u32 hci_result; 1033 u32 hci_result;
926 bool bt_present; 1034 bool bt_present;
927 int ret = 0; 1035 int ret = 0;
@@ -969,11 +1077,7 @@ static int __init toshiba_acpi_init(void)
969 toshiba_acpi_exit(); 1077 toshiba_acpi_exit();
970 return -ENODEV; 1078 return -ENODEV;
971 } else { 1079 } else {
972 status = add_device(); 1080 create_toshiba_proc_entries();
973 if (ACPI_FAILURE(status)) {
974 toshiba_acpi_exit();
975 return -ENODEV;
976 }
977 } 1081 }
978 1082
979 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; 1083 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
@@ -1013,6 +1117,13 @@ static int __init toshiba_acpi_init(void)
1013 } 1117 }
1014 } 1118 }
1015 1119
1120 toshiba_acpi.illumination_installed = 0;
1121 if (toshiba_illumination_available()) {
1122 if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
1123 &toshiba_led))
1124 toshiba_acpi.illumination_installed = 1;
1125 }
1126
1016 return 0; 1127 return 0;
1017} 1128}
1018 1129
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index e4eaa14ed987..b2978a04317f 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -518,8 +518,13 @@ static void wmi_notify_debug(u32 value, void *context)
518{ 518{
519 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 519 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
520 union acpi_object *obj; 520 union acpi_object *obj;
521 acpi_status status;
521 522
522 wmi_get_event_data(value, &response); 523 status = wmi_get_event_data(value, &response);
524 if (status != AE_OK) {
525 printk(KERN_INFO "wmi: bad event status 0x%x\n", status);
526 return;
527 }
523 528
524 obj = (union acpi_object *)response.pointer; 529 obj = (union acpi_object *)response.pointer;
525 530
@@ -543,6 +548,7 @@ static void wmi_notify_debug(u32 value, void *context)
543 default: 548 default:
544 printk("object type 0x%X\n", obj->type); 549 printk("object type 0x%X\n", obj->type);
545 } 550 }
551 kfree(obj);
546} 552}
547 553
548/** 554/**
@@ -804,7 +810,7 @@ static bool guid_already_parsed(const char *guid_string)
804/* 810/*
805 * Parse the _WDG method for the GUID data blocks 811 * Parse the _WDG method for the GUID data blocks
806 */ 812 */
807static __init acpi_status parse_wdg(acpi_handle handle) 813static acpi_status parse_wdg(acpi_handle handle)
808{ 814{
809 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 815 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
810 union acpi_object *obj; 816 union acpi_object *obj;
@@ -827,8 +833,10 @@ static __init acpi_status parse_wdg(acpi_handle handle)
827 total = obj->buffer.length / sizeof(struct guid_block); 833 total = obj->buffer.length / sizeof(struct guid_block);
828 834
829 gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); 835 gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
830 if (!gblock) 836 if (!gblock) {
831 return AE_NO_MEMORY; 837 status = AE_NO_MEMORY;
838 goto out_free_pointer;
839 }
832 840
833 for (i = 0; i < total; i++) { 841 for (i = 0; i < total; i++) {
834 /* 842 /*
@@ -848,8 +856,10 @@ static __init acpi_status parse_wdg(acpi_handle handle)
848 wmi_dump_wdg(&gblock[i]); 856 wmi_dump_wdg(&gblock[i]);
849 857
850 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); 858 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
851 if (!wblock) 859 if (!wblock) {
852 return AE_NO_MEMORY; 860 status = AE_NO_MEMORY;
861 goto out_free_gblock;
862 }
853 863
854 wblock->gblock = gblock[i]; 864 wblock->gblock = gblock[i];
855 wblock->handle = handle; 865 wblock->handle = handle;
@@ -860,8 +870,10 @@ static __init acpi_status parse_wdg(acpi_handle handle)
860 list_add_tail(&wblock->list, &wmi_blocks.list); 870 list_add_tail(&wblock->list, &wmi_blocks.list);
861 } 871 }
862 872
863 kfree(out.pointer); 873out_free_gblock:
864 kfree(gblock); 874 kfree(gblock);
875out_free_pointer:
876 kfree(out.pointer);
865 877
866 return status; 878 return status;
867} 879}
@@ -947,7 +959,7 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
947 return 0; 959 return 0;
948} 960}
949 961
950static int __init acpi_wmi_add(struct acpi_device *device) 962static int acpi_wmi_add(struct acpi_device *device)
951{ 963{
952 acpi_status status; 964 acpi_status status;
953 int result = 0; 965 int result = 0;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 929651725855..0e4122ed1b36 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -109,8 +109,6 @@ source "drivers/staging/hv/Kconfig"
109 109
110source "drivers/staging/vme/Kconfig" 110source "drivers/staging/vme/Kconfig"
111 111
112source "drivers/staging/rar_register/Kconfig"
113
114source "drivers/staging/memrar/Kconfig" 112source "drivers/staging/memrar/Kconfig"
115 113
116source "drivers/staging/sep/Kconfig" 114source "drivers/staging/sep/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 6c5b5237ccb9..ecfb0bb990b6 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_VT6656) += vt6656/
36obj-$(CONFIG_FB_UDL) += udlfb/ 36obj-$(CONFIG_FB_UDL) += udlfb/
37obj-$(CONFIG_HYPERV) += hv/ 37obj-$(CONFIG_HYPERV) += hv/
38obj-$(CONFIG_VME_BUS) += vme/ 38obj-$(CONFIG_VME_BUS) += vme/
39obj-$(CONFIG_RAR_REGISTER) += rar_register/
40obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ 39obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
41obj-$(CONFIG_DX_SEP) += sep/ 40obj-$(CONFIG_DX_SEP) += sep/
42obj-$(CONFIG_IIO) += iio/ 41obj-$(CONFIG_IIO) += iio/
diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c
index efa7fd62d390..41876f2b0e54 100644
--- a/drivers/staging/memrar/memrar_handler.c
+++ b/drivers/staging/memrar/memrar_handler.c
@@ -47,8 +47,7 @@
47#include <linux/mm.h> 47#include <linux/mm.h>
48#include <linux/ioport.h> 48#include <linux/ioport.h>
49#include <linux/io.h> 49#include <linux/io.h>
50 50#include <linux/rar_register.h>
51#include "../rar_register/rar_register.h"
52 51
53#include "memrar.h" 52#include "memrar.h"
54#include "memrar_allocator.h" 53#include "memrar_allocator.h"
diff --git a/drivers/staging/rar_register/Kconfig b/drivers/staging/rar_register/Kconfig
deleted file mode 100644
index e9c27738199b..000000000000
--- a/drivers/staging/rar_register/Kconfig
+++ /dev/null
@@ -1,30 +0,0 @@
1#
2# RAR device configuration
3#
4
5menu "RAR Register Driver"
6#
7# Restricted Access Register Manager
8#
9config RAR_REGISTER
10 tristate "Restricted Access Region Register Driver"
11 depends on PCI
12 default n
13 ---help---
14 This driver allows other kernel drivers access to the
15 contents of the restricted access region control registers.
16
17 The restricted access region control registers
18 (rar_registers) are used to pass address and
19 locking information on restricted access regions
20 to other drivers that use restricted access regions.
21
22 The restricted access regions are regions of memory
23 on the Intel MID Platform that are not accessible to
24 the x86 processor, but are accessible to dedicated
25 processors on board peripheral devices.
26
27 The purpose of the restricted access regions is to
28 protect sensitive data from compromise by unauthorized
29 programs running on the x86 processor.
30endmenu
diff --git a/drivers/staging/rar_register/Makefile b/drivers/staging/rar_register/Makefile
deleted file mode 100644
index d5954ccc16c9..000000000000
--- a/drivers/staging/rar_register/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
1EXTRA_CFLAGS += -DLITTLE__ENDIAN
2obj-$(CONFIG_RAR_REGISTER) += rar_register.o
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 7f0028e1010b..8f8b072c4c7b 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -33,6 +33,15 @@
33 * subject to backwards-compatibility constraints. 33 * subject to backwards-compatibility constraints.
34 */ 34 */
35 35
36#ifdef __KERNEL__
37/* For use by IPS driver */
38extern unsigned long i915_read_mch_val(void);
39extern bool i915_gpu_raise(void);
40extern bool i915_gpu_lower(void);
41extern bool i915_gpu_busy(void);
42extern bool i915_gpu_turbo_disable(void);
43#endif
44
36/* Each region is a minimum of 16k, and there are at most 255 of them. 45/* Each region is a minimum of 16k, and there are at most 255 of them.
37 */ 46 */
38#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use 47#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
diff --git a/include/linux/intel_pmic_gpio.h b/include/linux/intel_pmic_gpio.h
new file mode 100644
index 000000000000..920109a29191
--- /dev/null
+++ b/include/linux/intel_pmic_gpio.h
@@ -0,0 +1,15 @@
1#ifndef LINUX_INTEL_PMIC_H
2#define LINUX_INTEL_PMIC_H
3
4struct intel_pmic_gpio_platform_data {
5 /* the first IRQ of the chip */
6 unsigned irq_base;
7 /* number assigned to the first GPIO */
8 unsigned gpio_base;
9 /* sram address for gpiointr register, the langwell chip will map
10 * the PMIC spi GPIO expander's GPIOINTR register in sram.
11 */
12 unsigned gpiointr;
13};
14
15#endif
diff --git a/drivers/staging/rar_register/rar_register.h b/include/linux/rar_register.h
index ffa805780f85..ffa805780f85 100644
--- a/drivers/staging/rar_register/rar_register.h
+++ b/include/linux/rar_register.h
diff --git a/include/linux/timer.h b/include/linux/timer.h
index ea965b857a50..38cf093ef62c 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -100,6 +100,13 @@ void init_timer_deferrable_key(struct timer_list *timer,
100 setup_timer_on_stack_key((timer), #timer, &__key, \ 100 setup_timer_on_stack_key((timer), #timer, &__key, \
101 (fn), (data)); \ 101 (fn), (data)); \
102 } while (0) 102 } while (0)
103#define setup_deferrable_timer_on_stack(timer, fn, data) \
104 do { \
105 static struct lock_class_key __key; \
106 setup_deferrable_timer_on_stack_key((timer), #timer, \
107 &__key, (fn), \
108 (data)); \
109 } while (0)
103#else 110#else
104#define init_timer(timer)\ 111#define init_timer(timer)\
105 init_timer_key((timer), NULL, NULL) 112 init_timer_key((timer), NULL, NULL)
@@ -111,6 +118,8 @@ void init_timer_deferrable_key(struct timer_list *timer,
111 setup_timer_key((timer), NULL, NULL, (fn), (data)) 118 setup_timer_key((timer), NULL, NULL, (fn), (data))
112#define setup_timer_on_stack(timer, fn, data)\ 119#define setup_timer_on_stack(timer, fn, data)\
113 setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) 120 setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
121#define setup_deferrable_timer_on_stack(timer, fn, data)\
122 setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
114#endif 123#endif
115 124
116#ifdef CONFIG_DEBUG_OBJECTS_TIMERS 125#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
@@ -150,6 +159,12 @@ static inline void setup_timer_on_stack_key(struct timer_list *timer,
150 init_timer_on_stack_key(timer, name, key); 159 init_timer_on_stack_key(timer, name, key);
151} 160}
152 161
162extern void setup_deferrable_timer_on_stack_key(struct timer_list *timer,
163 const char *name,
164 struct lock_class_key *key,
165 void (*function)(unsigned long),
166 unsigned long data);
167
153/** 168/**
154 * timer_pending - is a timer pending? 169 * timer_pending - is a timer pending?
155 * @timer: the timer in question 170 * @timer: the timer in question
diff --git a/kernel/timer.c b/kernel/timer.c
index ee305c8d4e18..efde11e197c4 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -577,6 +577,19 @@ static void __init_timer(struct timer_list *timer,
577 lockdep_init_map(&timer->lockdep_map, name, key, 0); 577 lockdep_init_map(&timer->lockdep_map, name, key, 0);
578} 578}
579 579
580void setup_deferrable_timer_on_stack_key(struct timer_list *timer,
581 const char *name,
582 struct lock_class_key *key,
583 void (*function)(unsigned long),
584 unsigned long data)
585{
586 timer->function = function;
587 timer->data = data;
588 init_timer_on_stack_key(timer, name, key);
589 timer_set_deferrable(timer);
590}
591EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key);
592
580/** 593/**
581 * init_timer_key - initialize a timer 594 * init_timer_key - initialize a timer
582 * @timer: the timer to be initialized 595 * @timer: the timer to be initialized