linux/drivers/usb/host/isp116x-hcd.c

// SPDX-License-Identifier: GPL-2.0
/*
 * ISP116x HCD (Host Controller Driver) for USB.
 *
 * Derived from the SL811 HCD, rewritten for ISP116x.
 * Copyright (C) 2005 Olav Kongas <[email protected]>
 *
 * Portions:
 * Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
 * Copyright (C) 2004 David Brownell
 *
 * Periodic scheduling is based on Roman's OHCI code
 * Copyright (C) 1999 Roman Weissgaerber
 *
 */

/*
 * The driver basically works. A number of people have used it with a range
 * of devices.
 *
 * The driver passes all usbtests 1-14.
 *
 * Suspending/resuming of root hub via sysfs works. Remote wakeup works too.
 * And suspending/resuming of platform device works too. Suspend/resume
 * via HCD operations vector is not implemented.
 *
 * Iso transfer support is not implemented. Adding this would include
 * implementing recovery from the failure to service the processed ITL
 * fifo ram in time, which will involve chip reset.
 *
 * TODO:
 + More testing of suspend/resume.
*/

/*
  ISP116x chips require certain delays between accesses to its
  registers. The following timing options exist.

  1. Configure your memory controller (the best)
  2. Implement platform-specific delay function possibly
  combined with configuring the memory controller; see
  include/linux/usb-isp116x.h for more info. Some broken
  memory controllers line LH7A400 SMC need this. Also,
  uncomment for that to work the following
  USE_PLATFORM_DELAY macro.
  3. Use ndelay (easiest, poorest). For that, uncomment
  the following USE_NDELAY macro.
*/
#define USE_PLATFORM_DELAY
//#define USE_NDELAY

//#define DEBUG
//#define VERBOSE
/* Transfer descriptors. See dump_ptd() for printout format  */
//#define PTD_TRACE
/* enqueuing/finishing log of urbs */
//#define URB_TRACE

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/isp116x.h>
#include <linux/usb/hcd.h>
#include <linux/platform_device.h>

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

#include "isp116x.h"

#define DRIVER_VERSION
#define DRIVER_DESC

MODULE_DESCRIPTION();
MODULE_LICENSE();

static const char hcd_name[] =;

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

/*
  Write len bytes to fifo, pad till 32-bit boundary
 */
static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
{}

/*
  Read len bytes from fifo and then read till 32-bit boundary.
 */
static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
{}

/*
  Write ptd's and data for scheduled transfers into
  the fifo ram. Fifo must be empty and ready.
*/
static void pack_fifo(struct isp116x *isp116x)
{}

/*
  Read the processed ptd's and data from fifo ram back to
  URBs' buffers. Fifo must be full and done
*/
static void unpack_fifo(struct isp116x *isp116x)
{}

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

/*
  Set up PTD's.
*/
static void preproc_atl_queue(struct isp116x *isp116x)
{}

/*
  Take done or failed requests out of schedule. Give back
  processed urbs.
*/
static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
			   struct urb *urb, int status)
__releases(isp116x->lock) __acquires(isp116x->lock)
{}

/*
  Analyze transfer results, handle partial transfers and errors
*/
static void postproc_atl_queue(struct isp116x *isp116x)
{}

/*
  Scan transfer lists, schedule transfers, send data off
  to chip.
 */
static void start_atl_transfers(struct isp116x *isp116x)
{}

/*
  Finish the processed transfers
*/
static void finish_atl_transfers(struct isp116x *isp116x)
{}

static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
{}

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

/* usb 1.1 says max 90% of a frame is available for periodic transfers.
 * this driver doesn't promise that much since it's got to handle an
 * IRQ per packet; irq handling latencies also use up that time.
 */

/* out of 1000 us */
#define MAX_PERIODIC_LOAD
static int balance(struct isp116x *isp116x, u16 period, u16 load)
{}

/* NB! ALL the code above this point runs with isp116x->lock
   held, irqs off
*/

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

static int isp116x_urb_enqueue(struct usb_hcd *hcd,
			       struct urb *urb,
			       gfp_t mem_flags)
{}

/*
   Dequeue URBs.
*/
static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
		int status)
{}

static void isp116x_endpoint_disable(struct usb_hcd *hcd,
				     struct usb_host_endpoint *hep)
{}

static int isp116x_get_frame(struct usb_hcd *hcd)
{}

/*
  Adapted from ohci-hub.c. Currently we don't support autosuspend.
*/
static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
{}

static void isp116x_hub_descriptor(struct isp116x *isp116x,
				   struct usb_hub_descriptor *desc)
{}

/* Perform reset of a given port.
   It would be great to just start the reset and let the
   USB core to clear the reset in due time. However,
   root hub ports should be reset for at least 50 ms, while
   our chip stays in reset for about 10 ms. I.e., we must
   repeatedly reset it ourself here.
*/
static inline void root_port_reset(struct isp116x *isp116x, unsigned port)
{}

/* Adapted from ohci-hub.c */
static int isp116x_hub_control(struct usb_hcd *hcd,
			       u16 typeReq,
			       u16 wValue, u16 wIndex, char *buf, u16 wLength)
{}

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

#ifdef CONFIG_DEBUG_FS

static void dump_irq(struct seq_file *s, char *label, u16 mask)
{}

static void dump_int(struct seq_file *s, char *label, u32 mask)
{}

static int isp116x_debug_show(struct seq_file *s, void *unused)
{}
DEFINE_SHOW_ATTRIBUTE();

static void create_debug_file(struct isp116x *isp116x)
{}

static void remove_debug_file(struct isp116x *isp116x)
{}

#else

static inline void create_debug_file(struct isp116x *isp116x) { }
static inline void remove_debug_file(struct isp116x *isp116x) { }

#endif				/* CONFIG_DEBUG_FS */

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

/*
  Software reset - can be called from any contect.
*/
static int isp116x_sw_reset(struct isp116x *isp116x)
{}

static int isp116x_reset(struct usb_hcd *hcd)
{}

static void isp116x_stop(struct usb_hcd *hcd)
{}

/*
  Configure the chip. The chip must be successfully reset by now.
*/
static int isp116x_start(struct usb_hcd *hcd)
{}

#ifdef	CONFIG_PM

static int isp116x_bus_suspend(struct usb_hcd *hcd)
{}

static int isp116x_bus_resume(struct usb_hcd *hcd)
{}

#else

#define isp116x_bus_suspend
#define isp116x_bus_resume

#endif

static const struct hc_driver isp116x_hc_driver =;

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

static void isp116x_remove(struct platform_device *pdev)
{}

static int isp116x_probe(struct platform_device *pdev)
{}

#ifdef	CONFIG_PM
/*
  Suspend of platform device
*/
static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
{}

/*
  Resume platform device
*/
static int isp116x_resume(struct platform_device *dev)
{}

#else

#define isp116x_suspend
#define isp116x_resume

#endif

/* work with hotplug and coldplug */
MODULE_ALIAS();

static struct platform_driver isp116x_driver =;

module_platform_driver();