mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Revert "usb: dwc3: add functions to set force mode"
This reverts commit 9607f47dfe.
This commit is contained in:
committed by
Huang, Tao
parent
d09c511566
commit
86e6380a5b
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user