/* * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x * series processors. * * Such controller drivers work with a gadget driver. The gadget driver * returns descriptors, implements configuration and data protocols used * by the host to interact with this device, and allocates endpoints to * the different protocol interfaces. The controller driver virtualizes * usb hardware so that the gadget drivers will be more portable. * * This UDC hardware wants to implement a bit too much USB protocol. The * biggest issues are: that the endpoints have to be set up before the * controller can be enabled (minor, and not uncommon); and each endpoint * can only have one configuration, interface and alternative interface * number (major, and very unusual). Once set up, these cannot be changed * without a controller reset. * * The workaround is to setup all combinations necessary for the gadgets which * will work with this driver. This is done in pxa_udc structure, statically. * See pxa_udc, udc_usb_ep versus pxa_ep, and matching function find_pxa_ep. * (You could modify this if needed. Some drivers have a "fifo_mode" module * parameter to facilitate such changes.) * * The combinations have been tested with these gadgets : * - zero gadget * - file storage gadget * - ether gadget * * The driver doesn't use DMA, only IO access and IRQ callbacks. No use is * made of UDC's double buffering either. USB "On-The-Go" is not implemented. * * All the requests are handled the same way : * - the drivers tries to handle the request directly to the IO * - if the IO fifo is not big enough, the remaining is send/received in * interrupt handling.
*/
/** * is_match_usb_pxa - check if usb_ep and pxa_ep match * @udc_usb_ep: usb endpoint * @ep: pxa endpoint * @config: configuration required in pxa_ep * @interface: interface required in pxa_ep * @altsetting: altsetting required in pxa_ep * * Returns 1 if all criteria match between pxa and usb endpoint, 0 otherwise
*/ staticint is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep, int config, int interface, int altsetting)
{ if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr) return 0; if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in) return 0; if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type) return 0; if ((ep->config != config) || (ep->interface != interface)
|| (ep->alternate != altsetting)) return 0; return 1;
}
/** * find_pxa_ep - find pxa_ep structure matching udc_usb_ep * @udc: pxa udc * @udc_usb_ep: udc_usb_ep structure * * Match udc_usb_ep and all pxa_ep available, to see if one matches. * This is necessary because of the strong pxa hardware restriction requiring * that once pxa endpoints are initialized, their configuration is freezed, and * no change can be made to their address, direction, or in which configuration, * interface or altsetting they are active ... which differs from more usual * models which have endpoints be roughly just addressable fifos, and leave * configuration events up to gadget drivers (like all control messages). * * Note that there is still a blurred point here : * - we rely on UDCCR register "active interface" and "active altsetting". * This is a nonsense in regard of USB spec, where multiple interfaces are * active at the same time. * - if we knew for sure that the pxa can handle multiple interface at the * same time, assuming Intel's Developer Guide is wrong, this function * should be reviewed, and a cache of couples (iface, altsetting) should * be kept in the pxa_udc structure. In this case this function would match * against the cache of couples instead of the "last altsetting" set up. * * Returns the matched pxa_ep structure or NULL if none found
*/ staticstruct pxa_ep *find_pxa_ep(struct pxa_udc *udc, struct udc_usb_ep *udc_usb_ep)
{ int i; struct pxa_ep *ep; int cfg = udc->config; int iface = udc->last_interface; int alt = udc->last_alternate;
if (udc_usb_ep == &udc->udc_usb_ep[0]) return &udc->pxa_ep[0];
for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
ep = &udc->pxa_ep[i]; if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt)) return ep;
} return NULL;
}
/** * update_pxa_ep_matches - update pxa_ep cached values in all udc_usb_ep * @udc: pxa udc * * Context: interrupt handler * * Updates all pxa_ep fields in udc_usb_ep structures, if this field was * previously set up (and is not NULL). The update is necessary is a * configuration change or altsetting change was issued by the USB host.
*/ staticvoid update_pxa_ep_matches(struct pxa_udc *udc)
{ int i; struct udc_usb_ep *udc_usb_ep;
for (i = 1; i < NR_USB_ENDPOINTS; i++) {
udc_usb_ep = &udc->udc_usb_ep[i]; if (udc_usb_ep->pxa_ep)
udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
}
}
/** * pio_irq_enable - Enables irq generation for one endpoint * @ep: udc endpoint
*/ staticvoid pio_irq_enable(struct pxa_ep *ep)
{ struct pxa_udc *udc = ep->dev; int index = EPIDX(ep);
u32 udcicr0 = udc_readl(udc, UDCICR0);
u32 udcicr1 = udc_readl(udc, UDCICR1);
/** * udc_set_mask_UDCCR - set bits in UDCCR * @udc: udc device * @mask: bits to set in UDCCR * * Sets bits in UDCCR, leaving DME and FST bits as they were.
*/ staticinlinevoid udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
{
u32 udccr = udc_readl(udc, UDCCR);
udc_writel(udc, UDCCR,
(udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
}
/** * udc_clear_mask_UDCCR - clears bits in UDCCR * @udc: udc device * @mask: bit to clear in UDCCR * * Clears bits in UDCCR, leaving DME and FST bits as they were.
*/ staticinlinevoid udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
{
u32 udccr = udc_readl(udc, UDCCR);
udc_writel(udc, UDCCR,
(udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
}
/** * ep_write_UDCCSR - set bits in UDCCSR * @ep: udc endpoint * @mask: bits to set in UDCCR * * Sets bits in UDCCSR (UDCCSR0 and UDCCSR*). * * A specific case is applied to ep0 : the ACM bit is always set to 1, for * SET_INTERFACE and SET_CONFIGURATION.
*/ staticinlinevoid ep_write_UDCCSR(struct pxa_ep *ep, int mask)
{ if (is_ep0(ep))
mask |= UDCCSR0_ACM;
udc_ep_writel(ep, UDCCSR, mask);
}
/** * ep_count_bytes_remain - get how many bytes in udc endpoint * @ep: udc endpoint * * Returns number of bytes in OUT fifos. Broken for IN fifos (-EOPNOTSUPP)
*/ staticint ep_count_bytes_remain(struct pxa_ep *ep)
{ if (ep->dir_in) return -EOPNOTSUPP; return udc_ep_readl(ep, UDCBCR) & 0x3ff;
}
/** * ep_is_empty - checks if ep has byte ready for reading * @ep: udc endpoint * * If endpoint is the control endpoint, checks if there are bytes in the * control endpoint fifo. If endpoint is a data endpoint, checks if bytes * are ready for reading on OUT endpoint. * * Returns 0 if ep not empty, 1 if ep empty, -EOPNOTSUPP if IN endpoint
*/ staticint ep_is_empty(struct pxa_ep *ep)
{ int ret;
if (!is_ep0(ep) && ep->dir_in) return -EOPNOTSUPP; if (is_ep0(ep))
ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE); else
ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE); return ret;
}
/** * ep_is_full - checks if ep has place to write bytes * @ep: udc endpoint * * If endpoint is not the control endpoint and is an IN endpoint, checks if * there is place to write bytes into the endpoint. * * Returns 0 if ep not full, 1 if ep full, -EOPNOTSUPP if OUT endpoint
*/ staticint ep_is_full(struct pxa_ep *ep)
{ if (is_ep0(ep)) return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR); if (!ep->dir_in) return -EOPNOTSUPP; return (!(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF));
}
/** * epout_has_pkt - checks if OUT endpoint fifo has a packet available * @ep: pxa endpoint * * Returns 1 if a complete packet is available, 0 if not, -EOPNOTSUPP for IN ep.
*/ staticint epout_has_pkt(struct pxa_ep *ep)
{ if (!is_ep0(ep) && ep->dir_in) return -EOPNOTSUPP; if (is_ep0(ep)) return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC); return (udc_ep_readl(ep, UDCCSR) & UDCCSR_PC);
}
/** * set_ep0state - Set ep0 automata state * @udc: udc device * @state: state
*/ staticvoid set_ep0state(struct pxa_udc *udc, int state)
{ struct pxa_ep *ep = &udc->pxa_ep[0]; char *old_stname = EP0_STNAME(udc);
/** * pxa_eps_setup - Sets up all usb physical endpoints * @dev: udc device * * Setup all pxa physical endpoints, except ep0
*/ staticvoid pxa_eps_setup(struct pxa_udc *dev)
{ unsignedint i;
dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
for (i = 1; i < NR_PXA_ENDPOINTS; i++)
pxa_ep_setup(&dev->pxa_ep[i]);
}
/** * pxa_ep_alloc_request - Allocate usb request * @_ep: usb endpoint * @gfp_flags: * * For the pxa27x, these can just wrap kmalloc/kfree. gadget drivers * must still pass correctly initialized endpoints, since other controller * drivers may care about how it's currently set up (dma issues etc).
*/ staticstruct usb_request *
pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
{ struct pxa27x_request *req;
req = kzalloc(sizeof *req, gfp_flags); if (!req) return NULL;
/** * ep_add_request - add a request to the endpoint's queue * @ep: usb endpoint * @req: usb request * * Context: ep->lock held * * Queues the request in the endpoint's queue, and enables the interrupts * on the endpoint.
*/ staticvoid ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
{ if (unlikely(!req)) return;
ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
req->req.length, udc_ep_readl(ep, UDCCSR));
/** * ep_del_request - removes a request from the endpoint's queue * @ep: usb endpoint * @req: usb request * * Context: ep->lock held * * Unqueue the request from the endpoint's queue. If there are no more requests * on the endpoint, and if it's not the control endpoint, interrupts are * disabled on the endpoint.
*/ staticvoid ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
{ if (unlikely(!req)) return;
ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
req->req.length, udc_ep_readl(ep, UDCCSR));
list_del_init(&req->queue);
req->in_use = 0; if (!is_ep0(ep) && list_empty(&ep->queue))
pio_irq_disable(ep);
}
/** * req_done - Complete an usb request * @ep: pxa physical endpoint * @req: pxa request * @status: usb request status sent to gadget API * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * * Context: ep->lock held if flags not NULL, else ep->lock released * * Retire a pxa27x usb request. Endpoint must be locked.
*/ staticvoid req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status, unsignedlong *pflags)
{ unsignedlong flags;
ep_del_request(ep, req); if (likely(req->req.status == -EINPROGRESS))
req->req.status = status; else
status = req->req.status;
if (status && status != -ESHUTDOWN)
ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
&req->req, status,
req->req.actual, req->req.length);
if (pflags)
spin_unlock_irqrestore(&ep->lock, *pflags);
local_irq_save(flags);
usb_gadget_giveback_request(&req->udc_usb_ep->usb_ep, &req->req);
local_irq_restore(flags); if (pflags)
spin_lock_irqsave(&ep->lock, *pflags);
}
/** * ep_end_out_req - Ends endpoint OUT request * @ep: physical endpoint * @req: pxa request * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * * Context: ep->lock held or released (see req_done()) * * Ends endpoint OUT request (completes usb request).
*/ staticvoid ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req, unsignedlong *pflags)
{
inc_ep_stats_reqs(ep, !USB_DIR_IN);
req_done(ep, req, 0, pflags);
}
/** * ep0_end_out_req - Ends control endpoint OUT request (ends data stage) * @ep: physical endpoint * @req: pxa request * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * * Context: ep->lock held or released (see req_done()) * * Ends control endpoint OUT request (completes usb request), and puts * control endpoint into idle state
*/ staticvoid ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req, unsignedlong *pflags)
{
set_ep0state(ep->dev, OUT_STATUS_STAGE);
ep_end_out_req(ep, req, pflags);
ep0_idle(ep->dev);
}
/** * ep_end_in_req - Ends endpoint IN request * @ep: physical endpoint * @req: pxa request * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * * Context: ep->lock held or released (see req_done()) * * Ends endpoint IN request (completes usb request).
*/ staticvoid ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req, unsignedlong *pflags)
{
inc_ep_stats_reqs(ep, USB_DIR_IN);
req_done(ep, req, 0, pflags);
}
/** * ep0_end_in_req - Ends control endpoint IN request (ends data stage) * @ep: physical endpoint * @req: pxa request * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * * Context: ep->lock held or released (see req_done()) * * Ends control endpoint IN request (completes usb request), and puts * control endpoint into status state
*/ staticvoid ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req, unsignedlong *pflags)
{
set_ep0state(ep->dev, IN_STATUS_STAGE);
ep_end_in_req(ep, req, pflags);
}
/** * nuke - Dequeue all requests * @ep: pxa endpoint * @status: usb request status * * Context: ep->lock released * * Dequeues all requests on an endpoint. As a side effect, interrupts will be * disabled on that endpoint (because no more requests).
*/ staticvoid nuke(struct pxa_ep *ep, int status)
{ struct pxa27x_request *req; unsignedlong flags;
/** * read_packet - transfer 1 packet from an OUT endpoint into request * @ep: pxa physical endpoint * @req: usb request * * Takes bytes from OUT endpoint and transfers them info the usb request. * If there is less space in request than bytes received in OUT endpoint, * bytes are left in the OUT endpoint. * * Returns how many bytes were actually transferred
*/ staticint read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
{
u32 *buf; int bytes_ep, bufferspace, count, i;
for (i = count; i > 0; i -= 4)
*buf++ = udc_ep_readl(ep, UDCDR);
req->req.actual += count;
ep_write_UDCCSR(ep, UDCCSR_PC);
return count;
}
/** * write_packet - transfer 1 packet from request into an IN endpoint * @ep: pxa physical endpoint * @req: usb request * @max: max bytes that fit into endpoint * * Takes bytes from usb request, and transfers them into the physical * endpoint. If there are no bytes to transfer, doesn't write anything * to physical endpoint. * * Returns how many bytes were actually transferred.
*/ staticint write_packet(struct pxa_ep *ep, struct pxa27x_request *req, unsignedint max)
{ int length, count, remain, i;
u32 *buf;
u8 *buf_8;
/** * read_fifo - Transfer packets from OUT endpoint into usb request * @ep: pxa physical endpoint * @req: usb request * * Context: interrupt handler * * Unload as many packets as possible 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. * Doesn't complete the request, that's the caller's job * * Returns 1 if the request completed, 0 otherwise
*/ staticint read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
{ int count, is_short, completed = 0;
while (epout_has_pkt(ep)) {
count = read_packet(ep, req);
inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
/* completion */ if (is_short || req->req.actual == req->req.length) {
completed = 1; break;
} /* finished that packet. the next one may be waiting... */
} return completed;
}
/** * write_fifo - transfer packets from usb request into an IN endpoint * @ep: pxa physical endpoint * @req: pxa usb request * * Write to an IN endpoint fifo, as many packets as possible. * irqs will use this to write the rest later. * caller guarantees at least one packet buffer is ready (or a zlp). * Doesn't complete the request, that's the caller's job * * Returns 1 if request fully transferred, 0 if partial transfer
*/ staticint write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
{ unsigned max; int count, is_short, is_last = 0, completed = 0, totcount = 0;
u32 udccsr;
max = ep->fifo_size; do {
udccsr = udc_ep_readl(ep, UDCCSR); if (udccsr & UDCCSR_PC) {
ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
udccsr);
ep_write_UDCCSR(ep, UDCCSR_PC);
} if (udccsr & UDCCSR_TRN) {
ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
udccsr);
ep_write_UDCCSR(ep, UDCCSR_TRN);
}
/* last packet is usually short (or a zlp) */ if (unlikely(count < max)) {
is_last = 1;
is_short = 1;
} else { if (likely(req->req.length > req->req.actual)
|| req->req.zero)
is_last = 0; else
is_last = 1; /* interrupt/iso maxpacket may not fill the fifo */
is_short = unlikely(max < ep->fifo_size);
}
if (is_short)
ep_write_UDCCSR(ep, UDCCSR_SP);
/* requests complete when all IN data is in the FIFO */ if (is_last) {
completed = 1; break;
}
} while (!ep_is_full(ep));
/** * read_ep0_fifo - Transfer packets from control endpoint into usb request * @ep: control endpoint * @req: pxa usb request * * Special ep0 version of the above read_fifo. Reads as many bytes from control * endpoint as can be read, and stores them into usb request (limited by request * maximum length). * * Returns 0 if usb request only partially filled, 1 if fully filled
*/ staticint read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
{ int count, is_short, completed = 0;
/** * write_ep0_fifo - Send a request to control endpoint (ep0 in) * @ep: control endpoint * @req: request * * Context: interrupt handler * * Sends a request (or a part of the request) to the control endpoint (ep0 in). * If the request doesn't fit, the remaining part will be sent from irq. * The request is considered fully written only if either : * - last write transferred all remaining bytes, but fifo was not fully filled * - last write was a 0 length write * * Returns 1 if request fully written, 0 if request only partially sent
*/ staticint write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
{ unsigned count; int is_last, is_short;
/** * pxa_ep_queue - Queue a request into an IN endpoint * @_ep: usb endpoint * @_req: usb request * @gfp_flags: flags * * Context: thread context or from the interrupt handler in the * special case of ep0 setup : * (irq->handle_ep0_ctrl_req->gadget_setup->pxa_ep_queue) * * Returns 0 if succedeed, error otherwise
*/ staticint pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
gfp_t gfp_flags)
{ struct udc_usb_ep *udc_usb_ep; struct pxa_ep *ep; struct pxa27x_request *req; struct pxa_udc *dev; unsignedlong flags; int rc = 0; int is_first_req; unsigned length; int recursion_detected;
if (unlikely(!_req || !_req->complete || !_req->buf)) return -EINVAL;
if (unlikely(!_ep)) return -EINVAL;
ep = udc_usb_ep->pxa_ep; if (unlikely(!ep)) return -EINVAL;
dev = ep->dev; if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
ep_dbg(ep, "bogus device state\n"); return -ESHUTDOWN;
}
/* iso is always one packet per request, that's the only way * we can report per-packet status. that also helps with dma.
*/ if (unlikely(EPXFERTYPE_is_ISO(ep)
&& req->req.length > ep->fifo_size)) return -EMSGSIZE;
if (is_ep0(ep)) { switch (dev->ep0state) { case WAIT_ACK_SET_CONF_INTERF: if (length == 0) {
ep_end_in_req(ep, req, NULL);
} else {
ep_err(ep, "got a request of %d bytes while" "in state WAIT_ACK_SET_CONF_INTERF\n",
length);
ep_del_request(ep, req);
rc = -EL2HLT;
}
ep0_idle(ep->dev); break; case IN_DATA_STAGE: if (!ep_is_full(ep)) if (write_ep0_fifo(ep, req))
ep0_end_in_req(ep, req, NULL); break; case OUT_DATA_STAGE: if ((length == 0) || !epout_has_pkt(ep)) if (read_ep0_fifo(ep, req))
ep0_end_out_req(ep, req, NULL); break; default:
ep_err(ep, "odd state %s to send me a request\n",
EP0_STNAME(ep->dev));
ep_del_request(ep, req);
rc = -EL2HLT; break;
}
} else { if (!recursion_detected)
handle_ep(ep);
}
/** * pxa_ep_set_halt - Halts operations on one endpoint * @_ep: usb endpoint * @value: * * Returns 0 if no error, -EINVAL, -EROFS, -EAGAIN otherwise
*/ staticint pxa_ep_set_halt(struct usb_ep *_ep, int value)
{ struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep; unsignedlong flags; int rc;
if (!_ep) return -EINVAL;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep)) return -EINVAL;
if (value == 0) { /* * This path (reset toggle+halt) is needed to implement * SET_INTERFACE on normal hardware. but it can't be * done from software on the PXA UDC, and the hardware * forgets to do it as part of SET_INTERFACE automagic.
*/
ep_dbg(ep, "only host can clear halt\n"); return -EROFS;
}
/* FST, FEF bits are the same for control and non control endpoints */
rc = 0;
ep_write_UDCCSR(ep, UDCCSR_FST | UDCCSR_FEF); if (is_ep0(ep))
set_ep0state(ep->dev, STALL);
/** * pxa_ep_fifo_status - Get how many bytes in physical endpoint * @_ep: usb endpoint * * Returns number of bytes in OUT fifos. Broken for IN fifos.
*/ staticint pxa_ep_fifo_status(struct usb_ep *_ep)
{ struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep;
if (!_ep) return -ENODEV;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep)) return -ENODEV;
if (ep->dir_in) return -EOPNOTSUPP; if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep)) return 0; else return ep_count_bytes_remain(ep) + 1;
}
/** * pxa_ep_fifo_flush - Flushes one endpoint * @_ep: usb endpoint * * Discards all data in one endpoint(IN or OUT), except control endpoint.
*/ staticvoid pxa_ep_fifo_flush(struct usb_ep *_ep)
{ struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep; unsignedlong flags;
if (!_ep) return;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep)) return;
spin_lock_irqsave(&ep->lock, flags);
if (unlikely(!list_empty(&ep->queue)))
ep_dbg(ep, "called while queue list not empty\n");
ep_dbg(ep, "called\n");
/* for OUT, just read and discard the FIFO contents. */ if (!ep->dir_in) { while (!ep_is_empty(ep))
udc_ep_readl(ep, UDCDR);
} else { /* most IN status is the same, but ISO can't stall */
ep_write_UDCCSR(ep,
UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
| (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
}
spin_unlock_irqrestore(&ep->lock, flags);
}
/** * pxa_ep_enable - Enables usb endpoint * @_ep: usb endpoint * @desc: usb endpoint descriptor * * Nothing much to do here, as ep configuration is done once and for all * before udc is enabled. After udc enable, no physical endpoint configuration * can be changed. * Function makes sanity checks and flushes the endpoint.
*/ staticint pxa_ep_enable(struct usb_ep *_ep, conststruct usb_endpoint_descriptor *desc)
{ struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep; struct pxa_udc *udc;
if (!_ep || !desc) return -EINVAL;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); if (udc_usb_ep->pxa_ep) {
ep = udc_usb_ep->pxa_ep;
ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
_ep->name);
} else {
ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
}
if (!ep || is_ep0(ep)) {
dev_err(udc_usb_ep->dev->dev, "unable to match pxa_ep for ep %s\n",
_ep->name); return -EINVAL;
}
/* flush fifo (mostly for OUT buffers) */
pxa_ep_fifo_flush(_ep);
ep_dbg(ep, "enabled\n"); return 0;
}
/** * pxa_ep_disable - Disable usb endpoint * @_ep: usb endpoint * * Same as for pxa_ep_enable, no physical endpoint configuration can be * changed. * Function flushes the endpoint and related requests.
*/ staticint pxa_ep_disable(struct usb_ep *_ep)
{ struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep;
if (!_ep) return -EINVAL;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep) || !list_empty(&ep->queue)) return -EINVAL;
/** * dplus_pullup - Connect or disconnect pullup resistor to D+ pin * @udc: udc device * @on: 0 if disconnect pullup resistor, 1 otherwise * Context: any * * Handle D+ pullup resistor, make the device visible to the usb bus, and * declare it as a full speed usb device
*/ staticvoid dplus_pullup(struct pxa_udc *udc, int on)
{ if (udc->gpiod) {
gpiod_set_value(udc->gpiod, on);
} elseif (udc->udc_command) { if (on)
udc->udc_command(PXA2XX_UDC_CMD_CONNECT); else
udc->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
udc->pullup_on = on;
}
/** * pxa_udc_get_frame - Returns usb frame number * @_gadget: usb gadget
*/ staticint pxa_udc_get_frame(struct usb_gadget *_gadget)
{ struct pxa_udc *udc = to_gadget_udc(_gadget);
return (udc_readl(udc, UDCFNR) & 0x7ff);
}
/** * pxa_udc_wakeup - Force udc device out of suspend * @_gadget: usb gadget * * Returns 0 if successful, error code otherwise
*/ staticint pxa_udc_wakeup(struct usb_gadget *_gadget)
{ struct pxa_udc *udc = to_gadget_udc(_gadget);
/* host may not have enabled remote wakeup */ if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0) return -EHOSTUNREACH;
udc_set_mask_UDCCR(udc, UDCCR_UDR); return 0;
}
/** * should_enable_udc - Tells if UDC should be enabled * @udc: udc device * Context: any * * The UDC should be enabled if : * - the pullup resistor is connected * - and a gadget driver is bound * - and vbus is sensed (or no vbus sense is available) * * Returns 1 if UDC should be enabled, 0 otherwise
*/ staticint should_enable_udc(struct pxa_udc *udc)
{ int put_on;
/** * should_disable_udc - Tells if UDC should be disabled * @udc: udc device * Context: any * * The UDC should be disabled if : * - the pullup resistor is not connected * - or no gadget driver is bound * - or no vbus is sensed (when vbus sesing is available) * * Returns 1 if UDC should be disabled
*/ staticint should_disable_udc(struct pxa_udc *udc)
{ int put_off;
/** * pxa_udc_pullup - Offer manual D+ pullup control * @_gadget: usb gadget using the control * @is_active: 0 if disconnect, else connect D+ pullup resistor * * Context: task context, might sleep * * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
*/ staticint pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
{ struct pxa_udc *udc = to_gadget_udc(_gadget);
if (!udc->gpiod && !udc->udc_command) return -EOPNOTSUPP;
dplus_pullup(udc, is_active);
if (should_enable_udc(udc))
udc_enable(udc); if (should_disable_udc(udc))
udc_disable(udc); return 0;
}
/** * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc * @_gadget: usb gadget * @is_active: 0 if should disable the udc, 1 if should enable * * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the * udc, and deactivates D+ pullup resistor. * * Returns 0
*/ staticint pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{ struct pxa_udc *udc = to_gadget_udc(_gadget);
udc->vbus_sensed = is_active; if (should_enable_udc(udc))
udc_enable(udc); if (should_disable_udc(udc))
udc_disable(udc);
return 0;
}
/** * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed * @_gadget: usb gadget * @mA: current drawn * * Context: task context, might sleep * * Called after a configuration was chosen by a USB host, to inform how much * current can be drawn by the device from VBus line. * * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc
*/ staticint pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
{ struct pxa_udc *udc;
/** * pxa_udc_phy_event - Called by phy upon VBus event * @nb: notifier block * @action: phy action, is vbus connect or disconnect * @data: the usb_gadget structure in pxa_udc * * Called by the USB Phy when a cable connect or disconnect is sensed. * * Returns 0
*/ staticint pxa_udc_phy_event(struct notifier_block *nb, unsignedlong action, void *data)
{ struct usb_gadget *gadget = data;
switch (action) { case USB_EVENT_VBUS:
usb_gadget_vbus_connect(gadget); return NOTIFY_OK; case USB_EVENT_NONE:
usb_gadget_vbus_disconnect(gadget); return NOTIFY_OK; default: return NOTIFY_DONE;
}
}
/* USB endpoints init */ for (i = 1; i < NR_USB_ENDPOINTS; i++) {
list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
&dev->gadget.ep_list);
usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
dev->udc_usb_ep[i].usb_ep.maxpacket);
}
}
/** * udc_enable - Enables the udc device * @udc: udc device * * Enables the udc device : enables clocks, udc interrupts, control endpoint * interrupts, sets usb as UDC client and setups endpoints.
*/ staticvoid udc_enable(struct pxa_udc *udc)
{ if (udc->enabled) return;
/** * pxa27x_udc_start - Register gadget driver * @g: gadget * @driver: gadget driver * * When a driver is successfully registered, it will receive control requests * including set_configuration(), which enables non-control requests. Then * usb traffic follows until a disconnect is reported. Then a host may connect * again, or the driver might get unbound. * * Note that the udc is not automatically enabled. Check function * should_enable_udc(). * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
*/ staticint pxa27x_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver)
{ struct pxa_udc *udc = to_pxa(g); int retval;
/* first hook up the driver ... */
udc->driver = driver;
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget); if (retval) {
dev_err(udc->dev, "can't bind to transceiver\n"); goto fail;
}
}
if (should_enable_udc(udc))
udc_enable(udc); return 0;
fail:
udc->driver = NULL; return retval;
}
/** * stop_activity - Stops udc endpoints * @udc: udc device * * Disables all udc endpoints (even control endpoint), report disconnect to * the gadget user.
*/ staticvoid stop_activity(struct pxa_udc *udc)
{ int i;
udc->gadget.speed = USB_SPEED_UNKNOWN;
for (i = 0; i < NR_USB_ENDPOINTS; i++)
pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
}
/* * In the PXA320 manual, in the section about Back-to-Back setup * packets, it describes this situation. The solution is to set OPC to * get rid of the status packet, and then continue with the setup * packet. Generalize to pxa27x CPUs.
*/ if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0))
ep_write_UDCCSR(ep, UDCCSR0_OPC);
/* read SETUP packet */ for (i = 0; i < 2; i++) { if (unlikely(ep_is_empty(ep))) goto stall;
u.word[i] = udc_ep_readl(ep, UDCDR);
}
have_extrabytes = !ep_is_empty(ep); while (!ep_is_empty(ep)) {
i = udc_ep_readl(ep, UDCDR);
ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
}
/** * handle_ep0 - Handle control endpoint data transfers * @udc: udc device * @fifo_irq: 1 if triggered by fifo service type irq * @opc_irq: 1 if triggered by output packet complete type irq * * Context : interrupt handler * * Tries to transfer all pending request data into the endpoint and/or * transfer all pending data in the endpoint into usb requests. * Handles states of ep0 automata. * * PXA27x hardware handles several standard usb control requests without * driver notification. The requests fully handled by hardware are : * SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE, * GET_STATUS * The requests handled by hardware, but with irq notification are : * SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE * The remaining standard requests really handled by handle_ep0 are : * GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests. * Requests standardized outside of USB 2.0 chapter 9 are handled more * uniformly, by gadget drivers. * * The control endpoint state machine is _not_ USB spec compliant, it's even * hardly compliant with Intel PXA270 developers guide. * The key points which inferred this state machine are : * - on every setup token, bit UDCCSR0_SA is raised and held until cleared by * software. * - on every OUT packet received, UDCCSR0_OPC is raised and held until * cleared by software. * - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it * before reading ep0. * This is true only for PXA27x. This is not true anymore for PXA3xx family * (check Back-to-Back setup packet in developers guide). * - irq can be called on a "packet complete" event (opc_irq=1), while * UDCCSR0_OPC is not yet raised (delta can be as big as 100ms * from experimentation). * - as UDCCSR0_SA can be activated while in irq handling, and clearing * UDCCSR0_OPC would flush the setup data, we almost never clear UDCCSR0_OPC * => we never actually read the "status stage" packet of an IN data stage * => this is not documented in Intel documentation * - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA * STAGE. The driver add STATUS STAGE to send last zero length packet in * OUT_STATUS_STAGE. * - special attention was needed for IN_STATUS_STAGE. If a packet complete * event is detected, we terminate the status stage without ackowledging the * packet (not to risk to loose a potential SETUP packet)
*/ staticvoid handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
{
u32 udccsr0; struct pxa_ep *ep = &udc->pxa_ep[0]; struct pxa27x_request *req = NULL; int completed = 0;
if (!list_empty(&ep->queue))
req = list_entry(ep->queue.next, struct pxa27x_request, queue);
if (udccsr0 & UDCCSR0_SA) {
nuke(ep, 0);
set_ep0state(udc, SETUP_STAGE);
}
switch (udc->ep0state) { case WAIT_FOR_SETUP: /* * Hardware bug : beware, we cannot clear OPC, since we would * miss a potential OPC irq for a setup packet. * So, we only do ... nothing, and hope for a next irq with * UDCCSR0_SA set.
*/ break; case SETUP_STAGE:
udccsr0 &= UDCCSR0_CTRL_REQ_MASK; if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
handle_ep0_ctrl_req(udc, req); break; case IN_DATA_STAGE: /* GET_DESCRIPTOR */ if (epout_has_pkt(ep))
ep_write_UDCCSR(ep, UDCCSR0_OPC); if (req && !ep_is_full(ep))
completed = write_ep0_fifo(ep, req); if (completed)
ep0_end_in_req(ep, req, NULL); break; case OUT_DATA_STAGE: /* SET_DESCRIPTOR */ if (epout_has_pkt(ep) && req)
completed = read_ep0_fifo(ep, req); if (completed)
ep0_end_out_req(ep, req, NULL); break; case STALL:
ep_write_UDCCSR(ep, UDCCSR0_FST); break; case IN_STATUS_STAGE: /* * Hardware bug : beware, we cannot clear OPC, since we would * miss a potential PC irq for a setup packet. * So, we only put the ep0 into WAIT_FOR_SETUP state.
*/ if (opc_irq)
ep0_idle(udc); break; case OUT_STATUS_STAGE: case WAIT_ACK_SET_CONF_INTERF:
ep_warn(ep, "should never get in %s state here!!!\n",
EP0_STNAME(ep->dev));
ep0_idle(udc); break;
}
}
/** * handle_ep - Handle endpoint data tranfers * @ep: pxa physical endpoint * * Tries to transfer all pending request data into the endpoint and/or * transfer all pending data in the endpoint into usb requests. * * Is always called from the interrupt handler. ep->lock must not be held.
*/ staticvoid handle_ep(struct pxa_ep *ep)
{ struct pxa27x_request *req; int completed;
u32 udccsr; int is_in = ep->dir_in; int loop = 0; unsignedlong flags;
spin_lock_irqsave(&ep->lock, flags); if (ep->in_handle_ep) goto recursion_detected;
ep->in_handle_ep = 1;
do {
completed = 0;
udccsr = udc_ep_readl(ep, UDCCSR);
/** * pxa27x_change_interface - Handle SET_INTERF usb request notification * @udc: udc device * @iface: interface number * @alt: alternate setting number * * Post the request to upper level. * Don't use any pxa specific harware configuration capabilities
*/ staticvoid pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
{ struct usb_ctrlrequest req;
/* * irq_handle_data - Handle data transfer * @irq: irq IRQ number * @udc: dev pxa_udc device structure * * Called from irq handler, transferts data to or from endpoint to queue
*/ staticvoid irq_handle_data(int irq, struct pxa_udc *udc)
{ int i; struct pxa_ep *ep;
u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.86Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.