aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS8
-rw-r--r--arch/x86/include/asm/intel_pmc_ipc.h6
-rw-r--r--drivers/platform/x86/Kconfig31
-rw-r--r--drivers/platform/x86/Makefile2
-rw-r--r--drivers/platform/x86/acer-wmi.c97
-rw-r--r--drivers/platform/x86/alienware-wmi.c1
-rw-r--r--drivers/platform/x86/asus-wireless.c60
-rw-r--r--drivers/platform/x86/dell-laptop.c6
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c220
-rw-r--r--drivers/platform/x86/hp_accel.c1
-rw-r--r--drivers/platform/x86/intel-hid.c96
-rw-r--r--drivers/platform/x86/intel_mid_powerbtn.c187
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c2
-rw-r--r--drivers/platform/x86/intel_pmc_core.c6
-rw-r--r--drivers/platform/x86/intel_pmc_ipc.c67
-rw-r--r--drivers/platform/x86/intel_turbo_max_3.c151
-rw-r--r--drivers/platform/x86/mlx-platform.c84
-rw-r--r--drivers/platform/x86/silead_dmi.c136
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c124
19 files changed, 965 insertions, 320 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index dedc66c265c9..b4474a8b7e8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11456,6 +11456,14 @@ F: drivers/media/usb/siano/
11456F: drivers/media/usb/siano/ 11456F: drivers/media/usb/siano/
11457F: drivers/media/mmc/siano/ 11457F: drivers/media/mmc/siano/
11458 11458
11459SILEAD TOUCHSCREEN DRIVER
11460M: Hans de Goede <hdegoede@redhat.com>
11461L: linux-input@vger.kernel.org
11462L: platform-driver-x86@vger.kernel.org
11463S: Maintained
11464F: drivers/input/touchscreen/silead.c
11465F: drivers/platform/x86/silead_dmi.c
11466
11459SIMPLEFB FB DRIVER 11467SIMPLEFB FB DRIVER
11460M: Hans de Goede <hdegoede@redhat.com> 11468M: Hans de Goede <hdegoede@redhat.com>
11461L: linux-fbdev@vger.kernel.org 11469L: linux-fbdev@vger.kernel.org
diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h
index cd0310e186f4..4291b6a5ddf7 100644
--- a/arch/x86/include/asm/intel_pmc_ipc.h
+++ b/arch/x86/include/asm/intel_pmc_ipc.h
@@ -30,6 +30,7 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
30 u32 *out, u32 outlen, u32 dptr, u32 sptr); 30 u32 *out, u32 outlen, u32 dptr, u32 sptr);
31int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 31int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
32 u32 *out, u32 outlen); 32 u32 *out, u32 outlen);
33int intel_pmc_s0ix_counter_read(u64 *data);
33 34
34#else 35#else
35 36
@@ -50,6 +51,11 @@ static inline int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
50 return -EINVAL; 51 return -EINVAL;
51} 52}
52 53
54static inline int intel_pmc_s0ix_counter_read(u64 *data)
55{
56 return -EINVAL;
57}
58
53#endif /*CONFIG_INTEL_PMC_IPC*/ 59#endif /*CONFIG_INTEL_PMC_IPC*/
54 60
55#endif 61#endif
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index a9e9c91cf4d4..4bc88eb52712 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -92,9 +92,8 @@ config ASUS_LAPTOP
92 If you have an ACPI-compatible ASUS laptop, say Y or M here. 92 If you have an ACPI-compatible ASUS laptop, say Y or M here.
93 93
94config DELL_SMBIOS 94config DELL_SMBIOS
95 tristate "Dell SMBIOS Support" 95 tristate
96 depends on DCDBAS 96 select DCDBAS
97 default n
98 ---help--- 97 ---help---
99 This module provides common functions for kernel modules using 98 This module provides common functions for kernel modules using
100 Dell SMBIOS. 99 Dell SMBIOS.
@@ -103,16 +102,15 @@ config DELL_SMBIOS
103 102
104config DELL_LAPTOP 103config DELL_LAPTOP
105 tristate "Dell Laptop Extras" 104 tristate "Dell Laptop Extras"
106 depends on DELL_SMBIOS
107 depends on DMI 105 depends on DMI
108 depends on BACKLIGHT_CLASS_DEVICE 106 depends on BACKLIGHT_CLASS_DEVICE
109 depends on ACPI_VIDEO || ACPI_VIDEO = n 107 depends on ACPI_VIDEO || ACPI_VIDEO = n
110 depends on RFKILL || RFKILL = n 108 depends on RFKILL || RFKILL = n
111 depends on SERIO_I8042 109 depends on SERIO_I8042
110 select DELL_SMBIOS
112 select POWER_SUPPLY 111 select POWER_SUPPLY
113 select LEDS_CLASS 112 select LEDS_CLASS
114 select NEW_LEDS 113 select NEW_LEDS
115 default n
116 ---help--- 114 ---help---
117 This driver adds support for rfkill and backlight control to Dell 115 This driver adds support for rfkill and backlight control to Dell
118 laptops (except for some models covered by the Compal driver). 116 laptops (except for some models covered by the Compal driver).
@@ -123,7 +121,7 @@ config DELL_WMI
123 depends on DMI 121 depends on DMI
124 depends on INPUT 122 depends on INPUT
125 depends on ACPI_VIDEO || ACPI_VIDEO = n 123 depends on ACPI_VIDEO || ACPI_VIDEO = n
126 depends on DELL_SMBIOS 124 select DELL_SMBIOS
127 select INPUT_SPARSEKMAP 125 select INPUT_SPARSEKMAP
128 ---help--- 126 ---help---
129 Say Y here if you want to support WMI-based hotkeys on Dell laptops. 127 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
@@ -1069,6 +1067,27 @@ config MLX_CPLD_PLATFORM
1069 This driver handles hot-plug events for the power suppliers, power 1067 This driver handles hot-plug events for the power suppliers, power
1070 cables and fans on the wide range Mellanox IB and Ethernet systems. 1068 cables and fans on the wide range Mellanox IB and Ethernet systems.
1071 1069
1070config INTEL_TURBO_MAX_3
1071 bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
1072 depends on X86_64 && SCHED_MC_PRIO
1073 ---help---
1074 This driver reads maximum performance ratio of each CPU and set up
1075 the scheduler priority metrics. In this way scheduler can prefer
1076 CPU with higher performance to schedule tasks.
1077 This driver is only required when the system is not using Hardware
1078 P-States (HWP). In HWP mode, priority can be read from ACPI tables.
1079
1080config SILEAD_DMI
1081 bool "Tablets with Silead touchscreens"
1082 depends on ACPI && DMI && I2C=y && INPUT
1083 ---help---
1084 Certain ACPI based tablets with Silead touchscreens do not have
1085 enough data in ACPI tables for the touchscreen driver to handle
1086 the touchscreen properly, as OEMs expected the data to be baked
1087 into the tablet model specific version of the driver shipped
1088 with the OS-image for the device. This option supplies the missing
1089 information. Enable this for x86 tablets with Silead touchscreens.
1090
1072endif # X86_PLATFORM_DEVICES 1091endif # X86_PLATFORM_DEVICES
1073 1092
1074config PMC_ATOM 1093config PMC_ATOM
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index cf9fc3e930c7..299d0f9e40f7 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
65obj-$(CONFIG_PVPANIC) += pvpanic.o 65obj-$(CONFIG_PVPANIC) += pvpanic.o
66obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o 66obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
67obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o 67obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o
68obj-$(CONFIG_SILEAD_DMI) += silead_dmi.o
68obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o 69obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o
69obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o 70obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
70obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o 71obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
@@ -76,3 +77,4 @@ obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
76obj-$(CONFIG_PMC_ATOM) += pmc_atom.o 77obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
77obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o 78obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
78obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o 79obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o
80obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index a66192f692e3..dac0fbe87460 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -128,6 +128,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
128 {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, 128 {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
129 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, 129 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
130 {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} }, 130 {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
131 {KE_KEY, 0x86, {KEY_WLAN} },
131 {KE_END, 0} 132 {KE_END, 0}
132}; 133};
133 134
@@ -150,15 +151,30 @@ struct event_return_value {
150#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ 151#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
151#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */ 152#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */
152 153
153struct lm_input_params { 154/* Hotkey Customized Setting and Acer Application Status.
155 * Set Device Default Value and Report Acer Application Status.
156 * When Acer Application starts, it will run this method to inform
157 * BIOS/EC that Acer Application is on.
158 * App Status
159 * Bit[0]: Launch Manager Status
160 * Bit[1]: ePM Status
161 * Bit[2]: Device Control Status
162 * Bit[3]: Acer Power Button Utility Status
163 * Bit[4]: RF Button Status
164 * Bit[5]: ODD PM Status
165 * Bit[6]: Device Default Value Control
166 * Bit[7]: Hall Sensor Application Status
167 */
168struct func_input_params {
154 u8 function_num; /* Function Number */ 169 u8 function_num; /* Function Number */
155 u16 commun_devices; /* Communication type devices default status */ 170 u16 commun_devices; /* Communication type devices default status */
156 u16 devices; /* Other type devices default status */ 171 u16 devices; /* Other type devices default status */
157 u8 lm_status; /* Launch Manager Status */ 172 u8 app_status; /* Acer Device Status. LM, ePM, RF Button... */
158 u16 reserved; 173 u8 app_mask; /* Bit mask to app_status */
174 u8 reserved;
159} __attribute__((packed)); 175} __attribute__((packed));
160 176
161struct lm_return_value { 177struct func_return_value {
162 u8 error_code; /* Error Code */ 178 u8 error_code; /* Error Code */
163 u8 ec_return_value; /* EC Return Value */ 179 u8 ec_return_value; /* EC Return Value */
164 u16 reserved; 180 u16 reserved;
@@ -1769,13 +1785,13 @@ static void acer_wmi_notify(u32 value, void *context)
1769} 1785}
1770 1786
1771static acpi_status __init 1787static acpi_status __init
1772wmid3_set_lm_mode(struct lm_input_params *params, 1788wmid3_set_function_mode(struct func_input_params *params,
1773 struct lm_return_value *return_value) 1789 struct func_return_value *return_value)
1774{ 1790{
1775 acpi_status status; 1791 acpi_status status;
1776 union acpi_object *obj; 1792 union acpi_object *obj;
1777 1793
1778 struct acpi_buffer input = { sizeof(struct lm_input_params), params }; 1794 struct acpi_buffer input = { sizeof(struct func_input_params), params };
1779 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 1795 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1780 1796
1781 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output); 1797 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
@@ -1796,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params *params,
1796 return AE_ERROR; 1812 return AE_ERROR;
1797 } 1813 }
1798 1814
1799 *return_value = *((struct lm_return_value *)obj->buffer.pointer); 1815 *return_value = *((struct func_return_value *)obj->buffer.pointer);
1800 kfree(obj); 1816 kfree(obj);
1801 1817
1802 return status; 1818 return status;
@@ -1804,16 +1820,17 @@ wmid3_set_lm_mode(struct lm_input_params *params,
1804 1820
1805static int __init acer_wmi_enable_ec_raw(void) 1821static int __init acer_wmi_enable_ec_raw(void)
1806{ 1822{
1807 struct lm_return_value return_value; 1823 struct func_return_value return_value;
1808 acpi_status status; 1824 acpi_status status;
1809 struct lm_input_params params = { 1825 struct func_input_params params = {
1810 .function_num = 0x1, 1826 .function_num = 0x1,
1811 .commun_devices = 0xFFFF, 1827 .commun_devices = 0xFFFF,
1812 .devices = 0xFFFF, 1828 .devices = 0xFFFF,
1813 .lm_status = 0x00, /* Launch Manager Deactive */ 1829 .app_status = 0x00, /* Launch Manager Deactive */
1830 .app_mask = 0x01,
1814 }; 1831 };
1815 1832
1816 status = wmid3_set_lm_mode(&params, &return_value); 1833 status = wmid3_set_function_mode(&params, &return_value);
1817 1834
1818 if (return_value.error_code || return_value.ec_return_value) 1835 if (return_value.error_code || return_value.ec_return_value)
1819 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n", 1836 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
@@ -1827,16 +1844,17 @@ static int __init acer_wmi_enable_ec_raw(void)
1827 1844
1828static int __init acer_wmi_enable_lm(void) 1845static int __init acer_wmi_enable_lm(void)
1829{ 1846{
1830 struct lm_return_value return_value; 1847 struct func_return_value return_value;
1831 acpi_status status; 1848 acpi_status status;
1832 struct lm_input_params params = { 1849 struct func_input_params params = {
1833 .function_num = 0x1, 1850 .function_num = 0x1,
1834 .commun_devices = 0xFFFF, 1851 .commun_devices = 0xFFFF,
1835 .devices = 0xFFFF, 1852 .devices = 0xFFFF,
1836 .lm_status = 0x01, /* Launch Manager Active */ 1853 .app_status = 0x01, /* Launch Manager Active */
1854 .app_mask = 0x01,
1837 }; 1855 };
1838 1856
1839 status = wmid3_set_lm_mode(&params, &return_value); 1857 status = wmid3_set_function_mode(&params, &return_value);
1840 1858
1841 if (return_value.error_code || return_value.ec_return_value) 1859 if (return_value.error_code || return_value.ec_return_value)
1842 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n", 1860 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
@@ -1846,11 +1864,46 @@ static int __init acer_wmi_enable_lm(void)
1846 return status; 1864 return status;
1847} 1865}
1848 1866
1867static int __init acer_wmi_enable_rf_button(void)
1868{
1869 struct func_return_value return_value;
1870 acpi_status status;
1871 struct func_input_params params = {
1872 .function_num = 0x1,
1873 .commun_devices = 0xFFFF,
1874 .devices = 0xFFFF,
1875 .app_status = 0x10, /* RF Button Active */
1876 .app_mask = 0x10,
1877 };
1878
1879 status = wmid3_set_function_mode(&params, &return_value);
1880
1881 if (return_value.error_code || return_value.ec_return_value)
1882 pr_warn("Enabling RF Button failed: 0x%x - 0x%x\n",
1883 return_value.error_code,
1884 return_value.ec_return_value);
1885
1886 return status;
1887}
1888
1889#define ACER_WMID_ACCEL_HID "BST0001"
1890
1849static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, 1891static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
1850 void *ctx, void **retval) 1892 void *ctx, void **retval)
1851{ 1893{
1894 struct acpi_device *dev;
1895
1896 if (!strcmp(ctx, "SENR")) {
1897 if (acpi_bus_get_device(ah, &dev))
1898 return AE_OK;
1899 if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
1900 return AE_OK;
1901 } else
1902 return AE_OK;
1903
1852 *(acpi_handle *)retval = ah; 1904 *(acpi_handle *)retval = ah;
1853 return AE_OK; 1905
1906 return AE_CTRL_TERMINATE;
1854} 1907}
1855 1908
1856static int __init acer_wmi_get_handle(const char *name, const char *prop, 1909static int __init acer_wmi_get_handle(const char *name, const char *prop,
@@ -1877,7 +1930,7 @@ static int __init acer_wmi_accel_setup(void)
1877{ 1930{
1878 int err; 1931 int err;
1879 1932
1880 err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); 1933 err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle);
1881 if (err) 1934 if (err)
1882 return err; 1935 return err;
1883 1936
@@ -2216,6 +2269,9 @@ static int __init acer_wmi_init(void)
2216 interface->capability &= ~ACER_CAP_BRIGHTNESS; 2269 interface->capability &= ~ACER_CAP_BRIGHTNESS;
2217 2270
2218 if (wmi_has_guid(WMID_GUID3)) { 2271 if (wmi_has_guid(WMID_GUID3)) {
2272 if (ACPI_FAILURE(acer_wmi_enable_rf_button()))
2273 pr_warn("Cannot enable RF Button Driver\n");
2274
2219 if (ec_raw_mode) { 2275 if (ec_raw_mode) {
2220 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) { 2276 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
2221 pr_err("Cannot enable EC raw mode\n"); 2277 pr_err("Cannot enable EC raw mode\n");
@@ -2233,10 +2289,11 @@ static int __init acer_wmi_init(void)
2233 err = acer_wmi_input_setup(); 2289 err = acer_wmi_input_setup();
2234 if (err) 2290 if (err)
2235 return err; 2291 return err;
2292 err = acer_wmi_accel_setup();
2293 if (err)
2294 return err;
2236 } 2295 }
2237 2296
2238 acer_wmi_accel_setup();
2239
2240 err = platform_driver_register(&acer_platform_driver); 2297 err = platform_driver_register(&acer_platform_driver);
2241 if (err) { 2298 if (err) {
2242 pr_err("Unable to register platform driver\n"); 2299 pr_err("Unable to register platform driver\n");
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c
index 005629447b0c..d6b34923fb4e 100644
--- a/drivers/platform/x86/alienware-wmi.c
+++ b/drivers/platform/x86/alienware-wmi.c
@@ -21,7 +21,6 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/dmi.h> 23#include <linux/dmi.h>
24#include <linux/acpi.h>
25#include <linux/leds.h> 24#include <linux/leds.h>
26 25
27#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492" 26#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
diff --git a/drivers/platform/x86/asus-wireless.c b/drivers/platform/x86/asus-wireless.c
index 9f31bc1a47d0..f3796164329e 100644
--- a/drivers/platform/x86/asus-wireless.c
+++ b/drivers/platform/x86/asus-wireless.c
@@ -17,19 +17,41 @@
17#include <linux/pci_ids.h> 17#include <linux/pci_ids.h>
18#include <linux/leds.h> 18#include <linux/leds.h>
19 19
20#define ASUS_WIRELESS_LED_STATUS 0x2 20struct hswc_params {
21#define ASUS_WIRELESS_LED_OFF 0x4 21 u8 on;
22#define ASUS_WIRELESS_LED_ON 0x5 22 u8 off;
23 u8 status;
24};
23 25
24struct asus_wireless_data { 26struct asus_wireless_data {
25 struct input_dev *idev; 27 struct input_dev *idev;
26 struct acpi_device *adev; 28 struct acpi_device *adev;
29 const struct hswc_params *hswc_params;
27 struct workqueue_struct *wq; 30 struct workqueue_struct *wq;
28 struct work_struct led_work; 31 struct work_struct led_work;
29 struct led_classdev led; 32 struct led_classdev led;
30 int led_state; 33 int led_state;
31}; 34};
32 35
36static const struct hswc_params atk4001_id_params = {
37 .on = 0x0,
38 .off = 0x1,
39 .status = 0x2,
40};
41
42static const struct hswc_params atk4002_id_params = {
43 .on = 0x5,
44 .off = 0x4,
45 .status = 0x2,
46};
47
48static const struct acpi_device_id device_ids[] = {
49 {"ATK4001", (kernel_ulong_t)&atk4001_id_params},
50 {"ATK4002", (kernel_ulong_t)&atk4002_id_params},
51 {"", 0},
52};
53MODULE_DEVICE_TABLE(acpi, device_ids);
54
33static u64 asus_wireless_method(acpi_handle handle, const char *method, 55static u64 asus_wireless_method(acpi_handle handle, const char *method,
34 int param) 56 int param)
35{ 57{
@@ -61,8 +83,8 @@ static enum led_brightness led_state_get(struct led_classdev *led)
61 83
62 data = container_of(led, struct asus_wireless_data, led); 84 data = container_of(led, struct asus_wireless_data, led);
63 s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 85 s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC",
64 ASUS_WIRELESS_LED_STATUS); 86 data->hswc_params->status);
65 if (s == ASUS_WIRELESS_LED_ON) 87 if (s == data->hswc_params->on)
66 return LED_FULL; 88 return LED_FULL;
67 return LED_OFF; 89 return LED_OFF;
68} 90}
@@ -76,14 +98,13 @@ static void led_state_update(struct work_struct *work)
76 data->led_state); 98 data->led_state);
77} 99}
78 100
79static void led_state_set(struct led_classdev *led, 101static void led_state_set(struct led_classdev *led, enum led_brightness value)
80 enum led_brightness value)
81{ 102{
82 struct asus_wireless_data *data; 103 struct asus_wireless_data *data;
83 104
84 data = container_of(led, struct asus_wireless_data, led); 105 data = container_of(led, struct asus_wireless_data, led);
85 data->led_state = value == LED_OFF ? ASUS_WIRELESS_LED_OFF : 106 data->led_state = value == LED_OFF ? data->hswc_params->off :
86 ASUS_WIRELESS_LED_ON; 107 data->hswc_params->on;
87 queue_work(data->wq, &data->led_work); 108 queue_work(data->wq, &data->led_work);
88} 109}
89 110
@@ -104,12 +125,14 @@ static void asus_wireless_notify(struct acpi_device *adev, u32 event)
104static int asus_wireless_add(struct acpi_device *adev) 125static int asus_wireless_add(struct acpi_device *adev)
105{ 126{
106 struct asus_wireless_data *data; 127 struct asus_wireless_data *data;
128 const struct acpi_device_id *id;
107 int err; 129 int err;
108 130
109 data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL); 131 data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL);
110 if (!data) 132 if (!data)
111 return -ENOMEM; 133 return -ENOMEM;
112 adev->driver_data = data; 134 adev->driver_data = data;
135 data->adev = adev;
113 136
114 data->idev = devm_input_allocate_device(&adev->dev); 137 data->idev = devm_input_allocate_device(&adev->dev);
115 if (!data->idev) 138 if (!data->idev)
@@ -124,7 +147,16 @@ static int asus_wireless_add(struct acpi_device *adev)
124 if (err) 147 if (err)
125 return err; 148 return err;
126 149
127 data->adev = adev; 150 for (id = device_ids; id->id[0]; id++) {
151 if (!strcmp((char *) id->id, acpi_device_hid(adev))) {
152 data->hswc_params =
153 (const struct hswc_params *)id->driver_data;
154 break;
155 }
156 }
157 if (!data->hswc_params)
158 return 0;
159
128 data->wq = create_singlethread_workqueue("asus_wireless_workqueue"); 160 data->wq = create_singlethread_workqueue("asus_wireless_workqueue");
129 if (!data->wq) 161 if (!data->wq)
130 return -ENOMEM; 162 return -ENOMEM;
@@ -137,6 +169,7 @@ static int asus_wireless_add(struct acpi_device *adev)
137 err = devm_led_classdev_register(&adev->dev, &data->led); 169 err = devm_led_classdev_register(&adev->dev, &data->led);
138 if (err) 170 if (err)
139 destroy_workqueue(data->wq); 171 destroy_workqueue(data->wq);
172
140 return err; 173 return err;
141} 174}
142 175
@@ -149,13 +182,6 @@ static int asus_wireless_remove(struct acpi_device *adev)
149 return 0; 182 return 0;
150} 183}
151 184
152static const struct acpi_device_id device_ids[] = {
153 {"ATK4001", 0},
154 {"ATK4002", 0},
155 {"", 0},
156};
157MODULE_DEVICE_TABLE(acpi, device_ids);
158
159static struct acpi_driver asus_wireless_driver = { 185static struct acpi_driver asus_wireless_driver = {
160 .name = "Asus Wireless Radio Control Driver", 186 .name = "Asus Wireless Radio Control Driver",
161 .class = "hotkey", 187 .class = "hotkey",
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 14392a01ab36..f57dd282a002 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -106,6 +106,12 @@ static const struct dmi_system_id dell_device_table[] __initconst = {
106 }, 106 },
107 }, 107 },
108 { 108 {
109 .matches = {
110 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
111 DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /*Notebook*/
112 },
113 },
114 {
109 .ident = "Dell Computer Corporation", 115 .ident = "Dell Computer Corporation",
110 .matches = { 116 .matches = {
111 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 117 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 82d67715ce76..2b218b1d13e5 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -202,6 +202,7 @@ static int radio_led_set(struct led_classdev *cdev,
202 202
203static struct led_classdev radio_led = { 203static struct led_classdev radio_led = {
204 .name = "fujitsu::radio_led", 204 .name = "fujitsu::radio_led",
205 .default_trigger = "rfkill-any",
205 .brightness_get = radio_led_get, 206 .brightness_get = radio_led_get,
206 .brightness_set_blocking = radio_led_set 207 .brightness_set_blocking = radio_led_set
207}; 208};
@@ -270,15 +271,20 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
270static int logolamp_set(struct led_classdev *cdev, 271static int logolamp_set(struct led_classdev *cdev,
271 enum led_brightness brightness) 272 enum led_brightness brightness)
272{ 273{
273 if (brightness >= LED_FULL) { 274 int poweron = FUNC_LED_ON, always = FUNC_LED_ON;
274 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); 275 int ret;
275 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON); 276
276 } else if (brightness >= LED_HALF) { 277 if (brightness < LED_HALF)
277 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); 278 poweron = FUNC_LED_OFF;
278 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF); 279
279 } else { 280 if (brightness < LED_FULL)
280 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF); 281 always = FUNC_LED_OFF;
281 } 282
283 ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
284 if (ret < 0)
285 return ret;
286
287 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
282} 288}
283 289
284static int kblamps_set(struct led_classdev *cdev, 290static int kblamps_set(struct led_classdev *cdev,
@@ -313,17 +319,17 @@ static int eco_led_set(struct led_classdev *cdev,
313 319
314static enum led_brightness logolamp_get(struct led_classdev *cdev) 320static enum led_brightness logolamp_get(struct led_classdev *cdev)
315{ 321{
316 enum led_brightness brightness = LED_OFF; 322 int ret;
317 int poweron, always; 323
318 324 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
319 poweron = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); 325 if (ret == FUNC_LED_ON)
320 if (poweron == FUNC_LED_ON) { 326 return LED_FULL;
321 brightness = LED_HALF; 327
322 always = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); 328 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
323 if (always == FUNC_LED_ON) 329 if (ret == FUNC_LED_ON)
324 brightness = LED_FULL; 330 return LED_HALF;
325 } 331
326 return brightness; 332 return LED_OFF;
327} 333}
328 334
329static enum led_brightness kblamps_get(struct led_classdev *cdev) 335static enum led_brightness kblamps_get(struct led_classdev *cdev)
@@ -1029,107 +1035,117 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)
1029 return 0; 1035 return 0;
1030} 1036}
1031 1037
1038static void acpi_fujitsu_hotkey_press(int keycode)
1039{
1040 struct input_dev *input = fujitsu_hotkey->input;
1041 int status;
1042
1043 status = kfifo_in_locked(&fujitsu_hotkey->fifo,
1044 (unsigned char *)&keycode, sizeof(keycode),
1045 &fujitsu_hotkey->fifo_lock);
1046 if (status != sizeof(keycode)) {
1047 vdbg_printk(FUJLAPTOP_DBG_WARN,
1048 "Could not push keycode [0x%x]\n", keycode);
1049 return;
1050 }
1051 input_report_key(input, keycode, 1);
1052 input_sync(input);
1053 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1054 "Push keycode into ringbuffer [%d]\n", keycode);
1055}
1056
1057static void acpi_fujitsu_hotkey_release(void)
1058{
1059 struct input_dev *input = fujitsu_hotkey->input;
1060 int keycode, status;
1061
1062 while (true) {
1063 status = kfifo_out_locked(&fujitsu_hotkey->fifo,
1064 (unsigned char *)&keycode,
1065 sizeof(keycode),
1066 &fujitsu_hotkey->fifo_lock);
1067 if (status != sizeof(keycode))
1068 return;
1069 input_report_key(input, keycode, 0);
1070 input_sync(input);
1071 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1072 "Pop keycode from ringbuffer [%d]\n", keycode);
1073 }
1074}
1075
1032static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) 1076static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
1033{ 1077{
1034 struct input_dev *input; 1078 struct input_dev *input;
1035 int keycode, keycode_r; 1079 int keycode;
1036 unsigned int irb = 1; 1080 unsigned int irb = 1;
1037 int i, status; 1081 int i;
1038 1082
1039 input = fujitsu_hotkey->input; 1083 input = fujitsu_hotkey->input;
1040 1084
1085 if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
1086 keycode = KEY_UNKNOWN;
1087 vdbg_printk(FUJLAPTOP_DBG_WARN,
1088 "Unsupported event [0x%x]\n", event);
1089 input_report_key(input, keycode, 1);
1090 input_sync(input);
1091 input_report_key(input, keycode, 0);
1092 input_sync(input);
1093 return;
1094 }
1095
1041 if (fujitsu_hotkey->rfkill_supported) 1096 if (fujitsu_hotkey->rfkill_supported)
1042 fujitsu_hotkey->rfkill_state = 1097 fujitsu_hotkey->rfkill_state =
1043 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 1098 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
1044 1099
1045 switch (event) { 1100 i = 0;
1046 case ACPI_FUJITSU_NOTIFY_CODE1: 1101 while ((irb =
1047 i = 0; 1102 call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0
1048 while ((irb = 1103 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
1049 call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 1104 switch (irb & 0x4ff) {
1050 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { 1105 case KEY1_CODE:
1051 switch (irb & 0x4ff) { 1106 keycode = fujitsu->keycode1;
1052 case KEY1_CODE: 1107 break;
1053 keycode = fujitsu->keycode1; 1108 case KEY2_CODE:
1054 break; 1109 keycode = fujitsu->keycode2;
1055 case KEY2_CODE: 1110 break;
1056 keycode = fujitsu->keycode2; 1111 case KEY3_CODE:
1057 break; 1112 keycode = fujitsu->keycode3;
1058 case KEY3_CODE: 1113 break;
1059 keycode = fujitsu->keycode3; 1114 case KEY4_CODE:
1060 break; 1115 keycode = fujitsu->keycode4;
1061 case KEY4_CODE: 1116 break;
1062 keycode = fujitsu->keycode4; 1117 case KEY5_CODE:
1063 break; 1118 keycode = fujitsu->keycode5;
1064 case KEY5_CODE: 1119 break;
1065 keycode = fujitsu->keycode5; 1120 case 0:
1066 break; 1121 keycode = 0;
1067 case 0: 1122 break;
1068 keycode = 0; 1123 default:
1069 break; 1124 vdbg_printk(FUJLAPTOP_DBG_WARN,
1070 default: 1125 "Unknown GIRB result [%x]\n", irb);
1071 vdbg_printk(FUJLAPTOP_DBG_WARN, 1126 keycode = -1;
1072 "Unknown GIRB result [%x]\n", irb); 1127 break;
1073 keycode = -1;
1074 break;
1075 }
1076 if (keycode > 0) {
1077 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1078 "Push keycode into ringbuffer [%d]\n",
1079 keycode);
1080 status = kfifo_in_locked(&fujitsu_hotkey->fifo,
1081 (unsigned char *)&keycode,
1082 sizeof(keycode),
1083 &fujitsu_hotkey->fifo_lock);
1084 if (status != sizeof(keycode)) {
1085 vdbg_printk(FUJLAPTOP_DBG_WARN,
1086 "Could not push keycode [0x%x]\n",
1087 keycode);
1088 } else {
1089 input_report_key(input, keycode, 1);
1090 input_sync(input);
1091 }
1092 } else if (keycode == 0) {
1093 while ((status =
1094 kfifo_out_locked(
1095 &fujitsu_hotkey->fifo,
1096 (unsigned char *) &keycode_r,
1097 sizeof(keycode_r),
1098 &fujitsu_hotkey->fifo_lock))
1099 == sizeof(keycode_r)) {
1100 input_report_key(input, keycode_r, 0);
1101 input_sync(input);
1102 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1103 "Pop keycode from ringbuffer [%d]\n",
1104 keycode_r);
1105 }
1106 }
1107 } 1128 }
1108 1129
1109 /* On some models (first seen on the Skylake-based Lifebook 1130 if (keycode > 0)
1110 * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is 1131 acpi_fujitsu_hotkey_press(keycode);
1111 * handled in software; its state is queried using FUNC_RFKILL 1132 else if (keycode == 0)
1112 */ 1133 acpi_fujitsu_hotkey_release();
1113 if ((fujitsu_hotkey->rfkill_supported & BIT(26)) && 1134 }
1114 (call_fext_func(FUNC_RFKILL, 0x1, 0x0, 0x0) & BIT(26))) {
1115 keycode = KEY_TOUCHPAD_TOGGLE;
1116 input_report_key(input, keycode, 1);
1117 input_sync(input);
1118 input_report_key(input, keycode, 0);
1119 input_sync(input);
1120 }
1121 1135
1122 break; 1136 /* On some models (first seen on the Skylake-based Lifebook
1123 default: 1137 * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
1124 keycode = KEY_UNKNOWN; 1138 * handled in software; its state is queried using FUNC_RFKILL
1125 vdbg_printk(FUJLAPTOP_DBG_WARN, 1139 */
1126 "Unsupported event [0x%x]\n", event); 1140 if ((fujitsu_hotkey->rfkill_supported & BIT(26)) &&
1141 (call_fext_func(FUNC_RFKILL, 0x1, 0x0, 0x0) & BIT(26))) {
1142 keycode = KEY_TOUCHPAD_TOGGLE;
1127 input_report_key(input, keycode, 1); 1143 input_report_key(input, keycode, 1);
1128 input_sync(input); 1144 input_sync(input);
1129 input_report_key(input, keycode, 0); 1145 input_report_key(input, keycode, 0);
1130 input_sync(input); 1146 input_sync(input);
1131 break;
1132 } 1147 }
1148
1133} 1149}
1134 1150
1135/* Initialization */ 1151/* Initialization */
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 09356684c32f..493d8910a74e 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -251,6 +251,7 @@ static const struct dmi_system_id lis3lv02d_dmi_ids[] = {
251 AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), 251 AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
252 AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), 252 AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
253 AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted), 253 AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted),
254 AXIS_DMI_MATCH("HPZBook17", "HP ZBook 17", xy_swap_yz_inverted),
254 { NULL, } 255 { NULL, }
255/* Laptop models without axis info (yet): 256/* Laptop models without axis info (yet):
256 * "NC6910" "HP Compaq 6910" 257 * "NC6910" "HP Compaq 6910"
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index cb3ab2b212b1..bcf438f38781 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Intel HID event driver for Windows 8 2 * Intel HID event & 5 button array driver
3 * 3 *
4 * Copyright (C) 2015 Alex Hung <alex.hung@canonical.com> 4 * Copyright (C) 2015 Alex Hung <alex.hung@canonical.com>
5 * Copyright (C) 2015 Andrew Lutomirski <luto@kernel.org> 5 * Copyright (C) 2015 Andrew Lutomirski <luto@kernel.org>
@@ -57,8 +57,24 @@ static const struct key_entry intel_hid_keymap[] = {
57 { KE_END }, 57 { KE_END },
58}; 58};
59 59
60/* 5 button array notification value. */
61static const struct key_entry intel_array_keymap[] = {
62 { KE_KEY, 0xC2, { KEY_LEFTMETA } }, /* Press */
63 { KE_IGNORE, 0xC3, { KEY_LEFTMETA } }, /* Release */
64 { KE_KEY, 0xC4, { KEY_VOLUMEUP } }, /* Press */
65 { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* Release */
66 { KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* Press */
67 { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* Release */
68 { KE_SW, 0xC8, { .sw = { SW_ROTATE_LOCK, 1 } } }, /* Press */
69 { KE_SW, 0xC9, { .sw = { SW_ROTATE_LOCK, 0 } } }, /* Release */
70 { KE_KEY, 0xCE, { KEY_POWER } }, /* Press */
71 { KE_IGNORE, 0xCF, { KEY_POWER } }, /* Release */
72 { KE_END },
73};
74
60struct intel_hid_priv { 75struct intel_hid_priv {
61 struct input_dev *input_dev; 76 struct input_dev *input_dev;
77 struct input_dev *array;
62}; 78};
63 79
64static int intel_hid_set_enable(struct device *device, int enable) 80static int intel_hid_set_enable(struct device *device, int enable)
@@ -78,15 +94,43 @@ static int intel_hid_set_enable(struct device *device, int enable)
78 return 0; 94 return 0;
79} 95}
80 96
97static void intel_button_array_enable(struct device *device, bool enable)
98{
99 struct intel_hid_priv *priv = dev_get_drvdata(device);
100 acpi_handle handle = ACPI_HANDLE(device);
101 unsigned long long button_cap;
102 acpi_status status;
103
104 if (!priv->array)
105 return;
106
107 /* Query supported platform features */
108 status = acpi_evaluate_integer(handle, "BTNC", NULL, &button_cap);
109 if (ACPI_FAILURE(status)) {
110 dev_warn(device, "failed to get button capability\n");
111 return;
112 }
113
114 /* Enable|disable features - power button is always enabled */
115 status = acpi_execute_simple_method(handle, "BTNE",
116 enable ? button_cap : 1);
117 if (ACPI_FAILURE(status))
118 dev_warn(device, "failed to set button capability\n");
119}
120
81static int intel_hid_pl_suspend_handler(struct device *device) 121static int intel_hid_pl_suspend_handler(struct device *device)
82{ 122{
83 intel_hid_set_enable(device, 0); 123 intel_hid_set_enable(device, 0);
124 intel_button_array_enable(device, false);
125
84 return 0; 126 return 0;
85} 127}
86 128
87static int intel_hid_pl_resume_handler(struct device *device) 129static int intel_hid_pl_resume_handler(struct device *device)
88{ 130{
89 intel_hid_set_enable(device, 1); 131 intel_hid_set_enable(device, 1);
132 intel_button_array_enable(device, true);
133
90 return 0; 134 return 0;
91} 135}
92 136
@@ -126,6 +170,27 @@ err_free_device:
126 return ret; 170 return ret;
127} 171}
128 172
173static int intel_button_array_input_setup(struct platform_device *device)
174{
175 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
176 int ret;
177
178 /* Setup input device for 5 button array */
179 priv->array = devm_input_allocate_device(&device->dev);
180 if (!priv->array)
181 return -ENOMEM;
182
183 ret = sparse_keymap_setup(priv->array, intel_array_keymap, NULL);
184 if (ret)
185 return ret;
186
187 priv->array->dev.parent = &device->dev;
188 priv->array->name = "Intel HID 5 button array";
189 priv->array->id.bustype = BUS_HOST;
190
191 return input_register_device(priv->array);
192}
193
129static void intel_hid_input_destroy(struct platform_device *device) 194static void intel_hid_input_destroy(struct platform_device *device)
130{ 195{
131 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); 196 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
@@ -140,10 +205,11 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
140 unsigned long long ev_index; 205 unsigned long long ev_index;
141 acpi_status status; 206 acpi_status status;
142 207
143 /* The platform spec only defines one event code: 0xC0. */ 208 /* 0xC0 is for HID events, other values are for 5 button array */
144 if (event != 0xc0) { 209 if (event != 0xc0) {
145 dev_warn(&device->dev, "received unknown event (0x%x)\n", 210 if (!priv->array ||
146 event); 211 !sparse_keymap_report_event(priv->array, event, 1, true))
212 dev_info(&device->dev, "unknown event 0x%x\n", event);
147 return; 213 return;
148 } 214 }
149 215
@@ -161,8 +227,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
161static int intel_hid_probe(struct platform_device *device) 227static int intel_hid_probe(struct platform_device *device)
162{ 228{
163 acpi_handle handle = ACPI_HANDLE(&device->dev); 229 acpi_handle handle = ACPI_HANDLE(&device->dev);
230 unsigned long long event_cap, mode;
164 struct intel_hid_priv *priv; 231 struct intel_hid_priv *priv;
165 unsigned long long mode;
166 acpi_status status; 232 acpi_status status;
167 int err; 233 int err;
168 234
@@ -193,6 +259,15 @@ static int intel_hid_probe(struct platform_device *device)
193 return err; 259 return err;
194 } 260 }
195 261
262 /* Setup 5 button array */
263 status = acpi_evaluate_integer(handle, "HEBC", NULL, &event_cap);
264 if (ACPI_SUCCESS(status) && (event_cap & 0x20000)) {
265 dev_info(&device->dev, "platform supports 5 button array\n");
266 err = intel_button_array_input_setup(device);
267 if (err)
268 pr_err("Failed to setup Intel 5 button array hotkeys\n");
269 }
270
196 status = acpi_install_notify_handler(handle, 271 status = acpi_install_notify_handler(handle,
197 ACPI_DEVICE_NOTIFY, 272 ACPI_DEVICE_NOTIFY,
198 notify_handler, 273 notify_handler,
@@ -206,6 +281,16 @@ static int intel_hid_probe(struct platform_device *device)
206 if (err) 281 if (err)
207 goto err_remove_notify; 282 goto err_remove_notify;
208 283
284 if (priv->array) {
285 intel_button_array_enable(&device->dev, true);
286
287 /* Call button load method to enable HID power button */
288 status = acpi_evaluate_object(handle, "BTNL", NULL, NULL);
289 if (ACPI_FAILURE(status))
290 dev_warn(&device->dev,
291 "failed to enable HID power button\n");
292 }
293
209 return 0; 294 return 0;
210 295
211err_remove_notify: 296err_remove_notify:
@@ -224,6 +309,7 @@ static int intel_hid_remove(struct platform_device *device)
224 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 309 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
225 intel_hid_input_destroy(device); 310 intel_hid_input_destroy(device);
226 intel_hid_set_enable(&device->dev, 0); 311 intel_hid_set_enable(&device->dev, 0);
312 intel_button_array_enable(&device->dev, false);
227 313
228 /* 314 /*
229 * Even if we failed to shut off the event stream, we can still 315 * Even if we failed to shut off the event stream, we can still
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
index 361770568ad0..871cfa682519 100644
--- a/drivers/platform/x86/intel_mid_powerbtn.c
+++ b/drivers/platform/x86/intel_mid_powerbtn.c
@@ -1,7 +1,10 @@
1/* 1/*
2 * Power button driver for Medfield. 2 * Power button driver for Intel MID platforms.
3 * 3 *
4 * Copyright (C) 2010 Intel Corp 4 * Copyright (C) 2010,2017 Intel Corp
5 *
6 * Author: Hong Liu <hong.liu@intel.com>
7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
5 * 8 *
6 * 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
7 * 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
@@ -11,20 +14,20 @@
11 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details. 16 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 */ 17 */
19 18
20#include <linux/module.h>
21#include <linux/init.h> 19#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/platform_device.h>
25#include <linux/input.h> 20#include <linux/input.h>
21#include <linux/interrupt.h>
26#include <linux/mfd/intel_msic.h> 22#include <linux/mfd/intel_msic.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
27#include <linux/pm_wakeirq.h> 25#include <linux/pm_wakeirq.h>
26#include <linux/slab.h>
27
28#include <asm/cpu_device_id.h>
29#include <asm/intel-family.h>
30#include <asm/intel_scu_ipc.h>
28 31
29#define DRIVER_NAME "msic_power_btn" 32#define DRIVER_NAME "msic_power_btn"
30 33
@@ -36,37 +39,113 @@
36 */ 39 */
37#define MSIC_PWRBTNM (1 << 0) 40#define MSIC_PWRBTNM (1 << 0)
38 41
39static irqreturn_t mfld_pb_isr(int irq, void *dev_id) 42/* Intel Tangier */
43#define BCOVE_PB_LEVEL (1 << 4) /* 1 - release, 0 - press */
44
45/* Basin Cove PMIC */
46#define BCOVE_PBIRQ 0x02
47#define BCOVE_IRQLVL1MSK 0x0c
48#define BCOVE_PBIRQMASK 0x0d
49#define BCOVE_PBSTATUS 0x27
50
51struct mid_pb_ddata {
52 struct device *dev;
53 int irq;
54 struct input_dev *input;
55 unsigned short mirqlvl1_addr;
56 unsigned short pbstat_addr;
57 u8 pbstat_mask;
58 int (*setup)(struct mid_pb_ddata *ddata);
59};
60
61static int mid_pbstat(struct mid_pb_ddata *ddata, int *value)
40{ 62{
41 struct input_dev *input = dev_id; 63 struct input_dev *input = ddata->input;
42 int ret; 64 int ret;
43 u8 pbstat; 65 u8 pbstat;
44 66
45 ret = intel_msic_reg_read(INTEL_MSIC_PBSTATUS, &pbstat); 67 ret = intel_scu_ipc_ioread8(ddata->pbstat_addr, &pbstat);
68 if (ret)
69 return ret;
70
46 dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat); 71 dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat);
47 72
73 *value = !(pbstat & ddata->pbstat_mask);
74 return 0;
75}
76
77static int mid_irq_ack(struct mid_pb_ddata *ddata)
78{
79 return intel_scu_ipc_update_register(ddata->mirqlvl1_addr, 0, MSIC_PWRBTNM);
80}
81
82static int mrfld_setup(struct mid_pb_ddata *ddata)
83{
84 /* Unmask the PBIRQ and MPBIRQ on Tangier */
85 intel_scu_ipc_update_register(BCOVE_PBIRQ, 0, MSIC_PWRBTNM);
86 intel_scu_ipc_update_register(BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM);
87
88 return 0;
89}
90
91static irqreturn_t mid_pb_isr(int irq, void *dev_id)
92{
93 struct mid_pb_ddata *ddata = dev_id;
94 struct input_dev *input = ddata->input;
95 int value = 0;
96 int ret;
97
98 ret = mid_pbstat(ddata, &value);
48 if (ret < 0) { 99 if (ret < 0) {
49 dev_err(input->dev.parent, "Read error %d while reading" 100 dev_err(input->dev.parent,
50 " MSIC_PB_STATUS\n", ret); 101 "Read error %d while reading MSIC_PB_STATUS\n", ret);
51 } else { 102 } else {
52 input_event(input, EV_KEY, KEY_POWER, 103 input_event(input, EV_KEY, KEY_POWER, value);
53 !(pbstat & MSIC_PB_LEVEL));
54 input_sync(input); 104 input_sync(input);
55 } 105 }
56 106
107 mid_irq_ack(ddata);
57 return IRQ_HANDLED; 108 return IRQ_HANDLED;
58} 109}
59 110
60static int mfld_pb_probe(struct platform_device *pdev) 111static struct mid_pb_ddata mfld_ddata = {
112 .mirqlvl1_addr = INTEL_MSIC_IRQLVL1MSK,
113 .pbstat_addr = INTEL_MSIC_PBSTATUS,
114 .pbstat_mask = MSIC_PB_LEVEL,
115};
116
117static struct mid_pb_ddata mrfld_ddata = {
118 .mirqlvl1_addr = BCOVE_IRQLVL1MSK,
119 .pbstat_addr = BCOVE_PBSTATUS,
120 .pbstat_mask = BCOVE_PB_LEVEL,
121 .setup = mrfld_setup,
122};
123
124#define ICPU(model, ddata) \
125 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata }
126
127static const struct x86_cpu_id mid_pb_cpu_ids[] = {
128 ICPU(INTEL_FAM6_ATOM_PENWELL, mfld_ddata),
129 ICPU(INTEL_FAM6_ATOM_MERRIFIELD, mrfld_ddata),
130 {}
131};
132
133static int mid_pb_probe(struct platform_device *pdev)
61{ 134{
135 const struct x86_cpu_id *id;
136 struct mid_pb_ddata *ddata;
62 struct input_dev *input; 137 struct input_dev *input;
63 int irq = platform_get_irq(pdev, 0); 138 int irq = platform_get_irq(pdev, 0);
64 int error; 139 int error;
65 140
141 id = x86_match_cpu(mid_pb_cpu_ids);
142 if (!id)
143 return -ENODEV;
144
66 if (irq < 0) 145 if (irq < 0)
67 return -EINVAL; 146 return -EINVAL;
68 147
69 input = input_allocate_device(); 148 input = devm_input_allocate_device(&pdev->dev);
70 if (!input) 149 if (!input)
71 return -ENOMEM; 150 return -ENOMEM;
72 151
@@ -77,25 +156,36 @@ static int mfld_pb_probe(struct platform_device *pdev)
77 156
78 input_set_capability(input, EV_KEY, KEY_POWER); 157 input_set_capability(input, EV_KEY, KEY_POWER);
79 158
80 error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_ONESHOT, 159 ddata = (struct mid_pb_ddata *)id->driver_data;
81 DRIVER_NAME, input); 160 if (!ddata)
82 if (error) { 161 return -ENODATA;
83 dev_err(&pdev->dev, "Unable to request irq %d for mfld power" 162
84 "button\n", irq); 163 ddata->dev = &pdev->dev;
85 goto err_free_input; 164 ddata->irq = irq;
165 ddata->input = input;
166
167 if (ddata->setup) {
168 error = ddata->setup(ddata);
169 if (error)
170 return error;
86 } 171 }
87 172
88 device_init_wakeup(&pdev->dev, true); 173 error = devm_request_threaded_irq(&pdev->dev, irq, NULL, mid_pb_isr,
89 dev_pm_set_wake_irq(&pdev->dev, irq); 174 IRQF_ONESHOT, DRIVER_NAME, ddata);
175 if (error) {
176 dev_err(&pdev->dev,
177 "Unable to request irq %d for MID power button\n", irq);
178 return error;
179 }
90 180
91 error = input_register_device(input); 181 error = input_register_device(input);
92 if (error) { 182 if (error) {
93 dev_err(&pdev->dev, "Unable to register input dev, error " 183 dev_err(&pdev->dev,
94 "%d\n", error); 184 "Unable to register input dev, error %d\n", error);
95 goto err_free_irq; 185 return error;
96 } 186 }
97 187
98 platform_set_drvdata(pdev, input); 188 platform_set_drvdata(pdev, ddata);
99 189
100 /* 190 /*
101 * SCU firmware might send power button interrupts to IA core before 191 * SCU firmware might send power button interrupts to IA core before
@@ -107,46 +197,39 @@ static int mfld_pb_probe(struct platform_device *pdev)
107 * initialization. The race happens rarely. So we needn't worry 197 * initialization. The race happens rarely. So we needn't worry
108 * about it. 198 * about it.
109 */ 199 */
110 error = intel_msic_reg_update(INTEL_MSIC_IRQLVL1MSK, 0, MSIC_PWRBTNM); 200 error = mid_irq_ack(ddata);
111 if (error) { 201 if (error) {
112 dev_err(&pdev->dev, "Unable to clear power button interrupt, " 202 dev_err(&pdev->dev,
113 "error: %d\n", error); 203 "Unable to clear power button interrupt, error: %d\n",
114 goto err_free_irq; 204 error);
205 return error;
115 } 206 }
116 207
117 return 0; 208 device_init_wakeup(&pdev->dev, true);
209 dev_pm_set_wake_irq(&pdev->dev, irq);
118 210
119err_free_irq: 211 return 0;
120 free_irq(irq, input);
121err_free_input:
122 input_free_device(input);
123 return error;
124} 212}
125 213
126static int mfld_pb_remove(struct platform_device *pdev) 214static int mid_pb_remove(struct platform_device *pdev)
127{ 215{
128 struct input_dev *input = platform_get_drvdata(pdev);
129 int irq = platform_get_irq(pdev, 0);
130
131 dev_pm_clear_wake_irq(&pdev->dev); 216 dev_pm_clear_wake_irq(&pdev->dev);
132 device_init_wakeup(&pdev->dev, false); 217 device_init_wakeup(&pdev->dev, false);
133 free_irq(irq, input);
134 input_unregister_device(input);
135 218
136 return 0; 219 return 0;
137} 220}
138 221
139static struct platform_driver mfld_pb_driver = { 222static struct platform_driver mid_pb_driver = {
140 .driver = { 223 .driver = {
141 .name = DRIVER_NAME, 224 .name = DRIVER_NAME,
142 }, 225 },
143 .probe = mfld_pb_probe, 226 .probe = mid_pb_probe,
144 .remove = mfld_pb_remove, 227 .remove = mid_pb_remove,
145}; 228};
146 229
147module_platform_driver(mfld_pb_driver); 230module_platform_driver(mid_pb_driver);
148 231
149MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>"); 232MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
150MODULE_DESCRIPTION("Intel Medfield Power Button Driver"); 233MODULE_DESCRIPTION("Intel MID Power Button Driver");
151MODULE_LICENSE("GPL v2"); 234MODULE_LICENSE("GPL v2");
152MODULE_ALIAS("platform:" DRIVER_NAME); 235MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 0df3c9d37509..008a76903cbf 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -549,9 +549,9 @@ static int mid_thermal_remove(struct platform_device *pdev)
549 549
550static const struct platform_device_id therm_id_table[] = { 550static const struct platform_device_id therm_id_table[] = {
551 { DRIVER_NAME, 1 }, 551 { DRIVER_NAME, 1 },
552 { "msic_thermal", 1 },
553 { } 552 { }
554}; 553};
554MODULE_DEVICE_TABLE(platform, therm_id_table);
555 555
556static struct platform_driver mid_thermal_driver = { 556static struct platform_driver mid_thermal_driver = {
557 .driver = { 557 .driver = {
diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c
index b130b8c9b9d7..914bcd2edbde 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -188,8 +188,7 @@ static int pmc_core_check_read_lock_bit(void)
188 u32 value; 188 u32 value;
189 189
190 value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_CFG_OFFSET); 190 value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_CFG_OFFSET);
191 return test_bit(SPT_PMC_READ_DISABLE_BIT, 191 return value & BIT(SPT_PMC_READ_DISABLE_BIT);
192 (unsigned long *)&value);
193} 192}
194 193
195#if IS_ENABLED(CONFIG_DEBUG_FS) 194#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -238,8 +237,7 @@ static int pmc_core_mtpmc_link_status(void)
238 u32 value; 237 u32 value;
239 238
240 value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); 239 value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET);
241 return test_bit(SPT_PMC_MSG_FULL_STS_BIT, 240 return value & BIT(SPT_PMC_MSG_FULL_STS_BIT);
242 (unsigned long *)&value);
243} 241}
244 242
245static int pmc_core_send_msg(u32 *addr_xram) 243static int pmc_core_send_msg(u32 *addr_xram)
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index 0bf51d574fa9..0651d47b8eeb 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -32,7 +32,10 @@
32#include <linux/notifier.h> 32#include <linux/notifier.h>
33#include <linux/suspend.h> 33#include <linux/suspend.h>
34#include <linux/acpi.h> 34#include <linux/acpi.h>
35#include <linux/io-64-nonatomic-lo-hi.h>
36
35#include <asm/intel_pmc_ipc.h> 37#include <asm/intel_pmc_ipc.h>
38
36#include <linux/platform_data/itco_wdt.h> 39#include <linux/platform_data/itco_wdt.h>
37 40
38/* 41/*
@@ -54,6 +57,18 @@
54#define IPC_WRITE_BUFFER 0x80 57#define IPC_WRITE_BUFFER 0x80
55#define IPC_READ_BUFFER 0x90 58#define IPC_READ_BUFFER 0x90
56 59
60/* PMC Global Control Registers */
61#define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078
62#define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080
63
64/* Residency with clock rate at 19.2MHz to usecs */
65#define S0IX_RESIDENCY_IN_USECS(d, s) \
66({ \
67 u64 result = 10ull * ((d) + (s)); \
68 do_div(result, 192); \
69 result; \
70})
71
57/* 72/*
58 * 16-byte buffer for sending data associated with IPC command. 73 * 16-byte buffer for sending data associated with IPC command.
59 */ 74 */
@@ -68,7 +83,7 @@
68#define PLAT_RESOURCE_IPC_INDEX 0 83#define PLAT_RESOURCE_IPC_INDEX 0
69#define PLAT_RESOURCE_IPC_SIZE 0x1000 84#define PLAT_RESOURCE_IPC_SIZE 0x1000
70#define PLAT_RESOURCE_GCR_OFFSET 0x1008 85#define PLAT_RESOURCE_GCR_OFFSET 0x1008
71#define PLAT_RESOURCE_GCR_SIZE 0x4 86#define PLAT_RESOURCE_GCR_SIZE 0x1000
72#define PLAT_RESOURCE_BIOS_DATA_INDEX 1 87#define PLAT_RESOURCE_BIOS_DATA_INDEX 1
73#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 88#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
74#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3 89#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3
@@ -97,8 +112,6 @@
97#define TCO_PMC_OFFSET 0x8 112#define TCO_PMC_OFFSET 0x8
98#define TCO_PMC_SIZE 0x4 113#define TCO_PMC_SIZE 0x4
99 114
100static const int iTCO_version = 3;
101
102static struct intel_pmc_ipc_dev { 115static struct intel_pmc_ipc_dev {
103 struct device *dev; 116 struct device *dev;
104 void __iomem *ipc_base; 117 void __iomem *ipc_base;
@@ -115,6 +128,7 @@ static struct intel_pmc_ipc_dev {
115 /* gcr */ 128 /* gcr */
116 resource_size_t gcr_base; 129 resource_size_t gcr_base;
117 int gcr_size; 130 int gcr_size;
131 bool has_gcr_regs;
118 132
119 /* punit */ 133 /* punit */
120 struct platform_device *punit_dev; 134 struct platform_device *punit_dev;
@@ -180,6 +194,11 @@ static inline u32 ipc_data_readl(u32 offset)
180 return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 194 return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
181} 195}
182 196
197static inline u64 gcr_data_readq(u32 offset)
198{
199 return readq(ipcdev.ipc_base + offset);
200}
201
183static int intel_pmc_ipc_check_status(void) 202static int intel_pmc_ipc_check_status(void)
184{ 203{
185 int status; 204 int status;
@@ -389,6 +408,7 @@ static void ipc_pci_remove(struct pci_dev *pdev)
389static const struct pci_device_id ipc_pci_ids[] = { 408static const struct pci_device_id ipc_pci_ids[] = {
390 {PCI_VDEVICE(INTEL, 0x0a94), 0}, 409 {PCI_VDEVICE(INTEL, 0x0a94), 0},
391 {PCI_VDEVICE(INTEL, 0x1a94), 0}, 410 {PCI_VDEVICE(INTEL, 0x1a94), 0},
411 {PCI_VDEVICE(INTEL, 0x5a94), 0},
392 { 0,} 412 { 0,}
393}; 413};
394MODULE_DEVICE_TABLE(pci, ipc_pci_ids); 414MODULE_DEVICE_TABLE(pci, ipc_pci_ids);
@@ -712,7 +732,8 @@ static int ipc_plat_get_res(struct platform_device *pdev)
712 dev_err(&pdev->dev, "Failed to get ipc resource\n"); 732 dev_err(&pdev->dev, "Failed to get ipc resource\n");
713 return -ENXIO; 733 return -ENXIO;
714 } 734 }
715 size = PLAT_RESOURCE_IPC_SIZE; 735 size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE;
736
716 if (!request_mem_region(res->start, size, pdev->name)) { 737 if (!request_mem_region(res->start, size, pdev->name)) {
717 dev_err(&pdev->dev, "Failed to request ipc resource\n"); 738 dev_err(&pdev->dev, "Failed to request ipc resource\n");
718 return -EBUSY; 739 return -EBUSY;
@@ -748,6 +769,28 @@ static int ipc_plat_get_res(struct platform_device *pdev)
748 return 0; 769 return 0;
749} 770}
750 771
772/**
773 * intel_pmc_s0ix_counter_read() - Read S0ix residency.
774 * @data: Out param that contains current S0ix residency count.
775 *
776 * Return: an error code or 0 on success.
777 */
778int intel_pmc_s0ix_counter_read(u64 *data)
779{
780 u64 deep, shlw;
781
782 if (!ipcdev.has_gcr_regs)
783 return -EACCES;
784
785 deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET);
786 shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET);
787
788 *data = S0IX_RESIDENCY_IN_USECS(deep, shlw);
789
790 return 0;
791}
792EXPORT_SYMBOL_GPL(intel_pmc_s0ix_counter_read);
793
751#ifdef CONFIG_ACPI 794#ifdef CONFIG_ACPI
752static const struct acpi_device_id ipc_acpi_ids[] = { 795static const struct acpi_device_id ipc_acpi_ids[] = {
753 { "INT34D2", 0}, 796 { "INT34D2", 0},
@@ -797,6 +840,8 @@ static int ipc_plat_probe(struct platform_device *pdev)
797 goto err_sys; 840 goto err_sys;
798 } 841 }
799 842
843 ipcdev.has_gcr_regs = true;
844
800 return 0; 845 return 0;
801err_sys: 846err_sys:
802 free_irq(ipcdev.irq, &ipcdev); 847 free_irq(ipcdev.irq, &ipcdev);
@@ -808,8 +853,11 @@ err_device:
808 iounmap(ipcdev.ipc_base); 853 iounmap(ipcdev.ipc_base);
809 res = platform_get_resource(pdev, IORESOURCE_MEM, 854 res = platform_get_resource(pdev, IORESOURCE_MEM,
810 PLAT_RESOURCE_IPC_INDEX); 855 PLAT_RESOURCE_IPC_INDEX);
811 if (res) 856 if (res) {
812 release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE); 857 release_mem_region(res->start,
858 PLAT_RESOURCE_IPC_SIZE +
859 PLAT_RESOURCE_GCR_SIZE);
860 }
813 return ret; 861 return ret;
814} 862}
815 863
@@ -825,8 +873,11 @@ static int ipc_plat_remove(struct platform_device *pdev)
825 iounmap(ipcdev.ipc_base); 873 iounmap(ipcdev.ipc_base);
826 res = platform_get_resource(pdev, IORESOURCE_MEM, 874 res = platform_get_resource(pdev, IORESOURCE_MEM,
827 PLAT_RESOURCE_IPC_INDEX); 875 PLAT_RESOURCE_IPC_INDEX);
828 if (res) 876 if (res) {
829 release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE); 877 release_mem_region(res->start,
878 PLAT_RESOURCE_IPC_SIZE +
879 PLAT_RESOURCE_GCR_SIZE);
880 }
830 ipcdev.dev = NULL; 881 ipcdev.dev = NULL;
831 return 0; 882 return 0;
832} 883}
diff --git a/drivers/platform/x86/intel_turbo_max_3.c b/drivers/platform/x86/intel_turbo_max_3.c
new file mode 100644
index 000000000000..4f60d8e32a0a
--- /dev/null
+++ b/drivers/platform/x86/intel_turbo_max_3.c
@@ -0,0 +1,151 @@
1/*
2 * Intel Turbo Boost Max Technology 3.0 legacy (non HWP) enumeration driver
3 * Copyright (c) 2017, Intel Corporation.
4 * All rights reserved.
5 *
6 * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 */
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/topology.h>
23#include <linux/workqueue.h>
24#include <linux/cpuhotplug.h>
25#include <linux/cpufeature.h>
26#include <asm/cpu_device_id.h>
27#include <asm/intel-family.h>
28
29#define MSR_OC_MAILBOX 0x150
30#define MSR_OC_MAILBOX_CMD_OFFSET 32
31#define MSR_OC_MAILBOX_RSP_OFFSET 32
32#define MSR_OC_MAILBOX_BUSY_BIT 63
33#define OC_MAILBOX_FC_CONTROL_CMD 0x1C
34
35/*
36 * Typical latency to get mail box response is ~3us, It takes +3 us to
37 * process reading mailbox after issuing mailbox write on a Broadwell 3.4 GHz
38 * system. So for most of the time, the first mailbox read should have the
39 * response, but to avoid some boundary cases retry twice.
40 */
41#define OC_MAILBOX_RETRY_COUNT 2
42
43static int get_oc_core_priority(unsigned int cpu)
44{
45 u64 value, cmd = OC_MAILBOX_FC_CONTROL_CMD;
46 int ret, i;
47
48 /* Issue favored core read command */
49 value = cmd << MSR_OC_MAILBOX_CMD_OFFSET;
50 /* Set the busy bit to indicate OS is trying to issue command */
51 value |= BIT_ULL(MSR_OC_MAILBOX_BUSY_BIT);
52 ret = wrmsrl_safe(MSR_OC_MAILBOX, value);
53 if (ret) {
54 pr_debug("cpu %d OC mailbox write failed\n", cpu);
55 return ret;
56 }
57
58 for (i = 0; i < OC_MAILBOX_RETRY_COUNT; ++i) {
59 ret = rdmsrl_safe(MSR_OC_MAILBOX, &value);
60 if (ret) {
61 pr_debug("cpu %d OC mailbox read failed\n", cpu);
62 break;
63 }
64
65 if (value & BIT_ULL(MSR_OC_MAILBOX_BUSY_BIT)) {
66 pr_debug("cpu %d OC mailbox still processing\n", cpu);
67 ret = -EBUSY;
68 continue;
69 }
70
71 if ((value >> MSR_OC_MAILBOX_RSP_OFFSET) & 0xff) {
72 pr_debug("cpu %d OC mailbox cmd failed\n", cpu);
73 ret = -ENXIO;
74 break;
75 }
76
77 ret = value & 0xff;
78 pr_debug("cpu %d max_ratio %d\n", cpu, ret);
79 break;
80 }
81
82 return ret;
83}
84
85/*
86 * The work item is needed to avoid CPU hotplug locking issues. The function
87 * itmt_legacy_set_priority() is called from CPU online callback, so can't
88 * call sched_set_itmt_support() from there as this function will aquire
89 * hotplug locks in its path.
90 */
91static void itmt_legacy_work_fn(struct work_struct *work)
92{
93 sched_set_itmt_support();
94}
95
96static DECLARE_WORK(sched_itmt_work, itmt_legacy_work_fn);
97
98static int itmt_legacy_cpu_online(unsigned int cpu)
99{
100 static u32 max_highest_perf = 0, min_highest_perf = U32_MAX;
101 int priority;
102
103 priority = get_oc_core_priority(cpu);
104 if (priority < 0)
105 return 0;
106
107 sched_set_itmt_core_prio(priority, cpu);
108
109 /* Enable ITMT feature when a core with different priority is found */
110 if (max_highest_perf <= min_highest_perf) {
111 if (priority > max_highest_perf)
112 max_highest_perf = priority;
113
114 if (priority < min_highest_perf)
115 min_highest_perf = priority;
116
117 if (max_highest_perf > min_highest_perf)
118 schedule_work(&sched_itmt_work);
119 }
120
121 return 0;
122}
123
124#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
125
126static const struct x86_cpu_id itmt_legacy_cpu_ids[] = {
127 ICPU(INTEL_FAM6_BROADWELL_X),
128 {}
129};
130
131static int __init itmt_legacy_init(void)
132{
133 const struct x86_cpu_id *id;
134 int ret;
135
136 id = x86_match_cpu(itmt_legacy_cpu_ids);
137 if (!id)
138 return -ENODEV;
139
140 if (boot_cpu_has(X86_FEATURE_HWP))
141 return -ENODEV;
142
143 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
144 "platform/x86/turbo_max_3:online",
145 itmt_legacy_cpu_online, NULL);
146 if (ret < 0)
147 return ret;
148
149 return 0;
150}
151late_initcall(itmt_legacy_init)
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 25f15df5c2d7..8f98c211b440 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -45,6 +45,10 @@
45/* LPC bus IO offsets */ 45/* LPC bus IO offsets */
46#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 46#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
47#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 47#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
48#define MLXPLAT_CPLD_LPC_REG_AGGR_ADRR 0x253a
49#define MLXPLAT_CPLD_LPC_REG_PSU_ADRR 0x2558
50#define MLXPLAT_CPLD_LPC_REG_PWR_ADRR 0x2564
51#define MLXPLAT_CPLD_LPC_REG_FAN_ADRR 0x2588
48#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 52#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
49#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb 53#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
50#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda 54#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
@@ -56,6 +60,17 @@
56 MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \ 60 MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
57 MLXPLAT_CPLD_LPC_PIO_OFFSET) 61 MLXPLAT_CPLD_LPC_PIO_OFFSET)
58 62
63/* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
64#define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08
65#define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08
66#define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40
67#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
68 MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
69#define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04
70#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
71#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
72#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
73
59/* Start channel numbers */ 74/* Start channel numbers */
60#define MLXPLAT_CPLD_CH1 2 75#define MLXPLAT_CPLD_CH1 2
61#define MLXPLAT_CPLD_CH2 10 76#define MLXPLAT_CPLD_CH2 10
@@ -123,7 +138,7 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
123}; 138};
124 139
125/* Platform hotplug devices */ 140/* Platform hotplug devices */
126static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_psu[] = { 141static struct mlxcpld_hotplug_device mlxplat_mlxcpld_psu[] = {
127 { 142 {
128 .brdinfo = { I2C_BOARD_INFO("24c02", 0x51) }, 143 .brdinfo = { I2C_BOARD_INFO("24c02", 0x51) },
129 .bus = 10, 144 .bus = 10,
@@ -134,7 +149,7 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_psu[] = {
134 }, 149 },
135}; 150};
136 151
137static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_pwr[] = { 152static struct mlxcpld_hotplug_device mlxplat_mlxcpld_pwr[] = {
138 { 153 {
139 .brdinfo = { I2C_BOARD_INFO("dps460", 0x59) }, 154 .brdinfo = { I2C_BOARD_INFO("dps460", 0x59) },
140 .bus = 10, 155 .bus = 10,
@@ -145,7 +160,7 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_pwr[] = {
145 }, 160 },
146}; 161};
147 162
148static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_fan[] = { 163static struct mlxcpld_hotplug_device mlxplat_mlxcpld_fan[] = {
149 { 164 {
150 .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) }, 165 .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
151 .bus = 11, 166 .bus = 11,
@@ -166,38 +181,38 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_hotplug_fan[] = {
166 181
167/* Platform hotplug default data */ 182/* Platform hotplug default data */
168static 183static
169struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_hotplug_default_data = { 184struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_default_data = {
170 .top_aggr_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x3a), 185 .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
171 .top_aggr_mask = 0x48, 186 .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
172 .top_aggr_psu_mask = 0x08, 187 .top_aggr_psu_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
173 .psu_reg_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x58), 188 .psu_reg_offset = MLXPLAT_CPLD_LPC_REG_PSU_ADRR,
174 .psu_mask = 0x03, 189 .psu_mask = MLXPLAT_CPLD_PSU_MASK,
175 .psu_count = ARRAY_SIZE(mlxplat_mlxcpld_hotplug_psu), 190 .psu_count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
176 .psu = mlxplat_mlxcpld_hotplug_psu, 191 .psu = mlxplat_mlxcpld_psu,
177 .top_aggr_pwr_mask = 0x08, 192 .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
178 .pwr_reg_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x64), 193 .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
179 .pwr_mask = 0x03, 194 .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
180 .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_hotplug_pwr), 195 .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
181 .pwr = mlxplat_mlxcpld_hotplug_pwr, 196 .pwr = mlxplat_mlxcpld_pwr,
182 .top_aggr_fan_mask = 0x40, 197 .top_aggr_fan_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
183 .fan_reg_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x88), 198 .fan_reg_offset = MLXPLAT_CPLD_LPC_REG_FAN_ADRR,
184 .fan_mask = 0x0f, 199 .fan_mask = MLXPLAT_CPLD_FAN_MASK,
185 .fan_count = ARRAY_SIZE(mlxplat_mlxcpld_hotplug_fan), 200 .fan_count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
186 .fan = mlxplat_mlxcpld_hotplug_fan, 201 .fan = mlxplat_mlxcpld_fan,
187}; 202};
188 203
189/* Platform hotplug MSN21xx system family data */ 204/* Platform hotplug MSN21xx system family data */
190static 205static
191struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_hotplug_msn21xx_data = { 206struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
192 .top_aggr_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x3a), 207 .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
193 .top_aggr_mask = 0x04, 208 .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
194 .top_aggr_pwr_mask = 0x04, 209 .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
195 .pwr_reg_offset = (MLXPLAT_CPLD_LPC_REG_BASE_ADRR | 0x64), 210 .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
196 .pwr_mask = 0x03, 211 .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
197 .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_hotplug_pwr), 212 .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
198}; 213};
199 214
200static struct resource mlxplat_mlxcpld_hotplug_resources[] = { 215static struct resource mlxplat_mlxcpld_resources[] = {
201 [0] = DEFINE_RES_IRQ_NAMED(17, "mlxcpld-hotplug"), 216 [0] = DEFINE_RES_IRQ_NAMED(17, "mlxcpld-hotplug"),
202}; 217};
203 218
@@ -213,7 +228,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
213 mlxplat_mux_data[i].n_values = 228 mlxplat_mux_data[i].n_values =
214 ARRAY_SIZE(mlxplat_default_channels[i]); 229 ARRAY_SIZE(mlxplat_default_channels[i]);
215 } 230 }
216 mlxplat_hotplug = &mlxplat_mlxcpld_hotplug_default_data; 231 mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
217 232
218 return 1; 233 return 1;
219}; 234};
@@ -227,7 +242,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
227 mlxplat_mux_data[i].n_values = 242 mlxplat_mux_data[i].n_values =
228 ARRAY_SIZE(mlxplat_msn21xx_channels); 243 ARRAY_SIZE(mlxplat_msn21xx_channels);
229 } 244 }
230 mlxplat_hotplug = &mlxplat_mlxcpld_hotplug_msn21xx_data; 245 mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
231 246
232 return 1; 247 return 1;
233}; 248};
@@ -314,9 +329,10 @@ static int __init mlxplat_init(void)
314 } 329 }
315 330
316 priv->pdev_hotplug = platform_device_register_resndata( 331 priv->pdev_hotplug = platform_device_register_resndata(
317 &mlxplat_dev->dev, "mlxcpld-hotplug", -1, 332 &mlxplat_dev->dev, "mlxcpld-hotplug",
318 mlxplat_mlxcpld_hotplug_resources, 333 PLATFORM_DEVID_NONE,
319 ARRAY_SIZE(mlxplat_mlxcpld_hotplug_resources), 334 mlxplat_mlxcpld_resources,
335 ARRAY_SIZE(mlxplat_mlxcpld_resources),
320 mlxplat_hotplug, sizeof(*mlxplat_hotplug)); 336 mlxplat_hotplug, sizeof(*mlxplat_hotplug));
321 if (IS_ERR(priv->pdev_hotplug)) { 337 if (IS_ERR(priv->pdev_hotplug)) {
322 err = PTR_ERR(priv->pdev_hotplug); 338 err = PTR_ERR(priv->pdev_hotplug);
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
new file mode 100644
index 000000000000..02e11fdbf375
--- /dev/null
+++ b/drivers/platform/x86/silead_dmi.c
@@ -0,0 +1,136 @@
1/*
2 * Silead touchscreen driver DMI based configuration code
3 *
4 * Copyright (c) 2017 Red Hat Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Red Hat authors:
12 * Hans de Goede <hdegoede@redhat.com>
13 */
14
15#include <linux/acpi.h>
16#include <linux/device.h>
17#include <linux/dmi.h>
18#include <linux/i2c.h>
19#include <linux/notifier.h>
20#include <linux/property.h>
21#include <linux/string.h>
22
23struct silead_ts_dmi_data {
24 const char *acpi_name;
25 struct property_entry *properties;
26};
27
28static struct property_entry cube_iwork8_air_props[] = {
29 PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
30 PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
31 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
32 PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
33 PROPERTY_ENTRY_U32("silead,max-fingers", 10),
34 { }
35};
36
37static const struct silead_ts_dmi_data cube_iwork8_air_data = {
38 .acpi_name = "MSSL1680:00",
39 .properties = cube_iwork8_air_props,
40};
41
42static struct property_entry jumper_ezpad_mini3_props[] = {
43 PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
44 PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
45 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
46 PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
47 PROPERTY_ENTRY_U32("silead,max-fingers", 10),
48 { }
49};
50
51static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
52 .acpi_name = "MSSL1680:00",
53 .properties = jumper_ezpad_mini3_props,
54};
55
56static const struct dmi_system_id silead_ts_dmi_table[] = {
57 {
58 /* CUBE iwork8 Air */
59 .driver_data = (void *)&cube_iwork8_air_data,
60 .matches = {
61 DMI_MATCH(DMI_SYS_VENDOR, "cube"),
62 DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
63 DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
64 },
65 },
66 {
67 /* Jumper EZpad mini3 */
68 .driver_data = (void *)&jumper_ezpad_mini3_data,
69 .matches = {
70 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
71 /* jumperx.T87.KFBNEEA02 with the version-nr dropped */
72 DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
73 },
74 },
75 { },
76};
77
78static void silead_ts_dmi_add_props(struct device *dev)
79{
80 struct i2c_client *client = to_i2c_client(dev);
81 const struct dmi_system_id *dmi_id;
82 const struct silead_ts_dmi_data *ts_data;
83 int error;
84
85 dmi_id = dmi_first_match(silead_ts_dmi_table);
86 if (!dmi_id)
87 return;
88
89 ts_data = dmi_id->driver_data;
90 if (has_acpi_companion(dev) &&
91 !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
92 error = device_add_properties(dev, ts_data->properties);
93 if (error)
94 dev_err(dev, "failed to add properties: %d\n", error);
95 }
96}
97
98static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
99 unsigned long action, void *data)
100{
101 struct device *dev = data;
102
103 switch (action) {
104 case BUS_NOTIFY_ADD_DEVICE:
105 silead_ts_dmi_add_props(dev);
106 break;
107
108 default:
109 break;
110 }
111
112 return 0;
113}
114
115static struct notifier_block silead_ts_dmi_notifier = {
116 .notifier_call = silead_ts_dmi_notifier_call,
117};
118
119static int __init silead_ts_dmi_init(void)
120{
121 int error;
122
123 error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier);
124 if (error)
125 pr_err("%s: failed to register i2c bus notifier: %d\n",
126 __func__, error);
127
128 return error;
129}
130
131/*
132 * We are registering out notifier after i2c core is initialized and i2c bus
133 * itself is ready (which happens at postcore initcall level), but before
134 * ACPI starts enumerating devices (at subsys initcall level).
135 */
136arch_initcall(silead_ts_dmi_init);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cacb43fb1df7..1d18b32628ec 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -163,6 +163,7 @@ enum tpacpi_hkey_event_t {
163 TP_HKEY_EV_HOTKEY_BASE = 0x1001, /* first hotkey (FN+F1) */ 163 TP_HKEY_EV_HOTKEY_BASE = 0x1001, /* first hotkey (FN+F1) */
164 TP_HKEY_EV_BRGHT_UP = 0x1010, /* Brightness up */ 164 TP_HKEY_EV_BRGHT_UP = 0x1010, /* Brightness up */
165 TP_HKEY_EV_BRGHT_DOWN = 0x1011, /* Brightness down */ 165 TP_HKEY_EV_BRGHT_DOWN = 0x1011, /* Brightness down */
166 TP_HKEY_EV_KBD_LIGHT = 0x1012, /* Thinklight/kbd backlight */
166 TP_HKEY_EV_VOL_UP = 0x1015, /* Volume up or unmute */ 167 TP_HKEY_EV_VOL_UP = 0x1015, /* Volume up or unmute */
167 TP_HKEY_EV_VOL_DOWN = 0x1016, /* Volume down or unmute */ 168 TP_HKEY_EV_VOL_DOWN = 0x1016, /* Volume down or unmute */
168 TP_HKEY_EV_VOL_MUTE = 0x1017, /* Mixer output mute */ 169 TP_HKEY_EV_VOL_MUTE = 0x1017, /* Mixer output mute */
@@ -372,11 +373,9 @@ enum led_status_t {
372 TPACPI_LED_BLINK, 373 TPACPI_LED_BLINK,
373}; 374};
374 375
375/* Special LED class that can defer work */ 376/* tpacpi LED class */
376struct tpacpi_led_classdev { 377struct tpacpi_led_classdev {
377 struct led_classdev led_classdev; 378 struct led_classdev led_classdev;
378 struct work_struct work;
379 enum led_status_t new_state;
380 int led; 379 int led;
381}; 380};
382 381
@@ -1959,7 +1958,7 @@ enum { /* Positions of some of the keys in hotkey masks */
1959 TP_ACPI_HKEY_HIBERNATE_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF12, 1958 TP_ACPI_HKEY_HIBERNATE_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF12,
1960 TP_ACPI_HKEY_BRGHTUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNHOME, 1959 TP_ACPI_HKEY_BRGHTUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNHOME,
1961 TP_ACPI_HKEY_BRGHTDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNEND, 1960 TP_ACPI_HKEY_BRGHTDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNEND,
1962 TP_ACPI_HKEY_THNKLGHT_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP, 1961 TP_ACPI_HKEY_KBD_LIGHT_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP,
1963 TP_ACPI_HKEY_ZOOM_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNSPACE, 1962 TP_ACPI_HKEY_ZOOM_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNSPACE,
1964 TP_ACPI_HKEY_VOLUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEUP, 1963 TP_ACPI_HKEY_VOLUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEUP,
1965 TP_ACPI_HKEY_VOLDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEDOWN, 1964 TP_ACPI_HKEY_VOLDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
@@ -2344,7 +2343,7 @@ static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
2344 n->display_toggle = !!(d & TP_NVRAM_MASK_HKT_DISPLAY); 2343 n->display_toggle = !!(d & TP_NVRAM_MASK_HKT_DISPLAY);
2345 n->hibernate_toggle = !!(d & TP_NVRAM_MASK_HKT_HIBERNATE); 2344 n->hibernate_toggle = !!(d & TP_NVRAM_MASK_HKT_HIBERNATE);
2346 } 2345 }
2347 if (m & TP_ACPI_HKEY_THNKLGHT_MASK) { 2346 if (m & TP_ACPI_HKEY_KBD_LIGHT_MASK) {
2348 d = nvram_read_byte(TP_NVRAM_ADDR_THINKLIGHT); 2347 d = nvram_read_byte(TP_NVRAM_ADDR_THINKLIGHT);
2349 n->thinklight_toggle = !!(d & TP_NVRAM_MASK_THINKLIGHT); 2348 n->thinklight_toggle = !!(d & TP_NVRAM_MASK_THINKLIGHT);
2350 } 2349 }
@@ -5084,18 +5083,27 @@ static struct ibm_struct video_driver_data = {
5084 * Keyboard backlight subdriver 5083 * Keyboard backlight subdriver
5085 */ 5084 */
5086 5085
5086static enum led_brightness kbdlight_brightness;
5087static DEFINE_MUTEX(kbdlight_mutex);
5088
5087static int kbdlight_set_level(int level) 5089static int kbdlight_set_level(int level)
5088{ 5090{
5091 int ret = 0;
5092
5089 if (!hkey_handle) 5093 if (!hkey_handle)
5090 return -ENXIO; 5094 return -ENXIO;
5091 5095
5096 mutex_lock(&kbdlight_mutex);
5097
5092 if (!acpi_evalf(hkey_handle, NULL, "MLCS", "dd", level)) 5098 if (!acpi_evalf(hkey_handle, NULL, "MLCS", "dd", level))
5093 return -EIO; 5099 ret = -EIO;
5100 else
5101 kbdlight_brightness = level;
5094 5102
5095 return 0; 5103 mutex_unlock(&kbdlight_mutex);
5096}
5097 5104
5098static int kbdlight_set_level_and_update(int level); 5105 return ret;
5106}
5099 5107
5100static int kbdlight_get_level(void) 5108static int kbdlight_get_level(void)
5101{ 5109{
@@ -5158,24 +5166,10 @@ static bool kbdlight_is_supported(void)
5158 return status & BIT(9); 5166 return status & BIT(9);
5159} 5167}
5160 5168
5161static void kbdlight_set_worker(struct work_struct *work) 5169static int kbdlight_sysfs_set(struct led_classdev *led_cdev,
5162{
5163 struct tpacpi_led_classdev *data =
5164 container_of(work, struct tpacpi_led_classdev, work);
5165
5166 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
5167 kbdlight_set_level_and_update(data->new_state);
5168}
5169
5170static void kbdlight_sysfs_set(struct led_classdev *led_cdev,
5171 enum led_brightness brightness) 5170 enum led_brightness brightness)
5172{ 5171{
5173 struct tpacpi_led_classdev *data = 5172 return kbdlight_set_level(brightness);
5174 container_of(led_cdev,
5175 struct tpacpi_led_classdev,
5176 led_classdev);
5177 data->new_state = brightness;
5178 queue_work(tpacpi_wq, &data->work);
5179} 5173}
5180 5174
5181static enum led_brightness kbdlight_sysfs_get(struct led_classdev *led_cdev) 5175static enum led_brightness kbdlight_sysfs_get(struct led_classdev *led_cdev)
@@ -5193,7 +5187,8 @@ static struct tpacpi_led_classdev tpacpi_led_kbdlight = {
5193 .led_classdev = { 5187 .led_classdev = {
5194 .name = "tpacpi::kbd_backlight", 5188 .name = "tpacpi::kbd_backlight",
5195 .max_brightness = 2, 5189 .max_brightness = 2,
5196 .brightness_set = &kbdlight_sysfs_set, 5190 .flags = LED_BRIGHT_HW_CHANGED,
5191 .brightness_set_blocking = &kbdlight_sysfs_set,
5197 .brightness_get = &kbdlight_sysfs_get, 5192 .brightness_get = &kbdlight_sysfs_get,
5198 } 5193 }
5199}; 5194};
@@ -5205,7 +5200,6 @@ static int __init kbdlight_init(struct ibm_init_struct *iibm)
5205 vdbg_printk(TPACPI_DBG_INIT, "initializing kbdlight subdriver\n"); 5200 vdbg_printk(TPACPI_DBG_INIT, "initializing kbdlight subdriver\n");
5206 5201
5207 TPACPI_ACPIHANDLE_INIT(hkey); 5202 TPACPI_ACPIHANDLE_INIT(hkey);
5208 INIT_WORK(&tpacpi_led_kbdlight.work, kbdlight_set_worker);
5209 5203
5210 if (!kbdlight_is_supported()) { 5204 if (!kbdlight_is_supported()) {
5211 tp_features.kbdlight = 0; 5205 tp_features.kbdlight = 0;
@@ -5213,6 +5207,7 @@ static int __init kbdlight_init(struct ibm_init_struct *iibm)
5213 return 1; 5207 return 1;
5214 } 5208 }
5215 5209
5210 kbdlight_brightness = kbdlight_sysfs_get(NULL);
5216 tp_features.kbdlight = 1; 5211 tp_features.kbdlight = 1;
5217 5212
5218 rc = led_classdev_register(&tpacpi_pdev->dev, 5213 rc = led_classdev_register(&tpacpi_pdev->dev,
@@ -5222,6 +5217,8 @@ static int __init kbdlight_init(struct ibm_init_struct *iibm)
5222 return rc; 5217 return rc;
5223 } 5218 }
5224 5219
5220 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask |
5221 TP_ACPI_HKEY_KBD_LIGHT_MASK);
5225 return 0; 5222 return 0;
5226} 5223}
5227 5224
@@ -5229,7 +5226,6 @@ static void kbdlight_exit(void)
5229{ 5226{
5230 if (tp_features.kbdlight) 5227 if (tp_features.kbdlight)
5231 led_classdev_unregister(&tpacpi_led_kbdlight.led_classdev); 5228 led_classdev_unregister(&tpacpi_led_kbdlight.led_classdev);
5232 flush_workqueue(tpacpi_wq);
5233} 5229}
5234 5230
5235static int kbdlight_set_level_and_update(int level) 5231static int kbdlight_set_level_and_update(int level)
@@ -5358,25 +5354,11 @@ static int light_set_status(int status)
5358 return -ENXIO; 5354 return -ENXIO;
5359} 5355}
5360 5356
5361static void light_set_status_worker(struct work_struct *work) 5357static int light_sysfs_set(struct led_classdev *led_cdev,
5362{
5363 struct tpacpi_led_classdev *data =
5364 container_of(work, struct tpacpi_led_classdev, work);
5365
5366 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
5367 light_set_status((data->new_state != TPACPI_LED_OFF));
5368}
5369
5370static void light_sysfs_set(struct led_classdev *led_cdev,
5371 enum led_brightness brightness) 5358 enum led_brightness brightness)
5372{ 5359{
5373 struct tpacpi_led_classdev *data = 5360 return light_set_status((brightness != LED_OFF) ?
5374 container_of(led_cdev, 5361 TPACPI_LED_ON : TPACPI_LED_OFF);
5375 struct tpacpi_led_classdev,
5376 led_classdev);
5377 data->new_state = (brightness != LED_OFF) ?
5378 TPACPI_LED_ON : TPACPI_LED_OFF;
5379 queue_work(tpacpi_wq, &data->work);
5380} 5362}
5381 5363
5382static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) 5364static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
@@ -5387,7 +5369,7 @@ static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
5387static struct tpacpi_led_classdev tpacpi_led_thinklight = { 5369static struct tpacpi_led_classdev tpacpi_led_thinklight = {
5388 .led_classdev = { 5370 .led_classdev = {
5389 .name = "tpacpi::thinklight", 5371 .name = "tpacpi::thinklight",
5390 .brightness_set = &light_sysfs_set, 5372 .brightness_set_blocking = &light_sysfs_set,
5391 .brightness_get = &light_sysfs_get, 5373 .brightness_get = &light_sysfs_get,
5392 } 5374 }
5393}; 5375};
@@ -5403,7 +5385,6 @@ static int __init light_init(struct ibm_init_struct *iibm)
5403 TPACPI_ACPIHANDLE_INIT(lght); 5385 TPACPI_ACPIHANDLE_INIT(lght);
5404 } 5386 }
5405 TPACPI_ACPIHANDLE_INIT(cmos); 5387 TPACPI_ACPIHANDLE_INIT(cmos);
5406 INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker);
5407 5388
5408 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ 5389 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
5409 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; 5390 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
@@ -5437,7 +5418,6 @@ static int __init light_init(struct ibm_init_struct *iibm)
5437static void light_exit(void) 5418static void light_exit(void)
5438{ 5419{
5439 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); 5420 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev);
5440 flush_workqueue(tpacpi_wq);
5441} 5421}
5442 5422
5443static int light_read(struct seq_file *m) 5423static int light_read(struct seq_file *m)
@@ -5704,29 +5684,21 @@ static int led_set_status(const unsigned int led,
5704 return rc; 5684 return rc;
5705} 5685}
5706 5686
5707static void led_set_status_worker(struct work_struct *work) 5687static int led_sysfs_set(struct led_classdev *led_cdev,
5708{
5709 struct tpacpi_led_classdev *data =
5710 container_of(work, struct tpacpi_led_classdev, work);
5711
5712 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
5713 led_set_status(data->led, data->new_state);
5714}
5715
5716static void led_sysfs_set(struct led_classdev *led_cdev,
5717 enum led_brightness brightness) 5688 enum led_brightness brightness)
5718{ 5689{
5719 struct tpacpi_led_classdev *data = container_of(led_cdev, 5690 struct tpacpi_led_classdev *data = container_of(led_cdev,
5720 struct tpacpi_led_classdev, led_classdev); 5691 struct tpacpi_led_classdev, led_classdev);
5692 enum led_status_t new_state;
5721 5693
5722 if (brightness == LED_OFF) 5694 if (brightness == LED_OFF)
5723 data->new_state = TPACPI_LED_OFF; 5695 new_state = TPACPI_LED_OFF;
5724 else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK) 5696 else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK)
5725 data->new_state = TPACPI_LED_ON; 5697 new_state = TPACPI_LED_ON;
5726 else 5698 else
5727 data->new_state = TPACPI_LED_BLINK; 5699 new_state = TPACPI_LED_BLINK;
5728 5700
5729 queue_work(tpacpi_wq, &data->work); 5701 return led_set_status(data->led, new_state);
5730} 5702}
5731 5703
5732static int led_sysfs_blink_set(struct led_classdev *led_cdev, 5704static int led_sysfs_blink_set(struct led_classdev *led_cdev,
@@ -5743,10 +5715,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev,
5743 } else if ((*delay_on != 500) || (*delay_off != 500)) 5715 } else if ((*delay_on != 500) || (*delay_off != 500))
5744 return -EINVAL; 5716 return -EINVAL;
5745 5717
5746 data->new_state = TPACPI_LED_BLINK; 5718 return led_set_status(data->led, TPACPI_LED_BLINK);
5747 queue_work(tpacpi_wq, &data->work);
5748
5749 return 0;
5750} 5719}
5751 5720
5752static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev) 5721static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev)
@@ -5775,7 +5744,6 @@ static void led_exit(void)
5775 led_classdev_unregister(&tpacpi_leds[i].led_classdev); 5744 led_classdev_unregister(&tpacpi_leds[i].led_classdev);
5776 } 5745 }
5777 5746
5778 flush_workqueue(tpacpi_wq);
5779 kfree(tpacpi_leds); 5747 kfree(tpacpi_leds);
5780} 5748}
5781 5749
@@ -5789,7 +5757,7 @@ static int __init tpacpi_init_led(unsigned int led)
5789 if (!tpacpi_led_names[led]) 5757 if (!tpacpi_led_names[led])
5790 return 0; 5758 return 0;
5791 5759
5792 tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; 5760 tpacpi_leds[led].led_classdev.brightness_set_blocking = &led_sysfs_set;
5793 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; 5761 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
5794 if (led_supported == TPACPI_LED_570) 5762 if (led_supported == TPACPI_LED_570)
5795 tpacpi_leds[led].led_classdev.brightness_get = 5763 tpacpi_leds[led].led_classdev.brightness_get =
@@ -5797,8 +5765,6 @@ static int __init tpacpi_init_led(unsigned int led)
5797 5765
5798 tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led]; 5766 tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];
5799 5767
5800 INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker);
5801
5802 rc = led_classdev_register(&tpacpi_pdev->dev, 5768 rc = led_classdev_register(&tpacpi_pdev->dev,
5803 &tpacpi_leds[led].led_classdev); 5769 &tpacpi_leds[led].led_classdev);
5804 if (rc < 0) 5770 if (rc < 0)
@@ -9169,6 +9135,24 @@ static void tpacpi_driver_event(const unsigned int hkey_event)
9169 volume_alsa_notify_change(); 9135 volume_alsa_notify_change();
9170 } 9136 }
9171 } 9137 }
9138 if (tp_features.kbdlight && hkey_event == TP_HKEY_EV_KBD_LIGHT) {
9139 enum led_brightness brightness;
9140
9141 mutex_lock(&kbdlight_mutex);
9142
9143 /*
9144 * Check the brightness actually changed, setting the brightness
9145 * through kbdlight_set_level() also triggers this event.
9146 */
9147 brightness = kbdlight_sysfs_get(NULL);
9148 if (kbdlight_brightness != brightness) {
9149 kbdlight_brightness = brightness;
9150 led_classdev_notify_brightness_hw_changed(
9151 &tpacpi_led_kbdlight.led_classdev, brightness);
9152 }
9153
9154 mutex_unlock(&kbdlight_mutex);
9155 }
9172} 9156}
9173 9157
9174static void hotkey_driver_event(const unsigned int scancode) 9158static void hotkey_driver_event(const unsigned int scancode)