Module Name: src Committed By: jmcneill Date: Sun Feb 2 16:44:25 UTC 2020
Modified Files: src/sys/arch/arm/acpi: acpi_pci_layerscape_gen4.c Log Message: Map and read MCFG space directly instead of going through acpimcfg to simplify access through our tiny config space window. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c diff -u src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c:1.1 src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c:1.2 --- src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c:1.1 Sat Feb 1 13:26:43 2020 +++ src/sys/arch/arm/acpi/acpi_pci_layerscape_gen4.c Sun Feb 2 16:44:25 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_layerscape_gen4.c,v 1.1 2020/02/01 13:26:43 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_layerscape_gen4.c,v 1.2 2020/02/02 16:44:25 jmcneill Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_layerscape_gen4.c,v 1.1 2020/02/01 13:26:43 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_layerscape_gen4.c,v 1.2 2020/02/02 16:44:25 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -78,6 +78,7 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_pci_lay struct acpi_pci_layerscape_gen4 { bus_space_tag_t bst; bus_space_handle_t bsh; + bus_space_handle_t win_bsh; uint8_t rev; kmutex_t lock; }; @@ -120,12 +121,11 @@ static void acpi_pci_layerscape_gen4_select_target(struct acpi_pci_layerscape_gen4 *pcie, pci_chipset_tag_t pc, pcitag_t tag) { - struct acpi_pci_context *ap = pc->pc_conf_v; int b, d, f; pci_decompose_tag(pc, tag, &b, &d, &f); - const uint32_t target = PAB_TARGET_BUS(b - ap->ap_bus) | + const uint32_t target = PAB_TARGET_BUS(b) | PAB_TARGET_DEV(d) | PAB_TARGET_FUNC(f); acpi_pci_layerscape_gen4_ccsr_write4(pcie, PAB_AXI_AMAP_PEX_WIN_L(0), target); @@ -133,7 +133,7 @@ acpi_pci_layerscape_gen4_select_target(s } static bool -acpi_pci_layerscape_gen4_is_tag_okay(pci_chipset_tag_t pc, pcitag_t tag) +acpi_pci_layerscape_gen4_is_tag_okay(pci_chipset_tag_t pc, pcitag_t tag, int reg) { struct acpi_pci_context *ap = pc->pc_conf_v; int b, d, f; @@ -143,6 +143,9 @@ acpi_pci_layerscape_gen4_is_tag_okay(pci if (b <= ap->ap_bus + 1 && d > 0) return false; + if (b != ap->ap_bus) + return acpimcfg_conf_valid(pc, tag, reg); + return true; } @@ -152,11 +155,10 @@ acpi_pci_layerscape_gen4_conf_read(pci_c struct acpi_pci_context *ap = pc->pc_conf_v; struct acpi_pci_layerscape_gen4 *pcie = ap->ap_conf_priv; int b, d, f; - int error; pci_decompose_tag(pc, tag, &b, &d, &f); - if (!acpi_pci_layerscape_gen4_is_tag_okay(pc, tag)) { + if (!acpi_pci_layerscape_gen4_is_tag_okay(pc, tag, reg)) { *data = -1; return EINVAL; } @@ -168,10 +170,9 @@ acpi_pci_layerscape_gen4_conf_read(pci_c if (b == ap->ap_bus) { *data = acpi_pci_layerscape_gen4_ccsr_read4(pcie, reg); - error = 0; } else { acpi_pci_layerscape_gen4_select_target(pcie, pc, tag); - error = acpimcfg_conf_read(pc, pci_make_tag(pc, 0, 0, 0), reg, data); + *data = bus_space_read_4(pcie->bst, pcie->win_bsh, reg); } if (pcie->rev == 0x10 && reg == PCI_ID_REG) @@ -179,7 +180,7 @@ acpi_pci_layerscape_gen4_conf_read(pci_c mutex_exit(&pcie->lock); - return error; + return 0; } static int @@ -188,26 +189,49 @@ acpi_pci_layerscape_gen4_conf_write(pci_ struct acpi_pci_context *ap = pc->pc_conf_v; struct acpi_pci_layerscape_gen4 *pcie = ap->ap_conf_priv; int b, d, f; - int error; pci_decompose_tag(pc, tag, &b, &d, &f); - if (!acpi_pci_layerscape_gen4_is_tag_okay(pc, tag)) + if (!acpi_pci_layerscape_gen4_is_tag_okay(pc, tag, reg)) return EINVAL; mutex_enter(&pcie->lock); if (b == ap->ap_bus) { acpi_pci_layerscape_gen4_ccsr_write4(pcie, reg, data); - error = 0; } else { acpi_pci_layerscape_gen4_select_target(pcie, pc, tag); - error = acpimcfg_conf_write(pc, pci_make_tag(pc, 0, 0, 0), reg, data); + bus_space_write_4(pcie->bst, pcie->win_bsh, reg, data); } mutex_exit(&pcie->lock); - return error; + return 0; +} + +static UINT64 +acpi_pci_layerscape_win_base(ACPI_INTEGER seg) +{ + ACPI_TABLE_MCFG *mcfg; + ACPI_MCFG_ALLOCATION *ama; + ACPI_STATUS rv; + uint32_t off; + int i; + + rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); + if (ACPI_FAILURE(rv)) + return 0; + + off = sizeof(ACPI_TABLE_MCFG); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, off); + for (i = 0; off + sizeof(ACPI_MCFG_ALLOCATION) <= mcfg->Header.Length; i++) { + if (ama->PciSegment == seg) + return ama->Address; + off += sizeof(ACPI_MCFG_ALLOCATION); + ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, off); + } + + return 0; /* not found */ } static ACPI_STATUS @@ -221,6 +245,7 @@ acpi_pci_layerscape_gen4_map(ACPI_HANDLE ACPI_HANDLE parent; ACPI_INTEGER seg; ACPI_STATUS rv; + UINT64 win_base; int error; rv = AcpiGetParent(handle, &parent); @@ -242,6 +267,12 @@ acpi_pci_layerscape_gen4_map(ACPI_HANDLE return AE_NOT_FOUND; } + win_base = acpi_pci_layerscape_win_base(seg); + if (win_base == 0) { + aprint_error_dev(ap->ap_dev, "couldn't find MCFG entry for segment %ld\n", seg); + return AE_NOT_FOUND; + } + error = bus_space_map(ap->ap_bst, mem->ar_base, mem->ar_length, _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &bsh); if (error != 0) @@ -252,6 +283,11 @@ acpi_pci_layerscape_gen4_map(ACPI_HANDLE pcie->bsh = bsh; mutex_init(&pcie->lock, MUTEX_DEFAULT, IPL_HIGH); + error = bus_space_map(ap->ap_bst, win_base, PCI_EXTCONF_SIZE, + _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &pcie->win_bsh); + if (error != 0) + return AE_NO_MEMORY; + const pcireg_t cr = bus_space_read_4(pcie->bst, pcie->bsh, PCI_CLASS_REG); pcie->rev = PCI_REVISION(cr);