mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
usb: dwc3: gadget: make dwc3 gadget build in uboot
Did a bunch of things to get dwc3/gadget.c compile in u-boot without build errors and warnings *) Changed the included header files to that used in u-boot. *) Used dma_alloc_coherent and dma_free_coherent APIs of u-boot *) removed sg support *) remove jiffies and used a simple while loop *) removed irq support and added a function to call these interrupt handler. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Reviewed-by: Lukasz Majewski <l.majewski@samsung.com>
This commit is contained in:
parent
18be4cb151
commit
747a0a5b38
5 changed files with 124 additions and 162 deletions
|
@ -14,25 +14,22 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <common.h>
|
||||||
#include <linux/delay.h>
|
#include <malloc.h>
|
||||||
#include <linux/slab.h>
|
#include <asm/dma-mapping.h>
|
||||||
#include <linux/spinlock.h>
|
#include <usb/lin_gadget_compat.h>
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/dma-mapping.h>
|
|
||||||
|
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
#include <asm/arch/sys_proto.h>
|
||||||
|
|
||||||
#include "debug.h"
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "gadget.h"
|
#include "gadget.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
|
#include "linux-compat.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
|
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
|
||||||
* @dwc: pointer to our context structure
|
* @dwc: pointer to our context structure
|
||||||
|
@ -166,7 +163,6 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
|
||||||
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
|
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
|
||||||
{
|
{
|
||||||
int last_fifo_depth = 0;
|
int last_fifo_depth = 0;
|
||||||
int ram1_depth;
|
|
||||||
int fifo_size;
|
int fifo_size;
|
||||||
int mdwidth;
|
int mdwidth;
|
||||||
int num;
|
int num;
|
||||||
|
@ -174,7 +170,6 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
|
||||||
if (!dwc->needs_fifo_resize)
|
if (!dwc->needs_fifo_resize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
|
|
||||||
mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
|
mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
|
||||||
|
|
||||||
/* MDWIDTH is represented in bits, we need it in bytes */
|
/* MDWIDTH is represented in bits, we need it in bytes */
|
||||||
|
@ -232,24 +227,21 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||||
int status)
|
int status)
|
||||||
{
|
{
|
||||||
struct dwc3 *dwc = dep->dwc;
|
struct dwc3 *dwc = dep->dwc;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (req->queued) {
|
if (req->queued) {
|
||||||
i = 0;
|
dep->busy_slot++;
|
||||||
do {
|
/*
|
||||||
|
* Skip LINK TRB. We can't use req->trb and check for
|
||||||
|
* DWC3_TRBCTL_LINK_TRB because it points the TRB we
|
||||||
|
* just completed (not the LINK TRB).
|
||||||
|
*/
|
||||||
|
if (((dep->busy_slot & DWC3_TRB_MASK) ==
|
||||||
|
DWC3_TRB_NUM- 1) &&
|
||||||
|
usb_endpoint_xfer_isoc(dep->endpoint.desc))
|
||||||
dep->busy_slot++;
|
dep->busy_slot++;
|
||||||
/*
|
|
||||||
* Skip LINK TRB. We can't use req->trb and check for
|
|
||||||
* DWC3_TRBCTL_LINK_TRB because it points the TRB we
|
|
||||||
* just completed (not the LINK TRB).
|
|
||||||
*/
|
|
||||||
if (((dep->busy_slot & DWC3_TRB_MASK) ==
|
|
||||||
DWC3_TRB_NUM- 1) &&
|
|
||||||
usb_endpoint_xfer_isoc(dep->endpoint.desc))
|
|
||||||
dep->busy_slot++;
|
|
||||||
} while(++i < req->request.num_mapped_sgs);
|
|
||||||
req->queued = false;
|
req->queued = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&req->list);
|
list_del(&req->list);
|
||||||
req->trb = NULL;
|
req->trb = NULL;
|
||||||
|
|
||||||
|
@ -301,7 +293,6 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
|
||||||
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
|
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
|
||||||
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
|
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
|
||||||
{
|
{
|
||||||
struct dwc3_ep *dep = dwc->eps[ep];
|
|
||||||
u32 timeout = 500;
|
u32 timeout = 500;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
|
@ -340,17 +331,15 @@ static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
|
||||||
|
|
||||||
static int dwc3_alloc_trb_pool(struct dwc3_ep *dep)
|
static int dwc3_alloc_trb_pool(struct dwc3_ep *dep)
|
||||||
{
|
{
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
|
|
||||||
if (dep->trb_pool)
|
if (dep->trb_pool)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (dep->number == 0 || dep->number == 1)
|
if (dep->number == 0 || dep->number == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dep->trb_pool = dma_alloc_coherent(dwc->dev,
|
dep->trb_pool = dma_alloc_coherent(sizeof(struct dwc3_trb) *
|
||||||
sizeof(struct dwc3_trb) * DWC3_TRB_NUM,
|
DWC3_TRB_NUM,
|
||||||
&dep->trb_pool_dma, GFP_KERNEL);
|
(unsigned long *)&dep->trb_pool_dma);
|
||||||
if (!dep->trb_pool) {
|
if (!dep->trb_pool) {
|
||||||
dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n",
|
dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n",
|
||||||
dep->name);
|
dep->name);
|
||||||
|
@ -362,10 +351,7 @@ static int dwc3_alloc_trb_pool(struct dwc3_ep *dep)
|
||||||
|
|
||||||
static void dwc3_free_trb_pool(struct dwc3_ep *dep)
|
static void dwc3_free_trb_pool(struct dwc3_ep *dep)
|
||||||
{
|
{
|
||||||
struct dwc3 *dwc = dep->dwc;
|
dma_free_coherent(dep->trb_pool);
|
||||||
|
|
||||||
dma_free_coherent(dwc->dev, sizeof(struct dwc3_trb) * DWC3_TRB_NUM,
|
|
||||||
dep->trb_pool, dep->trb_pool_dma);
|
|
||||||
|
|
||||||
dep->trb_pool = NULL;
|
dep->trb_pool = NULL;
|
||||||
dep->trb_pool_dma = 0;
|
dep->trb_pool_dma = 0;
|
||||||
|
@ -607,7 +593,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
||||||
const struct usb_endpoint_descriptor *desc)
|
const struct usb_endpoint_descriptor *desc)
|
||||||
{
|
{
|
||||||
struct dwc3_ep *dep;
|
struct dwc3_ep *dep;
|
||||||
struct dwc3 *dwc;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -622,10 +607,9 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
||||||
}
|
}
|
||||||
|
|
||||||
dep = to_dwc3_ep(ep);
|
dep = to_dwc3_ep(ep);
|
||||||
dwc = dep->dwc;
|
|
||||||
|
|
||||||
if (dep->flags & DWC3_EP_ENABLED) {
|
if (dep->flags & DWC3_EP_ENABLED) {
|
||||||
dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n",
|
WARN(true, "%s is already enabled\n",
|
||||||
dep->name);
|
dep->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +641,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
||||||
static int dwc3_gadget_ep_disable(struct usb_ep *ep)
|
static int dwc3_gadget_ep_disable(struct usb_ep *ep)
|
||||||
{
|
{
|
||||||
struct dwc3_ep *dep;
|
struct dwc3_ep *dep;
|
||||||
struct dwc3 *dwc;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -667,10 +650,9 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
dep = to_dwc3_ep(ep);
|
dep = to_dwc3_ep(ep);
|
||||||
dwc = dep->dwc;
|
|
||||||
|
|
||||||
if (!(dep->flags & DWC3_EP_ENABLED)) {
|
if (!(dep->flags & DWC3_EP_ENABLED)) {
|
||||||
dev_WARN_ONCE(dwc->dev, true, "%s is already disabled\n",
|
WARN(true, "%s is already disabled\n",
|
||||||
dep->name);
|
dep->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -719,7 +701,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
|
||||||
struct dwc3_request *req, dma_addr_t dma,
|
struct dwc3_request *req, dma_addr_t dma,
|
||||||
unsigned length, unsigned last, unsigned chain, unsigned node)
|
unsigned length, unsigned last, unsigned chain, unsigned node)
|
||||||
{
|
{
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
struct dwc3_trb *trb;
|
struct dwc3_trb *trb;
|
||||||
|
|
||||||
dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n",
|
dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n",
|
||||||
|
@ -856,57 +837,22 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
|
||||||
dma_addr_t dma;
|
dma_addr_t dma;
|
||||||
last_one = false;
|
last_one = false;
|
||||||
|
|
||||||
if (req->request.num_mapped_sgs > 0) {
|
dma = req->request.dma;
|
||||||
struct usb_request *request = &req->request;
|
length = req->request.length;
|
||||||
struct scatterlist *sg = request->sg;
|
trbs_left--;
|
||||||
struct scatterlist *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for_each_sg(sg, s, request->num_mapped_sgs, i) {
|
if (!trbs_left)
|
||||||
unsigned chain = true;
|
last_one = 1;
|
||||||
|
|
||||||
length = sg_dma_len(s);
|
/* Is this the last request? */
|
||||||
dma = sg_dma_address(s);
|
if (list_is_last(&req->list, &dep->request_list))
|
||||||
|
last_one = 1;
|
||||||
|
|
||||||
if (i == (request->num_mapped_sgs - 1) ||
|
dwc3_prepare_one_trb(dep, req, dma, length,
|
||||||
sg_is_last(s)) {
|
last_one, false, 0);
|
||||||
if (list_is_last(&req->list,
|
|
||||||
&dep->request_list))
|
|
||||||
last_one = true;
|
|
||||||
chain = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
trbs_left--;
|
if (last_one)
|
||||||
if (!trbs_left)
|
break;
|
||||||
last_one = true;
|
|
||||||
|
|
||||||
if (last_one)
|
|
||||||
chain = false;
|
|
||||||
|
|
||||||
dwc3_prepare_one_trb(dep, req, dma, length,
|
|
||||||
last_one, chain, i);
|
|
||||||
|
|
||||||
if (last_one)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dma = req->request.dma;
|
|
||||||
length = req->request.length;
|
|
||||||
trbs_left--;
|
|
||||||
|
|
||||||
if (!trbs_left)
|
|
||||||
last_one = 1;
|
|
||||||
|
|
||||||
/* Is this the last request? */
|
|
||||||
if (list_is_last(&req->list, &dep->request_list))
|
|
||||||
last_one = 1;
|
|
||||||
|
|
||||||
dwc3_prepare_one_trb(dep, req, dma, length,
|
|
||||||
last_one, false, 0);
|
|
||||||
|
|
||||||
if (last_one)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,8 +1049,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||||
|
|
||||||
ret = __dwc3_gadget_kick_transfer(dep, 0, true);
|
ret = __dwc3_gadget_kick_transfer(dep, 0, true);
|
||||||
if (ret && ret != -EBUSY) {
|
if (ret && ret != -EBUSY) {
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
|
|
||||||
dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
|
dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
|
||||||
dep->name);
|
dep->name);
|
||||||
}
|
}
|
||||||
|
@ -1118,7 +1062,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
|
||||||
{
|
{
|
||||||
struct dwc3_request *req = to_dwc3_request(request);
|
struct dwc3_request *req = to_dwc3_request(request);
|
||||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -1132,8 +1075,9 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
|
if (req->dep != dep) {
|
||||||
request, req->dep->name)) {
|
WARN(true, "request %p belongs to '%s'\n",
|
||||||
|
request, req->dep->name);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1239,7 +1183,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
|
||||||
static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
|
static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
|
||||||
{
|
{
|
||||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -1255,7 +1198,6 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
|
||||||
static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
|
static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
|
||||||
{
|
{
|
||||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1371,9 +1313,9 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* poll until Link State changes to ON */
|
/* poll until Link State changes to ON */
|
||||||
timeout = jiffies + msecs_to_jiffies(100);
|
timeout = 1000;
|
||||||
|
|
||||||
while (!time_after(jiffies, timeout)) {
|
while (timeout--) {
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
||||||
|
|
||||||
/* in HS, means ON */
|
/* in HS, means ON */
|
||||||
|
@ -1498,9 +1440,6 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
|
||||||
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
|
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
|
|
||||||
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
|
|
||||||
|
|
||||||
static int dwc3_gadget_start(struct usb_gadget *g,
|
static int dwc3_gadget_start(struct usb_gadget *g,
|
||||||
struct usb_gadget_driver *driver)
|
struct usb_gadget_driver *driver)
|
||||||
{
|
{
|
||||||
|
@ -1508,24 +1447,14 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
||||||
struct dwc3_ep *dep;
|
struct dwc3_ep *dep;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int irq;
|
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
|
||||||
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
|
|
||||||
IRQF_SHARED, "dwc3", dwc);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
|
|
||||||
irq, ret);
|
|
||||||
goto err0;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dwc->lock, flags);
|
spin_lock_irqsave(&dwc->lock, flags);
|
||||||
|
|
||||||
if (dwc->gadget_driver) {
|
if (dwc->gadget_driver) {
|
||||||
dev_err(dwc->dev, "%s is already bound to %s\n",
|
dev_err(dwc->dev, "%s is already bound to %s\n",
|
||||||
dwc->gadget.name,
|
dwc->gadget.name,
|
||||||
dwc->gadget_driver->driver.name);
|
dwc->gadget_driver->function);
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
@ -1609,9 +1538,6 @@ err2:
|
||||||
err1:
|
err1:
|
||||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||||
|
|
||||||
free_irq(irq, dwc);
|
|
||||||
|
|
||||||
err0:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,7 +1545,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
|
||||||
{
|
{
|
||||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int irq;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dwc->lock, flags);
|
spin_lock_irqsave(&dwc->lock, flags);
|
||||||
|
|
||||||
|
@ -1631,9 +1556,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||||
|
|
||||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
|
||||||
free_irq(irq, dwc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1832,7 +1754,6 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
|
||||||
struct dwc3_request *req;
|
struct dwc3_request *req;
|
||||||
struct dwc3_trb *trb;
|
struct dwc3_trb *trb;
|
||||||
unsigned int slot;
|
unsigned int slot;
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -1841,20 +1762,18 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
slot = req->start_slot + i;
|
|
||||||
if ((slot == DWC3_TRB_NUM - 1) &&
|
|
||||||
usb_endpoint_xfer_isoc(dep->endpoint.desc))
|
|
||||||
slot++;
|
|
||||||
slot %= DWC3_TRB_NUM;
|
|
||||||
trb = &dep->trb_pool[slot];
|
|
||||||
|
|
||||||
ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
|
slot = req->start_slot;
|
||||||
event, status);
|
if ((slot == DWC3_TRB_NUM - 1) &&
|
||||||
if (ret)
|
usb_endpoint_xfer_isoc(dep->endpoint.desc))
|
||||||
break;
|
slot++;
|
||||||
}while (++i < req->request.num_mapped_sgs);
|
slot %= DWC3_TRB_NUM;
|
||||||
|
trb = &dep->trb_pool[slot];
|
||||||
|
|
||||||
|
ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
|
||||||
|
event, status);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
dwc3_gadget_giveback(dep, req, status);
|
dwc3_gadget_giveback(dep, req, status);
|
||||||
|
|
||||||
|
@ -2293,9 +2212,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
||||||
* BESL value in the LPM token is less than or equal to LPM
|
* BESL value in the LPM token is less than or equal to LPM
|
||||||
* NYET threshold.
|
* NYET threshold.
|
||||||
*/
|
*/
|
||||||
WARN_ONCE(dwc->revision < DWC3_REVISION_240A
|
if (dwc->revision < DWC3_REVISION_240A && dwc->has_lpm_erratum)
|
||||||
&& dwc->has_lpm_erratum,
|
WARN(true, "LPM Erratum not available on dwc3 revisisions < 2.40a\n");
|
||||||
"LPM Erratum not available on dwc3 revisisions < 2.40a\n");
|
|
||||||
|
|
||||||
if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
|
if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
|
||||||
reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);
|
reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);
|
||||||
|
@ -2482,10 +2400,10 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
|
||||||
dwc3_gadget_wakeup_interrupt(dwc);
|
dwc3_gadget_wakeup_interrupt(dwc);
|
||||||
break;
|
break;
|
||||||
case DWC3_DEVICE_EVENT_HIBER_REQ:
|
case DWC3_DEVICE_EVENT_HIBER_REQ:
|
||||||
if (dev_WARN_ONCE(dwc->dev, !dwc->has_hibernation,
|
if (!dwc->has_hibernation) {
|
||||||
"unexpected hibernation event\n"))
|
WARN(1 ,"unexpected hibernation event\n");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
dwc3_gadget_hibernation_interrupt(dwc, event->event_info);
|
dwc3_gadget_hibernation_interrupt(dwc, event->event_info);
|
||||||
break;
|
break;
|
||||||
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
|
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
|
||||||
|
@ -2649,16 +2567,16 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
|
dwc->ctrl_req = dma_alloc_coherent(sizeof(*dwc->ctrl_req),
|
||||||
&dwc->ctrl_req_addr, GFP_KERNEL);
|
(unsigned long *)&dwc->ctrl_req_addr);
|
||||||
if (!dwc->ctrl_req) {
|
if (!dwc->ctrl_req) {
|
||||||
dev_err(dwc->dev, "failed to allocate ctrl request\n");
|
dev_err(dwc->dev, "failed to allocate ctrl request\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err0;
|
goto err0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
|
dwc->ep0_trb = dma_alloc_coherent(sizeof(*dwc->ep0_trb),
|
||||||
&dwc->ep0_trb_addr, GFP_KERNEL);
|
(unsigned long *)&dwc->ep0_trb_addr);
|
||||||
if (!dwc->ep0_trb) {
|
if (!dwc->ep0_trb) {
|
||||||
dev_err(dwc->dev, "failed to allocate ep0 trb\n");
|
dev_err(dwc->dev, "failed to allocate ep0 trb\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -2671,9 +2589,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc->ep0_bounce = dma_alloc_coherent(dwc->dev,
|
dwc->ep0_bounce = dma_alloc_coherent(DWC3_EP0_BOUNCE_SIZE,
|
||||||
DWC3_EP0_BOUNCE_SIZE, &dwc->ep0_bounce_addr,
|
(unsigned long *)&dwc->ep0_bounce_addr);
|
||||||
GFP_KERNEL);
|
|
||||||
if (!dwc->ep0_bounce) {
|
if (!dwc->ep0_bounce) {
|
||||||
dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
|
dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -2683,7 +2600,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||||
dwc->gadget.ops = &dwc3_gadget_ops;
|
dwc->gadget.ops = &dwc3_gadget_ops;
|
||||||
dwc->gadget.max_speed = USB_SPEED_SUPER;
|
dwc->gadget.max_speed = USB_SPEED_SUPER;
|
||||||
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
dwc->gadget.sg_supported = true;
|
|
||||||
dwc->gadget.name = "dwc3-gadget";
|
dwc->gadget.name = "dwc3-gadget";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2711,19 +2627,16 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||||
|
|
||||||
err4:
|
err4:
|
||||||
dwc3_gadget_free_endpoints(dwc);
|
dwc3_gadget_free_endpoints(dwc);
|
||||||
dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
|
dma_free_coherent(dwc->ep0_bounce);
|
||||||
dwc->ep0_bounce, dwc->ep0_bounce_addr);
|
|
||||||
|
|
||||||
err3:
|
err3:
|
||||||
kfree(dwc->setup_buf);
|
kfree(dwc->setup_buf);
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
|
dma_free_coherent(dwc->ep0_trb);
|
||||||
dwc->ep0_trb, dwc->ep0_trb_addr);
|
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
|
dma_free_coherent(dwc->ctrl_req);
|
||||||
dwc->ctrl_req, dwc->ctrl_req_addr);
|
|
||||||
|
|
||||||
err0:
|
err0:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2737,14 +2650,25 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
|
||||||
|
|
||||||
dwc3_gadget_free_endpoints(dwc);
|
dwc3_gadget_free_endpoints(dwc);
|
||||||
|
|
||||||
dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
|
dma_free_coherent(dwc->ep0_bounce);
|
||||||
dwc->ep0_bounce, dwc->ep0_bounce_addr);
|
|
||||||
|
|
||||||
kfree(dwc->setup_buf);
|
kfree(dwc->setup_buf);
|
||||||
|
|
||||||
dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
|
dma_free_coherent(dwc->ep0_trb);
|
||||||
dwc->ep0_trb, dwc->ep0_trb_addr);
|
|
||||||
|
|
||||||
dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
|
dma_free_coherent(dwc->ctrl_req);
|
||||||
dwc->ctrl_req, dwc->ctrl_req_addr);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dwc3_gadget_uboot_handle_interrupt - handle dwc3 gadget interrupt
|
||||||
|
* @dwc: struct dwce *
|
||||||
|
*
|
||||||
|
* Handles ep0 and gadget interrupt
|
||||||
|
*
|
||||||
|
* Should be called from dwc3 core.
|
||||||
|
*/
|
||||||
|
void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc)
|
||||||
|
{
|
||||||
|
dwc3_interrupt(0, dwc);
|
||||||
|
dwc3_thread_interrupt(0, dwc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
|
||||||
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
|
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
|
||||||
gfp_t gfp_flags);
|
gfp_t gfp_flags);
|
||||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
|
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
|
||||||
|
void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
|
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
*
|
*
|
||||||
* Authors: Kishon Vijay Abraham I <kishon@ti.com>
|
* Authors: Kishon Vijay Abraham I <kishon@ti.com>
|
||||||
*
|
*
|
||||||
* Taken from Linux Kernel v3.16 (drivers/usb/dwc3/core.c) and ported
|
|
||||||
* to uboot.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -326,6 +326,7 @@ typedef unsigned long dmaaddr_t;
|
||||||
|
|
||||||
#define IRQ_NONE 0
|
#define IRQ_NONE 0
|
||||||
#define IRQ_HANDLED 1
|
#define IRQ_HANDLED 1
|
||||||
|
#define IRQ_WAKE_THREAD 2
|
||||||
|
|
||||||
#define dev_set_drvdata(dev, data) do {} while (0)
|
#define dev_set_drvdata(dev, data) do {} while (0)
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct usb_ep;
|
||||||
* @dma: DMA address corresponding to 'buf'. If you don't set this
|
* @dma: DMA address corresponding to 'buf'. If you don't set this
|
||||||
* field, and the usb controller needs one, it is responsible
|
* field, and the usb controller needs one, it is responsible
|
||||||
* for mapping and unmapping the buffer.
|
* for mapping and unmapping the buffer.
|
||||||
|
* @stream_id: The stream id, when USB3.0 bulk streams are being used
|
||||||
* @length: Length of that data
|
* @length: Length of that data
|
||||||
* @no_interrupt: If true, hints that no completion irq is needed.
|
* @no_interrupt: If true, hints that no completion irq is needed.
|
||||||
* Helpful sometimes with deep request queues that are handled
|
* Helpful sometimes with deep request queues that are handled
|
||||||
|
@ -85,6 +86,7 @@ struct usb_request {
|
||||||
unsigned length;
|
unsigned length;
|
||||||
dma_addr_t dma;
|
dma_addr_t dma;
|
||||||
|
|
||||||
|
unsigned stream_id:16;
|
||||||
unsigned no_interrupt:1;
|
unsigned no_interrupt:1;
|
||||||
unsigned zero:1;
|
unsigned zero:1;
|
||||||
unsigned short_not_ok:1;
|
unsigned short_not_ok:1;
|
||||||
|
@ -121,6 +123,7 @@ struct usb_ep_ops {
|
||||||
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
|
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
|
||||||
|
|
||||||
int (*set_halt) (struct usb_ep *ep, int value);
|
int (*set_halt) (struct usb_ep *ep, int value);
|
||||||
|
int (*set_wedge)(struct usb_ep *ep);
|
||||||
int (*fifo_status) (struct usb_ep *ep);
|
int (*fifo_status) (struct usb_ep *ep);
|
||||||
void (*fifo_flush) (struct usb_ep *ep);
|
void (*fifo_flush) (struct usb_ep *ep);
|
||||||
};
|
};
|
||||||
|
@ -133,8 +136,18 @@ struct usb_ep_ops {
|
||||||
* @maxpacket:The maximum packet size used on this endpoint. The initial
|
* @maxpacket:The maximum packet size used on this endpoint. The initial
|
||||||
* value can sometimes be reduced (hardware allowing), according to
|
* value can sometimes be reduced (hardware allowing), according to
|
||||||
* the endpoint descriptor used to configure the endpoint.
|
* the endpoint descriptor used to configure the endpoint.
|
||||||
|
* @maxpacket_limit:The maximum packet size value which can be handled by this
|
||||||
|
* endpoint. It's set once by UDC driver when endpoint is initialized, and
|
||||||
|
* should not be changed. Should not be confused with maxpacket.
|
||||||
|
* @max_streams: The maximum number of streams supported
|
||||||
|
* by this EP (0 - 16, actual number is 2^n)
|
||||||
|
* @maxburst: the maximum number of bursts supported by this EP (for usb3)
|
||||||
* @driver_data:for use by the gadget driver. all other fields are
|
* @driver_data:for use by the gadget driver. all other fields are
|
||||||
* read-only to gadget drivers.
|
* read-only to gadget drivers.
|
||||||
|
* @desc: endpoint descriptor. This pointer is set before the endpoint is
|
||||||
|
* enabled and remains valid until the endpoint is disabled.
|
||||||
|
* @comp_desc: In case of SuperSpeed support, this is the endpoint companion
|
||||||
|
* descriptor that is used to configure the endpoint
|
||||||
*
|
*
|
||||||
* the bus controller driver lists all the general purpose endpoints in
|
* the bus controller driver lists all the general purpose endpoints in
|
||||||
* gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
|
* gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
|
||||||
|
@ -146,10 +159,30 @@ struct usb_ep {
|
||||||
const struct usb_ep_ops *ops;
|
const struct usb_ep_ops *ops;
|
||||||
struct list_head ep_list;
|
struct list_head ep_list;
|
||||||
unsigned maxpacket:16;
|
unsigned maxpacket:16;
|
||||||
|
unsigned maxpacket_limit:16;
|
||||||
|
unsigned max_streams:16;
|
||||||
|
unsigned maxburst:5;
|
||||||
|
const struct usb_endpoint_descriptor *desc;
|
||||||
|
const struct usb_ss_ep_comp_descriptor *comp_desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_ep_set_maxpacket_limit - set maximum packet size limit for endpoint
|
||||||
|
* @ep:the endpoint being configured
|
||||||
|
* @maxpacket_limit:value of maximum packet size limit
|
||||||
|
*
|
||||||
|
* This function shoud be used only in UDC drivers to initialize endpoint
|
||||||
|
* (usually in probe function).
|
||||||
|
*/
|
||||||
|
static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
|
||||||
|
unsigned maxpacket_limit)
|
||||||
|
{
|
||||||
|
ep->maxpacket_limit = maxpacket_limit;
|
||||||
|
ep->maxpacket = maxpacket_limit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* usb_ep_enable - configure endpoint, making it usable
|
* usb_ep_enable - configure endpoint, making it usable
|
||||||
* @ep:the endpoint being configured. may not be the endpoint named "ep0".
|
* @ep:the endpoint being configured. may not be the endpoint named "ep0".
|
||||||
|
@ -422,6 +455,8 @@ struct usb_gadget_ops {
|
||||||
* driver setup() requests
|
* driver setup() requests
|
||||||
* @ep_list: List of other endpoints supported by the device.
|
* @ep_list: List of other endpoints supported by the device.
|
||||||
* @speed: Speed of current connection to USB host.
|
* @speed: Speed of current connection to USB host.
|
||||||
|
* @max_speed: Maximal speed the UDC can handle. UDC must support this
|
||||||
|
* and all slower speeds.
|
||||||
* @is_dualspeed: true if the controller supports both high and full speed
|
* @is_dualspeed: true if the controller supports both high and full speed
|
||||||
* operation. If it does, the gadget driver must also support both.
|
* operation. If it does, the gadget driver must also support both.
|
||||||
* @is_otg: true if the USB device port uses a Mini-AB jack, so that the
|
* @is_otg: true if the USB device port uses a Mini-AB jack, so that the
|
||||||
|
@ -438,6 +473,8 @@ struct usb_gadget_ops {
|
||||||
* @name: Identifies the controller hardware type. Used in diagnostics
|
* @name: Identifies the controller hardware type. Used in diagnostics
|
||||||
* and sometimes configuration.
|
* and sometimes configuration.
|
||||||
* @dev: Driver model state for this abstract device.
|
* @dev: Driver model state for this abstract device.
|
||||||
|
* @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
|
||||||
|
* MaxPacketSize.
|
||||||
*
|
*
|
||||||
* Gadgets have a mostly-portable "gadget driver" implementing device
|
* Gadgets have a mostly-portable "gadget driver" implementing device
|
||||||
* functions, handling all usb configurations and interfaces. Gadget
|
* functions, handling all usb configurations and interfaces. Gadget
|
||||||
|
@ -463,6 +500,7 @@ struct usb_gadget {
|
||||||
struct usb_ep *ep0;
|
struct usb_ep *ep0;
|
||||||
struct list_head ep_list; /* of usb_ep */
|
struct list_head ep_list; /* of usb_ep */
|
||||||
enum usb_device_speed speed;
|
enum usb_device_speed speed;
|
||||||
|
enum usb_device_speed max_speed;
|
||||||
enum usb_device_state state;
|
enum usb_device_state state;
|
||||||
unsigned is_dualspeed:1;
|
unsigned is_dualspeed:1;
|
||||||
unsigned is_otg:1;
|
unsigned is_otg:1;
|
||||||
|
@ -472,6 +510,7 @@ struct usb_gadget {
|
||||||
unsigned a_alt_hnp_support:1;
|
unsigned a_alt_hnp_support:1;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct device dev;
|
struct device dev;
|
||||||
|
unsigned quirk_ep_out_aligned_size:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
|
static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
|
||||||
|
|
Loading…
Add table
Reference in a new issue