195c3e4b4SKate Hsuan // SPDX-License-Identifier: GPL-2.0
295c3e4b4SKate Hsuan /*
395c3e4b4SKate Hsuan * WMI Thunderbolt driver
495c3e4b4SKate Hsuan *
595c3e4b4SKate Hsuan * Copyright (C) 2017 Dell Inc. All Rights Reserved.
695c3e4b4SKate Hsuan */
795c3e4b4SKate Hsuan
895c3e4b4SKate Hsuan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
995c3e4b4SKate Hsuan
1095c3e4b4SKate Hsuan #include <linux/acpi.h>
1195c3e4b4SKate Hsuan #include <linux/device.h>
1295c3e4b4SKate Hsuan #include <linux/fs.h>
1395c3e4b4SKate Hsuan #include <linux/kernel.h>
1495c3e4b4SKate Hsuan #include <linux/module.h>
1595c3e4b4SKate Hsuan #include <linux/string.h>
1695c3e4b4SKate Hsuan #include <linux/sysfs.h>
1795c3e4b4SKate Hsuan #include <linux/types.h>
1895c3e4b4SKate Hsuan #include <linux/wmi.h>
1995c3e4b4SKate Hsuan
2095c3e4b4SKate Hsuan #define INTEL_WMI_THUNDERBOLT_GUID "86CCFD48-205E-4A77-9C48-2021CBEDE341"
2195c3e4b4SKate Hsuan
force_power_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2295c3e4b4SKate Hsuan static ssize_t force_power_store(struct device *dev,
2395c3e4b4SKate Hsuan struct device_attribute *attr,
2495c3e4b4SKate Hsuan const char *buf, size_t count)
2595c3e4b4SKate Hsuan {
2695c3e4b4SKate Hsuan struct acpi_buffer input;
2795c3e4b4SKate Hsuan acpi_status status;
2895c3e4b4SKate Hsuan u8 mode;
2995c3e4b4SKate Hsuan
3095c3e4b4SKate Hsuan input.length = sizeof(u8);
3195c3e4b4SKate Hsuan input.pointer = &mode;
3295c3e4b4SKate Hsuan mode = hex_to_bin(buf[0]);
3395c3e4b4SKate Hsuan dev_dbg(dev, "force_power: storing %#x\n", mode);
3495c3e4b4SKate Hsuan if (mode == 0 || mode == 1) {
3595c3e4b4SKate Hsuan status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1,
3695c3e4b4SKate Hsuan &input, NULL);
3795c3e4b4SKate Hsuan if (ACPI_FAILURE(status)) {
3895c3e4b4SKate Hsuan dev_dbg(dev, "force_power: failed to evaluate ACPI method\n");
3995c3e4b4SKate Hsuan return -ENODEV;
4095c3e4b4SKate Hsuan }
4195c3e4b4SKate Hsuan } else {
4295c3e4b4SKate Hsuan dev_dbg(dev, "force_power: unsupported mode\n");
4395c3e4b4SKate Hsuan return -EINVAL;
4495c3e4b4SKate Hsuan }
4595c3e4b4SKate Hsuan return count;
4695c3e4b4SKate Hsuan }
4795c3e4b4SKate Hsuan
4895c3e4b4SKate Hsuan static DEVICE_ATTR_WO(force_power);
4995c3e4b4SKate Hsuan
5095c3e4b4SKate Hsuan static struct attribute *tbt_attrs[] = {
5195c3e4b4SKate Hsuan &dev_attr_force_power.attr,
5295c3e4b4SKate Hsuan NULL
5395c3e4b4SKate Hsuan };
54*4e3d731bSShyam Sundar S K ATTRIBUTE_GROUPS(tbt);
5595c3e4b4SKate Hsuan
5695c3e4b4SKate Hsuan static const struct wmi_device_id intel_wmi_thunderbolt_id_table[] = {
5795c3e4b4SKate Hsuan { .guid_string = INTEL_WMI_THUNDERBOLT_GUID },
5895c3e4b4SKate Hsuan { },
5995c3e4b4SKate Hsuan };
6095c3e4b4SKate Hsuan
6195c3e4b4SKate Hsuan static struct wmi_driver intel_wmi_thunderbolt_driver = {
6295c3e4b4SKate Hsuan .driver = {
6395c3e4b4SKate Hsuan .name = "intel-wmi-thunderbolt",
64*4e3d731bSShyam Sundar S K .dev_groups = tbt_groups,
6595c3e4b4SKate Hsuan },
6695c3e4b4SKate Hsuan .id_table = intel_wmi_thunderbolt_id_table,
6795c3e4b4SKate Hsuan };
6895c3e4b4SKate Hsuan
6995c3e4b4SKate Hsuan module_wmi_driver(intel_wmi_thunderbolt_driver);
7095c3e4b4SKate Hsuan
7195c3e4b4SKate Hsuan MODULE_DEVICE_TABLE(wmi, intel_wmi_thunderbolt_id_table);
7295c3e4b4SKate Hsuan MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
7395c3e4b4SKate Hsuan MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver");
7495c3e4b4SKate Hsuan MODULE_LICENSE("GPL v2");
75