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()
This commit is contained in:
Linus Torvalds 2014-01-29 18:54:05 -08:00
commit b7a8399edf
15 changed files with 642 additions and 237 deletions

View File

@ -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

View File

@ -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

View File

@ -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 @@ static int asus_wmi_add(struct platform_device *pdev)
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);

View File

@ -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,56 +655,56 @@ 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 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_attributes[] = {
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_attribute_group = {
.attrs = compal_attributes
static struct attribute_group compal_platform_attr_group = {
.attrs = compal_platform_attrs
};
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 *);
static struct platform_driver compal_driver = {
@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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 @@ static int acpi_fujitsu_add(struct acpi_device *device)
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 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
err_free_fifo:
kfifo_free(&fujitsu_hotkey->fifo);
err_stop:
return result;
return error;
}
static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)

View File

@ -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);

View File

@ -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 */

View File

@ -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, flags);
ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr);
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
return ret;
}
EXPORT_SYMBOL(bt_mbi_read);
int bt_mbi_write(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, flags);
ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr);
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
return ret;
}
EXPORT_SYMBOL(bt_mbi_write);
int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
{
u32 mcr, mcrx;
u32 value;
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, flags);
/* Read current mdr value */
ret = iosf_mbi_pci_read_mdr(mcrx, mcr & BT_MBI_RD_MASK, &value);
if (ret < 0) {
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
return ret;
}
/* Apply mask */
value &= ~mask;
mdr &= mask;
value |= mdr;
/* Write back */
ret = iosf_mbi_pci_write_mdr(mcrx, mcr | BT_MBI_WR_MASK, value);
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
return ret;
}
EXPORT_SYMBOL(bt_mbi_modify);
static int iosf_mbi_probe(struct pci_dev *pdev,
const struct pci_device_id *unused)
{
int ret;
ret = pci_enable_device(pdev);
if (ret < 0) {
dev_err(&pdev->dev, "error: could not enable device\n");
return ret;
}
mbi_pdev = pci_dev_get(pdev);
return 0;
}
static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids);
static struct pci_driver iosf_mbi_pci_driver = {
.name = "iosf_mbi_pci",
.probe = iosf_mbi_probe,
.id_table = iosf_mbi_pci_ids,
};
static int __init bt_mbi_init(void)
{
return pci_register_driver(&iosf_mbi_pci_driver);
}
static void __exit bt_mbi_exit(void)
{
pci_unregister_driver(&iosf_mbi_pci_driver);
if (mbi_pdev) {
pci_dev_put(mbi_pdev);
mbi_pdev = NULL;
}
}
module_init(bt_mbi_init);
module_exit(bt_mbi_exit);
MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
MODULE_DESCRIPTION("BayTrail Mailbox Interface accessor");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,90 @@
/*
* intel_baytrail.h: MailBox access support for Intel BayTrail platforms
*/
#ifndef INTEL_BAYTRAIL_MBI_SYMS_H
#define INTEL_BAYTRAIL_MBI_SYMS_H
#define BT_MBI_MCR_OFFSET 0xD0
#define BT_MBI_MDR_OFFSET 0xD4
#define BT_MBI_MCRX_OFFSET 0xD8
#define BT_MBI_RD_MASK 0xFEFFFFFF
#define BT_MBI_WR_MASK 0X01000000
#define BT_MBI_MASK_HI 0xFFFFFF00
#define BT_MBI_MASK_LO 0x000000FF
#define BT_MBI_ENABLE 0xF0
/* BT-SB unit access methods */
#define BT_MBI_UNIT_AUNIT 0x00
#define BT_MBI_UNIT_SMC 0x01
#define BT_MBI_UNIT_CPU 0x02
#define BT_MBI_UNIT_BUNIT 0x03
#define BT_MBI_UNIT_PMC 0x04
#define BT_MBI_UNIT_GFX 0x06
#define BT_MBI_UNIT_SMI 0x0C
#define BT_MBI_UNIT_USB 0x43
#define BT_MBI_UNIT_SATA 0xA3
#define BT_MBI_UNIT_PCIE 0xA6
/* Read/write opcodes */
#define BT_MBI_AUNIT_READ 0x10
#define BT_MBI_AUNIT_WRITE 0x11
#define BT_MBI_SMC_READ 0x10
#define BT_MBI_SMC_WRITE 0x11
#define BT_MBI_CPU_READ 0x10
#define BT_MBI_CPU_WRITE 0x11
#define BT_MBI_BUNIT_READ 0x10
#define BT_MBI_BUNIT_WRITE 0x11
#define BT_MBI_PMC_READ 0x06
#define BT_MBI_PMC_WRITE 0x07
#define BT_MBI_GFX_READ 0x00
#define BT_MBI_GFX_WRITE 0x01
#define BT_MBI_SMIO_READ 0x06
#define BT_MBI_SMIO_WRITE 0x07
#define BT_MBI_USB_READ 0x06
#define BT_MBI_USB_WRITE 0x07
#define BT_MBI_SATA_READ 0x00
#define BT_MBI_SATA_WRITE 0x01
#define BT_MBI_PCIE_READ 0x00
#define BT_MBI_PCIE_WRITE 0x01
/**
* bt_mbi_read() - MailBox Interface read command
* @port: port indicating subunit being accessed
* @opcode: port specific read or write opcode
* @offset: register address offset
* @mdr: register data to be read
*
* Locking is handled by spinlock - cannot sleep.
* Return: Nonzero on error
*/
int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr);
/**
* bt_mbi_write() - MailBox unmasked write command
* @port: port indicating subunit being accessed
* @opcode: port specific read or write opcode
* @offset: register address offset
* @mdr: register data to be written
*
* Locking is handled by spinlock - cannot sleep.
* Return: Nonzero on error
*/
int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
/**
* bt_mbi_modify() - MailBox masked write command
* @port: port indicating subunit being accessed
* @opcode: port specific read or write opcode
* @offset: register address offset
* @mdr: register data being modified
* @mask: mask indicating bits in mdr to be modified
*
* Locking is handled by spinlock - cannot sleep.
* Return: Nonzero on error
*/
int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);
#endif /* INTEL_BAYTRAIL_MBI_SYMS_H */

