USB: dwc3-msm: Initialize DBM ep before BAM pipe reset

On new platforms, endpoint clock gating is added for dbm endpoints
with Synopsys USB3.0 controller. This hardware feature requires
initialization of DBM endpoint before BAM pipe reset for bam2bam mode
data transfers working. Hence change sequence such that do DBM endpoint
initialization first followed by BAM pipe reset and do start transfer
as last operation.

CRs-Fixed: 965207
Change-Id: Ib5bfd1a7d258fe336a4c9924850fc9223c1c81f6
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
This commit is contained in:
Vijayavardhan Vennapusa 2016-02-03 19:22:23 +05:30 committed by Chandana Kishori Chiluveru
parent a80e267a8c
commit 58c91d96b2
6 changed files with 39 additions and 52 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -312,9 +312,6 @@ int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe, bool producer,
return -ENODEV;
}
/* First, reset the dbm endpoint */
ep_soft_reset(dbm, dbm_ep, 0);
/* Set ioc bit for dbm_ep if needed */
msm_dbm_write_reg_field(dbm, DBM_DBG_CNFG,
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
@ -391,23 +388,10 @@ int dbm_ep_unconfig(struct dbm *dbm, u8 usb_ep)
data &= (~0x1);
msm_dbm_write_ep_reg(dbm, DBM_EP_CFG, dbm_ep, data);
/* Reset the dbm endpoint */
ep_soft_reset(dbm, dbm_ep, true);
/*
* The necessary delay between asserting and deasserting the dbm ep
* reset is based on the number of active endpoints. If there is more
* than one endpoint, a 1 msec delay is required. Otherwise, a shorter
* delay will suffice.
*
* As this function can be called in atomic context, sleeping variants
* for delay are not possible - albeit a 1ms delay.
* ep_soft_reset is not required during disconnect as pipe reset on
* next connect will take care of the same.
*/
if (dbm_get_num_of_eps_configured(dbm) > 1)
udelay(1000);
else
udelay(10);
ep_soft_reset(dbm, dbm_ep, false);
return 0;
}

View file

@ -622,11 +622,6 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
struct dwc3_msm_req_complete *req_complete;
unsigned long flags;
int ret = 0, size;
u8 bam_pipe;
bool producer;
bool disable_wb;
bool internal_mem;
bool ioc;
bool superspeed;
if (!(request->udc_priv & MSM_SPS_MODE)) {
@ -659,23 +654,6 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
request->complete = dwc3_msm_req_complete_func;
/*
* Configure the DBM endpoint
*/
bam_pipe = request->udc_priv & MSM_PIPE_ID_MASK;
producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
ret = dbm_ep_config(mdwc->dbm, dep->number, bam_pipe, producer,
disable_wb, internal_mem, ioc);
if (ret < 0) {
dev_err(mdwc->dev,
"error %d after calling dbm_ep_config\n", ret);
return ret;
}
dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
__func__, request, ep->name, request->length);
size = dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0));
@ -1346,12 +1324,19 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
*
* @return int - 0 on success, negetive on error.
*/
int msm_ep_config(struct usb_ep *ep)
int msm_ep_config(struct usb_ep *ep, struct usb_request *request,
gfp_t gfp_flags)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *new_ep_ops;
int ret = 0;
u8 bam_pipe;
bool producer;
bool disable_wb;
bool internal_mem;
bool ioc;
/* Save original ep ops for future restore*/
@ -1364,7 +1349,7 @@ int msm_ep_config(struct usb_ep *ep)
mdwc->original_ep_ops[dep->number] = ep->ops;
/* Set new usb ops as we like */
new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_ATOMIC);
new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), gfp_flags);
if (!new_ep_ops) {
dev_err(mdwc->dev,
"%s: unable to allocate mem for new usb ep ops\n",
@ -1376,10 +1361,25 @@ int msm_ep_config(struct usb_ep *ep)
new_ep_ops->gsi_ep_op = dwc3_msm_gsi_ep_op;
ep->ops = new_ep_ops;
if (!mdwc->dbm || !request || (dep->endpoint.ep_type == EP_TYPE_GSI))
return 0;
/*
* Do HERE more usb endpoint configurations
* which are specific to MSM.
* Configure the DBM endpoint if required.
*/
bam_pipe = request->udc_priv & MSM_PIPE_ID_MASK;
producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
ret = dbm_ep_config(mdwc->dbm, dep->number, bam_pipe, producer,
disable_wb, internal_mem, ioc);
if (ret < 0) {
dev_err(mdwc->dev,
"error %d after calling dbm_ep_config\n", ret);
return ret;
}
return 0;
}

View file

@ -2245,7 +2245,7 @@ skip_string_id_alloc:
if (!ep)
goto fail;
gsi->d_port.in_ep = ep;
msm_ep_config(gsi->d_port.in_ep);
msm_ep_config(gsi->d_port.in_ep, NULL, GFP_KERNEL);
ep->driver_data = cdev; /* claim */
}
@ -2255,7 +2255,7 @@ skip_string_id_alloc:
if (!ep)
goto fail;
gsi->d_port.out_ep = ep;
msm_ep_config(gsi->d_port.out_ep);
msm_ep_config(gsi->d_port.out_ep, NULL, GFP_KERNEL);
ep->driver_data = cdev; /* claim */
}

View file

@ -457,7 +457,7 @@ static void ipa_data_connect_work(struct work_struct *w)
configure_fifo(port->usb_bam_type,
port->src_connection_idx,
port->port_usb->out);
ret = msm_ep_config(gport->out);
ret = msm_ep_config(gport->out, port->rx_req, GFP_ATOMIC);
if (ret) {
pr_err("msm_ep_config() failed for OUT EP\n");
usb_bam_free_fifos(port->usb_bam_type,
@ -475,7 +475,7 @@ static void ipa_data_connect_work(struct work_struct *w)
port->tx_req->udc_priv = sps_params;
configure_fifo(port->usb_bam_type,
port->dst_connection_idx, gport->in);
ret = msm_ep_config(gport->in);
ret = msm_ep_config(gport->in, port->tx_req, GFP_ATOMIC);
if (ret) {
pr_err("msm_ep_config() failed for IN EP\n");
goto unconfig_msm_ep_out;

View file

@ -94,11 +94,12 @@ int set_qdss_data_connection(struct usb_gadget *gadget,
static int init_data(struct usb_ep *ep)
{
struct f_qdss *qdss = ep->driver_data;
int res = 0;
pr_debug("init_data\n");
res = msm_ep_config(ep);
res = msm_ep_config(ep, qdss->endless_req, GFP_ATOMIC);
if (res)
pr_err("msm_ep_config failed\n");

View file

@ -296,7 +296,8 @@ static inline void msm_usb_irq_disable(bool disable)
#endif
#ifdef CONFIG_USB_DWC3_QCOM
int msm_ep_config(struct usb_ep *ep);
int msm_ep_config(struct usb_ep *ep, struct usb_request *request,
gfp_t gfp_flags);
int msm_ep_unconfig(struct usb_ep *ep);
void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr, u32 size,
@ -311,7 +312,8 @@ static inline int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
return -ENODEV;
}
static inline int msm_ep_config(struct usb_ep *ep)
static inline int msm_ep_config(struct usb_ep *ep, struct usb_request *request,
gfp_t gfp_flags)
{
return -ENODEV;
}