diff --git a/src/mainboard/system76/kudu6/Kconfig b/src/mainboard/system76/kudu6/Kconfig new file mode 100644 index 0000000000..00a03b5177 --- /dev/null +++ b/src/mainboard/system76/kudu6/Kconfig @@ -0,0 +1,62 @@ +if BOARD_SYSTEM76_KUDU6 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select AMD_SOC_CONSOLE_UART + select BOARD_ROMSIZE_KB_16384 + select DRIVERS_GFX_NVIDIA + select DRIVERS_I2C_HID + select EC_SYSTEM76_EC + select EC_SYSTEM76_EC_BAT_THRESHOLDS + select EC_SYSTEM76_EC_COLOR_KEYBOARD + select EC_SYSTEM76_EC_DGPU + select HAVE_ACPI_RESUME + select HAVE_ACPI_TABLES + select MAINBOARD_HAS_LPC_TPM + select MAINBOARD_HAS_TPM2 + select PCIEXP_ASPM + select PCIEXP_CLK_PM + select PCIEXP_COMMON_CLOCK + select PCIEXP_L1_SUB_STATE + select NO_UART_ON_SUPERIO + select SOC_AMD_CEZANNE + select SOC_AMD_COMMON_BLOCK_GRAPHICS_ATIF + select SOC_AMD_COMMON_BLOCK_USE_ESPI + select SPD_READ_BY_WORD + select SYSTEM_TYPE_LAPTOP + select TPM_RDRESP_NEED_DELAY + +config MAINBOARD_DIR + default "system76/kudu6" + +config MAINBOARD_PART_NUMBER + default "kudu6" + +config MAINBOARD_SMBIOS_PRODUCT_NAME + default "Kudu" + +config MAINBOARD_VERSION + default "kudu6" + +config CBFS_SIZE + default 0xA00000 + +config CONSOLE_POST + default y + +config DIMM_MAX + default 4 + +config DIMM_SPD_SIZE + default 512 + +config ONBOARD_VGA_IS_PRIMARY + default y + +config POST_DEVICE + default n + +config UART_FOR_CONSOLE + default 0 + +endif diff --git a/src/mainboard/system76/kudu6/Kconfig.name b/src/mainboard/system76/kudu6/Kconfig.name new file mode 100644 index 0000000000..2e63f757f9 --- /dev/null +++ b/src/mainboard/system76/kudu6/Kconfig.name @@ -0,0 +1,2 @@ +config BOARD_SYSTEM76_KUDU6 + bool "kudu6" diff --git a/src/mainboard/system76/kudu6/Makefile.inc b/src/mainboard/system76/kudu6/Makefile.inc new file mode 100644 index 0000000000..19a5765f4f --- /dev/null +++ b/src/mainboard/system76/kudu6/Makefile.inc @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only + +bootblock-y += bootblock.c +bootblock-y += early_gpio.c + +romstage-y += port_descriptors.c diff --git a/src/mainboard/system76/kudu6/board_info.txt b/src/mainboard/system76/kudu6/board_info.txt new file mode 100644 index 0000000000..aa4bbbe39c --- /dev/null +++ b/src/mainboard/system76/kudu6/board_info.txt @@ -0,0 +1,8 @@ +Vendor name: System76 +Board name: kudu6 +Category: laptop +Release year: 2021 +ROM package: SOIC-8 +ROM protocol: SPI +ROM socketed: n +Flashrom support: y diff --git a/src/mainboard/system76/kudu6/bootblock.c b/src/mainboard/system76/kudu6/bootblock.c new file mode 100644 index 0000000000..f768f3f778 --- /dev/null +++ b/src/mainboard/system76/kudu6/bootblock.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "gpio.h" + +void bootblock_mainboard_early_init(void) +{ + mainboard_program_early_gpios(); +} diff --git a/src/mainboard/system76/kudu6/devicetree.cb b/src/mainboard/system76/kudu6/devicetree.cb new file mode 100644 index 0000000000..9dddacb2b9 --- /dev/null +++ b/src/mainboard/system76/kudu6/devicetree.cb @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: GPL-2.0-only + +chip soc/amd/cezanne + + register "common_config.acp_config" = "{ + .acp_pin_cfg = I2S_PINS_I2S_TDM, + .acp_i2s_wake_enable = 0, + .acp_pme_enable = 0, + .dmic_present = 1, + }" + + register "common_config.espi_config" = "{ + .std_io_decode_bitmap = ESPI_DECODE_IO_0x80_EN | ESPI_DECODE_IO_0X60_0X64_EN, + /* EC PM channel */ + .generic_io_range[0] = { + .base = 0x62, + /* + * Only 0x62 and 0x66 are required. But, this is not supported by + * standard IO decodes and there are only 4 generic I/O windows + * available. Hence, open a window from 0x62-0x67. + */ + .size = 5, + }, + /* AP/EC debug */ + .generic_io_range[1] = { + .base = 0xE00, + .size = 256, + }, + /* AP/EC debug */ + .generic_io_range[2] = { + .base = 0xF00, + .size = 256, + }, + + .io_mode = ESPI_IO_MODE_QUAD, + .op_freq_mhz = ESPI_OP_FREQ_33_MHZ, + .crc_check_enable = 1, + .alert_pin = ESPI_ALERT_PIN_OPEN_DRAIN, + .periph_ch_en = 1, + .vw_ch_en = 1, + .oob_ch_en = 0, + .flash_ch_en = 0, + + .vw_irq_polarity = ESPI_VW_IRQ_LEVEL_HIGH(1), + }" + + register "i2c_scl_reset" = "GPIO_I2C0_SCL | GPIO_I2C1_SCL | + GPIO_I2C2_SCL | GPIO_I2C3_SCL" + # I2C Pad Control RX Select Configuration + register "i2c_pad_ctrl_rx_sel[0]" = "I2C_PAD_CTRL_RX_SEL_3_3V" # Trackpad + register "i2c_pad_ctrl_rx_sel[1]" = "I2C_PAD_CTRL_RX_SEL_3_3V" # NC + register "i2c_pad_ctrl_rx_sel[2]" = "I2C_PAD_CTRL_RX_SEL_3_3V" # DDR4 + register "i2c_pad_ctrl_rx_sel[3]" = "I2C_PAD_CTRL_RX_SEL_3_3V" # USB-PD + + + register "s0ix_enable" = "true" + + register "pspp_policy" = "DXIO_PSPP_BALANCED" + + 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_OFF" + register "gpp_clk_config[4]" = "GPP_CLK_REQ" + register "gpp_clk_config[5]" = "GPP_CLK_REQ" + register "gpp_clk_config[6]" = "GPP_CLK_REQ" + + #TODO: USB? + + device domain 0 on + device ref iommu on end + device ref gpp_gfx_bridge_0 on end # DGPU + device ref gpp_bridge_0 on end # LAN + device ref gpp_bridge_1 on end # WLAN + device ref gpp_bridge_2 on end # SSD2 + device ref gpp_bridge_3 on end # SSD1 + 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 # GFX HD Audio Controller + device ref crypto on end # Crypto Coprocessor + device ref xhci_0 on end # USB 3.1 (USB0) + device ref xhci_1 on end # USB 3.1 (USB1) + device ref acp on end # Audio Processor + device ref hda on end # HD Audio Controller + end + device ref gpp_bridge_b on # Internal GPP Bridge 1 to Bus B + device ref sata_0 on end # SATA + device ref sata_1 on end # SATA + end + end + + device ref uart_0 on end # UART0 + +end diff --git a/src/mainboard/system76/kudu6/dsdt.asl b/src/mainboard/system76/kudu6/dsdt.asl new file mode 100644 index 0000000000..4298823523 --- /dev/null +++ b/src/mainboard/system76/kudu6/dsdt.asl @@ -0,0 +1,25 @@ +/* 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 + + Scope (\_SB.PCI0.LPCB) + { + #include + } + + #define EC_GPE_SCI 0x6E + #define EC_GPE_SWI 0x6B + #include +} diff --git a/src/mainboard/system76/kudu6/early_gpio.c b/src/mainboard/system76/kudu6/early_gpio.c new file mode 100644 index 0000000000..edea66ce56 --- /dev/null +++ b/src/mainboard/system76/kudu6/early_gpio.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "gpio.h" + +/* GPIO pins used by coreboot should be initialized in bootblock */ + +static const struct soc_amd_gpio gpio_set_stage_reset[] = { + PAD_NF(GPIO_113, I2C2_SCL, PULL_NONE), // APU_SMB0_CLK + PAD_NF(GPIO_114, I2C2_SDA, PULL_NONE), // APU_SMB0_DATA + PAD_NF(GPIO_19, I2C3_SCL, PULL_NONE), // SMC_7411 + PAD_NF(GPIO_20, I2C3_SDA, PULL_NONE), // SMD_7411 +}; + +void mainboard_program_early_gpios(void) +{ + gpio_configure_pads(gpio_set_stage_reset, ARRAY_SIZE(gpio_set_stage_reset)); +} diff --git a/src/mainboard/system76/kudu6/gpio.h b/src/mainboard/system76/kudu6/gpio.h new file mode 100644 index 0000000000..2143368b2b --- /dev/null +++ b/src/mainboard/system76/kudu6/gpio.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef MAINBOARD_GPIO_H +#define MAINBOARD_GPIO_H + +void mainboard_program_early_gpios(void); /* bootblock GPIO configuration */ + +#endif /* MAINBOARD_GPIO_H */ diff --git a/src/mainboard/system76/kudu6/mainboard.c b/src/mainboard/system76/kudu6/mainboard.c new file mode 100644 index 0000000000..419b3b5951 --- /dev/null +++ b/src/mainboard/system76/kudu6/mainboard.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; +} kudu6_fch[] = { + { PIRQ_A, PIRQ_NC, PIRQ_NC }, + { PIRQ_B, PIRQ_NC, PIRQ_NC }, + { PIRQ_C, PIRQ_NC, PIRQ_NC }, + { PIRQ_D, PIRQ_NC, PIRQ_NC }, + { PIRQ_E, PIRQ_NC, PIRQ_NC }, + { PIRQ_F, PIRQ_NC, PIRQ_NC }, + { PIRQ_G, PIRQ_NC, PIRQ_NC }, + { PIRQ_H, PIRQ_NC, PIRQ_NC }, + + { PIRQ_SCI, ACPI_SCI_IRQ, ACPI_SCI_IRQ }, + { PIRQ_SD, PIRQ_NC, PIRQ_NC }, + { PIRQ_SDIO, PIRQ_NC, PIRQ_NC }, + { PIRQ_SATA, PIRQ_NC, PIRQ_NC }, + { PIRQ_EMMC, PIRQ_NC, PIRQ_NC }, + { PIRQ_GPIO, 7, 7 }, + { PIRQ_I2C2, PIRQ_NC, PIRQ_NC }, + { PIRQ_I2C3, PIRQ_NC, PIRQ_NC }, + { 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(kudu6_fch); i++) { + entry = kudu6_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) +{ +} + +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/system76/kudu6/port_descriptors.c b/src/mainboard/system76/kudu6/port_descriptors.c new file mode 100644 index 0000000000..8db310fde9 --- /dev/null +++ b/src/mainboard/system76/kudu6/port_descriptors.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +static const fsp_dxio_descriptor kudu6_dxio_descriptors[] = { + { /* DGPU */ + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 16, + .end_logical_lane = 23, + .device_number = 1, + .function_number = 1, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ0, + .port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122} + }, + { /* LAN */ + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 0, + .end_logical_lane = 0, + .device_number = 2, + .function_number = 1, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ1, + .port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122} + }, + { /* WLAN */ + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 1, + .end_logical_lane = 1, + .device_number = 2, + .function_number = 2, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ6, + .port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122} + }, + { /* SSD2 */ + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 4, + .end_logical_lane = 7, + .device_number = 2, + .function_number = 3, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ4_GFX, + .port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122} + }, + { /* SSD1 */ + .engine_type = PCIE_ENGINE, + .port_present = true, + .start_logical_lane = 8, + .end_logical_lane = 11, + .device_number = 2, + .function_number = 4, + .turn_off_unused_lanes = true, + .clk_req = CLK_REQ5, + .port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122} + }, + { /* HDD */ + .engine_type = SATA_ENGINE, + .port_present = true, + .start_logical_lane = 0, + .end_logical_lane = 0, + .channel_type = SATA_CHANNEL_LONG, + } +}; + +static const fsp_ddi_descriptor kudu6_ddi_descriptors[] = { + { /* DDI0 - eDP */ + .connector_type = DDI_EDP, + .aux_index = DDI_AUX1, + .hdp_index = DDI_HDP1 + }, + { /* DDI1 */ + .connector_type = DDI_UNUSED_TYPE, + .aux_index = DDI_AUX2, + .hdp_index = DDI_HDP2 + }, + { /* DDI2 */ + .connector_type = DDI_UNUSED_TYPE, + .aux_index = DDI_AUX3, + .hdp_index = DDI_HDP3, + }, + { /* DDI3 */ + .connector_type = DDI_UNUSED_TYPE, + .aux_index = DDI_AUX3, + .hdp_index = DDI_HDP3, + }, + { /* DDI4 */ + .connector_type = DDI_UNUSED_TYPE, + .aux_index = DDI_AUX4, + .hdp_index = DDI_HDP4, + } +}; + +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) +{ + *dxio_descs = kudu6_dxio_descriptors; + *dxio_num = ARRAY_SIZE(kudu6_dxio_descriptors); + *ddi_descs = kudu6_ddi_descriptors; + *ddi_num = ARRAY_SIZE(kudu6_ddi_descriptors); +}