aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAzael Avalos <coproscefalo@gmail.com>2015-01-18 20:30:22 -0500
committerDarren Hart <dvhart@linux.intel.com>2015-01-23 12:08:19 -0500
commite26ffe5124189bce99235fee403a71b719e10b6a (patch)
tree7ef24f70c7e751b725b2fa69320066ad7f8f7a7b /drivers/platform
parent97bf6af1f928216fd6c5a66e8a57bfa95a659672 (diff)
toshiba_acpi: Add support for USB Sleep and Charge function
Newer Toshiba models now come with a feature called Sleep and Charge, where the computer USB ports remain powered when the computer is asleep or turned off. This patch adds support to such feature, creating a sysfs entry called "usb_sleep_charge" to set the desired charging mode or to disable it. The sysfs entry accepts three parameters, 0, 1 and 2, beign disabled, alternate and auto respectively. The auto mode stands for USB conformant devices (which most are), and the alternate mode stands for those non USB conformant devices that require more power. Signed-off-by: Azael Avalos <coproscefalo@gmail.com> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index fc34a71866ed..6c3e25c65b70 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -122,6 +122,7 @@ MODULE_LICENSE("GPL");
122#define HCI_ECO_MODE 0x0097 122#define HCI_ECO_MODE 0x0097
123#define HCI_ACCELEROMETER2 0x00a6 123#define HCI_ACCELEROMETER2 0x00a6
124#define SCI_ILLUMINATION 0x014e 124#define SCI_ILLUMINATION 0x014e
125#define SCI_USB_SLEEP_CHARGE 0x0150
125#define SCI_KBD_ILLUM_STATUS 0x015c 126#define SCI_KBD_ILLUM_STATUS 0x015c
126#define SCI_TOUCHPAD 0x050e 127#define SCI_TOUCHPAD 0x050e
127 128
@@ -146,6 +147,10 @@ MODULE_LICENSE("GPL");
146#define SCI_KBD_MODE_ON 0x8 147#define SCI_KBD_MODE_ON 0x8
147#define SCI_KBD_MODE_OFF 0x10 148#define SCI_KBD_MODE_OFF 0x10
148#define SCI_KBD_TIME_MAX 0x3c001a 149#define SCI_KBD_TIME_MAX 0x3c001a
150#define SCI_USB_CHARGE_MODE_MASK 0xff
151#define SCI_USB_CHARGE_DISABLED 0x30000
152#define SCI_USB_CHARGE_ALTERNATE 0x30009
153#define SCI_USB_CHARGE_AUTO 0x30021
149 154
150struct toshiba_acpi_dev { 155struct toshiba_acpi_dev {
151 struct acpi_device *acpi_dev; 156 struct acpi_device *acpi_dev;
@@ -177,6 +182,7 @@ struct toshiba_acpi_dev {
177 unsigned int touchpad_supported:1; 182 unsigned int touchpad_supported:1;
178 unsigned int eco_supported:1; 183 unsigned int eco_supported:1;
179 unsigned int accelerometer_supported:1; 184 unsigned int accelerometer_supported:1;
185 unsigned int usb_sleep_charge_supported:1;
180 unsigned int sysfs_created:1; 186 unsigned int sysfs_created:1;
181 187
182 struct mutex mutex; 188 struct mutex mutex;
@@ -760,6 +766,53 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
760 return 0; 766 return 0;
761} 767}
762 768
769/* Sleep (Charge and Music) utilities support */
770static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev,
771 u32 *mode)
772{
773 u32 result;
774
775 if (!sci_open(dev))
776 return -EIO;
777
778 result = sci_read(dev, SCI_USB_SLEEP_CHARGE, mode);
779 sci_close(dev);
780 if (result == TOS_FAILURE) {
781 pr_err("ACPI call to set USB S&C mode failed\n");
782 return -EIO;
783 } else if (result == TOS_NOT_SUPPORTED) {
784 pr_info("USB Sleep and Charge not supported\n");
785 return -ENODEV;
786 } else if (result == TOS_INPUT_DATA_ERROR) {
787 return -EIO;
788 }
789
790 return 0;
791}
792
793static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev,
794 u32 mode)
795{
796 u32 result;
797
798 if (!sci_open(dev))
799 return -EIO;
800
801 result = sci_write(dev, SCI_USB_SLEEP_CHARGE, mode);
802 sci_close(dev);
803 if (result == TOS_FAILURE) {
804 pr_err("ACPI call to set USB S&C mode failed\n");
805 return -EIO;
806 } else if (result == TOS_NOT_SUPPORTED) {
807 pr_info("USB Sleep and Charge not supported\n");
808 return -ENODEV;
809 } else if (result == TOS_INPUT_DATA_ERROR) {
810 return -EIO;
811 }
812
813 return 0;
814}
815
763/* Bluetooth rfkill handlers */ 816/* Bluetooth rfkill handlers */
764 817
765static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) 818static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1313,6 +1366,12 @@ static ssize_t toshiba_touchpad_show(struct device *dev,
1313static ssize_t toshiba_position_show(struct device *dev, 1366static ssize_t toshiba_position_show(struct device *dev,
1314 struct device_attribute *attr, 1367 struct device_attribute *attr,
1315 char *buf); 1368 char *buf);
1369static ssize_t toshiba_usb_sleep_charge_show(struct device *dev,
1370 struct device_attribute *attr,
1371 char *buf);
1372static ssize_t toshiba_usb_sleep_charge_store(struct device *dev,
1373 struct device_attribute *attr,
1374 const char *buf, size_t count);
1316 1375
1317static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR, 1376static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
1318 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store); 1377 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
@@ -1324,6 +1383,9 @@ static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
1324static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR, 1383static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR,
1325 toshiba_touchpad_show, toshiba_touchpad_store); 1384 toshiba_touchpad_show, toshiba_touchpad_store);
1326static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL); 1385static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
1386static DEVICE_ATTR(usb_sleep_charge, S_IRUGO | S_IWUSR,
1387 toshiba_usb_sleep_charge_show,
1388 toshiba_usb_sleep_charge_store);
1327 1389
1328static struct attribute *toshiba_attributes[] = { 1390static struct attribute *toshiba_attributes[] = {
1329 &dev_attr_kbd_backlight_mode.attr, 1391 &dev_attr_kbd_backlight_mode.attr,
@@ -1332,6 +1394,7 @@ static struct attribute *toshiba_attributes[] = {
1332 &dev_attr_kbd_backlight_timeout.attr, 1394 &dev_attr_kbd_backlight_timeout.attr,
1333 &dev_attr_touchpad.attr, 1395 &dev_attr_touchpad.attr,
1334 &dev_attr_position.attr, 1396 &dev_attr_position.attr,
1397 &dev_attr_usb_sleep_charge.attr,
1335 NULL, 1398 NULL,
1336}; 1399};
1337 1400
@@ -1549,6 +1612,56 @@ static ssize_t toshiba_position_show(struct device *dev,
1549 return sprintf(buf, "%d %d %d\n", x, y, z); 1612 return sprintf(buf, "%d %d %d\n", x, y, z);
1550} 1613}
1551 1614
1615static ssize_t toshiba_usb_sleep_charge_show(struct device *dev,
1616 struct device_attribute *attr,
1617 char *buf)
1618{
1619 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1620 u32 mode;
1621 int ret;
1622
1623 ret = toshiba_usb_sleep_charge_get(toshiba, &mode);
1624 if (ret < 0)
1625 return ret;
1626
1627 return sprintf(buf, "%x\n", mode & SCI_USB_CHARGE_MODE_MASK);
1628}
1629
1630static ssize_t toshiba_usb_sleep_charge_store(struct device *dev,
1631 struct device_attribute *attr,
1632 const char *buf, size_t count)
1633{
1634 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1635 u32 mode;
1636 int state;
1637 int ret;
1638
1639 ret = kstrtoint(buf, 0, &state);
1640 if (ret)
1641 return ret;
1642 /* Check for supported values, where:
1643 * 0 - Disabled
1644 * 1 - Alternate (Non USB conformant devices that require more power)
1645 * 2 - Auto (USB conformant devices)
1646 */
1647 if (state != 0 && state != 1 && state != 2)
1648 return -EINVAL;
1649
1650 /* Set the USB charging mode to internal value */
1651 if (state == 0)
1652 mode = SCI_USB_CHARGE_DISABLED;
1653 else if (state == 1)
1654 mode = SCI_USB_CHARGE_ALTERNATE;
1655 else if (state == 2)
1656 mode = SCI_USB_CHARGE_AUTO;
1657
1658 ret = toshiba_usb_sleep_charge_set(toshiba, mode);
1659 if (ret)
1660 return ret;
1661
1662 return count;
1663}
1664
1552static umode_t toshiba_sysfs_is_visible(struct kobject *kobj, 1665static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1553 struct attribute *attr, int idx) 1666 struct attribute *attr, int idx)
1554{ 1667{
@@ -1564,6 +1677,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1564 exists = (drv->touchpad_supported) ? true : false; 1677 exists = (drv->touchpad_supported) ? true : false;
1565 else if (attr == &dev_attr_position.attr) 1678 else if (attr == &dev_attr_position.attr)
1566 exists = (drv->accelerometer_supported) ? true : false; 1679 exists = (drv->accelerometer_supported) ? true : false;
1680 else if (attr == &dev_attr_usb_sleep_charge.attr)
1681 exists = (drv->usb_sleep_charge_supported) ? true : false;
1567 1682
1568 return exists ? attr->mode : 0; 1683 return exists ? attr->mode : 0;
1569} 1684}
@@ -1973,6 +2088,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
1973 ret = toshiba_accelerometer_supported(dev); 2088 ret = toshiba_accelerometer_supported(dev);
1974 dev->accelerometer_supported = !ret; 2089 dev->accelerometer_supported = !ret;
1975 2090
2091 ret = toshiba_usb_sleep_charge_get(dev, &dummy);
2092 dev->usb_sleep_charge_supported = !ret;
2093
1976 /* Determine whether or not BIOS supports fan and video interfaces */ 2094 /* Determine whether or not BIOS supports fan and video interfaces */
1977 2095
1978 ret = get_video_status(dev, &dummy); 2096 ret = get_video_status(dev, &dummy);