From 3c963d9e88240eaf4ea6eff8af7590d7c473acd4 Mon Sep 17 00:00:00 2001 From: Martin Roth Date: Thu, 6 Oct 2022 16:29:07 -0600 Subject: [PATCH] mb/amd/birman: Add framework for morgana crb birman birman is the reference board for the morgana SoC. It needs to be updated to match the actual board design as well. Signed-off-by: Martin Roth Change-Id: I4b16854c954949217a76c3d4f04ddc4001f64337 Reviewed-on: https://review.coreboot.org/c/coreboot/+/68196 Reviewed-by: Fred Reitberger Reviewed-by: Marshall Dawson Tested-by: build bot (Jenkins) --- src/mainboard/amd/birman/Kconfig | 108 ++++++++++ src/mainboard/amd/birman/Kconfig.name | 2 + src/mainboard/amd/birman/Makefile.inc | 42 ++++ src/mainboard/amd/birman/board.fmd | 8 + src/mainboard/amd/birman/board_info.txt | 1 + src/mainboard/amd/birman/bootblock.c | 18 ++ src/mainboard/amd/birman/chromeos.c | 21 ++ src/mainboard/amd/birman/chromeos.fmd | 34 +++ src/mainboard/amd/birman/devicetree.cb | 226 ++++++++++++++++++++ src/mainboard/amd/birman/dsdt.asl | 16 ++ src/mainboard/amd/birman/early_gpio.c | 16 ++ src/mainboard/amd/birman/ec.c | 67 ++++++ src/mainboard/amd/birman/ec.h | 8 + src/mainboard/amd/birman/gpio.c | 20 ++ src/mainboard/amd/birman/gpio.h | 9 + src/mainboard/amd/birman/mainboard.c | 106 +++++++++ src/mainboard/amd/birman/port_descriptors.c | 130 +++++++++++ 17 files changed, 832 insertions(+) create mode 100644 src/mainboard/amd/birman/Kconfig create mode 100644 src/mainboard/amd/birman/Kconfig.name create mode 100644 src/mainboard/amd/birman/Makefile.inc create mode 100644 src/mainboard/amd/birman/board.fmd create mode 100644 src/mainboard/amd/birman/board_info.txt create mode 100644 src/mainboard/amd/birman/bootblock.c create mode 100644 src/mainboard/amd/birman/chromeos.c create mode 100644 src/mainboard/amd/birman/chromeos.fmd create mode 100644 src/mainboard/amd/birman/devicetree.cb create mode 100644 src/mainboard/amd/birman/dsdt.asl create mode 100644 src/mainboard/amd/birman/early_gpio.c create mode 100644 src/mainboard/amd/birman/ec.c create mode 100644 src/mainboard/amd/birman/ec.h create mode 100644 src/mainboard/amd/birman/gpio.c create mode 100644 src/mainboard/amd/birman/gpio.h create mode 100644 src/mainboard/amd/birman/mainboard.c create mode 100644 src/mainboard/amd/birman/port_descriptors.c diff --git a/src/mainboard/amd/birman/Kconfig b/src/mainboard/amd/birman/Kconfig new file mode 100644 index 0000000000..46e5e31bd1 --- /dev/null +++ b/src/mainboard/amd/birman/Kconfig @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: GPL-2.0-only + +if BOARD_AMD_BIRMAN + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOARD_ROMSIZE_KB_16384 + select EC_ACPI + select SOC_AMD_MORGANA + select SOC_AMD_COMMON_BLOCK_USE_ESPI + select AMD_SOC_CONSOLE_UART + select MAINBOARD_HAS_CHROMEOS + select PCIEXP_ASPM + select PCIEXP_CLK_PM + select PCIEXP_COMMON_CLOCK + select PCIEXP_L1_SUB_STATE + select SOC_AMD_COMMON_BLOCK_ESPI_RETAIN_PORT80_EN + +config FMDFILE + default "src/mainboard/amd/birman/chromeos.fmd" if CHROMEOS + default "src/mainboard/amd/birman/board.fmd" + +config MAINBOARD_DIR + default "amd/birman" + +config MAINBOARD_PART_NUMBER + default "BIRMAN" + +config AMD_FWM_POSITION_INDEX + int + default 3 if CHROMEOS + help + TODO: might need to be adapted for better placement of files in cbfs + +config BIRMAN_HAVE_MCHP_FW + bool "Have Microchip EC firmware?" + default n + +config BIRMAN_MCHP_SIG_FILE + string "Microchip EC signature file" + depends on BIRMAN_HAVE_MCHP_FW + default "3rdparty/blobs/mainboard/amd/birman/EC_birman_sig.bin" + help + The EC sig blob is the first 4kBytes of the firmware image. + The first 4 bytes form a pointer (with CRC) to where the EC firmware + is located + +config BIRMAN_MCHP_FW_FILE + string "Microchip EC firmware file" + depends on BIRMAN_HAVE_MCHP_FW + default "3rdparty/blobs/mainboard/amd/birman/EC_birman.bin" + help + The EC firmware blob is at the BIRMAN_MCHP_FW_OFFSET offset of the + firmware image. + +config BIRMAN_MCHP_FW_OFFSET + hex + depends on BIRMAN_HAVE_MCHP_FW + default 0xB80000 + help + The EC firmware blob defaults to the 4MByte offset of the firmware + image. If this offset needs to change, a new signature block must be + generated with the updated offset. + +config VBOOT + select VBOOT_NO_BOARD_SUPPORT + select VBOOT_SEPARATE_VERSTAGE + select VBOOT_STARTS_IN_BOOTBLOCK + +config VBOOT_VBNV_OFFSET + hex + default 0x2A + +config RO_REGION_ONLY + string + depends on VBOOT_SLOTS_RW_AB || VBOOT_SLOTS_RW_A + # Add the EFS and EC to the RO region only + # This is a birman-specific override of soc/amd/morgana/Kconfig + default "apu/amdfw apu/ecfw" + +config CHROMEOS + # Use default libpayload config + select LP_DEFCONFIG_OVERRIDE if PAYLOAD_DEPTHCHARGE + # We don't have recovery buttons, so we can't manually enable devmode. + select GBB_FLAG_FORCE_DEV_SWITCH_ON + +if !EM100 # EM100 defaults in soc/amd/common/blocks/spi/Kconfig +config EFS_SPI_READ_MODE + default 3 # Quad IO (1-1-4) + +config EFS_SPI_SPEED + default 0 # 66MHz + +config EFS_SPI_MICRON_FLAG + default 0 + +config NORMAL_READ_SPI_SPEED + default 1 # 33MHz + +config ALT_SPI_SPEED + default 1 # 33MHz + +config TPM_SPI_SPEED + default 1 # 33MHz + +endif # !EM100 + +endif # BOARD_AMD_BIRMAN diff --git a/src/mainboard/amd/birman/Kconfig.name b/src/mainboard/amd/birman/Kconfig.name new file mode 100644 index 0000000000..14c117a29d --- /dev/null +++ b/src/mainboard/amd/birman/Kconfig.name @@ -0,0 +1,2 @@ +config BOARD_AMD_BIRMAN + bool "Birman" diff --git a/src/mainboard/amd/birman/Makefile.inc b/src/mainboard/amd/birman/Makefile.inc new file mode 100644 index 0000000000..b0466e7b04 --- /dev/null +++ b/src/mainboard/amd/birman/Makefile.inc @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only + +bootblock-y += bootblock.c +bootblock-y += early_gpio.c +bootblock-y += ec.c + +romstage-y += port_descriptors.c + +ramstage-y += chromeos.c +ramstage-y += gpio.c + +ifneq ($(wildcard $(MAINBOARD_BLOBS_DIR)/APCB_Updatable.bin),) +APCB_SOURCES = $(MAINBOARD_BLOBS_DIR)/APCB_Updatable.bin +APCB_SOURCES_RECOVERY = $(MAINBOARD_BLOBS_DIR)/APCB_DefaultRecovery.bin +else +$(info APCB sources not found. Skipping APCB. The resulting image won't boot.) +endif + +ifeq ($(CONFIG_BIRMAN_HAVE_MCHP_FW),y) +$(call add_intermediate, add_mchp_fw) + $(CBFSTOOL) $(obj)/coreboot.pre write -r EC -f $(CONFIG_BIRMAN_MCHP_SIG_FILE) --fill-upward + +# calculate the absolute position from the config offset +BIRMAN_EC_POSITION=$(call int-add, \ + $(call int-subtract, 0xffffffff \ + $(CONFIG_ROM_SIZE)) $(CONFIG_BIRMAN_MCHP_FW_OFFSET) 1) + +cbfs-files-y += apu/ecfw +apu/ecfw-file := $(CONFIG_BIRMAN_MCHP_FW_FILE) +apu/ecfw-position := $(BIRMAN_EC_POSITION) +apu/ecfw-type := raw + +else +files_added:: warn_no_mchp +endif # CONFIG_BIRMAN_HAVE_MCHP_FW + +PHONY+=warn_no_mchp +warn_no_mchp: + printf "\n\t** WARNING **\n" + printf "coreboot has been built without the EC FW.\n" + printf "Do not flash this image. Your Birman's power button\n" + printf "will not respond when you press it.\n\n" diff --git a/src/mainboard/amd/birman/board.fmd b/src/mainboard/amd/birman/board.fmd new file mode 100644 index 0000000000..6c6ad92a28 --- /dev/null +++ b/src/mainboard/amd/birman/board.fmd @@ -0,0 +1,8 @@ +FLASH@0xFF000000 16M { + BIOS { + EC 4K + RW_MRC_CACHE 120K + FMAP 4K + COREBOOT(CBFS) + } +} diff --git a/src/mainboard/amd/birman/board_info.txt b/src/mainboard/amd/birman/board_info.txt new file mode 100644 index 0000000000..b351b8e696 --- /dev/null +++ b/src/mainboard/amd/birman/board_info.txt @@ -0,0 +1 @@ +Category: eval diff --git a/src/mainboard/amd/birman/bootblock.c b/src/mainboard/amd/birman/bootblock.c new file mode 100644 index 0000000000..a6e525dcd4 --- /dev/null +++ b/src/mainboard/amd/birman/bootblock.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include "ec.h" +#include "gpio.h" + +void bootblock_mainboard_early_init(void) +{ + mainboard_program_early_gpios(); + + espi_switch_to_spi1_pads(); +} + +void bootblock_mainboard_init(void) +{ + birman_ec_init(); +} diff --git a/src/mainboard/amd/birman/chromeos.c b/src/mainboard/amd/birman/chromeos.c new file mode 100644 index 0000000000..515da94df1 --- /dev/null +++ b/src/mainboard/amd/birman/chromeos.c @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio chromeos_gpios[] = {}; + lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios)); +} + +int get_write_protect_state(void) +{ + /* Birman doesn't have a write protect pin */ + return 0; +} + +DECLARE_NO_CROS_GPIOS(); diff --git a/src/mainboard/amd/birman/chromeos.fmd b/src/mainboard/amd/birman/chromeos.fmd new file mode 100644 index 0000000000..c28070ad11 --- /dev/null +++ b/src/mainboard/amd/birman/chromeos.fmd @@ -0,0 +1,34 @@ +FLASH@0xFF000000 16M { + SI_BIOS { + EC 4K + RW_MRC_CACHE(PRESERVE) 120K + RW_SECTION_A 4M { + VBLOCK_A 8K + FW_MAIN_A(CBFS) + RW_FWID_A 256 + } + RW_SECTION_B 4M { + VBLOCK_B 8K + FW_MAIN_B(CBFS) + RW_FWID_B 256 + } + RW_ELOG(PRESERVE) 4K + RW_SHARED 16K { + SHARED_DATA 8K + VBLOCK_DEV 8K + } + RW_VPD(PRESERVE) 8K + RW_NVRAM(PRESERVE) 20K + SMMSTORE(PRESERVE) 64K + RW_LEGACY(CBFS) + WP_RO@10M 6M { + RO_VPD(PRESERVE) 16K + RO_SECTION { + FMAP 2K + RO_FRID 64 + GBB@4K 448K + COREBOOT(CBFS) + } + } + } +} diff --git a/src/mainboard/amd/birman/devicetree.cb b/src/mainboard/amd/birman/devicetree.cb new file mode 100644 index 0000000000..8b5728f9e2 --- /dev/null +++ b/src/mainboard/amd/birman/devicetree.cb @@ -0,0 +1,226 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# TODO: Update for birman + +chip soc/amd/morgana + register "common_config.espi_config" = "{ + .std_io_decode_bitmap = ESPI_DECODE_IO_0x80_EN | ESPI_DECODE_IO_0X2E_0X2F_EN | ESPI_DECODE_IO_0X60_0X64_EN, + .generic_io_range[0] = { + .base = 0x3f8, + .size = 8, + }, + .generic_io_range[1] = { + .base = 0x600, + .size = 256, + }, + .io_mode = ESPI_IO_MODE_QUAD, + .op_freq_mhz = ESPI_OP_FREQ_16_MHZ, + .crc_check_enable = 1, + .alert_pin = ESPI_ALERT_PIN_PUSH_PULL, + .periph_ch_en = 1, + .vw_ch_en = 1, + .oob_ch_en = 1, + .flash_ch_en = 0, + }" + + register "i2c_scl_reset" = "GPIO_I2C0_SCL | GPIO_I2C1_SCL | + GPIO_I2C2_SCL | GPIO_I2C3_SCL" + + register "i2c[0].early_init" = "1" + register "i2c[1].early_init" = "1" + register "i2c[2].early_init" = "1" + register "i2c[3].early_init" = "1" + + # I2C Pad Control RX Select Configuration + register "i2c_pad[0].rx_level" = "I2C_PAD_RX_1_8V" + register "i2c_pad[1].rx_level" = "I2C_PAD_RX_1_8V" + register "i2c_pad[2].rx_level" = "I2C_PAD_RX_1_8V" + register "i2c_pad[3].rx_level" = "I2C_PAD_RX_1_8V" + + register "s0ix_enable" = "true" + + register "pspp_policy" = "DXIO_PSPP_DISABLED" # TODO: reenable when PSPP works + + register "usb_phy_custom" = "1" + register "usb_phy" = "{ + .Usb2PhyPort[0] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb2PhyPort[1] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb2PhyPort[2] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb2PhyPort[3] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb2PhyPort[4] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb2PhyPort[5] = { + .compdistune = 0x3, + .pllbtune = 0x1, + .pllitune = 0x0, + .pllptune = 0xe, + .sqrxtune = 0x3, + .txfslstune = 0x3, + .txpreempamptune = 0x2, + .txpreemppulsetune = 0x0, + .txrisetune = 0x1, + .txvreftune = 0x3, + .txhsxvtune = 0x3, + .txrestune = 0x2, + }, + .Usb3PhyPort[0] = { + .tx_term_ctrl = 0x2, + .rx_term_ctrl = 0x2, + .tx_vboost_lvl_en = 0x0, + .tx_vboost_lvl = 0x5, + }, + .Usb3PhyPort[1] = { + .tx_term_ctrl = 0x2, + .rx_term_ctrl = 0x2, + .tx_vboost_lvl_en = 0x0, + .tx_vboost_lvl = 0x5, + }, + .Usb3PhyPort[2] = { + .tx_term_ctrl = 0x2, + .rx_term_ctrl = 0x2, + .tx_vboost_lvl_en = 0x0, + .tx_vboost_lvl = 0x5, + }, + .ComboPhyStaticConfig[0] = USB_COMBO_PHY_MODE_USB_C, + .ComboPhyStaticConfig[1] = USB_COMBO_PHY_MODE_USB_C, + .BatteryChargerEnable = 0, + .PhyP3CpmP4Support = 0, + }" + + register "gpp_clk_config[0]" = "GPP_CLK_REQ" + register "gpp_clk_config[1]" = "GPP_CLK_REQ" + register "gpp_clk_config[2]" = "GPP_CLK_OFF" + register "gpp_clk_config[3]" = "GPP_CLK_REQ" + + device domain 0 on + device ref iommu on end + device ref gpp_bridge_0 on end # GBE + device ref gpp_bridge_1 on end # WIFI + device ref gpp_bridge_2 on end # NVMe SSD + device ref gpp_bridge_a on # Internal GPP Bridge 0 to Bus A + device ref gfx on end # Internal GPU (GFX) + device ref gfx_hda on end # Display HD Audio Controller (GFXAZ) + device ref crypto on end # Crypto Coprocessor + device ref xhci_0 on # USB 3.1 (USB0) + chip drivers/usb/acpi + device ref xhci_0_root_hub on + chip drivers/usb/acpi + device ref usb3_port0 on end + end + chip drivers/usb/acpi + device ref usb2_port0 on end + end + chip drivers/usb/acpi + device ref usb2_port1 on end + end + end + end + end + device ref xhci_1 on # USB 3.1 (USB1) + chip drivers/usb/acpi + device ref xhci_1_root_hub on + chip drivers/usb/acpi + device ref usb3_port2 on end + end + chip drivers/usb/acpi + device ref usb3_port3 on end + end + chip drivers/usb/acpi + device ref usb2_port2 on end + end + chip drivers/usb/acpi + device ref usb2_port3 on end + end + chip drivers/usb/acpi + device ref usb2_port4 on end + end + end + end + end + device ref acp on end # Audio Processor (ACP) + end + device ref gpp_bridge_c on # Internal GPP Bridge 2 to Bus C + device ref xhci_2 on + chip drivers/usb/acpi + register "type" = "UPC_TYPE_HUB" + device usb 0.0 alias xhci_2_root_hub on + chip drivers/usb/acpi + device usb 2.0 alias usb2_port5 on end + end + end + end + end + end + end + + device ref i2c_0 on end + device ref i2c_1 on end + device ref i2c_2 on end + device ref i2c_3 on end + device ref uart_0 on end # UART0 + +end diff --git a/src/mainboard/amd/birman/dsdt.asl b/src/mainboard/amd/birman/dsdt.asl new file mode 100644 index 0000000000..7b8982a645 --- /dev/null +++ b/src/mainboard/amd/birman/dsdt.asl @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +DefinitionBlock ( + "dsdt.aml", + "DSDT", + ACPI_DSDT_REV_2, + OEM_ID, + ACPI_TABLE_CREATOR, + 0x00010001 /* OEM Revision */ + ) +{ + #include + + #include +} diff --git a/src/mainboard/amd/birman/early_gpio.c b/src/mainboard/amd/birman/early_gpio.c new file mode 100644 index 0000000000..bcdeea7914 --- /dev/null +++ b/src/mainboard/amd/birman/early_gpio.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "gpio.h" + +/* TODO: Update for birman */ + +/* GPIO pins used by coreboot should be initialized in bootblock */ + +static const struct soc_amd_gpio gpio_set_stage_reset[] = { +}; + +void mainboard_program_early_gpios(void) +{ + gpio_configure_pads(gpio_set_stage_reset, ARRAY_SIZE(gpio_set_stage_reset)); +} diff --git a/src/mainboard/amd/birman/ec.c b/src/mainboard/amd/birman/ec.c new file mode 100644 index 0000000000..3775ef5a2a --- /dev/null +++ b/src/mainboard/amd/birman/ec.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Update for birman */ + +#include +#include "ec.h" + +#define BIRMAN_EC_CMD 0x666 +#define BIRMAN_EC_DATA 0x662 + +#define EC_GPIO_3_ADDR 0xA3 +#define EC_GPIO_LOM_RESET_AUX BIT(1) + +#define EC_GPIO_7_ADDR 0xA7 +#define EC_GPIO_DT_PWREN BIT(2) +#define EC_GPIO_WWAN_MODULE_RST BIT(5) + +#define EC_GPIO_8_ADDR 0xA8 +#define EC_GPIO_SMBUS0_EN BIT(0) + +#define EC_GPIO_A_ADDR 0xAA +#define EC_GPIO_WWAN_PWREN BIT(3) +#define EC_GPIO_M2_SSD0_PWREN BIT(6) +#define EC_GPIO_LOM_PWREN BIT(7) + +#define EC_GPIO_C_ADDR 0xAC +#define EC_GPIO_DT_N_WLAN_SW BIT(1) +#define EC_GPIO_MP2_SEL BIT(2) +#define EC_GPIO_WWAN_N_LOM_SW BIT(3) + +#define EC_SW02_ADDR 0xB7 +#define EC_SW02_MS BIT(7) + +static void configure_ec_gpio(void) +{ + uint8_t tmp; + + tmp = ec_read(EC_GPIO_3_ADDR); + tmp |= EC_GPIO_LOM_RESET_AUX; + ec_write(EC_GPIO_3_ADDR, tmp); + + tmp = ec_read(EC_GPIO_7_ADDR); + tmp |= EC_GPIO_WWAN_MODULE_RST | EC_GPIO_DT_PWREN; + ec_write(EC_GPIO_7_ADDR, tmp); + + tmp = ec_read(EC_GPIO_8_ADDR); + tmp |= EC_GPIO_SMBUS0_EN; + ec_write(EC_GPIO_8_ADDR, tmp); + + tmp = ec_read(EC_GPIO_A_ADDR); + tmp |= EC_GPIO_M2_SSD0_PWREN | EC_GPIO_LOM_PWREN | EC_GPIO_WWAN_PWREN; + ec_write(EC_GPIO_A_ADDR, tmp); + + tmp = ec_read(EC_GPIO_C_ADDR); + tmp |= EC_GPIO_WWAN_N_LOM_SW | EC_GPIO_MP2_SEL | EC_GPIO_DT_N_WLAN_SW; + ec_write(EC_GPIO_C_ADDR, tmp); + + tmp = ec_read(EC_SW02_ADDR); + tmp |= EC_SW02_MS; + ec_write(EC_SW02_ADDR, tmp); +} + +void birman_ec_init(void) +{ + ec_set_ports(BIRMAN_EC_CMD, BIRMAN_EC_DATA); + configure_ec_gpio(); +} diff --git a/src/mainboard/amd/birman/ec.h b/src/mainboard/amd/birman/ec.h new file mode 100644 index 0000000000..d8e54db35f --- /dev/null +++ b/src/mainboard/amd/birman/ec.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef BIRMAN_EC_H +#define BIRMAN_EC_H + +void birman_ec_init(void); + +#endif /* BIRMAN_EC_H */ diff --git a/src/mainboard/amd/birman/gpio.c b/src/mainboard/amd/birman/gpio.c new file mode 100644 index 0000000000..583b1d1ab3 --- /dev/null +++ b/src/mainboard/amd/birman/gpio.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "gpio.h" + +/* TODO: Update for birman */ + +/* + * As a rule of thumb, GPIO pins used by coreboot should be initialized at + * bootblock while GPIO pins used only by the OS should be initialized at + * ramstage. + */ +static const struct soc_amd_gpio gpio_set_stage_ram[] = { + +}; + +void mainboard_program_gpios(void) +{ + gpio_configure_pads(gpio_set_stage_ram, ARRAY_SIZE(gpio_set_stage_ram)); +} diff --git a/src/mainboard/amd/birman/gpio.h b/src/mainboard/amd/birman/gpio.h new file mode 100644 index 0000000000..04c98c50df --- /dev/null +++ b/src/mainboard/amd/birman/gpio.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef MAINBOARD_GPIO_H +#define MAINBOARD_GPIO_H + +void mainboard_program_early_gpios(void); /* bootblock GPIO configuration */ +void mainboard_program_gpios(void); /* ramstage GPIO configuration */ + +#endif /* MAINBOARD_GPIO_H */ diff --git a/src/mainboard/amd/birman/mainboard.c b/src/mainboard/amd/birman/mainboard.c new file mode 100644 index 0000000000..ffb778cf4e --- /dev/null +++ b/src/mainboard/amd/birman/mainboard.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +/* TODO: Update for birman */ + +/* + * 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 controls the device -> IRQ routing. + * + * Hardcoded IRQs: + * 0: timer < soc/amd/common/acpi/lpc.asl + * 1: i8042 - Keyboard + * 2: cascade + * 8: rtc0 <- soc/amd/common/acpi/lpc.asl + * 9: acpi <- soc/amd/common/acpi/lpc.asl + */ +static const struct fch_irq_routing { + uint8_t intr_index; + uint8_t pic_irq_num; + uint8_t apic_irq_num; +} birman_fch[] = { + { PIRQ_A, 12, PIRQ_NC }, + { PIRQ_B, 14, PIRQ_NC }, + { PIRQ_C, 15, PIRQ_NC }, + { PIRQ_D, 12, PIRQ_NC }, + { PIRQ_E, 14, PIRQ_NC }, + { PIRQ_F, 15, PIRQ_NC }, + { PIRQ_G, 12, PIRQ_NC }, + { PIRQ_H, 14, PIRQ_NC }, + + { PIRQ_SCI, ACPI_SCI_IRQ, ACPI_SCI_IRQ }, + { PIRQ_SD, PIRQ_NC, PIRQ_NC }, + { PIRQ_SDIO, PIRQ_NC, PIRQ_NC }, + { PIRQ_EMMC, PIRQ_NC, PIRQ_NC }, + { PIRQ_GPIO, 11, 11 }, + { PIRQ_I2C0, 10, 10 }, + { PIRQ_I2C1, 7, 7 }, + { PIRQ_I2C2, 6, 6 }, + { PIRQ_I2C3, 5, 5 }, + { PIRQ_UART0, 4, 4 }, + { PIRQ_UART1, 3, 3 }, + + /* The MISC registers are not interrupt numbers */ + { PIRQ_MISC, 0xfa, 0x00 }, + { PIRQ_MISC0, 0x91, 0x00 }, + { PIRQ_HPET_L, 0x00, 0x00 }, + { PIRQ_HPET_H, 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(birman_fch); i++) { + entry = birman_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) +{ + intr_data_ptr = fch_apic_routing; + picr_data_ptr = fch_pic_routing; +} + +static void mainboard_init(void *chip_info) +{ + mainboard_program_gpios(); +} + +static void mainboard_enable(struct device *dev) +{ + init_tables(); + /* Initialize the PIRQ data structures for consumption */ + pirq_setup(); +} + +struct chip_operations mainboard_ops = { + .init = mainboard_init, + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/amd/birman/port_descriptors.c b/src/mainboard/amd/birman/port_descriptors.c new file mode 100644 index 0000000000..f2ed5c54fe --- /dev/null +++ b/src/mainboard/amd/birman/port_descriptors.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +/* TODO: Update for birman */ + +static const fsp_dxio_descriptor birman_dxio_descriptors[] = { + { + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 0, + .end_logical_lane = 0, + .device_number = 2, + .function_number = 1, + .link_speed_capability = GEN3, + .turn_off_unused_lanes = true, + .link_aspm = 2, + .link_hotplug = 3, + .clk_req = CLK_REQ3, + }, + { + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 1, + .end_logical_lane = 1, + .device_number = 2, + .function_number = 2, + .link_speed_capability = GEN3, + .turn_off_unused_lanes = true, + .link_aspm = 2, + .link_hotplug = 3, + .clk_req = CLK_REQ1, + }, + { + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 2, + .end_logical_lane = 3, + .device_number = 2, + .function_number = 3, + .link_speed_capability = GEN3, + .turn_off_unused_lanes = true, + .link_aspm = 2, + .link_hotplug = 3, + .gpio_group_id = GPIO_27, + .clk_req = CLK_REQ0, + }, +}; + +static fsp_ddi_descriptor birman_ddi_descriptors[] = { + { /* DDI0 - eDP */ + .connector_type = DDI_EDP, + .aux_index = DDI_AUX1, + .hdp_index = DDI_HDP1 + }, + { /* DDI1 - HDMI/DP */ + .connector_type = DDI_HDMI, + .aux_index = DDI_AUX2, + .hdp_index = DDI_HDP2 + }, + { /* DDI2 - DP (type C) */ + .connector_type = DDI_DP, + .aux_index = DDI_AUX3, + .hdp_index = DDI_HDP3, + }, + { /* DDI3 - DP (type C) */ + .connector_type = DDI_DP, + .aux_index = DDI_AUX4, + .hdp_index = DDI_HDP4, + }, + { /* DDI4 - unused */ + .connector_type = DDI_UNUSED_TYPE, + .aux_index = DDI_AUX5, + .hdp_index = DDI_HDP5, + } +}; + +static uint8_t get_ddi1_type(void) +{ + const uint8_t eeprom_i2c_bus = 2; + const uint8_t eeprom_i2c_address = 0x55; + const uint16_t eeprom_connector_type_offset = 2; + uint8_t eeprom_connector_type_data[2]; + uint16_t connector_type; + + if (i2c_2ba_read_bytes(eeprom_i2c_bus, eeprom_i2c_address, + eeprom_connector_type_offset, eeprom_connector_type_data, + sizeof(eeprom_connector_type_data))) { + printk(BIOS_NOTICE, + "Display connector type couldn't be determined. Disabling DDI1.\n"); + return DDI_UNUSED_TYPE; + } + + connector_type = eeprom_connector_type_data[1] | eeprom_connector_type_data[0] << 8; + + switch (connector_type) { + case 0xc: + printk(BIOS_DEBUG, "Configuring DDI1 as HDMI.\n"); + return DDI_HDMI; + break; + case 0x13: + printk(BIOS_DEBUG, "Configuring DDI1 as DP.\n"); + return DDI_DP; + break; + case 0x14: + printk(BIOS_DEBUG, "Configuring DDI1 as eDP.\n"); + return DDI_EDP; + break; + default: + printk(BIOS_WARNING, "Unexpected display connector type %x. Disabling DDI1.\n", + connector_type); + return DDI_UNUSED_TYPE; + } +} + +void mainboard_get_dxio_ddi_descriptors( + const fsp_dxio_descriptor **dxio_descs, size_t *dxio_num, + const fsp_ddi_descriptor **ddi_descs, size_t *ddi_num) +{ + birman_ddi_descriptors[1].connector_type = get_ddi1_type(); + + *dxio_descs = birman_dxio_descriptors; + *dxio_num = ARRAY_SIZE(birman_dxio_descriptors); + *ddi_descs = birman_ddi_descriptors; + *ddi_num = ARRAY_SIZE(birman_ddi_descriptors); +}