Commit e18bf801 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v4.10-1' of...

Merge tag 'platform-drivers-x86-v4.10-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86

Pull x86 platform driver updates from Darrent Hart:
 "Introduce one new driver for Mellanox platforms. Add support for
  various new models to existing drivers via quirks, hotkeys, etc.
  Significant updates to intel_pmc_core in support of Kabylake and
  Sunrise Point PCH power management debug. Some cleanup and refactoring
  across various drivers.

  Detailed summary:

  dell-laptop:
   - Use brightness_set_blocking for kbd_led_level_set

  thinkpad_acpi:
   - Initialize local in_tablet_mode and type
   - Fix old style declaration GCC warning
   - Adding new hotkey ID for Lenovo thinkpad
   - Add support for X1 Yoga (2016) Tablet Mode
   - Move tablet detection into separate function

  asus-nb-wmi:
   - Add X45U quirk
   - Make use of dmi->ident

  asus-wmi:
   - Set specified XUSB2PR value for X550LB

  intel_mid_thermal:
   - Fix suspend handlers unused warning

  intel-vbtn:
   - Switch to use devm_input_allocate_device

  dell-wmi:
   - Add events created by Dell Rugged 2-in-1s
   - Adjust wifi catcher to emit KEY_WLAN

  intel_pmc_core:
   - Add KBL CPUID support
   - Add LTR IGNORE debug feature
   - Add MPHY PLL clock gating status
   - ModPhy core lanes pg status
   - Add PCH IP Power Gating Status
   - Fix PWRMBASE mask and mmio reg len

  acer-wmi:
   - Only supports AMW0_GUID1 on acer family

  mlx-platform:
   - Introduce support for Mellanox hotplug driver

  platform/x86:
   - Use ACPI_FAILURE at appropriate places"

* tag 'platform-drivers-x86-v4.10-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (22 commits)
  platform/x86: thinkpad_acpi: Initialize local in_tablet_mode and type
  platform/x86: dell-laptop: Use brightness_set_blocking for kbd_led_level_set
  platform/x86: thinkpad_acpi: Fix old style declaration GCC warning
  platform/x86: thinkpad_acpi: Adding new hotkey ID for Lenovo thinkpad
  platform/x86: thinkpad_acpi: Add support for X1 Yoga (2016) Tablet Mode
  platform/x86: thinkpad_acpi: Move tablet detection into separate function
  platform/x86: asus-nb-wmi.c: Add X45U quirk
  platform/x86: asus-nb-wmi: Make use of dmi->ident
  platform/x86: asus-wmi: Set specified XUSB2PR value for X550LB
  platform/x86: intel_mid_thermal: Fix suspend handlers unused warning
  platform/x86: intel-vbtn: Switch to use devm_input_allocate_device
  platform/x86: Use ACPI_FAILURE at appropriate places
  platform/x86: dell-wmi: Add events created by Dell Rugged 2-in-1s
  platform/x86: dell-wmi: Adjust wifi catcher to emit KEY_WLAN
  platform/x86: intel_pmc_core: Add KBL CPUID support
  platform/x86: intel_pmc_core: Add LTR IGNORE debug feature
  platform/x86: intel_pmc_core: Add MPHY PLL clock gating status
  platform/x86: intel_pmc_core: ModPhy core lanes pg status
  platform/x86: intel_pmc_core: Add PCH IP Power Gating Status
  platform/x86: intel_pmc_core: Fix PWRMBASE mask and mmio reg len
  ...
