linux/drivers/usb/host/pci-quirks.c

// SPDX-License-Identifier: GPL-2.0
/*
 * This file contains code to reset and initialize USB host controllers.
 * Some of it includes work-arounds for PCI hardware and BIOS quirks.
 * It may need to run early during booting -- before USB would normally
 * initialize -- to ensure that Linux doesn't use any legacy modes.
 *
 *  Copyright (c) 1999 Martin Mares <[email protected]>
 *  (and others)
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/of.h>
#include <linux/iopoll.h>

#include "pci-quirks.h"
#include "xhci-ext-caps.h"


#define UHCI_USBLEGSUP
#define UHCI_USBCMD
#define UHCI_USBINTR
#define UHCI_USBLEGSUP_RWC
#define UHCI_USBLEGSUP_RO
#define UHCI_USBCMD_RUN
#define UHCI_USBCMD_HCRESET
#define UHCI_USBCMD_EGSM
#define UHCI_USBCMD_CONFIGURE
#define UHCI_USBINTR_RESUME

#define OHCI_CONTROL
#define OHCI_CMDSTATUS
#define OHCI_INTRSTATUS
#define OHCI_INTRENABLE
#define OHCI_INTRDISABLE
#define OHCI_FMINTERVAL
#define OHCI_HCFS
#define OHCI_HCR
#define OHCI_OCR
#define OHCI_CTRL_RWC
#define OHCI_CTRL_IR
#define OHCI_INTR_OC

#define EHCI_HCC_PARAMS
#define EHCI_USBCMD
#define EHCI_USBCMD_RUN
#define EHCI_USBSTS
#define EHCI_USBSTS_HALTED
#define EHCI_USBINTR
#define EHCI_CONFIGFLAG
#define EHCI_USBLEGSUP
#define EHCI_USBLEGSUP_BIOS
#define EHCI_USBLEGSUP_OS
#define EHCI_USBLEGCTLSTS
#define EHCI_USBLEGCTLSTS_SOOE

/* ASMEDIA quirk use */
#define ASMT_DATA_WRITE0_REG
#define ASMT_DATA_WRITE1_REG
#define ASMT_CONTROL_REG
#define ASMT_CONTROL_WRITE_BIT
#define ASMT_WRITEREG_CMD
#define ASMT_FLOWCTL_ADDR
#define ASMT_FLOWCTL_DATA
#define ASMT_PSEUDO_DATA

/* Intel quirk use */
#define USB_INTEL_XUSB2PR
#define USB_INTEL_USB2PRM
#define USB_INTEL_USB3_PSSEN
#define USB_INTEL_USB3PRM

#ifdef CONFIG_USB_PCI_AMD
/* AMD quirk use */
#define AB_REG_BAR_LOW
#define AB_REG_BAR_HIGH
#define AB_REG_BAR_SB700
#define AB_INDX(addr)
#define AB_DATA(addr)
#define AX_INDXC
#define AX_DATAC

#define PT_ADDR_INDX
#define PT_READ_INDX
#define PT_SIG_1_ADDR
#define PT_SIG_2_ADDR
#define PT_SIG_3_ADDR
#define PT_SIG_4_ADDR
#define PT_SIG_1_DATA
#define PT_SIG_2_DATA
#define PT_SIG_3_DATA
#define PT_SIG_4_DATA
#define PT4_P1_REG
#define PT4_P2_REG
#define PT2_P1_REG
#define PT2_P2_REG
#define PT1_P1_REG
#define PT1_P2_REG

#define NB_PCIE_INDX_ADDR
#define NB_PCIE_INDX_DATA
#define PCIE_P_CNTL
#define BIF_NB
#define NB_PIF0_PWRDOWN_0
#define NB_PIF0_PWRDOWN_1

/*
 * amd_chipset_gen values represent AMD different chipset generations
 */
enum amd_chipset_gen {};

struct amd_chipset_type {};

static struct amd_chipset_info {} amd_chipset;

static DEFINE_SPINLOCK(amd_lock);

/*
 * amd_chipset_sb_type_init - initialize amd chipset southbridge type
 *
 * AMD FCH/SB generation and revision is identified by SMBus controller
 * vendor, device and revision IDs.
 *
 * Returns: 1 if it is an AMD chipset, 0 otherwise.
 */
static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
{}

void sb800_prefetch(struct device *dev, int on)
{}
EXPORT_SYMBOL_GPL();

static void usb_amd_find_chipset_info(void)
{}

int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev)
{}
EXPORT_SYMBOL_GPL();

bool usb_amd_hang_symptom_quirk(void)
{}
EXPORT_SYMBOL_GPL();

