Revert "usb: dwc3: add functions to set force mode"

This reverts commit 9607f47dfe.
This commit is contained in:
Wu Liang feng
2016-08-10 11:17:20 +08:00
committed by Huang, Tao
parent d09c511566
commit 86e6380a5b
4 changed files with 10 additions and 368 deletions

View File

@@ -109,7 +109,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
* dwc3_soft_reset - Issue soft reset
* @dwc: Pointer to our controller context structure
*/
int dwc3_soft_reset(struct dwc3 *dwc)
static int dwc3_soft_reset(struct dwc3 *dwc)
{
unsigned long timeout;
u32 reg;
@@ -253,7 +253,7 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
*
* Returns 0 on success otherwise negative errno.
*/
int dwc3_event_buffers_setup(struct dwc3 *dwc)
static int dwc3_event_buffers_setup(struct dwc3 *dwc)
{
struct dwc3_event_buffer *evt;
int n;
@@ -279,7 +279,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
return 0;
}
void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
{
struct dwc3_event_buffer *evt;
int n;
@@ -809,76 +809,6 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
}
}
/* Returns true if the controller is capable of DRD. */
bool dwc3_hw_is_drd(struct dwc3 *dwc)
{
u32 op_mode = DWC3_GHWPARAMS0_USB3_MODE(dwc->hwparams.hwparams0);
return (op_mode == DWC3_GHWPARAMS0_USB3_DRD);
}
bool dwc3_force_mode(struct dwc3 *dwc, u32 mode)
{
u32 reg;
unsigned long flags;
struct usb_hcd *hcd;
/*
* Force mode has no effect if the hardware is not drd mode.
*/
if (!dwc3_hw_is_drd(dwc))
return false;
/*
* If dr_mode is either peripheral or host only, there is no
* need to ever force the mode to the opposite mode.
*/
if (WARN_ON(mode == DWC3_GCTL_PRTCAP_DEVICE &&
dwc->dr_mode == USB_DR_MODE_HOST))
return false;
if (WARN_ON(mode == DWC3_GCTL_PRTCAP_HOST &&
dwc->dr_mode == USB_DR_MODE_PERIPHERAL))
return false;
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
if (DWC3_GCTL_PRTCAP(reg) == mode)
return false;
hcd = dev_get_drvdata(&dwc->xhci->dev);
switch (mode) {
case DWC3_GCTL_PRTCAP_DEVICE:
if (hcd->state != HC_STATE_HALT) {
usb_remove_hcd(hcd->shared_hcd);
usb_remove_hcd(hcd);
}
spin_lock_irqsave(&dwc->lock, flags);
dwc3_set_mode(dwc, mode);
dwc3_gadget_restart(dwc, true);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case DWC3_GCTL_PRTCAP_HOST:
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_restart(dwc, false);
dwc3_set_mode(dwc, mode);
spin_unlock_irqrestore(&dwc->lock, flags);
if (hcd->state == HC_STATE_HALT) {
usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
usb_add_hcd(hcd->shared_hcd, hcd->irq, IRQF_SHARED);
}
break;
default:
/* do nothing */
break;
}
return true;
}
#define DWC3_ALIGN_MASK (16 - 1)
static int dwc3_probe(struct platform_device *pdev)

View File

