u-boot/arch/x86/lib/pirq_routing.c
Tom Rini 83d290c56f SPDX: Convert all of our single license tags to Linux Kernel style
When U-Boot started using SPDX tags we were among the early adopters and
there weren't a lot of other examples to borrow from.  So we picked the
area of the file that usually had a full license text and replaced it
with an appropriate SPDX-License-Identifier: entry.  Since then, the
Linux Kernel has adopted SPDX tags and they place it as the very first
line in a file (except where shebangs are used, then it's second line)
and with slightly different comment styles than us.

In part due to community overlap, in part due to better tag visibility
and in part for other minor reasons, switch over to that style.

This commit changes all instances where we have a single declared
license in the tag as both the before and after are identical in tag
contents.  There's also a few places where I found we did not have a tag
and have introduced one.

Signed-off-by: Tom Rini <trini@konsulko.com>
2018-05-07 09:34:12 -04:00

133 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Part of this file is ported from coreboot src/arch/x86/boot/pirq_routing.c
*/
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/pirq_routing.h>
static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap,
bool irq_already_routed[])
{
int i, link;
u8 irq = 0;
/* IRQ sharing starts from IRQ#3 */
for (i = 3; i < 16; i++) {
/* Can we assign this IRQ? */
if (!((bitmap >> i) & 1))
continue;
/* We can, now let's assume we can use this IRQ */
irq = i;
/* Have we already routed it? */
if (irq_already_routed[irq])
continue;
for (link = 0; link < CONFIG_MAX_PIRQ_LINKS; link++) {
if (pirq_check_irq_routed(dev, link, irq)) {
irq_already_routed[irq] = true;
break;
}
}
/* If it's not yet routed, use it */
if (!irq_already_routed[irq]) {
irq_already_routed[irq] = true;
break;
}
/* But if it was already routed, try the next one */
}
/* Now we get our IRQ */
return irq;
}
void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num)
{
unsigned char irq_slot[MAX_INTX_ENTRIES];
unsigned char pirq[CONFIG_MAX_PIRQ_LINKS];
bool irq_already_routed[16];
int i, intx;
memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS);
memset(irq_already_routed, '\0', sizeof(irq_already_routed));
/* Set PCI IRQs */
for (i = 0; i < num; i++) {
debug("PIRQ Entry %d Dev: %d.%x.%d\n", i,
irq->bus, irq->devfn >> 3, irq->devfn & 7);
for (intx = 0; intx < MAX_INTX_ENTRIES; intx++) {
int link = irq->irq[intx].link;
int bitmap = irq->irq[intx].bitmap;
int irq = 0;
debug("INT%c link: %x bitmap: %x ",
'A' + intx, link, bitmap);
if (!bitmap || !link) {
debug("not routed\n");
irq_slot[intx] = irq;
continue;
}
/* translate link value to link number */
link = pirq_translate_link(dev, link);
/* yet not routed */
if (!pirq[link]) {
irq = pirq_get_next_free_irq(dev, pirq, bitmap,
irq_already_routed);
pirq[link] = irq;
} else {
irq = pirq[link];
}
debug("IRQ: %d\n", irq);
irq_slot[intx] = irq;
/* Assign IRQ in the interrupt router */
pirq_assign_irq(dev, link, irq);
}
/* Bus, device, slots IRQs for {A,B,C,D} */
pci_assign_irqs(irq->bus, irq->devfn >> 3, irq_slot);
irq++;
}
for (i = 0; i < CONFIG_MAX_PIRQ_LINKS; i++)
debug("PIRQ%c: %d\n", 'A' + i, pirq[i]);
}
u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt)
{
struct irq_routing_table *rom_rt;
/* Align the table to be 16 byte aligned */
addr = ALIGN(addr, 16);
debug("Copying Interrupt Routing Table to 0x%x\n", addr);
memcpy((void *)(uintptr_t)addr, rt, rt->size);
/*
* We do the sanity check here against the copied table after memcpy,
* as something might go wrong after the memcpy, which is normally
* due to the F segment decode is not turned on to systeam RAM.
*/
rom_rt = (struct irq_routing_table *)(uintptr_t)addr;
if (rom_rt->signature != PIRQ_SIGNATURE ||
rom_rt->version != PIRQ_VERSION || rom_rt->size % 16) {
printf("Interrupt Routing Table not valid\n");
return addr;
}
return addr + rt->size;
}