summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Wang <albertccwang@google.com>2021-03-18 18:13:03 +0800
committerMichael Bestas <mkbestas@lineageos.org>2024-03-21 17:43:49 +0200
commite08bc0c0312b3e91fe5b752768608e4a209182f6 (patch)
tree73507fb9cb4b045304161d4bf5eb4c5b01891178
parent069ac1bc7175e12f6d2d9f92be4687146918da86 (diff)
usb: new attributes implementation to enable/disable usb data
Bug: 184613044 Test: driver probe and attributes access normally Signed-off-by: Albert Wang <albertccwang@google.com> Change-Id: Ia34cfd8e76a21f7239e356608e46ddeebd6fa10a
-rw-r--r--Documentation/ABI/testing/sysfs-class-udc16
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c39
2 files changed, 54 insertions, 1 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-udc b/Documentation/ABI/testing/sysfs-class-udc
new file mode 100644
index 000000000000..1b9c566d0552
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-udc
@@ -0,0 +1,16 @@
+What: /sys/class/udc/<udc name>/device/usb_data_enabled
+Date: December 2020
+Contact: "Ray Chi" <raychi@google.com>
+Description:
+ The attribute can allow user space can check and modify
+ the value to enable or disable usb functionality. Therefore,
+ if the attritube is set to 0, USB host and USB peripheral
+ modes wouldn't be working.
+
+ Example:
+ Enable USB data functionality
+ # echo 1 > /sys/class/udc/.../device/usb_data_enabled
+
+ Disable USB data functionality
+ # echo 0 > /sys/class/udc/.../device/usb_data_enabled
+
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index b6b25c75b80c..561b109c3442 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -278,6 +278,7 @@ struct dwc3_msm {
enum usb_device_speed override_usb_speed;
bool core_init_failed;
+ bool usb_data_enabled;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -2692,6 +2693,9 @@ static int dwc3_msm_id_notifier(struct notifier_block *nb,
goto done;
}
+ if (!mdwc->usb_data_enabled)
+ return NOTIFY_DONE;
+
id = event ? DWC3_ID_GROUND : DWC3_ID_FLOAT;
dev_dbg(mdwc->dev, "host:%ld (id:%d) event received\n", event, id);
@@ -2769,6 +2773,9 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
goto done;
}
+ if (!mdwc->usb_data_enabled)
+ return NOTIFY_DONE;
+
dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);
if (mdwc->vbus_active == event)
@@ -2977,7 +2984,6 @@ static ssize_t xhci_link_compliance_store(struct device *dev,
return ret;
}
-
static DEVICE_ATTR_RW(xhci_link_compliance);
static ssize_t usb_compliance_mode_show(struct device *dev,
@@ -3004,6 +3010,33 @@ static ssize_t usb_compliance_mode_store(struct device *dev,
}
static DEVICE_ATTR_RW(usb_compliance_mode);
+static ssize_t usb_data_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%s\n",
+ mdwc->usb_data_enabled ? "enabled" : "disabled");
+}
+
+static ssize_t usb_data_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (kstrtobool(buf, &mdwc->usb_data_enabled))
+ return -EINVAL;
+
+ if (!mdwc->usb_data_enabled) {
+ mdwc->vbus_active = false;
+ mdwc->id_state = DWC3_ID_FLOAT;
+ dwc3_ext_event_notify(mdwc);
+ }
+
+ return count;
+}
+static DEVICE_ATTR_RW(usb_data_enabled);
+
static int dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node, *dwc3_node;
@@ -3361,10 +3394,13 @@ static int dwc3_msm_probe(struct platform_device *pdev)
dev_info(mdwc->dev, "charger detection in progress\n");
}
+ /* set the initial value */
+ mdwc->usb_data_enabled = true;
device_create_file(&pdev->dev, &dev_attr_mode);
device_create_file(&pdev->dev, &dev_attr_speed);
device_create_file(&pdev->dev, &dev_attr_xhci_link_compliance);
device_create_file(&pdev->dev, &dev_attr_usb_compliance_mode);
+ device_create_file(&pdev->dev, &dev_attr_usb_data_enabled);
host_mode = usb_get_dr_mode(&mdwc->dwc3->dev) == USB_DR_MODE_HOST;
if (host_mode ||
@@ -3400,6 +3436,7 @@ static int dwc3_msm_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_mode);
device_remove_file(&pdev->dev, &dev_attr_xhci_link_compliance);
+ device_create_file(&pdev->dev, &dev_attr_usb_data_enabled);
if (cpu_to_affin)
unregister_cpu_notifier(&mdwc->dwc3_cpu_notifier);