bool usb_amd_prefetch_quirk(void)
{}
EXPORT_SYMBOL_GPL();

bool usb_amd_quirk_pll_check(void)
{}
EXPORT_SYMBOL_GPL();

/*
 * The hardware normally enables the A-link power management feature, which
 * lets the system lower the power consumption in idle states.
 *
 * This USB quirk prevents the link going into that lower power state
 * during isochronous transfers.
 *
 * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of
 * some AMD platforms may stutter or have breaks occasionally.
 */
static void usb_amd_quirk_pll(int disable)
{}

void usb_amd_quirk_pll_disable(void)
{}
EXPORT_SYMBOL_GPL();

void usb_amd_quirk_pll_enable(void)
{}
EXPORT_SYMBOL_GPL();

void usb_amd_dev_put(void)
{}
EXPORT_SYMBOL_GPL();

/*
 * Check if port is disabled in BIOS on AMD Promontory host.
 * BIOS Disabled ports may wake on connect/disconnect and need
 * driver workaround to keep them disabled.
 * Returns true if port is marked disabled.
 */
bool usb_amd_pt_check_port(struct device *device, int port)
{}
EXPORT_SYMBOL_GPL();
#endif /* CONFIG_USB_PCI_AMD */

static int usb_asmedia_wait_write(struct pci_dev *pdev)
{}

void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
{}
EXPORT_SYMBOL_GPL();

static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
{}

#define mmio_enabled(dev)

#if defined(CONFIG_HAS_IOPORT) && IS_ENABLED(CONFIG_USB_UHCI_HCD)
/*
 * Make sure the controller is completely inactive, unable to
 * generate interrupts or do DMA.
 */
void uhci_reset_hc(struct pci_dev *pdev, unsigned long base)
{}
EXPORT_SYMBOL_GPL();

/*
 * Initialize a controller that was newly discovered or has just been
 * resumed.  In either case we can't be sure of its previous state.
 *
 * Returns: 1 if the controller was reset, 0 otherwise.
 */
int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
{}
EXPORT_SYMBOL_GPL();

#define pio_enabled(dev)

static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
{}

#else /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */

static void quirk_usb_handoff_uhci(struct pci_dev *pdev) {}

#endif /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */

static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
{}

static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
{}

static const struct dmi_system_id ehci_dmi_nohandoff_table[] =;

static void ehci_bios_handoff(struct pci_dev *pdev,
					void __iomem *op_reg_base,
					u32 cap, u8 offset)
{}

static void quirk_usb_disable_ehci(struct pci_dev *pdev)
{}

/*
 * handshake - spin reading a register until handshake completes
 * @ptr: address of hc register to be read
 * @mask: bits to look at in result of read
 * @done: value of those bits when handshake succeeds
 * @wait_usec: timeout in microseconds
 * @delay_usec: delay in microseconds to wait between polling
 *
 * Polls a register every delay_usec microseconds.
 * Returns 0 when the mask bits have the value done.
 * Returns -ETIMEDOUT if this condition is not true after
 * wait_usec microseconds have passed.
 */
static int handshake(void __iomem *ptr, u32 mask, u32 done,
		int wait_usec, int delay_usec)
{}

/*
 * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that
 * share some number of ports.  These ports can be switched between either
 * controller.  Not all of the ports under the EHCI host controller may be
 * switchable.
 *
 * The ports should be switched over to xHCI before PCI probes for any device
 * start.  This avoids active devices under EHCI being disconnected during the
 * port switchover, which could cause loss of data on USB storage devices, or
 * failed boot when the root file system is on a USB mass storage device and is
 * enumerated under EHCI first.
 *
 * We write into the xHC's PCI configuration space in some Intel-specific
 * registers to switch the ports over.  The USB 3.0 terminations and the USB
 * 2.0 data wires are switched separately.  We want to enable the SuperSpeed
 * terminations before switching the USB 2.0 wires over, so that USB 3.0
 * devices connect at SuperSpeed, rather than at USB 2.0 speeds.
 */
void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
{}
EXPORT_SYMBOL_GPL();

void usb_disable_xhci_ports(struct pci_dev *xhci_pdev)
{}
EXPORT_SYMBOL_GPL();

/*
 * PCI Quirks for xHCI.
 *
 * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS.
 * It signals to the BIOS that the OS wants control of the host controller,
 * and then waits 1 second for the BIOS to hand over control.
 * If we timeout, assume the BIOS is broken and take control anyway.
 */
static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
{}

static void quirk_usb_early_handoff(struct pci_dev *pdev)
{}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
			PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff);