linux/drivers/usb/host/ehci.h

/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2001-2002 by David Brownell
 */

#ifndef __LINUX_EHCI_HCD_H
#define __LINUX_EHCI_HCD_H

/* definitions used for the EHCI driver */

/*
 * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
 * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on
 * the host controller implementation.
 *
 * To facilitate the strongest possible byte-order checking from "sparse"
 * and so on, we use __leXX unless that's not practical.
 */
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
#else
#define __hc32
#define __hc16
#endif

/* statistics can be kept for tuning/monitoring */
#ifdef CONFIG_DYNAMIC_DEBUG
#define EHCI_STATS
#endif

struct ehci_stats {};

/*
 * Scheduling and budgeting information for periodic transfers, for both
 * high-speed devices and full/low-speed devices lying behind a TT.
 */
struct ehci_per_sched {};
#define NO_FRAME

/* ehci_hcd->lock guards shared data against other CPUs:
 *   ehci_hcd:	async, unlink, periodic (and shadow), ...
 *   usb_host_endpoint: hcpriv
 *   ehci_qh:	qh_next, qtd_list
 *   ehci_qtd:	qtd_list
 *
 * Also, hold this lock when talking to HC registers or
 * when updating hw_* fields in shared qh/qtd/... structures.
 */

#define EHCI_MAX_ROOT_PORTS

/*
 * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the
 * controller may be doing DMA.  Lower values mean there's no DMA.
 */
enum ehci_rh_state {};

/*
 * Timer events, ordered by increasing delay length.
 * Always update event_delays_ns[] and event_handlers[] (defined in
 * ehci-timer.c) in parallel with this list.
 */
enum ehci_hrtimer_event {};
#define EHCI_HRTIMER_NO_EVENT

struct ehci_hcd {};

/* convert between an HCD pointer and the corresponding EHCI_HCD */
static inline struct ehci_hcd *hcd_to_ehci(struct usb_hcd *hcd)
{}
static inline struct usb_hcd *ehci_to_hcd(struct ehci_hcd *ehci)
{}

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

#include <linux/usb/ehci_def.h>

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

#define QTD_NEXT(ehci, dma)

/*
 * EHCI Specification 0.95 Section 3.5
 * QTD: describe data transfer components (buffer, direction, ...)
 * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
 *
 * These are associated only with "QH" (Queue Head) structures,
 * used with control, bulk, and interrupt transfers.
 */
struct ehci_qtd {} __aligned();

/* PID Codes that are used here, from EHCI specification, Table 3-16. */
#define PID_CODE_OUT
#define PID_CODE_IN
#define PID_CODE_SETUP

/* mask NakCnt+T in qh->hw_alt_next */
#define QTD_MASK(ehci)

#define IS_SHORT_READ(token)

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

/* type tag from {qh,itd,sitd,fstn}->hw_next */
#define Q_NEXT_TYPE(ehci, dma)

/*
 * Now the following defines are not converted using the
 * cpu_to_le32() macro anymore, since we have to support
 * "dynamic" switching between be and le support, so that the driver
 * can be used on one system with SoC EHCI controller using big-endian
 * descriptors as well as a normal little-endian PCI EHCI controller.
 */
/* values for that type tag */
#define Q_TYPE_ITD
#define Q_TYPE_QH
#define Q_TYPE_SITD
#define Q_TYPE_FSTN

/* next async queue entry, or pointer to interrupt/periodic QH */
#define QH_NEXT(ehci, dma)

/* for periodic/async schedules and qtd lists, mark end of list */
#define EHCI_LIST_END(ehci)

/*
 * Entries in periodic shadow table are pointers to one of four kinds
 * of data structure.  That's dictated by the hardware; a type tag is
 * encoded in the low bits of the hardware's periodic schedule.  Use
 * Q_NEXT_TYPE to get the tag.
 *
 * For entries in the async schedule, the type tag always says "qh".
 */
ehci_shadow;

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

