1 /* $NetBSD: pci_machdep.c,v 1.12 2017/04/19 12:26:00 jmcneill Exp $ */ 2 /* 3 * Copyright (c) 2008 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.12 2017/04/19 12:26:00 jmcneill Exp $"); 30 31 #include "opt_mvsoc.h" 32 #include "gtpci.h" 33 #include "mvpex.h" 34 #include "pci.h" 35 36 #include <sys/param.h> 37 #include <sys/device.h> 38 #include <sys/extent.h> 39 40 #include <dev/pci/pcivar.h> 41 #include <dev/pci/pciconf.h> 42 43 #include <arm/marvell/mvsocreg.h> 44 #include <arm/marvell/mvsocvar.h> 45 #include <arm/marvell/mvsocgppvar.h> 46 #if NGTPCI > 0 47 #include <dev/marvell/gtpcireg.h> 48 #include <dev/marvell/gtpcivar.h> 49 #endif 50 #if NMVPEX > 0 51 #include <dev/marvell/mvpexreg.h> 52 #include <dev/marvell/mvpexvar.h> 53 #endif 54 55 #include <machine/pci_machdep.h> 56 57 #if defined(ORION) 58 #include <arm/marvell/orionreg.h> 59 #endif 60 #if defined(KIRKWOOD) 61 #include <arm/marvell/kirkwoodreg.h> 62 #endif 63 #include <dev/marvell/marvellreg.h> 64 65 66 #if NGTPCI > 0 67 #if NGTPCI_MBUS > 0 68 static pcireg_t gtpci_mbus_conf_read(void *, pcitag_t, int); 69 static void gtpci_mbus_conf_write(void *, pcitag_t, int, pcireg_t); 70 #endif 71 static int gtpci_gpp_intr_map(const struct pci_attach_args *, 72 pci_intr_handle_t *); 73 static const char *gtpci_gpp_intr_string(void *, pci_intr_handle_t, 74 char *, size_t); 75 static const struct evcnt *gtpci_gpp_intr_evcnt(void *, pci_intr_handle_t); 76 static void *gtpci_gpp_intr_establish(void *, pci_intr_handle_t, int, int (*)(void *), void *); 77 static void gtpci_gpp_intr_disestablish(void *, void *); 78 79 struct arm32_pci_chipset arm32_gtpci_chipset = { 80 NULL, /* conf_v */ 81 gtpci_attach_hook, 82 gtpci_bus_maxdevs, 83 gtpci_make_tag, 84 gtpci_decompose_tag, 85 #if NGTPCI_MBUS > 0 86 gtpci_mbus_conf_read, /* XXXX: always this functions */ 87 gtpci_mbus_conf_write, 88 #else 89 gtpci_conf_read, 90 gtpci_conf_write, 91 #endif 92 NULL, /* intr_v */ 93 gtpci_gpp_intr_map, 94 gtpci_gpp_intr_string, 95 gtpci_gpp_intr_evcnt, 96 NULL, /* intr_setattr */ 97 gtpci_gpp_intr_establish, 98 gtpci_gpp_intr_disestablish, 99 #ifdef __HAVE_PCI_CONF_HOOK 100 gtpci_conf_hook, 101 #endif 102 gtpci_conf_interrupt, 103 }; 104 #endif 105 106 #if NMVPEX > 0 107 #if NMVPEX_MBUS > 0 108 static pcireg_t mvpex_mbus_conf_read(void *, pcitag_t, int); 109 #endif 110 111 struct arm32_pci_chipset arm32_mvpex0_chipset = { 112 NULL, /* conf_v */ 113 mvpex_attach_hook, 114 mvpex_bus_maxdevs, 115 mvpex_make_tag, 116 mvpex_decompose_tag, 117 #if NMVPEX_MBUS > 0 118 mvpex_mbus_conf_read, /* XXXX: always this functions */ 119 #else 120 mvpex_conf_read, 121 #endif 122 mvpex_conf_write, 123 NULL, /* intr_v */ 124 mvpex_intr_map, 125 mvpex_intr_string, 126 mvpex_intr_evcnt, 127 NULL, /* intr_setattr */ 128 mvpex_intr_establish, 129 mvpex_intr_disestablish, 130 #ifdef __HAVE_PCI_CONF_HOOK 131 mvpex_conf_hook, 132 #endif 133 mvpex_conf_interrupt, 134 }; 135 struct arm32_pci_chipset arm32_mvpex1_chipset = { 136 NULL, /* conf_v */ 137 mvpex_attach_hook, 138 mvpex_bus_maxdevs, 139 mvpex_make_tag, 140 mvpex_decompose_tag, 141 #if NMVPEX_MBUS > 0 142 mvpex_mbus_conf_read, /* XXXX: always this functions */ 143 #else 144 mvpex_conf_read, 145 #endif 146 mvpex_conf_write, 147 NULL, /* intr_v */ 148 mvpex_intr_map, 149 mvpex_intr_string, 150 mvpex_intr_evcnt, 151 NULL, /* intr_setattr */ 152 mvpex_intr_establish, 153 mvpex_intr_disestablish, 154 #ifdef __HAVE_PCI_CONF_HOOK 155 mvpex_conf_hook, 156 #endif 157 mvpex_conf_interrupt, 158 }; 159 struct arm32_pci_chipset arm32_mvpex2_chipset = { 160 NULL, /* conf_v */ 161 mvpex_attach_hook, 162 mvpex_bus_maxdevs, 163 mvpex_make_tag, 164 mvpex_decompose_tag, 165 #if NMVPEX_MBUS > 0 166 mvpex_mbus_conf_read, /* XXXX: always this functions */ 167 #else 168 mvpex_conf_read, 169 #endif 170 mvpex_conf_write, 171 NULL, /* intr_v */ 172 mvpex_intr_map, 173 mvpex_intr_string, 174 mvpex_intr_evcnt, 175 NULL, /* intr_setattr */ 176 mvpex_intr_establish, 177 mvpex_intr_disestablish, 178 #ifdef __HAVE_PCI_CONF_HOOK 179 mvpex_conf_hook, 180 #endif 181 mvpex_conf_interrupt, 182 }; 183 struct arm32_pci_chipset arm32_mvpex3_chipset = { 184 NULL, /* conf_v */ 185 mvpex_attach_hook, 186 mvpex_bus_maxdevs, 187 mvpex_make_tag, 188 mvpex_decompose_tag, 189 #if NMVPEX_MBUS > 0 190 mvpex_mbus_conf_read, /* XXXX: always this functions */ 191 #else 192 mvpex_conf_read, 193 #endif 194 mvpex_conf_write, 195 NULL, /* intr_v */ 196 mvpex_intr_map, 197 mvpex_intr_string, 198 mvpex_intr_evcnt, 199 NULL, /* intr_setattr */ 200 mvpex_intr_establish, 201 mvpex_intr_disestablish, 202 #ifdef __HAVE_PCI_CONF_HOOK 203 mvpex_conf_hook, 204 #endif 205 mvpex_conf_interrupt, 206 }; 207 struct arm32_pci_chipset arm32_mvpex4_chipset = { 208 NULL, /* conf_v */ 209 mvpex_attach_hook, 210 mvpex_bus_maxdevs, 211 mvpex_make_tag, 212 mvpex_decompose_tag, 213 #if NMVPEX_MBUS > 0 214 mvpex_mbus_conf_read, /* XXXX: always this functions */ 215 #else 216 mvpex_conf_read, 217 #endif 218 mvpex_conf_write, 219 NULL, /* intr_v */ 220 mvpex_intr_map, 221 mvpex_intr_string, 222 mvpex_intr_evcnt, 223 NULL, /* intr_setattr */ 224 mvpex_intr_establish, 225 mvpex_intr_disestablish, 226 #ifdef __HAVE_PCI_CONF_HOOK 227 mvpex_conf_hook, 228 #endif 229 mvpex_conf_interrupt, 230 }; 231 struct arm32_pci_chipset arm32_mvpex5_chipset = { 232 NULL, /* conf_v */ 233 mvpex_attach_hook, 234 mvpex_bus_maxdevs, 235 mvpex_make_tag, 236 mvpex_decompose_tag, 237 #if NMVPEX_MBUS > 0 238 mvpex_mbus_conf_read, /* XXXX: always this functions */ 239 #else 240 mvpex_conf_read, 241 #endif 242 mvpex_conf_write, 243 NULL, /* intr_v */ 244 mvpex_intr_map, 245 mvpex_intr_string, 246 mvpex_intr_evcnt, 247 NULL, /* intr_setattr */ 248 mvpex_intr_establish, 249 mvpex_intr_disestablish, 250 #ifdef __HAVE_PCI_CONF_HOOK 251 mvpex_conf_hook, 252 #endif 253 mvpex_conf_interrupt, 254 }; 255 struct arm32_pci_chipset arm32_mvpex6_chipset = { 256 NULL, /* conf_v */ 257 mvpex_attach_hook, 258 mvpex_bus_maxdevs, 259 mvpex_make_tag, 260 mvpex_decompose_tag, 261 #if NMVPEX_MBUS > 0 262 mvpex_mbus_conf_read, /* XXXX: always this functions */ 263 #else 264 mvpex_conf_read, 265 #endif 266 mvpex_conf_write, 267 NULL, /* intr_v */ 268 mvpex_intr_map, 269 mvpex_intr_string, 270 mvpex_intr_evcnt, 271 NULL, /* intr_setattr */ 272 mvpex_intr_establish, 273 mvpex_intr_disestablish, 274 #ifdef __HAVE_PCI_CONF_HOOK 275 mvpex_conf_hook, 276 #endif 277 mvpex_conf_interrupt, 278 }; 279 #endif /* NMVPEX > 0 */ 280 281 #if NGTPCI > 0 282 /* ARGSUSED */ 283 void 284 gtpci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz, int *iline) 285 { 286 287 /* nothing */ 288 } 289 290 #if NGTPCI_MBUS > 0 291 #define GTPCI_MBUS_CA 0x0c78 /* Configuration Address */ 292 #define GTPCI_MBUS_CD 0x0c7c /* Configuration Data */ 293 294 static pcireg_t 295 gtpci_mbus_conf_read(void *v, pcitag_t tag, int reg) 296 { 297 struct gtpci_softc *sc = v; 298 const pcireg_t addr = tag | reg; 299 300 if ((unsigned int)reg >= PCI_CONF_SIZE) 301 return -1; 302 303 bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA, 304 addr | GTPCI_CA_CONFIGEN); 305 if ((addr | GTPCI_CA_CONFIGEN) != 306 bus_space_read_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA)) 307 return -1; 308 309 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CD); 310 } 311 312 static void 313 gtpci_mbus_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 314 { 315 struct gtpci_softc *sc = v; 316 pcireg_t addr = tag | (reg & 0xfc); 317 318 if ((unsigned int)reg >= PCI_CONF_SIZE) 319 return; 320 321 bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA, 322 addr | GTPCI_CA_CONFIGEN); 323 if ((addr | GTPCI_CA_CONFIGEN) != 324 bus_space_read_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CA)) 325 return; 326 327 bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTPCI_MBUS_CD, data); 328 } 329 #endif /* NGTPCI_MBUS */ 330 331 /* 332 * We assume to use GPP interrupt as PCI interrupts. 333 * pci_intr_map() shall returns number of GPP between 0 and 31. However 334 * returns 0xff, because we do not know the connected pin number for GPP 335 * of your board. 336 * pci_intr_string() shall returns string "gpp <num>". 337 * pci_intr_establish() established interrupt in the pin of all GPP. 338 * Moreover, the return value will be disregarded. For instance, the 339 * setting for interrupt is not done. 340 */ 341 342 /* ARGSUSED */ 343 static int 344 gtpci_gpp_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 345 { 346 347 *ihp = pa->pa_intrpin; 348 return 0; 349 } 350 351 /* ARGSUSED */ 352 static const char * 353 gtpci_gpp_intr_string(void *v, pci_intr_handle_t pin, char *buf, size_t len) 354 { 355 struct gtpci_softc *sc = v; 356 prop_array_t int2gpp; 357 prop_object_t gpp; 358 359 int2gpp = prop_dictionary_get(device_properties(sc->sc_dev), "int2gpp"); 360 gpp = prop_array_get(int2gpp, pin); 361 snprintf(buf, len, "gpp %d", (int)prop_number_integer_value(gpp)); 362 363 return buf; 364 } 365 366 /* ARGSUSED */ 367 static const struct evcnt * 368 gtpci_gpp_intr_evcnt(void *v, pci_intr_handle_t pin) 369 { 370 371 return NULL; 372 } 373 374 static void * 375 gtpci_gpp_intr_establish(void *v, pci_intr_handle_t int_pin, int ipl, 376 int (*intrhand)(void *), void *intrarg) 377 { 378 struct gtpci_softc *sc = v; 379 prop_array_t int2gpp; 380 prop_object_t gpp; 381 int gpp_pin; 382 383 int2gpp = prop_dictionary_get(device_properties(sc->sc_dev), "int2gpp"); 384 gpp = prop_array_get(int2gpp, int_pin); 385 gpp_pin = prop_number_integer_value(gpp); 386 return mvsocgpp_intr_establish(gpp_pin, ipl, IST_LEVEL_LOW, intrhand, 387 intrarg); 388 } 389 390 static void 391 gtpci_gpp_intr_disestablish(void *v, void *ih) 392 { 393 394 mvsocgpp_intr_disestablish(ih); 395 } 396 #endif 397 398 #if NMVPEX_MBUS > 0 399 /* ARGSUSED */ 400 void 401 mvpex_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, int *ilinep) 402 { 403 404 /* nothing */ 405 } 406 407 static pcireg_t 408 mvpex_mbus_conf_read(void *v, pcitag_t tag, int reg) 409 { 410 struct mvpex_softc *sc = v; 411 pcireg_t addr, data, pci_cs; 412 uint32_t stat; 413 int bus, dev, func, pexbus, pexdev; 414 415 if ((unsigned int)reg >= PCI_CONF_SIZE) 416 return -1; 417 418 mvpex_decompose_tag(v, tag, &bus, &dev, &func); 419 420 stat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_STAT); 421 pexbus = MVPEX_STAT_PEXBUSNUM(stat); 422 pexdev = MVPEX_STAT_PEXDEVNUM(stat); 423 if (bus != pexbus || dev != pexdev) 424 if (stat & MVPEX_STAT_DLDOWN) 425 return -1; 426 427 if (bus == pexbus) { 428 if (pexdev == 0) { 429 if (dev != 1 && dev != pexdev) 430 return -1; 431 } else { 432 if (dev != 0 && dev != pexdev) 433 return -1; 434 } 435 if (func != 0) 436 return -1; 437 } 438 439 addr = ((reg & 0xf00) << 24) | tag | (reg & 0xfc); 440 441 #if defined(ORION) 442 /* 443 * Guideline (GL# PCI Express-1) Erroneous Read Data on Configuration 444 * This guideline is relevant for all devices except of the following 445 * devices: 446 * 88F5281-BO and above, and 88F5181L-A0 and above 447 */ 448 if ((bus != pexbus || dev != pexdev) && 449 !(sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev == 1) && 450 !(sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev == 8)) { 451 452 /* PCI-Express configuration read work-around */ 453 /* 454 * We will use one of the Punit (AHBToMbus) windows to 455 * access the xbar and read the data from there 456 * 457 * Need to configure the 2 free Punit (AHB to MBus bridge) 458 * address decoding windows: 459 * Configure the flash Window to handle Configuration space 460 * requests for PEX0/1: 461 * 462 * Configuration transactions from the CPU should write/read 463 * the data to/from address of the form: 464 * addr[31:28]: 0x5 (for PEX0) or 0x6 (for PEX1) 465 * addr[27:24]: extended register number 466 * addr[23:16]: bus number 467 * addr[15:11]: device number 468 * addr[10: 8]: function number 469 * addr[ 7: 0]: register number 470 */ 471 472 struct mvsoc_softc *soc = 473 device_private(device_parent(sc->sc_dev));; 474 bus_space_handle_t pcicfg_ioh; 475 uint32_t remapl, remaph, wc, pcicfg_addr, pcicfg_size; 476 int window, target, attr, base, size, s; 477 const int pex_pcicfg_tag = 478 (sc->sc_model == MARVELL_ORION_1_88F1181) ? 479 ORION_TAG_FLASH_CS : ORION_TAG_PEX0_MEM; 480 481 window = mvsoc_target(pex_pcicfg_tag, 482 &target, &attr, &base, &size); 483 if (window >= nwindow) { 484 aprint_error_dev(sc->sc_dev, 485 "can't read pcicfg space\n"); 486 return -1; 487 } 488 489 s = splhigh(); 490 491 remapl = remaph = 0; 492 if (window == 0 || window == 1) { 493 remapl = read_mlmbreg(MVSOC_MLMB_WRLR(window)); 494 remaph = read_mlmbreg(MVSOC_MLMB_WRHR(window)); 495 } 496 497 wc = 498 MVSOC_MLMB_WCR_WINEN | 499 MVSOC_MLMB_WCR_ATTR(ORION_ATTR_PEX_CFG) | 500 MVSOC_MLMB_WCR_TARGET((soc->sc_addr + sc->sc_offset) >> 16); 501 if (sc->sc_model == MARVELL_ORION_1_88F1181) { 502 pcicfg_addr = base; 503 pcicfg_size = size; 504 } else if (sc->sc_model == MARVELL_ORION_1_88F5182) { 505 #define PEX_PCICFG_RW_WA_BASE 0x50000000 506 #define PEX_PCICFG_RW_WA_5182_BASE 0xf0000000 507 #define PEX_PCICFG_RW_WA_SIZE (16 * 1024 * 1024) 508 pcicfg_addr = PEX_PCICFG_RW_WA_5182_BASE; 509 pcicfg_size = PEX_PCICFG_RW_WA_SIZE; 510 } else { 511 pcicfg_addr = PEX_PCICFG_RW_WA_BASE; 512 pcicfg_size = PEX_PCICFG_RW_WA_SIZE; 513 } 514 write_mlmbreg(MVSOC_MLMB_WCR(window), 515 wc | MVSOC_MLMB_WCR_SIZE(pcicfg_size)); 516 write_mlmbreg(MVSOC_MLMB_WBR(window), pcicfg_addr); 517 518 if (window == 0 || window == 1) { 519 write_mlmbreg(MVSOC_MLMB_WRLR(window), pcicfg_addr); 520 write_mlmbreg(MVSOC_MLMB_WRHR(window), 0); 521 } 522 523 if (bus_space_map(sc->sc_iot, pcicfg_addr, pcicfg_size, 0, 524 &pcicfg_ioh) == 0) { 525 data = bus_space_read_4(sc->sc_iot, pcicfg_ioh, addr); 526 bus_space_unmap(sc->sc_iot, pcicfg_ioh, pcicfg_size); 527 } else 528 data = -1; 529 530 write_mlmbreg(MVSOC_MLMB_WCR(window), 531 MVSOC_MLMB_WCR_WINEN | 532 MVSOC_MLMB_WCR_ATTR(attr) | 533 MVSOC_MLMB_WCR_TARGET(target) | 534 MVSOC_MLMB_WCR_SIZE(size)); 535 write_mlmbreg(MVSOC_MLMB_WBR(window), base); 536 if (window == 0 || window == 1) { 537 write_mlmbreg(MVSOC_MLMB_WRLR(window), remapl); 538 write_mlmbreg(MVSOC_MLMB_WRHR(window), remaph); 539 } 540 541 splx(s); 542 #else 543 if (0) { 544 #endif 545 } else { 546 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVPEX_CA, 547 addr | MVPEX_CA_CONFIGEN); 548 if ((addr | MVPEX_CA_CONFIGEN) != 549 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_CA)) 550 return -1; 551 552 pci_cs = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 553 PCI_COMMAND_STATUS_REG); 554 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 555 PCI_COMMAND_STATUS_REG, pci_cs | PCI_STATUS_MASTER_ABORT); 556 557 data = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVPEX_CD); 558 } 559 560 return data; 561 } 562 #endif 563