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

// SPDX-License-Identifier: GPL-2.0+
/*
 * Driver for the PLX NET2280 USB device controller.
 * Specs and errata are available from <http://www.plxtech.com>.
 *
 * PLX Technology Inc. (formerly NetChip Technology) supported the
 * development of this driver.
 *
 *
 * CODE STATUS HIGHLIGHTS
 *
 * This driver should work well with most "gadget" drivers, including
 * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
 * as well as Gadget Zero and Gadgetfs.
 *
 * DMA is enabled by default.
 *
 * MSI is enabled by default.  The legacy IRQ is used if MSI couldn't
 * be enabled.
 *
 * Note that almost all the errata workarounds here are only needed for
 * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
 */

/*
 * Copyright (C) 2003 David Brownell
 * Copyright (C) 2003-2005 PLX Technology, Inc.
 * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
 *
 * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
 *	with 2282 chip
 *
 * Modified Ricardo Ribalda Qtechnology AS  to provide compatibility
 *	with usb 338x chip. Based on PLX driver
 */

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/prefetch.h>
#include <linux/io.h>
#include <linux/iopoll.h>

#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/unaligned.h>

#define DRIVER_DESC
#define DRIVER_VERSION

#define EP_DONTUSE

#define USE_RDK_LEDS


static const char driver_name[] =;
static const char driver_desc[] =;

static const u32 ep_bit[9] =;
static const char ep0name[] =;

#define EP_INFO

static const struct {} ep_info_dft[] =, ep_info_adv[] =;

#undef EP_INFO

/* mode 0 == ep-{a,b,c,d} 1K fifo each
 * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
 * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
 */
static ushort fifo_mode;

/* "modprobe net2280 fifo_mode=1" etc */
module_param(fifo_mode, ushort, 0644);

/* enable_suspend -- When enabled, the driver will respond to
 * USB suspend requests by powering down the NET2280.  Otherwise,
 * USB suspend requests will be ignored.  This is acceptable for
 * self-powered devices
 */
static bool enable_suspend;

/* "modprobe net2280 enable_suspend=1" etc */
module_param(enable_suspend, bool, 0444);

#define DIR_STRING(bAddress)

static char *type_string(u8 bmAttributes)
{}

#include "net2280.h"

#define valid_bit
#define dma_done_ie

static void ep_clear_seqnum(struct net2280_ep *ep);
static void stop_activity(struct net2280 *dev,
					struct usb_gadget_driver *driver);
static void ep0_start(struct net2280 *dev);

/*-------------------------------------------------------------------------*/
static inline void enable_pciirqenb(struct net2280_ep *ep)
{}

static int
net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
{}

static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec)
{}

static const struct usb_ep_ops net2280_ep_ops;

static void ep_reset_228x(struct net2280_regs __iomem *regs,
			  struct net2280_ep *ep)
{}

static void ep_reset_338x(struct net2280_regs __iomem *regs,
					struct net2280_ep *ep)
{}

static void nuke(struct net2280_ep *);

static int net2280_disable(struct usb_ep *_ep)
{}

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

static struct usb_request
*net2280_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
{}

static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req)
{}

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

/* load a packet into the fifo we use for usb IN transfers.
 * works for all endpoints.
 *
 * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
 * at a time, but this code is simpler because it knows it only writes
 * one packet.  ep-a..ep-d should use dma instead.
 */
static void write_fifo(struct net2280_ep *ep, struct usb_request *req)
{}

/* work around erratum 0106: PCI and USB race over the OUT fifo.
 * caller guarantees chiprev 0100, out endpoint is NAKing, and
 * there's no real data in the fifo.
 *
 * NOTE:  also used in cases where that erratum doesn't apply:
 * where the host wrote "too much" data to us.
 */
static void out_flush(struct net2280_ep *ep)
{}

/* unload packet(s) from the fifo we use for usb OUT transfers.
 * returns true iff the request completed, because of short packet
 * or the request buffer having filled with full packets.
 *
 * for ep-a..ep-d this will read multiple packets out when they
 * have been accepted.
 */
static int read_fifo(struct net2280_ep *ep, struct net2280_request *req)
{}

/* fill out dma descriptor to match a given request */
static void fill_dma_desc(struct net2280_ep *ep,
					struct net2280_request *req, int valid)
{}

static const u32 dmactl_default =;

static inline void spin_stop_dma(struct net2280_dma_regs __iomem *dma)
{}

static inline void stop_dma(struct net2280_dma_regs __iomem *dma)
{}

static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
{}

static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
{}

static inline void
queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid)
{}

static void
done(struct net2280_ep *ep, struct net2280_request *req, int status)
{}

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

static int
net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{}

static inline void
dma_done(struct net2280_ep *ep,	struct net2280_request *req, u32 dmacount,
		int status)
{}

static int scan_dma_completions(struct net2280_ep *ep)
{}

