linux/arch/x86/kernel/amd_nb.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Shared support code for AMD K8 northbridges and derivatives.
 * Copyright 2006 Andi Kleen, SUSE Labs.
 */

#define pr_fmt(fmt)

#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/spinlock.h>
#include <linux/pci_ids.h>
#include <asm/amd_nb.h>

#define PCI_DEVICE_ID_AMD_17H_ROOT
#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT
#define PCI_DEVICE_ID_AMD_17H_M30H_ROOT
#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT
#define PCI_DEVICE_ID_AMD_17H_MA0H_ROOT
#define PCI_DEVICE_ID_AMD_19H_M10H_ROOT
#define PCI_DEVICE_ID_AMD_19H_M40H_ROOT
#define PCI_DEVICE_ID_AMD_19H_M60H_ROOT
#define PCI_DEVICE_ID_AMD_19H_M70H_ROOT
#define PCI_DEVICE_ID_AMD_1AH_M00H_ROOT
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT
#define PCI_DEVICE_ID_AMD_MI200_ROOT
#define PCI_DEVICE_ID_AMD_MI300_ROOT

#define PCI_DEVICE_ID_AMD_17H_DF_F4
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4
#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4
#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4
#define PCI_DEVICE_ID_AMD_17H_MA0H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M10H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M40H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4
#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4
#define PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4
#define PCI_DEVICE_ID_AMD_MI200_DF_F4
#define PCI_DEVICE_ID_AMD_MI300_DF_F4

/* Protect the PCI config register pairs used for SMN. */
static DEFINE_MUTEX(smn_mutex);

static u32 *flush_words;

static const struct pci_device_id amd_root_ids[] =;

#define PCI_DEVICE_ID_AMD_CNB17H_F4

static const struct pci_device_id amd_nb_misc_ids[] =;

static const struct pci_device_id amd_nb_link_ids[] =;

static const struct pci_device_id hygon_root_ids[] =;

static const struct pci_device_id hygon_nb_misc_ids[] =;

static const struct pci_device_id hygon_nb_link_ids[] =;

const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst =;

static struct amd_northbridge_info amd_northbridges;

u16 amd_nb_num(void)
{}
EXPORT_SYMBOL_GPL();

bool amd_nb_has_feature(unsigned int feature)
{}
EXPORT_SYMBOL_GPL();

struct amd_northbridge *node_to_amd_nb(int node)
{}
EXPORT_SYMBOL_GPL();

static struct pci_dev *next_northbridge(struct pci_dev *dev,
					const struct pci_device_id *ids)
{}

/*
 * SMN accesses may fail in ways that are difficult to detect here in the called
 * functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
 * their own checking based on what behavior they expect.
 *
 * For SMN reads, the returned value may be zero if the register is Read-as-Zero.
 * Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
 * can be checked here, and a proper error code can be returned.
 *
 * But the Read-as-Zero response cannot be verified here. A value of 0 may be
 * correct in some cases, so callers must check that this correct is for the
 * register/fields they need.
 *
 * For SMN writes, success can be determined through a "write and read back"
 * However, this is not robust when done here.
 *
 * Possible issues:
 *
 * 1) Bits that are "Write-1-to-Clear". In this case, the read value should
 *    *not* match the write value.
 *
 * 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
 *    known here.
 *
 * 3) Bits that are "Reserved / Set to 1". Ditto above.
 *
 * Callers of amd_smn_write() should do the "write and read back" check
 * themselves, if needed.
 *
 * For #1, they can see if their target bits got cleared.
 *
 * For #2 and #3, they can check if their target bits got set as intended.
 *
 * This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
 * the operation is considered a success, and the caller does their own
 * checking.
 */
static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
{}

int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
{}
EXPORT_SYMBOL_GPL();

int __must_check amd_smn_write(u16 node, u32 address, u32 value)
{}
EXPORT_SYMBOL_GPL();


static int amd_cache_northbridges(void)
{}

/*
 * Ignores subdevice/subvendor but as far as I can figure out
 * they're useless anyways
 */
bool __init early_is_amd_nb(u32 device)
{}

struct resource *amd_get_mmconfig_range(struct resource *res)
{}

int amd_get_subcaches(int cpu)
{}

int amd_set_subcaches(int cpu, unsigned long mask)
{}

static void amd_cache_gart(void)
{}

void amd_flush_garts(void)
{}
EXPORT_SYMBOL_GPL();

static void __fix_erratum_688(void *info)
{}

/* Apply erratum 688 fix so machines without a BIOS fix work. */
static __init void fix_erratum_688(void)
{}

static __init int init_amd_nbs(void)
{}

/* This has to go after the PCI subsystem */
fs_initcall(init_amd_nbs);