Hannah Williams (hannah.williams@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18468
-gerrit
commit a66a566f20866bf397ba11938a713f8aae7302c0 Author: Hannah Williams hannah.williams@intel.com Date: Tue Feb 14 09:32:28 2017 -0800
mainboard/intel: Create common code for Intel boards using FSP2.0
This is a WIP patch to see if having a common mainboard code for INTEL platforms using FSP2.0 is feasible.
Change-Id: I704951c82ba09b7d8c606f4086ee2404169b3673 Signed-off-by: Hannah Williams hannah.williams@intel.com --- src/mainboard/intel/common/Kconfig | 49 +++++ src/mainboard/intel/common/Makefile.inc | 21 ++ src/mainboard/intel/common/boardid.c | 35 +++ src/mainboard/intel/common/bootblock.c | 32 +++ src/mainboard/intel/common/chromeos.c | 86 ++++++++ src/mainboard/intel/common/ec.c | 46 ++++ src/mainboard/intel/common/include/ec.h | 59 +++++ src/mainboard/intel/common/include/meminit.h | 99 +++++++++ src/mainboard/intel/common/include/variants.h | 48 +++++ src/mainboard/intel/common/mainboard.c | 79 +++++++ src/mainboard/intel/common/meminit_fsp2_atom.c | 284 +++++++++++++++++++++++++ src/mainboard/intel/common/meminit_fsp2_core.c | 64 ++++++ src/mainboard/intel/common/ramstage.c | 40 ++++ src/mainboard/intel/common/smihandler.c | 54 +++++ 14 files changed, 996 insertions(+)
diff --git a/src/mainboard/intel/common/Kconfig b/src/mainboard/intel/common/Kconfig new file mode 100644 index 0000000..2eca9f4 --- /dev/null +++ b/src/mainboard/intel/common/Kconfig @@ -0,0 +1,49 @@ +config INTEL_MAINBOARD_COMMON + bool "Using Intel mainboard common" + default n + help + Common code for Intel mainboards + + +config MAINBOARD_COMMON_LPC_CONFIG + bool "Configure LPC from mainboard common" + default n + help + Configure LPC from mainboard common + + +config MAINBOARD_COMMON_GPIO_CONFIG + bool "Configure GPIO from mainboard common" + default n + help + Configure GPIO from mainboard common + +config HAVE_SPD + bool "Read data from SPD on SMBUS" + default n + help + Read data from SPD on SMBUS + +config HAVE_SPD_BIN + bool "Read data from spd.bin" + default n + help + Read data from spd.bin + +config MAINBOARD_COMMON_WRITE_ACPI_TABLES + bool "update acpi tables from mainboard common" + default n + help + update acpi tables from mainboard common + +config MAINBOARD_COMMON_FSP2_CORE + bool "Is this platform using FSP2.0 for CORE SOCs" + default n + help + Is this platform using FSP2.0 for CORE SOCs + +config MAINBOARD_COMMON_FSP2_ATOM + bool "Is this platform using FSP2.0 for ATOM SOCs" + default n + help + Is this platform using FSP2.0 for ATOM SOCs diff --git a/src/mainboard/intel/common/Makefile.inc b/src/mainboard/intel/common/Makefile.inc new file mode 100644 index 0000000..346fe7b --- /dev/null +++ b/src/mainboard/intel/common/Makefile.inc @@ -0,0 +1,21 @@ +#ifeq ($(CONFIG_INTEL_MAINBOARD_COMMON),y) + +bootblock-y += bootblock.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +romstage-y += boardid.c +romstage-$(CONFIG_MAINBOARD_COMMON_FSP2_CORE) += meminit_fsp2_core.c +romstage-$(CONFIG_MAINBOARD_COMMON_FSP2_ATOM) += meminit_fsp2_atom.c + + +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c +ramstage-y += mainboard.c +ramstage-y += boardid.c + +verstage-$(CONFIG_CHROMEOS) += chromeos.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +CPPFLAGS_common += -I$(src)/mainboard/intel/common/include +CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants +#endif diff --git a/src/mainboard/intel/common/boardid.c b/src/mainboard/intel/common/boardid.c new file mode 100644 index 0000000..25e1b17 --- /dev/null +++ b/src/mainboard/intel/common/boardid.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <variants.h> +#include <ec/google/chromeec/ec.h> + +uint8_t __attribute__((weak)) variant_board_id(void) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + return google_chromeec_get_board_version(); + else + return 0; +} + +uint8_t __attribute__((weak)) variant_get_spd_index(void) +{ + return 0; +} + +size_t __attribute__((weak)) variant_memory_sku(void ) +{ + return 0; +} diff --git a/src/mainboard/intel/common/bootblock.c b/src/mainboard/intel/common/bootblock.c new file mode 100644 index 0000000..7001220 --- /dev/null +++ b/src/mainboard/intel/common/bootblock.c @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <variants.h> +#include <bootblock_common.h> +#include <soc/lpc.h> +#include <soc/gpio.h> +#include <variant/ec.h> + +void mainboard_ec_init(void); + +void bootblock_mainboard_init(void) +{ + const struct pad_config *pads; + size_t num; + if (IS_ENABLED(CONFIG_MAINBOARD_LPC_CONFIG)) + lpc_configure_pads();/* TODO Add bootblock_ec_init into soc folder as lpc_configure_ioport)*/ + pads = variant_early_gpio_table(&num); + gpio_configure_pads(pads, num); +} diff --git a/src/mainboard/intel/common/chromeos.c b/src/mainboard/intel/common/chromeos.c new file mode 100644 index 0000000..5b6bd3a --- /dev/null +++ b/src/mainboard/intel/common/chromeos.c @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <variants.h> +#include <boot/coreboot_tables.h> +#include <ec/google/chromeec/ec.h> +#include <gpio.h> +#include <vendorcode/google/chromeos/chromeos.h> +#include <soc/gpio.h> +#include <variant/gpio.h> + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio chromeos_gpios[] = { + {-1, ACTIVE_HIGH, get_write_protect_state(), "write protect"}, + {-1, ACTIVE_HIGH, get_recovery_mode_switch(), "recovery"}, + {-1, ACTIVE_HIGH, get_developer_mode_switch(), "developer"}, + {-1, ACTIVE_HIGH, get_lid_switch(), "lid"}, + {-1, ACTIVE_HIGH, 0, "power"}, + {-1, ACTIVE_HIGH, gfx_get_init_done(), "oprom"}, + {GPIO_EC_IN_RW, ACTIVE_HIGH, + gpio_get(GPIO_EC_IN_RW), "EC in RW"}, + }; + lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios)); +} + +int get_lid_switch(void) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + /* Read lid switch state from the EC. */ + return !!(google_chromeec_get_switches() & EC_SWITCH_LID_OPEN); + else + return 1; +} + +int get_developer_mode_switch(void) +{ + /* No physical developer mode switch. It's virtual. */ + return 0; +} + +int get_recovery_mode_switch(void) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + /* Check if the EC has posted the keyboard recovery event. */ + return !!(google_chromeec_get_events_b() & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); + return 0; +} + +int clear_recovery_mode_switch(void) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + /* Clear keyboard recovery event. */ + return google_chromeec_clear_events_b( + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); + else + return 0; +} + +int get_write_protect_state(void) +{ + /* Read PCH_WP GPIO. */ + return gpio_get(GPIO_PCH_WP); +} + +void mainboard_chromeos_acpi_generate(void) +{ + const struct cros_gpio *gpios; + size_t num; + + gpios = variant_cros_gpios(&num); + chromeos_acpi_gpio_generate(gpios, num); +} diff --git a/src/mainboard/intel/common/ec.c b/src/mainboard/intel/common/ec.c new file mode 100644 index 0000000..7a5bda2 --- /dev/null +++ b/src/mainboard/intel/common/ec.c @@ -0,0 +1,46 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Google Inc. + * Copyright (C) 2016 Intel Corporation + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/acpi.h> +#include <console/console.h> +#include <ec/google/chromeec/ec.h> +#include "./include/ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard: EC init\n"); + + if (acpi_is_wakeup_s3()) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0) + ; + + /* Restore SCI event mask */ + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake event mask */ + google_chromeec_set_wake_mask(0); +} diff --git a/src/mainboard/intel/common/include/ec.h b/src/mainboard/intel/common/include/ec.h new file mode 100644 index 0000000..9fe3dad --- /dev/null +++ b/src/mainboard/intel/common/include/ec.h @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Google Inc. + * Copyright (C) 2016 Intel Corporation + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef MAINBOARD_COMMON_EC_H +#define MAINBOARD_COMMON_EC_H + +#include <ec/ec.h> +#include <ec/google/chromeec/ec_commands.h> + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MKBP)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)|\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC)) + +#endif diff --git a/src/mainboard/intel/common/include/meminit.h b/src/mainboard/intel/common/include/meminit.h new file mode 100644 index 0000000..bc45200 --- /dev/null +++ b/src/mainboard/intel/common/include/meminit.h @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Intel Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _MAINBOARD_COMMON_MEMINIT_H_ +#define _MAINBOARD_COMMON_MEMINIT_H_ + +#include <stddef.h> +#include <stdint.h> + +/* + * There are 4 physical channels each 32-bits wide. There are 2 logical + * channels using 2 physical channels together to form a 64-bit interface to + * memory for each logical channel. + */ +enum { + DDR_PHYS_CH0A, + DDR_PHYS_CH0B, + DDR_PHYS_CH1A, + DDR_PHYS_CH1B, + DDR_NUM_PHYS_CHANNELS +}; + +/* Logical channel identification. */ +enum { + DDR_LCH0, + DDR_LCH1 +}; + +/* + * The DQs within a physical channel can be bit-swizzled within each byte. + * Within a channel the bytes can be swapped, but the DQs need to be routed + * with the corresponding DQS (strobe). + */ +enum { + DDR_DQS0, + DDR_DQS1, + DDR_DQS2, + DDR_DQS3, + DDR_NUM_BYTE_LANES, + DQ_BITS_PER_DQS = 8, +}; + +enum { + LP4_SPEED_1600, + LP4_SPEED_2133, + LP4_SPEED_2400, +}; + +/* LPDDR4 module density in bits. */ +enum { + DDR_8Gb_DENSITY = 2, + DDR_12Gb_DESNITY, + DDR_16Gb_DENSITY, +}; + +/* Provide bit swizzling per DQS and byte swapping within a channel. */ +struct ddr_chan_swizzle_cfg { + uint8_t dqs[DDR_NUM_BYTE_LANES][DQ_BITS_PER_DQS]; +}; + +struct ddr_swizzle_cfg { + struct ddr_chan_swizzle_cfg phys[DDR_NUM_PHYS_CHANNELS]; +}; + + +struct ddr_sku { + int speed; + int ch0_rank_density; + int ch1_rank_density; + int ch0_dual_rank; + int ch1_dual_rank; + const char *part_num; + bool disable_periodic_retraining; +}; + +struct ddr_cfg { + const struct ddr_sku *skus; + size_t num_skus; + const struct ddr_swizzle_cfg *swizzle_config; +}; + + +void save_lpddr4_dimm_info(const struct ddr_cfg *lpcfg, size_t mem_sku); +void override_ddr_defaults(FSP_M_CONFIG *cfg); +void soc_display_memory_init_params(FSP_M_CONFIG *fspm_cfg); + +#endif /* _MAINBOARD_COMMON_MEMINIT_H_ */ diff --git a/src/mainboard/intel/common/include/variants.h b/src/mainboard/intel/common/include/variants.h new file mode 100644 index 0000000..caa3399 --- /dev/null +++ b/src/mainboard/intel/common/include/variants.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef BASEBOARD_VARIANTS_H +#define BASEBOARD_VARIANTS_H + +#include <soc/gpio.h> +#include <stdint.h> +#include <vendorcode/google/chromeos/chromeos.h> + +/* Return the board id for the current variant board. */ +uint8_t variant_board_id(void); + +/* The next set of functions return the gpio table and fill in the number of + * entries for each table. */ +const struct pad_config *variant_gpio_table(size_t *num); +const struct pad_config *variant_early_gpio_table(size_t *num); +const struct pad_config *variant_sleep_gpio_table(size_t *num); + +/* Baseboard default swizzle. Can be reused if swizzle is same. */ +extern const struct lpddr4_swizzle_cfg baseboard_lpddr4_swizzle; +/* Return LPDDR4 configuration structure. */ +const struct ddr_cfg *variant_ddr_config(void); +/* Return memory SKU for the board. */ +size_t variant_memory_sku(void); + +/* Return ChromeOS gpio table and fill in number of entries. */ +const struct cros_gpio *variant_cros_gpios(size_t *num); + +/* Seed the NHLT tables with the board specific information. */ +struct nhlt; +void variant_nhlt_init(struct nhlt *nhlt); + +uint8_t variant_get_spd_index(void); + +#endif /* BASEBOARD_VARIANTS_H */ diff --git a/src/mainboard/intel/common/mainboard.c b/src/mainboard/intel/common/mainboard.c new file mode 100644 index 0000000..6b474bb --- /dev/null +++ b/src/mainboard/intel/common/mainboard.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/acpi.h> +#include <variants.h> +#include <boardid.h> +#include <console/console.h> +#include <device/device.h> +#include <nhlt.h> +#include <soc/gpio.h> +#include <soc/nhlt.h> +#include <vendorcode/google/chromeos/chromeos.h> +#include <variant/ec.h> +#include <variant/gpio.h> + +void mainboard_ec_init(void); + +static void mainboard_init(device_t dev) +{ + size_t num; + const void *pads; + if (IS_ENABLED(CONFIG_MAINBOARD_GPIO_CONFIG)) { + pads = variant_gpio_table(&num); + gpio_configure_pads(pads, num); + } + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + mainboard_ec_init(); +} + +#if IS_ENABLED(CONFIG_MAINBOARD_WRITE_ACPI_TABLES) +static unsigned long mainboard_write_acpi_tables( + device_t device, unsigned long current, acpi_rsdp_t *rsdp) +{ + uintptr_t start_addr; + uintptr_t end_addr; + struct nhlt *nhlt; + + start_addr = current; + + nhlt = nhlt_init(); + + if (nhlt == NULL) + return start_addr; + + variant_nhlt_init(nhlt); + + end_addr = nhlt_soc_serialize(nhlt, start_addr); + + if (end_addr != start_addr) + acpi_add_table(rsdp, (void *)start_addr); + + return end_addr; +} +#endif + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +#if IS_ENABLED(CONFIG_MAINBOARD_WRITE_ACPI_TABLES) + dev->ops->write_acpi_tables = mainboard_write_acpi_tables; +#endif + dev->ops->acpi_inject_dsdt_generator = chromeos_dsdt_generator; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/intel/common/meminit_fsp2_atom.c b/src/mainboard/intel/common/meminit_fsp2_atom.c new file mode 100644 index 0000000..2315955 --- /dev/null +++ b/src/mainboard/intel/common/meminit_fsp2_atom.c @@ -0,0 +1,284 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Intel Corporation. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <arch/byteorder.h> +#include <console/console.h> +#include <fsp/api.h> +#include <soc/romstage.h> +#include <string.h> +#include <meminit.h> +#include <variants.h> +#include <smbios.h> +#include <memory_info.h> +#include <cbmem.h> +#include <fsp/util.h> + + +#define CONFIG_CHANNEL(log_num, phys_num, fspm_cfg, sku, chan) \ + fspm_cfg->Ch##phys_num##_DramDensity = \ + sku->ch##log_num##_rank_density; \ + fspm_cfg->Ch##phys_num##_RankEnable = \ + sku->ch##log_num##_dual_rank ? 0x1 : 0x3; \ + memcpy(&fspm_cfg->Ch##phys_num##_Bit_swizzling[0], \ + &(chan)->dqs[DDR_DQS0] ,DQ_BITS_PER_DQS); \ + memcpy(&fspm_cfg->Ch##phys_num##_Bit_swizzling[8], \ + &(chan)->dqs[DDR_DQS1],DQ_BITS_PER_DQS); \ + memcpy(&fspm_cfg->Ch##phys_num##_Bit_swizzling[16], \ + &(chan)->dqs[DDR_DQS2] ,DQ_BITS_PER_DQS); \ + memcpy(&fspm_cfg->Ch##phys_num##_Bit_swizzling[24], \ + &(chan)->dqs[DDR_DQS3],DQ_BITS_PER_DQS); + + +#define PRINT_CHANNEL_CONFIG(fspm_cfg, phys_num) \ +printk(BIOS_SPEW,"RankEnable : %x\n", \ + fspm_cfg->Ch##phys_num##_RankEnable); \ +printk(BIOS_SPEW,"DeviceWidth : %x\n", \ + fspm_cfg->Ch##phys_num##_DeviceWidth); \ +printk(BIOS_SPEW,"DramDensity : %x\n", \ + fspm_cfg->Ch##phys_num##_DramDensity); \ +printk(BIOS_SPEW,"Option : %x\n", \ + fspm_cfg->Ch##phys_num##_Option); \ +printk(BIOS_SPEW,"OdtConfig : %x\n", \ + fspm_cfg->Ch##phys_num##_OdtConfig); \ +printk(BIOS_SPEW,"TristateClk1 : %x\n", \ + fspm_cfg->Ch##phys_num##_TristateClk1); \ +printk(BIOS_SPEW,"Mode2N : %x\n", \ + fspm_cfg->Ch##phys_num##_Mode2N); \ +printk(BIOS_SPEW,"OdtLevels : %x\n", \ + fspm_cfg->Ch##phys_num##_OdtLevels); \ +{ \ +int i; \ + printk(BIOS_SPEW,"Bit_swizzling:\n"); \ + for(i=0; i < 32; i++) \ + { \ + printk(BIOS_SPEW," %02d ", \ + fspm_cfg->Ch##phys_num##_Bit_swizzling[i]); \ + if((i) && (i%8) == 7) \ + printk(BIOS_SPEW,"\n"); \ + } \ + printk(BIOS_SPEW,"\n"); \ +} + +__attribute__((weak)) void override_ddr_defaults(FSP_M_CONFIG *cfg) +{ + return; +} + +static void set_ddr_defaults(FSP_M_CONFIG *cfg) +{ + /* Enable memory down BGA since it's the only LPDDR4 packaging. */ + cfg->Package = 1; + cfg->MemoryDown = 1; + + cfg->ScramblerSupport = 1; + cfg->ChannelHashMask = 0x36; + cfg->SliceHashMask = 0x9; + cfg->InterleavedMode = 2; + cfg->ChannelsSlicesEnable = 0; + cfg->MinRefRate2xEnable = 0; + cfg->DualRankSupportEnable = 1; + /* Don't enforce a memory size limit. */ + cfg->MemorySizeLimit = 0; + /* Use a 2GiB I/O hole -- field is in MiB units. */ + cfg->LowMemoryMaxValue = 2 * (GiB/MiB); + /* No restrictions on memory above 4GiB */ + cfg->HighMemoryMaxValue = 0; + + /* Always default to attempt to use saved training data. */ + cfg->DisableFastBoot = 0; + + /* memory down so no SPD addresses. */ + cfg->DIMM0SPDAddress = 0; + cfg->DIMM1SPDAddress = 0; + + /* Clear all the rank enables. */ + cfg->Ch0_RankEnable = 0x0; + cfg->Ch1_RankEnable = 0x0; + cfg->Ch2_RankEnable = 0x0; + cfg->Ch3_RankEnable = 0x0; + + /* + * Set the device width to x16 which is half a LPDDR4 module as that's + * what the reference code expects. + */ + cfg->Ch0_DeviceWidth = 0x1; + cfg->Ch1_DeviceWidth = 0x1; + cfg->Ch2_DeviceWidth = 0x1; + cfg->Ch3_DeviceWidth = 0x1; + + /* + * Enable bank hashing (bit 1) and rank interleaving (bit 0) with + * a 1KiB address mapping (bits 5:4). + */ + cfg->Ch0_Option = 0x3; + cfg->Ch1_Option = 0x3; + cfg->Ch2_Option = 0x3; + cfg->Ch3_Option = 0x3; + + /* Weak on-die termination. */ + cfg->Ch0_OdtConfig = 0; + cfg->Ch1_OdtConfig = 0; + cfg->Ch2_OdtConfig = 0; + cfg->Ch3_OdtConfig = 0; + override_ddr_defaults(cfg); +} + +static void set_ddr_profile(FSP_M_CONFIG *cfg, int speed) +{ + uint8_t profile; + + switch (speed) { + case LP4_SPEED_1600: + profile = 0x9; + break; + case LP4_SPEED_2133: + profile = 0xa; + break; + case LP4_SPEED_2400: + profile = 0xb; + break; + default: + printk(BIOS_WARNING, "Invalid DDR speed: %d\n", speed); + /* Set defaults. */ + speed = LP4_SPEED_1600; + profile = 0x9; + } + + printk(BIOS_INFO, "DDR speed is %dMHz\n", speed); + cfg->Profile = profile; +} + +void soc_display_memory_init_params(FSP_M_CONFIG *fspm_cfg) +{ + printk(BIOS_SPEW, "UPD values for MemoryInit:\n"); + printk(BIOS_SPEW, "Channel0:\n"); + PRINT_CHANNEL_CONFIG(fspm_cfg, 0); + printk(BIOS_SPEW, "Channel1:\n"); + PRINT_CHANNEL_CONFIG(fspm_cfg, 1); + printk(BIOS_SPEW, "Channel2:\n"); + PRINT_CHANNEL_CONFIG(fspm_cfg, 2); + printk(BIOS_SPEW, "Channel3:\n"); + PRINT_CHANNEL_CONFIG(fspm_cfg, 3); + +} + +__attribute__((weak)) void mainboard_memory_init_params(FSPM_UPD *mupd) +{ + FSP_M_CONFIG *fspm_cfg = &mupd->FspmConfig; + const struct ddr_cfg *mem_cfg = variant_ddr_config(); + size_t sku_id = variant_memory_sku(); + const struct ddr_sku *sku = &mem_cfg->skus[sku_id]; + const struct ddr_swizzle_cfg *scfg= mem_cfg->swizzle_config; + + set_ddr_defaults(fspm_cfg); + set_ddr_profile(fspm_cfg, sku->speed); + if (sku->ch0_rank_density) { + CONFIG_CHANNEL(0, 0, fspm_cfg, sku, + &scfg->phys[DDR_PHYS_CH0A] ); + CONFIG_CHANNEL(0, 1, fspm_cfg, sku, + &scfg->phys[DDR_PHYS_CH0B] ); + } + if (sku->ch1_rank_density) { + CONFIG_CHANNEL(1, 2, fspm_cfg, sku, + &scfg->phys[DDR_PHYS_CH1A] ); + CONFIG_CHANNEL(1, 3, fspm_cfg, sku, + &scfg->phys[DDR_PHYS_CH1B] ); + } + //cfg->PeriodicRetrainingDisable = sku->disable_periodic_retraining; + soc_display_memory_init_params(fspm_cfg); +} + +void mainboard_save_dimm_info(void) +{ + const struct ddr_cfg *cfg = variant_ddr_config(); + size_t mem_sku = variant_memory_sku(); + int channel, dimm, dimm_max, index; + size_t hob_size; + const DIMM_INFO *src_dimm; + struct dimm_info *dest_dimm; + struct memory_info *mem_info; + const CHANNEL_INFO *channel_info; + const FSP_SMBIOS_MEMORY_INFO *memory_info_hob; + + if (mem_sku >= cfg->num_skus) { + printk(BIOS_ERR, "Too few LPDDR4 SKUs: 0x%zx/0x%zx\n", + mem_sku, cfg->num_skus); + return; + } + + memory_info_hob = fsp_find_smbios_memory_info(&hob_size); + + /* + * Allocate CBMEM area for DIMM information used to populate SMBIOS + * table 17 + */ + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); + if (mem_info == NULL) { + printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); + return; + } + memset(mem_info, 0, sizeof(*mem_info)); + + /* Describe the first N DIMMs in the system */ + index = 0; + dimm_max = ARRAY_SIZE(mem_info->dimm); + for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) { + if (index >= dimm_max) + break; + channel_info = &memory_info_hob->ChannelInfo[channel]; + for (dimm = 0; dimm < channel_info->DimmCount; dimm++) { + if (index >= dimm_max) + break; + src_dimm = &channel_info->DimmInfo[dimm]; + dest_dimm = &mem_info->dimm[index]; + + if (!src_dimm->SizeInMb) + continue; + + /* Populate the DIMM information */ + dest_dimm->dimm_size = src_dimm->SizeInMb; + dest_dimm->ddr_type = memory_info_hob->MemoryType; + dest_dimm->ddr_frequency = + memory_info_hob->MemoryFrequencyInMHz; + dest_dimm->channel_num = channel_info->ChannelId; + dest_dimm->dimm_num = src_dimm->DimmId; + strncpy((char *)dest_dimm->module_part_number, + cfg->skus[mem_sku].part_num, + sizeof(dest_dimm->module_part_number)); + + switch (memory_info_hob->DataWidth) { + case 8: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_8; + break; + case 16: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_16; + break; + case 32: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_32; + break; + case 64: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_64; + break; + case 128: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_128; + break; + default: + printk(BIOS_ERR, "Incorrect DIMM Data Width"); + } + index++; + } + } + mem_info->dimm_cnt = index; + printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt); +} diff --git a/src/mainboard/intel/common/meminit_fsp2_core.c b/src/mainboard/intel/common/meminit_fsp2_core.c new file mode 100644 index 0000000..2d894a7 --- /dev/null +++ b/src/mainboard/intel/common/meminit_fsp2_core.c @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Intel Corporation. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/byteorder.h> +#include <cbfs.h> +#include <console/console.h> +#include <fsp/api.h> +#include <soc/romstage.h> +#include <string.h> +#include <spd_bin.h> + +extern const uint8_t dq_map[][]; +extern const uint8_t dqs_map[][]; +extern const uint8_t rcomp_resistor[]; +extern const uint8_t rcomp_target[]; +extern const uint8_t dq_pins_interleaved; + +__attribute__((weak)) void mainboard_memory_init_params(FSPM_UPD *mupd) +{ + FSP_M_CONFIG *mem_cfg; + mem_cfg = &mupd->FspmConfig; + u8 spd_index = variant_get_spd_index(); + + printk(BIOS_INFO, "SPD index %d\n", spd_index); + + memcpy(&mem_cfg->DqByteMapCh0, dq_map, sizeof(dq_map)); + memcpy(&mem_cfg->DqsMapCpu2DramCh0, dqs_map, sizeof(dqs_map)); + memcpy(&mem_cfg->RcompResistor, rcomp_resistor, sizeof(rcomp_resistor)); + memcpy(&mem_cfg->RcompTarget, rcomp_target, sizeof(rcomp_target)); + + mem_cfg->DqPinsInterleaved = dq_pins_interleaved; + + if (IS_ENABLED(CONFIG_HAVE_SPD_BIN)) { + struct region_device spd_rdev; + + if (get_spd_cbfs_rdev(&spd_rdev, spd_index) < 0) + die("spd.bin not found\n"); + mem_cfg->MemorySpdDataLen = region_device_sz(&spd_rdev); + /* Memory leak is ok since we have memory mapped boot media */ + mem_cfg->MemorySpdPtr00 = (uintptr_t)rdev_mmap_full(&spd_rdev); + } else if (IS_ENABLED(CONFIG_HAVE_SPD)) { + struct spd_block blk; + + get_spd_smbus(&blk); + mem_cfg->MemorySpdDataLen = blk.len; + mem_cfg->MemorySpdPtr00 = (u32)blk.spd_array[0]; + } + else { + die("spd data not found\n"); + } + mem_cfg->MemorySpdPtr10 = mem_cfg->MemorySpdPtr00; +} diff --git a/src/mainboard/intel/common/ramstage.c b/src/mainboard/intel/common/ramstage.c new file mode 100644 index 0000000..b3062cb --- /dev/null +++ b/src/mainboard/intel/common/ramstage.c @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2016 Intel Corporation + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <bootstate.h> +#include <console/console.h> +#include <device/i2c.h> +#include <soc/ramstage.h> +#include <variant/gpio.h> + +__attribute__((weak)) +void variant_mainboard_silicon_init_params(FSP_SIL_UPD *params) +{ + return; +} + +void mainboard_silicon_init_params(FSP_SIL_UPD *params) +{ + variant_mainboard_silicon_init_params(params); +} + +__attribute__((weak)) void dev_init_exit(void *unused) +{ + /* add any board specific init here which needs to be run after + BS_POST_DEVICE */ + return; +} + +BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, dev_init_exit, NULL); diff --git a/src/mainboard/intel/common/smihandler.c b/src/mainboard/intel/common/smihandler.c new file mode 100644 index 0000000..8cfa61e --- /dev/null +++ b/src/mainboard/intel/common/smihandler.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2016 Intel Corp. + * + * 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/acpi.h> +#include <variants.h> +#include <cpu/x86/smm.h> +#include <ec/google/chromeec/smm.h> +#include <soc/pm.h> +#include <soc/smm.h> +#include <soc/gpio.h> +#include "include/ec.h" +#include <variant/ec.h> +#include <variant/gpio.h> + +void mainboard_smi_gpi_handler(const struct gpi_status *sts) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + if (gpi_status_get(sts, EC_SMI_GPI)) + chromeec_smi_process_events(); +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + const struct pad_config *pads; + size_t num; + + pads = variant_sleep_gpio_table(&num); + gpio_configure_pads(pads, num); + + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + chromeec_smi_sleep(slp_typ, MAINBOARD_EC_S3_WAKE_EVENTS, + MAINBOARD_EC_S5_WAKE_EVENTS); +} + +int mainboard_smi_apmc(u8 apmc) +{ + if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) + chromeec_smi_apmc(apmc, MAINBOARD_EC_SCI_EVENTS, + MAINBOARD_EC_SMI_EVENTS); + return 0; +}