1 1.22 jmcneill /* $NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.17 ad * Copyright (c) 2018, 2020 The NetBSD Foundation, Inc. 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * This code is derived from software contributed to The NetBSD Foundation 8 1.1 jmcneill * by Jared McNeill <jmcneill (at) invisible.ca>. 9 1.1 jmcneill * 10 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 11 1.1 jmcneill * modification, are permitted provided that the following conditions 12 1.1 jmcneill * are met: 13 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 14 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 15 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 17 1.1 jmcneill * documentation and/or other materials provided with the distribution. 18 1.1 jmcneill * 19 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jmcneill */ 31 1.1 jmcneill 32 1.19 jmcneill #include "opt_pci.h" 33 1.19 jmcneill 34 1.14 jmcneill #define _INTR_PRIVATE 35 1.14 jmcneill 36 1.1 jmcneill #include <sys/cdefs.h> 37 1.22 jmcneill __KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $"); 38 1.1 jmcneill 39 1.1 jmcneill #include <sys/param.h> 40 1.1 jmcneill #include <sys/bus.h> 41 1.1 jmcneill #include <sys/device.h> 42 1.1 jmcneill #include <sys/intr.h> 43 1.1 jmcneill #include <sys/systm.h> 44 1.1 jmcneill #include <sys/kernel.h> 45 1.1 jmcneill #include <sys/queue.h> 46 1.1 jmcneill #include <sys/mutex.h> 47 1.1 jmcneill #include <sys/kmem.h> 48 1.17 ad #include <sys/cpu.h> 49 1.1 jmcneill 50 1.1 jmcneill #include <arm/cpufunc.h> 51 1.1 jmcneill 52 1.14 jmcneill #include <arm/pic/picvar.h> 53 1.14 jmcneill 54 1.1 jmcneill #include <dev/pci/pcireg.h> 55 1.1 jmcneill #include <dev/pci/pcivar.h> 56 1.1 jmcneill #include <dev/pci/pciconf.h> 57 1.1 jmcneill 58 1.1 jmcneill #include <dev/acpi/acpivar.h> 59 1.1 jmcneill #include <dev/acpi/acpi_mcfg.h> 60 1.1 jmcneill #include <dev/acpi/acpi_pci.h> 61 1.1 jmcneill 62 1.9 jmcneill #include <arm/acpi/acpi_iort.h> 63 1.2 jmcneill #include <arm/acpi/acpi_pci_machdep.h> 64 1.2 jmcneill 65 1.19 jmcneill #ifdef PCI_SMCCC 66 1.19 jmcneill #include <arm/pci/pci_smccc.h> 67 1.19 jmcneill #endif 68 1.19 jmcneill 69 1.3 jmcneill #include <arm/pci/pci_msi_machdep.h> 70 1.1 jmcneill 71 1.1 jmcneill struct acpi_pci_prt { 72 1.7 jmcneill u_int prt_segment; 73 1.1 jmcneill u_int prt_bus; 74 1.22 jmcneill u_int prt_bridge_dev; 75 1.22 jmcneill bool prt_derived; 76 1.1 jmcneill ACPI_HANDLE prt_handle; 77 1.1 jmcneill TAILQ_ENTRY(acpi_pci_prt) prt_list; 78 1.1 jmcneill }; 79 1.1 jmcneill 80 1.1 jmcneill static TAILQ_HEAD(, acpi_pci_prt) acpi_pci_irq_routes = 81 1.1 jmcneill TAILQ_HEAD_INITIALIZER(acpi_pci_irq_routes); 82 1.1 jmcneill 83 1.13 jmcneill struct acpi_pci_pct { 84 1.13 jmcneill struct acpi_pci_context pct_ap; 85 1.13 jmcneill TAILQ_ENTRY(acpi_pci_pct) pct_list; 86 1.13 jmcneill }; 87 1.13 jmcneill 88 1.13 jmcneill static TAILQ_HEAD(, acpi_pci_pct) acpi_pci_chipset_tags = 89 1.13 jmcneill TAILQ_HEAD_INITIALIZER(acpi_pci_chipset_tags); 90 1.13 jmcneill 91 1.14 jmcneill struct acpi_pci_intr { 92 1.14 jmcneill struct pic_softc pi_pic; 93 1.14 jmcneill int pi_irqbase; 94 1.14 jmcneill int pi_irq; 95 1.14 jmcneill uint32_t pi_unblocked; 96 1.14 jmcneill void *pi_ih; 97 1.14 jmcneill TAILQ_ENTRY(acpi_pci_intr) pi_list; 98 1.14 jmcneill }; 99 1.14 jmcneill 100 1.14 jmcneill static TAILQ_HEAD(, acpi_pci_intr) acpi_pci_intrs = 101 1.14 jmcneill TAILQ_HEAD_INITIALIZER(acpi_pci_intrs); 102 1.14 jmcneill 103 1.19 jmcneill static const struct acpi_pci_quirk acpi_pci_mcfg_quirks[] = { 104 1.13 jmcneill /* OEM ID OEM Table ID Revision Seg Func */ 105 1.13 jmcneill { "AMAZON", "GRAVITON", 0, -1, acpi_pci_graviton_init }, 106 1.13 jmcneill { "ARMLTD", "ARMN1SDP", 0x20181101, 0, acpi_pci_n1sdp_init }, 107 1.13 jmcneill { "ARMLTD", "ARMN1SDP", 0x20181101, 1, acpi_pci_n1sdp_init }, 108 1.15 jmcneill { "NXP ", "LX2160 ", 0, -1, acpi_pci_layerscape_gen4_init }, 109 1.13 jmcneill }; 110 1.13 jmcneill 111 1.19 jmcneill #ifdef PCI_SMCCC 112 1.19 jmcneill static const struct acpi_pci_quirk acpi_pci_smccc_quirk = { 113 1.19 jmcneill .q_segment = -1, 114 1.19 jmcneill .q_init = acpi_pci_smccc_init, 115 1.19 jmcneill }; 116 1.19 jmcneill #endif 117 1.19 jmcneill 118 1.13 jmcneill pci_chipset_tag_t acpi_pci_md_get_chipset_tag(struct acpi_softc *, int, int); 119 1.13 jmcneill 120 1.1 jmcneill static void acpi_pci_md_attach_hook(device_t, device_t, 121 1.1 jmcneill struct pcibus_attach_args *); 122 1.1 jmcneill static int acpi_pci_md_bus_maxdevs(void *, int); 123 1.1 jmcneill static pcitag_t acpi_pci_md_make_tag(void *, int, int, int); 124 1.1 jmcneill static void acpi_pci_md_decompose_tag(void *, pcitag_t, int *, int *, int *); 125 1.6 jmcneill static u_int acpi_pci_md_get_segment(void *); 126 1.9 jmcneill static uint32_t acpi_pci_md_get_devid(void *, uint32_t); 127 1.16 jmcneill static uint32_t acpi_pci_md_get_frameid(void *, uint32_t); 128 1.1 jmcneill static pcireg_t acpi_pci_md_conf_read(void *, pcitag_t, int); 129 1.1 jmcneill static void acpi_pci_md_conf_write(void *, pcitag_t, int, pcireg_t); 130 1.1 jmcneill static int acpi_pci_md_conf_hook(void *, int, int, int, pcireg_t); 131 1.1 jmcneill static void acpi_pci_md_conf_interrupt(void *, int, int, int, int, int *); 132 1.1 jmcneill 133 1.1 jmcneill static int acpi_pci_md_intr_map(const struct pci_attach_args *, 134 1.1 jmcneill pci_intr_handle_t *); 135 1.1 jmcneill static const char *acpi_pci_md_intr_string(void *, pci_intr_handle_t, 136 1.1 jmcneill char *, size_t); 137 1.1 jmcneill static const struct evcnt *acpi_pci_md_intr_evcnt(void *, pci_intr_handle_t); 138 1.1 jmcneill static int acpi_pci_md_intr_setattr(void *, pci_intr_handle_t *, int, 139 1.1 jmcneill uint64_t); 140 1.1 jmcneill static void * acpi_pci_md_intr_establish(void *, pci_intr_handle_t, 141 1.8 jmcneill int, int (*)(void *), void *, 142 1.8 jmcneill const char *); 143 1.1 jmcneill static void acpi_pci_md_intr_disestablish(void *, void *); 144 1.1 jmcneill 145 1.1 jmcneill struct arm32_pci_chipset arm_acpi_pci_chipset = { 146 1.1 jmcneill .pc_attach_hook = acpi_pci_md_attach_hook, 147 1.1 jmcneill .pc_bus_maxdevs = acpi_pci_md_bus_maxdevs, 148 1.1 jmcneill .pc_make_tag = acpi_pci_md_make_tag, 149 1.1 jmcneill .pc_decompose_tag = acpi_pci_md_decompose_tag, 150 1.6 jmcneill .pc_get_segment = acpi_pci_md_get_segment, 151 1.9 jmcneill .pc_get_devid = acpi_pci_md_get_devid, 152 1.16 jmcneill .pc_get_frameid = acpi_pci_md_get_frameid, 153 1.1 jmcneill .pc_conf_read = acpi_pci_md_conf_read, 154 1.1 jmcneill .pc_conf_write = acpi_pci_md_conf_write, 155 1.1 jmcneill .pc_conf_hook = acpi_pci_md_conf_hook, 156 1.1 jmcneill .pc_conf_interrupt = acpi_pci_md_conf_interrupt, 157 1.1 jmcneill 158 1.1 jmcneill .pc_intr_map = acpi_pci_md_intr_map, 159 1.1 jmcneill .pc_intr_string = acpi_pci_md_intr_string, 160 1.1 jmcneill .pc_intr_evcnt = acpi_pci_md_intr_evcnt, 161 1.1 jmcneill .pc_intr_setattr = acpi_pci_md_intr_setattr, 162 1.1 jmcneill .pc_intr_establish = acpi_pci_md_intr_establish, 163 1.1 jmcneill .pc_intr_disestablish = acpi_pci_md_intr_disestablish, 164 1.1 jmcneill }; 165 1.1 jmcneill 166 1.1 jmcneill static ACPI_STATUS 167 1.13 jmcneill acpi_pci_md_pci_link(ACPI_HANDLE handle, pci_chipset_tag_t pc, int bus) 168 1.1 jmcneill { 169 1.1 jmcneill ACPI_PCI_ROUTING_TABLE *prt; 170 1.1 jmcneill ACPI_HANDLE linksrc; 171 1.1 jmcneill ACPI_BUFFER buf; 172 1.1 jmcneill ACPI_STATUS rv; 173 1.1 jmcneill void *linkdev; 174 1.1 jmcneill 175 1.1 jmcneill rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable); 176 1.1 jmcneill if (ACPI_FAILURE(rv)) 177 1.1 jmcneill return rv; 178 1.1 jmcneill 179 1.1 jmcneill for (char *p = buf.Pointer; ; p += prt->Length) { 180 1.1 jmcneill prt = (ACPI_PCI_ROUTING_TABLE *)p; 181 1.1 jmcneill if (prt->Length == 0) 182 1.1 jmcneill break; 183 1.1 jmcneill 184 1.1 jmcneill const u_int dev = ACPI_HIWORD(prt->Address); 185 1.1 jmcneill if (prt->Source[0] != 0) { 186 1.1 jmcneill aprint_debug("ACPI: %s dev %u INT%c on lnkdev %s\n", 187 1.1 jmcneill acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->Source); 188 1.1 jmcneill rv = AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source, &linksrc); 189 1.1 jmcneill if (ACPI_FAILURE(rv)) { 190 1.1 jmcneill aprint_debug("ACPI: AcpiGetHandle failed for '%s': %s\n", 191 1.1 jmcneill prt->Source, AcpiFormatException(rv)); 192 1.1 jmcneill continue; 193 1.1 jmcneill } 194 1.1 jmcneill 195 1.1 jmcneill linkdev = acpi_pci_link_devbyhandle(linksrc); 196 1.13 jmcneill acpi_pci_link_add_reference(linkdev, pc, 0, bus, dev, prt->Pin & 3); 197 1.1 jmcneill } else { 198 1.1 jmcneill aprint_debug("ACPI: %s dev %u INT%c on globint %d\n", 199 1.1 jmcneill acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->SourceIndex); 200 1.1 jmcneill } 201 1.1 jmcneill } 202 1.1 jmcneill 203 1.1 jmcneill return AE_OK; 204 1.1 jmcneill } 205 1.1 jmcneill 206 1.1 jmcneill static void 207 1.1 jmcneill acpi_pci_md_attach_hook(device_t parent, device_t self, 208 1.1 jmcneill struct pcibus_attach_args *pba) 209 1.1 jmcneill { 210 1.2 jmcneill struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; 211 1.1 jmcneill struct acpi_pci_prt *prt, *prtp; 212 1.1 jmcneill struct acpi_devnode *ad; 213 1.1 jmcneill ACPI_HANDLE handle; 214 1.1 jmcneill int seg, bus, dev, func; 215 1.22 jmcneill u_int bridge_dev = 0; 216 1.22 jmcneill bool derived = false; 217 1.1 jmcneill 218 1.2 jmcneill seg = ap->ap_seg; 219 1.1 jmcneill handle = NULL; 220 1.1 jmcneill 221 1.1 jmcneill if (pba->pba_bridgetag) { 222 1.1 jmcneill /* 223 1.1 jmcneill * Find the PCI address of our parent bridge and look for the 224 1.1 jmcneill * corresponding ACPI device node. If there is no node for this 225 1.1 jmcneill * bus, use the parent bridge routing information. 226 1.1 jmcneill */ 227 1.1 jmcneill acpi_pci_md_decompose_tag(NULL, *pba->pba_bridgetag, &bus, &dev, &func); 228 1.1 jmcneill ad = acpi_pcidev_find(seg, bus, dev, func); 229 1.1 jmcneill if (ad != NULL) { 230 1.1 jmcneill handle = ad->ad_handle; 231 1.1 jmcneill } else { 232 1.22 jmcneill /* No routes defined for this bus, derive from parent */ 233 1.1 jmcneill TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 234 1.22 jmcneill if (prtp->prt_bus == bus && 235 1.22 jmcneill prtp->prt_segment == seg) { 236 1.1 jmcneill handle = prtp->prt_handle; 237 1.22 jmcneill bridge_dev = dev; 238 1.22 jmcneill derived = true; 239 1.1 jmcneill break; 240 1.1 jmcneill } 241 1.1 jmcneill } 242 1.1 jmcneill } else { 243 1.1 jmcneill /* 244 1.1 jmcneill * Lookup the ACPI device node for the root bus. 245 1.1 jmcneill */ 246 1.1 jmcneill ad = acpi_pciroot_find(seg, 0); 247 1.1 jmcneill if (ad != NULL) 248 1.1 jmcneill handle = ad->ad_handle; 249 1.1 jmcneill } 250 1.1 jmcneill 251 1.1 jmcneill if (handle != NULL) { 252 1.1 jmcneill prt = kmem_alloc(sizeof(*prt), KM_SLEEP); 253 1.1 jmcneill prt->prt_bus = pba->pba_bus; 254 1.22 jmcneill prt->prt_segment = seg; 255 1.1 jmcneill prt->prt_handle = handle; 256 1.22 jmcneill prt->prt_bridge_dev = bridge_dev; 257 1.22 jmcneill prt->prt_derived = derived; 258 1.1 jmcneill TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); 259 1.1 jmcneill } 260 1.1 jmcneill 261 1.1 jmcneill acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); 262 1.4 jmcneill 263 1.4 jmcneill if (ad != NULL) { 264 1.4 jmcneill /* 265 1.4 jmcneill * This is a new ACPI managed bus. Add PCI link references. 266 1.4 jmcneill */ 267 1.13 jmcneill acpi_pci_md_pci_link(ad->ad_handle, pba->pba_pc, pba->pba_bus); 268 1.4 jmcneill } 269 1.1 jmcneill } 270 1.1 jmcneill 271 1.1 jmcneill static int 272 1.1 jmcneill acpi_pci_md_bus_maxdevs(void *v, int busno) 273 1.1 jmcneill { 274 1.1 jmcneill return 32; 275 1.1 jmcneill } 276 1.1 jmcneill 277 1.1 jmcneill static pcitag_t 278 1.1 jmcneill acpi_pci_md_make_tag(void *v, int b, int d, int f) 279 1.1 jmcneill { 280 1.1 jmcneill return (b << 16) | (d << 11) | (f << 8); 281 1.1 jmcneill } 282 1.1 jmcneill 283 1.1 jmcneill static void 284 1.1 jmcneill acpi_pci_md_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 285 1.1 jmcneill { 286 1.1 jmcneill if (bp) 287 1.1 jmcneill *bp = (tag >> 16) & 0xff; 288 1.1 jmcneill if (dp) 289 1.1 jmcneill *dp = (tag >> 11) & 0x1f; 290 1.1 jmcneill if (fp) 291 1.1 jmcneill *fp = (tag >> 8) & 0x7; 292 1.1 jmcneill } 293 1.1 jmcneill 294 1.6 jmcneill static u_int 295 1.6 jmcneill acpi_pci_md_get_segment(void *v) 296 1.6 jmcneill { 297 1.6 jmcneill struct acpi_pci_context * const ap = v; 298 1.6 jmcneill 299 1.6 jmcneill return ap->ap_seg; 300 1.6 jmcneill } 301 1.6 jmcneill 302 1.9 jmcneill static uint32_t 303 1.9 jmcneill acpi_pci_md_get_devid(void *v, uint32_t devid) 304 1.9 jmcneill { 305 1.9 jmcneill struct acpi_pci_context * const ap = v; 306 1.9 jmcneill 307 1.9 jmcneill return acpi_iort_pci_root_map(ap->ap_seg, devid); 308 1.9 jmcneill } 309 1.9 jmcneill 310 1.16 jmcneill static uint32_t 311 1.16 jmcneill acpi_pci_md_get_frameid(void *v, uint32_t devid) 312 1.16 jmcneill { 313 1.16 jmcneill struct acpi_pci_context * const ap = v; 314 1.16 jmcneill 315 1.16 jmcneill return acpi_iort_its_id_map(ap->ap_seg, devid); 316 1.16 jmcneill } 317 1.16 jmcneill 318 1.1 jmcneill static pcireg_t 319 1.1 jmcneill acpi_pci_md_conf_read(void *v, pcitag_t tag, int offset) 320 1.1 jmcneill { 321 1.2 jmcneill struct acpi_pci_context * const ap = v; 322 1.1 jmcneill pcireg_t val; 323 1.1 jmcneill 324 1.1 jmcneill if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 325 1.1 jmcneill return (pcireg_t) -1; 326 1.1 jmcneill 327 1.10 jmcneill if (ap->ap_conf_read != NULL) 328 1.10 jmcneill ap->ap_conf_read(&ap->ap_pc, tag, offset, &val); 329 1.10 jmcneill else 330 1.10 jmcneill acpimcfg_conf_read(&ap->ap_pc, tag, offset, &val); 331 1.1 jmcneill 332 1.1 jmcneill return val; 333 1.1 jmcneill } 334 1.1 jmcneill 335 1.1 jmcneill static void 336 1.1 jmcneill acpi_pci_md_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) 337 1.1 jmcneill { 338 1.2 jmcneill struct acpi_pci_context * const ap = v; 339 1.2 jmcneill 340 1.1 jmcneill if (offset < 0 || offset >= PCI_EXTCONF_SIZE) 341 1.1 jmcneill return; 342 1.1 jmcneill 343 1.10 jmcneill if (ap->ap_conf_write != NULL) 344 1.10 jmcneill ap->ap_conf_write(&ap->ap_pc, tag, offset, val); 345 1.10 jmcneill else 346 1.10 jmcneill acpimcfg_conf_write(&ap->ap_pc, tag, offset, val); 347 1.1 jmcneill } 348 1.1 jmcneill 349 1.1 jmcneill static int 350 1.1 jmcneill acpi_pci_md_conf_hook(void *v, int b, int d, int f, pcireg_t id) 351 1.1 jmcneill { 352 1.1 jmcneill return PCI_CONF_DEFAULT; 353 1.1 jmcneill } 354 1.1 jmcneill 355 1.1 jmcneill static void 356 1.1 jmcneill acpi_pci_md_conf_interrupt(void *v, int bus, int dev, int ipin, int sqiz, int *ilinep) 357 1.1 jmcneill { 358 1.1 jmcneill } 359 1.1 jmcneill 360 1.1 jmcneill static struct acpi_pci_prt * 361 1.7 jmcneill acpi_pci_md_intr_find_prt(pci_chipset_tag_t pc, u_int bus) 362 1.1 jmcneill { 363 1.1 jmcneill struct acpi_pci_prt *prt, *prtp; 364 1.7 jmcneill u_int segment; 365 1.7 jmcneill 366 1.7 jmcneill segment = pci_get_segment(pc); 367 1.1 jmcneill 368 1.1 jmcneill prt = NULL; 369 1.1 jmcneill TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) 370 1.7 jmcneill if (prtp->prt_segment == segment && prtp->prt_bus == bus) { 371 1.1 jmcneill prt = prtp; 372 1.1 jmcneill break; 373 1.1 jmcneill } 374 1.1 jmcneill 375 1.1 jmcneill return prt; 376 1.1 jmcneill } 377 1.1 jmcneill 378 1.1 jmcneill static int 379 1.1 jmcneill acpi_pci_md_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) 380 1.1 jmcneill { 381 1.1 jmcneill struct acpi_pci_prt *prt; 382 1.1 jmcneill ACPI_PCI_ROUTING_TABLE *tab; 383 1.1 jmcneill int line, pol, trig, error; 384 1.1 jmcneill ACPI_HANDLE linksrc; 385 1.1 jmcneill ACPI_BUFFER buf; 386 1.1 jmcneill void *linkdev; 387 1.22 jmcneill u_int pin; 388 1.1 jmcneill 389 1.1 jmcneill if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE) 390 1.1 jmcneill return EINVAL; 391 1.1 jmcneill 392 1.7 jmcneill prt = acpi_pci_md_intr_find_prt(pa->pa_pc, pa->pa_bus); 393 1.1 jmcneill if (prt == NULL) 394 1.1 jmcneill return ENXIO; 395 1.1 jmcneill 396 1.1 jmcneill if (ACPI_FAILURE(acpi_get(prt->prt_handle, &buf, AcpiGetIrqRoutingTable))) 397 1.1 jmcneill return EIO; 398 1.1 jmcneill 399 1.22 jmcneill /* 400 1.22 jmcneill * For busses with no direct _PRT entry, derive the pin from the 401 1.22 jmcneill * parent bridge. 402 1.22 jmcneill */ 403 1.22 jmcneill if (prt->prt_derived) { 404 1.22 jmcneill pin = (((pa->pa_rawintrpin + prt->prt_bridge_dev) - 1) % 4) + 1; 405 1.22 jmcneill } else { 406 1.22 jmcneill pin = pa->pa_intrpin; 407 1.22 jmcneill } 408 1.22 jmcneill 409 1.22 jmcneill aprint_debug("%s: bus=%u pin=%u pa_rawintrpin=%u pa_intrpin=%u " 410 1.22 jmcneill "pa_intrswiz=%u prt_bridge_dev=%u\n", 411 1.22 jmcneill __func__, pa->pa_bus, pin, pa->pa_rawintrpin, 412 1.22 jmcneill pa->pa_intrpin, pa->pa_intrswiz, prt->prt_bridge_dev); 413 1.22 jmcneill 414 1.1 jmcneill error = ENOENT; 415 1.1 jmcneill for (char *p = buf.Pointer; ; p += tab->Length) { 416 1.1 jmcneill tab = (ACPI_PCI_ROUTING_TABLE *)p; 417 1.1 jmcneill if (tab->Length == 0) 418 1.1 jmcneill break; 419 1.1 jmcneill 420 1.1 jmcneill if (pa->pa_device == ACPI_HIWORD(tab->Address) && 421 1.22 jmcneill (pin - 1) == (tab->Pin & 3)) { 422 1.1 jmcneill if (tab->Source[0] != 0) { 423 1.1 jmcneill if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, tab->Source, &linksrc))) 424 1.1 jmcneill goto done; 425 1.1 jmcneill linkdev = acpi_pci_link_devbyhandle(linksrc); 426 1.13 jmcneill *ih = acpi_pci_link_route_interrupt(linkdev, 427 1.13 jmcneill pa->pa_pc, tab->SourceIndex, 428 1.1 jmcneill &line, &pol, &trig); 429 1.1 jmcneill error = 0; 430 1.1 jmcneill goto done; 431 1.1 jmcneill } else { 432 1.1 jmcneill *ih = tab->SourceIndex; 433 1.1 jmcneill error = 0; 434 1.1 jmcneill goto done; 435 1.1 jmcneill } 436 1.1 jmcneill } 437 1.1 jmcneill } 438 1.1 jmcneill 439 1.1 jmcneill done: 440 1.1 jmcneill ACPI_FREE(buf.Pointer); 441 1.1 jmcneill return error; 442 1.1 jmcneill } 443 1.1 jmcneill 444 1.1 jmcneill static const char * 445 1.1 jmcneill acpi_pci_md_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) 446 1.1 jmcneill { 447 1.3 jmcneill const int irq = __SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 448 1.5 jmcneill const int vec = __SHIFTOUT(ih, ARM_PCI_INTR_MSI_VEC); 449 1.3 jmcneill 450 1.5 jmcneill if (ih & ARM_PCI_INTR_MSIX) 451 1.5 jmcneill snprintf(buf, len, "irq %d (MSI-X vec %d)", irq, vec); 452 1.5 jmcneill else if (ih & ARM_PCI_INTR_MSI) 453 1.5 jmcneill snprintf(buf, len, "irq %d (MSI vec %d)", irq, vec); 454 1.3 jmcneill else 455 1.3 jmcneill snprintf(buf, len, "irq %d", irq); 456 1.3 jmcneill 457 1.1 jmcneill return buf; 458 1.1 jmcneill } 459 1.1 jmcneill 460 1.1 jmcneill static const struct evcnt * 461 1.1 jmcneill acpi_pci_md_intr_evcnt(void *v, pci_intr_handle_t ih) 462 1.1 jmcneill { 463 1.1 jmcneill return NULL; 464 1.1 jmcneill } 465 1.1 jmcneill 466 1.1 jmcneill static int 467 1.1 jmcneill acpi_pci_md_intr_setattr(void *v, pci_intr_handle_t *ih, int attr, uint64_t data) 468 1.1 jmcneill { 469 1.1 jmcneill switch (attr) { 470 1.1 jmcneill case PCI_INTR_MPSAFE: 471 1.1 jmcneill if (data) 472 1.3 jmcneill *ih |= ARM_PCI_INTR_MPSAFE; 473 1.1 jmcneill else 474 1.3 jmcneill *ih &= ~ARM_PCI_INTR_MPSAFE; 475 1.1 jmcneill return 0; 476 1.1 jmcneill default: 477 1.1 jmcneill return ENODEV; 478 1.1 jmcneill } 479 1.1 jmcneill } 480 1.1 jmcneill 481 1.14 jmcneill static struct acpi_pci_intr * 482 1.14 jmcneill acpi_pci_md_intr_lookup(int irq) 483 1.14 jmcneill { 484 1.14 jmcneill struct acpi_pci_intr *pi; 485 1.14 jmcneill 486 1.14 jmcneill TAILQ_FOREACH(pi, &acpi_pci_intrs, pi_list) 487 1.14 jmcneill if (pi->pi_irq == irq) 488 1.14 jmcneill return pi; 489 1.14 jmcneill 490 1.14 jmcneill return NULL; 491 1.14 jmcneill } 492 1.14 jmcneill 493 1.14 jmcneill static void 494 1.14 jmcneill acpi_pci_md_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 495 1.14 jmcneill { 496 1.14 jmcneill struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 497 1.14 jmcneill 498 1.14 jmcneill pi->pi_unblocked |= irqmask; 499 1.14 jmcneill } 500 1.14 jmcneill 501 1.14 jmcneill static void 502 1.14 jmcneill acpi_pci_md_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask) 503 1.14 jmcneill { 504 1.14 jmcneill struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 505 1.14 jmcneill 506 1.14 jmcneill pi->pi_unblocked &= ~irqmask; 507 1.14 jmcneill } 508 1.14 jmcneill 509 1.14 jmcneill static int 510 1.14 jmcneill acpi_pci_md_find_pending_irqs(struct pic_softc *pic) 511 1.14 jmcneill { 512 1.14 jmcneill struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic; 513 1.14 jmcneill 514 1.14 jmcneill pic_mark_pending_sources(pic, 0, pi->pi_unblocked); 515 1.14 jmcneill 516 1.14 jmcneill return 1; 517 1.14 jmcneill } 518 1.14 jmcneill 519 1.14 jmcneill static void 520 1.14 jmcneill acpi_pci_md_establish_irq(struct pic_softc *pic, struct intrsource *is) 521 1.14 jmcneill { 522 1.14 jmcneill } 523 1.14 jmcneill 524 1.14 jmcneill static void 525 1.14 jmcneill acpi_pci_md_source_name(struct pic_softc *pic, int irq, char *buf, size_t len) 526 1.14 jmcneill { 527 1.14 jmcneill snprintf(buf, len, "slot %d", irq); 528 1.14 jmcneill } 529 1.14 jmcneill 530 1.14 jmcneill static struct pic_ops acpi_pci_pic_ops = { 531 1.14 jmcneill .pic_unblock_irqs = acpi_pci_md_unblock_irqs, 532 1.14 jmcneill .pic_block_irqs = acpi_pci_md_block_irqs, 533 1.14 jmcneill .pic_find_pending_irqs = acpi_pci_md_find_pending_irqs, 534 1.14 jmcneill .pic_establish_irq = acpi_pci_md_establish_irq, 535 1.14 jmcneill .pic_source_name = acpi_pci_md_source_name, 536 1.14 jmcneill }; 537 1.14 jmcneill 538 1.1 jmcneill static void * 539 1.1 jmcneill acpi_pci_md_intr_establish(void *v, pci_intr_handle_t ih, int ipl, 540 1.8 jmcneill int (*callback)(void *), void *arg, const char *xname) 541 1.1 jmcneill { 542 1.3 jmcneill struct acpi_pci_context * const ap = v; 543 1.14 jmcneill struct acpi_pci_intr *pi; 544 1.14 jmcneill int slot; 545 1.3 jmcneill 546 1.5 jmcneill if ((ih & (ARM_PCI_INTR_MSI | ARM_PCI_INTR_MSIX)) != 0) 547 1.8 jmcneill return arm_pci_msi_intr_establish(&ap->ap_pc, ih, ipl, callback, arg, xname); 548 1.3 jmcneill 549 1.3 jmcneill const int irq = (int)__SHIFTOUT(ih, ARM_PCI_INTR_IRQ); 550 1.3 jmcneill const int mpsafe = (ih & ARM_PCI_INTR_MPSAFE) ? IST_MPSAFE : 0; 551 1.1 jmcneill 552 1.14 jmcneill pi = acpi_pci_md_intr_lookup(irq); 553 1.14 jmcneill if (pi == NULL) { 554 1.14 jmcneill pi = kmem_zalloc(sizeof(*pi), KM_SLEEP); 555 1.14 jmcneill pi->pi_irq = irq; 556 1.14 jmcneill snprintf(pi->pi_pic.pic_name, sizeof(pi->pi_pic.pic_name), 557 1.14 jmcneill "PCI irq %d", irq); 558 1.14 jmcneill pi->pi_pic.pic_maxsources = 32; 559 1.14 jmcneill pi->pi_pic.pic_ops = &acpi_pci_pic_ops; 560 1.14 jmcneill pi->pi_irqbase = pic_add(&pi->pi_pic, PIC_IRQBASE_ALLOC); 561 1.14 jmcneill TAILQ_INSERT_TAIL(&acpi_pci_intrs, pi, pi_list); 562 1.20 jmcneill pi->pi_ih = intr_establish_xname(irq, IPL_VM, IST_LEVEL | IST_MPSAFE, 563 1.14 jmcneill pic_handle_intr, &pi->pi_pic, device_xname(ap->ap_dev)); 564 1.14 jmcneill } 565 1.14 jmcneill if (pi->pi_ih == NULL) 566 1.14 jmcneill return NULL; 567 1.14 jmcneill 568 1.14 jmcneill /* Find a free slot */ 569 1.14 jmcneill for (slot = 0; slot < pi->pi_pic.pic_maxsources; slot++) 570 1.14 jmcneill if (pi->pi_pic.pic_sources[slot] == NULL) 571 1.14 jmcneill break; 572 1.14 jmcneill if (slot == pi->pi_pic.pic_maxsources) 573 1.14 jmcneill return NULL; 574 1.14 jmcneill 575 1.14 jmcneill return intr_establish_xname(pi->pi_irqbase + slot, ipl, IST_LEVEL | mpsafe, 576 1.14 jmcneill callback, arg, xname); 577 1.1 jmcneill } 578 1.1 jmcneill 579 1.1 jmcneill static void 580 1.1 jmcneill acpi_pci_md_intr_disestablish(void *v, void *vih) 581 1.1 jmcneill { 582 1.1 jmcneill intr_disestablish(vih); 583 1.1 jmcneill } 584 1.13 jmcneill 585 1.13 jmcneill const struct acpi_pci_quirk * 586 1.13 jmcneill acpi_pci_md_find_quirk(int seg) 587 1.13 jmcneill { 588 1.13 jmcneill ACPI_STATUS rv; 589 1.13 jmcneill ACPI_TABLE_MCFG *mcfg; 590 1.13 jmcneill u_int n; 591 1.13 jmcneill 592 1.13 jmcneill rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); 593 1.19 jmcneill if (ACPI_FAILURE(rv)) { 594 1.19 jmcneill #ifdef PCI_SMCCC 595 1.19 jmcneill uint32_t ver = pci_smccc_version(); 596 1.19 jmcneill aprint_debug("%s: SMCCC version %#x\n", __func__, ver); 597 1.19 jmcneill if (PCI_SMCCC_SUCCESS(ver)) { 598 1.19 jmcneill return &acpi_pci_smccc_quirk; 599 1.19 jmcneill } 600 1.19 jmcneill #endif 601 1.13 jmcneill return NULL; 602 1.19 jmcneill } 603 1.13 jmcneill 604 1.19 jmcneill for (n = 0; n < __arraycount(acpi_pci_mcfg_quirks); n++) { 605 1.19 jmcneill const struct acpi_pci_quirk *q = &acpi_pci_mcfg_quirks[n]; 606 1.13 jmcneill if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && 607 1.13 jmcneill memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && 608 1.13 jmcneill q->q_oemrevision == mcfg->Header.OemRevision && 609 1.13 jmcneill (q->q_segment == -1 || q->q_segment == seg)) 610 1.13 jmcneill return q; 611 1.13 jmcneill } 612 1.13 jmcneill 613 1.13 jmcneill return NULL; 614 1.13 jmcneill } 615 1.13 jmcneill 616 1.13 jmcneill pci_chipset_tag_t 617 1.13 jmcneill acpi_pci_md_get_chipset_tag(struct acpi_softc *sc, int seg, int bbn) 618 1.13 jmcneill { 619 1.13 jmcneill struct acpi_pci_pct *pct = NULL, *pctp; 620 1.13 jmcneill const struct acpi_pci_quirk *q; 621 1.13 jmcneill 622 1.13 jmcneill TAILQ_FOREACH(pctp, &acpi_pci_chipset_tags, pct_list) 623 1.13 jmcneill if (pctp->pct_ap.ap_seg == seg) { 624 1.13 jmcneill pct = pctp; 625 1.13 jmcneill break; 626 1.13 jmcneill } 627 1.13 jmcneill 628 1.13 jmcneill if (pct == NULL) { 629 1.13 jmcneill pct = kmem_zalloc(sizeof(*pct), KM_SLEEP); 630 1.13 jmcneill pct->pct_ap.ap_dev = sc->sc_dev; 631 1.13 jmcneill pct->pct_ap.ap_pc = arm_acpi_pci_chipset; 632 1.13 jmcneill pct->pct_ap.ap_pc.pc_conf_v = &pct->pct_ap; 633 1.14 jmcneill pct->pct_ap.ap_pc.pc_intr_v = &pct->pct_ap; 634 1.13 jmcneill pct->pct_ap.ap_seg = seg; 635 1.13 jmcneill pct->pct_ap.ap_bus = bbn; 636 1.19 jmcneill pct->pct_ap.ap_maxbus = -1; 637 1.13 jmcneill pct->pct_ap.ap_bst = acpi_softc->sc_memt; 638 1.13 jmcneill 639 1.13 jmcneill q = acpi_pci_md_find_quirk(seg); 640 1.13 jmcneill if (q != NULL) 641 1.13 jmcneill q->q_init(&pct->pct_ap); 642 1.13 jmcneill 643 1.13 jmcneill TAILQ_INSERT_TAIL(&acpi_pci_chipset_tags, pct, pct_list); 644 1.13 jmcneill } 645 1.13 jmcneill 646 1.13 jmcneill return &pct->pct_ap.ap_pc; 647 1.13 jmcneill } 648 1.13 jmcneill __strong_alias(acpi_get_pci_chipset_tag,acpi_pci_md_get_chipset_tag); 649