Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cc26228 authored by Chandana Kishori Chiluveru's avatar Chandana Kishori Chiluveru Committed by Gerrit - the friendly Code Review server
Browse files

usb: dwc3-msm: Add support to change USB modes using sysfs



Driver supports DRD mode and mode is changed based on
usb power_supply notification for ID and BSV changes.
This works fine for primary USB port as only one instance
of psy can exist. For other USB ports allow user to change
change modes using sysfs attribute 'mode'. This requires
user to pass qcom,psy-not-used DT attribute to handle
probe error due to duplicate registration of usb_psy.

Example commands to change the mode:
echo peripheral > /sys/devices/soc/6a00000.ssusb/mode (Device)
echo host > /sys/devices/soc/6a00000.ssusb/mode (Host)
echo none > /sys/devices/soc/6a00000.ssusb/mode (Disconnect)

Change-Id: I69b4c822d194cdd93cb77dbbf79e420bdee597d7
Signed-off-by: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent a780366c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ Optional properties :
- qcom,no-wakeup-src-in-hostmode: If present then driver doesn't use wakeup_source APIs e.g.
  pm_stay_awake and pm_relax in host mode. This allows PM suspend to happen irrespective of
  runtimePM state of host.
- qcom,psy-not-used: If present then driver won't be registering usb power_supply.
  Without usb_psy, user should be able to change modes using sysfs.

Sub nodes:
- Sub node for "DWC3- USB3 controller".
+47 −1
Original line number Diff line number Diff line
@@ -257,6 +257,7 @@ struct dwc3_msm {
	bool			stop_host;
	bool			no_wakeup_src_in_hostmode;
	bool			host_only_mode;
	bool			psy_not_used;

	int  pwr_event_irq;
	atomic_t                in_p3;
@@ -2798,6 +2799,43 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
	return 0;
}

static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
		char *buf)
{
	struct dwc3_msm *mdwc = dev_get_drvdata(dev);

	if (mdwc->vbus_active)
		return snprintf(buf, PAGE_SIZE, "peripheral\n");
	if (mdwc->id_state == DWC3_ID_GROUND)
		return snprintf(buf, PAGE_SIZE, "host\n");

	return snprintf(buf, PAGE_SIZE, "none\n");
}

static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct dwc3_msm *mdwc = dev_get_drvdata(dev);

	if (sysfs_streq(buf, "peripheral")) {
		mdwc->vbus_active = true;
		mdwc->id_state = DWC3_ID_FLOAT;
		mdwc->chg_type = DWC3_SDP_CHARGER;
	} else if (sysfs_streq(buf, "host")) {
		mdwc->vbus_active = false;
		mdwc->id_state = DWC3_ID_GROUND;
	} else {
		mdwc->vbus_active = false;
		mdwc->id_state = DWC3_ID_FLOAT;
	}

	dwc3_ext_event_notify(mdwc);

	return count;
}

static DEVICE_ATTR_RW(mode);

static int dwc3_msm_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node, *dwc3_node;
@@ -3072,6 +3110,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
	if (mdwc->no_wakeup_src_in_hostmode)
		dev_dbg(&pdev->dev, "dwc3 host not using wakeup source\n");

	mdwc->psy_not_used = of_property_read_bool(node, "qcom,psy-not-used");

	mdwc->detect_dpdm_floating = of_property_read_bool(node,
				"qcom,detect-dpdm-floating");

@@ -3087,7 +3127,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)

	host_mode = of_usb_get_dr_mode(dwc3_node) == USB_DR_MODE_HOST;
	/* usb_psy required only for vbus_notifications */
	if (!host_mode) {
	if (!host_mode && !mdwc->psy_not_used) {
		mdwc->usb_psy.name = "usb";
		mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
		mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
@@ -3181,6 +3221,9 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		enable_irq_wake(mdwc->pmic_id_irq);
	}

	if (dwc->is_drd)
		device_create_file(&pdev->dev, &dev_attr_mode);

	if (!dwc->is_drd && host_mode) {
		dev_dbg(&pdev->dev, "DWC3 in host only mode\n");
		mdwc->host_only_mode = true;
@@ -3213,6 +3256,9 @@ static int dwc3_msm_remove(struct platform_device *pdev)
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
	int ret_pm;

	if (dwc->is_drd)
		device_remove_file(&pdev->dev, &dev_attr_mode);

	if (cpu_to_affin)
		unregister_cpu_notifier(&mdwc->dwc3_cpu_notifier);