ARM64: Add quirk mechanism to pci_host_generic_acpi
Add few quirks which are necessary to use AHCI on ThX2 Submitted by: Patryk Duda <pdk@semihalf.com> Obtained from: Semihalf Sponsored by: Cavium Differential revision: https://reviews.freebsd.org/D15929
This commit is contained in:
parent
db2156bc49
commit
d50fbe3fe2
@ -69,6 +69,25 @@ __FBSDID("$FreeBSD$");
|
||||
(((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT) | \
|
||||
((reg) & PCIE_REG_MASK))
|
||||
|
||||
typedef void (*pci_host_generic_quirk_function)(device_t);
|
||||
|
||||
struct pci_host_generic_quirk_entry {
|
||||
int impl;
|
||||
int part;
|
||||
int var;
|
||||
int rev;
|
||||
pci_host_generic_quirk_function func;
|
||||
};
|
||||
|
||||
struct pci_host_generic_block_entry {
|
||||
int impl;
|
||||
int part;
|
||||
int var;
|
||||
int rev;
|
||||
int bus;
|
||||
int slot;
|
||||
};
|
||||
|
||||
/* Forward prototypes */
|
||||
|
||||
static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
|
||||
@ -80,6 +99,21 @@ static int generic_pcie_read_ivar(device_t dev, device_t child, int index,
|
||||
uintptr_t *result);
|
||||
static int generic_pcie_write_ivar(device_t dev, device_t child, int index,
|
||||
uintptr_t value);
|
||||
static void pci_host_generic_apply_quirks(device_t);
|
||||
static void thunderx2_ahci_bar_quirk(device_t);
|
||||
|
||||
struct pci_host_generic_quirk_entry pci_host_generic_quirks[] =
|
||||
{
|
||||
{CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0, 0, thunderx2_ahci_bar_quirk},
|
||||
{0, 0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
struct pci_host_generic_block_entry pci_host_generic_blocked[] =
|
||||
{
|
||||
/* ThunderX2 AHCI on second socket */
|
||||
{CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0, 0, 0x80, 0x10},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int
|
||||
pci_host_generic_core_attach(device_t dev)
|
||||
@ -134,9 +168,30 @@ pci_host_generic_core_attach(device_t dev)
|
||||
return (error);
|
||||
}
|
||||
|
||||
pci_host_generic_apply_quirks(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_host_generic_apply_quirks(device_t dev)
|
||||
{
|
||||
struct pci_host_generic_quirk_entry *quirk;
|
||||
|
||||
quirk = pci_host_generic_quirks;
|
||||
while (1) {
|
||||
if (quirk->impl == 0)
|
||||
break;
|
||||
|
||||
if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
|
||||
quirk->impl, quirk->part, quirk->var, quirk->rev) &&
|
||||
quirk->func != NULL)
|
||||
quirk->func(dev);
|
||||
|
||||
quirk++;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
|
||||
u_int func, u_int reg, int bytes)
|
||||
@ -146,11 +201,25 @@ generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
|
||||
bus_space_tag_t t;
|
||||
uint64_t offset;
|
||||
uint32_t data;
|
||||
struct pci_host_generic_block_entry *block;
|
||||
|
||||
if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
|
||||
(func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
|
||||
return (~0U);
|
||||
|
||||
block = pci_host_generic_blocked;
|
||||
while (1) {
|
||||
if (block->impl == 0)
|
||||
break;
|
||||
|
||||
if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
|
||||
block->impl, block->part, block->var, block->rev) &&
|
||||
block->bus == bus && block->slot == slot)
|
||||
return (~0);
|
||||
|
||||
block++;
|
||||
}
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
|
||||
@ -392,3 +461,20 @@ static device_method_t generic_pcie_methods[] = {
|
||||
|
||||
DEFINE_CLASS_0(pcib, generic_pcie_core_driver,
|
||||
generic_pcie_methods, sizeof(struct generic_pcie_core_softc));
|
||||
|
||||
static void thunderx2_ahci_bar_quirk(device_t dev)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* On ThunderX2, AHCI BAR2 address is wrong. It needs to precisely
|
||||
* match the one described in datasheet. Fixup it unconditionally.
|
||||
*/
|
||||
if (device_get_unit(dev) == 0) {
|
||||
device_printf(dev, "running AHCI BAR fixup\n");
|
||||
PCIB_WRITE_CONFIG(dev, 0, 16, 0, 0x18, 0x01440000, 4);
|
||||
PCIB_WRITE_CONFIG(dev, 0, 16, 0, 0x1c, 0x40, 4);
|
||||
PCIB_WRITE_CONFIG(dev, 0, 16, 1, 0x18, 0x01450000, 4);
|
||||
PCIB_WRITE_CONFIG(dev, 0, 16, 1, 0x1c, 0x40, 4);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user