usb: dwc3-msm: Add sysfs node to enable SS host compliance

xHCI specs revision 1.1 mentions that if Compliance Transition
Capability (CTC) flag is set, then xHC supports software control
of the transition to Compliance mode. For this, we need to write
a value of 10 to Port Link State(PLS) field of PORTSC register
during dwc3_otg_start_host time after the xhci platform device
has been added. Then the link transitions to compliance state
on detection of first LFPS timeout.

Steps to enable compliance transition:
  1. Do not connect host cable
  2. echo y > /sys/devices/soc/a800000.ssusb/xhci_link_compliance
  3. Connect host cable with breakout fixture and start testing

Steps to disable compliance transition:
  1. Disconnect the host cable
  2. echo n > /sys/devices/soc/a800000.ssusb/xhci_link_compliance
  3. Connect host cable

Change-Id: I73225ccad105414d3ebd60f95138b9ecf65005d4
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
This commit is contained in:
Ajay Agarwal 2017-06-30 23:22:18 +05:30
parent d9fbe4b921
commit 6787d25926

View file

@ -70,6 +70,8 @@ MODULE_PARM_DESC(cpu_to_affin, "affin usb irq to this cpu");
/* XHCI registers */
#define USB3_HCSPARAMS1 (0x4)
#define USB3_HCCPARAMS2 (0x1c)
#define HCC_CTC(p) ((p) & (1 << 3))
#define USB3_PORTSC (0x420)
/**
@ -211,6 +213,7 @@ struct dwc3_msm {
struct notifier_block dwc3_cpu_notifier;
struct notifier_block usbdev_nb;
bool hc_died;
bool xhci_ss_compliance_enable;
struct extcon_dev *extcon_vbus;
struct extcon_dev *extcon_id;
@ -2796,6 +2799,34 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(speed);
static void msm_dwc3_perf_vote_work(struct work_struct *w);
static ssize_t xhci_link_compliance_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dev);
if (mdwc->xhci_ss_compliance_enable)
return snprintf(buf, PAGE_SIZE, "y\n");
else
return snprintf(buf, PAGE_SIZE, "n\n");
}
static ssize_t xhci_link_compliance_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dev);
bool value;
int ret;
ret = strtobool(buf, &value);
if (!ret) {
mdwc->xhci_ss_compliance_enable = value;
return count;
}
return ret;
}
static DEVICE_ATTR_RW(xhci_link_compliance);
static int dwc3_msm_probe(struct platform_device *pdev)
{
@ -3139,6 +3170,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
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);
host_mode = usb_get_dr_mode(&mdwc->dwc3->dev) == USB_DR_MODE_HOST;
if (host_mode ||
@ -3170,6 +3202,7 @@ static int dwc3_msm_remove(struct platform_device *pdev)
int ret_pm;
device_remove_file(&pdev->dev, &dev_attr_mode);
device_remove_file(&pdev->dev, &dev_attr_xhci_link_compliance);
if (cpu_to_affin)
unregister_cpu_notifier(&mdwc->dwc3_cpu_notifier);
@ -3433,6 +3466,25 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
return ret;
}
/*
* If the Compliance Transition Capability(CTC) flag of
* HCCPARAMS2 register is set and xhci_link_compliance sysfs
* param has been enabled by the user for the SuperSpeed host
* controller, then write 10 (Link in Compliance Mode State)
* onto the Port Link State(PLS) field of the PORTSC register
* for 3.0 host controller which is at an offset of USB3_PORTSC
* + 0x10 from the DWC3 base address. Also, disable the runtime
* PM of 3.0 root hub (root hub of shared_hcd of xhci device)
*/
if (HCC_CTC(dwc3_msm_read_reg(mdwc->base, USB3_HCCPARAMS2))
&& mdwc->xhci_ss_compliance_enable
&& dwc->maximum_speed == USB_SPEED_SUPER) {
dwc3_msm_write_reg(mdwc->base, USB3_PORTSC + 0x10,
0x10340);
pm_runtime_disable(&hcd_to_xhci(platform_get_drvdata(
dwc->xhci))->shared_hcd->self.root_hub->dev);
}
/*
* In some cases it is observed that USB PHY is not going into
* suspend with host mode suspend functionality. Hence disable