parents 8600b697 cb2bf251
...@@ -540,6 +540,7 @@ Events that are propagated by the driver to userspace: ...@@ -540,6 +540,7 @@ Events that are propagated by the driver to userspace:
0x6022 ALARM: a sensor is extremely hot 0x6022 ALARM: a sensor is extremely hot
0x6030 System thermal table changed 0x6030 System thermal table changed
0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED) 0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED)
0x60C0 X1 Yoga 2016, Tablet mode status changed
Battery nearly empty alarms are a last resort attempt to get the Battery nearly empty alarms are a last resort attempt to get the
operating system to hibernate or shutdown cleanly (0x2313), or shutdown operating system to hibernate or shutdown cleanly (0x2313), or shutdown
......
...@@ -8045,6 +8045,13 @@ L: platform-driver-x86@vger.kernel.org ...@@ -8045,6 +8045,13 @@ L: platform-driver-x86@vger.kernel.org
S: Supported S: Supported
F: arch/x86/platform/mellanox/mlx-platform.c F: arch/x86/platform/mellanox/mlx-platform.c
MELLANOX MLX CPLD HOTPLUG DRIVER
M: Vadim Pasternak <vadimp@mellanox.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
F: drivers/platform/x86/mlxcpld-hotplug.c
F: include/linux/platform_data/mlxcpld-hotplug.h
SOFT-ROCE DRIVER (rxe) SOFT-ROCE DRIVER (rxe)
M: Moni Shoua <monis@mellanox.com> M: Moni Shoua <monis@mellanox.com>
L: linux-rdma@vger.kernel.org L: linux-rdma@vger.kernel.org
......
...@@ -1027,4 +1027,15 @@ config INTEL_TELEMETRY ...@@ -1027,4 +1027,15 @@ config INTEL_TELEMETRY
used to get various SoC events and parameters used to get various SoC events and parameters
directly via debugfs files. Various tools may use directly via debugfs files. Various tools may use
this interface for SoC state monitoring. this interface for SoC state monitoring.
config MLX_CPLD_PLATFORM
tristate "Mellanox platform hotplug driver support"
default n
depends on MLX_PLATFORM
select HWMON
select I2C
---help---
This driver handles hot-plug events for the power suppliers, power
cables and fans on the wide range Mellanox IB and Ethernet systems.
endif # X86_PLATFORM_DEVICES endif # X86_PLATFORM_DEVICES
...@@ -71,3 +71,4 @@ obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ ...@@ -71,3 +71,4 @@ obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
intel_telemetry_pltdrv.o \ intel_telemetry_pltdrv.o \
intel_telemetry_debugfs.o intel_telemetry_debugfs.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o
...@@ -355,6 +355,32 @@ static const struct dmi_system_id acer_blacklist[] __initconst = { ...@@ -355,6 +355,32 @@ static const struct dmi_system_id acer_blacklist[] __initconst = {
{} {}
}; };
static const struct dmi_system_id amw0_whitelist[] __initconst = {
{
.ident = "Acer",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
},
},
{
.ident = "Gateway",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),
},
},
{
.ident = "Packard Bell",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"),
},
},
{}
};
/*
* This quirk table is only for Acer/Gateway/Packard Bell family
* that those machines are supported by acer-wmi driver.
*/
static const struct dmi_system_id acer_quirks[] __initconst = { static const struct dmi_system_id acer_quirks[] __initconst = {
{ {
.callback = dmi_matched, .callback = dmi_matched,
...@@ -464,6 +490,17 @@ static const struct dmi_system_id acer_quirks[] __initconst = { ...@@ -464,6 +490,17 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
}, },
.driver_data = &quirk_acer_travelmate_2490, .driver_data = &quirk_acer_travelmate_2490,
}, },
{}
};
/*
* This quirk list is for those non-acer machines that have AMW0_GUID1
* but supported by acer-wmi in past days. Keeping this quirk list here
* is only for backward compatible. Please do not add new machine to
* here anymore. Those non-acer machines should be supported by
* appropriate wmi drivers.
*/
static const struct dmi_system_id non_acer_quirks[] __initconst = {
{ {
.callback = dmi_matched, .callback = dmi_matched,
.ident = "Fujitsu Siemens Amilo Li 1718", .ident = "Fujitsu Siemens Amilo Li 1718",
...@@ -598,6 +635,7 @@ static void __init find_quirks(void) ...@@ -598,6 +635,7 @@ static void __init find_quirks(void)
{ {
if (!force_series) { if (!force_series) {
dmi_check_system(acer_quirks); dmi_check_system(acer_quirks);
dmi_check_system(non_acer_quirks);
} else if (force_series == 2490) { } else if (force_series == 2490) {
quirks = &quirk_acer_travelmate_2490; quirks = &quirk_acer_travelmate_2490;
} }
...@@ -2107,6 +2145,24 @@ static int __init acer_wmi_init(void) ...@@ -2107,6 +2145,24 @@ static int __init acer_wmi_init(void)
find_quirks(); find_quirks();
/*
* The AMW0_GUID1 wmi is not only found on Acer family but also other
* machines like Lenovo, Fujitsu and Medion. In the past days,
* acer-wmi driver handled those non-Acer machines by quirks list.
* But actually acer-wmi driver was loaded on any machines that have
* AMW0_GUID1. This behavior is strange because those machines should
* be supported by appropriate wmi drivers. e.g. fujitsu-laptop,
* ideapad-laptop. So, here checks the machine that has AMW0_GUID1
* should be in Acer/Gateway/Packard Bell white list, or it's already
* in the past quirk list.
*/
if (wmi_has_guid(AMW0_GUID1) &&
!dmi_check_system(amw0_whitelist) &&
quirks == &quirk_unknown) {
pr_err("Unsupported machine has AMW0_GUID1, unable to load\n");
return -ENODEV;
}
/* /*
* Detect which ACPI-WMI interface we're using. * Detect which ACPI-WMI interface we're using.
*/ */
......
...@@ -116,8 +116,13 @@ static struct quirk_entry quirk_asus_ux303ub = { ...@@ -116,8 +116,13 @@ static struct quirk_entry quirk_asus_ux303ub = {
.wmi_backlight_native = true, .wmi_backlight_native = true,
}; };
static struct quirk_entry quirk_asus_x550lb = {
.xusb2pr = 0x01D9,
};
static int dmi_matched(const struct dmi_system_id *dmi) static int dmi_matched(const struct dmi_system_id *dmi)
{ {
pr_info("Identified laptop model '%s'\n", dmi->ident);
quirks = dmi->driver_data; quirks = dmi->driver_data;
return 1; return 1;
} }
...@@ -173,6 +178,15 @@ static const struct dmi_system_id asus_quirks[] = { ...@@ -173,6 +178,15 @@ static const struct dmi_system_id asus_quirks[] = {
}, },
.driver_data = &quirk_asus_wapf4, .driver_data = &quirk_asus_wapf4,
}, },
{
.callback = dmi_matched,
.ident = "ASUSTeK COMPUTER INC. X45U",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X45U"),
},
.driver_data = &quirk_asus_wapf4,
},
{ {
.callback = dmi_matched, .callback = dmi_matched,
.ident = "ASUSTeK COMPUTER INC. X456UA", .ident = "ASUSTeK COMPUTER INC. X456UA",
...@@ -398,6 +412,15 @@ static const struct dmi_system_id asus_quirks[] = { ...@@ -398,6 +412,15 @@ static const struct dmi_system_id asus_quirks[] = {
}, },
.driver_data = &quirk_asus_ux303ub, .driver_data = &quirk_asus_ux303ub,
}, },
{
.callback = dmi_matched,
.ident = "ASUSTeK COMPUTER INC. X550LB",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"),
},
.driver_data = &quirk_asus_x550lb,
},
{}, {},
}; };
......
...@@ -156,6 +156,9 @@ MODULE_LICENSE("GPL"); ...@@ -156,6 +156,9 @@ MODULE_LICENSE("GPL");
#define ASUS_FAN_CTRL_MANUAL 1 #define ASUS_FAN_CTRL_MANUAL 1
#define ASUS_FAN_CTRL_AUTO 2 #define ASUS_FAN_CTRL_AUTO 2
#define USB_INTEL_XUSB2PR 0xD0
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
struct bios_args { struct bios_args {
u32 arg0; u32 arg0;
u32 arg1; u32 arg1;
...@@ -1080,6 +1083,29 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) ...@@ -1080,6 +1083,29 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
return result; return result;
} }
static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
{
struct pci_dev *xhci_pdev;
u32 orig_ports_available;
u32 ports_available = asus->driver->quirks->xusb2pr;
xhci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI,
NULL);
if (!xhci_pdev)
return;
pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
&orig_ports_available);
pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
cpu_to_le32(ports_available));
pr_info("set USB_INTEL_XUSB2PR old: 0x%04x, new: 0x%04x\n",
orig_ports_available, ports_available);
}
/* /*
* Hwmon device * Hwmon device
*/ */
...@@ -2087,6 +2113,9 @@ static int asus_wmi_add(struct platform_device *pdev) ...@@ -2087,6 +2113,9 @@ static int asus_wmi_add(struct platform_device *pdev)
if (asus->driver->quirks->wmi_backlight_native) if (asus->driver->quirks->wmi_backlight_native)
acpi_video_set_dmi_backlight_type(acpi_backlight_native); acpi_video_set_dmi_backlight_type(acpi_backlight_native);
if (asus->driver->quirks->xusb2pr)
asus_wmi_set_xusb2pr(asus);
if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
err = asus_wmi_backlight_init(asus); err = asus_wmi_backlight_init(asus);
if (err && err != -ENODEV) if (err && err != -ENODEV)
......
...@@ -53,6 +53,7 @@ struct quirk_entry { ...@@ -53,6 +53,7 @@ struct quirk_entry {
* and let the ACPI interrupt to send out the key event. * and let the ACPI interrupt to send out the key event.
*/ */
int no_display_toggle; int no_display_toggle;
u32 xusb2pr;
bool (*i8042_filter)(unsigned char data, unsigned char str, bool (*i8042_filter)(unsigned char data, unsigned char str,
struct serio *serio); struct serio *serio);
......
...@@ -1904,38 +1904,40 @@ static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev) ...@@ -1904,38 +1904,40 @@ static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev)
return 0; return 0;
} }
static void kbd_led_level_set(struct led_classdev *led_cdev, static int kbd_led_level_set(struct led_classdev *led_cdev,
enum led_brightness value) enum led_brightness value)
{ {
struct kbd_state state; struct kbd_state state;
struct kbd_state new_state; struct kbd_state new_state;
u16 num; u16 num;
int ret;
if (kbd_get_max_level()) { if (kbd_get_max_level()) {
if (kbd_get_state(&state)) ret = kbd_get_state(&state);
return; if (ret)
return ret;
new_state = state; new_state = state;
if (kbd_set_level(&new_state, value)) ret = kbd_set_level(&new_state, value);
return; if (ret)
kbd_set_state_safe(&new_state, &state); return ret;
return; return kbd_set_state_safe(&new_state, &state);
} }
if (kbd_get_valid_token_counts()) { if (kbd_get_valid_token_counts()) {
for (num = kbd_token_bits; num != 0 && value > 0; --value) for (num = kbd_token_bits; num != 0 && value > 0; --value)
num &= num - 1; /* clear the first bit set */ num &= num - 1; /* clear the first bit set */
if (num == 0) if (num == 0)
return; return 0;
kbd_set_token_bit(ffs(num) - 1); return kbd_set_token_bit(ffs(num) - 1);
return;
} }
pr_warn("Keyboard brightness level control not supported\n"); pr_warn("Keyboard brightness level control not supported\n");
return -ENXIO;
} }
static struct led_classdev kbd_led = { static struct led_classdev kbd_led = {
.name = "dell::kbd_backlight", .name = "dell::kbd_backlight",
.brightness_set = kbd_led_level_set, .brightness_set_blocking = kbd_led_level_set,
.brightness_get = kbd_led_level_get, .brightness_get = kbd_led_level_get,
.groups = kbd_led_groups, .groups = kbd_led_groups,
}; };
......
...@@ -114,7 +114,7 @@ static const struct key_entry dell_wmi_keymap_type_0000[] __initconst = { ...@@ -114,7 +114,7 @@ static const struct key_entry dell_wmi_keymap_type_0000[] __initconst = {
{ KE_IGNORE, 0xe00e, { KEY_RESERVED } }, { KE_IGNORE, 0xe00e, { KEY_RESERVED } },
/* Wifi Catcher */ /* Wifi Catcher */
{ KE_KEY, 0xe011, { KEY_PROG2 } }, { KE_KEY, 0xe011, { KEY_WLAN } },
/* Ambient light sensor toggle */ /* Ambient light sensor toggle */
{ KE_IGNORE, 0xe013, { KEY_RESERVED } }, { KE_IGNORE, 0xe013, { KEY_RESERVED } },
...@@ -274,6 +274,16 @@ static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = { ...@@ -274,6 +274,16 @@ static const struct key_entry dell_wmi_keymap_type_0010[] __initconst = {
/* Stealth mode toggle */ /* Stealth mode toggle */
{ KE_IGNORE, 0x155, { KEY_RESERVED } }, { KE_IGNORE, 0x155, { KEY_RESERVED } },
/* Rugged magnetic dock attach/detach events */
{ KE_IGNORE, 0x156, { KEY_RESERVED } },
{ KE_IGNORE, 0x157, { KEY_RESERVED } },
/* Rugged programmable (P1/P2/P3 keys) */
{ KE_KEY, 0x850, { KEY_PROG1 } },
{ KE_KEY, 0x851, { KEY_PROG2 } },
{ KE_KEY, 0x852, { KEY_PROG3 } },
}; };
/* /*
......
...@@ -69,7 +69,7 @@ static int intel_hid_set_enable(struct device *device, int enable) ...@@ -69,7 +69,7 @@ static int intel_hid_set_enable(struct device *device, int enable)
arg0.integer.value = enable; arg0.integer.value = enable;
status = acpi_evaluate_object(ACPI_HANDLE(device), "HDSM", &args, NULL); status = acpi_evaluate_object(ACPI_HANDLE(device), "HDSM", &args, NULL);
if (!ACPI_SUCCESS(status)) { if (ACPI_FAILURE(status)) {
dev_warn(device, "failed to %sable hotkeys\n", dev_warn(device, "failed to %sable hotkeys\n",
enable ? "en" : "dis"); enable ? "en" : "dis");
return -EIO; return -EIO;
...@@ -148,7 +148,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) ...@@ -148,7 +148,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
} }
status = acpi_evaluate_integer(handle, "HDEM", NULL, &ev_index); status = acpi_evaluate_integer(handle, "HDEM", NULL, &ev_index);
if (!ACPI_SUCCESS(status)) { if (ACPI_FAILURE(status)) {
dev_warn(&device->dev, "failed to get event index\n"); dev_warn(&device->dev, "failed to get event index\n");
return; return;
} }
...@@ -167,7 +167,7 @@ static int intel_hid_probe(struct platform_device *device) ...@@ -167,7 +167,7 @@ static int intel_hid_probe(struct platform_device *device)
int err; int err;
status = acpi_evaluate_integer(handle, "HDMM", NULL, &mode); status = acpi_evaluate_integer(handle, "HDMM", NULL, &mode);
if (!ACPI_SUCCESS(status)) { if (ACPI_FAILURE(status)) {
dev_warn(&device->dev, "failed to read mode\n"); dev_warn(&device->dev, "failed to read mode\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -29,7 +29,7 @@ static int smartconnect_acpi_init(struct acpi_device *acpi) ...@@ -29,7 +29,7 @@ static int smartconnect_acpi_init(struct acpi_device *acpi)
acpi_status status; acpi_status status;
status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value); status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value);
if (!ACPI_SUCCESS(status)) if (ACPI_FAILURE(status))
return -EINVAL; return -EINVAL;
if (value & 0x1) { if (value & 0x1) {
......
...@@ -49,34 +49,19 @@ static int intel_vbtn_input_setup(struct platform_device *device) ...@@ -49,34 +49,19 @@ static int intel_vbtn_input_setup(struct platform_device *device)
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
int ret; int ret;
priv->input_dev = input_allocate_device(); priv->input_dev = devm_input_allocate_device(&device->dev);
if (!priv->input_dev) if (!priv->input_dev)
return -ENOMEM; return -ENOMEM;
ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL); ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL);
if (ret) if (ret)
goto err_free_device; return ret;
priv->input_dev->dev.parent = &device->dev; priv->input_dev->dev.parent = &device->dev;
priv->input_dev->name = "Intel Virtual Button driver"; priv->input_dev->name = "Intel Virtual Button driver";
priv->input_dev->id.bustype = BUS_HOST; priv->input_dev->id.bustype = BUS_HOST;
ret = input_register_device(priv->input_dev); return input_register_device(priv->input_dev);
if (ret)
goto err_free_device;
return 0;
err_free_device:
input_free_device(priv->input_dev);
return ret;
}
static void intel_vbtn_input_destroy(struct platform_device *device)
{
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
input_unregister_device(priv->input_dev);
} }
static void notify_handler(acpi_handle handle, u32 event, void *context) static void notify_handler(acpi_handle handle, u32 event, void *context)
...@@ -97,7 +82,7 @@ static int intel_vbtn_probe(struct platform_device *device) ...@@ -97,7 +82,7 @@ static int intel_vbtn_probe(struct platform_device *device)
int err; int err;
status = acpi_evaluate_object(handle, "VBDL", NULL, NULL); status = acpi_evaluate_object(handle, "VBDL", NULL, NULL);
if (!ACPI_SUCCESS(status)) { if (ACPI_FAILURE(status)) {
dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n"); dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n");
return -ENODEV; return -ENODEV;
} }
...@@ -117,24 +102,16 @@ static int intel_vbtn_probe(struct platform_device *device) ...@@ -117,24 +102,16 @@ static int intel_vbtn_probe(struct platform_device *device)
ACPI_DEVICE_NOTIFY, ACPI_DEVICE_NOTIFY,
notify_handler, notify_handler,
device); device);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status))
err = -EBUSY; return -EBUSY;
goto err_remove_input;
}
return 0; return 0;
err_remove_input:
intel_vbtn_input_destroy(device);
return err;
} }
static int intel_vbtn_remove(struct platform_device *device) static int intel_vbtn_remove(struct platform_device *device)
{ {
acpi_handle handle = ACPI_HANDLE(&device->dev); acpi_handle handle = ACPI_HANDLE(&device->dev);
intel_vbtn_input_destroy(device);
acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
/* /*
......
...@@ -415,6 +415,7 @@ static struct thermal_device_info *initialize_sensor(int index) ...@@ -415,6 +415,7 @@ static struct thermal_device_info *initialize_sensor(int index)
return td_info; return td_info;
} }
#ifdef CONFIG_PM_SLEEP
/** /**
* mid_thermal_resume - resume routine * mid_thermal_resume - resume routine
* @dev: device structure * @dev: device structure
...@@ -442,6 +443,7 @@ static int mid_thermal_suspend(struct device *dev) ...@@ -442,6 +443,7 @@ static int mid_thermal_suspend(struct device *dev)
*/ */
return configure_adc(0); return configure_adc(0);
} }
#endif
static SIMPLE_DEV_PM_OPS(mid_thermal_pm, static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
mid_thermal_suspend, mid_thermal_resume); mid_thermal_suspend, mid_thermal_resume);
......
This diff is collapsed.
...@@ -26,8 +26,111 @@ ...@@ -26,8 +26,111 @@
#define SPT_PMC_BASE_ADDR_OFFSET 0x48 #define SPT_PMC_BASE_ADDR_OFFSET 0x48
#define SPT_PMC_SLP_S0_RES_COUNTER_OFFSET 0x13c #define SPT_PMC_SLP_S0_RES_COUNTER_OFFSET 0x13c
#define SPT_PMC_MMIO_REG_LEN 0x100 #define SPT_PMC_PM_CFG_OFFSET 0x18
#define SPT_PMC_PM_STS_OFFSET 0x1c
#define SPT_PMC_MTPMC_OFFSET 0x20
#define SPT_PMC_MFPMC_OFFSET 0x38
#define SPT_PMC_LTR_IGNORE_OFFSET 0x30C
#define SPT_PMC_MPHY_CORE_STS_0 0x1143
#define SPT_PMC_MPHY_CORE_STS_1 0x1142
#define SPT_PMC_MPHY_COM_STS_0 0x1155
#define SPT_PMC_MMIO_REG_LEN 0x1000
#define SPT_PMC_SLP_S0_RES_COUNTER_STEP 0x64 #define SPT_PMC_SLP_S0_RES_COUNTER_STEP 0x64
#define PMC_BASE_ADDR_MASK ~(SPT_PMC_MMIO_REG_LEN - 1)
#define MTPMC_MASK 0xffff0000
#define NUM_ENTRIES 5
#define SPT_PMC_READ_DISABLE_BIT 0x16
#define SPT_PMC_MSG_FULL_STS_BIT 0x18
#define NUM_RETRIES 100
#define NUM_IP_IGN_ALLOWED 17
/* Sunrise Point: PGD PFET Enable Ack Status Registers */
enum ppfear_regs {
SPT_PMC_XRAM_PPFEAR0A = 0x590,
SPT_PMC_XRAM_PPFEAR0B,
SPT_PMC_XRAM_PPFEAR0C,
SPT_PMC_XRAM_PPFEAR0D,
SPT_PMC_XRAM_PPFEAR1A,
};
#define SPT_PMC_BIT_PMC BIT(0)
#define SPT_PMC_BIT_OPI BIT(1)
#define SPT_PMC_BIT_SPI BIT(2)
#define SPT_PMC_BIT_XHCI BIT(3)
#define SPT_PMC_BIT_SPA BIT(4)
#define SPT_PMC_BIT_SPB BIT(5)
#define SPT_PMC_BIT_SPC BIT(6)
#define SPT_PMC_BIT_GBE BIT(7)
#define SPT_PMC_BIT_SATA BIT(0)
#define SPT_PMC_BIT_HDA_PGD0 BIT(1)
#define SPT_PMC_BIT_HDA_PGD1 BIT(2)
#define SPT_PMC_BIT_HDA_PGD2 BIT(3)
#define SPT_PMC_BIT_HDA_PGD3 BIT(4)
#define SPT_PMC_BIT_RSVD_0B BIT(5)
#define SPT_PMC_BIT_LPSS BIT(6)
#define SPT_PMC_BIT_LPC BIT(7)
#define SPT_PMC_BIT_SMB BIT(0)
#define SPT_PMC_BIT_ISH BIT(1)
#define SPT_PMC_BIT_P2SB BIT(2)
#define SPT_PMC_BIT_DFX BIT(3)
#define SPT_PMC_BIT_SCC BIT(4)
#define SPT_PMC_BIT_RSVD_0C BIT(5)
#define SPT_PMC_BIT_FUSE BIT(6)
#define SPT_PMC_BIT_CAMREA BIT(7)
#define SPT_PMC_BIT_RSVD_0D BIT(0)
#define SPT_PMC_BIT_USB3_OTG BIT(1)
#define SPT_PMC_BIT_EXI BIT(2)
#define SPT_PMC_BIT_CSE BIT(3)
#define SPT_PMC_BIT_CSME_KVM BIT(4)
#define SPT_PMC_BIT_CSME_PMT BIT(5)
#define SPT_PMC_BIT_CSME_CLINK BIT(6)
#define SPT_PMC_BIT_CSME_PTIO BIT(7)
#define SPT_PMC_BIT_CSME_USBR BIT(0)
#define SPT_PMC_BIT_CSME_SUSRAM BIT(1)
#define SPT_PMC_BIT_CSME_SMT BIT(2)
#define SPT_PMC_BIT_RSVD_1A BIT(3)
#define SPT_PMC_BIT_CSME_SMS2 BIT(4)
#define SPT_PMC_BIT_CSME_SMS1 BIT(5)
#define SPT_PMC_BIT_CSME_RTC BIT(6)
#define SPT_PMC_BIT_CSME_PSF BIT(7)
#define SPT_PMC_BIT_MPHY_LANE0 BIT(0)
#define SPT_PMC_BIT_MPHY_LANE1 BIT(1)
#define SPT_PMC_BIT_MPHY_LANE2 BIT(2)
#define SPT_PMC_BIT_MPHY_LANE3 BIT(3)
#define SPT_PMC_BIT_MPHY_LANE4 BIT(4)
#define SPT_PMC_BIT_MPHY_LANE5 BIT(5)
#define SPT_PMC_BIT_MPHY_LANE6 BIT(6)
#define SPT_PMC_BIT_MPHY_LANE7 BIT(7)
#define SPT_PMC_BIT_MPHY_LANE8 BIT(0)
#define SPT_PMC_BIT_MPHY_LANE9 BIT(1)
#define SPT_PMC_BIT_MPHY_LANE10 BIT(2)
#define SPT_PMC_BIT_MPHY_LANE11 BIT(3)
#define SPT_PMC_BIT_MPHY_LANE12 BIT(4)
#define SPT_PMC_BIT_MPHY_LANE13 BIT(5)
#define SPT_PMC_BIT_MPHY_LANE14 BIT(6)
#define SPT_PMC_BIT_MPHY_LANE15 BIT(7)
#define SPT_PMC_BIT_MPHY_CMN_LANE0 BIT(0)
#define SPT_PMC_BIT_MPHY_CMN_LANE1 BIT(1)
#define SPT_PMC_BIT_MPHY_CMN_LANE2 BIT(2)
#define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3)
struct pmc_bit_map {
const char *name;
u32 bit_mask;
};
struct pmc_reg_map {
const struct pmc_bit_map *pfear_sts;
const struct pmc_bit_map *mphy_sts;
const struct pmc_bit_map *pll_sts;
};
/** /**
* struct pmc_dev - pmc device structure * struct pmc_dev - pmc device structure
...@@ -43,8 +146,13 @@ ...@@ -43,8 +146,13 @@
struct pmc_dev { struct pmc_dev {
u32 base_addr; u32 base_addr;
void __iomem *regbase; void __iomem *regbase;
const struct pmc_reg_map *map;
#if IS_ENABLED(CONFIG_DEBUG_FS)
struct dentry *dbgfs_dir; struct dentry *dbgfs_dir;
#endif /* CONFIG_DEBUG_FS */
bool has_slp_s0_res; bool has_slp_s0_res;
int pmc_xram_read_bit;
struct mutex lock; /* generic mutex lock for PMC Core */
}; };
#endif /* PMC_CORE_H */ #endif /* PMC_CORE_H */
This diff is collapsed.
...@@ -458,7 +458,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) ...@@ -458,7 +458,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
NULL, &result); NULL, &result);
if (!ACPI_SUCCESS(rc)) { if (ACPI_FAILURE(rc)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"error getting hotkey status\n")); "error getting hotkey status\n"));
return; return;
......
...@@ -128,6 +128,7 @@ enum { ...@@ -128,6 +128,7 @@ enum {
/* ACPI HIDs */ /* ACPI HIDs */
#define TPACPI_ACPI_IBM_HKEY_HID "IBM0068" #define TPACPI_ACPI_IBM_HKEY_HID "IBM0068"
#define TPACPI_ACPI_LENOVO_HKEY_HID "LEN0068" #define TPACPI_ACPI_LENOVO_HKEY_HID "LEN0068"
#define TPACPI_ACPI_LENOVO_HKEY_V2_HID "LEN0268"
#define TPACPI_ACPI_EC_HID "PNP0C09" #define TPACPI_ACPI_EC_HID "PNP0C09"
/* Input IDs */ /* Input IDs */
...@@ -190,6 +191,9 @@ enum tpacpi_hkey_event_t { ...@@ -190,6 +191,9 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_LID_OPEN = 0x5002, /* laptop lid opened */ TP_HKEY_EV_LID_OPEN = 0x5002, /* laptop lid opened */
TP_HKEY_EV_TABLET_TABLET = 0x5009, /* tablet swivel up */ TP_HKEY_EV_TABLET_TABLET = 0x5009, /* tablet swivel up */
TP_HKEY_EV_TABLET_NOTEBOOK = 0x500a, /* tablet swivel down */ TP_HKEY_EV_TABLET_NOTEBOOK = 0x500a, /* tablet swivel down */
TP_HKEY_EV_TABLET_CHANGED = 0x60c0, /* X1 Yoga (2016):
* enter/leave tablet mode
*/
TP_HKEY_EV_PEN_INSERTED = 0x500b, /* tablet pen inserted */ TP_HKEY_EV_PEN_INSERTED = 0x500b, /* tablet pen inserted */
TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */ TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */
TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */ TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */
...@@ -302,7 +306,12 @@ static struct { ...@@ -302,7 +306,12 @@ static struct {
u32 hotkey:1; u32 hotkey:1;
u32 hotkey_mask:1; u32 hotkey_mask:1;
u32 hotkey_wlsw:1; u32 hotkey_wlsw:1;
u32 hotkey_tablet:1; enum {
TP_HOTKEY_TABLET_NONE = 0,
TP_HOTKEY_TABLET_USES_MHKG,
/* X1 Yoga 2016, seen on BIOS N1FET44W */
TP_HOTKEY_TABLET_USES_CMMD,
} hotkey_tablet;
u32 kbdlight:1; u32 kbdlight:1;
u32 light:1; u32 light:1;
u32 light_status:1; u32 light_status:1;
...@@ -2059,6 +2068,8 @@ static void hotkey_poll_setup(const bool may_warn); ...@@ -2059,6 +2068,8 @@ static void hotkey_poll_setup(const bool may_warn);
/* HKEY.MHKG() return bits */ /* HKEY.MHKG() return bits */
#define TP_HOTKEY_TABLET_MASK (1 << 3) #define TP_HOTKEY_TABLET_MASK (1 << 3)
/* ThinkPad X1 Yoga (2016) */
#define TP_EC_CMMD_TABLET_MODE 0x6
static int hotkey_get_wlsw(void) static int hotkey_get_wlsw(void)
{ {
...@@ -2083,10 +2094,23 @@ static int hotkey_get_tablet_mode(int *status) ...@@ -2083,10 +2094,23 @@ static int hotkey_get_tablet_mode(int *status)
{ {
int s; int s;
if (!acpi_evalf(hkey_handle, &s, "MHKG", "d")) switch (tp_features.hotkey_tablet) {
return -EIO; case TP_HOTKEY_TABLET_USES_MHKG:
if (!acpi_evalf(hkey_handle, &s, "MHKG", "d"))
return -EIO;
*status = ((s & TP_HOTKEY_TABLET_MASK) != 0);
break;
case TP_HOTKEY_TABLET_USES_CMMD:
if (!acpi_evalf(ec_handle, &s, "CMMD", "d"))
return -EIO;
*status = (s == TP_EC_CMMD_TABLET_MODE);
break;
default:
break;
}
*status = ((s & TP_HOTKEY_TABLET_MASK) != 0);
return 0; return 0;
} }
...@@ -3117,6 +3141,37 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = { ...@@ -3117,6 +3141,37 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = {
typedef u16 tpacpi_keymap_entry_t; typedef u16 tpacpi_keymap_entry_t;
typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];
static int hotkey_init_tablet_mode(void)
{
int in_tablet_mode = 0, res;
char *type = NULL;
if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) {
/* For X41t, X60t, X61t Tablets... */
tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_MHKG;
in_tablet_mode = !!(res & TP_HOTKEY_TABLET_MASK);
type = "MHKG";
} else if (acpi_evalf(ec_handle, &res, "CMMD", "qd")) {
/* For X1 Yoga (2016) */
tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_CMMD;
in_tablet_mode = res == TP_EC_CMMD_TABLET_MODE;
type = "CMMD";
}
if (!tp_features.hotkey_tablet)
return 0;
pr_info("Tablet mode switch found (type: %s), currently in %s mode\n",
type, in_tablet_mode ? "tablet" : "laptop");
res = add_to_attr_set(hotkey_dev_attributes,
&dev_attr_hotkey_tablet_mode.attr);
if (res)
return -1;
return in_tablet_mode;
}
static int __init hotkey_init(struct ibm_init_struct *iibm) static int __init hotkey_init(struct ibm_init_struct *iibm)
{ {
/* Requirements for changing the default keymaps: /* Requirements for changing the default keymaps:
...@@ -3464,21 +3519,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) ...@@ -3464,21 +3519,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
res = add_to_attr_set(hotkey_dev_attributes, res = add_to_attr_set(hotkey_dev_attributes,
&dev_attr_hotkey_radio_sw.attr); &dev_attr_hotkey_radio_sw.attr);
/* For X41t, X60t, X61t Tablets... */ res = hotkey_init_tablet_mode();
if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { if (res < 0)
tp_features.hotkey_tablet = 1; goto err_exit;
tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
pr_info("possible tablet mode switch found; "
"ThinkPad in %s mode\n",
(tabletsw_state) ? "tablet" : "laptop");
res = add_to_attr_set(hotkey_dev_attributes,
&dev_attr_hotkey_tablet_mode.attr);
}
if (!res) tabletsw_state = res;
res = register_attr_set_with_sysfs(
hotkey_dev_attributes, res = register_attr_set_with_sysfs(hotkey_dev_attributes,
&tpacpi_pdev->dev.kobj); &tpacpi_pdev->dev.kobj);
if (res) if (res)
goto err_exit; goto err_exit;
...@@ -3899,6 +3947,12 @@ static bool hotkey_notify_6xxx(const u32 hkey, ...@@ -3899,6 +3947,12 @@ static bool hotkey_notify_6xxx(const u32 hkey,
*ignore_acpi_ev = true; *ignore_acpi_ev = true;
return true; return true;
case TP_HKEY_EV_TABLET_CHANGED:
tpacpi_input_send_tabletsw();
hotkey_tablet_mode_notify_change();
*send_acpi_ev = false;
break;
default: default:
pr_warn("unknown possible thermal alarm or keyboard event received\n"); pr_warn("unknown possible thermal alarm or keyboard event received\n");
known = false; known = false;
...@@ -4143,6 +4197,7 @@ static int hotkey_write(char *buf) ...@@ -4143,6 +4197,7 @@ static int hotkey_write(char *buf)
static const struct acpi_device_id ibm_htk_device_ids[] = { static const struct acpi_device_id ibm_htk_device_ids[] = {
{TPACPI_ACPI_IBM_HKEY_HID, 0}, {TPACPI_ACPI_IBM_HKEY_HID, 0},
{TPACPI_ACPI_LENOVO_HKEY_HID, 0}, {TPACPI_ACPI_LENOVO_HKEY_HID, 0},
{TPACPI_ACPI_LENOVO_HKEY_V2_HID, 0},
{"", 0}, {"", 0},
}; };
...@@ -7716,7 +7771,7 @@ static struct ibm_struct volume_driver_data = { ...@@ -7716,7 +7771,7 @@ static struct ibm_struct volume_driver_data = {
#define alsa_card NULL #define alsa_card NULL
static void inline volume_alsa_notify_change(void) static inline void volume_alsa_notify_change(void)
{ {
} }
...@@ -9018,7 +9073,7 @@ static int mute_led_on_off(struct tp_led_table *t, bool state) ...@@ -9018,7 +9073,7 @@ static int mute_led_on_off(struct tp_led_table *t, bool state)
acpi_handle temp; acpi_handle temp;
int output; int output;
if (!ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) { if (ACPI_FAILURE(acpi_get_handle(hkey_handle, t->name, &temp))) {
pr_warn("Thinkpad ACPI has no %s interface.\n", t->name); pr_warn("Thinkpad ACPI has no %s interface.\n", t->name);
return -EIO; return -EIO;
} }
......
/*
* include/linux/platform_data/mlxcpld-hotplug.h
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H
#define __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H
/**
* struct mlxcpld_hotplug_device - I2C device data:
* @adapter: I2C device adapter;
* @client: I2C device client;
* @brdinfo: device board information;
* @bus: I2C bus, where device is attached;
*
* Structure represents I2C hotplug device static data (board topology) and
* dynamic data (related kernel objects handles).
*/
struct mlxcpld_hotplug_device {
struct i2c_adapter *adapter;
struct i2c_client *client;
struct i2c_board_info brdinfo;
u16 bus;
};
/**
* struct mlxcpld_hotplug_platform_data - device platform data:
* @top_aggr_offset: offset of top aggregation interrupt register;
* @top_aggr_mask: top aggregation interrupt common mask;
* @top_aggr_psu_mask: top aggregation interrupt PSU mask;
* @psu_reg_offset: offset of PSU interrupt register;
* @psu_mask: PSU interrupt mask;
* @psu_count: number of equipped replaceable PSUs;
* @psu: pointer to PSU devices data array;
* @top_aggr_pwr_mask: top aggregation interrupt power mask;
* @pwr_reg_offset: offset of power interrupt register
* @pwr_mask: power interrupt mask;
* @pwr_count: number of power sources;
* @pwr: pointer to power devices data array;
* @top_aggr_fan_mask: top aggregation interrupt FAN mask;
* @fan_reg_offset: offset of FAN interrupt register;
* @fan_mask: FAN interrupt mask;
* @fan_count: number of equipped replaceable FANs;
* @fan: pointer to FAN devices data array;
*
* Structure represents board platform data, related to system hotplug events,
* like FAN, PSU, power cable insertion and removing. This data provides the
* number of hot-pluggable devices and hardware description for event handling.
*/
struct mlxcpld_hotplug_platform_data {
u16 top_aggr_offset;
u8 top_aggr_mask;
u8 top_aggr_psu_mask;
u16 psu_reg_offset;
u8 psu_mask;
u8 psu_count;
struct mlxcpld_hotplug_device *psu;
u8 top_aggr_pwr_mask;
u16 pwr_reg_offset;
u8 pwr_mask;
u8 pwr_count;
struct mlxcpld_hotplug_device *pwr;
u8 top_aggr_fan_mask;
u16 fan_reg_offset;
u8 fan_mask;
u8 fan_count;
struct mlxcpld_hotplug_device *fan;
};
#endif /* __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment