linux/drivers/usb/gadget/udc/snps_udc_core.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * amd5536.c -- AMD 5536 UDC high/full speed USB device controller
 *
 * Copyright (C) 2005-2007 AMD (https://www.amd.com)
 * Author: Thomas Dahlmann
 */

/*
 * This file does the core driver implementation for the UDC that is based
 * on Synopsys device controller IP (different than HS OTG IP) that is either
 * connected through PCI bus or integrated to SoC platforms.
 */

/* Driver strings */
#define UDC_MOD_DESCRIPTION
#define UDC_DRIVER_VERSION_STRING

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/dmapool.h>
#include <linux/prefetch.h>
#include <linux/moduleparam.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include "amd5536udc.h"

static void udc_setup_endpoints(struct udc *dev);
static void udc_soft_reset(struct udc *dev);
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);

/* description */
static const char mod_desc[] =;
static const char name[] =;

/* structure to hold endpoint function pointers */
static const struct usb_ep_ops udc_ep_ops;

/* received setup data */
static union udc_setup_data setup_data;

/* pointer to device object */
static struct udc *udc;

/* irq spin lock for soft reset */
static DEFINE_SPINLOCK(udc_irq_spinlock);
/* stall spin lock */
static DEFINE_SPINLOCK(udc_stall_spinlock);

/*
* slave mode: pending bytes in rx fifo after nyet,
* used if EPIN irq came but no req was available
*/
static unsigned int udc_rxfifo_pending;

/* count soft resets after suspend to avoid loop */
static int soft_reset_occured;
static int soft_reset_after_usbreset_occured;

/* timer */
static struct timer_list udc_timer;
static int stop_timer;

/* set_rde -- Is used to control enabling of RX DMA. Problem is
 * that UDC has only one bit (RDE) to enable/disable RX DMA for
 * all OUT endpoints. So we have to handle race conditions like
 * when OUT data reaches the fifo but no request was queued yet.
 * This cannot be solved by letting the RX DMA disabled until a
 * request gets queued because there may be other OUT packets
 * in the FIFO (important for not blocking control traffic).
 * The value of set_rde controls the corresponding timer.
 *
 * set_rde -1 == not used, means it is alloed to be set to 0 or 1
 * set_rde  0 == do not touch RDE, do no start the RDE timer
 * set_rde  1 == timer function will look whether FIFO has data
 * set_rde  2 == set by timer function to enable RX DMA on next call
 */
static int set_rde =;

static DECLARE_COMPLETION(on_exit);
static struct timer_list udc_pollstall_timer;
static int stop_pollstall_timer;
static DECLARE_COMPLETION(on_pollstall_exit);

/* endpoint names used for print */
static const char ep0_string[] =;
static const struct {} ep_info[] =;

/* buffer fill mode */
static int use_dma_bufferfill_mode;
/* tx buffer size for high speed */
static unsigned long hs_tx_buf =;

/*---------------------------------------------------------------------------*/
/* Prints UDC device registers and endpoint irq registers */
static void print_regs(struct udc *dev)
{}

/* Masks unused interrupts */
int udc_mask_unused_interrupts(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* Enables endpoint 0 interrupts */
static int udc_enable_ep0_interrupts(struct udc *dev)
{}

/* Enables device interrupts for SET_INTF and SET_CONFIG */
int udc_enable_dev_setup_interrupts(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* Calculates fifo start of endpoint based on preceding endpoints */
static int udc_set_txfifo_addr(struct udc_ep *ep)
{}

/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */
static u32 cnak_pending;

static void UDC_QUEUE_CNAK(struct udc_ep *ep, unsigned num)
{}


/* Enables endpoint, is called by gadget driver */
static int
udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
{}

/* Resets endpoint */
static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
{}

/* Disables endpoint, is called by gadget driver */
static int udc_ep_disable(struct usb_ep *usbep)
{}

/* Allocates request packet, called by gadget driver */
static struct usb_request *
udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
{}

/* frees pci pool descriptors of a DMA chain */
static void udc_free_dma_chain(struct udc *dev, struct udc_request *req)
{}

/* Frees request packet, called by gadget driver */
static void
udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
{}

/* Init BNA dummy descriptor for HOST BUSY and pointing to itself */
static void udc_init_bna_dummy(struct udc_request *req)
{}

/* Allocate BNA dummy descriptor */
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep)
{}

/* Write data to TX fifo for IN packets */
static void
udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
{}

/* Read dwords from RX fifo for OUT transfers */
static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
{}

/* Read bytes from RX fifo for OUT transfers */
static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
{}

/* Read data from RX fifo for OUT transfers */
static int
udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
{}

/* Creates or re-inits a DMA chain */
static int udc_create_dma_chain(
	struct udc_ep *ep,
	struct udc_request *req,
	unsigned long buf_len, gfp_t gfp_flags
)
{}

/* create/re-init a DMA descriptor or a DMA descriptor chain */
static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
{}

/* Completes request packet ... caller MUST hold lock */
static void
complete_req(struct udc_ep *ep, struct udc_request *req, int sts)
__releases(ep->dev->lock)
__acquires(ep->dev->lock)
{}

/* Iterates to the end of a DMA chain and returns last descriptor */
static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
{}

/* Iterates to the end of a DMA chain and counts bytes received */
static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
{}

/* Enabling RX DMA */
static void udc_set_rde(struct udc *dev)
{}

/* Queues a request packet, called by gadget driver */
static int
udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
{}

/* Empty request queue of an endpoint; caller holds spinlock */
void empty_req_queue(struct udc_ep *ep)
{}
EXPORT_SYMBOL_GPL();

/* Dequeues a request packet, called by gadget driver */
static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
{}

/* Halt or clear halt of endpoint */
static int
udc_set_halt(struct usb_ep *usbep, int halt)
{}

/* gadget interface */
static const struct usb_ep_ops udc_ep_ops =;

/*-------------------------------------------------------------------------*/

/* Get frame counter (not implemented) */
static int udc_get_frame(struct usb_gadget *gadget)
{}

/* Initiates a remote wakeup */
static int udc_remote_wakeup(struct udc *dev)
{}

/* Remote wakeup gadget interface */
static int udc_wakeup(struct usb_gadget *gadget)
{}

static int amd5536_udc_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver);
static int amd5536_udc_stop(struct usb_gadget *g);

