This merge is rather big. Here's what it contains:

For am5536udc we have just simple coding style fixes. Nothing that has any
 potential to cause any issues going forward.
 
 With mv_udc, there's only one single change removing an unneeded NULL check.
 
 at91_udc also only saw a single change this merge window, and that's only
 removing a duplicated header.
 
 The Renesas controller has a few more involved changes. Support for SUDMAC was
 added, there's now a special handling of IRQ resources for when the IRQ line is
 shared between Renesas controller and SUDMAC, we also had a bug fix where
 Renesas controller would sleep in atomic context while doing DMA transfers from
 a tasklet. There were also a set of minor cleanups.
 
 The FSL UDC also had a scheduling in atomic context bug fix, but that's all.
 
 Thanks to Sebastian, the dummy_hcd now works better than ever with support for
 scatterlists and streams. Sebastian also added SuperSpeed descriptors to the
 serial gadgets.
 
 The highlight on this merge is the addition of a generic API for mapping and
 unmapping usb_requests. This will avoid code duplication on all UDC controllers
 and also kills all the defines for DMA_ADDR_INVALID which UDC controllers
 sprinkled around. A few of the UDC controllers were already converted to use
 this new API.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPTeaWAAoJEIaOsuA1yqREdT8QAK8ob6RqnZs9en7NdaBTq18G
 qPtdheAZ9TkWxv+JE69Nqq1DuLO93+ZqLt88kaIVp/jTg+MxZ4qeANe9Nga0Qr+U
 Qc4d9HOkKsLGC+E45TApAMCQkPZ3DxbObJRUeJI7DBefPJ+MzQYAeeQtzjEeKKf8
 hGY5kh5FdXds/TlTePwWuyVoe09grgoy7cvptIVJRZiWx8+n9PZeMiKe+vAmQDEc
 +V0FfOMZLcSY9Oi14faYDrOFIV5cjBxnwnBpinOYx5TArxep35HSynt/mJtW2a7/
 lcdpbS4Hn35LJQWcYl0onx0GNgvI/YDYg9V6vrSjoBVU7vZ/7slZ896yjiovmAsc
 KQXxKoqss80sd+rYUe/si/Ues+koN9HztucG//+9cuS2ZCnDydHMJHonMBXUZguv
 o2gzQwjRCUOcGLj+vnSAFiBAGZwAZV99rA2VgIz3dSyegDN+SverXJscOuvzzW/V
 6yERLjbmxwtIQczlUMPQgGE9gSMYKRzyDV4JlO1xtfsBwcVc0c4YE+ZnWOeEAbOa
 evrI/3RGjP12rY+eyntlN2ZpHq2ZJnS7guDjooi0mGK16LWeQh8h0zD24XoUiwnr
 nhkv+eqWJQXV2iQcyezO1TLnxhZ7LZdtfkYg5MH/VqGIuh6SNQdhew4bijUuKKsq
 +aLPREySYHdIloQjPBe/
 =RR+f
 -----END PGP SIGNATURE-----

Merge tag 'gadget-for-v3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

USB: Gadget: changes for 3.4

This merge is rather big. Here's what it contains:

For am5536udc we have just simple coding style fixes. Nothing that has any
potential to cause any issues going forward.

With mv_udc, there's only one single change removing an unneeded NULL check.

at91_udc also only saw a single change this merge window, and that's only
removing a duplicated header.

The Renesas controller has a few more involved changes. Support for SUDMAC was
added, there's now a special handling of IRQ resources for when the IRQ line is
shared between Renesas controller and SUDMAC, we also had a bug fix where
Renesas controller would sleep in atomic context while doing DMA transfers from
a tasklet. There were also a set of minor cleanups.

The FSL UDC also had a scheduling in atomic context bug fix, but that's all.

Thanks to Sebastian, the dummy_hcd now works better than ever with support for
scatterlists and streams. Sebastian also added SuperSpeed descriptors to the
serial gadgets.

The highlight on this merge is the addition of a generic API for mapping and
unmapping usb_requests. This will avoid code duplication on all UDC controllers
and also kills all the defines for DMA_ADDR_INVALID which UDC controllers
sprinkled around. A few of the UDC controllers were already converted to use
this new API.

Conflicts:
	drivers/usb/dwc3/gadget.c
This commit is contained in:
Greg Kroah-Hartman 2012-03-01 09:20:28 -08:00
commit f9b0f51709
52 changed files with 2736 additions and 689 deletions

View File

@ -572,7 +572,6 @@ struct dwc3_request {
* @ctrl_req_addr: dma address of ctrl_req
* @ep0_trb: dma address of ep0_trb
* @ep0_usb_req: dummy req used while handling STD USB requests
* @setup_buf_addr: dma address of setup_buf
* @ep0_bounce_addr: dma address of ep0_bounce
* @lock: for synchronizing
* @dev: pointer to our struct device
@ -609,7 +608,6 @@ struct dwc3 {
u8 *setup_buf;
dma_addr_t ctrl_req_addr;
dma_addr_t ep0_trb_addr;
dma_addr_t setup_buf_addr;
dma_addr_t ep0_bounce_addr;
struct dwc3_request ep0_usb_req;
/* device lock */

View File

@ -302,7 +302,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr;
dwc->ep0_usb_req.request.buf = dwc->setup_buf;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@ -679,7 +679,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
DWC3_TRBCTL_CONTROL_DATA);
} else if ((req->request.length % dep->endpoint.maxpacket)
&& (event->endpoint_number == 0)) {
dwc3_map_buffer_to_dma(req);
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
event->endpoint_number);
if (ret) {
dev_dbg(dwc->dev, "failed to map request\n");
return;
}
WARN_ON(req->request.length > dep->endpoint.maxpacket);
@ -694,7 +699,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
dwc->ep0_bounce_addr, dep->endpoint.maxpacket,
DWC3_TRBCTL_CONTROL_DATA);
} else {
dwc3_map_buffer_to_dma(req);
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
event->endpoint_number);
if (ret) {
dev_dbg(dwc->dev, "failed to map request\n");
return;
}
ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
req->request.dma, req->request.length,

View File