@@ -30,10 +30,6 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/ulpi/interface.h>
#include <linux/phy/phy.h>
@@ -223,10 +219,6 @@
#define DWC3_GEVNTSIZ_INTMASK (1 << 31)
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
/* Global HWPARAMS0 Register */
#define DWC3_GHWPARAMS0_USB3_MODE(n) ((n) & 7)
#define DWC3_GHWPARAMS0_USB3_DRD 2
/* Global HWPARAMS1 Register */
#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24)
#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
@@ -722,7 +714,6 @@ struct dwc3_scratchpad_array {
* 1 - utmi_l1_suspend_n
* @is_fpga: true when we are using the FPGA board
* @needs_fifo_resize: not all users might want fifo resizing, flag it
* @enabled: true when gadget driver is ready
* @pullups_connected: true when Run/Stop bit is set
* @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
@@ -876,7 +867,6 @@ struct dwc3 {
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
unsigned needs_fifo_resize:1;
unsigned enabled:1;
unsigned pullups_connected:1;
unsigned resize_fifos:1;
unsigned setup_packet_pending:1;
@@ -1050,11 +1040,6 @@ struct dwc3_gadget_ep_cmd_params {
/* prototypes */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
int dwc3_soft_reset(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
int dwc3_gadget_restart(struct dwc3 *dwc, bool start);
bool dwc3_force_mode(struct dwc3 *dwc, u32 mode);
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc);

View File

@@ -402,17 +402,11 @@ static ssize_t dwc3_mode_write(struct file *file,
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (!strncmp(buf, "host", 4)) {
if (!strncmp(buf, "host", 4))
mode |= DWC3_GCTL_PRTCAP_HOST;
dwc3_force_mode(dwc, mode);
return count;
}
if (!strncmp(buf, "device", 6)) {
if (!strncmp(buf, "device", 6))
mode |= DWC3_GCTL_PRTCAP_DEVICE;
dwc3_force_mode(dwc, mode);
return count;
}
if (!strncmp(buf, "otg", 3))
mode |= DWC3_GCTL_PRTCAP_OTG;

View File

@@ -1579,20 +1579,12 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
{
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
int ret = 0;
u32 reg;
int ret;
is_on = !!is_on;
spin_lock_irqsave(&dwc->lock, flags);
dwc->enabled = is_on;
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
if (DWC3_GCTL_PRTCAP(reg) == DWC3_GCTL_PRTCAP_DEVICE)
ret = dwc3_gadget_run_stop(dwc, is_on, false);
ret = dwc3_gadget_run_stop(dwc, is_on, false);
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
@@ -1656,10 +1648,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc->gadget_driver = driver;
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
if (DWC3_GCTL_PRTCAP(reg) != DWC3_GCTL_PRTCAP_DEVICE)
goto mode_mismatch;
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK);
@@ -1722,7 +1710,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc3_gadget_enable_irq(dwc);
mode_mismatch:
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
@@ -1747,17 +1734,12 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
int irq;
u32 reg;
spin_lock_irqsave(&dwc->lock, flags);
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
if (DWC3_GCTL_PRTCAP(reg) == DWC3_GCTL_PRTCAP_DEVICE) {
dwc3_gadget_disable_irq(dwc);
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
}
dwc3_gadget_disable_irq(dwc);
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->gadget_driver = NULL;
@@ -2998,252 +2980,3 @@ err1:
err0:
return ret;
}
static int dwc3_gadget_reinit(struct dwc3 *dwc)
{
u32 hwparams4 = dwc->hwparams.hwparams4;
u32 reg;
int ret;
struct dwc3_ep *dep = NULL;
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
/* This should read as U3 followed by revision number */
if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
/* Detected DWC_usb3 IP */
dwc->revision = reg;
} else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
/* Detected DWC_usb31 IP */
dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
dwc->revision |= DWC3_REVISION_IS_DWC31;
} else {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
ret = -ENODEV;
goto err0;
}
/*
* Write Linux Version Code to our GUID register so it's easy to figure
* out which kernel version a bug was found.
*/
dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
/* Handle USB2.0-only core configuration */
if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
if (dwc->maximum_speed == USB_SPEED_SUPER)
dwc->maximum_speed = USB_SPEED_HIGH;
}
/* issue device SoftReset too */
ret = dwc3_soft_reset(dwc);
if (ret)
goto err0;
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
/**
* WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
* issue which would cause xHCI compliance tests to fail.
*
* Because of that we cannot enable clock gating on such
* configurations.
*
* Refers to:
*
* STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
* SOF/ITP Mode Used
*/
if ((dwc->dr_mode == USB_DR_MODE_HOST ||
dwc->dr_mode == USB_DR_MODE_OTG) &&
(dwc->revision >= DWC3_REVISION_210A &&
dwc->revision <= DWC3_REVISION_250A))
reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
else
reg &= ~DWC3_GCTL_DSBLCLKGTNG;
break;
case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
/* enable hibernation here */
dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
/*
* REVISIT Enabling this bit so that host-mode hibernation
* will work. Device-mode hibernation is not yet implemented.
*/
reg |= DWC3_GCTL_GBLHIBERNATIONEN;
break;
default:
dwc3_trace(trace_dwc3_core,
"No power optimization available\n");
}
/* check if current dwc3 is on simulation board */
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
dwc3_trace(trace_dwc3_core,
"running on FPGA platform\n");
dwc->is_fpga = true;
}
WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga,
"disable_scramble cannot be used on non-FPGA builds\n");
if (dwc->disable_scramble_quirk && dwc->is_fpga)
reg |= DWC3_GCTL_DISSCRAMBLE;
else
reg &= ~DWC3_GCTL_DISSCRAMBLE;
if (dwc->u2exit_lfps_quirk)
reg |= DWC3_GCTL_U2EXIT_LFPS;
/*
* WORKAROUND: DWC3 revisions <1.90a have a bug
* where the device can fail to connect at SuperSpeed
* and falls back to high-speed mode which causes
* the device to enter a Connect/Disconnect loop
*/
if (dwc->revision < DWC3_REVISION_190A)
reg |= DWC3_GCTL_U2RSTECN;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
goto err1;
}
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg |= DWC3_DCFG_LPM_CAP;
reg &= ~(DWC3_DCFG_SPEED_MASK);
/**
* WORKAROUND: DWC3 revision < 2.20a have an issue
* which would cause metastability state on Run/Stop
* bit if we try to force the IP to USB2-only mode.
*
* Because of that, we cannot configure the IP to any
* speed other than the SuperSpeed
*
* Refers to:
*
* STAR#9000525659: Clock Domain Crossing on DCTL in
* USB 2.0 Mode
*/
if (dwc->revision < DWC3_REVISION_220A) {
reg |= DWC3_DCFG_SUPERSPEED;
} else {
switch (dwc->maximum_speed) {
case USB_SPEED_LOW:
reg |= DWC3_DSTS_LOWSPEED;
break;
case USB_SPEED_FULL:
reg |= DWC3_DSTS_FULLSPEED1;
break;
case USB_SPEED_HIGH:
reg |= DWC3_DSTS_HIGHSPEED;
break;
case USB_SPEED_SUPER: /* FALLTHROUGH */
case USB_SPEED_UNKNOWN: /* FALTHROUGH */
default:
reg |= DWC3_DSTS_SUPERSPEED;
}
}
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
dep = dwc->eps[0];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
goto err1;
}
dep = dwc->eps[1];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
goto err2;
}
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
return 0;
err2:
__dwc3_gadget_ep_disable(dwc->eps[0]);
err1:
dwc3_event_buffers_cleanup(dwc);
err0:
return ret;
}
int dwc3_gadget_restart(struct dwc3 *dwc, bool start)
{
struct dwc3_event_buffer *evt;
int ret = 0;
int i;
u32 reg;
if (start) {
ret = dwc3_gadget_reinit(dwc);
if (ret < 0) {
dev_err(dwc->dev,
"dwc3 gadget reinit error = %d\n", ret);
goto err;
}
if (dwc->enabled) {
ret = dwc3_gadget_run_stop(dwc, start, false);
if (ret < 0) {
dev_err(dwc->dev,
"dwc3 gadget run stop err = %d\n", ret);
goto err;
}
}
dwc3_gadget_enable_irq(dwc);
} else {
/*
* Per databook, DEVCTRLHLT bit setting requires
* interrupts to be acknowledged. so acknowledge
* the events that are generated (by writing to
* GEVNTCOUNTn) first. And we also mask interrupts
* and clear SW states to avoid generating other
* interrupts after do gadget disconnnect operation.
*/
dwc3_gadget_disable_irq(dwc);
for (i = 0; i < dwc->num_event_buffers; i++) {
evt = dwc->ev_buffs[i];
evt->count = 0;
evt->flags &= ~DWC3_EVENT_PENDING;
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(i));
reg |= DWC3_GEVNTSIZ_INTMASK;
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(i), reg);
reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(i));
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), reg);
}
/*
* DEVCTRLHLT bit sometimes does not get set
* even when GEVNTCOUNT is acked so do not
* care run stop function return value.
*/
dwc3_gadget_run_stop(dwc, start, false);
if (dwc->gadget.state != USB_STATE_NOTATTACHED)
dwc3_gadget_disconnect_interrupt(dwc);
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
}
err:
return ret;
}