amd/stoneyridge: Create new name/IRQ association

Table intr_types[] is hard to maintain, and has unused spaces filled with
NULL. A new table format is needed that creates strong association between
the APIC register index and the associated IRQ name, is easy to maintain
and has no unused space (index) to indicate that a particular register is
unused while still indicating which registers are valid.

Also, the string that defines the name of associated IRQ should be declared
with "#define" in a header, but must be physically initiated in a source
file. The "#define" must make a strong association between the used register
index and the associated IRQ name. Example:
#define INDEX_0X16_NAME "PerMon\t"

BUG=b:69868534
TEST=Check serial output against BKDG for AMD Family 15h Models 70h-7Fh
Processors definitions for Pci_Intr_Index. Also, check for new output
format to confirm write_pci_int_table() is working as desired. There's
no test for write_pci_cfg_irqs, as it's not being used by kahlee.

Change-Id: I2dde4d016cc3228e50dcfadd2d3586a3609e608d
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/22667
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Richard Spiegel 2017-12-01 08:24:26 -07:00 committed by Martin Roth
parent 8fdbd114ec
commit 376dc82dca
4 changed files with 119 additions and 51 deletions

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2014 Sage Electronic Engineering, LLC. * Copyright (C) 2014 Sage Electronic Engineering, LLC.
* Copyright (C) 2017 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +21,6 @@
#include <amd_pci_util.h> #include <amd_pci_util.h>
#include <pc80/i8259.h> #include <pc80/i8259.h>
#include <soc/amd_pci_int_defs.h> #include <soc/amd_pci_int_defs.h>
#include <amd_pci_int_types.h>
const struct pirq_struct *pirq_data_ptr; const struct pirq_struct *pirq_data_ptr;
u32 pirq_data_size; u32 pirq_data_size;
@ -54,40 +54,38 @@ void write_pci_int_idx(u8 index, int mode, u8 data)
*/ */
void write_pci_int_table(void) void write_pci_int_table(void)
{ {
u8 byte; uint8_t byte;
size_t i, limit;
const struct irq_idx_name *idx_name;
if (picr_data_ptr == NULL || intr_data_ptr == NULL) { idx_name = sb_get_apic_reg_association(&limit);
if (picr_data_ptr == NULL || idx_name == NULL) {
printk(BIOS_ERR, "Warning: Can't write PCI_INTR 0xC00/0xC01" printk(BIOS_ERR, "Warning: Can't write PCI_INTR 0xC00/0xC01"
" registers because\n" " registers because\n"
"'mainboard_picr_data' or 'mainboard_intr_data'" "'mainboard_picr_data' or"
" tables are NULL\n"); " irq_association' tables are NULL\n");
return; return;
} }
/* PIC IRQ routine */ /* PIC IRQ routine */
printk(BIOS_DEBUG, "PCI_INTR tables: Writing registers C00/C01 for PIC" printk(BIOS_DEBUG, "PCI_INTR tables: Writing registers C00/C01 for"
" mode PCI IRQ routing:\n" " PCI IRQ routing:\n"
"\tPCI_INTR_INDEX\t\tPCI_INTR_DATA\n"); "\tPCI_INTR_INDEX\t\tPIC mode"
for (byte = 0 ; byte < FCH_INT_TABLE_SIZE ; byte++) { "\tAPIC mode\n");
if (intr_types[byte]) { /*
* Iterate table idx_name, indexes outside the table are ignored
* (assumed not connected within the chip). For each iteration,
* get the register index "byte" and the name of the associated
* IRQ source for printing.
*/
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, (u8) picr_data_ptr[byte]);
printk(BIOS_DEBUG, "\t0x%02X %s\t: 0x%02X\n", printk(BIOS_DEBUG, "\t0x%02X %s\t0x%02X\t\t",
byte, intr_types[byte], byte, idx_name[i].name,
read_pci_int_idx(byte, 0)); read_pci_int_idx(byte, 0));
}
}
/* APIC IRQ routine */
printk(BIOS_DEBUG, "PCI_INTR tables: Writing registers C00/C01 for APIC"
" mode PCI IRQ routing:\n"
"\tPCI_INTR_INDEX\t\tPCI_INTR_DATA\n");
for (byte = 0 ; byte < FCH_INT_TABLE_SIZE ; byte++) {
if (intr_types[byte]) {
write_pci_int_idx(byte, 1, (u8) intr_data_ptr[byte]); write_pci_int_idx(byte, 1, (u8) intr_data_ptr[byte]);
printk(BIOS_DEBUG, "\t0x%02X %s\t: 0x%02X\n", printk(BIOS_DEBUG, "0x%02X\n", read_pci_int_idx(byte, 1));
byte, intr_types[byte],
read_pci_int_idx(byte, 1));
}
} }
} }
@ -108,7 +106,10 @@ void write_pci_cfg_irqs(void)
u16 devfn = 0; /* A PCI Device and Function number */ u16 devfn = 0; /* A PCI Device and Function number */
u8 bridged_device = 0; /* This device is on a PCI bridge */ u8 bridged_device = 0; /* This device is on a PCI bridge */
u32 i = 0; u32 i = 0;
size_t limit;
const struct irq_idx_name *idx_name;
idx_name = sb_get_apic_reg_association(&limit);
if (pirq_data_ptr == NULL) { if (pirq_data_ptr == NULL) {
printk(BIOS_WARNING, "Warning: Can't write PCI IRQ assignments" printk(BIOS_WARNING, "Warning: Can't write PCI IRQ assignments"
" because 'mainboard_pirq_data' structure does" " because 'mainboard_pirq_data' structure does"
@ -172,11 +173,20 @@ void write_pci_cfg_irqs(void)
" perhaps this device was" " perhaps this device was"
" defined wrong?\n"); " defined wrong?\n");
continue; continue;
} else if (pci_intr_idx >= FCH_INT_TABLE_SIZE) { }
/* Index out of bounds */ /*
printk(BIOS_ERR, "%s: got 0xC00/0xC01 table index" * Find the name associated with register [pci_intr_idx]
" 0x%x, max is 0x%x\n", __func__, * and print information.
pci_intr_idx, FCH_INT_TABLE_SIZE); */
for (i = 0; i < limit; i++) {
if (idx_name[i].index == pci_intr_idx)
break;
}
if (i == limit) {
printk(BIOS_SPEW, "Got register index 0x%02x"
" undefined in table irq_idx_name,\n"
" perhaps this device was"
" defined wrong?\n", pci_intr_idx);
continue; continue;
} }
@ -208,9 +218,10 @@ void write_pci_cfg_irqs(void)
if (bridged_device) if (bridged_device)
printk(BIOS_SPEW, "\tSwizzled to\t: %d (%s)\n", printk(BIOS_SPEW, "\tSwizzled to\t: %d (%s)\n",
target_pin, pin_to_str(target_pin)); target_pin, pin_to_str(target_pin));
printk(BIOS_SPEW, "\tPCI_INTR idx\t: 0x%02x (%s)\n" printk(BIOS_SPEW, "\tPCI_INTR idx\t: 0x%02x (%s)\n"
"\tINT_LINE\t: 0x%X (IRQ %d)\n", "\tINT_LINE\t: 0x%X (IRQ %d)\n",
pci_intr_idx, intr_types[pci_intr_idx], pci_intr_idx, idx_name[i].name,
int_line, int_line); int_line, int_line);
} /* for (dev = all_devices) */ } /* for (dev = all_devices) */
printk(BIOS_DEBUG, "PCI_CFG IRQ: Finished writing PCI config space" printk(BIOS_DEBUG, "PCI_CFG IRQ: Finished writing PCI config space"

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2014 Sage Electronic Engineering, LLC. * Copyright (C) 2014 Sage Electronic Engineering, LLC.
* Copyright (C) 2017 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,6 +18,7 @@
#define __AMD_PCI_UTIL_H__ #define __AMD_PCI_UTIL_H__
#include <stdint.h> #include <stdint.h>
#include <soc/amd_pci_int_defs.h>
/* FCH index/data registers */ /* FCH index/data registers */
#define PCI_INTR_INDEX 0xc00 #define PCI_INTR_INDEX 0xc00
@ -27,6 +29,11 @@ struct pirq_struct {
u8 PIN[4]; /* PINA/B/C/D are index 0/1/2/3 */ u8 PIN[4]; /* PINA/B/C/D are index 0/1/2/3 */
}; };
struct irq_idx_name {
uint8_t index;
const char * const name;
};
extern const struct pirq_struct *pirq_data_ptr; extern const struct pirq_struct *pirq_data_ptr;
extern u32 pirq_data_size; extern u32 pirq_data_size;
extern const u8 *intr_data_ptr; extern const u8 *intr_data_ptr;
@ -36,5 +43,6 @@ u8 read_pci_int_idx(u8 index, int mode);
void write_pci_int_idx(u8 index, int mode, u8 data); void write_pci_int_idx(u8 index, int mode, u8 data);
void write_pci_cfg_irqs(void); void write_pci_cfg_irqs(void);
void write_pci_int_table(void); void write_pci_int_table(void);
const struct irq_idx_name *sb_get_apic_reg_association(size_t *size);
#endif /* __AMD_PCI_UTIL_H__ */ #endif /* __AMD_PCI_UTIL_H__ */

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2014 Sage Electronic Engineering, LLC. * Copyright (C) 2014 Sage Electronic Engineering, LLC.
* Copyright (C) 2017 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,9 +18,8 @@
#define __AMD_PCI_INT_DEFS_H__ #define __AMD_PCI_INT_DEFS_H__
/* /*
* PIRQ and device routing - these define the index * PIRQ and device routing - these define the index into the
* into the FCH PCI_INTR 0xC00/0xC01 interrupt * FCH PCI_INTR 0xC00/0xC01 interrupt routing table.
* routing table
*/ */
#define PIRQ_NC 0x1f /* Not Used */ #define PIRQ_NC 0x1f /* Not Used */
@ -44,26 +44,18 @@
#define PIRQ_ASF 0x12 /* ASF */ #define PIRQ_ASF 0x12 /* ASF */
#define PIRQ_HDA 0x13 /* HDA 14h.2 */ #define PIRQ_HDA 0x13 /* HDA 14h.2 */
#define PIRQ_FC 0x14 /* FC */ #define PIRQ_FC 0x14 /* FC */
#define PIRQ_GEC 0x15 /* GEC */
#define PIRQ_PMON 0x16 /* Performance Monitor */ #define PIRQ_PMON 0x16 /* Performance Monitor */
#define PIRQ_SD 0x17 /* SD */ #define PIRQ_SD 0x17 /* SD */
#define PIRQ_SDIO 0x1a /* SDIO */
#define PIRQ_IMC0 0x20 /* IMC INT0 */ #define PIRQ_IMC0 0x20 /* IMC INT0 */
#define PIRQ_IMC1 0x21 /* IMC INT1 */ #define PIRQ_IMC1 0x21 /* IMC INT1 */
#define PIRQ_IMC2 0x22 /* IMC INT2 */ #define PIRQ_IMC2 0x22 /* IMC INT2 */
#define PIRQ_IMC3 0x23 /* IMC INT3 */ #define PIRQ_IMC3 0x23 /* IMC INT3 */
#define PIRQ_IMC4 0x24 /* IMC INT4 */ #define PIRQ_IMC4 0x24 /* IMC INT4 */
#define PIRQ_IMC5 0x25 /* IMC INT5 */ #define PIRQ_IMC5 0x25 /* IMC INT5 */
#define PIRQ_OHCI1 0x30 /* USB OHCI 12h.0 */ #define PIRQ_EHCI 0x30 /* USB EHCI 12h.0 */
#define PIRQ_EHCI1 0x31 /* USB EHCI 12h.2 */ #define PIRQ_XHCI 0x34 /* USB XHCI 10h.0 */
#define PIRQ_OHCI2 0x32 /* USB OHCI 13h.0 */
#define PIRQ_EHCI2 0x33 /* USB EHCI 13h.2 */
#define PIRQ_OHCI3 0x34 /* USB OHCI 16h.0 */
#define PIRQ_EHCI3 0x35 /* USB EHCI 16h.2 */
#define PIRQ_OHCI4 0x36 /* USB OHCI 14h.5 */
#define PIRQ_IDE 0x40 /* IDE 14h.1 */
#define PIRQ_SATA 0x41 /* SATA 11h.0 */ #define PIRQ_SATA 0x41 /* SATA 11h.0 */
#define FCH_INT_TABLE_SIZE 0x76
#define PIRQ_GPIO 0x62 /* GPIO Controller Interrupt */ #define PIRQ_GPIO 0x62 /* GPIO Controller Interrupt */
#define PIRQ_I2C0 0x70 #define PIRQ_I2C0 0x70
#define PIRQ_I2C1 0x71 #define PIRQ_I2C1 0x71

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2010 Advanced Micro Devices, Inc. * Copyright (C) 2010-2017 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -27,10 +27,67 @@
#include <amd_pci_util.h> #include <amd_pci_util.h>
#include <soc/southbridge.h> #include <soc/southbridge.h>
#include <soc/smi.h> #include <soc/smi.h>
#include <soc/amd_pci_int_defs.h>
#include <fchec.h> #include <fchec.h>
#include <delay.h> #include <delay.h>
#include <soc/pci_devs.h> #include <soc/pci_devs.h>
/*
* Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
* provides a visible association with the index, therefor helping
* maintainability of table. If a new index/name is defined in
* amd_pci_int_defs.h, just add the pair at the end of this table.
* Order is not important.
*/
const static struct irq_idx_name irq_association[] = {
{ PIRQ_A, "INTA#\t" },
{ PIRQ_B, "INTB#\t" },
{ PIRQ_C, "INTC#\t" },
{ PIRQ_D, "INTD#\t" },
{ PIRQ_E, "INTE#\t" },
{ PIRQ_F, "INTF#\t" },
{ PIRQ_G, "INTG#\t" },
{ PIRQ_H, "INTH#\t" },
{ PIRQ_MISC, "Misc\t" },
{ PIRQ_MISC0, "Misc0\t" },
{ PIRQ_MISC1, "Misc1\t" },
{ PIRQ_MISC2, "Misc2\t" },
{ PIRQ_SIRQA, "Ser IRQ INTA" },
{ PIRQ_SIRQB, "Ser IRQ INTB" },
{ PIRQ_SIRQC, "Ser IRQ INTC" },
{ PIRQ_SIRQD, "Ser IRQ INTD" },
{ PIRQ_SCI, "SCI\t" },
{ PIRQ_SMBUS, "SMBUS\t" },
{ PIRQ_ASF, "ASF\t" },
{ PIRQ_HDA, "HDA\t" },
{ PIRQ_FC, "FC\t\t" },
{ PIRQ_PMON, "PerMon\t" },
{ PIRQ_SD, "SD\t\t" },
{ PIRQ_SDIO, "SDIO\t" },
{ PIRQ_IMC0, "IMC INT0\t" },
{ PIRQ_IMC1, "IMC INT1\t" },
{ PIRQ_IMC2, "IMC INT2\t" },
{ PIRQ_IMC3, "IMC INT3\t" },
{ PIRQ_IMC4, "IMC INT4\t" },
{ PIRQ_IMC5, "IMC INT5\t" },
{ PIRQ_EHCI, "EHCI\t" },
{ PIRQ_XHCI, "XHCI\t" },
{ PIRQ_SATA, "SATA\t" },
{ PIRQ_GPIO, "GPIO\t" },
{ PIRQ_I2C0, "I2C0\t" },
{ PIRQ_I2C1, "I2C1\t" },
{ PIRQ_I2C2, "I2C2\t" },
{ PIRQ_I2C3, "I2C3\t" },
{ PIRQ_UART0, "UART0\t" },
{ PIRQ_UART1, "UART1\t" },
};
const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
{
*size = ARRAY_SIZE(irq_association);
return irq_association;
}
void configure_stoneyridge_uart(void) void configure_stoneyridge_uart(void)
{ {
u8 byte, byte2; u8 byte, byte2;