@ -54,70 +54,6 @@
#include "gadget.h"
#include "io.h"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
void dwc3_map_buffer_to_dma(struct dwc3_request *req)
{
struct dwc3 *dwc = req->dep->dwc;
if (req->request.length == 0) {
/* req->request.dma = dwc->setup_buf_addr; */
return;
}
if (req->request.num_sgs) {
int mapped;
mapped = dma_map_sg(dwc->dev, req->request.sg,
req->request.num_sgs,
req->direction ? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
if (mapped < 0) {
dev_err(dwc->dev, "failed to map SGs\n");
return;
}
req->request.num_mapped_sgs = mapped;
return;
}
if (req->request.dma == DMA_ADDR_INVALID) {
req->request.dma = dma_map_single(dwc->dev, req->request.buf,
req->request.length, req->direction
? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = true;
}
}
void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
{
struct dwc3 *dwc = req->dep->dwc;
if (req->request.length == 0) {
req->request.dma = DMA_ADDR_INVALID;
return;
}
if (req->request.num_mapped_sgs) {
req->request.dma = DMA_ADDR_INVALID;
dma_unmap_sg(dwc->dev, req->request.sg,
req->request.num_mapped_sgs,
req->direction ? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->request.num_mapped_sgs = 0;
return;
}
if (req->mapped) {
dma_unmap_single(dwc->dev, req->request.dma,
req->request.length, req->direction
? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 0;
req->request.dma = DMA_ADDR_INVALID;
}
}
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status)
{
@ -144,14 +80,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
if (req->request.status == -EINPROGRESS)
req->request.status = status;
dwc3_unmap_buffer_from_dma(req);
usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
req, dep->name, req->request.actual,
req->request.length, status);
spin_unlock(&dwc->lock);
req->request.complete(&req->dep->endpoint, &req->request);
req->request.complete(&dep->endpoint, &req->request);
spin_lock(&dwc->lock);
}
@ -440,6 +377,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->stream_capable = false;
dep->desc = NULL;
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
dep->flags = 0;
@ -562,7 +500,6 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
req->epnum = dep->number;
req->dep = dep;
req->request.dma = DMA_ADDR_INVALID;
return &req->request;
}
@ -821,7 +758,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
* here and stop, unmap, free and del each of the linked
* requests instead of we do now.
*/
dwc3_unmap_buffer_from_dma(req);
usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
list_del(&req->list);
return ret;
}
@ -837,6 +775,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
int ret;
req->request.actual = 0;
req->request.status = -EINPROGRESS;
req->direction = dep->direction;
@ -854,7 +795,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
* This will also avoid Host cancelling URBs due to too
* many NACKs.
*/
dwc3_map_buffer_to_dma(req);
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->direction);
if (ret)
return ret;
list_add_tail(&req->list, &dep->request_list);
/*
@ -2149,9 +2094,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
dwc->setup_buf = dma_alloc_coherent(dwc->dev,
sizeof(*dwc->setup_buf) * 2,
&dwc->setup_buf_addr, GFP_KERNEL);
dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2,
GFP_KERNEL);
if (!dwc->setup_buf) {
dev_err(dwc->dev, "failed to allocate setup buffer\n");
ret = -ENOMEM;
@ -2242,8 +2186,7 @@ err4:
dwc->ep0_bounce_addr);
err3:
dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
dwc->setup_buf, dwc->setup_buf_addr);
kfree(dwc->setup_buf);
err2:
dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
@ -2272,8 +2215,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
dwc->ep0_bounce_addr);
dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
dwc->setup_buf, dwc->setup_buf_addr);
kfree(dwc->setup_buf);
dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
dwc->ep0_trb, dwc->ep0_trb_addr);

View File

@ -108,8 +108,6 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
void dwc3_map_buffer_to_dma(struct dwc3_request *req);
void dwc3_unmap_buffer_from_dma(struct dwc3_request *req);
/**
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW

View File

@ -599,16 +599,29 @@ config USB_AUDIO
depends on SND
select SND_PCM
help
Gadget Audio is compatible with USB Audio Class specification 1.0.
It will include at least one AudioControl interface, zero or more
AudioStream interface and zero or more MIDIStream interface.
Gadget Audio will use on-board ALSA (CONFIG_SND) audio card to
playback or capture audio stream.
This Gadget Audio driver is compatible with USB Audio Class
specification 2.0. It implements 1 AudioControl interface,
1 AudioStreaming Interface each for USB-OUT and USB-IN.
Number of channels, sample rate and sample size can be
specified as module parameters.
This driver doesn't expect any real Audio codec to be present
on the device - the audio streams are simply sinked to and
sourced from a virtual ALSA sound card created. The user-space
application may choose to do whatever it wants with the data
received from the USB Host and choose to provide whatever it
wants as audio data to the USB Host.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_audio".
config GADGET_UAC1
bool "UAC 1.0 (Legacy)"
depends on USB_AUDIO
help
If you instead want older UAC Spec-1.0 driver that also has audio
paths hardwired to the Audio codec chip on-board and doesn't work
without one.
config USB_ETH
tristate "Ethernet Gadget (with CDC Ethernet support)"
depends on NET

View File

@ -29,7 +29,7 @@
/* Driver strings */
#define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller"
#define UDC_DRIVER_VERSION_STRING "01.00.0206 - $Revision: #3 $"
#define UDC_DRIVER_VERSION_STRING "01.00.0206"
/* system */
#include <linux/module.h>
@ -140,7 +140,7 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
/* endpoint names used for print */
static const char ep0_string[] = "ep0in";
static const char *ep_string[] = {
static const char *const ep_string[] = {
ep0_string,
"ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
"ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
@ -204,9 +204,8 @@ static void print_regs(struct udc *dev)
DBG(dev, "DMA mode = BF (buffer fill mode)\n");
dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
}
if (!use_dma) {
if (!use_dma)
dev_info(&dev->pdev->dev, "FIFO mode\n");
}
DBG(dev, "-------------------------------------------------------\n");
}
@ -445,6 +444,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
VDBG(ep->dev, "ep-%d reset\n", ep->num);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->ep.ops = &udc_ep_ops;
INIT_LIST_HEAD(&ep->queue);
@ -569,9 +569,8 @@ udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
/* free dma chain if created */
if (req->chain_len > 1) {
if (req->chain_len > 1)
udc_free_dma_chain(ep->dev, req);
}
pci_pool_free(ep->dev->data_requests, req->td_data,
req->td_phys);
@ -639,9 +638,8 @@ udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
bytes = remaining;
/* dwords first */
for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
writel(*(buf + i), ep->txfifo);
}
/* remaining bytes must be written by byte access */
for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
@ -660,9 +658,8 @@ static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
for (i = 0; i < dwords; i++) {
for (i = 0; i < dwords; i++)
*(buf + i) = readl(dev->rxfifo);
}
return 0;
}
@ -675,9 +672,8 @@ static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
/* dwords first */
for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
*((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
}
/* remaining bytes must be read by byte access */
if (bytes % UDC_DWORD_BYTES) {
@ -831,20 +827,8 @@ __acquires(ep->dev->lock)
dev = ep->dev;
/* unmap DMA */
if (req->dma_mapping) {
if (ep->in)
pci_unmap_single(dev->pdev,
req->req.dma,
req->req.length,
PCI_DMA_TODEVICE);
else
pci_unmap_single(dev->pdev,
req->req.dma,
req->req.length,
PCI_DMA_FROMDEVICE);
req->dma_mapping = 0;
req->req.dma = DMA_DONT_USE;
}
if (ep->dma)
usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in);
halted = ep->halted;
ep->halted = 1;
@ -897,9 +881,8 @@ static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
struct udc_data_dma *td;
td = req->td_data;
while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L)))
td = phys_to_virt(td->next);
}
return td;
@ -949,21 +932,18 @@ static int udc_create_dma_chain(
dma_addr = DMA_DONT_USE;
/* unset L bit in first desc for OUT */
if (!ep->in) {
if (!ep->in)
req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
}
/* alloc only new desc's if not already available */
len = req->req.length / ep->ep.maxpacket;
if (req->req.length % ep->ep.maxpacket) {
if (req->req.length % ep->ep.maxpacket)
len++;
}
if (len > req->chain_len) {
/* shorter chain already allocated before */
if (req->chain_len > 1) {
if (req->chain_len > 1)
udc_free_dma_chain(ep->dev, req);
}
req->chain_len = len;
create_new_chain = 1;
}
@ -1006,11 +986,12 @@ static int udc_create_dma_chain(
/* link td and assign tx bytes */
if (i == buf_len) {
if (create_new_chain) {
if (create_new_chain)
req->td_data->next = dma_addr;
} else {
/* req->td_data->next = virt_to_phys(td); */
}
/*
else
req->td_data->next = virt_to_phys(td);
*/
/* write tx bytes */
if (ep->in) {
/* first desc */
@ -1024,11 +1005,12 @@ static int udc_create_dma_chain(
UDC_DMA_IN_STS_TXBYTES);
}
} else {
if (create_new_chain) {
if (create_new_chain)
last->next = dma_addr;
} else {
/* last->next = virt_to_phys(td); */
}
/*
else
last->next = virt_to_phys(td);
*/
if (ep->in) {
/* write tx bytes */
td->status = AMD_ADDBITS(td->status,
@ -1095,20 +1077,11 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
return -ESHUTDOWN;
/* map dma (usually done before) */
if (ep->dma && usbreq->length != 0
&& (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) {
if (ep->dma) {
VDBG(dev, "DMA map req %p\n", req);
if (ep->in)
usbreq->dma = pci_map_single(dev->pdev,
usbreq->buf,
usbreq->length,
PCI_DMA_TODEVICE);
else
usbreq->dma = pci_map_single(dev->pdev,
usbreq->buf,
usbreq->length,
PCI_DMA_FROMDEVICE);
req->dma_mapping = 1;
retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in);
if (retval)
return retval;
}
VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",
@ -1479,11 +1452,10 @@ static int startup_registers(struct udc *dev)
/* program speed */
tmp = readl(&dev->regs->cfg);
if (use_fullspeed) {
if (use_fullspeed)
tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
} else {
else
tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
}
writel(tmp, &dev->regs->cfg);
return 0;
@ -1504,9 +1476,8 @@ static void udc_basic_init(struct udc *dev)
mod_timer(&udc_timer, jiffies - 1);
}
/* stop poll stall timer */
if (timer_pending(&udc_pollstall_timer)) {
if (timer_pending(&udc_pollstall_timer))
mod_timer(&udc_pollstall_timer, jiffies - 1);
}
/* disable DMA */
tmp = readl(&dev->regs->ctl);
tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
@ -1540,11 +1511,10 @@ static void udc_setup_endpoints(struct udc *dev)
/* read enum speed */
tmp = readl(&dev->regs->sts);
tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) {
if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH)
dev->gadget.speed = USB_SPEED_HIGH;
} else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) {
else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL)
dev->gadget.speed = USB_SPEED_FULL;
}
/* set basic ep parameters */
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
@ -1570,9 +1540,8 @@ static void udc_setup_endpoints(struct udc *dev)
* disabling ep interrupts when ENUM interrupt occurs but ep is
* not enabled by gadget driver
*/
if (!ep->desc) {
if (!ep->desc)
ep_init(dev->regs, ep);
}
if (use_dma) {
/*
@ -1670,9 +1639,8 @@ static void udc_tasklet_disconnect(unsigned long par)
spin_lock(&dev->lock);
/* empty queues */
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
empty_req_queue(&dev->ep[tmp]);
}
}
@ -1746,9 +1714,8 @@ static void udc_timer_function(unsigned long v)
* open the fifo
*/
udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
if (!stop_timer) {
if (!stop_timer)
add_timer(&udc_timer);
}
} else {
/*
* fifo contains data now, setup timer for opening
@ -1760,9 +1727,8 @@ static void udc_timer_function(unsigned long v)
set_rde++;
/* debug: lhadmot_timer_start = 221070 */
udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
if (!stop_timer) {
if (!stop_timer)
add_timer(&udc_timer);
}
}
} else
@ -1907,19 +1873,17 @@ static void activate_control_endpoints(struct udc *dev)
mod_timer(&udc_timer, jiffies - 1);
}
/* stop pollstall timer */
if (timer_pending(&udc_pollstall_timer)) {
if (timer_pending(&udc_pollstall_timer))
mod_timer(&udc_pollstall_timer, jiffies - 1);
}
/* enable DMA */
tmp = readl(&dev->regs->ctl);
tmp |= AMD_BIT(UDC_DEVCTL_MODE)
| AMD_BIT(UDC_DEVCTL_RDE)
| AMD_BIT(UDC_DEVCTL_TDE);
if (use_dma_bufferfill_mode) {
if (use_dma_bufferfill_mode)
tmp |= AMD_BIT(UDC_DEVCTL_BF);
} else if (use_dma_ppb_du) {
else if (use_dma_ppb_du)
tmp |= AMD_BIT(UDC_DEVCTL_DU);
}
writel(tmp, &dev->regs->ctl);
}
@ -2104,9 +2068,8 @@ static void udc_ep0_set_rde(struct udc *dev)
udc_timer.expires =
jiffies + HZ/UDC_RDE_TIMER_DIV;
set_rde = 1;
if (!stop_timer) {
if (!stop_timer)
add_timer(&udc_timer);
}
}
}
}
@ -2131,7 +2094,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
if (use_dma) {
/* BNA event ? */
if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
DBG(dev, "BNA ep%dout occurred - DESPTR = %x \n",
DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n",
ep->num, readl(&ep->regs->desptr));
/* clear BNA */
writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
@ -2294,9 +2257,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
jiffies
+ HZ*UDC_RDE_TIMER_SECONDS;
set_rde = 1;
if (!stop_timer) {
if (!stop_timer)
add_timer(&udc_timer);
}
}
if (ep->num != UDC_EP0OUT_IX)
dev->data_ep_queued = 0;
@ -2318,9 +2280,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
/* check pending CNAKS */
if (cnak_pending) {
/* CNAk processing when rxfifo empty only */
if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
udc_process_cnak_queue(dev);
}
}
/* clear OUT bits in ep status */
@ -2348,7 +2309,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
/* BNA ? */
if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
dev_err(&dev->pdev->dev,
"BNA ep%din occurred - DESPTR = %08lx \n",
"BNA ep%din occurred - DESPTR = %08lx\n",
ep->num,
(unsigned long) readl(&ep->regs->desptr));
@ -2361,7 +2322,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
/* HE event ? */
if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
dev_err(&dev->pdev->dev,
"HE ep%dn occurred - DESPTR = %08lx \n",
"HE ep%dn occurred - DESPTR = %08lx\n",
ep->num, (unsigned long) readl(&ep->regs->desptr));
/* clear HE */
@ -2427,9 +2388,9 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
/* write fifo */
udc_txfifo_write(ep, &req->req);
len = req->req.length - req->req.actual;
if (len > ep->ep.maxpacket)
len = ep->ep.maxpacket;
req->req.actual += len;
if (len > ep->ep.maxpacket)
len = ep->ep.maxpacket;
req->req.actual += len;
if (req->req.actual == req->req.length
|| (len != ep->ep.maxpacket)) {
/* complete req */
@ -2581,9 +2542,8 @@ __acquires(dev->lock)
if (!timer_pending(&udc_timer)) {
udc_timer.expires = jiffies +
HZ/UDC_RDE_TIMER_DIV;
if (!stop_timer) {
if (!stop_timer)
add_timer(&udc_timer);
}
}
}
@ -2697,9 +2657,8 @@ __acquires(dev->lock)
/* check pending CNAKS */
if (cnak_pending) {
/* CNAk processing when rxfifo empty only */
if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
udc_process_cnak_queue(dev);
}
}
finished:
@ -2723,7 +2682,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev)
tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
/* DMA completion */
if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
VDBG(dev, "isr: TDC clear \n");
VDBG(dev, "isr: TDC clear\n");
ret_val = IRQ_HANDLED;
/* clear TDC bit */
@ -3426,7 +3385,7 @@ static int udc_remote_wakeup(struct udc *dev)
}
/* PCI device parameters */
static const struct pci_device_id pci_id[] = {
static DEFINE_PCI_DEVICE_TABLE(pci_id) = {
{
PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,

View File

@ -29,7 +29,6 @@
#include <linux/clk.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h>
#include <mach/hardware.h>
@ -558,6 +557,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
/* restore the endpoint's pristine config */
ep->desc = NULL;
ep->ep.desc = NULL;
ep->ep.maxpacket = ep->maxpacket;
/* reset fifos and endpoint */

View File

@ -659,6 +659,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
return -EINVAL;
}
ep->desc = NULL;
ep->ep.desc = NULL;
list_splice_init(&ep->queue, &req_list);
if (ep->can_dma) {

View File

@ -14,10 +14,8 @@
#include <linux/kernel.h>
#include <linux/utsname.h>
#include "u_audio.h"
#define DRIVER_DESC "Linux USB Audio Gadget"
#define DRIVER_VERSION "Dec 18, 2008"
#define DRIVER_VERSION "Feb 2, 2012"
/*-------------------------------------------------------------------------*/
@ -33,8 +31,36 @@
#include "config.c"
#include "epautoconf.c"
#include "u_audio.c"
#include "f_audio.c"
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[STRING_MANUFACTURER_IDX].s = manufacturer,
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *audio_strings[] = {
&stringtab_dev,
NULL,
};
#ifdef CONFIG_GADGET_UAC1
#include "u_uac1.h"
#include "u_uac1.c"
#include "f_uac1.c"
#else
#include "f_uac2.c"
#endif
/*-------------------------------------------------------------------------*/
@ -54,9 +80,15 @@ static struct usb_device_descriptor device_desc = {
.bcdUSB = __constant_cpu_to_le16(0x200),
#ifdef CONFIG_GADGET_UAC1
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
#else
.bDeviceClass = USB_CLASS_MISC,
.bDeviceSubClass = 0x02,
.bDeviceProtocol = 0x01,
#endif
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id defaults change according to what configs
@ -108,6 +140,9 @@ static struct usb_configuration audio_config_driver = {
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
#ifndef CONFIG_GADGET_UAC1
.unbind = uac2_unbind_config,
#endif
};
/*-------------------------------------------------------------------------*/
@ -157,7 +192,9 @@ fail:
static int __exit audio_unbind(struct usb_composite_dev *cdev)
{
#ifdef CONFIG_GADGET_UAC1
gaudio_cleanup();
#endif
return 0;
}

View File

@ -2181,6 +2181,7 @@ static int ep_disable(struct usb_ep *ep)
} while (mEp->dir != direction);
mEp->desc = NULL;
mEp->ep.desc = NULL;
spin_unlock_irqrestore(mEp->lock, flags);
return retval;

File diff suppressed because it is too large Load Diff

View File

@ -275,24 +275,24 @@ struct usb_ep *usb_ep_autoconfig_ss(
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep (gadget, "ep-e");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
goto found_ep;
ep = find_ep (gadget, "ep-f");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
goto found_ep;
} else if (gadget_is_goku (gadget)) {
if (USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough */
ep = find_ep(gadget, "ep3-bulk");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
goto found_ep;
} else if (USB_ENDPOINT_XFER_BULK == type
&& (USB_DIR_IN & desc->bEndpointAddress)) {
/* DMA may be available */
ep = find_ep(gadget, "ep2-bulk");
if (ep && ep_matches(gadget, ep, desc,
ep_comp))
return ep;
goto found_ep;
}
#ifdef CONFIG_BLACKFIN
@ -311,18 +311,22 @@ struct usb_ep *usb_ep_autoconfig_ss(
} else
ep = NULL;
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
goto found_ep;
#endif
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (ep_matches(gadget, ep, desc, ep_comp))
return ep;
goto found_ep;
}
/* Fail */
return NULL;
found_ep:
ep->desc = NULL;
ep->comp_desc = NULL;
return ep;
}
/**

View File

@ -5,7 +5,7 @@
* Copyright (C) 2008 by David Brownell
* Copyright (C) 2008 by Nokia Corporation
* Copyright (C) 2009 by Samsung Electronics
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
* Author: Michal Nazarewicz (mina86@mina86.com)
*
* This software is distributed under the terms of the GNU General
* Public License ("GPL") as published by the Free Software Foundation,
@ -237,6 +237,42 @@ static struct usb_descriptor_header *acm_hs_function[] = {
NULL,
};
static struct usb_endpoint_descriptor acm_ss_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor acm_ss_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = {
.bLength = sizeof acm_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
static struct usb_descriptor_header *acm_ss_function[] = {
(struct usb_descriptor_header *) &acm_iad_descriptor,
(struct usb_descriptor_header *) &acm_control_interface_desc,
(struct usb_descriptor_header *) &acm_header_desc,
(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
(struct usb_descriptor_header *) &acm_descriptor,
(struct usb_descriptor_header *) &acm_union_desc,
(struct usb_descriptor_header *) &acm_hs_notify_desc,
(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &acm_data_interface_desc,
(struct usb_descriptor_header *) &acm_ss_in_desc,
(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &acm_ss_out_desc,
(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
NULL,
};
/* string descriptors: */
#define ACM_CTRL_IDX 0
@ -643,9 +679,21 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors */
f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
}
if (gadget_is_superspeed(c->cdev->gadget)) {
acm_ss_in_desc.bEndpointAddress =
acm_fs_in_desc.bEndpointAddress;
acm_ss_out_desc.bEndpointAddress =
acm_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
if (!f->ss_descriptors)
goto fail;
}
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
acm->port.in->name, acm->port.out->name,
acm->notify->name);
@ -675,6 +723,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);

