drivers/usb/gadget/udc/pxa25x_udc.c
Source file repositories/reference/linux-study-clean/drivers/usb/gadget/udc/pxa25x_udc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/gadget/udc/pxa25x_udc.c- Extension
.c- Size
- 68264 bytes
- Lines
- 2490
- Domain
- Driver Families
- Bucket
- drivers/usb
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/device.hlinux/gpio.hlinux/module.hlinux/kernel.hlinux/ioport.hlinux/types.hlinux/errno.hlinux/err.hlinux/delay.hlinux/slab.hlinux/timer.hlinux/list.hlinux/interrupt.hlinux/mm.hlinux/platform_data/pxa2xx_udc.hlinux/platform_device.hlinux/dma-mapping.hlinux/irq.hlinux/clk.hlinux/seq_file.hlinux/debugfs.hlinux/io.hlinux/prefetch.hasm/byteorder.hasm/dma.hasm/mach-types.hlinux/unaligned.hlinux/usb/ch9.hlinux/usb/gadget.hlinux/usb/otg.hpxa25x_udc.h
Detected Declarations
function pullup_offfunction pullup_onfunction udc_set_regfunction udc_get_regfunction udc_set_regfunction udc_get_regfunction pio_irq_enablefunction pio_irq_disablefunction udc_set_mask_UDCCRfunction udc_clear_mask_UDCCRfunction udc_ack_int_UDCCRfunction udc_ep_get_UDCCSfunction udc_ep_set_UDCCSfunction udc_ep0_get_UDCCSfunction udc_ep0_set_UDCCSfunction udc_ep_get_UDDRfunction udc_ep_set_UDDRfunction udc_ep_get_UBCRfunction interfacefunction pxa25x_ep_disablefunction pxa25x_ep_alloc_requestfunction pxa25x_ep_free_requestfunction donefunction ep0_idlefunction write_packetfunction readyfunction ep0startfunction write_ep0_fifofunction filledfunction commandsfunction pxa25x_ep_queuefunction nukefunction pxa25x_ep_dequeuefunction pxa25x_ep_set_haltfunction pxa25x_ep_fifo_statusfunction pxa25x_ep_fifo_flushfunction pxa25x_udc_get_framefunction pxa25x_udc_wakeupfunction pullupfunction pxa25x_udc_vbus_sessionfunction pxa25x_udc_pullupfunction pxa25x_udc_vbus_drawfunction udc_debug_showfunction list_for_each_entryfunction udc_disablefunction udc_reinitfunction udc_enablefunction set_configuration
Annotated Snippet
if (is_last) {
done (ep, req, 0);
if (list_empty(&ep->queue))
pio_irq_disable(ep);
return 1;
}
// TODO experiment: how robust can fifo mode tweaking be?
// double buffering is off in the default fifo mode, which
// prevents TFS from being set here.
} while (udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS);
return 0;
}
/* caller asserts req->pending (ep0 irq status nyet cleared); starts
* ep0 data stage. these chips want very simple state transitions.
*/
static inline
void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
{
udc_ep0_set_UDCCS(dev, flags|UDCCS0_SA|UDCCS0_OPR);
udc_set_reg(dev, USIR0, USIR0_IR0);
dev->req_pending = 0;
DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
__func__, tag, udc_ep0_get_UDCCS(dev), flags);
}
static int
write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
{
struct pxa25x_udc *dev = ep->dev;
unsigned count;
int is_short;
count = write_packet(&dev->ep[0], req, EP0_FIFO_SIZE);
ep->dev->stats.write.bytes += count;
/* last packet "must be" short (or a zlp) */
is_short = (count != EP0_FIFO_SIZE);
DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
req->req.length - req->req.actual, req);
if (unlikely (is_short)) {
if (ep->dev->req_pending)
ep0start(ep->dev, UDCCS0_IPR, "short IN");
else
udc_ep0_set_UDCCS(dev, UDCCS0_IPR);
count = req->req.length;
done (ep, req, 0);
ep0_idle(ep->dev);
#ifndef CONFIG_ARCH_IXP4XX
#if 1
/* This seems to get rid of lost status irqs in some cases:
* host responds quickly, or next request involves config
* change automagic, or should have been hidden, or ...
*
* FIXME get rid of all udelays possible...
*/
if (count >= EP0_FIFO_SIZE) {
count = 100;
do {
if ((udc_ep0_get_UDCCS(dev) & UDCCS0_OPR) != 0) {
/* clear OPR, generate ack */
udc_ep0_set_UDCCS(dev, UDCCS0_OPR);
break;
}
count--;
udelay(1);
} while (count);
}
#endif
#endif
} else if (ep->dev->req_pending)
ep0start(ep->dev, 0, "IN");
return is_short;
}
/*
* read_fifo - unload packet(s) from the fifo we use for usb OUT
* transfers and put them into the request. caller should have made
* sure there's at least one packet ready.
*
* returns true if the request completed because of short packet or the
* request buffer having filled (and maybe overran till end-of-packet).
*/
static int
Annotation
- Immediate include surface: `linux/device.h`, `linux/gpio.h`, `linux/module.h`, `linux/kernel.h`, `linux/ioport.h`, `linux/types.h`, `linux/errno.h`, `linux/err.h`.
- Detected declarations: `function pullup_off`, `function pullup_on`, `function udc_set_reg`, `function udc_get_reg`, `function udc_set_reg`, `function udc_get_reg`, `function pio_irq_enable`, `function pio_irq_disable`, `function udc_set_mask_UDCCR`, `function udc_clear_mask_UDCCR`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.