diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 18:54:05 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 18:54:05 -0800 |
commit | b7a8399edfd7ad3da36d51513ea30a4708b02b52 (patch) | |
tree | 5da5a480f020cefc4450ca679bf7d193fe82462f /drivers/platform | |
parent | 30c867eebfbd1c25310aec9f152578deaf793080 (diff) | |
parent | b4b0b4a9e0392dbd00e5f033e1329ce61ed06fef (diff) |
Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86
Pull x86 platform drivers update from Matthew Garrett:
"Nothing amazingly special here. Some cleanups, a new driver to
support a single button on some new HPs, a tiny amount of hardware
enablement"
* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86:
ipc: add intel-mid's pci id macros
hp-wireless: new driver for hp wireless button for Windows 8
toshiba_acpi: Support RFKILL hotkey scancode
hp_accel: Add a new PnP ID HPQ6007 for new HP laptops
sony-laptop: remove unnecessary assigment of len
fujitsu-laptop: fix error return code
dell-laptop: Only install the i8042 filter when rfkill is active
X86 platform: New BayTrail IOSF-SB MBI driver
drivers: platform: Include appropriate header file in mxm-wmi.c
drivers: platform: Mark functions as static in hp_accel.c
dell-laptop: rkill whitelist Precision models
ipc: simplify platform data approach
asus-wmi: Convert to use devm_hwmon_device_register_with_groups
compal-laptop: Use devm_hwmon_device_register_with_groups
compal-laptop: Replace SENSOR_DEVICE_ATTR with DEVICE_ATTR
eeepc-laptop: Convert to use devm_hwmon_device_register_with_groups
compal-laptop: Use devm_kzalloc to allocate local data structure
dell-laptop: fix to return error code in dell_send_intensity()
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 19 | ||||
-rw-r--r-- | drivers/platform/x86/Makefile | 2 | ||||
-rw-r--r-- | drivers/platform/x86/asus-wmi.c | 48 | ||||
-rw-r--r-- | drivers/platform/x86/compal-laptop.c | 121 | ||||
-rw-r--r-- | drivers/platform/x86/dell-laptop.c | 78 | ||||
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 52 | ||||
-rw-r--r-- | drivers/platform/x86/fujitsu-laptop.c | 15 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wireless.c | 132 | ||||
-rw-r--r-- | drivers/platform/x86/hp_accel.c | 7 | ||||
-rw-r--r-- | drivers/platform/x86/intel_baytrail.c | 224 | ||||
-rw-r--r-- | drivers/platform/x86/intel_baytrail.h | 90 | ||||
-rw-r--r-- | drivers/platform/x86/intel_scu_ipc.c | 87 | ||||
-rw-r--r-- | drivers/platform/x86/mxm-wmi.c | 1 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 1 |
15 files changed, 642 insertions, 237 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index d9dcd37b5a52..5ae65c11d544 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -197,6 +197,17 @@ config HP_ACCEL To compile this driver as a module, choose M here: the module will be called hp_accel. +config HP_WIRELESS + tristate "HP WIRELESS" + depends on ACPI + depends on INPUT + help + This driver provides supports for new HP wireless button for Windows 8. + On such systems the driver should load automatically (via ACPI alias). + + To compile this driver as a module, choose M here: the module will + be called hp-wireless. + config HP_WMI tristate "HP WMI extras" depends on ACPI_WMI @@ -808,4 +819,12 @@ config PVPANIC a paravirtualized device provided by QEMU; it lets a virtual machine (guest) communicate panic events to the host. +config INTEL_BAYTRAIL_MBI + tristate + depends on PCI + ---help--- + Needed on Baytrail platforms for access to the IOSF Sideband Mailbox + Interface. This is a requirement for systems that need to configure + the PUNIT for power management features such as RAPL. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index f0e6aa407ffb..9b87cfc42b84 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ACERHDF) += acerhdf.o obj-$(CONFIG_HP_ACCEL) += hp_accel.o +obj-$(CONFIG_HP_WIRELESS) += hp-wireless.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o @@ -54,3 +55,4 @@ obj-$(CONFIG_INTEL_RST) += intel-rst.o obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o +obj-$(CONFIG_INTEL_BAYTRAIL_MBI) += intel_baytrail.o diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 109f6383040c..c5e082fb82fa 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -183,7 +183,6 @@ struct asus_wmi { struct input_dev *inputdev; struct backlight_device *backlight_device; - struct device *hwmon_device; struct platform_device *platform_device; struct led_classdev wlan_led; @@ -1072,20 +1071,12 @@ static ssize_t asus_hwmon_temp1(struct device *dev, return sprintf(buf, "%d\n", value); } -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0); - -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "asus\n"); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +static DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL); +static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL); static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, + &dev_attr_pwm1.attr, + &dev_attr_temp1_input.attr, NULL }; @@ -1099,9 +1090,9 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, int dev_id = -1; u32 value = ASUS_WMI_UNSUPPORTED_METHOD; - if (attr == &sensor_dev_attr_pwm1.dev_attr.attr) + if (attr == &dev_attr_pwm1.attr) dev_id = ASUS_WMI_DEVID_FAN_CTRL; - else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr) + else if (attr == &dev_attr_temp1_input.attr) dev_id = ASUS_WMI_DEVID_THERMAL_CTRL; if (dev_id != -1) { @@ -1136,35 +1127,20 @@ static struct attribute_group hwmon_attribute_group = { .is_visible = asus_hwmon_sysfs_is_visible, .attrs = hwmon_attributes }; - -static void asus_wmi_hwmon_exit(struct asus_wmi *asus) -{ - struct device *hwmon; - - hwmon = asus->hwmon_device; - if (!hwmon) - return; - sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group); - hwmon_device_unregister(hwmon); - asus->hwmon_device = NULL; -} +__ATTRIBUTE_GROUPS(hwmon_attribute); static int asus_wmi_hwmon_init(struct asus_wmi *asus) { struct device *hwmon; - int result; - hwmon = hwmon_device_register(&asus->platform_device->dev); + hwmon = hwmon_device_register_with_groups(&asus->platform_device->dev, + "asus", asus, + hwmon_attribute_groups); if (IS_ERR(hwmon)) { pr_err("Could not register asus hwmon device\n"); return PTR_ERR(hwmon); } - dev_set_drvdata(hwmon, asus); - asus->hwmon_device = hwmon; - result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group); - if (result) - asus_wmi_hwmon_exit(asus); - return result; + return 0; } /* @@ -1835,7 +1811,6 @@ fail_backlight: fail_rfkill: asus_wmi_led_exit(asus); fail_leds: - asus_wmi_hwmon_exit(asus); fail_hwmon: asus_wmi_input_exit(asus); fail_input: @@ -1853,7 +1828,6 @@ static int asus_wmi_remove(struct platform_device *device) wmi_remove_notify_handler(asus->driver->event_guid); asus_wmi_backlight_exit(asus); asus_wmi_input_exit(asus); - asus_wmi_hwmon_exit(asus); asus_wmi_led_exit(asus); asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index eaa78edb1f4e..7297df2ebf50 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -173,8 +173,7 @@ /* ======= */ struct compal_data{ /* Fan control */ - struct device *hwmon_dev; - int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by moterboard */ + int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by motherboard */ unsigned char curr_pwm; /* Power supply */ @@ -402,15 +401,6 @@ SIMPLE_MASKED_STORE_SHOW(wake_up_wlan, WAKE_UP_ADDR, WAKE_UP_WLAN) SIMPLE_MASKED_STORE_SHOW(wake_up_key, WAKE_UP_ADDR, WAKE_UP_KEY) SIMPLE_MASKED_STORE_SHOW(wake_up_mouse, WAKE_UP_ADDR, WAKE_UP_MOUSE) - -/* General hwmon interface */ -static ssize_t hwmon_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", DRIVER_NAME); -} - - /* Fan control interface */ static ssize_t pwm_enable_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -665,55 +655,55 @@ static DEVICE_ATTR(wake_up_key, static DEVICE_ATTR(wake_up_mouse, 0644, wake_up_mouse_show, wake_up_mouse_store); -static SENSOR_DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL, 1); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL, 1); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL, 1); -static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL, 1); -static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL, 1); -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store, 1); -static SENSOR_DEVICE_ATTR(pwm1_enable, - S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store, 0); - -static struct attribute *compal_attributes[] = { +static DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL); +static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL); +static DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL); +static DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL); +static DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL); +static DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL); +static DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL); +static DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL); +static DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL); +static DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL); +static DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL); +static DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL); +static DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL); +static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store); +static DEVICE_ATTR(pwm1_enable, + S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store); + +static struct attribute *compal_platform_attrs[] = { &dev_attr_wake_up_pme.attr, &dev_attr_wake_up_modem.attr, &dev_attr_wake_up_lan.attr, &dev_attr_wake_up_wlan.attr, &dev_attr_wake_up_key.attr, &dev_attr_wake_up_mouse.attr, - /* Maybe put the sensor-stuff in a separate hwmon-driver? That way, - * the hwmon sysfs won't be cluttered with the above files. */ - &sensor_dev_attr_name.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_temp4_label.dev_attr.attr, - &sensor_dev_attr_temp5_label.dev_attr.attr, - &sensor_dev_attr_temp6_label.dev_attr.attr, NULL }; +static struct attribute_group compal_platform_attr_group = { + .attrs = compal_platform_attrs +}; -static struct attribute_group compal_attribute_group = { - .attrs = compal_attributes +static struct attribute *compal_hwmon_attrs[] = { + &dev_attr_pwm1_enable.attr, + &dev_attr_pwm1.attr, + &dev_attr_fan1_input.attr, + &dev_attr_temp1_input.attr, + &dev_attr_temp2_input.attr, + &dev_attr_temp3_input.attr, + &dev_attr_temp4_input.attr, + &dev_attr_temp5_input.attr, + &dev_attr_temp6_input.attr, + &dev_attr_temp1_label.attr, + &dev_attr_temp2_label.attr, + &dev_attr_temp3_label.attr, + &dev_attr_temp4_label.attr, + &dev_attr_temp5_label.attr, + &dev_attr_temp6_label.attr, + NULL }; +ATTRIBUTE_GROUPS(compal_hwmon); static int compal_probe(struct platform_device *); static int compal_remove(struct platform_device *); @@ -1021,30 +1011,28 @@ static int compal_probe(struct platform_device *pdev) { int err; struct compal_data *data; + struct device *hwmon_dev; if (!extra_features) return 0; /* Fan control */ - data = kzalloc(sizeof(struct compal_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct compal_data), GFP_KERNEL); if (!data) return -ENOMEM; initialize_fan_control_data(data); - err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); - if (err) { - kfree(data); + err = sysfs_create_group(&pdev->dev.kobj, &compal_platform_attr_group); + if (err) return err; - } - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, - &compal_attribute_group); - kfree(data); - return err; + hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, + DRIVER_NAME, data, + compal_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto remove; } /* Power supply */ @@ -1054,6 +1042,10 @@ static int compal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); return 0; + +remove: + sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group); + return err; } static void __exit compal_cleanup(void) @@ -1080,12 +1072,9 @@ static int compal_remove(struct platform_device *pdev) pwm_disable_control(); data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->hwmon_dev); power_supply_unregister(&data->psy); - kfree(data); - - sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group); + sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group); return 0; } diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index c608b1d33f4a..fed4111ac31a 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -559,19 +559,45 @@ static void dell_update_rfkill(struct work_struct *ignored) } static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); +static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, + round_jiffies_relative(HZ / 4)); + break; + } + extended = false; + } + + return false; +} static int __init dell_setup_rfkill(void) { - int status; - int ret; + int status, ret, whitelisted; const char *product; /* - * rfkill causes trouble on various non Latitudes, according to Dell - * actually testing the rfkill functionality is only done on Latitudes. + * rfkill support causes trouble on various models, mostly Inspirons. + * So we whitelist certain series, and don't support rfkill on others. */ + whitelisted = 0; product = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!force_rfkill && (!product || strncmp(product, "Latitude", 8))) + if (product && (strncmp(product, "Latitude", 8) == 0 || + strncmp(product, "Precision", 9) == 0)) + whitelisted = 1; + if (!force_rfkill && !whitelisted) return 0; get_buffer(); @@ -633,7 +659,16 @@ static int __init dell_setup_rfkill(void) goto err_wwan; } + ret = i8042_install_filter(dell_laptop_i8042_filter); + if (ret) { + pr_warn("Unable to install key filter\n"); + goto err_filter; + } + return 0; +err_filter: + if (wwan_rfkill) + rfkill_unregister(wwan_rfkill); err_wwan: rfkill_destroy(wwan_rfkill); if (bluetooth_rfkill) @@ -684,7 +719,7 @@ static int dell_send_intensity(struct backlight_device *bd) out: release_buffer(); - return 0; + return ret; } static int dell_get_intensity(struct backlight_device *bd) @@ -755,30 +790,6 @@ static void touchpad_led_exit(void) led_classdev_unregister(&touchpad_led); } -static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, - struct serio *port) -{ - static bool extended; - - if (str & 0x20) - return false; - - if (unlikely(data == 0xe0)) { - extended = true; - return false; - } else if (unlikely(extended)) { - switch (data) { - case 0x8: - schedule_delayed_work(&dell_rfkill_work, - round_jiffies_relative(HZ / 4)); - break; - } - extended = false; - } - - return false; -} - static int __init dell_init(void) { int max_intensity = 0; @@ -828,12 +839,6 @@ static int __init dell_init(void) goto fail_rfkill; } - ret = i8042_install_filter(dell_laptop_i8042_filter); - if (ret) { - pr_warn("Unable to install key filter\n"); - goto fail_filter; - } - if (quirks && quirks->touchpad_led) touchpad_led_init(&platform_device->dev); @@ -885,7 +890,6 @@ static int __init dell_init(void) fail_backlight: i8042_remove_filter(dell_laptop_i8042_filter); cancel_delayed_work_sync(&dell_rfkill_work); -fail_filter: dell_cleanup_rfkill(); fail_rfkill: free_page((unsigned long)bufferpage); diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index ed69ec5f36f7..399e8c562192 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -165,7 +165,6 @@ struct eeepc_laptop { struct platform_device *platform_device; struct acpi_device *device; /* the device we are in */ - struct device *hwmon_device; struct backlight_device *backlight_device; struct input_dev *inputdev; @@ -1068,7 +1067,7 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) { \ return store_sys_hwmon(_get, buf, count); \ } \ - static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); + static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, @@ -1076,55 +1075,26 @@ EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "eeepc\n"); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, +static struct attribute *hwmon_attrs[] = { + &dev_attr_pwm1.attr, + &dev_attr_fan1_input.attr, + &dev_attr_pwm1_enable.attr, NULL }; - -static struct attribute_group hwmon_attribute_group = { - .attrs = hwmon_attributes -}; - -static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc) -{ - struct device *hwmon; - - hwmon = eeepc->hwmon_device; - if (!hwmon) - return; - sysfs_remove_group(&hwmon->kobj, - &hwmon_attribute_group); - hwmon_device_unregister(hwmon); - eeepc->hwmon_device = NULL; -} +ATTRIBUTE_GROUPS(hwmon); static int eeepc_hwmon_init(struct eeepc_laptop *eeepc) { + struct device *dev = &eeepc->platform_device->dev; struct device *hwmon; - int result; - hwmon = hwmon_device_register(&eeepc->platform_device->dev); + hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL, + hwmon_groups); if (IS_ERR(hwmon)) { pr_err("Could not register eeepc hwmon device\n"); - eeepc->hwmon_device = NULL; return PTR_ERR(hwmon); } - eeepc->hwmon_device = hwmon; - result = sysfs_create_group(&hwmon->kobj, - &hwmon_attribute_group); - if (result) - eeepc_hwmon_exit(eeepc); - return result; + return 0; } /* @@ -1480,7 +1450,6 @@ static int eeepc_acpi_add(struct acpi_device *device) fail_rfkill: eeepc_led_exit(eeepc); fail_led: - eeepc_hwmon_exit(eeepc); fail_hwmon: eeepc_input_exit(eeepc); fail_input: @@ -1500,7 +1469,6 @@ static int eeepc_acpi_remove(struct acpi_device *device) eeepc_backlight_exit(eeepc); eeepc_rfkill_exit(eeepc); eeepc_input_exit(eeepc); - eeepc_hwmon_exit(eeepc); eeepc_led_exit(eeepc); eeepc_platform_exit(eeepc); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 9d30d69aa78f..be02bcc346d3 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -633,7 +633,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = { static int acpi_fujitsu_add(struct acpi_device *device) { - int result = 0; int state = 0; struct input_dev *input; int error; @@ -669,8 +668,8 @@ static int acpi_fujitsu_add(struct acpi_device *device) if (error) goto err_free_input_dev; - result = acpi_bus_update_power(fujitsu->acpi_handle, &state); - if (result) { + error = acpi_bus_update_power(fujitsu->acpi_handle, &state); + if (error) { pr_err("Error reading power state\n"); goto err_unregister_input_dev; } @@ -700,7 +699,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS; get_lcd_level(); - return result; + return 0; err_unregister_input_dev: input_unregister_device(input); @@ -708,7 +707,7 @@ err_unregister_input_dev: err_free_input_dev: input_free_device(input); err_stop: - return result; + return error; } static int acpi_fujitsu_remove(struct acpi_device *device) @@ -831,8 +830,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) if (error) goto err_free_input_dev; - result = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state); - if (result) { + error = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state); + if (error) { pr_err("Error reading power state\n"); goto err_unregister_input_dev; } @@ -907,7 +906,7 @@ err_free_input_dev: err_free_fifo: kfifo_free(&fujitsu_hotkey->fifo); err_stop: - return result; + return error; } static int acpi_fujitsu_hotkey_remove(struct acpi_device *device) diff --git a/drivers/platform/x86/hp-wireless.c b/drivers/platform/x86/hp-wireless.c new file mode 100644 index 000000000000..415348fc1210 --- /dev/null +++ b/drivers/platform/x86/hp-wireless.c @@ -0,0 +1,132 @@ +/* + * hp-wireless button for Windows 8 + * + * Copyright (C) 2014 Alex Hung <alex.hung@canonical.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/acpi.h> +#include <acpi/acpi_bus.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alex Hung"); +MODULE_ALIAS("acpi*:HPQ6001:*"); + +static struct input_dev *hpwl_input_dev; + +static const struct acpi_device_id hpwl_ids[] = { + {"HPQ6001", 0}, + {"", 0}, +}; + +static int hp_wireless_input_setup(void) +{ + int err; + + hpwl_input_dev = input_allocate_device(); + if (!hpwl_input_dev) + return -ENOMEM; + + hpwl_input_dev->name = "HP Wireless hotkeys"; + hpwl_input_dev->phys = "hpq6001/input0"; + hpwl_input_dev->id.bustype = BUS_HOST; + hpwl_input_dev->evbit[0] = BIT(EV_KEY); + set_bit(KEY_RFKILL, hpwl_input_dev->keybit); + + err = input_register_device(hpwl_input_dev); + if (err) + goto err_free_dev; + + return 0; + +err_free_dev: + input_free_device(hpwl_input_dev); + return err; +} + +static void hp_wireless_input_destroy(void) +{ + input_unregister_device(hpwl_input_dev); +} + +static void hpwl_notify(struct acpi_device *acpi_dev, u32 event) +{ + if (event != 0x80) { + pr_info("Received unknown event (0x%x)\n", event); + return; + } + + input_report_key(hpwl_input_dev, KEY_RFKILL, 1); + input_sync(hpwl_input_dev); + input_report_key(hpwl_input_dev, KEY_RFKILL, 0); + input_sync(hpwl_input_dev); +} + +static int hpwl_add(struct acpi_device *device) +{ + int err; + + err = hp_wireless_input_setup(); + return err; +} + +static int hpwl_remove(struct acpi_device *device) +{ + hp_wireless_input_destroy(); + return 0; +} + +static struct acpi_driver hpwl_driver = { + .name = "hp-wireless", + .owner = THIS_MODULE, + .ids = hpwl_ids, + .ops = { + .add = hpwl_add, + .remove = hpwl_remove, + .notify = hpwl_notify, + }, +}; + +static int __init hpwl_init(void) +{ + int err; + + pr_info("Initializing HPQ6001 module\n"); + err = acpi_bus_register_driver(&hpwl_driver); + if (err) { + pr_err("Unable to register HP wireless control driver.\n"); + goto error_acpi_register; + } + + return 0; + +error_acpi_register: + return err; +} + +static void __exit hpwl_exit(void) +{ + pr_info("Exiting HPQ6001 module\n"); + acpi_bus_unregister_driver(&hpwl_driver); +} + +module_init(hpwl_init); +module_exit(hpwl_exit); diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index aff4d0670edf..3dc934438c28 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -77,6 +77,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, static struct acpi_device_id lis3lv02d_device_ids[] = { {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ + {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ {"", 0}, }; MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); @@ -88,7 +89,7 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); * * Returns 0 on success. */ -int lis3lv02d_acpi_init(struct lis3lv02d *lis3) +static int lis3lv02d_acpi_init(struct lis3lv02d *lis3) { struct acpi_device *dev = lis3->bus_priv; if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI, @@ -106,7 +107,7 @@ int lis3lv02d_acpi_init(struct lis3lv02d *lis3) * * Returns 0 on success. */ -int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) +static int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) { struct acpi_device *dev = lis3->bus_priv; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; @@ -129,7 +130,7 @@ int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) * * Returns 0 on success. */ -int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) +static int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) { struct acpi_device *dev = lis3->bus_priv; unsigned long long ret; /* Not used when writting */ diff --git a/drivers/platform/x86/intel_baytrail.c b/drivers/platform/x86/intel_baytrail.c new file mode 100644 index 000000000000..f96626b17260 --- /dev/null +++ b/drivers/platform/x86/intel_baytrail.c @@ -0,0 +1,224 @@ +/* + * Baytrail IOSF-SB MailBox Interface Driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * + * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a + * mailbox interface (MBI) to communicate with mutiple devices. This + * driver implements BayTrail-specific access to this interface. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/pci.h> + +#include "intel_baytrail.h" + +static DEFINE_SPINLOCK(iosf_mbi_lock); + +static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) +{ + return (op << 24) | (port << 16) | (offset << 8) | BT_MBI_ENABLE; +} + +static struct pci_dev *mbi_pdev; /* one mbi device */ + +/* Hold lock before calling */ +static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr) +{ + int result; + + if (!mbi_pdev) + return -ENODEV; + + if (mcrx) { + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCRX_OFFSET, mcrx); + if (result < 0) + goto iosf_mbi_read_err; + } + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCR_OFFSET, mcr); + if (result < 0) + goto iosf_mbi_read_err; + + result = pci_read_config_dword(mbi_pdev, + BT_MBI_MDR_OFFSET, mdr); + if (result < 0) + goto iosf_mbi_read_err; + + return 0; + +iosf_mbi_read_err: + dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n", + result); + return result; +} + +/* Hold lock before calling */ +static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr) +{ + int result; + + if (!mbi_pdev) + return -ENODEV; + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MDR_OFFSET, mdr); + if (result < 0) + goto iosf_mbi_write_err; + + if (mcrx) { + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCRX_OFFSET, mcrx); + if (result < 0) + goto iosf_mbi_write_err; + } + + result = pci_write_config_dword(mbi_pdev, + BT_MBI_MCR_OFFSET, mcr); + if (result < 0) + goto iosf_mbi_write_err; + + return 0; + +iosf_mbi_write_err: + dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n", + result); + return result; +} + +int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) +{ + u32 mcr, mcrx; + unsigned long flags; + int ret; + + /*Access to the GFX unit is handled by GPU code */ + BUG_ON(port == BT_MBI_UNIT_GFX); + + mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO); + mcrx = offset & BT_MBI_MASK_HI; + + spin_lock_irqsave(&iosf_mbi_lock, fla |