File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <rtems.h>
0021 #include <bsp.h>
0022
0023 #include <libcpu/io.h>
0024 #include <bsp/pci.h>
0025 #include <rtems/bspIo.h>
0026
0027 #undef SHOW_PCI_SETTING
0028
0029
0030 #ifndef PCI_CONFIG_ADDR
0031 #define PCI_CONFIG_ADDR 0xcf8
0032 #endif
0033 #ifndef PCI_CONFIG_DATA
0034 #define PCI_CONFIG_DATA 0xcfc
0035 #endif
0036
0037
0038 #define pci BSP_pci_configuration
0039
0040 #ifndef PCI_CONFIG_ADDR_VAL
0041 #define PCI_CONFIG_ADDR_VAL(bus, slot, funcion, offset) \
0042 (0x80<<24|((bus)<<16)|(PCI_DEVFN((slot),(function))<<8)|(((offset)&~3)))
0043 #endif
0044
0045 #ifndef PCI_CONFIG_WR_ADDR
0046 #define PCI_CONFIG_WR_ADDR( addr, val ) out_le32((volatile uint32_t*)(addr), (val))
0047 #endif
0048
0049 #define PCI_CONFIG_SET_ADDR(addr, bus, slot,function,offset) \
0050 PCI_CONFIG_WR_ADDR((addr), PCI_CONFIG_ADDR_VAL((bus), (slot), (function), (offset)))
0051
0052
0053 extern void detect_host_bridge(void);
0054
0055
0056
0057
0058 unsigned char ucMaxPCIBus;
0059
0060 static int
0061 indirect_pci_read_config_byte(
0062 unsigned char bus,
0063 unsigned char slot,
0064 unsigned char function,
0065 unsigned char offset,
0066 uint8_t *val
0067 ) {
0068 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0069 *val = in_8(pci.pci_config_data + (offset&3));
0070 return PCIBIOS_SUCCESSFUL;
0071 }
0072
0073 static int
0074 indirect_pci_read_config_word(
0075 unsigned char bus,
0076 unsigned char slot,
0077 unsigned char function,
0078 unsigned char offset,
0079 uint16_t *val
0080 ) {
0081 *val = 0xffff;
0082 if (offset&1)
0083 return PCIBIOS_BAD_REGISTER_NUMBER;
0084
0085 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0086 *val = in_le16((volatile uint16_t *)(pci.pci_config_data + (offset&3)));
0087 return PCIBIOS_SUCCESSFUL;
0088 }
0089
0090 static int
0091 indirect_pci_read_config_dword(
0092 unsigned char bus,
0093 unsigned char slot,
0094 unsigned char function,
0095 unsigned char offset,
0096 uint32_t *val
0097 ) {
0098 *val = 0xffffffff;
0099 if (offset&3)
0100 return PCIBIOS_BAD_REGISTER_NUMBER;
0101
0102 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0103 *val = in_le32((volatile uint32_t *)pci.pci_config_data);
0104 return PCIBIOS_SUCCESSFUL;
0105 }
0106
0107 static int
0108 indirect_pci_write_config_byte(
0109 unsigned char bus,
0110 unsigned char slot,
0111 unsigned char function,
0112 unsigned char offset,
0113 uint8_t val
0114 ) {
0115 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0116 out_8(pci.pci_config_data + (offset&3), val);
0117 return PCIBIOS_SUCCESSFUL;
0118 }
0119
0120 static int
0121 indirect_pci_write_config_word(
0122 unsigned char bus,
0123 unsigned char slot,
0124 unsigned char function,
0125 unsigned char offset,
0126 uint16_t val
0127 ) {
0128 if (offset&1)
0129 return PCIBIOS_BAD_REGISTER_NUMBER;
0130
0131 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0132 out_le16((volatile uint16_t *)(pci.pci_config_data + (offset&3)), val);
0133 return PCIBIOS_SUCCESSFUL;
0134 }
0135
0136 static int
0137 indirect_pci_write_config_dword(
0138 unsigned char bus,
0139 unsigned char slot,
0140 unsigned char function,
0141 unsigned char offset,
0142 uint32_t val
0143 ) {
0144 if (offset&3)
0145 return PCIBIOS_BAD_REGISTER_NUMBER;
0146 PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset);
0147 out_le32((volatile uint32_t *)pci.pci_config_data, val);
0148 return PCIBIOS_SUCCESSFUL;
0149 }
0150
0151 const pci_config_access_functions pci_indirect_functions = {
0152 indirect_pci_read_config_byte,
0153 indirect_pci_read_config_word,
0154 indirect_pci_read_config_dword,
0155 indirect_pci_write_config_byte,
0156 indirect_pci_write_config_word,
0157 indirect_pci_write_config_dword
0158 };
0159
0160 rtems_pci_config_t BSP_pci_configuration = {
0161 (volatile unsigned char*)PCI_CONFIG_ADDR,
0162 (volatile unsigned char*)PCI_CONFIG_DATA,
0163 &pci_indirect_functions
0164 };
0165
0166 static int
0167 direct_pci_read_config_byte(
0168 unsigned char bus,
0169 unsigned char slot,
0170 unsigned char function,
0171 unsigned char offset,
0172 uint8_t *val
0173 ) {
0174 if (bus != 0 || (1<<slot & 0xff8007fe)) {
0175 *val=0xff;
0176 return PCIBIOS_DEVICE_NOT_FOUND;
0177 }
0178 *val=in_8(pci.pci_config_data + ((1<<slot)&~1)
0179 + (function<<8) + offset);
0180 return PCIBIOS_SUCCESSFUL;
0181 }
0182
0183 static int
0184 direct_pci_read_config_word(
0185 unsigned char bus,
0186 unsigned char slot,
0187 unsigned char function,
0188 unsigned char offset,
0189 uint16_t *val
0190 ) {
0191 *val = 0xffff;
0192 if (offset&1)
0193 return PCIBIOS_BAD_REGISTER_NUMBER;
0194 if (bus != 0 || (1<<slot & 0xff8007fe))
0195 return PCIBIOS_DEVICE_NOT_FOUND;
0196
0197 *val=in_le16((volatile uint16_t *)
0198 (pci.pci_config_data + ((1<<slot)&~1)
0199 + (function<<8) + offset));
0200 return PCIBIOS_SUCCESSFUL;
0201 }
0202
0203 static int
0204 direct_pci_read_config_dword(
0205 unsigned char bus,
0206 unsigned char slot,
0207 unsigned char function,
0208 unsigned char offset,
0209 uint32_t *val
0210 ) {
0211 *val = 0xffffffff;
0212 if (offset&3)
0213 return PCIBIOS_BAD_REGISTER_NUMBER;
0214 if (bus != 0 || (1<<slot & 0xff8007fe))
0215 return PCIBIOS_DEVICE_NOT_FOUND;
0216
0217 *val=in_le32((volatile uint32_t *)
0218 (pci.pci_config_data + ((1<<slot)&~1)
0219 + (function<<8) + offset));
0220 return PCIBIOS_SUCCESSFUL;
0221 }
0222
0223 static int
0224 direct_pci_write_config_byte(
0225 unsigned char bus,
0226 unsigned char slot,
0227 unsigned char function,
0228 unsigned char offset,
0229 uint8_t val
0230 ) {
0231 if (bus != 0 || (1<<slot & 0xff8007fe))
0232 return PCIBIOS_DEVICE_NOT_FOUND;
0233
0234 out_8(pci.pci_config_data + ((1<<slot)&~1)
0235 + (function<<8) + offset,
0236 val);
0237 return PCIBIOS_SUCCESSFUL;
0238 }
0239
0240 static int
0241 direct_pci_write_config_word(
0242 unsigned char bus,
0243 unsigned char slot,
0244 unsigned char function,
0245 unsigned char offset,
0246 uint16_t val
0247 ) {
0248 if (offset&1)
0249 return PCIBIOS_BAD_REGISTER_NUMBER;
0250 if (bus != 0 || (1<<slot & 0xff8007fe))
0251 return PCIBIOS_DEVICE_NOT_FOUND;
0252
0253 out_le16((volatile uint16_t *)
0254 (pci.pci_config_data + ((1<<slot)&~1)
0255 + (function<<8) + offset),
0256 val);
0257 return PCIBIOS_SUCCESSFUL;
0258 }
0259
0260 static int
0261 direct_pci_write_config_dword(
0262 unsigned char bus,
0263 unsigned char slot,
0264 unsigned char function,
0265 unsigned char offset,
0266 uint32_t val
0267 ) {
0268 if (offset&3)
0269 return PCIBIOS_BAD_REGISTER_NUMBER;
0270 if (bus != 0 || (1<<slot & 0xff8007fe))
0271 return PCIBIOS_DEVICE_NOT_FOUND;
0272
0273 out_le32((volatile uint32_t *)
0274 (pci.pci_config_data + ((1<<slot)&~1)
0275 + (function<<8) + offset),
0276 val);
0277 return PCIBIOS_SUCCESSFUL;
0278 }
0279
0280 const pci_config_access_functions pci_direct_functions = {
0281 direct_pci_read_config_byte,
0282 direct_pci_read_config_word,
0283 direct_pci_read_config_dword,
0284 direct_pci_write_config_byte,
0285 direct_pci_write_config_word,
0286 direct_pci_write_config_dword
0287 };
0288
0289 #define PRINT_MSG() \
0290 printk("pci : Device %d:0x%02x:%d routed to interrupt_line %d\n", \
0291 pbus, pslot, pfun, int_name )
0292
0293
0294
0295
0296
0297 static int test_intname(
0298 const struct _int_map *row,
0299 int pbus,
0300 int pslot,
0301 int pfun,
0302 int int_pin,
0303 int int_name
0304 ) {
0305 int j, k;
0306 int _nopin= -1, _noname= -1;
0307
0308 for (j=0; row->pin_route[j].pin > -1; j++) {
0309 if ( row->pin_route[j].pin == int_pin ) {
0310 _nopin = 0;
0311
0312 for (k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) {
0313 if ( row->pin_route[j].int_name[k] == int_name ) {
0314 _noname=0; break;
0315 }
0316 }
0317 break;
0318 }
0319 }
0320
0321 if( _nopin )
0322 {
0323 printk("pci : Device %d:0x%02x:%d supplied a bogus interrupt_pin %d\n", pbus, pslot, pfun, int_pin );
0324 return -1;
0325 }
0326 else
0327 {
0328 if( _noname ) {
0329 unsigned char v = row->pin_route[j].int_name[0];
0330 printk("pci : Device %d:0x%02x:%d supplied a suspicious interrupt_line %d, ", pbus, pslot, pfun, int_name );
0331 if ( (row->opts & PCI_FIXUP_OPT_OVERRIDE_NAME) && 255 != (v = row->pin_route[j].int_name[0]) ) {
0332 printk("OVERRIDING with %d from fixup table\n", v);
0333 pci_write_config_byte(pbus,pslot,pfun,PCI_INTERRUPT_LINE,v);
0334 } else {
0335 printk("using it anyway\n");
0336 }
0337 }
0338 }
0339 return 0;
0340 }
0341
0342 struct pcibridge
0343 {
0344 int bus;
0345 int slot;
0346 };
0347
0348 static int FindPCIbridge( int mybus, struct pcibridge *pb )
0349 {
0350 int pbus, pslot;
0351 uint8_t bussec, buspri;
0352 uint16_t devid, vendorid, dclass;
0353
0354 for(pbus=0; pbus< pci_bus_count(); pbus++) {
0355 for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
0356 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
0357 if ( devid == 0xffff ) continue;
0358
0359 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid);
0360 if ( vendorid == 0xffff ) continue;
0361
0362 pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass);
0363
0364 if ( dclass == PCI_CLASS_BRIDGE_PCI ) {
0365 pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS, &buspri);
0366 pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS, &bussec);
0367
0368 #ifdef SHOW_PCI_SETTING
0369 printk("pci : Found bridge at %d:0x%02x, mybus %d, pribus %d, secbus %d ",
0370 pbus, pslot, mybus, buspri, bussec );
0371 #endif
0372 if ( bussec == mybus ) {
0373 #ifdef SHOW_PCI_SETTING
0374 printk("match\n");
0375 #endif
0376
0377 pb->bus = pbus;
0378 pb->slot = pslot;
0379
0380 return 0;
0381 }
0382 #ifdef SHOW_PCI_SETTING
0383 printk("no match\n");
0384 #endif
0385 }
0386
0387 }
0388 }
0389 return -1;
0390 }
0391
0392 void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) )
0393 {
0394 unsigned char cvalue;
0395 uint16_t devid;
0396 int ismatch, i, j, pbus, pslot, pfun, int_pin, int_name, nfuns;
0397
0398
0399
0400
0401
0402
0403
0404 for (pbus=0; pbus< pci_bus_count(); pbus++) {
0405 for (pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
0406 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
0407 if ( devid == 0xffff ) continue;
0408
0409
0410 pci_read_config_byte(pbus, pslot, 0, PCI_HEADER_TYPE, &cvalue);
0411 nfuns = cvalue & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1;
0412
0413 for (pfun=0; pfun< nfuns; pfun++) {
0414 pci_read_config_word(pbus, pslot, pfun, PCI_DEVICE_ID, &devid);
0415 if( devid == 0xffff ) continue;
0416
0417 pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_PIN, &cvalue);
0418 int_pin = cvalue;
0419
0420 pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_LINE, &cvalue);
0421 int_name = cvalue;
0422
0423
0424
0425
0426 #ifdef SHOW_PCI_SETTING
0427 {
0428 unsigned short cmd,stat;
0429 unsigned char lat, seclat, csize;
0430
0431 pci_read_config_word(pbus,pslot,pfun,PCI_COMMAND, &cmd );
0432 pci_read_config_word(pbus,pslot,pfun,PCI_STATUS, &stat );
0433 pci_read_config_byte(pbus,pslot,pfun,PCI_LATENCY_TIMER, &lat );
0434 pci_read_config_byte(pbus,pslot,pfun,PCI_SEC_LATENCY_TIMER, &seclat );
0435 pci_read_config_byte(pbus,pslot,pfun,PCI_CACHE_LINE_SIZE, &csize );
0436
0437
0438 printk("pci : device %d:0x%02x:%d cmd %04X, stat %04X, latency %d, "
0439 " sec_latency %d, clsize %d\n", pbus, pslot, pfun, cmd, stat,
0440 lat, seclat, csize);
0441 }
0442 #endif
0443
0444 if ( int_pin > 0 ) {
0445 ismatch = 0;
0446
0447
0448
0449
0450
0451 for (i=0; bspmap[i].bus > -1; i++) {
0452 if ( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) {
0453 ismatch = -1;
0454
0455
0456 if ( int_name == 255 ) {
0457
0458
0459
0460 for ( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) {
0461 if ( bspmap[i].pin_route[j].pin == int_pin ) {
0462 int_name = bspmap[i].pin_route[j].int_name[0];
0463 break;
0464 }
0465 }
0466 if ( int_name == -1 ) {
0467 printk("pci : Unable to resolve device %d:0x%02x:%d w/ swizzled int "
0468 "pin %i to an interrupt_line.\n", pbus, pslot, pfun, int_pin );
0469 } else {
0470 PRINT_MSG();
0471 pci_write_config_byte( pbus,pslot,pfun,
0472 PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
0473 }
0474 } else {
0475 test_intname( &bspmap[i],pbus,pslot,pfun,int_pin,int_name);
0476 }
0477 break;
0478 }
0479 }
0480
0481 if ( !ismatch ) {
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 int tbus= pbus, tslot= pslot;
0495
0496 for (;;) {
0497 for (i=0; bspmap[i].bus > -1; i++) {
0498 if ( bspmap[i].bus == tbus &&
0499 (bspmap[i].slot == tslot || bspmap[i].slot == -1) ) {
0500 ismatch = -1;
0501
0502
0503
0504
0505
0506 if ( int_name == 255 ) {
0507
0508
0509
0510
0511
0512 if ( tbus ) int_pin = (*swizzler)(tslot,int_pin);
0513
0514
0515
0516
0517
0518
0519 for (int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++){
0520 if ( bspmap[i].pin_route[j].pin == int_pin ) {
0521 int_name = bspmap[i].pin_route[j].int_name[0];
0522 break;
0523 }
0524 }
0525
0526 if ( int_name == -1 ) {
0527 printk("pci : Unable to resolve device %d:0x%02x:%d w/ swizzled "
0528 "int pin %i to an interrupt_line.\n",
0529 pbus, pslot, pfun, int_pin );
0530 } else {
0531 PRINT_MSG();
0532 pci_write_config_byte(pbus,pslot,pfun,
0533 PCI_INTERRUPT_LINE,(cvalue=int_name, cvalue));
0534 }
0535 } else {
0536 test_intname(&bspmap[i],pbus,pslot,pfun,int_pin,int_name);
0537 }
0538 goto donesearch;
0539 }
0540 }
0541
0542 if ( !ismatch ) {
0543 struct pcibridge pb;
0544
0545
0546
0547
0548
0549
0550 if ( FindPCIbridge( tbus, &pb )== 0 ) {
0551 int_pin = (*swizzler)(tslot,int_pin);
0552
0553
0554
0555
0556
0557
0558
0559 tbus = pb.bus;
0560 tslot = pb.slot;
0561 } else {
0562 printk("pci : No bridge from bus %i towards root found\n",
0563 tbus );
0564 goto donesearch;
0565 }
0566 }
0567 }
0568 }
0569 donesearch:
0570
0571 if ( !ismatch && int_pin != 0 && int_name == 255 ) {
0572 printk("pci : Unable to match device %d:0x%02x:%d with an int "
0573 "routing table entry\n", pbus, pslot, pfun );
0574 }
0575 }
0576 }
0577 }
0578 }
0579 }
0580
0581
0582
0583
0584 int pci_initialize(void)
0585 {
0586 unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
0587 unsigned char ucHeader;
0588 unsigned char ucMaxSubordinate;
0589 uint32_t ulClass;
0590 uint32_t ulDeviceID;
0591
0592 detect_host_bridge();
0593
0594
0595
0596
0597 for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
0598 pci_read_config_dword(0, ucSlotNumber, 0, PCI_VENDOR_ID, &ulDeviceID);
0599 if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
0600
0601 continue;
0602 }
0603 pci_read_config_byte(0, ucSlotNumber, 0, PCI_HEADER_TYPE, &ucHeader);
0604 if (ucHeader&PCI_HEADER_TYPE_MULTI_FUNCTION) {
0605 ucNumFuncs=PCI_MAX_FUNCTIONS;
0606 } else {
0607 ucNumFuncs=1;
0608 }
0609 for (ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
0610 pci_read_config_dword(0, ucSlotNumber, ucFnNumber,
0611 PCI_VENDOR_ID, &ulDeviceID);
0612 if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
0613
0614 continue;
0615 }
0616
0617
0618 pci_read_config_dword(0, ucSlotNumber, ucFnNumber,
0619 PCI_CLASS_REVISION, &ulClass);
0620 ulClass >>= 16;
0621 if (ulClass == PCI_CLASS_BRIDGE_PCI) {
0622
0623 pci_read_config_byte(0, ucSlotNumber, ucFnNumber,
0624 PCI_SUBORDINATE_BUS, &ucMaxSubordinate);
0625 if (ucMaxSubordinate>ucMaxPCIBus) {
0626 ucMaxPCIBus=ucMaxSubordinate;
0627 }
0628 }
0629 }
0630 }
0631 return PCIB_ERR_SUCCESS;
0632 }
0633
0634
0635
0636
0637 unsigned char pci_bus_count(void)
0638 {
0639 return (ucMaxPCIBus+1);
0640 }