drivers/usb/host/pci-quirks.c

Source file repositories/reference/linux-study-clean/drivers/usb/host/pci-quirks.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/host/pci-quirks.c
Extension
.c
Size
36184 bytes
Lines
1307
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct amd_chipset_type {
	enum amd_chipset_gen gen;
	u8 rev;
};

static struct amd_chipset_info {
	struct pci_dev	*nb_dev;
	struct pci_dev	*smbus_dev;
	int nb_type;
	struct amd_chipset_type sb_type;
	int isoc_reqs;
	int probe_count;
	bool need_pll_quirk;
} 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)
{
	u8 rev = 0;
	pinfo->sb_type.gen = AMD_CHIPSET_UNKNOWN;

	pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
			PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
	if (pinfo->smbus_dev) {
		rev = pinfo->smbus_dev->revision;
		if (rev >= 0x10 && rev <= 0x1f)
			pinfo->sb_type.gen = AMD_CHIPSET_SB600;
		else if (rev >= 0x30 && rev <= 0x3f)
			pinfo->sb_type.gen = AMD_CHIPSET_SB700;
		else if (rev >= 0x40 && rev <= 0x4f)
			pinfo->sb_type.gen = AMD_CHIPSET_SB800;
	} else {
		pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
				PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);

		if (pinfo->smbus_dev) {
			rev = pinfo->smbus_dev->revision;
			if (rev >= 0x11 && rev <= 0x14)
				pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
			else if (rev >= 0x15 && rev <= 0x18)
				pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
			else if (rev >= 0x39 && rev <= 0x3a)
				pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
		} else {
			pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
							  0x145c, NULL);
			if (pinfo->smbus_dev) {
				rev = pinfo->smbus_dev->revision;
				pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
			} else {
				pinfo->sb_type.gen = NOT_AMD_CHIPSET;
				return 0;
			}
		}
	}
	pinfo->sb_type.rev = rev;
	return 1;
}

void sb800_prefetch(struct device *dev, int on)
{
	u16 misc;
	struct pci_dev *pdev = to_pci_dev(dev);

	pci_read_config_word(pdev, 0x50, &misc);
	if (on == 0)
		pci_write_config_word(pdev, 0x50, misc & 0xfcff);
	else
		pci_write_config_word(pdev, 0x50, misc | 0x0300);
}
EXPORT_SYMBOL_GPL(sb800_prefetch);

static void usb_amd_find_chipset_info(void)
{
	unsigned long flags;
	struct amd_chipset_info info = { };

	spin_lock_irqsave(&amd_lock, flags);

	/* probe only once */
	if (amd_chipset.probe_count > 0) {

Annotation

Implementation Notes