/*
 * EHCI Specification 0.95 Section 3.6
 * QH: describes control/bulk/interrupt endpoints
 * See Fig 3-7 "Queue Head Structure Layout".
 *
 * These appear in both the async and (for interrupt) periodic schedules.
 */

/* first part defined by EHCI spec */
struct ehci_qh_hw {} __aligned();

struct ehci_qh {};

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

/* description of one iso transaction (up to 3 KB data if highspeed) */
struct ehci_iso_packet {};

/* temporary schedule data for packets from iso urbs (both speeds)
 * each packet is one logical usb transaction to the device (not TT),
 * beginning at stream->next_uframe
 */
struct ehci_iso_sched {};

/*
 * ehci_iso_stream - groups all (s)itds for this endpoint.
 * acts like a qh would, if EHCI had them for ISO.
 */
struct ehci_iso_stream {};

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

/*
 * EHCI Specification 0.95 Section 3.3
 * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
 *
 * Schedule records for high speed iso xfers
 */
struct ehci_itd {} __aligned();

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

/*
 * EHCI Specification 0.95 Section 3.4
 * siTD, aka split-transaction isochronous Transfer Descriptor
 *       ... describe full speed iso xfers through TT in hubs
 * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
 */
struct ehci_sitd {} __aligned();

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

/*
 * EHCI Specification 0.96 Section 3.7
 * Periodic Frame Span Traversal Node (FSTN)
 *
 * Manages split interrupt transactions (using TT) that span frame boundaries
 * into uframes 0/1; see 4.12.2.2.  In those uframes, a "save place" FSTN
 * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
 * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
 */
struct ehci_fstn {} __aligned();

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

/*
 * USB-2.0 Specification Sections 11.14 and 11.18
 * Scheduling and budgeting split transactions using TTs
 *
 * A hub can have a single TT for all its ports, or multiple TTs (one for each
 * port).  The bandwidth and budgeting information for the full/low-speed bus
 * below each TT is self-contained and independent of the other TTs or the
 * high-speed bus.
 *
 * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated
 * to an interrupt or isochronous endpoint for each frame.  "Budget" refers to
 * the best-case estimate of the number of full-speed bytes allocated to an
 * endpoint for each microframe within an allocated frame.
 *
 * Removal of an endpoint invalidates a TT's budget.  Instead of trying to
 * keep an up-to-date record, we recompute the budget when it is needed.
 */

struct ehci_tt {};

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

/* Prepare the PORTSC wakeup flags during controller suspend/resume */

#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)

#define ehci_prepare_ports_for_controller_resume(ehci)

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

#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT

/*
 * Some EHCI controllers have a Transaction Translator built into the
 * root hub. This is a non-standard feature.  Each controller will need
 * to add code to the following inline functions, and call them as
 * needed (mostly in root hub code).
 */

#define ehci_is_TDI(e)

/* Returns the speed of a device attached to a port on the root hub. */
static inline unsigned int
ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
{}

#else

#define ehci_is_TDI

#define ehci_port_speed
#endif

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

#ifdef CONFIG_PPC_83xx
/* Some Freescale processors have an erratum in which the TT
 * port number in the queue head was 0..N-1 instead of 1..N.
 */
#define ehci_has_fsl_portno_bug
#else
#define ehci_has_fsl_portno_bug(e)
#endif

#define PORTSC_FSL_PFSC

#if defined(CONFIG_PPC_85xx)
/* Some Freescale processors have an erratum (USB A-005275) in which
 * incoming packets get corrupted in HS mode
 */
#define ehci_has_fsl_hs_errata
#else
#define ehci_has_fsl_hs_errata(e)
#endif

/*
 * Some Freescale/NXP processors have an erratum (USB A-005697)
 * in which we need to wait for 10ms for bus to enter suspend mode
 * after setting SUSP bit.
 */
#define ehci_has_fsl_susp_errata(e)

/*
 * Some Freescale/NXP processors using ChipIdea IP have a bug in which
 * disabling the port (PE is cleared) does not cause PEC to be asserted
 * when frame babble is detected.
 */
