// SPDX-License-Identifier: GPL-2.0 /* * MUSB OTG driver peripheral support * * Copyright 2005 Mentor Graphics Corporation * Copyright (C) 2005-2006 by Texas Instruments * Copyright (C) 2006-2007 Nokia Corporation * Copyright (C) 2009 MontaVista Software, Inc. <[email protected]> */ #include <linux/kernel.h> #include <linux/list.h> #include <linux/timer.h> #include <linux/module.h> #include <linux/smp.h> #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/slab.h> #include "musb_core.h" #include "musb_trace.h" /* ----------------------------------------------------------------------- */ #define is_buffer_mapped(req) … /* Maps the buffer to dma */ static inline void map_dma_buffer(struct musb_request *request, struct musb *musb, struct musb_ep *musb_ep) { … } /* Unmap the buffer from dma and maps it back to cpu */ static inline void unmap_dma_buffer(struct musb_request *request, struct musb *musb) { … } /* * Immediately complete a request. * * @param request the request to complete * @param status the status to complete the request with * Context: controller locked, IRQs blocked. */ void musb_g_giveback( struct musb_ep *ep, struct usb_request *request, int status) __releases(ep->musb->lock) __acquires(ep->musb->lock) { … } /* ----------------------------------------------------------------------- */ /* * Abort requests queued to an endpoint using the status. Synchronous. * caller locked controller and blocked irqs, and selected this ep. */ static void nuke(struct musb_ep *ep, const int status) { … } /* ----------------------------------------------------------------------- */ /* Data transfers - pure PIO, pure DMA, or mixed mode */ /* * This assumes the separate CPPI engine is responding to DMA requests * from the usb core ... sequenced a bit differently from mentor dma. */ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) { … } /* * An endpoint is transmitting data. This can be called either from * the IRQ routine or from ep.queue() to kickstart a request on an * endpoint. * * Context: controller locked, IRQs blocked, endpoint selected */ static void txstate(struct musb *musb, struct musb_request *req) { … } /* * FIFO state update (e.g. data ready). * Called from IRQ, with controller locked. */ void musb_g_tx(struct musb *musb, u8 epnum) { … } /* ------------------------------------------------------------ */ /* * Context: controller locked, IRQs blocked, endpoint selected */ static void rxstate(struct musb *musb, struct musb_request *req) { … } /* * Data ready for a request; called from IRQ */ void musb_g_rx(struct musb *musb, u8 epnum) { … } /* ------------------------------------------------------------ */ static int musb_gadget_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { … } /* * Disable an endpoint flushing all requests queued. */ static int musb_gadget_disable(struct usb_ep *ep) { … } /* * Allocate a request for an endpoint. * Reused by ep0 code. */ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) { … } /* * Free a request * Reused by ep0 code. */ void musb_free_request(struct usb_ep *ep, struct usb_request *req) { … } /* * Context: controller locked, IRQs blocked. */ void musb_ep_restart(struct musb *musb, struct musb_request *req) { … } static int musb_ep_restart_resume_work(struct musb *musb, void *data) { … } static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { … } static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request) { … } /* * Set or clear the halt bit of an endpoint. A halted endpoint won't tx/rx any * data but will queue requests. * * exported to ep0 code */ static int musb_gadget_set_halt(struct usb_ep *ep, int value) { … } /* * Sets the halt feature with the clear requests ignored */ static int musb_gadget_set_wedge(struct usb_ep *ep) { … } static int musb_gadget_fifo_status(struct usb_ep *ep) { … } static void musb_gadget_fifo_flush(struct usb_ep *ep) { … } static const struct usb_ep_ops musb_ep_ops = …; /* ----------------------------------------------------------------------- */ static int musb_gadget_get_frame(struct usb_gadget *gadget) { … } static int musb_gadget_wakeup(struct usb_gadget *gadget) { … } static int musb_gadget_set_self_powered(struct usb_gadget *gadget, int is_selfpowered) { … } static void musb_pullup(struct musb *musb, int is_on) { … } #if 0 static int musb_gadget_vbus_session(struct usb_gadget *gadget, int is_active) { musb_dbg(musb, "<= %s =>\n", __func__); /* * FIXME iff driver's softconnect flag is set (as it is during probe, * though that can clear it), just musb_pullup(). */ return -EINVAL; } #endif static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) { … } static void musb_gadget_work(struct work_struct *work) { … } static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) { … } static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int musb_gadget_stop(struct usb_gadget *g); static const struct usb_gadget_ops musb_gadget_operations = …; /* ----------------------------------------------------------------------- */ /* Registration */ /* Only this registration code "knows" the rule (from USB standards) * about there being only one external upstream port. It assumes * all peripheral ports are external... */ static void init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) { … } /* * Initialize the endpoints exposed to peripheral drivers, with backlinks * to the rest of the driver state. */ static inline void musb_g_init_endpoints(struct musb *musb) { … } /* called once during driver setup to initialize and link into * the driver model; memory is zeroed. */ int musb_gadget_setup(struct musb *musb) { … } void musb_gadget_cleanup(struct musb *musb) { … } /* * Register the gadget driver. Used by gadget drivers when * registering themselves with the controller. * * -EINVAL something went wrong (not driver) * -EBUSY another gadget is already using the controller * -ENOMEM no memory to perform the operation * * @param driver the gadget driver * @return <0 if error, 0 if everything is fine */ static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { … } /* * Unregister the gadget driver. Used by gadget drivers when * unregistering themselves from the controller. * * @param driver the gadget driver to unregister */ static int musb_gadget_stop(struct usb_gadget *g) { … } /* ----------------------------------------------------------------------- */ /* lifecycle operations called through plat_uds.c */ void musb_g_resume(struct musb *musb) { … } /* called when SOF packets stop for 3+ msec */ void musb_g_suspend(struct musb *musb) { … } /* Called during SRP */ void musb_g_wakeup(struct musb *musb) { … } /* called when VBUS drops below session threshold, and in other cases */ void musb_g_disconnect(struct musb *musb) { … } void musb_g_reset(struct musb *musb) __releases(musb->lock) __acquires(musb->lock) { … }