diff options
author | Felix Held <felix.held@amd.corp-partner.google.com> | 2020-04-04 05:27:05 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2020-06-21 01:17:31 +0000 |
commit | e6315f74d6f402734e476a57a8faf4ac9cb23d38 (patch) | |
tree | 21ef786a292ad9ec95bbbb196d9234588d6ffa97 /src/mainboard/amd/mandolin/mainboard.c | |
parent | 12b0f7746e6ce8c3eeb677e093b756aeb8ede493 (diff) | |
download | coreboot-e6315f74d6f402734e476a57a8faf4ac9cb23d38.tar.xz |
mb/amd/mandolin: Add Picasso CRB
Mandolin is the CRB for AMD Picasso and Dali.
The mainboard code still needs a little cleanup and verification, but
I'll do that in a follow-up to have a non Chromebook board using the
Picasso SoC code in tree as soon as possible to be able to detect some
possible breakage.
BUG=b:130660285
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: I2b4a78e1eef9f998e1986da1506201eb505822eb
Reviewed-on: https://review.coreboot.org/c/coreboot/+/33772
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/mainboard/amd/mandolin/mainboard.c')
-rw-r--r-- | src/mainboard/amd/mandolin/mainboard.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/mainboard/amd/mandolin/mainboard.c b/src/mainboard/amd/mandolin/mainboard.c new file mode 100644 index 0000000000..2e66c65832 --- /dev/null +++ b/src/mainboard/amd/mandolin/mainboard.c @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <device/device.h> +#include <acpi/acpi.h> +#include <amdblocks/amd_pci_util.h> +#include <FspsUpd.h> +#include <soc/cpu.h> +#include <soc/southbridge.h> +#include <soc/pci_devs.h> +#include <soc/platform_descriptors.h> +#include <soc/soc_util.h> +#include <types.h> +#include <commonlib/helpers.h> +#include <chip.h> +#include "gpio.h" + +/* TODO: recheck IRQ tables */ + +/* + * 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[0x80]; +static uint8_t fch_apic_routing[0x80]; + +_Static_assert(sizeof(fch_pic_routing) == sizeof(fch_apic_routing), + "PIC and APIC FCH interrupt tables must be the same size"); + +/* + * This table doesn't actually perform any routing. It only populates the + * PCI_INTERRUPT_LINE register on the PCI device with the PIC value specified + * in fch_apic_routing. The linux kernel only looks at this field as a backup + * if ACPI routing fails to describe the PCI routing correctly. The linux kernel + * also uses the APIC by default, so the value coded into the registers will be + * wrong. + * + * This table is also confusing because PCI Interrupt routing happens at the + * device/slot level, not the function level. + */ +static const struct pirq_struct mainboard_pirq_data[] = { + { PCIE_GPP_0_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_1_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_2_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_3_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_4_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_5_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_6_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_A_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { PCIE_GPP_B_DEVFN, { PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D } }, + { SMBUS_DEVFN, { PIRQ_SMBUS, PIRQ_NC, PIRQ_NC, PIRQ_NC } }, +}; + +static const struct fch_irq_routing { + uint8_t intr_index; + uint8_t pic_irq_num; + uint8_t apic_irq_num; +} mandolin_fch[] = { + { PIRQ_A, 8, 16 }, + { PIRQ_B, 10, 17 }, + { PIRQ_C, 11, 18 }, + { PIRQ_D, 12, 19 }, + { PIRQ_SCI, 9, 9 }, + { PIRQ_SD, PIRQ_NC, 16 }, + { PIRQ_SDIO, PIRQ_NC, 16 }, + { PIRQ_SATA, PIRQ_NC, 19 }, + { PIRQ_EMMC, PIRQ_NC, 17 }, + { PIRQ_GPIO, 7, 7 }, + { PIRQ_I2C2, 6, 6 }, + { PIRQ_I2C3, 14, 14 }, + { PIRQ_UART0, 4, 4 }, + { PIRQ_UART1, 3, 3 }, + { PIRQ_UART2, 4, 4 }, + { PIRQ_UART3, 3, 3 }, + + /* The MISC registers are not interrupt numbers */ + { PIRQ_MISC, 0xfa, 0x00 }, + { PIRQ_MISC0, 0x91, 0x00 }, + { PIRQ_MISC1, 0x00, 0x00 }, + { PIRQ_MISC2, 0x00, 0x00 }, +}; + +static void init_tables(void) +{ + const struct fch_irq_routing *entry; + int i; + + memset(fch_pic_routing, PIRQ_NC, sizeof(fch_pic_routing)); + memset(fch_apic_routing, PIRQ_NC, sizeof(fch_apic_routing)); + + for (i = 0; i < ARRAY_SIZE(mandolin_fch); i++) { + entry = mandolin_fch + i; + fch_pic_routing[entry->intr_index] = entry->pic_irq_num; + fch_apic_routing[entry->intr_index] = entry->apic_irq_num; + } +} + +static void pirq_setup(void) +{ + init_tables(); + + pirq_data_ptr = mainboard_pirq_data; + pirq_data_size = ARRAY_SIZE(mainboard_pirq_data); + intr_data_ptr = fch_apic_routing; + picr_data_ptr = fch_pic_routing; +} + +static void mainboard_init(void *chip_info) +{ + struct soc_amd_picasso_config *cfg = config_of_soc(); + + if (!CONFIG(PICASSO_LPC_IOMUX)) + cfg->sd_emmc_config = SD_EMMC_EMMC_HS400; + + mainboard_program_gpios(); +} + +static const fsp_pcie_descriptor pco_pcie_descriptors[] = { + { /* MXM */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 8, + .end_lane = 15, + .device_number = 1, + .function_number = 1, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ6 + }, + { /* SSD */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 0, + .end_lane = 1, + .device_number = 1, + .function_number = 7, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ5 + }, + { /* WLAN */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 4, + .end_lane = 4, + .device_number = 1, + .function_number = 2, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ0 + }, + { /* LAN */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 5, + .end_lane = 5, + .device_number = 1, + .function_number = 3, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ1 + }, + { /* WWAN */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 2, + .end_lane = 2, + .device_number = 1, + .function_number = 4, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ2 + }, + { /* WIFI */ + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 3, + .end_lane = 3, + .gpio_group_id = 1, + .device_number = 1, + .function_number = 5, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ3 + }, + { /* SATA EXPRESS */ + .port_present = true, + .engine_type = SATA_ENGINE, + .start_lane = 6, + .end_lane = 7, + .gpio_group_id = 1, + .channel_type = SATA_CHANNEL_LONG, + } +}; + +static const fsp_pcie_descriptor dali_pcie_descriptors[] = { + { // MXM + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 8, + .end_lane = 11, + .device_number = 1, + .function_number = 1, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ6 + }, + { // SSD + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 0, + .end_lane = 1, + .device_number = 1, + .function_number = 7, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ5 + }, + { // WLAN + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 4, + .end_lane = 4, + .device_number = 1, + .function_number = 2, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ0 + }, + { // LAN + .port_present = true, + .engine_type = PCIE_ENGINE, + .start_lane = 5, + .end_lane = 5, + .device_number = 1, + .function_number = 3, + .link_aspm = ASPM_L1, + .link_aspm_L1_1 = true, + .link_aspm_L1_2 = true, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ1 + } +}; + +static const fsp_ddi_descriptor pco_ddi_descriptors[] = { + { // DDI0 - DP + .connector_type = DP, + .aux_index = AUX1, + .hdp_index = HDP1 + }, + { /* DDI1 - eDP */ + .connector_type = EDP, + .aux_index = AUX2, + .hdp_index = HDP2 + }, + { /* DDI2 - DP */ + .connector_type = DP, + .aux_index = AUX3, + .hdp_index = HDP3, + }, + { /* DDI3 - DP */ + .connector_type = DP, + .aux_index = AUX4, + .hdp_index = HDP4, + } +}; + +static const fsp_ddi_descriptor dali_ddi_descriptors[] = { + { // DDI0 - DP + .connector_type = DP, + .aux_index = AUX1, + .hdp_index = HDP1 + }, + { // DDI1 - eDP + .connector_type = EDP, + .aux_index = AUX2, + .hdp_index = HDP2 + }, + { // DDI2 - DP + .connector_type = DP, + .aux_index = AUX3, + .hdp_index = HDP3, + } +}; + +void mainboard_get_pcie_ddi_descriptors( + const fsp_pcie_descriptor **pcie_descs, size_t *pcie_num, + const fsp_ddi_descriptor **ddi_descs, size_t *ddi_num) +{ + /* Dali */ + if (soc_is_dali()) { + *pcie_descs = dali_pcie_descriptors; + *pcie_num = ARRAY_SIZE(dali_pcie_descriptors); + *ddi_descs = dali_ddi_descriptors; + *ddi_num = ARRAY_SIZE(dali_ddi_descriptors); + } + /* Picasso and default */ + else { + *pcie_descs = pco_pcie_descriptors; + *pcie_num = ARRAY_SIZE(pco_pcie_descriptors); + *ddi_descs = pco_ddi_descriptors; + *ddi_num = ARRAY_SIZE(pco_ddi_descriptors); + } +} + +static void mandolin_enable(struct device *dev) +{ + printk(BIOS_INFO, "Mainboard " CONFIG_MAINBOARD_PART_NUMBER " Enable.\n"); + + /* Initialize the PIRQ data structures for consumption */ + pirq_setup(); +} + +struct chip_operations mainboard_ops = { + .init = mainboard_init, + .enable_dev = mandolin_enable, +}; |