diff options
Diffstat (limited to 'src/soc/amd')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/amd_pci_util.h | 4 | ||||
-rw-r--r-- | src/soc/amd/common/block/pci/amd_pci_util.c | 49 |
2 files changed, 43 insertions, 10 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h b/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h index c766d501bd..f862bf997d 100644 --- a/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h +++ b/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h @@ -19,6 +19,8 @@ struct fch_irq_routing { uint8_t apic_irq_num; }; +const struct fch_irq_routing *mb_get_fch_irq_mapping(size_t *length); + struct pirq_struct { u8 devfn; u8 PIN[4]; /* PINA/B/C/D are index 0/1/2/3 */ @@ -31,8 +33,6 @@ struct irq_idx_name { extern const struct pirq_struct *pirq_data_ptr; extern u32 pirq_data_size; -extern const u8 *intr_data_ptr; -extern const u8 *picr_data_ptr; u8 read_pci_int_idx(u8 index, int mode); void write_pci_int_idx(u8 index, int mode, u8 data); diff --git a/src/soc/amd/common/block/pci/amd_pci_util.c b/src/soc/amd/common/block/pci/amd_pci_util.c index d665a81bc2..ecc0498ef0 100644 --- a/src/soc/amd/common/block/pci/amd_pci_util.c +++ b/src/soc/amd/common/block/pci/amd_pci_util.c @@ -7,11 +7,21 @@ #include <amdblocks/amd_pci_util.h> #include <pc80/i8259.h> #include <soc/amd_pci_int_defs.h> +#include <string.h> + +/* + * These arrays set up the FCH PCI_INTR registers 0xC00/0xC01. + * This table is responsible for physically routing the PIC and + * IOAPIC IRQs to the different PCI devices on the system. It + * is read and written via registers 0xC00/0xC01 as an + * Index/Data pair. These values are chipset and mainboard + * dependent and should be updated accordingly. + */ +static uint8_t fch_pic_routing[FCH_IRQ_ROUTING_ENTRIES]; +static uint8_t fch_apic_routing[FCH_IRQ_ROUTING_ENTRIES]; const struct pirq_struct *pirq_data_ptr; u32 pirq_data_size; -const u8 *intr_data_ptr; -const u8 *picr_data_ptr; /* * Read the FCH PCI_INTR registers 0xC00/0xC01 at a @@ -33,6 +43,29 @@ void write_pci_int_idx(u8 index, int mode, u8 data) outb(data, PCI_INTR_DATA); } +static void init_fch_irq_map_tables(void) +{ + const struct fch_irq_routing *mb_irq_map; + size_t mb_fch_irq_mapping_table_size; + size_t i; + + mb_irq_map = mb_get_fch_irq_mapping(&mb_fch_irq_mapping_table_size); + + memset(fch_pic_routing, PIRQ_NC, sizeof(fch_pic_routing)); + memset(fch_apic_routing, PIRQ_NC, sizeof(fch_apic_routing)); + + for (i = 0; i < mb_fch_irq_mapping_table_size; i++) { + if (mb_irq_map[i].intr_index >= FCH_IRQ_ROUTING_ENTRIES) { + printk(BIOS_WARNING, + "Invalid IRQ index %u in FCH IRQ routing table entry %zu\n", + mb_irq_map[i].intr_index, i); + continue; + } + fch_pic_routing[mb_irq_map[i].intr_index] = mb_irq_map[i].pic_irq_num; + fch_apic_routing[mb_irq_map[i].intr_index] = mb_irq_map[i].apic_irq_num; + } +} + /* * Write the FCH PCI_INTR registers 0xC00/0xC01 with values * given in global variables intr_data and picr_data. @@ -44,13 +77,13 @@ void write_pci_int_table(void) size_t i, limit; const struct irq_idx_name *idx_name; + init_fch_irq_map_tables(); + idx_name = sb_get_apic_reg_association(&limit); - if (picr_data_ptr == NULL || intr_data_ptr == NULL || - idx_name == NULL) { + if (idx_name == NULL) { printk(BIOS_ERR, "Warning: Can't write PCI_INTR 0xC00/0xC01" " registers because\n" - "'mainboard_picr_data' or 'mainboard_intr_data'" - " or 'irq_association'\ntables are NULL\n"); + " 'irq_association'\ntables is NULL\n"); return; } @@ -67,11 +100,11 @@ void write_pci_int_table(void) */ for (i = 0 ; i < limit; i++) { byte = idx_name[i].index; - write_pci_int_idx(byte, 0, (u8)picr_data_ptr[byte]); + write_pci_int_idx(byte, 0, fch_pic_routing[byte]); printk(BIOS_DEBUG, "0x%02X\t\t%-20s 0x%02X\t", byte, idx_name[i].name, read_pci_int_idx(byte, 0)); - write_pci_int_idx(byte, 1, (u8)intr_data_ptr[byte]); + write_pci_int_idx(byte, 1, fch_apic_routing[byte]); printk(BIOS_DEBUG, "0x%02X\n", read_pci_int_idx(byte, 1)); } } |