static const struct usb_gadget_ops udc_ops =;

/* Setups endpoint parameters, adds endpoints to linked list */
static void make_ep_lists(struct udc *dev)
{}

/* Inits UDC context */
void udc_basic_init(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* init registers at driver load time */
static int startup_registers(struct udc *dev)
{}

/* Sets initial endpoint parameters */
static void udc_setup_endpoints(struct udc *dev)
{}

/* Bringup after Connect event, initial bringup to be ready for ep0 events */
static void usb_connect(struct udc *dev)
{}

/*
 * Calls gadget with disconnect event and resets the UDC and makes
 * initial bringup to be ready for ep0 events
 */
static void usb_disconnect(struct udc *dev)
{}

/* Reset the UDC core */
static void udc_soft_reset(struct udc *dev)
{}

/* RDE timer callback to set RDE bit */
static void udc_timer_function(struct timer_list *unused)
{}

/* Handle halt state, used in stall poll timer */
static void udc_handle_halt_state(struct udc_ep *ep)
{}

/* Stall timer callback to poll S bit and set it again after */
static void udc_pollstall_timer_function(struct timer_list *unused)
{}

/* Inits endpoint 0 so that SETUP packets are processed */
static void activate_control_endpoints(struct udc *dev)
{}

/* Make endpoint 0 ready for control traffic */
static int setup_ep0(struct udc *dev)
{}

/* Called by gadget driver to register itself */
static int amd5536_udc_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver)
{}

/* shutdown requests and disconnect from gadget */
static void
shutdown(struct udc *dev, struct usb_gadget_driver *driver)
__releases(dev->lock)
__acquires(dev->lock)
{}

/* Called by gadget driver to unregister itself */
static int amd5536_udc_stop(struct usb_gadget *g)
{}

/* Clear pending NAK bits */
static void udc_process_cnak_queue(struct udc *dev)
{}

/* Enabling RX DMA after setup packet */
static void udc_ep0_set_rde(struct udc *dev)
{}


/* Interrupt handler for data OUT traffic */
static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
{}

/* Interrupt handler for data IN traffic */
static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
{}

/* Interrupt handler for Control OUT traffic */
static irqreturn_t udc_control_out_isr(struct udc *dev)
__releases(dev->lock)
__acquires(dev->lock)
{}

/* Interrupt handler for Control IN traffic */
static irqreturn_t udc_control_in_isr(struct udc *dev)
{}


/* Interrupt handler for global device events */
static irqreturn_t udc_dev_isr(struct udc *dev, u32 dev_irq)
__releases(dev->lock)
__acquires(dev->lock)
{}

/* Interrupt Service Routine, see Linux Kernel Doc for parameters */
irqreturn_t udc_irq(int irq, void *pdev)
{}
EXPORT_SYMBOL_GPL();

/* Tears down device */
void gadget_release(struct device *pdev)
{}
EXPORT_SYMBOL_GPL();

/* Cleanup on device remove */
void udc_remove(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* free all the dma pools */
void free_dma_pools(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* create dma pools on init */
int init_dma_pools(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

/* general probe */
int udc_probe(struct udc *dev)
{}
EXPORT_SYMBOL_GPL();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();