acpi_pci_n1sdp.c revision 1.5
1/* $NetBSD: acpi_pci_n1sdp.c,v 1.5 2020/09/13 21:41:17 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jared McNeill <jmcneill@invisible.ca>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: acpi_pci_n1sdp.c,v 1.5 2020/09/13 21:41:17 jmcneill Exp $"); 34 35#include <sys/param.h> 36#include <sys/bus.h> 37#include <sys/device.h> 38#include <sys/intr.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/kmem.h> 42#include <sys/cpu.h> 43 44#include <dev/pci/pcireg.h> 45#include <dev/pci/pcivar.h> 46#include <dev/pci/pciconf.h> 47 48#include <dev/acpi/acpivar.h> 49#include <dev/acpi/acpi_pci.h> 50#include <dev/acpi/acpi_mcfg.h> 51 52#include <arm/acpi/acpi_pci_machdep.h> 53 54extern struct bus_space arm_generic_bs_tag; 55 56/* Shared memory location written by the SCP at boot */ 57#define N1SDP_SHARED_MEM_BASE 0x06000000 58 59#define N1SDP_NSEGS 2 60#define N1SDP_TABLE_SIZE 0x4000 61 62#define N1SDP_BUS_SHIFT 20 63#define N1SDP_DEV_SHIFT 15 64#define N1SDP_FUNC_SHIFT 12 65 66struct n1sdp_pcie_discovery_data { 67 uint32_t rc_base_addr; 68 uint32_t nr_bdfs; 69 uint32_t valid_bdfs[0]; 70}; 71 72static struct n1sdp_pcie_discovery_data *n1sdp_data[N1SDP_NSEGS]; 73 74static bool 75acpi_pci_n1sdp_valid(pci_chipset_tag_t pc, pcitag_t tag) 76{ 77 struct acpi_pci_context *ap = pc->pc_conf_v; 78 u_int n, bdfaddr; 79 int b, d, f; 80 81 if (ap->ap_seg >= N1SDP_NSEGS || n1sdp_data[ap->ap_seg] == NULL) 82 return false; 83 84 pci_decompose_tag(pc, tag, &b, &d, &f); 85 86 bdfaddr = (b << N1SDP_BUS_SHIFT) + 87 (d << N1SDP_DEV_SHIFT) + 88 (f << N1SDP_FUNC_SHIFT); 89 90 for (n = 0; n < n1sdp_data[ap->ap_seg]->nr_bdfs; n++) { 91 if (n1sdp_data[ap->ap_seg]->valid_bdfs[n] == bdfaddr) 92 return true; 93 } 94 95 return false; 96} 97 98static int 99acpi_pci_n1sdp_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) 100{ 101 struct acpi_pci_context *ap = pc->pc_conf_v; 102 int b, d, f; 103 104 pci_decompose_tag(pc, tag, &b, &d, &f); 105 106 if (ap->ap_bus == b) { 107 if (d > 0 || f > 0 || reg >= PCI_EXTCONF_SIZE) { 108 *data = -1; 109 return EINVAL; 110 } 111 *data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, reg); 112 return 0; 113 } 114 115 if (!acpi_pci_n1sdp_valid(pc, tag)) { 116 *data = -1; 117 return 0; 118 } 119 120 return acpimcfg_conf_read(pc, tag, reg, data); 121} 122 123static int 124acpi_pci_n1sdp_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 125{ 126 struct acpi_pci_context *ap = pc->pc_conf_v; 127 int b, d, f; 128 129 pci_decompose_tag(pc, tag, &b, &d, &f); 130 131 if (ap->ap_bus == b) { 132 if (d > 0 || f > 0 || reg >= PCI_EXTCONF_SIZE) { 133 return EINVAL; 134 } 135 bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, reg, data); 136 return 0; 137 } 138 139 if (!acpi_pci_n1sdp_valid(pc, tag)) 140 return 0; 141 142 return acpimcfg_conf_write(pc, tag, reg, data); 143} 144 145void 146acpi_pci_n1sdp_init(struct acpi_pci_context *ap) 147{ 148 bus_space_tag_t bst = &arm_generic_bs_tag; 149 bus_space_handle_t bsh; 150 paddr_t pa; 151 int error; 152 u_int n; 153 154 if (ap->ap_seg >= N1SDP_NSEGS) 155 return; 156 157 if (n1sdp_data[ap->ap_seg] == NULL) { 158 aprint_normal_dev(ap->ap_dev, "applying N1SDP quirk for segment %d\n", ap->ap_seg); 159 160 pa = N1SDP_SHARED_MEM_BASE + ap->ap_seg * N1SDP_TABLE_SIZE; 161 if (bus_space_map(bst, pa, N1SDP_TABLE_SIZE, BUS_SPACE_MAP_LINEAR, &bsh) != 0) 162 panic("acpi_pci_n1sdp_init: couldn't map PCIe discovery table"); 163 164 n1sdp_data[ap->ap_seg] = bus_space_vaddr(bst, bsh); 165 if (n1sdp_data[ap->ap_seg] == NULL) 166 panic("acpi_pci_n1sdp_init: couldn't get PCIe discovery table VA"); 167 168 error = bus_space_map(bst, n1sdp_data[ap->ap_seg]->rc_base_addr, PCI_EXTCONF_SIZE, 169 _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &ap->ap_conf_bsh); 170 if (error != 0) 171 panic("acpi_pci_n1sdp_init: couldn't map segment %d", ap->ap_seg); 172 173 aprint_debug_dev(ap->ap_dev, "N1SDP: RC @ 0x%08x, %d devices\n", 174 n1sdp_data[ap->ap_seg]->rc_base_addr, n1sdp_data[ap->ap_seg]->nr_bdfs); 175 for (n = 0; n < n1sdp_data[ap->ap_seg]->nr_bdfs; n++) { 176 const uint32_t bdf = le32toh(n1sdp_data[ap->ap_seg]->valid_bdfs[n]); 177 const int b = (bdf >> N1SDP_BUS_SHIFT) & 0xff; 178 const int d = (bdf >> N1SDP_DEV_SHIFT) & 0x1f; 179 const int f = (bdf >> N1SDP_FUNC_SHIFT) & 0x7; 180 aprint_debug_dev(ap->ap_dev, "N1SDP: %02x:%02x.%x (%08x)\n", b, d, f, bdf); 181 } 182 } 183 184 ap->ap_conf_read = acpi_pci_n1sdp_conf_read; 185 ap->ap_conf_write = acpi_pci_n1sdp_conf_write; 186 187 /* IO space access seems to cause async SErrors, so disable for now */ 188 ap->ap_pciflags_clear = PCI_FLAGS_IO_OKAY; 189} 190