View File

@ -62,12 +62,10 @@
#define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */
#define IPC_IOC 0x100 /* IPC command register IOC bit */
enum {
SCU_IPC_LINCROFT,
SCU_IPC_PENWELL,
SCU_IPC_CLOVERVIEW,
SCU_IPC_TANGIER,
};
#define PCI_DEVICE_ID_LINCROFT 0x082a
#define PCI_DEVICE_ID_PENWELL 0x080e
#define PCI_DEVICE_ID_CLOVERVIEW 0x08ea
#define PCI_DEVICE_ID_TANGIER 0x11a0
/* intel scu ipc driver data*/
struct intel_scu_ipc_pdata_t {
@ -78,35 +76,29 @@ struct intel_scu_ipc_pdata_t {
u8 irq_mode;
};
static struct intel_scu_ipc_pdata_t intel_scu_ipc_pdata[] = {
[SCU_IPC_LINCROFT] = {
.ipc_base = 0xff11c000,
.i2c_base = 0xff12b000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 0,
},
[SCU_IPC_PENWELL] = {
.ipc_base = 0xff11c000,
.i2c_base = 0xff12b000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 1,
},
[SCU_IPC_CLOVERVIEW] = {
.ipc_base = 0xff11c000,
.i2c_base = 0xff12b000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 1,
},
[SCU_IPC_TANGIER] = {
.ipc_base = 0xff009000,
.i2c_base = 0xff00d000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 0,
},
static struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = {
.ipc_base = 0xff11c000,
.i2c_base = 0xff12b000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 0,
};
/* Penwell and Cloverview */
static struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = {
.ipc_base = 0xff11c000,
.i2c_base = 0xff12b000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 1,
};
static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
.ipc_base = 0xff009000,
.i2c_base = 0xff00d000,
.ipc_len = 0x100,
.i2c_len = 0x10,
.irq_mode = 0,
};
static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id);
@ -583,15 +575,14 @@ static irqreturn_t ioc(int irq, void *dev_id)
*/
static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int err, pid;
int err;
struct intel_scu_ipc_pdata_t *pdata;
resource_size_t pci_resource;
if (ipcdev.pdev) /* We support only one SCU */
return -EBUSY;
pid = id->driver_data;
pdata = &intel_scu_ipc_pdata[pid];
pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
ipcdev.pdev = pci_dev_get(dev);
ipcdev.irq_mode = pdata->irq_mode;
@ -650,11 +641,21 @@ static void ipc_remove(struct pci_dev *pdev)
}
static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
{PCI_VDEVICE(INTEL, 0x082a), SCU_IPC_LINCROFT},
{PCI_VDEVICE(INTEL, 0x080e), SCU_IPC_PENWELL},
{PCI_VDEVICE(INTEL, 0x08ea), SCU_IPC_CLOVERVIEW},
{PCI_VDEVICE(INTEL, 0x11a0), SCU_IPC_TANGIER},
{ 0,}
{
PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT),
(kernel_ulong_t)&intel_scu_ipc_lincroft_pdata,
}, {
PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL),
(kernel_ulong_t)&intel_scu_ipc_penwell_pdata,
}, {
PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CLOVERVIEW),
(kernel_ulong_t)&intel_scu_ipc_penwell_pdata,
}, {
PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER),
(kernel_ulong_t)&intel_scu_ipc_tangier_pdata,
}, {
0,
}
};
MODULE_DEVICE_TABLE(pci, pci_ids);

View File

@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mxm-wmi.h>
#include <linux/acpi.h>
MODULE_AUTHOR("Dave Airlie");

View File

@ -789,7 +789,7 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
void *buffer, size_t buflen)
{
int ret = 0;
size_t len = len;
size_t len;
union acpi_object *object = __call_snc_method(handle, name, value);
if (!object)

View File

@ -149,6 +149,7 @@ static const struct acpi_device_id toshiba_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
static const struct key_entry toshiba_acpi_keymap[] = {
{ KE_KEY, 0x9e, { KEY_RFKILL } },
{ KE_KEY, 0x101, { KEY_MUTE } },
{ KE_KEY, 0x102, { KEY_ZOOMOUT } },
{ KE_KEY, 0x103, { KEY_ZOOMIN } },