static void restart_dma(struct net2280_ep *ep)
{}

static void abort_dma(struct net2280_ep *ep)
{}

/* dequeue ALL requests */
static void nuke(struct net2280_ep *ep)
{}

/* dequeue JUST ONE request */
static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
{}

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

static int net2280_fifo_status(struct usb_ep *_ep);

static int
net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
{}

static int net2280_set_halt(struct usb_ep *_ep, int value)
{}

static int net2280_set_wedge(struct usb_ep *_ep)
{}

static int net2280_fifo_status(struct usb_ep *_ep)
{}

static void net2280_fifo_flush(struct usb_ep *_ep)
{}

static const struct usb_ep_ops net2280_ep_ops =;

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

static int net2280_get_frame(struct usb_gadget *_gadget)
{}

static int net2280_wakeup(struct usb_gadget *_gadget)
{}

static int net2280_set_selfpowered(struct usb_gadget *_gadget, int value)
{}

static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
{}

static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
		struct usb_endpoint_descriptor *desc,
		struct usb_ss_ep_comp_descriptor *ep_comp)
{}

static int net2280_start(struct usb_gadget *_gadget,
		struct usb_gadget_driver *driver);
static int net2280_stop(struct usb_gadget *_gadget);
static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable);

static const struct usb_gadget_ops net2280_ops =;

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

#ifdef	CONFIG_USB_GADGET_DEBUG_FILES

/* FIXME move these into procfs, and use seq_file.
 * Sysfs _still_ doesn't behave for arbitrarily sized files,
 * and also doesn't help products using this with 2.4 kernels.
 */

/* "function" sysfs attribute */
static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
			     char *buf)
{}
static DEVICE_ATTR_RO(function);

static ssize_t registers_show(struct device *_dev,
			      struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(registers);

static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
			   char *buf)
{}
static DEVICE_ATTR_RO(queues);


#else

#define device_create_file
#define device_remove_file

#endif

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

/* another driver-specific mode might be a request type doing dma
 * to/from another device fifo instead of to/from memory.
 */

static void set_fifo_mode(struct net2280 *dev, int mode)
{}

static void defect7374_disable_data_eps(struct net2280 *dev)
{}

static void defect7374_enable_data_eps_zero(struct net2280 *dev)
{}

/* keeping it simple:
 * - one bus driver, initted first;
 * - one function driver, initted second
 *
 * most of the work to support multiple net2280 controllers would
 * be to associate this gadget driver (yes?) with all of them, or
 * perhaps to bind specific drivers to specific devices.
 */

static void usb_reset_228x(struct net2280 *dev)
{}

static void usb_reset_338x(struct net2280 *dev)
{}

static void usb_reset(struct net2280 *dev)
{}

static void usb_reinit_228x(struct net2280 *dev)
{}

static void usb_reinit_338x(struct net2280 *dev)
{}

static void usb_reinit(struct net2280 *dev)
{}

static void ep0_start_228x(struct net2280 *dev)
{}

static void ep0_start_338x(struct net2280 *dev)
{}

static void ep0_start(struct net2280 *dev)
{}

/* 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.
 */
static int net2280_start(struct usb_gadget *_gadget,
		struct usb_gadget_driver *driver)
{}

static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
{}

static int net2280_stop(struct usb_gadget *_gadget)
{}

static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable)
{}

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

/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
 * also works for dma-capable endpoints, in pio mode or just
 * to manually advance the queue after short OUT transfers.
 */
static void handle_ep_small(struct net2280_ep *ep)
{}

static struct net2280_ep *get_ep_by_addr(struct net2280 *dev, u16 wIndex)
{}

static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r)
{}

static void ep_clear_seqnum(struct net2280_ep *ep)
{}

static void handle_stat0_irqs_superspeed(struct net2280 *dev,
		struct net2280_ep *ep, struct usb_ctrlrequest r)
{}

static void usb338x_handle_ep_intr(struct net2280 *dev, u32 stat0)
{}

static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
{}

#define DMA_INTERRUPTS
#define PCI_ERROR_INTERRUPTS

static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
__releases(dev->lock)
__acquires(dev->lock)
{}

static irqreturn_t net2280_irq(int irq, void *_dev)
{}

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

static void gadget_release(struct device *_dev)
{}

/* tear down the binding between this driver and the pci device */

static void net2280_remove(struct pci_dev *pdev)
{}

/* wrap this driver around the specified device, but
 * don't respond over USB until a gadget driver binds to us.
 */

static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{}

/* make sure the board is quiescent; otherwise it will continue
 * generating IRQs across the upcoming reboot.
 */

static void net2280_shutdown(struct pci_dev *pdev)
{}


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

static const struct pci_device_id pci_ids[] =;
MODULE_DEVICE_TABLE(pci, pci_ids);

/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver net2280_pci_driver =;

module_pci_driver();

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