#define ehci_has_ci_pec_bug(e, portsc)

/*
 * While most USB host controllers implement their registers in
 * little-endian format, a minority (celleb companion chip) implement
 * them in big endian format.
 *
 * This attempts to support either format at compile time without a
 * runtime penalty, or both formats with the additional overhead
 * of checking a flag bit.
 *
 * ehci_big_endian_capbase is a special quirk for controllers that
 * implement the HC capability registers as separate registers and not
 * as fields of a 32-bit register.
 */

#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
#define ehci_big_endian_mmio
#define ehci_big_endian_capbase
#else
#define ehci_big_endian_mmio(e)
#define ehci_big_endian_capbase(e)
#endif

/*
 * Big-endian read/write functions are arch-specific.
 * Other arches can be added if/when they're needed.
 */
#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX)
#define readl_be
#define writel_be
#endif

static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
		__u32 __iomem *regs)
{}

#ifdef CONFIG_SOC_IMX28
static inline void imx28_ehci_writel(const unsigned int val,
		volatile __u32 __iomem *addr)
{
	__asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr));
}
#else
static inline void imx28_ehci_writel(const unsigned int val,
		volatile __u32 __iomem *addr)
{}
#endif
static inline void ehci_writel(const struct ehci_hcd *ehci,
		const unsigned int val, __u32 __iomem *regs)
{}

/*
 * On certain ppc-44x SoC there is a HW issue, that could only worked around with
 * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch.
 * Other common bits are dependent on has_amcc_usb23 quirk flag.
 */
#ifdef CONFIG_44x
static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational)
{
	u32 hc_control;

	hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS);
	if (operational)
		hc_control |= OHCI_USB_OPER;
	else
		hc_control |= OHCI_USB_SUSPEND;

	writel_be(hc_control, ehci->ohci_hcctrl_reg);
	(void) readl_be(ehci->ohci_hcctrl_reg);
}
#else
static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational)
{}
#endif

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

/*
 * The AMCC 440EPx not only implements its EHCI registers in big-endian
 * format, but also its DMA data structures (descriptors).
 *
 * EHCI controllers accessed through PCI work normally (little-endian
 * everywhere), so we won't bother supporting a BE-only mode for now.
 */
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
#define ehci_big_endian_desc

/* cpu to ehci */
static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x)
{
	return ehci_big_endian_desc(ehci)
		? (__force __hc32)cpu_to_be32(x)
		: (__force __hc32)cpu_to_le32(x);
}

/* ehci to cpu */
static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x)
{
	return ehci_big_endian_desc(ehci)
		? be32_to_cpu((__force __be32)x)
		: le32_to_cpu((__force __le32)x);
}

static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x)
{
	return ehci_big_endian_desc(ehci)
		? be32_to_cpup((__force __be32 *)x)
		: le32_to_cpup((__force __le32 *)x);
}

#else

/* cpu to ehci */
static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x)
{}

/* ehci to cpu */
static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x)
{}

static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x)
{}

#endif

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

#define ehci_dbg(ehci, fmt, args...)
#define ehci_err(ehci, fmt, args...)
#define ehci_info(ehci, fmt, args...)
#define ehci_warn(ehci, fmt, args...)

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

/* Declarations of things exported for use by ehci platform drivers */

struct ehci_driver_overrides {};

extern void	ehci_init_driver(struct hc_driver *drv,
				const struct ehci_driver_overrides *over);
extern int	ehci_setup(struct usb_hcd *hcd);
extern int	ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr,
				u32 mask, u32 done, int usec);
extern int	ehci_reset(struct ehci_hcd *ehci);

extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
extern int	ehci_resume(struct usb_hcd *hcd, bool force_reset);
extern void	ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
			bool suspending, bool do_wakeup);

extern int	ehci_hub_control(struct usb_hcd	*hcd, u16 typeReq, u16 wValue,
				 u16 wIndex, char *buf, u16 wLength);

#endif /* __LINUX_EHCI_HCD_H */