PCI IRQs: Swizzle PCI IRQs for PCI bridges

The PCI Specification states that devices that implement
a bridge and a secondary bus must swizzle (rotate) the
interrupt pins according to the table below:
	Child Dev #     Child PIN       Parent PIN
	0,4,8,12...     A/B/C/D         A/B/C/D
	1,5,9,13...     A/B/C/D         B/C/D/A
	2,6,10,14..     A/B/C/D         C/D/A/B
	3,7,11,15..     A/B/C/D         D/A/B/C

Which is also described by this equation:
	PIN_parent = (Pin_child + Dev_child) % 4

When a device is found and its bus number is greater than 0,
it is on a bridge and needs to be swizzled.  Following the
string of parents up to the root bus and swizzling as we go
gives us the desired swizzling result.  When BIOS_SPEW is
defined, it will print out each step of the swizzling process.

Change-Id: Icafeadd01983282c86e25f560c831c9482c74e68
Signed-off-by: Martin Roth <gaumless@gmail.com>
Reviewed-on: http://review.coreboot.org/5734
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marc.jones@se-eng.com>
Reviewed-by: Mike Loptien <mike.loptien@se-eng.com>
This commit is contained in:
Mike Loptien
2014-05-12 21:46:31 -06:00
committed by Martin Roth
parent 433659ad1e
commit 0f5cf5e45b
2 changed files with 153 additions and 0 deletions

View File

@ -82,6 +82,8 @@ void pci_dev_set_subsystem(device_t dev, unsigned vendor, unsigned device);
void pci_dev_init(struct device *dev);
unsigned int pci_match_simple_dev(device_t dev, pci_devfn_t sdev);
const char * pin_to_str(int pin);
int get_pci_irq_pins(device_t dev, device_t *parent_bdg);
void pci_assign_irqs(unsigned bus, unsigned slot,
const unsigned char pIntAtoD[4]);