On x86 boards, platform chipset receives up to four different
interrupt signals from PCI devices (INTA/B/C/D), which in turn
will be routed to chipset internal PIRQ lines then routed to
8259 PIC finally if configuring the whole system to work under
the so-called PIC mode (in contrast to symmetric IO mode which
uses IOAPIC).
We add two major APIs to aid this, one for routing PIRQ and the
other one for generating a PIRQ routing table.
Signed-off-by: Bin Meng bmeng...@gmail.com
Acked-by: Simon Glass s...@chromium.org
---
Changes in v2: None
arch/x86/Kconfig| 31
arch/x86/include/asm/pirq_routing.h | 139
arch/x86/lib/Makefile | 1 +
arch/x86/lib/pirq_routing.c | 129 +
4 files changed, 300 insertions(+)
create mode 100644 arch/x86/include/asm/pirq_routing.h
create mode 100644 arch/x86/lib/pirq_routing.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3f1401a..aaceaef 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -442,6 +442,37 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
+menu System tables
+
+config GENERATE_PIRQ_TABLE
+ bool Generate a PIRQ table
+ default n
+ help
+ Generate a PIRQ routing table for this board. The PIRQ routing table
+ is generated by U-Boot in the system memory from 0xf to 0xf
+ at every 16-byte boundary with a PCI IRQ routing signature ($PIR).
+ It specifies the interrupt router information as well how all the PCI
+ devices' interrupt pins are wired to PIRQs.
+
+endmenu
+
+config MAX_PIRQ_LINKS
+ int
+ default 8
+ help
+ This variable specifies the number of PIRQ interrupt links which are
+ routable. On most older chipsets, this is 4, PIRQA through PIRQD.
+ Some newer chipsets offer more than four links, commonly up to PIRQH.
+
+config IRQ_SLOT_COUNT
+ int
+ default 128
+ help
+ U-Boot can support up to 254 IRQ slot info in the PIRQ routing table
+ which in turns forms a table of exact 4KiB. The default value 128
+ should be enough for most boards. If this does not fit your board,
+ change it according to your needs.
+
source board/coreboot/coreboot/Kconfig
source board/google/chromebook_link/Kconfig
diff --git a/arch/x86/include/asm/pirq_routing.h
b/arch/x86/include/asm/pirq_routing.h
new file mode 100644
index 000..ddc08e1
--- /dev/null
+++ b/arch/x86/include/asm/pirq_routing.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015, Bin Meng bmeng...@gmail.com
+ *
+ * Ported from coreboot src/arch/x86/include/arch/pirq_routing.h
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+#ifndef _PIRQ_ROUTING_H_
+#define _PIRQ_ROUTING_H_
+
+/*
+ * This is the maximum number on interrupt entries that a PCI device may have.
+ * This is NOT the number of slots or devices in the system
+ * This is NOT the number of entries in the PIRQ table
+ *
+ * This tells us that in the PIRQ table, we are going to have 4 link-bitmap
+ * entries per PCI device which is fixed at 4: INTA, INTB, INTC, and INTD.
+ *
+ * CAUTION: If you change this, PIRQ routing will not work correctly.
+ */
+#define MAX_INTX_ENTRIES 4
+
+#define PIRQ_SIGNATURE \
+ (('$' 0) + ('P' 8) + ('I' 16) + ('R' 24))
+#define PIRQ_VERSION 0x0100
+
+struct __packed irq_info {
+ u8 bus; /* Bus number */
+ u8 devfn; /* Device and function number */
+ struct __packed {
+ u8 link;/* IRQ line ID, 0=not routed */
+ u16 bitmap; /* Available IRQs */
+ } irq[MAX_INTX_ENTRIES];
+ u8 slot;/* Slot number, 0=onboard */
+ u8 rfu;
+};
+
+struct __packed irq_routing_table {
+ u32 signature; /* PIRQ_SIGNATURE */
+ u16 version;/* PIRQ_VERSION */
+ u16 size; /* Table size in bytes */
+ u8 rtr_bus; /* busno of the interrupt router */
+ u8 rtr_devfn; /* devfn of the interrupt router */
+ u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
+ u16 rtr_vendor; /* Vendor ID of the interrupt router */
+ u16 rtr_device; /* Device ID of the interrupt router */
+ u32 miniport_data;
+ u8 rfu[11];
+ u8 checksum;/* Modulo 256 checksum must give zero */
+ struct irq_info slots[CONFIG_IRQ_SLOT_COUNT];
+};
+
+/**
+ * get_irq_slot_count() - Get the number of entries in the irq_info table
+ *
+ * This calculates the number of entries for the irq_info table.
+ *
+ * @rt:pointer to the base address of the struct irq_info
+ * @return:number of entries
+ */
+static inline int get_irq_slot_count(struct irq_routing_table *rt)
+{
+ return (rt-size - 32) / sizeof(struct