View File

@ -97,6 +97,20 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
/* interface descriptor: */
static struct usb_interface_assoc_descriptor
ecm_iad_descriptor = {
.bLength = sizeof ecm_iad_descriptor,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
/* .bFirstInterface = DYNAMIC, */
.bInterfaceCount = 2, /* control + data */
.bFunctionClass = USB_CLASS_COMM,
.bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET,
.bFunctionProtocol = USB_CDC_PROTO_NONE,
/* .iFunction = DYNAMIC */
};
static struct usb_interface_descriptor ecm_control_intf = {
.bLength = sizeof ecm_control_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -199,6 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc = {
static struct usb_descriptor_header *ecm_fs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_iad_descriptor,
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
@ -247,6 +262,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc = {
static struct usb_descriptor_header *ecm_hs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_iad_descriptor,
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
@ -339,6 +355,7 @@ static struct usb_string ecm_string_defs[] = {
[0].s = "CDC Ethernet Control Model (ECM)",
[1].s = NULL /* DYNAMIC */,
[2].s = "CDC Ethernet Data",
[3].s = "CDC ECM",
{ } /* end of list */
};
@ -674,6 +691,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (status < 0)
goto fail;
ecm->ctrl_id = status;
ecm_iad_descriptor.bFirstInterface = status;
ecm_control_intf.bInterfaceNumber = status;
ecm_union_desc.bMasterInterface0 = status;
@ -864,6 +882,13 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
return status;
ecm_string_defs[1].id = status;
ecm_desc.iMACAddress = status;
/* IAD label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ecm_string_defs[3].id = status;
ecm_iad_descriptor.iFunction = status;
}
/* allocate and initialize one new instance */

View File

@ -2,7 +2,7 @@
* f_fs.c -- user mode file system API for USB composite function controllers
*
* Copyright (C) 2010 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
*
* Based on inode.c (GadgetFS) which was:
* Copyright (C) 2003-2004 David Brownell

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2003-2008 Alan Stern
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -304,7 +304,6 @@
static const char fsg_string_interface[] = "Mass Storage";
#define FSG_NO_INTR_EP 1
#define FSG_NO_DEVICE_STRINGS 1
#define FSG_NO_OTG 1
#define FSG_NO_INTR_EP 1

View File

@ -5,7 +5,7 @@
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
* Author: Michal Nazarewicz (mina86@mina86.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -99,6 +99,34 @@ static struct usb_descriptor_header *gser_hs_function[] __initdata = {
NULL,
};
static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
.bLength = sizeof gser_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
static struct usb_descriptor_header *gser_ss_function[] __initdata = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &gser_ss_out_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
NULL,
};
/* string descriptors: */
static struct usb_string gser_string_defs[] = {
@ -201,9 +229,21 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
}
if (gadget_is_superspeed(c->cdev->gadget)) {
gser_ss_in_desc.bEndpointAddress =
gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
if (!f->ss_descriptors)
goto fail;
}
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
gser->port.in->name, gser->port.out->name);
return 0;
@ -225,6 +265,8 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f)
{
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
kfree(func_to_gser(f));
}

View File

@ -14,7 +14,7 @@
#include <linux/device.h>
#include <linux/atomic.h>
#include "u_audio.h"
#include "u_uac1.h"
#define OUT_EP_MAX_PACKET_SIZE 200
static int req_buf_size = OUT_EP_MAX_PACKET_SIZE;
@ -216,29 +216,6 @@ static struct usb_descriptor_header *f_audio_desc[] __initdata = {
NULL,
};
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[STRING_MANUFACTURER_IDX].s = manufacturer,
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *audio_strings[] = {
&stringtab_dev,
NULL,
};
/*
* This function is an ALSA sound card following USB Audio Class Spec 1.0.
*/

1449
drivers/usb/gadget/f_uac2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1638,6 +1638,7 @@ static int qe_ep_disable(struct usb_ep *_ep)
/* Nuke all pending requests (does flush) */
nuke(ep, -ESHUTDOWN);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
ep->tx_req = NULL;
qe_ep_reset(udc, ep->epnum);

View File

@ -659,6 +659,7 @@ static int fsl_ep_disable(struct usb_ep *_ep)
nuke(ep, -ESHUTDOWN);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
spin_unlock_irqrestore(&udc->lock, flags);
@ -768,7 +769,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
* @is_last: return flag if it is the last dTD of the request
* return: pointer to the built dTD */
static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
dma_addr_t *dma, int *is_last)
dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
{
u32 swap_temp;
struct ep_td_struct *dtd;
@ -777,7 +778,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
*length = min(req->req.length - req->req.actual,
(unsigned)EP_MAX_LENGTH_TRANSFER);
dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
if (dtd == NULL)
return dtd;
@ -827,7 +828,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
}
/* Generate dtd chain for a request */
static int fsl_req_to_dtd(struct fsl_req *req)
static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
{
unsigned count;
int is_last;
@ -836,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req *req)
dma_addr_t dma;
do {
dtd = fsl_build_dtd(req, &count, &dma, &is_last);
dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
if (dtd == NULL)
return -ENOMEM;
@ -910,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->req.actual = 0;
req->dtd_count = 0;
spin_lock_irqsave(&udc->lock, flags);
/* build dtds and push them to device queue */
if (!fsl_req_to_dtd(req)) {
if (!fsl_req_to_dtd(req, gfp_flags)) {
spin_lock_irqsave(&udc->lock, flags);
fsl_queue_td(ep, req);
} else {
spin_unlock_irqrestore(&udc->lock, flags);
return -ENOMEM;
}
@ -1295,7 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
if (fsl_req_to_dtd(req) == 0)
if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
fsl_queue_td(ep, req);
else
return -ENOMEM;
@ -1379,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->mapped = 1;
/* prime the data phase */
if ((fsl_req_to_dtd(req) == 0))
if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
fsl_queue_td(ep, req);
else /* no mem */
goto stall;

View File

@ -2,7 +2,7 @@
* g_ffs.c -- user mode file system API for USB composite function controllers
*
* Copyright (C) 2010 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -235,6 +235,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
ep->ep.maxpacket = MAX_FIFO_SIZE;
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
ep->irqs = 0;
ep->dma = 0;
@ -310,12 +311,9 @@ done(struct goku_ep *ep, struct goku_request *req, int status)
status = req->req.status;
dev = ep->dev;
if (req->mapped) {
pci_unmap_single(dev->pdev, req->req.dma, req->req.length,
ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
}
if (ep->dma)
usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
#ifndef USB_TRACE
if (status && status != -ESHUTDOWN)
@ -736,10 +734,11 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -EBUSY;
/* set up dma mapping in case the caller didn't */
if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
_req->dma = pci_map_single(dev->pdev, _req->buf, _req->length,
ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
req->mapped = 1;
if (ep->dma) {
status = usb_gadget_map_request(&dev->gadget, &req->req,
ep->is_in);
if (status)
return status;
}
#ifdef USB_TRACE

View File

@ -401,16 +401,7 @@ static void done(struct langwell_ep *ep, struct langwell_request *req,
dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma);
}
if (req->mapped) {
dma_unmap_single(&dev->pdev->dev,
req->req.dma, req->req.length,
is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else
dma_sync_single_for_cpu(&dev->pdev->dev, req->req.dma,
req->req.length,
is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep));
if (status != -ESHUTDOWN)
dev_dbg(&dev->pdev->dev,
@ -487,6 +478,7 @@ static int langwell_ep_disable(struct usb_ep *_ep)
nuke(ep, -ESHUTDOWN);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
spin_unlock_irqrestore(&dev->lock, flags);
@ -749,7 +741,8 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
struct langwell_ep *ep;
struct langwell_udc *dev;
unsigned long flags;
int is_iso = 0, zlflag = 0;
int is_iso = 0;
int ret;
/* always require a cpu-view buffer */
req = container_of(_req, struct langwell_request, req);
@ -776,33 +769,10 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
return -ESHUTDOWN;
/* set up dma mapping in case the caller didn't */
if (_req->dma == DMA_ADDR_INVALID) {
/* WORKAROUND: WARN_ON(size == 0) */
if (_req->length == 0) {
dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n");
zlflag = 1;
_req->length++;
}
_req->dma = dma_map_single(&dev->pdev->dev,
_req->buf, _req->length,
is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (zlflag && (_req->length == 1)) {
dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n");
zlflag = 0;
_req->length = 0;
}
req->mapped = 1;
dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n");
} else {
dma_sync_single_for_device(&dev->pdev->dev,
_req->dma, _req->length,
is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 0;
dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n");
}
/* set up dma mapping */
ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep));
if (ret)
return ret;
dev_dbg(&dev->pdev->dev,
"%s queue req %p, len %u, buf %p, dma 0x%08x\n",

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2003-2008 Alan Stern
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify

View File

@ -4,7 +4,7 @@
* Copyright (C) 2008 David Brownell
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
* Author: Michal Nazarewicz (mina86@mina86.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -608,6 +608,7 @@ static int mv_ep_disable(struct usb_ep *_ep)
nuke(ep, -ESHUTDOWN);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
spin_unlock_irqrestore(&udc->lock, flags);
@ -771,8 +772,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
udc->ep0_state = DATA_STATE_XMIT;
/* irq handler advances the queue */
if (req != NULL)
list_add_tail(&req->queue, &ep->queue);
list_add_tail(&req->queue, &ep->queue);
spin_unlock_irqrestore(&udc->lock, flags);
return 0;

View File

@ -385,12 +385,9 @@ net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status)
status = req->req.status;
dev = ep->dev;
if (use_dma && req->mapped) {
dma_unmap_single(dev->dev, req->req.dma, req->req.length,
ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
}
if (use_dma && ep->dma)
usb_gadget_unmap_request(&dev->gadget, &req->req,
ep->is_in);
if (status && status != -ESHUTDOWN)
dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
@ -850,10 +847,11 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -ESHUTDOWN;
/* set up dma mapping in case the caller didn't */
if (use_dma && ep->dma && _req->dma == DMA_ADDR_INVALID) {
_req->dma = dma_map_single(dev->dev, _req->buf, _req->length,
ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
if (use_dma && ep->dma) {
status = usb_gadget_map_request(&dev->gadget, _req,
ep->is_in);
if (status)
return status;
}
dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",

View File

@ -806,12 +806,8 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
status = req->req.status;
dev = ep->dev;
if (req->mapped) {
pci_unmap_single (dev->pdev, req->req.dma, req->req.length,
ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
}
if (ep->dma)
usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
if (status && status != -ESHUTDOWN)
VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n",
@ -857,10 +853,13 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -EOPNOTSUPP;
/* set up dma mapping in case the caller didn't */
if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
_req->dma = pci_map_single (dev->pdev, _req->buf, _req->length,
ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
req->mapped = 1;
if (ep->dma) {
int ret;
ret = usb_gadget_map_request(&dev->gadget, _req,
ep->is_in);
if (ret)
return ret;
}
#if 0

View File

@ -251,6 +251,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
spin_lock_irqsave(&ep->udc->lock, flags);
ep->desc = NULL;
ep->ep.desc = NULL;
nuke (ep, -ESHUTDOWN);
ep->ep.maxpacket = ep->maxpacket;
ep->has_dma = 0;

View File

@ -15,6 +15,13 @@
#include <linux/interrupt.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/gpio.h>
/* GPIO port for VBUS detecting */
static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */
#define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */
#define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */
/* Address offset of Registers */
#define UDC_EP_REG_SHIFT 0x20 /* Offset to next EP */
@ -295,6 +302,21 @@ struct pch_udc_ep {
unsigned long epsts;
};
/**
* struct pch_vbus_gpio_data - Structure holding GPIO informaton
* for detecting VBUS
* @port: gpio port number
* @intr: gpio interrupt number
* @irq_work_fall Structure for WorkQueue
* @irq_work_rise Structure for WorkQueue
*/
struct pch_vbus_gpio_data {
int port;
int intr;
struct work_struct irq_work_fall;
struct work_struct irq_work_rise;
};
/**
* struct pch_udc_dev - Structure holding complete information
* of the PCH USB device
@ -311,6 +333,7 @@ struct pch_udc_ep {
* @registered: driver regsitered with system
* @suspended: driver in suspended state
* @connected: gadget driver associated
* @vbus_session: required vbus_session state
* @set_cfg_not_acked: pending acknowledgement 4 setup
* @waiting_zlp_ack: pending acknowledgement 4 ZLP
* @data_requests: DMA pool for data requests
@ -322,6 +345,7 @@ struct pch_udc_ep {
* @base_addr: for mapped device memory
* @irq: IRQ line for the device
* @cfg_data: current cfg, intf, and alt in use
* @vbus_gpio: GPIO informaton for detecting VBUS
*/
struct pch_udc_dev {
struct usb_gadget gadget;
@ -337,6 +361,7 @@ struct pch_udc_dev {
registered:1,
suspended:1,
connected:1,
vbus_session:1,
set_cfg_not_acked:1,
waiting_zlp_ack:1;
struct pci_pool *data_requests;
@ -347,7 +372,8 @@ struct pch_udc_dev {
unsigned long phys_addr;
void __iomem *base_addr;
unsigned irq;
struct pch_udc_cfg_data cfg_data;
struct pch_udc_cfg_data cfg_data;
struct pch_vbus_gpio_data vbus_gpio;
};
#define PCH_UDC_PCI_BAR 1
@ -553,6 +579,29 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
}
/**
* pch_udc_reconnect() - This API initializes usb device controller,
* and clear the disconnect status.
* @dev: Reference to pch_udc_regs structure
*/
static void pch_udc_init(struct pch_udc_dev *dev);
static void pch_udc_reconnect(struct pch_udc_dev *dev)
{
pch_udc_init(dev);
/* enable device interrupts */
/* pch_udc_enable_interrupts() */
pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
UDC_DEVINT_UR | UDC_DEVINT_ENUM);
/* Clear the disconnect */
pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
mdelay(1);
/* Resume USB signalling */
pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
}
/**
* pch_udc_vbus_session() - set or clearr the disconnect status.
* @dev: Reference to pch_udc_regs structure
@ -563,10 +612,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
int is_active)
{
if (is_active)
pch_udc_clear_disconnect(dev);
else
if (is_active) {
pch_udc_reconnect(dev);
dev->vbus_session = 1;
} else {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
pch_udc_set_disconnect(dev);
dev->vbus_session = 0;
}
}
/**
@ -1126,7 +1183,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
if (!gadget)
return -EINVAL;
dev = container_of(gadget, struct pch_udc_dev, gadget);
pch_udc_vbus_session(dev, is_on);
if (is_on) {
pch_udc_reconnect(dev);
} else {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
pch_udc_set_disconnect(dev);
}
return 0;
}
@ -1182,6 +1249,188 @@ static const struct usb_gadget_ops pch_udc_ops = {
.stop = pch_udc_stop,
};
/**
* pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status.
* @dev: Reference to the driver structure
*
* Return value:
* 1: VBUS is high
* 0: VBUS is low
* -1: It is not enable to detect VBUS using GPIO
*/
static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev)
{
int vbus = 0;
if (dev->vbus_gpio.port)
vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0;
else
vbus = -1;
return vbus;
}
/**
* pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low.
* If VBUS is Low, disconnect is processed
* @irq_work: Structure for WorkQueue
*
*/
static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
{
struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
struct pch_vbus_gpio_data, irq_work_fall);
struct pch_udc_dev *dev =
container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
int vbus_saved = -1;
int vbus;
int count;
if (!dev->vbus_gpio.port)
return;
for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL);
count++) {
vbus = pch_vbus_gpio_get_value(dev);
if ((vbus_saved == vbus) && (vbus == 0)) {
dev_dbg(&dev->pdev->dev, "VBUS fell");
if (dev->driver
&& dev->driver->disconnect) {
dev->driver->disconnect(
&dev->gadget);
}
if (dev->vbus_gpio.intr)
pch_udc_init(dev);
else
pch_udc_reconnect(dev);
return;
}
vbus_saved = vbus;
mdelay(PCH_VBUS_INTERVAL);
}
}
/**
* pch_vbus_gpio_work_rise() - This API checks VBUS is High.
* If VBUS is High, connect is processed
* @irq_work: Structure for WorkQueue
*
*/
static void pch_vbus_gpio_work_rise(struct work_struct *irq_work)
{
struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
struct pch_vbus_gpio_data, irq_work_rise);
struct pch_udc_dev *dev =
container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
int vbus;
if (!dev->vbus_gpio.port)
return;
mdelay(PCH_VBUS_INTERVAL);
vbus = pch_vbus_gpio_get_value(dev);
if (vbus == 1) {
dev_dbg(&dev->pdev->dev, "VBUS rose");
pch_udc_reconnect(dev);
return;
}
}
/**
* pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS
* @irq: Interrupt request number
* @dev: Reference to the device structure
*
* Return codes:
* 0: Success
* -EINVAL: GPIO port is invalid or can't be initialized.
*/
static irqreturn_t pch_vbus_gpio_irq(int irq, void *data)
{
struct pch_udc_dev *dev = (struct pch_udc_dev *)data;
if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr)
return IRQ_NONE;
if (pch_vbus_gpio_get_value(dev))
schedule_work(&dev->vbus_gpio.irq_work_rise);
else
schedule_work(&dev->vbus_gpio.irq_work_fall);
return IRQ_HANDLED;
}
/**
* pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
* @dev: Reference to the driver structure
* @vbus_gpio Number of GPIO port to detect gpio
*
* Return codes:
* 0: Success
* -EINVAL: GPIO port is invalid or can't be initialized.
*/
static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
{
int err;
int irq_num = 0;
dev->vbus_gpio.port = 0;
dev->vbus_gpio.intr = 0;
if (vbus_gpio_port <= -1)
return -EINVAL;
err = gpio_is_valid(vbus_gpio_port);
if (!err) {
pr_err("%s: gpio port %d is invalid\n",
__func__, vbus_gpio_port);
return -EINVAL;
}
err = gpio_request(vbus_gpio_port, "pch_vbus");
if (err) {
pr_err("%s: can't request gpio port %d, err: %d\n",
__func__, vbus_gpio_port, err);
return -EINVAL;
}
dev->vbus_gpio.port = vbus_gpio_port;
gpio_direction_input(vbus_gpio_port);
INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
irq_num = gpio_to_irq(vbus_gpio_port);
if (irq_num > 0) {
irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH);
err = request_irq(irq_num, pch_vbus_gpio_irq, 0,
"vbus_detect", dev);
if (!err) {
dev->vbus_gpio.intr = irq_num;
INIT_WORK(&dev->vbus_gpio.irq_work_rise,
pch_vbus_gpio_work_rise);
} else {
pr_err("%s: can't request irq %d, err: %d\n",
__func__, irq_num, err);
}
}
return 0;
}
/**
* pch_vbus_gpio_free() - This API frees resources of GPIO port
* @dev: Reference to the driver structure
*/
static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
{
if (dev->vbus_gpio.intr)
free_irq(dev->vbus_gpio.intr, dev);
if (dev->vbus_gpio.port)
gpio_free(dev->vbus_gpio.port);
}
/**
* complete_req() - This API is invoked from the driver when processing
* of a request is complete
@ -1493,6 +1742,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
pch_udc_ep_disable(ep);
pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
ep->desc = NULL;
ep->ep.desc = NULL;
INIT_LIST_HEAD(&ep->queue);
spin_unlock_irqrestore(&ep->dev->lock, iflags);
return 0;
@ -2335,8 +2585,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
/* Complete request queue */
empty_req_queue(ep);
}
if (dev->driver && dev->driver->disconnect)
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
}
/**
@ -2371,6 +2624,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
pch_udc_set_dma(dev, DMA_DIR_TX);
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
/* enable device interrupts */
pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
UDC_DEVINT_ES | UDC_DEVINT_ENUM |
UDC_DEVINT_SI | UDC_DEVINT_SC);
}
/**
@ -2459,12 +2717,18 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
*/
static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
{
int vbus;
/* USB Reset Interrupt */
if (dev_intr & UDC_DEVINT_UR)
if (dev_intr & UDC_DEVINT_UR) {
pch_udc_svc_ur_interrupt(dev);
dev_dbg(&dev->pdev->dev, "USB_RESET\n");
}
/* Enumeration Done Interrupt */
if (dev_intr & UDC_DEVINT_ENUM)
if (dev_intr & UDC_DEVINT_ENUM) {
pch_udc_svc_enum_interrupt(dev);
dev_dbg(&dev->pdev->dev, "USB_ENUM\n");
}
/* Set Interface Interrupt */
if (dev_intr & UDC_DEVINT_SI)
pch_udc_svc_intf_interrupt(dev);
@ -2472,8 +2736,30 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
if (dev_intr & UDC_DEVINT_SC)
pch_udc_svc_cfg_interrupt(dev);
/* USB Suspend interrupt */
if (dev_intr & UDC_DEVINT_US)
if (dev_intr & UDC_DEVINT_US) {
if (dev->driver
&& dev->driver->suspend) {
spin_unlock(&dev->lock);
dev->driver->suspend(&dev->gadget);
spin_lock(&dev->lock);
}
vbus = pch_vbus_gpio_get_value(dev);
if ((dev->vbus_session == 0)
&& (vbus != 1)) {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
pch_udc_reconnect(dev);
} else if ((dev->vbus_session == 0)
&& (vbus == 1)
&& !dev->vbus_gpio.intr)
schedule_work(&dev->vbus_gpio.irq_work_fall);
dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
}
/* Clear the SOF interrupt, if enabled */
if (dev_intr & UDC_DEVINT_SOF)
dev_dbg(&dev->pdev->dev, "SOF\n");
@ -2499,6 +2785,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
dev_intr = pch_udc_read_device_interrupts(dev);
ep_intr = pch_udc_read_ep_interrupts(dev);
/* For a hot plug, this find that the controller is hung up. */
if (dev_intr == ep_intr)
if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
/* The controller is reset */
pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
return IRQ_HANDLED;
}
if (dev_intr)
/* Clear device interrupts */
pch_udc_write_device_interrupts(dev, dev_intr);
@ -2625,6 +2919,7 @@ static int pch_udc_pcd_init(struct pch_udc_dev *dev)
{
pch_udc_init(dev);
pch_udc_pcd_reinit(dev);
pch_vbus_gpio_init(dev, vbus_gpio_port);
return 0;
}
@ -2725,7 +3020,8 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
pch_udc_setup_ep0(dev);
/* clear SD */
pch_udc_clear_disconnect(dev);
if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr)
pch_udc_clear_disconnect(dev);
dev->connected = 1;
return 0;
@ -2803,6 +3099,8 @@ static void pch_udc_remove(struct pci_dev *pdev)
UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
kfree(dev->ep0out_buf);
pch_vbus_gpio_free(dev);
pch_udc_exit(dev);
if (dev->irq_registered)
@ -2912,8 +3210,10 @@ static int pch_udc_probe(struct pci_dev *pdev,
}
pch_udc = dev;
/* initialize the hardware */
if (pch_udc_pcd_init(dev))
if (pch_udc_pcd_init(dev)) {
retval = -ENODEV;
goto finished;
}
if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
dev)) {
dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,

View File

@ -283,6 +283,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
pxa25x_ep_fifo_flush (_ep);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
local_irq_restore(flags);
@ -1192,6 +1193,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
ep->pio_irqs = 0;

View File

@ -663,11 +663,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
ep->fifoctr = D0FIFOCTR;
/* dma mapping */
req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597),
req->req.buf, req->req.length,
dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
return 0;
return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir);
}
static void sudmac_free_channel(struct r8a66597 *r8a66597,
@ -677,9 +673,7 @@ static void sudmac_free_channel(struct r8a66597 *r8a66597,
if (!r8a66597_is_sudmac(r8a66597))
return;
dma_unmap_single(r8a66597_to_dev(ep->r8a66597),
req->req.dma, req->req.length,
ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir);
r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel);

View File

@ -30,6 +30,7 @@
#include <linux/prefetch.h>
#include <linux/platform_data/s3c-hsudc.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <mach/regs-s3c2443-clock.h>
@ -759,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
unsigned long flags;
u32 ecr = 0;
hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
hsep = our_ep(_ep);
if (!_ep || !desc || hsep->desc || _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT
|| hsep->bEndpointAddress != desc->bEndpointAddress
@ -816,6 +817,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
hsep->desc = 0;
hsep->ep.desc = NULL;
hsep->stopped = 1;
spin_unlock_irqrestore(&hsudc->lock, flags);
@ -853,7 +855,7 @@ static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req)
{
struct s3c_hsudc_req *hsreq;
hsreq = container_of(_req, struct s3c_hsudc_req, req);
hsreq = our_req(_req);
WARN_ON(!list_empty(&hsreq->queue));
kfree(hsreq);
}
@ -876,12 +878,12 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
u32 offset;
u32 csr;
hsreq = container_of(_req, struct s3c_hsudc_req, req);
hsreq = our_req(_req);
if ((!_req || !_req->complete || !_req->buf ||
!list_empty(&hsreq->queue)))
return -EINVAL;
hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
hsep = our_ep(_ep);
hsudc = hsep->dev;
if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
return -ESHUTDOWN;
@ -935,7 +937,7 @@ static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
struct s3c_hsudc_req *hsreq;
unsigned long flags;
hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
hsep = our_ep(_ep);
if (!_ep || hsep->ep.name == ep0name)
return -EINVAL;
@ -1005,6 +1007,7 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->ep.ops = &s3c_hsudc_ep_ops;
hsep->fifo = hsudc->regs + S3C_BR(epnum);
hsep->desc = 0;
hsep->ep.desc = NULL;
hsep->stopped = 0;
hsep->wedge = 0;
@ -1179,6 +1182,9 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
s3c_hsudc_reconfig(hsudc);
pm_runtime_get_sync(hsudc->dev);
s3c_hsudc_init_phy();
if (hsudc->pd->gpio_init)
hsudc->pd->gpio_init();
@ -1209,6 +1215,9 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
hsudc->gadget.dev.driver = NULL;
hsudc->gadget.speed = USB_SPEED_UNKNOWN;
s3c_hsudc_uninit_phy();
pm_runtime_put(hsudc->dev);
if (hsudc->pd->gpio_uninit)
hsudc->pd->gpio_uninit();
s3c_hsudc_stop_activity(hsudc);
@ -1363,6 +1372,8 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
if (ret)
goto err_add_udc;
pm_runtime_enable(dev);
return 0;
err_add_udc:
device_unregister(&hsudc->gadget.dev);

View File

@ -1148,6 +1148,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
ep->desc = NULL;
ep->ep.desc = NULL;
ep->halted = 1;
s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
@ -1630,6 +1631,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
ep->dev = dev;
ep->desc = NULL;
ep->ep.desc = NULL;
ep->halted = 0;
INIT_LIST_HEAD (&ep->queue);
}

