dwc3-msm: Add dwc3_msm_release_ss_lane() API

DP driver needs to use both USB SS lane in some use case. Hence
to release USB SS lane, add dwc3_msm_release_ss_lane() API which
performs below operations:
i. Stop USB host mode
ii. Start USB host mode into high speed mode if USB host mode
was active.

dwc3_msm_release_ss_lane() API is blocking call, and will comeback
once above both operations are performed.

Change-Id: I56df606914a613bfe4b76298b0041a66fc74878d
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
Mayank Rana 2020-01-16 10:20:04 -08:00 • committed by Gerrit - the friendly Code Review server
commit 0ed723e6bb
2 changed files with 63 additions and 1 deletions

View file

@ -150,6 +150,9 @@
#define DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX(n) (n << 16)
#define DWC3_GEVENT_TYPE_GSI 0x3
/* BAM pipe mask */
#define MSM_PIPE_ID_MASK (0x1F)
enum dbm_reg {
DBM_EP_CFG,
DBM_DATA_FIFO,
@ -3738,6 +3741,63 @@ static void dwc3_init_dbm(struct dwc3_msm *mdwc)
"qcom,reset-ep-after-lpm-resume");
}
static void dwc3_start_stop_host(struct dwc3_msm *mdwc, bool start)
{
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
if (start) {
dbg_log_string("start host mode");
mdwc->id_state = DWC3_ID_GROUND;
mdwc->vbus_active = false;
} else {
dbg_log_string("stop_host_mode started");
mdwc->id_state = DWC3_ID_FLOAT;
mdwc->vbus_active = false;
}
dwc3_ext_event_notify(mdwc);
dbg_event(0xFF, "flush_work", 0);
flush_work(&mdwc->resume_work);
drain_workqueue(mdwc->sm_usb_wq);
if (start)
dbg_log_string("host mode started");
else
dbg_log_string("stop_host_mode completed");
}
int dwc3_msm_release_ss_lane(struct device *dev)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dev);
struct dwc3 *dwc = NULL;
if (mdwc == NULL) {
dev_err(dev, "dwc3-msm is not initialized yet.\n");
return -EAGAIN;
}
dwc = platform_get_drvdata(mdwc->dwc3);
if (dwc == NULL) {
dev_err(dev, "dwc3 controller is not initialized yet.\n");
return -EAGAIN;
}
dbg_event(0xFF, "ss_lane_release", 0);
if (mdwc->id_state != DWC3_ID_GROUND) {
dbg_log_string("USB host mode is not active");
return 0;
}
/* stop USB host mode */
dwc3_start_stop_host(mdwc, false);
/* restart USB host mode into high speed */
dwc->maximum_speed = USB_SPEED_HIGH;
dwc3_start_stop_host(mdwc, true);
return 0;
}
EXPORT_SYMBOL(dwc3_msm_release_ss_lane);
static int dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node, *dwc3_node;

View file

@ -22,7 +22,6 @@
* These bit fields are set by function drivers that wish to queue
* usb_requests with sps/bam parameters.
*/
#define MSM_PIPE_ID_MASK (0x1F)
#define MSM_TX_PIPE_ID_OFS (16)
#define MSM_SPS_MODE BIT(5)
#define MSM_IS_FINITE_TRANSFER BIT(6)
@ -121,6 +120,7 @@ int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
u8 dst_pipe_idx);
bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget);
int msm_dwc3_reset_dbm_ep(struct usb_ep *ep);
int dwc3_msm_release_ss_lane(struct device *dev);
#else
static inline struct usb_ep *usb_ep_autoconfig_by_name(
struct usb_gadget *gadget, struct usb_endpoint_descriptor *desc,
@ -146,6 +146,8 @@ static inline bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget)
{ return false; }
static inline int msm_dwc3_reset_dbm_ep(struct usb_ep *ep)
{ return -ENODEV; }
static inline int dwc3_msm_release_ss_lane(struct device *dev)
{ return -ENODEV; }
#endif
#endif /* __LINUX_USB_DWC3_MSM_H */