1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * PPC Board Support Package: PCI File: mpc824x_pci_machdep.c 5 * 6 * Author: Ed Satterthwaite 7 * 8 ********************************************************************* 9 * 10 * Copyright 2004 11 * Broadcom Corporation. All rights reserved. 12 * 13 * This software is furnished under license and may be used and 14 * copied only in accordance with the following terms and 15 * conditions. Subject to these conditions, you may download, 16 * copy, install, use, modify and distribute modified or unmodified 17 * copies of this software in source and/or binary form. No title 18 * or ownership is transferred hereby. 19 * 20 * 1) Any source code used, modified or distributed must reproduce 21 * and retain this copyright notice and list of conditions 22 * as they appear in the source file. 23 * 24 * 2) No right is granted to use any trade name, trademark, or 25 * logo of Broadcom Corporation. The "Broadcom Corporation" 26 * name may not be used to endorse or promote products derived 27 * from this software without the prior written permission of 28 * Broadcom Corporation. 29 * 30 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 32 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 33 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 34 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 35 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 36 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 40 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 41 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 42 * THE POSSIBILITY OF SUCH DAMAGE. 43 ********************************************************************* */ 44 45/* 46 * MPC824x machine-specific functions for PCI autoconfiguration. 47 */ 48 49#include "lib_types.h" 50#include "lib_printf.h" 51#include "lib_string.h" 52#include "cfe_timer.h" 53 54#include "bsp_config.h" 55 56#include "endian.h" 57#include "addrspace.h" 58 59#include "ppcdefs.h" 60#include "mpc824x.h" 61 62#include "pcivar.h" 63#include "pci_internal.h" 64#include "pcireg.h" 65 66#if ((ENDIAN_BIG + ENDIAN_LITTLE) != 1) 67#error "mpc824x_pci_machdep: system endian not set" 68#endif 69 70extern int _pciverbose; 71 72const cons_t pci_optnames[] = { 73 {"verbose", PCI_FLG_VERBOSE}, 74 {NULL, 0} 75}; 76 77/* Templates for bus attributes. */ 78 79static const struct pci_bus init_pci_bus = { 80 0, /* minimum grant */ 81 255, /* maximum latency */ 82 0, /* devsel time = unknown */ 83 0, /* configure fast back-to-back */ 84 0, /* we don't prefetch */ 85 0, /* configure 66 MHz */ 86 0, /* we don't support 64 bits */ 87 4000000, /* bandwidth: in 0.25us cycles / sec */ 88 0, /* initially no devices on bus */ 89}; 90 91#define MAXBUS 10 92static struct pci_bus _pci_bus[MAXBUS]; 93static int _pci_nbus = 0; 94 95#define PCI_MAKE_TAG(b,d,f) \ 96 (((b) << 16) | ((d) << 11) | ((f) << 8)) 97 98 99/* PCI spaces as seen by the CPU in Host mode (Table 3-1). */ 100 101/* Core regions allocated for mapping to PCI address spaces. */ 102#define MPC824X_PCI_MEM_SPACE 0x80000000 103#define MPC824X_PCI_MEM_SPACE_SIZE 0x7D000000 104#define MPC824X_PCI_IO_SPACE 0xFE800000 105#define MPC824X_PCI_IO_SPACE_SIZE 0x00400000 106 107/* PCI regions mapped from the core addresses. */ 108#define MPC824X_PCI_MEM_BASE 0x80000000 109#define MPC824X_PCI_IO_BASE 0x00800000 110 111/* Window on configuration registers */ 112#define MPC824X_CONFIG_ADDR 0xFEC00000 113#define MPC824X_CONFIG_DATA 0xFEE00000 114 115#define MPC824X_PCI_ENABLE 0x80000000 116 117 118/* The following should return the index of the last usable bus port. */ 119int 120pci_maxport (void) 121{ 122 return PCI_HOST_PORTS - 1; 123} 124 125 126/* The following must either fail or return the next sequential bus 127 number to make secondary/subordinate numbering work correctly. */ 128int 129pci_nextbus (int port) 130{ 131 int bus = _pci_nbus; 132 133 if (bus >= MAXBUS) 134 return -1; 135 _pci_nbus++; 136 return bus; 137} 138 139int 140pci_maxbus (int port) 141{ 142 return _pci_nbus - 1; 143} 144 145struct pci_bus * 146pci_businfo (int port, int bus) 147{ 148 return (bus < _pci_nbus ? &_pci_bus[bus] : NULL); 149} 150 151/* 152 * PCI address resources. 153 * NB: initial limits for address allocation are assumed to be aligned 154 * appropriately for PCI bridges (4K boundaries for I/O, 1M for memory). 155 */ 156 157pcireg_t 158pci_minmemaddr (int port) 159{ 160 return MPC824X_PCI_MEM_BASE; 161} 162 163pcireg_t 164pci_maxmemaddr (int port) 165{ 166 return MPC824X_PCI_MEM_BASE + MPC824X_PCI_MEM_SPACE_SIZE; 167} 168 169pcireg_t 170pci_minioaddr (int port) 171{ 172 return MPC824X_PCI_IO_BASE; 173} 174 175pcireg_t 176pci_maxioaddr (int port) 177{ 178 return MPC824X_PCI_IO_BASE + MPC824X_PCI_IO_SPACE_SIZE; 179} 180 181 182/* The PCI core (a host bridge in Host mode) */ 183 184#define PPC_PCI_BRIDGE (PCI_MAKE_TAG(0,0,0)) 185 186/* Called to initialise the host bridge at the beginning of time. */ 187static void 188phb_init (void) 189{ 190 pcireg_t csr; 191 192 /* stop the servicing of any further PCI */ 193 pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, 0); 194 cfe_usleep(100); 195 196 /* XXX set up PMCR2, arbiter, PICR1 */ 197 198 /* enable bridge to PCI and PCI memory accesses, including 199 write-invalidate, plus error handling */ 200 csr = PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE | 201 PCI_COMMAND_INVALIDATE_ENABLE | 202 PCI_COMMAND_SERR_ENABLE | PCI_COMMAND_PARITY_ENABLE; 203 pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr); 204 205 /* clear errors */ 206 csr = pci_conf_read(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG); 207 csr |= PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | 208 PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | 209 PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT; 210 pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr); 211 212 (void)pci_conf_read(PPC_PCI_BRIDGE, PCI_ID_REG); /* push */ 213} 214 215 216int 217pci_hwinit (int port, pci_flags_t flags) 218{ 219 int i; 220 221 /* Enable the internal arbiter. PARK_LAST apparently locks the bus 222 when there is no response. */ 223 /* XXX TBD, currently done in cpu init. */ 224 225 memcpy(&_pci_bus[_pci_nbus], &init_pci_bus, sizeof(struct pci_bus)); 226 _pci_bus[_pci_nbus].port = port; 227 _pci_nbus++; 228 for (i = _pci_nbus; i < MAXBUS; i++) 229 memcpy(&_pci_bus[i], &init_pci_bus, sizeof(struct pci_bus)); 230 231 cfe_sleep(CFE_HZ/2); /* let devices initialize */ 232 233 phb_init(); 234 return 0; 235} 236 237/* Called to update the host bridge after we've scanned each PCI 238 device and know what is possible. */ 239void 240pci_hwreinit (int port, pci_flags_t flags) 241{ 242} 243 244 245/* The following functions provide for device-specific setup required 246 during configuration. There is nothing host-specific about them, 247 and it would be better to do the packaging and registration in a 248 more modular way. */ 249 250/* Dispatch functions for device pre- and post-configuration hooks. */ 251 252/* Called for each hostbridge, to discover and scan secondary buses */ 253void 254pci_businit_hostbridge (pcitag_t tag, pci_flags_t flags) 255{ 256} 257 258/* Called for each function prior to assigning PCI resources. */ 259int 260pci_device_preset (pcitag_t tag) 261{ 262 /* Check for a host bridge seen internally, in which case 263 we don't want to allocate any address space for its BARs. */ 264 265 return (tag == PPC_PCI_BRIDGE ? 1 : 0); 266} 267 268 269/* Called for each non-bridge (Type 0) function after assigning the 270 BAR and InterruptLine resources. */ 271void 272pci_device_setup (pcitag_t tag) 273{ 274} 275 276/* Called for each bridge (Type 1) function after configuring the 277 secondary bus, to allow device-specific initialization. */ 278void 279pci_bridge_setup (pcitag_t tag, pci_flags_t flags) 280{ 281} 282 283 284/* Machine dependent access primitives and utility functions */ 285 286void 287pci_flush (void) 288{ 289} 290 291 292pcitag_t 293pci_make_tag (int port, int bus, int device, int function) 294{ 295 return PCI_MAKE_TAG(bus, device, function); 296} 297 298void 299pci_break_tag (pcitag_t tag, 300 int *portp, int *busp, int *devicep, int *functionp) 301{ 302 if (portp) *portp = 0; 303 if (busp) *busp = (tag >> 16) & PCI_BUSMAX; 304 if (devicep) *devicep = (tag >> 11) & PCI_DEVMAX; 305 if (functionp) *functionp = (tag >> 8) & PCI_FUNCMAX; 306} 307 308 309/* Read/write access to PCI configuration registers. Type0 addresses 310 are used for bus 0, with a unary encoding of IDSEL in which device 311 n is mapped to AD bit n except that device 10 is mapped to bit 31 312 (21 possible possible devices, 10..30). The host bridge itself 313 is mapped internally to bus 0, device 0. */ 314 315int 316pci_canscan (pcitag_t tag) 317{ 318 int bus, device, function; 319 320 pci_break_tag(tag, NULL, &bus, &device, &function); 321 if (bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX) 322 return 0; 323 324 return 1; 325} 326 327int 328pci_probe_tag(pcitag_t tag) 329{ 330 pcireg_t data; 331 332 if (!pci_canscan(tag)) 333 return 0; 334 335 data = pci_conf_read(tag, PCI_ID_REG); /* bus error if no response */ 336 337 /* if it returned all vendor id bits set, it's not a device */ 338 return (PCI_VENDOR(data) != 0xffff); 339} 340 341 342pcireg_t 343pci_conf_read(pcitag_t tag, int reg) 344{ 345 pcireg_t data; 346 uint32_t cfg; 347 uint32_t addr = MPC824X_PCI_ENABLE | tag | reg; 348 349#if ENDIAN_BIG 350 __asm __volatile ("\ 351 addis %0,0,0xfec0 \t\n \ 352 stwbrx %2,0,%0 \t\n \ 353 sync \t\n \ 354 addis %0,0,0xfee0 \t\n \ 355 lwbrx %1,0,%0 \t\n \ 356 sync " : 357 "=r&" (cfg), "=r" (data) : "r" (addr)); 358#else 359 __asm __volatile ("\ 360 addis %0,0,0xfec0 \n\t \ 361 stw %2,0(%0) \n\t \ 362 sync \n\t \ 363 addis %0,0,0xfee0 \n\t \ 364 lw %1,0(%0) \n\t \ 365 sync " : 366 "=&r" (cfg), "=r" (data) : "r" (addr)); 367#endif 368 369 return data; 370} 371 372void 373pci_conf_write(pcitag_t tag, int reg, pcireg_t data) 374{ 375 uint32_t addr = MPC824X_PCI_ENABLE | tag | reg; 376 uint32_t cfg; 377 378#if ENDIAN_BIG 379 __asm __volatile ("\ 380 addis %0,0,0xfec0 \t\n \ 381 stwbrx %2,0,%0 \t\n \ 382 sync \t\n \ 383 addis %0,0,0xfee0 \t\n \ 384 stwbrx %1,0,%0 \t\n \ 385 sync " : 386 "=&r" (cfg) : "r" (data), "r" (addr)); 387#else 388 __asm __volatile ("\ 389 addis %0,0,0xfec0 \n\t \ 390 stw %2,0(%0) \n\t \ 391 sync \n\t \ 392 addis %0,0,0xfee0 \n\t \ 393 stw %1,0(%0) \n\t \ 394 sync " : 395 "=&r" (cfg) : "r" (data), "r" (addr)); 396#endif 397} 398 399int 400pci_conf_write_acked(pcitag_t tag, int reg, pcireg_t data) 401{ 402 pci_conf_write(tag, reg, data); 403 (void) pci_conf_read(tag, reg); 404 return 1; 405} 406 407 408int 409pci_map_io(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap) 410{ 411 pcireg_t address; 412 phys_addr_t pa; 413 414#if ENDIAN_BIG 415 if (endian == PCI_MATCH_BITS) { 416 if (_pciverbose != 0) 417 pci_tagprintf(tag, "pci_map_io: attempt to use MATCH BITS mode\n"); 418 return -1; 419 } 420#endif 421 422 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { 423 if (_pciverbose != 0) 424 pci_tagprintf(tag, "pci_map_io: bad request\n"); 425 return -1; 426 } 427 428 address = pci_conf_read(tag, reg); 429 430 if ((address & PCI_MAPREG_TYPE_IO) == 0) { 431 if (_pciverbose != 0) 432 pci_tagprintf(tag, "pci_map_io: attempt to i/o map a memory region\n"); 433 return -1; 434 } 435 436 pa = ((address & PCI_MAPREG_IO_ADDR_MASK) - MPC824X_PCI_IO_BASE) 437 + MPC824X_PCI_IO_SPACE; 438 *pap = pa; 439 return 0; 440} 441 442int 443pci_map_mem(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap) 444{ 445 pcireg_t address; 446 phys_addr_t pa; 447 448#if ENDIAN_BIG 449 if (endian == PCI_MATCH_BITS) { 450 if (_pciverbose != 0) 451 pci_tagprintf(tag, "pci_map_mem: attempt to use MATCH BITS mode\n"); 452 return -1; 453 } 454#endif 455 456 if (reg == PCI_MAPREG_ROM) { 457 /* expansion ROM */ 458 address = pci_conf_read(tag, reg); 459 if ((address & PCI_MAPREG_ROM_ENABLE) == 0) { 460 pci_tagprintf(tag, "pci_map_mem: attempt to map missing rom\n"); 461 return -1; 462 } 463 pa = address & PCI_MAPREG_ROM_ADDR_MASK; 464 } 465 else { 466 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { 467 if (_pciverbose != 0) 468 pci_tagprintf(tag, "pci_map_mem: bad request\n"); 469 return -1; 470 } 471 472 address = pci_conf_read(tag, reg); 473 474 if ((address & PCI_MAPREG_TYPE_IO) != 0) { 475 if (_pciverbose != 0) 476 pci_tagprintf(tag, "pci_map_mem: attempt to memory map an I/O region\n"); 477 return -1; 478 } 479 480 pa = address & PCI_MAPREG_MEM_ADDR_MASK; 481 482 switch (address & PCI_MAPREG_MEM_TYPE_MASK) { 483 case PCI_MAPREG_MEM_TYPE_32BIT: 484 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 485 break; 486 case PCI_MAPREG_MEM_TYPE_64BIT: 487 if (reg + 4 < PCI_MAPREG_END) 488#if 0 /* XXX check for all zeros at reg+4 */ 489 pa |= ((phys_addr_t)pci_conf_read(tag, reg+4) << 32); 490#else 491 ; 492#endif 493 else { 494 if (_pciverbose != 0) 495 pci_tagprintf(tag, "pci_map_mem: bad 64-bit reguest\n"); 496 return -1; 497 } 498 break; 499 default: 500 if (_pciverbose != 0) 501 pci_tagprintf(tag, "pci_map_mem: reserved mapping type\n"); 502 return -1; 503 } 504 } 505 506 pa = (pa - MPC824X_PCI_MEM_BASE) + MPC824X_PCI_MEM_SPACE; 507 *pap = pa; 508 return 0; 509} 510 511 512/* ISA-style i/o access (not supported) */ 513 514uint8_t 515inb (unsigned int port) 516{ 517 xprintf("inb: i/o regions not supported\n"); 518 return 0xFF; 519} 520 521uint16_t 522inw (unsigned int port) 523{ 524 xprintf("inw: i/o regions not supported\n"); 525 return 0xFFFF; 526} 527 528uint32_t 529inl (unsigned int port) 530{ 531 xprintf("inl: i/o regions not supported\n"); 532 return 0xFFFFFFFF; 533} 534 535void 536outb (unsigned int port, uint8_t val) 537{ 538 xprintf("outb: i/o regions not supported\n"); 539} 540 541void 542outw (unsigned int port, uint16_t val) 543{ 544 xprintf("outw: i/o regions not supported\n"); 545} 546 547void 548outl (unsigned int port, uint32_t val) 549{ 550 xprintf("outl: i/o regions not supported\n"); 551} 552 553 554/* Map PCI interrupts A, B, C, D into the index in the IRQ vector, or 555 0xff if none. This makes assumptions about both the CPLD and the 556 programming of the EPIC. */ 557uint8_t 558pci_int_line(uint8_t pci_int) 559{ 560 return pci_int; 561} 562