View File

@ -242,7 +242,7 @@ static struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.max_speed = USB_SPEED_SUPER,
};
static int __init init(void)

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2003-2008 Alan Stern
* Copyeight (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
* Author: Michal Nazarewicz (mina86@mina86.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/*
* u_audio.c -- ALSA audio utilities for Gadget stack
* u_uac1.c -- ALSA audio utilities for Gadget stack
*
* Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
* Copyright (C) 2008 Analog Devices, Inc
@ -17,7 +17,7 @@
#include <linux/random.h>
#include <linux/syscalls.h>
#include "u_audio.h"
#include "u_uac1.h"
/*
* This component encapsulates the ALSA devices for USB audio gadget

View File

@ -1,5 +1,5 @@
/*
* u_audio.h -- interface to USB gadget "ALSA AUDIO" utilities
* u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
*
* Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
* Copyright (C) 2008 Analog Devices, Inc

View File

@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/dma-mapping.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -49,6 +50,57 @@ static DEFINE_MUTEX(udc_lock);
/* ------------------------------------------------------------------------- */
int usb_gadget_map_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in)
{
if (req->length == 0)
return 0;
if (req->num_sgs) {
int mapped;
mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
dev_err(&gadget->dev, "failed to map SGs\n");
return -EFAULT;
}
req->num_mapped_sgs = mapped;
} else {
req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (dma_mapping_error(&gadget->dev, req->dma)) {
dev_err(&gadget->dev, "failed to map buffer\n");
return -EFAULT;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(usb_gadget_map_request);
void usb_gadget_unmap_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in)
{
if (req->length == 0)
return;
if (req->num_mapped_sgs) {
dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
} else {
dma_unmap_single(&gadget->dev, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
}
}
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
/* ------------------------------------------------------------------------- */
/**
* usb_gadget_start - tells usb device controller to start up
* @gadget: The gadget we want to get started

View File

@ -413,8 +413,7 @@ static int usbhs_probe(struct platform_device *pdev)
struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
struct renesas_usbhs_driver_callback *dfunc;
struct usbhs_priv *priv;
struct resource *res;
unsigned int irq;
struct resource *res, *irq_res;
int ret;
/* check platform information */
@ -426,8 +425,8 @@ static int usbhs_probe(struct platform_device *pdev)
/* platform data */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (!res || (int)irq <= 0) {
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res || !irq_res) {
dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
return -ENODEV;
}
@ -476,7 +475,9 @@ static int usbhs_probe(struct platform_device *pdev)
/*
* priv settings
*/
priv->irq = irq;
priv->irq = irq_res->start;
if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
priv->irqflags = IRQF_SHARED;
priv->pdev = pdev;
INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
spin_lock_init(usbhs_priv_to_lock(priv));

View File

@ -242,6 +242,7 @@ struct usbhs_priv {
void __iomem *base;
unsigned int irq;
unsigned long irqflags;
struct renesas_usbhs_platform_callback pfunc;
struct renesas_usbhs_driver_param dparam;

View File

@ -23,6 +23,7 @@
#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
#define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo))
#define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo))
#define usbhsf_is_cfifo(p, f) (usbhsf_get_cfifo(p) == f)
#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */
@ -75,8 +76,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
pipe->handler = &usbhsf_null_handler;
}
list_del_init(&pkt->node);
list_add_tail(&pkt->node, &pipe->list);
list_move_tail(&pkt->node, &pipe->list);
/*
* each pkt must hold own handler.
@ -106,7 +106,7 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
if (list_empty(&pipe->list))
return NULL;
return list_entry(pipe->list.next, struct usbhs_pkt, node);
return list_first_entry(&pipe->list, struct usbhs_pkt, node);
}
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
@ -305,7 +305,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
}
/* "base" will be used below */
usbhs_write(priv, fifo->sel, base | MBW_32);
if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo))
usbhs_write(priv, fifo->sel, base);
else
usbhs_write(priv, fifo->sel, base | MBW_32);
/* check ISEL and CURPIPE value */
while (timeout--) {
@ -762,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
}
static void usbhsf_dma_complete(void *arg);
static void usbhsf_dma_prepare_tasklet(unsigned long data)
static void xfer_work(struct work_struct *work)
{
struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@ -844,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
pkt->trans = len;
tasklet_init(&fifo->tasklet,
usbhsf_dma_prepare_tasklet,
(unsigned long)pkt);
tasklet_schedule(&fifo->tasklet);
INIT_WORK(&pkt->work, xfer_work);
schedule_work(&pkt->work);
return 0;
@ -938,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
pkt->trans = len;
tasklet_init(&fifo->tasklet,
usbhsf_dma_prepare_tasklet,
(unsigned long)pkt);
tasklet_schedule(&fifo->tasklet);
INIT_WORK(&pkt->work, xfer_work);
schedule_work(&pkt->work);
return 0;

View File

@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/sh_dma.h>
#include <linux/workqueue.h>
#include <asm/dma.h>
#include "pipe.h"
@ -31,7 +32,6 @@ struct usbhs_fifo {
u32 ctr; /* xFIFOCTR */
struct usbhs_pipe *pipe;
struct tasklet_struct tasklet;
struct dma_chan *tx_chan;
struct dma_chan *rx_chan;
@ -53,6 +53,7 @@ struct usbhs_pkt {
struct usbhs_pkt_handle *handler;
void (*done)(struct usbhs_priv *priv,
struct usbhs_pkt *pkt);
struct work_struct work;
dma_addr_t dma;
void *buf;
int length;

View File

@ -152,7 +152,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
/* irq settings */
ret = request_irq(priv->irq, usbhs_interrupt,
0, dev_name(dev), priv);
priv->irqflags, dev_name(dev), priv);
if (ret) {
dev_err(dev, "irq request err\n");
goto mod_init_gadget_err;

View File

@ -165,69 +165,32 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep,
/*
* dma map/unmap
*/
static int usbhsg_dma_map(struct device *dev,
struct usbhs_pkt *pkt,
enum dma_data_direction dir)
{
struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
if (pkt->dma != DMA_ADDR_INVALID) {
dev_err(dev, "dma is already mapped\n");
return -EIO;
}
if (req->dma == DMA_ADDR_INVALID) {
pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
} else {
dma_sync_single_for_device(dev, req->dma, req->length, dir);
pkt->dma = req->dma;
}
if (dma_mapping_error(dev, pkt->dma)) {
dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma);
return -EIO;
}
return 0;
}
static int usbhsg_dma_unmap(struct device *dev,
struct usbhs_pkt *pkt,
enum dma_data_direction dir)
{
struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
if (pkt->dma == DMA_ADDR_INVALID) {
dev_err(dev, "dma is not mapped\n");
return -EIO;
}
if (req->dma == DMA_ADDR_INVALID)
dma_unmap_single(dev, pkt->dma, pkt->length, dir);
else
dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
pkt->dma = DMA_ADDR_INVALID;
return 0;
}
static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
{
struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
enum dma_data_direction dir;
int ret = 0;
dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
dir = usbhs_pipe_is_dir_host(pipe);
if (map)
return usbhsg_dma_map(dev, pkt, dir);
else
return usbhsg_dma_unmap(dev, pkt, dir);
if (map) {
/* it can not use scatter/gather */
WARN_ON(req->num_sgs);
ret = usb_gadget_map_request(&gpriv->gadget, req, dir);
if (ret < 0)
return ret;
pkt->dma = req->dma;
} else {
usb_gadget_unmap_request(&gpriv->gadget, req, dir);
}
return ret;
}
/*
@ -657,8 +620,6 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
ureq->req.dma = DMA_ADDR_INVALID;
return &ureq->req;
}
@ -941,6 +902,11 @@ static int usbhsg_stop(struct usbhs_priv *priv)
return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
}
static void usbhs_mod_gadget_release(struct device *pdev)
{
/* do nothing */
}
int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv;
@ -989,6 +955,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
*/
dev_set_name(&gpriv->gadget.dev, "gadget");
gpriv->gadget.dev.parent = dev;
gpriv->gadget.dev.release = usbhs_mod_gadget_release;
gpriv->gadget.name = "renesas_usbhs_udc";
gpriv->gadget.ops = &usbhsg_gadget_ops;
gpriv->gadget.max_speed = USB_SPEED_HIGH;

View File

@ -43,6 +43,27 @@ static inline bool uac2_control_is_writeable(u32 bmControls, u8 control)
return (bmControls >> (control * 2)) & 0x2;
}
/* 4.7.2 Class-Specific AC Interface Descriptor */
struct uac2_ac_header_descriptor {
__u8 bLength; /* 9 */
__u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
__u8 bDescriptorSubtype; /* UAC_MS_HEADER */
__le16 bcdADC; /* 0x0200 */
__u8 bCategory;
__le16 wTotalLength; /* includes Unit and Terminal desc. */
__u8 bmControls;
} __packed;
/* 2.3.1.6 Type I Format Type Descriptor (Frmts20 final.pdf)*/
struct uac2_format_type_i_descriptor {
__u8 bLength; /* in bytes: 6 */
__u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
__u8 bDescriptorSubtype; /* FORMAT_TYPE */
__u8 bFormatType; /* FORMAT_TYPE_1 */
__u8 bSubslotSize; /* {1,2,3,4} */
__u8 bBitResolution;
} __packed;
/* 4.7.2.1 Clock Source Descriptor */
struct uac_clock_source_descriptor {

View File

@ -950,6 +950,16 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
/*-------------------------------------------------------------------------*/
/* utility to simplify map/unmap of usb_requests to/from DMA */
extern int usb_gadget_map_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in);
extern void usb_gadget_unmap_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in);
/*-------------------------------------------------------------------------*/
/* utility wrapping a simple endpoint selection policy */
extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,

View File

@ -149,6 +149,7 @@ struct renesas_usbhs_driver_param {
* option:
*/
u32 has_otg:1; /* for controlling PWEN/EXTLP */
u32 has_sudmac:1; /* for SUDMAC */
};
/*

View File

@ -2,7 +2,7 @@
* ffs-test.c.c -- user mode filesystem api for usb composite function
*
* Copyright (C) 2010 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
/*
* Copyright (c) 2002 by David Brownell
* Copyright (c) 2010 by Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Author: Michal Nazarewicz <mina86@mina86.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the