From ad96973589d8929f02e4cc0c170f1f4162ad6436 Mon Sep 17 00:00:00 2001 From: Albert Wang Date: Fri, 2 Jul 2021 21:06:34 +0800 Subject: [PATCH] usb: new attributes implementation to enable/disable usb data Bug: 188760285 Test: driver probe and attributes access normally Signed-off-by: Albert Wang Change-Id: I0aec98eebff9454cdec065bb09825f6442ac013b --- Documentation/ABI/testing/sysfs-class-udc | 16 +++++++++ drivers/usb/dwc3/dwc3-msm.c | 41 +++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-udc diff --git a/Documentation/ABI/testing/sysfs-class-udc b/Documentation/ABI/testing/sysfs-class-udc new file mode 100644 index 000000000000..750128896b38 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-udc @@ -0,0 +1,16 @@ +What: /sys/class/udc//device/usb_data_enabled +Date: December 2020 +Contact: "Ray Chi" +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 c3049360cc7b..52be2bd26d52 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -360,6 +360,7 @@ struct dwc3_msm { u64 dummy_gsi_db; dma_addr_t dummy_gsi_db_dma; int orientation_override; + bool usb_data_enabled; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -3294,6 +3295,9 @@ static int dwc3_msm_id_notifier(struct notifier_block *nb, if (!edev || !mdwc) return NOTIFY_DONE; + if (!mdwc->usb_data_enabled) + return NOTIFY_DONE; + dwc = platform_get_drvdata(mdwc->dwc3); dbg_event(0xFF, "extcon idx", enb->idx); @@ -3355,6 +3359,9 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, if (!edev || !mdwc) return NOTIFY_DONE; + if (!mdwc->usb_data_enabled) + return NOTIFY_DONE; + dwc = platform_get_drvdata(mdwc->dwc3); dbg_event(0xFF, "extcon idx", enb->idx); @@ -3686,6 +3693,35 @@ static int dwc_dpdm_cb(struct notifier_block *nb, unsigned long evt, void *p) return NOTIFY_OK; } + +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; @@ -4058,11 +4094,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) dwc3_ext_event_notify(mdwc); } + /* set the initial value */ + mdwc->usb_data_enabled = true; device_create_file(&pdev->dev, &dev_attr_orientation); device_create_file(&pdev->dev, &dev_attr_mode); device_create_file(&pdev->dev, &dev_attr_speed); device_create_file(&pdev->dev, &dev_attr_usb_compliance_mode); device_create_file(&pdev->dev, &dev_attr_bus_vote); + device_create_file(&pdev->dev, &dev_attr_usb_data_enabled); return 0; @@ -4091,6 +4130,8 @@ static int dwc3_msm_remove(struct platform_device *pdev) mdwc->dpdm_nb.notifier_call = NULL; } + device_remove_file(&pdev->dev, &dev_attr_usb_data_enabled); + if (mdwc->usb_psy) power_supply_put(mdwc->usb_psy);