Merge "USB: dwc3-msm: Disable Update xfer for DBM on ep disable or dequeue"
This commit is contained in:
commit
04d779afaa
6 changed files with 81 additions and 23 deletions
|
@ -180,9 +180,9 @@ static int dwc3_core_reset(struct dwc3 *dwc)
|
|||
reg &= ~DWC3_GUSB3PIPECTL_DELAYP1TRANS;
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
|
||||
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT, 0);
|
||||
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -908,19 +908,19 @@ void dwc3_post_host_reset_core_init(struct dwc3 *dwc)
|
|||
dwc3_gadget_restart(dwc);
|
||||
}
|
||||
|
||||
static void (*notify_event) (struct dwc3 *, unsigned);
|
||||
void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned))
|
||||
static void (*notify_event)(struct dwc3 *, unsigned, unsigned);
|
||||
void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned, unsigned))
|
||||
{
|
||||
notify_event = notify;
|
||||
}
|
||||
EXPORT_SYMBOL(dwc3_set_notifier);
|
||||
|
||||
int dwc3_notify_event(struct dwc3 *dwc, unsigned event)
|
||||
int dwc3_notify_event(struct dwc3 *dwc, unsigned event, unsigned value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dwc->notify_event)
|
||||
dwc->notify_event(dwc, event);
|
||||
dwc->notify_event(dwc, event, value);
|
||||
else
|
||||
ret = -ENODEV;
|
||||
|
||||
|
@ -1317,7 +1317,7 @@ static int dwc3_suspend(struct device *dev)
|
|||
unsigned long flags;
|
||||
|
||||
/* Check if platform glue driver handling PM, if not then handle here */
|
||||
if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT))
|
||||
if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT, 0))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
@ -1353,7 +1353,7 @@ static int dwc3_resume(struct device *dev)
|
|||
int ret;
|
||||
|
||||
/* Check if platform glue driver handling PM, if not then handle here */
|
||||
if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
|
||||
if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0))
|
||||
return 0;
|
||||
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
|
|
@ -731,6 +731,7 @@ struct dwc3_scratchpad_array {
|
|||
#define DWC3_CONTROLLER_NOTIFY_OTG_EVENT 6
|
||||
#define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT 7
|
||||
#define DWC3_CONTROLLER_RESTART_USB_SESSION 8
|
||||
#define DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER 9
|
||||
|
||||
#define MAX_INTR_STATS 10
|
||||
/**
|
||||
|
@ -952,7 +953,7 @@ struct dwc3 {
|
|||
|
||||
const char *hsphy_interface;
|
||||
|
||||
void (*notify_event) (struct dwc3 *, unsigned);
|
||||
void (*notify_event)(struct dwc3 *, unsigned, unsigned);
|
||||
struct work_struct wakeup_work;
|
||||
|
||||
unsigned delayed_status:1;
|
||||
|
@ -1252,7 +1253,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc);
|
|||
void dwc3_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
|
||||
|
||||
extern void dwc3_set_notifier(
|
||||
void (*notify) (struct dwc3 *dwc3, unsigned event));
|
||||
extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned event);
|
||||
void (*notify)(struct dwc3 *dwc3, unsigned event, unsigned value));
|
||||
extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned event, unsigned value);
|
||||
|
||||
#endif /* __DRIVERS_USB_DWC3_CORE_H */
|
||||
|
|
|
@ -37,6 +37,7 @@ enum dbm_reg {
|
|||
DBM_HW_TRB2_EP,
|
||||
DBM_HW_TRB3_EP,
|
||||
DBM_PIPE_CFG,
|
||||
DBM_DISABLE_UPDXFER,
|
||||
DBM_SOFT_RESET,
|
||||
DBM_GEN_CFG,
|
||||
DBM_GEVNTADR_LSB,
|
||||
|
@ -103,6 +104,7 @@ static const struct dbm_reg_data dbm_1_5_regtable[] = {
|
|||
[DBM_HW_TRB2_EP] = { 0x0240, 0x4 },
|
||||
[DBM_HW_TRB3_EP] = { 0x0250, 0x4 },
|
||||
[DBM_PIPE_CFG] = { 0x0274, 0x0 },
|
||||
[DBM_DISABLE_UPDXFER] = { 0x0298, 0x0 },
|
||||
[DBM_SOFT_RESET] = { 0x020C, 0x0 },
|
||||
[DBM_GEN_CFG] = { 0x0210, 0x0 },
|
||||
[DBM_GEVNTADR_LSB] = { 0x0260, 0x0 },
|
||||
|
@ -291,6 +293,7 @@ int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe, bool producer,
|
|||
{
|
||||
int dbm_ep;
|
||||
u32 ep_cfg;
|
||||
u32 data;
|
||||
|
||||
if (!dbm) {
|
||||
pr_err("%s: dbm pointer is NULL!\n", __func__);
|
||||
|
@ -334,6 +337,10 @@ int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe, bool producer,
|
|||
|
||||
msm_dbm_write_ep_reg_field(dbm, DBM_EP_CFG, dbm_ep, DBM_EN_EP, 1);
|
||||
|
||||
data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER);
|
||||
data &= ~(0x1 << dbm_ep);
|
||||
msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data);
|
||||
|
||||
return dbm_ep;
|
||||
}
|
||||
|
||||
|
@ -433,6 +440,35 @@ int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo, u32 addr_hi, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable update xfer before queueing stop xfer command to USB3 core.
|
||||
*
|
||||
* @usb_ep - USB physical EP number.
|
||||
*
|
||||
*/
|
||||
int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep)
|
||||
{
|
||||
u32 data;
|
||||
u8 dbm_ep;
|
||||
|
||||
if (!dbm) {
|
||||
pr_err("%s: dbm pointer is NULL!\n", __func__);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dbm_ep = find_matching_dbm_ep(dbm, usb_ep);
|
||||
|
||||
if (dbm_ep < 0) {
|
||||
pr_err("usb ep index %d has no corresponding dbm ep\n", usb_ep);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER);
|
||||
data |= (0x1 << dbm_ep);
|
||||
msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr,
|
||||
u32 size, u8 dst_pipe_idx)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* 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
|
||||
|
@ -63,6 +63,7 @@ int dbm_ep_unconfig(struct dbm *dbm, u8 usb_ep);
|
|||
int dbm_get_num_of_eps_configured(struct dbm *dbm);
|
||||
int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo, u32 addr_hi,
|
||||
int size);
|
||||
int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep);
|
||||
int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr,
|
||||
u32 size, u8 dst_pipe_idx);
|
||||
void dbm_set_speed(struct dbm *dbm, bool speed);
|
||||
|
|
|
@ -367,6 +367,16 @@ static inline bool dwc3_msm_is_superspeed(struct dwc3_msm *mdwc)
|
|||
return dwc3_msm_is_dev_superspeed(mdwc);
|
||||
}
|
||||
|
||||
int dwc3_msm_dbm_disable_updxfer(struct dwc3 *dwc, u8 usb_ep)
|
||||
{
|
||||
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
||||
|
||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
||||
dwc3_dbm_disable_update_xfer(mdwc->dbm, usb_ep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
|
||||
/**
|
||||
* Configure the DBM with the BAM's data fifo.
|
||||
|
@ -1625,7 +1635,8 @@ static void dwc3_msm_vbus_draw_work(struct work_struct *w)
|
|||
dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
|
||||
}
|
||||
|
||||
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
|
||||
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event,
|
||||
unsigned value)
|
||||
{
|
||||
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
||||
u32 reg;
|
||||
|
@ -1717,6 +1728,9 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
|
|||
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n");
|
||||
schedule_work(&mdwc->restart_usb_work);
|
||||
break;
|
||||
case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
|
||||
dwc3_msm_dbm_disable_updxfer(dwc, value);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(mdwc->dev, "unknown dwc3 event\n");
|
||||
break;
|
||||
|
|
|
@ -384,7 +384,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
|
|||
if (!(cmd & DWC3_DEPCMD_ENDTRANSFER)) {
|
||||
dwc->ep_cmd_timeout_cnt++;
|
||||
dwc3_notify_event(dwc,
|
||||
DWC3_CONTROLLER_RESTART_USB_SESSION);
|
||||
DWC3_CONTROLLER_RESTART_USB_SESSION, 0);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -1872,7 +1872,7 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned mA)
|
|||
|
||||
dwc->vbus_draw = mA;
|
||||
dev_dbg(dwc->dev, "Notify controller from %s. mA = %d\n", __func__, mA);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1907,7 +1907,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
*/
|
||||
dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
|
||||
dwc->b_suspend = false;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
|
||||
|
||||
ret = dwc3_gadget_run_stop(dwc, is_on, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
@ -2143,7 +2143,7 @@ static int dwc3_gadget_restart_usb_session(struct usb_gadget *g)
|
|||
{
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
|
||||
return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION);
|
||||
return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION, 0);
|
||||
}
|
||||
|
||||
static const struct usb_gadget_ops dwc3_gadget_ops = {
|
||||
|
@ -2659,6 +2659,10 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
|
|||
if (!dep->resource_index)
|
||||
return;
|
||||
|
||||
if (dep->endpoint.endless)
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
|
||||
dep->number);
|
||||
|
||||
/*
|
||||
* NOTICE: We are violating what the Databook says about the
|
||||
* EndTransfer command. Ideally we would _always_ wait for the
|
||||
|
@ -2743,7 +2747,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
|
|||
|
||||
dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
|
||||
dwc->b_suspend = false;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
reg &= ~DWC3_DCTL_INITU1ENA;
|
||||
|
@ -2799,7 +2803,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
|||
|
||||
dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
|
||||
dwc->b_suspend = false;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
|
||||
|
||||
dwc3_usb3_phy_suspend(dwc, false);
|
||||
usb_gadget_vbus_draw(&dwc->gadget, 100);
|
||||
|
@ -2960,7 +2964,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
|||
return;
|
||||
}
|
||||
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT, 0);
|
||||
|
||||
/*
|
||||
* Configure PHY via GUSB3PIPECTLn if required.
|
||||
|
@ -2996,7 +3000,8 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup)
|
|||
*/
|
||||
dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
|
||||
dwc->b_suspend = false;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
|
||||
dwc3_notify_event(dwc,
|
||||
DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
|
||||
|
||||
/*
|
||||
* set state to U0 as function level resume is trying to queue
|
||||
|
@ -3163,7 +3168,7 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc,
|
|||
|
||||
dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
|
||||
dwc->b_suspend = true;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
|
||||
}
|
||||
|
||||
dwc->link_state = next;
|
||||
|
@ -3334,7 +3339,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
|
|||
evt->lpos = (evt->lpos + left) %
|
||||
DWC3_EVENT_BUFFERS_SIZE;
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), left);
|
||||
if (dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT))
|
||||
if (dwc3_notify_event(dwc,
|
||||
DWC3_CONTROLLER_ERROR_EVENT, 0))
|
||||
dwc->err_evt_seen = 0;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue