1 /* $OpenBSD: aplpcie.c,v 1.16 2023/04/16 12:09:01 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/extent.h> 22 #include <sys/malloc.h> 23 24 #include <machine/intr.h> 25 #include <machine/bus.h> 26 #include <machine/fdt.h> 27 28 #include <dev/pci/pcidevs.h> 29 #include <dev/pci/pcireg.h> 30 #include <dev/pci/pcivar.h> 31 32 #include <dev/ofw/openfirm.h> 33 #include <dev/ofw/ofw_gpio.h> 34 #include <dev/ofw/ofw_misc.h> 35 #include <dev/ofw/ofw_pinctrl.h> 36 #include <dev/ofw/ofw_power.h> 37 #include <dev/ofw/fdt.h> 38 39 #define PCIE_RC_PHY_BASE(port) (0x84000 + (port) * 0x4000) 40 #define PCIE_RC_PHY_SIZE 0x4000 41 42 #define PCIE_PHY_LANE_CONF 0x0000 43 #define PCIE_PHY_LANE_CONF_REFCLK0REQ (1 << 0) 44 #define PCIE_PHY_LANE_CONF_REFCLK1REQ (1 << 1) 45 #define PCIE_PHY_LANE_CONF_REFCLK0ACK (1 << 2) 46 #define PCIE_PHY_LANE_CONF_REFCLK1ACK (1 << 3) 47 #define PCIE_PHY_LANE_CONF_REFCLK0EN (1 << 9) 48 #define PCIE_PHY_LANE_CONF_REFCLK1EN (1 << 10) 49 #define PCIE_PHY_LANE_CONF_REFCLK0CGEN (1 << 30) 50 #define PCIE_PHY_LANE_CONF_REFCLK1CGEN (1U << 31) 51 #define PCIE_PHY_LANE_CTRL 0x0004 52 #define PCIE_PHY_LANE_CTRL_CFGACC (1 << 15) 53 54 #define PCIE_PORT_LTSSM_CTRL 0x0080 55 #define PCIE_PORT_LTSSM_CTRL_START (1 << 0) 56 #define PCIE_PORT_MSI_CTRL 0x0124 57 #define PCIE_PORT_MSI_CTRL_ENABLE (1 << 0) 58 #define PCIE_PORT_MSI_CTRL_32 (5 << 4) 59 #define PCIE_PORT_MSI_REMAP 0x0128 60 #define PCIE_PORT_MSI_DOORBELL 0x0168 61 #define PCIE_PORT_LINK_STAT 0x0208 62 #define PCIE_PORT_LINK_STAT_UP (1 << 0) 63 #define PCIE_PORT_APPCLK 0x0800 64 #define PCIE_PORT_APPCLK_EN (1 << 0) 65 #define PCIE_PORT_APPCLK_CGDIS (1 << 8) 66 #define PCIE_PORT_STAT 0x0804 67 #define PCIE_PORT_STAT_READY (1 << 0) 68 #define PCIE_PORT_REFCLK 0x0810 69 #define PCIE_PORT_REFCLK_EN (1 << 0) 70 #define PCIE_PORT_REFCLK_CGDIS (1 << 8) 71 #define PCIE_PORT_PERST 0x0814 72 #define PCIE_PORT_PERST_DIS (1 << 0) 73 74 #define PCIE_T6020_PORT_MSI_DOORBELL_LO 0x016c 75 #define PCIE_T6020_PORT_MSI_DOORBELL_HI 0x0170 76 #define PCIE_T6020_PORT_PERST 0x082c 77 #define PCIE_T6020_PORT_MSI_MAP(idx) (0x3800 + (idx) * 4) 78 #define PCIE_T6020_PORT_MSI_MAP_ENABLE (1U << 31) 79 80 #define HREAD4(sc, reg) \ 81 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 82 #define HWRITE4(sc, reg, val) \ 83 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 84 85 #define RREAD4(sc, reg) \ 86 (bus_space_read_4((sc)->sc_iot, (sc)->sc_rc_ioh, (reg))) 87 #define RWRITE4(sc, reg, val) \ 88 bus_space_write_4((sc)->sc_iot, (sc)->sc_rc_ioh, (reg), (val)) 89 #define RSET4(sc, reg, bits) \ 90 RWRITE4((sc), (reg), RREAD4((sc), (reg)) | (bits)) 91 #define RCLR4(sc, reg, bits) \ 92 RWRITE4((sc), (reg), RREAD4((sc), (reg)) & ~(bits)) 93 94 #define LREAD4(sc, port, reg) \ 95 (bus_space_read_4((sc)->sc_iot, (sc)->sc_phy_ioh[port], (reg))) 96 #define LWRITE4(sc, port, reg, val) \ 97 bus_space_write_4((sc)->sc_iot, (sc)->sc_phy_ioh[port], (reg), (val)) 98 #define LSET4(sc, port, reg, bits) \ 99 LWRITE4((sc), (port), (reg), LREAD4((sc), (port), (reg)) | (bits)) 100 #define LCLR4(sc, port, reg, bits) \ 101 LWRITE4((sc), (port), (reg), LREAD4((sc), (port), (reg)) & ~(bits)) 102 103 #define PREAD4(sc, port, reg) \ 104 (bus_space_read_4((sc)->sc_iot, (sc)->sc_port_ioh[(port)], (reg))) 105 #define PWRITE4(sc, port, reg, val) \ 106 bus_space_write_4((sc)->sc_iot, (sc)->sc_port_ioh[(port)], (reg), (val)) 107 #define PSET4(sc, port, reg, bits) \ 108 PWRITE4((sc), (port), (reg), PREAD4((sc), (port), (reg)) | (bits)) 109 #define PCLR4(sc, port, reg, bits) \ 110 PWRITE4((sc), (port), (reg), PREAD4((sc), (port), (reg)) & ~(bits)) 111 112 struct aplpcie_range { 113 uint32_t flags; 114 uint64_t pci_base; 115 uint64_t phys_base; 116 uint64_t size; 117 }; 118 119 #define APLPCIE_MAX_PORTS 4 120 121 struct aplpcie_softc { 122 struct device sc_dev; 123 bus_space_tag_t sc_iot; 124 bus_space_handle_t sc_ioh; 125 bus_space_handle_t sc_rc_ioh; 126 bus_space_handle_t sc_phy_ioh[APLPCIE_MAX_PORTS]; 127 bus_size_t sc_phy_ios[APLPCIE_MAX_PORTS]; 128 bus_space_handle_t sc_port_ioh[APLPCIE_MAX_PORTS]; 129 bus_size_t sc_port_ios[APLPCIE_MAX_PORTS]; 130 bus_dma_tag_t sc_dmat; 131 132 int sc_node; 133 int sc_acells; 134 int sc_scells; 135 int sc_pacells; 136 int sc_pscells; 137 struct aplpcie_range *sc_ranges; 138 int sc_nranges; 139 140 struct bus_space sc_bus_iot; 141 struct bus_space sc_bus_memt; 142 143 struct machine_pci_chipset sc_pc; 144 struct extent *sc_busex; 145 struct extent *sc_memex; 146 struct extent *sc_pmemex; 147 struct extent *sc_ioex; 148 int sc_bus; 149 150 int sc_msi; 151 bus_addr_t sc_msi_doorbell; 152 uint32_t sc_msi_range[6]; 153 int sc_msi_rangelen; 154 struct interrupt_controller sc_msi_ic; 155 }; 156 157 int aplpcie_match(struct device *, void *, void *); 158 void aplpcie_attach(struct device *, struct device *, void *); 159 160 const struct cfattach aplpcie_ca = { 161 sizeof (struct aplpcie_softc), aplpcie_match, aplpcie_attach 162 }; 163 164 struct cfdriver aplpcie_cd = { 165 NULL, "aplpcie", DV_DULL 166 }; 167 168 int 169 aplpcie_match(struct device *parent, void *match, void *aux) 170 { 171 struct fdt_attach_args *faa = aux; 172 173 return OF_is_compatible(faa->fa_node, "apple,pcie") || 174 OF_is_compatible(faa->fa_node, "apple,t6020-pcie"); 175 } 176 177 void aplpcie_init_port(struct aplpcie_softc *, int); 178 void aplpcie_t6020_init_port(struct aplpcie_softc *, int); 179 180 void aplpcie_attach_hook(struct device *, struct device *, 181 struct pcibus_attach_args *); 182 int aplpcie_bus_maxdevs(void *, int); 183 pcitag_t aplpcie_make_tag(void *, int, int, int); 184 void aplpcie_decompose_tag(void *, pcitag_t, int *, int *, int *); 185 int aplpcie_conf_size(void *, pcitag_t); 186 pcireg_t aplpcie_conf_read(void *, pcitag_t, int); 187 void aplpcie_conf_write(void *, pcitag_t, int, pcireg_t); 188 int aplpcie_probe_device_hook(void *, struct pci_attach_args *); 189 190 int aplpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 191 const char *aplpcie_intr_string(void *, pci_intr_handle_t); 192 void *aplpcie_intr_establish(void *, pci_intr_handle_t, int, 193 struct cpu_info *, int (*)(void *), void *, char *); 194 void aplpcie_intr_disestablish(void *, void *); 195 196 int aplpcie_bs_iomap(bus_space_tag_t, bus_addr_t, bus_size_t, int, 197 bus_space_handle_t *); 198 int aplpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int, 199 bus_space_handle_t *); 200 201 void *aplpcie_intr_establish_msi(void *, uint64_t *, uint64_t *, 202 int, struct cpu_info *, int (*)(void *), void *, char *); 203 void aplpcie_intr_disestablish_msi(void *); 204 205 void 206 aplpcie_attach(struct device *parent, struct device *self, void *aux) 207 { 208 struct aplpcie_softc *sc = (struct aplpcie_softc *)self; 209 struct fdt_attach_args *faa = aux; 210 struct pcibus_attach_args pba; 211 uint32_t *ranges; 212 int i, j, nranges, rangeslen; 213 uint32_t bus_range[2]; 214 char name[32]; 215 int idx, node, port; 216 217 sc->sc_iot = faa->fa_iot; 218 219 idx = OF_getindex(faa->fa_node, "config", "reg-names"); 220 if (idx < 0 || idx >= faa->fa_nreg || 221 bus_space_map(sc->sc_iot, faa->fa_reg[idx].addr, 222 faa->fa_reg[idx].size, 0, &sc->sc_ioh)) { 223 printf(": can't map registers\n"); 224 return; 225 } 226 227 idx = OF_getindex(faa->fa_node, "rc", "reg-names"); 228 if (idx < 0 || idx >= faa->fa_nreg || 229 bus_space_map(sc->sc_iot, faa->fa_reg[idx].addr, 230 faa->fa_reg[idx].size, 0, &sc->sc_rc_ioh)) { 231 printf(": can't map registers\n"); 232 return; 233 } 234 235 for (port = 0; port < APLPCIE_MAX_PORTS; port++) { 236 snprintf(name, sizeof(name), "port%d", port); 237 idx = OF_getindex(faa->fa_node, name, "reg-names"); 238 if (idx < 0) 239 continue; 240 if (idx > faa->fa_nreg || 241 bus_space_map(sc->sc_iot, faa->fa_reg[idx].addr, 242 faa->fa_reg[idx].size, 0, &sc->sc_port_ioh[port])) { 243 printf(": can't map registers\n"); 244 return; 245 } 246 sc->sc_port_ios[port] = faa->fa_reg[idx].size; 247 248 snprintf(name, sizeof(name), "phy%d", port); 249 idx = OF_getindex(faa->fa_node, name, "reg-names"); 250 if (idx < 0) { 251 bus_space_subregion(sc->sc_iot, sc->sc_rc_ioh, 252 PCIE_RC_PHY_BASE(port), PCIE_RC_PHY_SIZE, 253 &sc->sc_phy_ioh[port]); 254 continue; 255 } 256 if (idx > faa->fa_nreg || 257 bus_space_map(sc->sc_iot, faa->fa_reg[idx].addr, 258 faa->fa_reg[idx].size, 0, &sc->sc_phy_ioh[port])) { 259 printf(": can't map registers\n"); 260 return; 261 } 262 sc->sc_phy_ios[port] = faa->fa_reg[idx].size; 263 } 264 265 sc->sc_dmat = faa->fa_dmat; 266 sc->sc_node = faa->fa_node; 267 268 power_domain_enable(sc->sc_node); 269 pinctrl_byname(sc->sc_node, "default"); 270 271 sc->sc_msi_doorbell = 272 OF_getpropint64(sc->sc_node, "msi-doorbell", 0xffff000ULL); 273 sc->sc_msi_rangelen = OF_getpropintarray(sc->sc_node, "msi-ranges", 274 sc->sc_msi_range, sizeof(sc->sc_msi_range)); 275 if (sc->sc_msi_rangelen <= 0 || 276 (sc->sc_msi_rangelen % sizeof(uint32_t)) || 277 (sc->sc_msi_rangelen / sizeof(uint32_t)) < 5 || 278 (sc->sc_msi_rangelen / sizeof(uint32_t) > 6)) { 279 printf(": invalid msi-ranges property\n"); 280 return; 281 } 282 283 if (OF_is_compatible(sc->sc_node, "apple,t6020-pcie")) { 284 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) 285 aplpcie_t6020_init_port(sc, node); 286 } else { 287 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) 288 aplpcie_init_port(sc, node); 289 } 290 291 /* 292 * Must wait at least 100ms after link training completes 293 * before sending a configuration request to a device 294 * immediately below a port. 295 */ 296 delay(100000); 297 298 sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells", 299 faa->fa_acells); 300 sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells", 301 faa->fa_scells); 302 sc->sc_pacells = faa->fa_acells; 303 sc->sc_pscells = faa->fa_scells; 304 305 rangeslen = OF_getproplen(sc->sc_node, "ranges"); 306 if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) || 307 (rangeslen / sizeof(uint32_t)) % (sc->sc_acells + 308 sc->sc_pacells + sc->sc_scells)) { 309 printf(": invalid ranges property\n"); 310 return; 311 } 312 313 ranges = malloc(rangeslen, M_TEMP, M_WAITOK); 314 OF_getpropintarray(sc->sc_node, "ranges", ranges, 315 rangeslen); 316 317 nranges = (rangeslen / sizeof(uint32_t)) / 318 (sc->sc_acells + sc->sc_pacells + sc->sc_scells); 319 sc->sc_ranges = mallocarray(nranges, 320 sizeof(struct aplpcie_range), M_TEMP, M_WAITOK); 321 sc->sc_nranges = nranges; 322 323 for (i = 0, j = 0; i < sc->sc_nranges; i++) { 324 sc->sc_ranges[i].flags = ranges[j++]; 325 sc->sc_ranges[i].pci_base = ranges[j++]; 326 if (sc->sc_acells - 1 == 2) { 327 sc->sc_ranges[i].pci_base <<= 32; 328 sc->sc_ranges[i].pci_base |= ranges[j++]; 329 } 330 sc->sc_ranges[i].phys_base = ranges[j++]; 331 if (sc->sc_pacells == 2) { 332 sc->sc_ranges[i].phys_base <<= 32; 333 sc->sc_ranges[i].phys_base |= ranges[j++]; 334 } 335 sc->sc_ranges[i].size = ranges[j++]; 336 if (sc->sc_scells == 2) { 337 sc->sc_ranges[i].size <<= 32; 338 sc->sc_ranges[i].size |= ranges[j++]; 339 } 340 } 341 342 free(ranges, M_TEMP, rangeslen); 343 344 printf("\n"); 345 346 /* Create extents for our address spaces. */ 347 sc->sc_busex = extent_create("pcibus", 0, 255, 348 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 349 sc->sc_memex = extent_create("pcimem", 0, (u_long)-1, 350 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 351 sc->sc_pmemex = extent_create("pcipmem", 0, (u_long)-1, 352 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 353 sc->sc_ioex = extent_create("pciio", 0, 0xffffffff, 354 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 355 for (i = 0; i < sc->sc_nranges; i++) { 356 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000) { 357 extent_free(sc->sc_ioex, sc->sc_ranges[i].pci_base, 358 sc->sc_ranges[i].size, EX_WAITOK); 359 } 360 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000) { 361 extent_free(sc->sc_memex, sc->sc_ranges[i].pci_base, 362 sc->sc_ranges[i].size, EX_WAITOK); 363 } 364 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x03000000) { 365 extent_free(sc->sc_pmemex, sc->sc_ranges[i].pci_base, 366 sc->sc_ranges[i].size, EX_WAITOK); 367 } 368 } 369 370 /* Set up bus range. */ 371 if (OF_getpropintarray(sc->sc_node, "bus-range", bus_range, 372 sizeof(bus_range)) != sizeof(bus_range) || 373 bus_range[0] >= 32 || bus_range[1] >= 32) { 374 bus_range[0] = 0; 375 bus_range[1] = 31; 376 } 377 sc->sc_bus = bus_range[0]; 378 extent_free(sc->sc_busex, bus_range[0], 379 bus_range[1] - bus_range[0] + 1, EX_WAITOK); 380 381 memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 382 sc->sc_bus_iot.bus_private = sc; 383 sc->sc_bus_iot._space_map = aplpcie_bs_iomap; 384 memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 385 sc->sc_bus_memt.bus_private = sc; 386 sc->sc_bus_memt._space_map = aplpcie_bs_memmap; 387 388 sc->sc_pc.pc_conf_v = sc; 389 sc->sc_pc.pc_attach_hook = aplpcie_attach_hook; 390 sc->sc_pc.pc_bus_maxdevs = aplpcie_bus_maxdevs; 391 sc->sc_pc.pc_make_tag = aplpcie_make_tag; 392 sc->sc_pc.pc_decompose_tag = aplpcie_decompose_tag; 393 sc->sc_pc.pc_conf_size = aplpcie_conf_size; 394 sc->sc_pc.pc_conf_read = aplpcie_conf_read; 395 sc->sc_pc.pc_conf_write = aplpcie_conf_write; 396 sc->sc_pc.pc_probe_device_hook = aplpcie_probe_device_hook; 397 398 sc->sc_pc.pc_intr_v = sc; 399 sc->sc_pc.pc_intr_map = aplpcie_intr_map; 400 sc->sc_pc.pc_intr_map_msi = _pci_intr_map_msi; 401 sc->sc_pc.pc_intr_map_msix = _pci_intr_map_msix; 402 sc->sc_pc.pc_intr_string = aplpcie_intr_string; 403 sc->sc_pc.pc_intr_establish = aplpcie_intr_establish; 404 sc->sc_pc.pc_intr_disestablish = aplpcie_intr_disestablish; 405 406 memset(&pba, 0, sizeof(pba)); 407 pba.pba_busname = "pci"; 408 pba.pba_iot = &sc->sc_bus_iot; 409 pba.pba_memt = &sc->sc_bus_memt; 410 pba.pba_dmat = sc->sc_dmat; 411 pba.pba_pc = &sc->sc_pc; 412 pba.pba_busex = sc->sc_busex; 413 pba.pba_memex = sc->sc_memex; 414 pba.pba_pmemex = sc->sc_pmemex; 415 pba.pba_ioex = sc->sc_ioex; 416 pba.pba_domain = pci_ndomains++; 417 pba.pba_bus = sc->sc_bus; 418 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 419 420 sc->sc_msi_ic.ic_node = sc->sc_node; 421 sc->sc_msi_ic.ic_cookie = sc; 422 sc->sc_msi_ic.ic_establish_msi = aplpcie_intr_establish_msi; 423 sc->sc_msi_ic.ic_disestablish = aplpcie_intr_disestablish_msi; 424 sc->sc_msi_ic.ic_barrier = intr_barrier; 425 fdt_intr_register(&sc->sc_msi_ic); 426 427 pci_dopm = 1; 428 429 config_found(self, &pba, NULL); 430 } 431 432 void 433 aplpcie_init_port(struct aplpcie_softc *sc, int node) 434 { 435 char status[32]; 436 uint32_t reg[5]; 437 uint32_t *pwren_gpio; 438 uint32_t *reset_gpio; 439 int pwren_gpiolen, reset_gpiolen; 440 uint32_t stat; 441 int port, timo; 442 443 if (OF_getprop(node, "status", status, sizeof(status)) > 0 && 444 strcmp(status, "disabled") == 0) 445 return; 446 447 if (OF_getpropintarray(node, "reg", reg, sizeof(reg)) != sizeof(reg)) 448 return; 449 450 port = reg[0] >> 11; 451 if (port >= APLPCIE_MAX_PORTS || sc->sc_port_ios[port] == 0) 452 return; 453 454 pwren_gpiolen = OF_getproplen(node, "pwren-gpios"); 455 reset_gpiolen = OF_getproplen(node, "reset-gpios"); 456 if (reset_gpiolen <= 0) 457 return; 458 459 /* 460 * Set things up such that we can share the 32 available MSIs 461 * across all ports. 462 */ 463 PWRITE4(sc, port, PCIE_PORT_MSI_CTRL, 464 PCIE_PORT_MSI_CTRL_32 | PCIE_PORT_MSI_CTRL_ENABLE); 465 PWRITE4(sc, port, PCIE_PORT_MSI_REMAP, 0); 466 PWRITE4(sc, port, PCIE_PORT_MSI_DOORBELL, sc->sc_msi_doorbell); 467 468 /* Check if the link is already up. */ 469 stat = PREAD4(sc, port, PCIE_PORT_LINK_STAT); 470 if (stat & PCIE_PORT_LINK_STAT_UP) 471 return; 472 473 PSET4(sc, port, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_EN); 474 475 /* Assert PERST#. */ 476 reset_gpio = malloc(reset_gpiolen, M_TEMP, M_WAITOK); 477 OF_getpropintarray(node, "reset-gpios", reset_gpio, reset_gpiolen); 478 gpio_controller_config_pin(reset_gpio, GPIO_CONFIG_OUTPUT); 479 gpio_controller_set_pin(reset_gpio, 1); 480 481 /* Power up the device if necessary. */ 482 if (pwren_gpiolen > 0) { 483 pwren_gpio = malloc(pwren_gpiolen, M_TEMP, M_WAITOK); 484 OF_getpropintarray(node, "pwren-gpios", 485 pwren_gpio, pwren_gpiolen); 486 gpio_controller_config_pin(pwren_gpio, GPIO_CONFIG_OUTPUT); 487 gpio_controller_set_pin(pwren_gpio, 1); 488 free(pwren_gpio, M_TEMP, pwren_gpiolen); 489 } 490 491 /* Setup Refclk. */ 492 LSET4(sc, port, PCIE_PHY_LANE_CTRL, PCIE_PHY_LANE_CTRL_CFGACC); 493 LSET4(sc, port, PCIE_PHY_LANE_CONF, PCIE_PHY_LANE_CONF_REFCLK0REQ); 494 for (timo = 500; timo > 0; timo--) { 495 stat = LREAD4(sc, port, PCIE_PHY_LANE_CONF); 496 if (stat & PCIE_PHY_LANE_CONF_REFCLK0ACK) 497 break; 498 delay(100); 499 } 500 LSET4(sc, port, PCIE_PHY_LANE_CONF, PCIE_PHY_LANE_CONF_REFCLK1REQ); 501 for (timo = 500; timo > 0; timo--) { 502 stat = LREAD4(sc, port, PCIE_PHY_LANE_CONF); 503 if (stat & PCIE_PHY_LANE_CONF_REFCLK1ACK) 504 break; 505 delay(100); 506 } 507 LCLR4(sc, port, PCIE_PHY_LANE_CTRL, PCIE_PHY_LANE_CTRL_CFGACC); 508 LSET4(sc, port, PCIE_PHY_LANE_CONF, 509 PCIE_PHY_LANE_CONF_REFCLK0EN | PCIE_PHY_LANE_CONF_REFCLK1EN); 510 PSET4(sc, port, PCIE_PORT_REFCLK, PCIE_PORT_REFCLK_EN); 511 512 /* 513 * PERST# must remain asserted for at least 100us after the 514 * reference clock becomes stable. But also has to remain 515 * active at least 100ms after power up. 516 */ 517 if (pwren_gpiolen > 0) 518 delay(100000); 519 else 520 delay(100); 521 522 /* Deassert PERST#. */ 523 PSET4(sc, port, PCIE_PORT_PERST, PCIE_PORT_PERST_DIS); 524 gpio_controller_set_pin(reset_gpio, 0); 525 free(reset_gpio, M_TEMP, reset_gpiolen); 526 527 for (timo = 2500; timo > 0; timo--) { 528 stat = PREAD4(sc, port, PCIE_PORT_STAT); 529 if (stat & PCIE_PORT_STAT_READY) 530 break; 531 delay(100); 532 } 533 if ((stat & PCIE_PORT_STAT_READY) == 0) 534 return; 535 536 PCLR4(sc, port, PCIE_PORT_REFCLK, PCIE_PORT_REFCLK_CGDIS); 537 PCLR4(sc, port, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_CGDIS); 538 539 /* Bring up the link. */ 540 PWRITE4(sc, port, PCIE_PORT_LTSSM_CTRL, PCIE_PORT_LTSSM_CTRL_START); 541 for (timo = 1000; timo > 0; timo--) { 542 stat = PREAD4(sc, port, PCIE_PORT_LINK_STAT); 543 if (stat & PCIE_PORT_LINK_STAT_UP) 544 break; 545 delay(100); 546 } 547 } 548 549 void 550 aplpcie_t6020_init_port(struct aplpcie_softc *sc, int node) 551 { 552 char status[32]; 553 uint32_t reg[5]; 554 uint32_t *pwren_gpio; 555 uint32_t *reset_gpio; 556 int pwren_gpiolen, reset_gpiolen; 557 uint32_t stat; 558 int msi, port, timo; 559 560 if (OF_getprop(node, "status", status, sizeof(status)) > 0 && 561 strcmp(status, "disabled") == 0) 562 return; 563 564 if (OF_getpropintarray(node, "reg", reg, sizeof(reg)) != sizeof(reg)) 565 return; 566 567 port = reg[0] >> 11; 568 if (port >= APLPCIE_MAX_PORTS || sc->sc_port_ios[port] == 0) 569 return; 570 571 pwren_gpiolen = OF_getproplen(node, "pwren-gpios"); 572 reset_gpiolen = OF_getproplen(node, "reset-gpios"); 573 if (reset_gpiolen <= 0) 574 return; 575 576 /* 577 * Set things up such that we can share the 32 available MSIs 578 * across all ports. 579 */ 580 PWRITE4(sc, port, PCIE_PORT_MSI_CTRL, PCIE_PORT_MSI_CTRL_ENABLE); 581 for (msi = 0; msi < 32; msi++) 582 PWRITE4(sc, port, PCIE_T6020_PORT_MSI_MAP(msi), 583 msi | PCIE_T6020_PORT_MSI_MAP_ENABLE); 584 PWRITE4(sc, port, PCIE_T6020_PORT_MSI_DOORBELL_LO, 585 sc->sc_msi_doorbell); 586 PWRITE4(sc, port, PCIE_T6020_PORT_MSI_DOORBELL_HI, 587 sc->sc_msi_doorbell >> 32); 588 589 /* Check if the link is already up. */ 590 stat = PREAD4(sc, port, PCIE_PORT_LINK_STAT); 591 if (stat & PCIE_PORT_LINK_STAT_UP) 592 return; 593 594 PSET4(sc, port, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_EN); 595 596 /* Assert PERST#. */ 597 reset_gpio = malloc(reset_gpiolen, M_TEMP, M_WAITOK); 598 OF_getpropintarray(node, "reset-gpios", reset_gpio, reset_gpiolen); 599 gpio_controller_config_pin(reset_gpio, GPIO_CONFIG_OUTPUT); 600 gpio_controller_set_pin(reset_gpio, 1); 601 602 /* Power up the device if necessary. */ 603 if (pwren_gpiolen > 0) { 604 pwren_gpio = malloc(pwren_gpiolen, M_TEMP, M_WAITOK); 605 OF_getpropintarray(node, "pwren-gpios", 606 pwren_gpio, pwren_gpiolen); 607 gpio_controller_config_pin(pwren_gpio, GPIO_CONFIG_OUTPUT); 608 gpio_controller_set_pin(pwren_gpio, 1); 609 free(pwren_gpio, M_TEMP, pwren_gpiolen); 610 } 611 612 /* Setup Refclk. */ 613 LSET4(sc, port, PCIE_PHY_LANE_CONF, PCIE_PHY_LANE_CONF_REFCLK0REQ); 614 for (timo = 500; timo > 0; timo--) { 615 stat = LREAD4(sc, port, PCIE_PHY_LANE_CONF); 616 if (stat & PCIE_PHY_LANE_CONF_REFCLK0ACK) 617 break; 618 delay(100); 619 } 620 LSET4(sc, port, PCIE_PHY_LANE_CONF, PCIE_PHY_LANE_CONF_REFCLK1REQ); 621 for (timo = 500; timo > 0; timo--) { 622 stat = LREAD4(sc, port, PCIE_PHY_LANE_CONF); 623 if (stat & PCIE_PHY_LANE_CONF_REFCLK1ACK) 624 break; 625 delay(100); 626 } 627 LSET4(sc, port, PCIE_PHY_LANE_CONF, 628 PCIE_PHY_LANE_CONF_REFCLK0EN | PCIE_PHY_LANE_CONF_REFCLK1EN); 629 630 /* 631 * PERST# must remain asserted for at least 100us after the 632 * reference clock becomes stable. But also has to remain 633 * active at least 100ms after power up. 634 */ 635 if (pwren_gpiolen > 0) 636 delay(100000); 637 else 638 delay(100); 639 640 /* Deassert PERST#. */ 641 PSET4(sc, port, PCIE_T6020_PORT_PERST, PCIE_PORT_PERST_DIS); 642 gpio_controller_set_pin(reset_gpio, 0); 643 free(reset_gpio, M_TEMP, reset_gpiolen); 644 645 for (timo = 2500; timo > 0; timo--) { 646 stat = PREAD4(sc, port, PCIE_PORT_STAT); 647 if (stat & PCIE_PORT_STAT_READY) 648 break; 649 delay(100); 650 } 651 if ((stat & PCIE_PORT_STAT_READY) == 0) 652 return; 653 654 LSET4(sc, port, PCIE_PHY_LANE_CONF, 655 PCIE_PHY_LANE_CONF_REFCLK0CGEN | PCIE_PHY_LANE_CONF_REFCLK1CGEN); 656 PCLR4(sc, port, PCIE_PORT_APPCLK, PCIE_PORT_APPCLK_CGDIS); 657 658 /* Bring up the link. */ 659 PWRITE4(sc, port, PCIE_PORT_LTSSM_CTRL, PCIE_PORT_LTSSM_CTRL_START); 660 for (timo = 1000; timo > 0; timo--) { 661 stat = PREAD4(sc, port, PCIE_PORT_LINK_STAT); 662 if (stat & PCIE_PORT_LINK_STAT_UP) 663 break; 664 delay(100); 665 } 666 } 667 668 void 669 aplpcie_attach_hook(struct device *parent, struct device *self, 670 struct pcibus_attach_args *pba) 671 { 672 } 673 674 int 675 aplpcie_bus_maxdevs(void *v, int bus) 676 { 677 return 32; 678 } 679 680 int 681 aplpcie_find_node(int node, int bus, int device, int function) 682 { 683 uint32_t reg[5]; 684 uint32_t phys_hi; 685 int child; 686 687 phys_hi = ((bus << 16) | (device << 11) | (function << 8)); 688 689 for (child = OF_child(node); child; child = OF_peer(child)) { 690 if (OF_getpropintarray(child, "reg", 691 reg, sizeof(reg)) != sizeof(reg)) 692 continue; 693 694 if (reg[0] == phys_hi) 695 return child; 696 697 node = aplpcie_find_node(child, bus, device, function); 698 if (node) 699 return node; 700 } 701 702 return 0; 703 } 704 705 pcitag_t 706 aplpcie_make_tag(void *v, int bus, int device, int function) 707 { 708 struct aplpcie_softc *sc = v; 709 int node; 710 711 node = aplpcie_find_node(sc->sc_node, bus, device, function); 712 return (((pcitag_t)node << 32) | 713 (bus << 20) | (device << 15) | (function << 12)); 714 } 715 716 void 717 aplpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 718 { 719 if (bp != NULL) 720 *bp = (tag >> 20) & 0xff; 721 if (dp != NULL) 722 *dp = (tag >> 15) & 0x1f; 723 if (fp != NULL) 724 *fp = (tag >> 12) & 0x7; 725 } 726 727 int 728 aplpcie_conf_size(void *v, pcitag_t tag) 729 { 730 return PCIE_CONFIG_SPACE_SIZE; 731 } 732 733 pcireg_t 734 aplpcie_conf_read(void *v, pcitag_t tag, int reg) 735 { 736 struct aplpcie_softc *sc = v; 737 738 tag = PCITAG_OFFSET(tag); 739 return HREAD4(sc, tag | reg); 740 } 741 742 void 743 aplpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 744 { 745 struct aplpcie_softc *sc = v; 746 747 tag = PCITAG_OFFSET(tag); 748 HWRITE4(sc, tag | reg, data); 749 } 750 751 int 752 aplpcie_probe_device_hook(void *v, struct pci_attach_args *pa) 753 { 754 struct aplpcie_softc *sc = v; 755 uint16_t rid; 756 757 rid = pci_requester_id(pa->pa_pc, pa->pa_tag); 758 pa->pa_dmat = iommu_device_map_pci(sc->sc_node, rid, pa->pa_dmat); 759 760 return 0; 761 } 762 763 int 764 aplpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 765 { 766 int pin = pa->pa_rawintrpin; 767 768 if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX) 769 return -1; 770 771 if (pa->pa_tag == 0) 772 return -1; 773 774 ihp->ih_pc = pa->pa_pc; 775 ihp->ih_tag = pa->pa_intrtag; 776 ihp->ih_intrpin = pa->pa_intrpin; 777 ihp->ih_type = PCI_INTX; 778 779 return 0; 780 } 781 782 const char * 783 aplpcie_intr_string(void *v, pci_intr_handle_t ih) 784 { 785 switch (ih.ih_type) { 786 case PCI_MSI: 787 return "msi"; 788 case PCI_MSIX: 789 return "msix"; 790 } 791 792 return "intx"; 793 } 794 795 void * 796 aplpcie_intr_establish(void *v, pci_intr_handle_t ih, int level, 797 struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 798 { 799 struct aplpcie_softc *sc = v; 800 void *cookie; 801 802 KASSERT(ih.ih_type != PCI_NONE); 803 804 if (ih.ih_type != PCI_INTX) { 805 uint64_t addr, data; 806 807 cookie = fdt_intr_establish_msi_cpu(sc->sc_node, &addr, 808 &data, level, ci, func, arg, name); 809 if (cookie == NULL) 810 return NULL; 811 812 if (ih.ih_type == PCI_MSIX) { 813 pci_msix_enable(ih.ih_pc, ih.ih_tag, 814 &sc->sc_bus_memt, ih.ih_intrpin, addr, data); 815 } else 816 pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data); 817 } else { 818 int bus, dev, fn; 819 uint32_t reg[4]; 820 821 aplpcie_decompose_tag(sc, ih.ih_tag, &bus, &dev, &fn); 822 823 reg[0] = bus << 16 | dev << 11 | fn << 8; 824 reg[1] = reg[2] = 0; 825 reg[3] = ih.ih_intrpin; 826 827 cookie = fdt_intr_establish_imap_cpu(sc->sc_node, reg, 828 sizeof(reg), level, ci, func, arg, name); 829 } 830 831 return cookie; 832 } 833 834 void 835 aplpcie_intr_disestablish(void *v, void *cookie) 836 { 837 } 838 839 void * 840 aplpcie_intr_establish_msi(void *cookie, uint64_t *addr, uint64_t *data, 841 int level, struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 842 { 843 struct aplpcie_softc *sc = cookie; 844 uint32_t cells[4]; 845 int ncells; 846 847 ncells = sc->sc_msi_rangelen / sizeof(uint32_t); 848 if (sc->sc_msi >= sc->sc_msi_range[ncells - 1]) 849 return NULL; 850 851 *addr = sc->sc_msi_doorbell; 852 *data = sc->sc_msi++; 853 854 memcpy(cells, &sc->sc_msi_range[1], sizeof(cells)); 855 cells[ncells - 4] += *data; 856 857 return fdt_intr_parent_establish(&sc->sc_msi_ic, cells, 858 level, ci, func, arg, name); 859 } 860 861 void 862 aplpcie_intr_disestablish_msi(void *cookie) 863 { 864 fdt_intr_parent_disestablish(cookie); 865 } 866 867 int 868 aplpcie_bs_iomap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 869 int flags, bus_space_handle_t *bshp) 870 { 871 struct aplpcie_softc *sc = t->bus_private; 872 int i; 873 874 for (i = 0; i < sc->sc_nranges; i++) { 875 uint64_t pci_start = sc->sc_ranges[i].pci_base; 876 uint64_t pci_end = pci_start + sc->sc_ranges[i].size; 877 uint64_t phys_start = sc->sc_ranges[i].phys_base; 878 879 if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 && 880 addr >= pci_start && addr + size <= pci_end) { 881 return bus_space_map(sc->sc_iot, 882 addr - pci_start + phys_start, size, flags, bshp); 883 } 884 } 885 886 return ENXIO; 887 } 888 889 int 890 aplpcie_bs_memmap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 891 int flags, bus_space_handle_t *bshp) 892 { 893 struct aplpcie_softc *sc = t->bus_private; 894 int i; 895 896 flags |= BUS_SPACE_MAP_POSTED; 897 898 for (i = 0; i < sc->sc_nranges; i++) { 899 uint64_t pci_start = sc->sc_ranges[i].pci_base; 900 uint64_t pci_end = pci_start + sc->sc_ranges[i].size; 901 uint64_t phys_start = sc->sc_ranges[i].phys_base; 902 903 if ((sc->sc_ranges[i].flags & 0x02000000) == 0x02000000 && 904 addr >= pci_start && addr + size <= pci_end) { 905 return bus_space_map(sc->sc_iot, 906 addr - pci_start + phys_start, size, flags, bshp); 907 } 908 } 909 910 return ENXIO; 911 } 912