// SPDX-License-Identifier: GPL-2.0+ /* * Xilinx USB peripheral controller driver * * Copyright (C) 2004 by Thomas Rathbone * Copyright (C) 2005 by HP Labs * Copyright (C) 2005 by David Brownell * Copyright (C) 2010 - 2014 Xilinx, Inc. * * Some parts of this driver code is based on the driver for at91-series * USB peripheral controller (at91_udc.c). */ #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/prefetch.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> /* Register offsets for the USB device.*/ #define XUSB_EP0_CONFIG_OFFSET … #define XUSB_SETUP_PKT_ADDR_OFFSET … #define XUSB_ADDRESS_OFFSET … #define XUSB_CONTROL_OFFSET … #define XUSB_STATUS_OFFSET … #define XUSB_FRAMENUM_OFFSET … #define XUSB_IER_OFFSET … #define XUSB_BUFFREADY_OFFSET … #define XUSB_TESTMODE_OFFSET … #define XUSB_DMA_RESET_OFFSET … #define XUSB_DMA_CONTROL_OFFSET … #define XUSB_DMA_DSAR_ADDR_OFFSET … #define XUSB_DMA_DDAR_ADDR_OFFSET … #define XUSB_DMA_LENGTH_OFFSET … #define XUSB_DMA_STATUS_OFFSET … /* Endpoint Configuration Space offsets */ #define XUSB_EP_CFGSTATUS_OFFSET … #define XUSB_EP_BUF0COUNT_OFFSET … #define XUSB_EP_BUF1COUNT_OFFSET … #define XUSB_CONTROL_USB_READY_MASK … #define XUSB_CONTROL_USB_RMTWAKE_MASK … /* Interrupt register related masks.*/ #define XUSB_STATUS_GLOBAL_INTR_MASK … #define XUSB_STATUS_DMADONE_MASK … #define XUSB_STATUS_DMAERR_MASK … #define XUSB_STATUS_DMABUSY_MASK … #define XUSB_STATUS_RESUME_MASK … #define XUSB_STATUS_RESET_MASK … #define XUSB_STATUS_SUSPEND_MASK … #define XUSB_STATUS_DISCONNECT_MASK … #define XUSB_STATUS_FIFO_BUFF_RDY_MASK … #define XUSB_STATUS_FIFO_BUFF_FREE_MASK … #define XUSB_STATUS_SETUP_PACKET_MASK … #define XUSB_STATUS_EP1_BUFF2_COMP_MASK … #define XUSB_STATUS_EP1_BUFF1_COMP_MASK … #define XUSB_STATUS_EP0_BUFF2_COMP_MASK … #define XUSB_STATUS_EP0_BUFF1_COMP_MASK … #define XUSB_STATUS_HIGH_SPEED_MASK … /* Suspend,Reset,Suspend and Disconnect Mask */ #define XUSB_STATUS_INTR_EVENT_MASK … /* Buffers completion Mask */ #define XUSB_STATUS_INTR_BUFF_COMP_ALL_MASK … /* Mask for buffer 0 and buffer 1 completion for all Endpoints */ #define XUSB_STATUS_INTR_BUFF_COMP_SHIFT_MASK … #define XUSB_STATUS_EP_BUFF2_SHIFT … /* Endpoint Configuration Status Register */ #define XUSB_EP_CFG_VALID_MASK … #define XUSB_EP_CFG_STALL_MASK … #define XUSB_EP_CFG_DATA_TOGGLE_MASK … /* USB device specific global configuration constants.*/ #define XUSB_MAX_ENDPOINTS … #define XUSB_EP_NUMBER_ZERO … /* DPRAM is the source address for DMA transfer */ #define XUSB_DMA_READ_FROM_DPRAM … #define XUSB_DMA_DMASR_BUSY … #define XUSB_DMA_DMASR_ERROR … /* * When this bit is set, the DMA buffer ready bit is set by hardware upon * DMA transfer completion. */ #define XUSB_DMA_BRR_CTRL … /* Phase States */ #define SETUP_PHASE … #define DATA_PHASE … #define STATUS_PHASE … #define EP0_MAX_PACKET … #define STATUSBUFF_SIZE … #define EPNAME_SIZE … /* container_of helper macros */ #define to_udc(g) … #define to_xusb_ep(ep) … #define to_xusb_req(req) … /** * struct xusb_req - Xilinx USB device request structure * @usb_req: Linux usb request structure * @queue: usb device request queue * @ep: pointer to xusb_endpoint structure */ struct xusb_req { … }; /** * struct xusb_ep - USB end point structure. * @ep_usb: usb endpoint instance * @queue: endpoint message queue * @udc: xilinx usb peripheral driver instance pointer * @desc: pointer to the usb endpoint descriptor * @rambase: the endpoint buffer address * @offset: the endpoint register offset value * @name: name of the endpoint * @epnumber: endpoint number * @maxpacket: maximum packet size the endpoint can store * @buffer0count: the size of the packet recieved in the first buffer * @buffer1count: the size of the packet received in the second buffer * @curbufnum: current buffer of endpoint that will be processed next * @buffer0ready: the busy state of first buffer * @buffer1ready: the busy state of second buffer * @is_in: endpoint direction (IN or OUT) * @is_iso: endpoint type(isochronous or non isochronous) */ struct xusb_ep { … }; /** * struct xusb_udc - USB peripheral driver structure * @gadget: USB gadget driver instance * @ep: an array of endpoint structures * @driver: pointer to the usb gadget driver instance * @setup: usb_ctrlrequest structure for control requests * @req: pointer to dummy request for get status command * @dev: pointer to device structure in gadget * @usb_state: device in suspended state or not * @remote_wkp: remote wakeup enabled by host * @setupseqtx: tx status * @setupseqrx: rx status * @addr: the usb device base address * @lock: instance of spinlock * @dma_enabled: flag indicating whether the dma is included in the system * @clk: pointer to struct clk * @read_fn: function pointer to read device registers * @write_fn: function pointer to write to device registers */ struct xusb_udc { … }; /* Endpoint buffer start addresses in the core */ static u32 rambase[8] = …; static const char driver_name[] = …; static const char ep0name[] = …; /* Control endpoint configuration.*/ static const struct usb_endpoint_descriptor config_bulk_out_desc = …; /** * xudc_write32 - little endian write to device registers * @addr: base addr of device registers * @offset: register offset * @val: data to be written */ static void xudc_write32(void __iomem *addr, u32 offset, u32 val) { … } /** * xudc_read32 - little endian read from device registers * @addr: addr of device register * Return: value at addr */ static unsigned int xudc_read32(void __iomem *addr) { … } /** * xudc_write32_be - big endian write to device registers * @addr: base addr of device registers * @offset: register offset * @val: data to be written */ static void xudc_write32_be(void __iomem *addr, u32 offset, u32 val) { … } /** * xudc_read32_be - big endian read from device registers * @addr: addr of device register * Return: value at addr */ static unsigned int xudc_read32_be(void __iomem *addr) { … } /** * xudc_wrstatus - Sets up the usb device status stages. * @udc: pointer to the usb device controller structure. */ static void xudc_wrstatus(struct xusb_udc *udc) { … } /** * xudc_epconfig - Configures the given endpoint. * @ep: pointer to the usb device endpoint structure. * @udc: pointer to the usb peripheral controller structure. * * This function configures a specific endpoint with the given configuration * data. */ static void xudc_epconfig(struct xusb_ep *ep, struct xusb_udc *udc) { … } /** * xudc_start_dma - Starts DMA transfer. * @ep: pointer to the usb device endpoint structure. * @src: DMA source address. * @dst: DMA destination address. * @length: number of bytes to transfer. * * Return: 0 on success, error code on failure * * This function starts DMA transfer by writing to DMA source, * destination and lenth registers. */ static int xudc_start_dma(struct xusb_ep *ep, dma_addr_t src, dma_addr_t dst, u32 length) { … } /** * xudc_dma_send - Sends IN data using DMA. * @ep: pointer to the usb device endpoint structure. * @req: pointer to the usb request structure. * @buffer: pointer to data to be sent. * @length: number of bytes to send. * * Return: 0 on success, -EAGAIN if no buffer is free and error * code on failure. * * This function sends data using DMA. */ static int xudc_dma_send(struct xusb_ep *ep, struct xusb_req *req, u8 *buffer, u32 length) { … } /** * xudc_dma_receive - Receives OUT data using DMA. * @ep: pointer to the usb device endpoint structure. * @req: pointer to the usb request structure. * @buffer: pointer to storage buffer of received data. * @length: number of bytes to receive. * * Return: 0 on success, -EAGAIN if no buffer is free and error * code on failure. * * This function receives data using DMA. */ static int xudc_dma_receive(struct xusb_ep *ep, struct xusb_req *req, u8 *buffer, u32 length) { … } /** * xudc_eptxrx - Transmits or receives data to or from an endpoint. * @ep: pointer to the usb endpoint configuration structure. * @req: pointer to the usb request structure. * @bufferptr: pointer to buffer containing the data to be sent. * @bufferlen: The number of data bytes to be sent. * * Return: 0 on success, -EAGAIN if no buffer is free. * * This function copies the transmit/receive data to/from the end point buffer * and enables the buffer for transmission/reception. */ static int xudc_eptxrx(struct xusb_ep *ep, struct xusb_req *req, u8 *bufferptr, u32 bufferlen) { … } /** * xudc_done - Exeutes the endpoint data transfer completion tasks. * @ep: pointer to the usb device endpoint structure. * @req: pointer to the usb request structure. * @status: Status of the data transfer. * * Deletes the message from the queue and updates data transfer completion * status. */ static void xudc_done(struct xusb_ep *ep, struct xusb_req *req, int status) { … } /** * xudc_read_fifo - Reads the data from the given endpoint buffer. * @ep: pointer to the usb device endpoint structure. * @req: pointer to the usb request structure. * * Return: 0 if request is completed and -EAGAIN if not completed. * * Pulls OUT packet data from the endpoint buffer. */ static int xudc_read_fifo(struct xusb_ep *ep, struct xusb_req *req) { … } /** * xudc_write_fifo - Writes data into the given endpoint buffer. * @ep: pointer to the usb device endpoint structure. * @req: pointer to the usb request structure. * * Return: 0 if request is completed and -EAGAIN if not completed. * * Loads endpoint buffer for an IN packet. */ static int xudc_write_fifo(struct xusb_ep *ep, struct xusb_req *req) { … } /** * xudc_nuke - Cleans up the data transfer message list. * @ep: pointer to the usb device endpoint structure. * @status: Status of the data transfer. */ static void xudc_nuke(struct xusb_ep *ep, int status) { … } /** * xudc_ep_set_halt - Stalls/unstalls the given endpoint. * @_ep: pointer to the usb device endpoint structure. * @value: value to indicate stall/unstall. * * Return: 0 for success and error value on failure */ static int xudc_ep_set_halt(struct usb_ep *_ep, int value) { … } /** * __xudc_ep_enable - Enables the given endpoint. * @ep: pointer to the xusb endpoint structure. * @desc: pointer to usb endpoint descriptor. * * Return: 0 for success and error value on failure */ static int __xudc_ep_enable(struct xusb_ep *ep, const struct usb_endpoint_descriptor *desc) { … } /** * xudc_ep_enable - Enables the given endpoint. * @_ep: pointer to the usb endpoint structure. * @desc: pointer to usb endpoint descriptor. * * Return: 0 for success and error value on failure */ static int xudc_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { … } /** * xudc_ep_disable - Disables the given endpoint. * @_ep: pointer to the usb endpoint structure. * * Return: 0 for success and error value on failure */ static int xudc_ep_disable(struct usb_ep *_ep) { … } /** * xudc_ep_alloc_request - Initializes the request queue. * @_ep: pointer to the usb endpoint structure. * @gfp_flags: Flags related to the request call. * * Return: pointer to request structure on success and a NULL on failure. */ static struct usb_request *xudc_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) { … } /** * xudc_free_request - Releases the request from queue. * @_ep: pointer to the usb device endpoint structure. * @_req: pointer to the usb request structure. */ static void xudc_free_request(struct usb_ep *_ep, struct usb_request *_req) { … } /** * __xudc_ep0_queue - Adds the request to endpoint 0 queue. * @ep0: pointer to the xusb endpoint 0 structure. * @req: pointer to the xusb request structure. * * Return: 0 for success and error value on failure */ static int __xudc_ep0_queue(struct xusb_ep *ep0, struct xusb_req *req) { … } /** * xudc_ep0_queue - Adds the request to endpoint 0 queue. * @_ep: pointer to the usb endpoint 0 structure. * @_req: pointer to the usb request structure. * @gfp_flags: Flags related to the request call. * * Return: 0 for success and error value on failure */ static int xudc_ep0_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { … } /** * xudc_ep_queue - Adds the request to endpoint queue. * @_ep: pointer to the usb endpoint structure. * @_req: pointer to the usb request structure. * @gfp_flags: Flags related to the request call. * * Return: 0 for success and error value on failure */ static int xudc_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { … } /** * xudc_ep_dequeue - Removes the request from the queue. * @_ep: pointer to the usb device endpoint structure. * @_req: pointer to the usb request structure. * * Return: 0 for success and error value on failure */ static int xudc_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) { … } /** * xudc_ep0_enable - Enables the given endpoint. * @ep: pointer to the usb endpoint structure. * @desc: pointer to usb endpoint descriptor. * * Return: error always. * * endpoint 0 enable should not be called by gadget layer. */ static int xudc_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { … } /** * xudc_ep0_disable - Disables the given endpoint. * @ep: pointer to the usb endpoint structure. * * Return: error always. * * endpoint 0 disable should not be called by gadget layer. */ static int xudc_ep0_disable(struct usb_ep *ep) { … } static const struct usb_ep_ops xusb_ep0_ops = …; static const struct usb_ep_ops xusb_ep_ops = …; /** * xudc_get_frame - Reads the current usb frame number. * @gadget: pointer to the usb gadget structure. * * Return: current frame number for success and error value on failure. */ static int xudc_get_frame(struct usb_gadget *gadget) { … } /** * xudc_wakeup - Send remote wakeup signal to host * @gadget: pointer to the usb gadget structure. * * Return: 0 on success and error on failure */ static int xudc_wakeup(struct usb_gadget *gadget) { … } /** * xudc_pullup - start/stop USB traffic * @gadget: pointer to the usb gadget structure. * @is_on: flag to start or stop * * Return: 0 always * * This function starts/stops SIE engine of IP based on is_on. */ static int xudc_pullup(struct usb_gadget *gadget, int is_on) { … } /** * xudc_eps_init - initialize endpoints. * @udc: pointer to the usb device controller structure. */ static void xudc_eps_init(struct xusb_udc *udc) { … } /** * xudc_stop_activity - Stops any further activity on the device. * @udc: pointer to the usb device controller structure. */ static void xudc_stop_activity(struct xusb_udc *udc) { … } /** * xudc_start - Starts the device. * @gadget: pointer to the usb gadget structure * @driver: pointer to gadget driver structure * * Return: zero on success and error on failure */ static int xudc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { … } /** * xudc_stop - stops the device. * @gadget: pointer to the usb gadget structure * * Return: zero always */ static int xudc_stop(struct usb_gadget *gadget) { … } static const struct usb_gadget_ops xusb_udc_ops = …; /** * xudc_clear_stall_all_ep - clears stall of every endpoint. * @udc: pointer to the udc structure. */ static void xudc_clear_stall_all_ep(struct xusb_udc *udc) { … } /** * xudc_startup_handler - The usb device controller interrupt handler. * @udc: pointer to the udc structure. * @intrstatus: The mask value containing the interrupt sources. * * This function handles the RESET,SUSPEND,RESUME and DISCONNECT interrupts. */ static void xudc_startup_handler(struct xusb_udc *udc, u32 intrstatus) { … } /** * xudc_ep0_stall - Stall endpoint zero. * @udc: pointer to the udc structure. * * This function stalls endpoint zero. */ static void xudc_ep0_stall(struct xusb_udc *udc) { … } /** * xudc_setaddress - executes SET_ADDRESS command * @udc: pointer to the udc structure. * * This function executes USB SET_ADDRESS command */ static void xudc_setaddress(struct xusb_udc *udc) { … } /** * xudc_getstatus - executes GET_STATUS command * @udc: pointer to the udc structure. * * This function executes USB GET_STATUS command */ static void xudc_getstatus(struct xusb_udc *udc) { … } /** * xudc_set_clear_feature - Executes the set feature and clear feature commands. * @udc: pointer to the usb device controller structure. * * Processes the SET_FEATURE and CLEAR_FEATURE commands. */ static void xudc_set_clear_feature(struct xusb_udc *udc) { … } /** * xudc_handle_setup - Processes the setup packet. * @udc: pointer to the usb device controller structure. * * Process setup packet and delegate to gadget layer. */ static void xudc_handle_setup(struct xusb_udc *udc) __must_hold(&udc->lock) { … } /** * xudc_ep0_out - Processes the endpoint 0 OUT token. * @udc: pointer to the usb device controller structure. */ static void xudc_ep0_out(struct xusb_udc *udc) { … } /** * xudc_ep0_in - Processes the endpoint 0 IN token. * @udc: pointer to the usb device controller structure. */ static void xudc_ep0_in(struct xusb_udc *udc) { … } /** * xudc_ctrl_ep_handler - Endpoint 0 interrupt handler. * @udc: pointer to the udc structure. * @intrstatus: It's the mask value for the interrupt sources on endpoint 0. * * Processes the commands received during enumeration phase. */ static void xudc_ctrl_ep_handler(struct xusb_udc *udc, u32 intrstatus) { … } /** * xudc_nonctrl_ep_handler - Non control endpoint interrupt handler. * @udc: pointer to the udc structure. * @epnum: End point number for which the interrupt is to be processed * @intrstatus: mask value for interrupt sources of endpoints other * than endpoint 0. * * Processes the buffer completion interrupts. */ static void xudc_nonctrl_ep_handler(struct xusb_udc *udc, u8 epnum, u32 intrstatus) { … } /** * xudc_irq - The main interrupt handler. * @irq: The interrupt number. * @_udc: pointer to the usb device controller structure. * * Return: IRQ_HANDLED after the interrupt is handled. */ static irqreturn_t xudc_irq(int irq, void *_udc) { … } /** * xudc_probe - The device probe function for driver initialization. * @pdev: pointer to the platform device structure. * * Return: 0 for success and error value on failure */ static int xudc_probe(struct platform_device *pdev) { … } /** * xudc_remove - Releases the resources allocated during the initialization. * @pdev: pointer to the platform device structure. * * Return: 0 always */ static void xudc_remove(struct platform_device *pdev) { … } #ifdef CONFIG_PM_SLEEP static int xudc_suspend(struct device *dev) { … } static int xudc_resume(struct device *dev) { … } #endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops xudc_pm_ops = …; /* Match table for of_platform binding */ static const struct of_device_id usb_of_match[] = …; MODULE_DEVICE_TABLE(of, usb_of_match); static struct platform_driver xudc_driver = …; module_platform_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;