diff options
author | Azael Avalos <coproscefalo@gmail.com> | 2015-02-10 23:09:20 -0500 |
---|---|---|
committer | Darren Hart <dvhart@linux.intel.com> | 2015-02-11 23:40:48 -0500 |
commit | 17fe4b3d31e6b1d3afd40a34849fa353d0ca5616 (patch) | |
tree | 0c4a5ade07711e952b54d84f59fa04da527e95d1 | |
parent | 35d53ceaf7160fa1950142757420ba96921034bf (diff) |
toshiba_acpi: Add support to enable/disable USB 3
Toshiba laptops that come with USB 3 ports have a feature that lets
them disable USB 3 functionality and act as a regular USB 2 port, and
thus, saving power.
This patch adds support to that feature, by creating a sysfs entry
named "usb_three", acceptig only two parameters, 0 to disable the
USB 3 (acting as a USB 2) and 1 to enable it, however, a reboot is
needed everytime this is toggled.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 70370d3f5dcf..b162a54f03a7 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -127,6 +127,7 @@ MODULE_LICENSE("GPL"); | |||
127 | #define SCI_USB_SLEEP_CHARGE 0x0150 | 127 | #define SCI_USB_SLEEP_CHARGE 0x0150 |
128 | #define SCI_KBD_ILLUM_STATUS 0x015c | 128 | #define SCI_KBD_ILLUM_STATUS 0x015c |
129 | #define SCI_USB_SLEEP_MUSIC 0x015e | 129 | #define SCI_USB_SLEEP_MUSIC 0x015e |
130 | #define SCI_USB_THREE 0x0169 | ||
130 | #define SCI_TOUCHPAD 0x050e | 131 | #define SCI_TOUCHPAD 0x050e |
131 | #define SCI_KBD_FUNCTION_KEYS 0x0522 | 132 | #define SCI_KBD_FUNCTION_KEYS 0x0522 |
132 | 133 | ||
@@ -197,6 +198,7 @@ struct toshiba_acpi_dev { | |||
197 | unsigned int usb_sleep_music_supported:1; | 198 | unsigned int usb_sleep_music_supported:1; |
198 | unsigned int kbd_function_keys_supported:1; | 199 | unsigned int kbd_function_keys_supported:1; |
199 | unsigned int panel_power_on_supported:1; | 200 | unsigned int panel_power_on_supported:1; |
201 | unsigned int usb_three_supported:1; | ||
200 | unsigned int sysfs_created:1; | 202 | unsigned int sysfs_created:1; |
201 | 203 | ||
202 | struct mutex mutex; | 204 | struct mutex mutex; |
@@ -1095,6 +1097,51 @@ static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state) | |||
1095 | return 0; | 1097 | return 0; |
1096 | } | 1098 | } |
1097 | 1099 | ||
1100 | /* USB Three */ | ||
1101 | static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state) | ||
1102 | { | ||
1103 | u32 result; | ||
1104 | |||
1105 | if (!sci_open(dev)) | ||
1106 | return -EIO; | ||
1107 | |||
1108 | result = sci_read(dev, SCI_USB_THREE, state); | ||
1109 | sci_close(dev); | ||
1110 | if (result == TOS_FAILURE) { | ||
1111 | pr_err("ACPI call to get USB 3 failed\n"); | ||
1112 | return -EIO; | ||
1113 | } else if (result == TOS_NOT_SUPPORTED) { | ||
1114 | pr_info("USB 3 not supported\n"); | ||
1115 | return -ENODEV; | ||
1116 | } else if (result == TOS_INPUT_DATA_ERROR) { | ||
1117 | return -EIO; | ||
1118 | } | ||
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) | ||
1124 | { | ||
1125 | u32 result; | ||
1126 | |||
1127 | if (!sci_open(dev)) | ||
1128 | return -EIO; | ||
1129 | |||
1130 | result = sci_write(dev, SCI_USB_THREE, state); | ||
1131 | sci_close(dev); | ||
1132 | if (result == TOS_FAILURE) { | ||
1133 | pr_err("ACPI call to set USB 3 failed\n"); | ||
1134 | return -EIO; | ||
1135 | } else if (result == TOS_NOT_SUPPORTED) { | ||
1136 | pr_info("USB 3 not supported\n"); | ||
1137 | return -ENODEV; | ||
1138 | } else if (result == TOS_INPUT_DATA_ERROR) { | ||
1139 | return -EIO; | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1098 | /* Bluetooth rfkill handlers */ | 1145 | /* Bluetooth rfkill handlers */ |
1099 | 1146 | ||
1100 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) | 1147 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) |
@@ -1691,6 +1738,12 @@ static ssize_t toshiba_panel_power_on_show(struct device *dev, | |||
1691 | static ssize_t toshiba_panel_power_on_store(struct device *dev, | 1738 | static ssize_t toshiba_panel_power_on_store(struct device *dev, |
1692 | struct device_attribute *attr, | 1739 | struct device_attribute *attr, |
1693 | const char *buf, size_t count); | 1740 | const char *buf, size_t count); |
1741 | static ssize_t toshiba_usb_three_show(struct device *dev, | ||
1742 | struct device_attribute *attr, | ||
1743 | char *buf); | ||
1744 | static ssize_t toshiba_usb_three_store(struct device *dev, | ||
1745 | struct device_attribute *attr, | ||
1746 | const char *buf, size_t count); | ||
1694 | 1747 | ||
1695 | static DEVICE_ATTR(version, S_IRUGO, toshiba_version_show, NULL); | 1748 | static DEVICE_ATTR(version, S_IRUGO, toshiba_version_show, NULL); |
1696 | static DEVICE_ATTR(fan, S_IRUGO | S_IWUSR, | 1749 | static DEVICE_ATTR(fan, S_IRUGO | S_IWUSR, |
@@ -1723,6 +1776,8 @@ static DEVICE_ATTR(kbd_function_keys, S_IRUGO | S_IWUSR, | |||
1723 | static DEVICE_ATTR(panel_power_on, S_IRUGO | S_IWUSR, | 1776 | static DEVICE_ATTR(panel_power_on, S_IRUGO | S_IWUSR, |
1724 | toshiba_panel_power_on_show, | 1777 | toshiba_panel_power_on_show, |
1725 | toshiba_panel_power_on_store); | 1778 | toshiba_panel_power_on_store); |
1779 | static DEVICE_ATTR(usb_three, S_IRUGO | S_IWUSR, | ||
1780 | toshiba_usb_three_show, toshiba_usb_three_store); | ||
1726 | 1781 | ||
1727 | static struct attribute *toshiba_attributes[] = { | 1782 | static struct attribute *toshiba_attributes[] = { |
1728 | &dev_attr_version.attr, | 1783 | &dev_attr_version.attr, |
@@ -1739,6 +1794,7 @@ static struct attribute *toshiba_attributes[] = { | |||
1739 | &dev_attr_usb_sleep_music.attr, | 1794 | &dev_attr_usb_sleep_music.attr, |
1740 | &dev_attr_kbd_function_keys.attr, | 1795 | &dev_attr_kbd_function_keys.attr, |
1741 | &dev_attr_panel_power_on.attr, | 1796 | &dev_attr_panel_power_on.attr, |
1797 | &dev_attr_usb_three.attr, | ||
1742 | NULL, | 1798 | NULL, |
1743 | }; | 1799 | }; |
1744 | 1800 | ||
@@ -2264,6 +2320,48 @@ static ssize_t toshiba_panel_power_on_store(struct device *dev, | |||
2264 | return count; | 2320 | return count; |
2265 | } | 2321 | } |
2266 | 2322 | ||
2323 | static ssize_t toshiba_usb_three_show(struct device *dev, | ||
2324 | struct device_attribute *attr, | ||
2325 | char *buf) | ||
2326 | { | ||
2327 | struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); | ||
2328 | u32 state; | ||
2329 | int ret; | ||
2330 | |||
2331 | ret = toshiba_usb_three_get(toshiba, &state); | ||
2332 | if (ret < 0) | ||
2333 | return ret; | ||
2334 | |||
2335 | return sprintf(buf, "%d\n", state); | ||
2336 | } | ||
2337 | |||
2338 | static ssize_t toshiba_usb_three_store(struct device *dev, | ||
2339 | struct device_attribute *attr, | ||
2340 | const char *buf, size_t count) | ||
2341 | { | ||
2342 | struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); | ||
2343 | int state; | ||
2344 | int ret; | ||
2345 | |||
2346 | ret = kstrtoint(buf, 0, &state); | ||
2347 | if (ret) | ||
2348 | return ret; | ||
2349 | /* Check for USB 3 mode where: | ||
2350 | * 0 - Disabled (Acts like a USB 2 port, saving power) | ||
2351 | * 1 - Enabled | ||
2352 | */ | ||
2353 | if (state != 0 && state != 1) | ||
2354 | return -EINVAL; | ||
2355 | |||
2356 | ret = toshiba_usb_three_set(toshiba, state); | ||
2357 | if (ret) | ||
2358 | return ret; | ||
2359 | |||
2360 | pr_info("Reboot for changes to USB 3 to take effect"); | ||
2361 | |||
2362 | return count; | ||
2363 | } | ||
2364 | |||
2267 | static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, | 2365 | static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, |
2268 | struct attribute *attr, int idx) | 2366 | struct attribute *attr, int idx) |
2269 | { | 2367 | { |
@@ -2293,6 +2391,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, | |||
2293 | exists = (drv->kbd_function_keys_supported) ? true : false; | 2391 | exists = (drv->kbd_function_keys_supported) ? true : false; |
2294 | else if (attr == &dev_attr_panel_power_on.attr) | 2392 | else if (attr == &dev_attr_panel_power_on.attr) |
2295 | exists = (drv->panel_power_on_supported) ? true : false; | 2393 | exists = (drv->panel_power_on_supported) ? true : false; |
2394 | else if (attr == &dev_attr_usb_three.attr) | ||
2395 | exists = (drv->usb_three_supported) ? true : false; | ||
2296 | 2396 | ||
2297 | return exists ? attr->mode : 0; | 2397 | return exists ? attr->mode : 0; |
2298 | } | 2398 | } |
@@ -2717,6 +2817,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
2717 | ret = toshiba_panel_power_on_get(dev, &dummy); | 2817 | ret = toshiba_panel_power_on_get(dev, &dummy); |
2718 | dev->panel_power_on_supported = !ret; | 2818 | dev->panel_power_on_supported = !ret; |
2719 | 2819 | ||
2820 | ret = toshiba_usb_three_get(dev, &dummy); | ||
2821 | dev->usb_three_supported = !ret; | ||
2822 | |||
2720 | /* Determine whether or not BIOS supports fan and video interfaces */ | 2823 | /* Determine whether or not BIOS supports fan and video interfaces */ |
2721 | 2824 | ||
2722 | ret = get_video_status(dev, &dummy); | 2825 | ret = get_video_status(dev, &dummy); |