From 1fa6305fd605635781b66abd5c6170ee29624743 Mon Sep 17 00:00:00 2001 From: Bernhard Messerklinger Date: Mon, 18 May 2020 12:33:34 +0200 Subject: [PATCH] x86: apl: Use devicetree for FSP-M configuration A the moment the FSP-M configuration is a mix of hard coded values and devicetree properties. This patch makes FSP-M full configurable from devicetree by adding binding properties for all FSP-M parameters. Co-developed-by: Wolfgang Wallner Signed-off-by: Wolfgang Wallner Signed-off-by: Bernhard Messerklinger Reviewed-by: Simon Glass Tested-by: Simon Glass (Tested on coral) [sjg: Fix a build error for coral] Signed-off-by: Simon Glass [bmeng: Add __maybe_unused to fsp_update_config_from_dtb()] Signed-off-by: Bin Meng --- arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/fsp_bindings.c | 616 ++++++++++++++++++ arch/x86/cpu/apollolake/fsp_m.c | 169 +---- arch/x86/dts/chromebook_coral.dts | 38 +- .../asm/arch-apollolake/fsp/fsp_m_upd.h | 168 +++++ .../asm/arch-apollolake/fsp_bindings.h | 96 +++ .../fsp/fsp2/apollolake/fsp-m.txt | 320 +++++++++ 7 files changed, 1244 insertions(+), 164 deletions(-) create mode 100644 arch/x86/cpu/apollolake/fsp_bindings.c create mode 100644 arch/x86/include/asm/arch-apollolake/fsp_bindings.h create mode 100644 doc/device-tree-bindings/fsp/fsp2/apollolake/fsp-m.txt diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 578e15c4bf..3aa2a55676 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -10,6 +10,7 @@ obj-y += cpu_common.o ifndef CONFIG_TPL_BUILD obj-y += cpu.o obj-y += punit.o +obj-y += fsp_bindings.o ifdef CONFIG_SPL_BUILD obj-y += fsp_m.o endif diff --git a/arch/x86/cpu/apollolake/fsp_bindings.c b/arch/x86/cpu/apollolake/fsp_bindings.c new file mode 100644 index 0000000000..6b97060b6d --- /dev/null +++ b/arch/x86/cpu/apollolake/fsp_bindings.c @@ -0,0 +1,616 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 B&R Industrial Automation GmbH - http://www.br-automation.com + */ + +#include +#include +#include +#include + +/** + * read_u8_prop() - Read an u8 property from devicetree (scalar or array) + * @node: Valid node reference to read property from + * @name: Name of the property to read from + * @count: If the property is expected to be an array, this is the + * number of expected elements + * Set to 0 if the property is expected to be a scalar + * @dst: Pointer to destination of where to save the value(s) read + * from devicetree + */ +static void read_u8_prop(ofnode node, char *name, size_t count, u8 *dst) +{ + u32 tmp; + const u8 *buf; + int ret; + + if (count == 0) { + ret = ofnode_read_u32(node, name, &tmp); + if (ret == 0) + *dst = tmp; + } else { + buf = ofnode_read_u8_array_ptr(node, name, count); + if (buf) + memcpy(dst, buf, count); + } +} + +/** + * read_u16_prop() - Read an u16 property from devicetree (scalar or array) + * @node: Valid node reference to read property from + * @name: Name of the property to read from + * @count: If the property is expected to be an array, this is the + * number of expected elements + * Set to 0 if the property is expected to be a scalar + * @dst: Pointer to destination of where to save the value(s) read + * from devicetree + * @return 0 on success, -ve on error + */ +static int read_u16_prop(ofnode node, char *name, size_t count, u16 *dst) +{ + u32 tmp; + u32 buf[32]; + int ret; + + if (ARRAY_SIZE(buf) < count) { + debug("ERROR: %s buffer to small!\n", __func__); + return -ENOSPC; + } + + if (count == 0) { + ret = ofnode_read_u32(node, name, &tmp); + if (ret == 0) + *dst = tmp; + } else { + ret = ofnode_read_u32_array(node, name, buf, count); + if (ret == 0) + for (int i = 0; i < count; i++) + dst[i] = buf[i]; + } + + return 0; +} + +/** + * read_u32_prop() - Read an u32 property from devicetree (scalar or array) + * @node: Valid node reference to read property from + * @name: Name of the property to read from + * @count: If the property is expected to be an array, this is the + * number of expected elements + * set to 0 if the property is expected to be a scalar + * @dst: Pointer to destination of where to save the value(s) read + * from devicetree + */ +static void read_u32_prop(ofnode node, char *name, size_t count, u32 *dst) +{ + if (count == 0) + ofnode_read_u32(node, name, dst); + else + ofnode_read_u32_array(node, name, dst, count); +} + +/** + * read_string_prop() - Read a string property from devicetree + * @node: Valid node reference to read property from + * @name: Name of the property to read from + * @count: Size of the destination buffer + * @dst: Pointer to destination of where to save the values read + * from devicetree + */ +static void read_string_prop(ofnode node, char *name, size_t count, char *dst) +{ + const char *string_buf; + + if (count > 0) { + string_buf = ofnode_read_string(node, name); + if (string_buf) + strlcpy(dst, string_buf, count); + } +} + +/** + * read_swizzle_prop() - Read a swizzle property from devicetree + * @node: Valid node reference to read property from + * @name: Name of the property to read from + * @count: Number of elements in the swizzle configuration + * @dst: pointer to destination of where to save the values read + * from devicetree + */ +static void read_swizzle_prop(ofnode node, char *name, size_t count, u8 *dst) +{ + const struct lpddr4_chan_swizzle_cfg *sch; + /* Number of bytes to copy per DQS */ + const size_t sz = DQ_BITS_PER_DQS; + const struct lpddr4_swizzle_cfg *swizzle_cfg; + + swizzle_cfg = (const struct lpddr4_swizzle_cfg *) + ofnode_read_u8_array_ptr(node, name, count); + + if (!swizzle_cfg) + return; + /* + * CH0_DQB byte lanes in the bit swizzle configuration field are + * not 1:1. The mapping within the swizzling field is: + * indices [0:7] - byte lane 1 (DQS1) DQ[8:15] + * indices [8:15] - byte lane 0 (DQS0) DQ[0:7] + * indices [16:23] - byte lane 3 (DQS3) DQ[24:31] + * indices [24:31] - byte lane 2 (DQS2) DQ[16:23] + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH0B]; + memcpy(&dst[0 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz); + memcpy(&dst[1 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz); + memcpy(&dst[2 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz); + memcpy(&dst[3 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz); + + /* + * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH0A]; + memcpy(&dst[4 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz); + memcpy(&dst[5 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz); + memcpy(&dst[6 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz); + memcpy(&dst[7 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz); + + sch = &swizzle_cfg->phys[LP4_PHYS_CH1B]; + memcpy(&dst[8 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz); + memcpy(&dst[9 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz); + memcpy(&dst[10 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz); + memcpy(&dst[11 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz); + + /* + * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. + */ + sch = &swizzle_cfg->phys[LP4_PHYS_CH1A]; + memcpy(&dst[12 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS0], sz); + memcpy(&dst[13 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS1], sz); + memcpy(&dst[14 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS2], sz); + memcpy(&dst[15 * DQ_BITS_PER_DQS], &sch->dqs[LP4_DQS3], sz); +} + +/** + * fsp_update_config_from_dtb() - Read FSP config from devicetree node + * @node: Valid node reference to read property from + * @cfg: Pointer to FSP config structure + * @fsp_bindings: Binding describing which devicetree properties should + * be stored where in the FSP configuration structure + * The end of the list is declared by a NULL pointer in propname + * @return 0 on success, -ve on error + * + * This function reads the configuration for FSP from the provided + * devicetree node and saves it in the FSP configuration structure. + * Configuration options that are not present in the devicetree are + * left at their current value. + */ +__maybe_unused +static int fsp_update_config_from_dtb(ofnode node, u8 *cfg, + const struct fsp_binding *fsp_bindings) +{ + const struct fsp_binding *fspb; + int ret; + + for (int i = 0; fsp_bindings[i].propname; i++) { + fspb = &fsp_bindings[i]; + + switch (fspb->type) { + case FSP_UINT8: + read_u8_prop(node, fspb->propname, fspb->count, + &cfg[fspb->offset]); + break; + case FSP_UINT16: + ret = read_u16_prop(node, fspb->propname, fspb->count, + (u16 *)&cfg[fspb->offset]); + if (ret) + return ret; + break; + case FSP_UINT32: + read_u32_prop(node, fspb->propname, fspb->count, + (u32 *)&cfg[fspb->offset]); + break; + case FSP_STRING: + read_string_prop(node, fspb->propname, fspb->count, + (char *)&cfg[fspb->offset]); + break; + case FSP_LPDDR4_SWIZZLE: + read_swizzle_prop(node, fspb->propname, fspb->count, + &cfg[fspb->offset]); + break; + } + } + + return 0; +} + +#if defined(CONFIG_SPL_BUILD) +const struct fsp_binding fsp_m_bindings[] = { + { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, serial_debug_port_address), + .propname = "fspm,serial-debug-port-address", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, serial_debug_port_type), + .propname = "fspm,serial-debug-port-type", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, serial_debug_port_device), + .propname = "fspm,serial-debug-port-device", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, serial_debug_port_stride_size), + .propname = "fspm,serial-debug-port-stride-size", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, mrc_fast_boot), + .propname = "fspm,mrc-fast-boot", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, igd), + .propname = "fspm,igd", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, igd_dvmt50_pre_alloc), + .propname = "fspm,igd-dvmt50-pre-alloc", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, igd_aperture_size), + .propname = "fspm,igd-aperture-size", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, gtt_size), + .propname = "fspm,gtt-size", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, primary_video_adaptor), + .propname = "fspm,primary-video-adaptor", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, package), + .propname = "fspm,package", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, profile), + .propname = "fspm,profile", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, memory_down), + .propname = "fspm,memory-down", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, ddr3_l_page_size), + .propname = "fspm,ddr3-l-page-size", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, ddr3_lasr), + .propname = "fspm,ddr3-lasr", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, scrambler_support), + .propname = "fspm,scrambler-support", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, interleaved_mode), + .propname = "fspm,interleaved-mode", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, channel_hash_mask), + .propname = "fspm,channel-hash-mask", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, slice_hash_mask), + .propname = "fspm,slice-hash-mask", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, channels_slices_enable), + .propname = "fspm,channels-slices-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, min_ref_rate2x_enable), + .propname = "fspm,min-ref-rate2x-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, dual_rank_support_enable), + .propname = "fspm,dual-rank-support-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, rmt_mode), + .propname = "fspm,rmt-mode", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, memory_size_limit), + .propname = "fspm,memory-size-limit", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, low_memory_max_value), + .propname = "fspm,low-memory-max-value", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, high_memory_max_value), + .propname = "fspm,high-memory-max-value", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, disable_fast_boot), + .propname = "fspm,disable-fast-boot", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, dimm0_spd_address), + .propname = "fspm,dimm0-spd-address", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, dimm1_spd_address), + .propname = "fspm,dimm1-spd-address", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].rank_enable), + .propname = "fspm,ch0-rank-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].device_width), + .propname = "fspm,ch0-device-width", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].dram_density), + .propname = "fspm,ch0-dram-density", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].option), + .propname = "fspm,ch0-option", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].odt_config), + .propname = "fspm,ch0-odt-config", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].tristate_clk1), + .propname = "fspm,ch0-tristate-clk1", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].mode2_n), + .propname = "fspm,ch0-mode2-n", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[0].odt_levels), + .propname = "fspm,ch0-odt-levels", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].rank_enable), + .propname = "fspm,ch1-rank-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].device_width), + .propname = "fspm,ch1-device-width", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].dram_density), + .propname = "fspm,ch1-dram-density", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].option), + .propname = "fspm,ch1-option", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].odt_config), + .propname = "fspm,ch1-odt-config", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].tristate_clk1), + .propname = "fspm,ch1-tristate-clk1", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].mode2_n), + .propname = "fspm,ch1-mode2-n", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[1].odt_levels), + .propname = "fspm,ch1-odt-levels", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].rank_enable), + .propname = "fspm,ch2-rank-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].device_width), + .propname = "fspm,ch2-device-width", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].dram_density), + .propname = "fspm,ch2-dram-density", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].option), + .propname = "fspm,ch2-option", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].odt_config), + .propname = "fspm,ch2-odt-config", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].tristate_clk1), + .propname = "fspm,ch2-tristate-clk1", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].mode2_n), + .propname = "fspm,ch2-mode2-n", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[2].odt_levels), + .propname = "fspm,ch2-odt-levels", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].rank_enable), + .propname = "fspm,ch3-rank-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].device_width), + .propname = "fspm,ch3-device-width", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].dram_density), + .propname = "fspm,ch3-dram-density", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].option), + .propname = "fspm,ch3-option", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].odt_config), + .propname = "fspm,ch3-odt-config", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].tristate_clk1), + .propname = "fspm,ch3-tristate-clk1", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].mode2_n), + .propname = "fspm,ch3-mode2-n", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, chan[3].odt_levels), + .propname = "fspm,ch3-odt-levels", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, rmt_check_run), + .propname = "fspm,rmt-check-run", + }, { + .type = FSP_UINT16, + .offset = offsetof(struct fsp_m_config, + rmt_margin_check_scale_high_threshold), + .propname = "fspm,rmt-margin-check-scale-high-threshold", + }, { + .type = FSP_LPDDR4_SWIZZLE, + .offset = offsetof(struct fsp_m_config, ch_bit_swizzling), + .propname = "fspm,ch-bit-swizzling", + .count = SIZE_OF_MEMBER(struct fsp_m_config, ch_bit_swizzling) / + SIZE_OF_MEMBER(struct fsp_m_config, ch_bit_swizzling[0][0]) + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, msg_level_mask), + .propname = "fspm,msg-level-mask", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_pin_num), + .propname = "fspm,pre-mem-gpio-table-pin-num", + .count = ARRAY_SIZE_OF_MEMBER(struct fsp_m_config, + pre_mem_gpio_table_pin_num), + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_ptr), + .propname = "fspm,pre-mem-gpio-table-ptr", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pre_mem_gpio_table_entry_num), + .propname = "fspm,pre-mem-gpio-table-entry-num", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, enhance_port8xh_decoding), + .propname = "fspm,enhance-port8xh-decoding", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, spd_write_enable), + .propname = "fspm,spd-write-enable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, mrc_data_saving), + .propname = "fspm,mrc-data-saving", + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, oem_loading_base), + .propname = "fspm,oem-loading-base", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, oem_file_name), + .propname = "fspm,oem-file-name", + .count = ARRAY_SIZE_OF_MEMBER(struct fsp_m_config, oem_file_name), + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, mrc_boot_data_ptr), + .propname = "fspm,mrc-boot-data-ptr", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, e_mmc_trace_len), + .propname = "fspm,e-mmc-trace-len", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, skip_cse_rbp), + .propname = "fspm,skip-cse-rbp", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, npk_en), + .propname = "fspm,npk-en", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, fw_trace_en), + .propname = "fspm,fw-trace-en", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, fw_trace_destination), + .propname = "fspm,fw-trace-destination", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, recover_dump), + .propname = "fspm,recover-dump", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, msc0_wrap), + .propname = "fspm,msc0-wrap", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, msc1_wrap), + .propname = "fspm,msc1-wrap", + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, msc0_size), + .propname = "fspm,msc0-size", + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, msc1_size), + .propname = "fspm,msc1-size", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pti_mode), + .propname = "fspm,pti-mode", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pti_training), + .propname = "fspm,pti-training", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pti_speed), + .propname = "fspm,pti-speed", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, punit_mlvl), + .propname = "fspm,punit-mlvl", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, pmc_mlvl), + .propname = "fspm,pmc-mlvl", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, sw_trace_en), + .propname = "fspm,sw-trace-en", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, periodic_retraining_disable), + .propname = "fspm,periodic-retraining-disable", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, enable_reset_system), + .propname = "fspm,enable-reset-system", + }, { + .type = FSP_UINT8, + .offset = offsetof(struct fsp_m_config, enable_s3_heci2), + .propname = "fspm,enable-s3-heci2", + }, { + .type = FSP_UINT32, + .offset = offsetof(struct fsp_m_config, variable_nvs_buffer_ptr), + .propname = "fspm,variable-nvs-buffer-ptr", + }, { + .propname = NULL + } +}; + +int fsp_m_update_config_from_dtb(ofnode node, struct fsp_m_config *cfg) +{ + return fsp_update_config_from_dtb(node, (u8 *)cfg, fsp_m_bindings); +} +#endif diff --git a/arch/x86/cpu/apollolake/fsp_m.c b/arch/x86/cpu/apollolake/fsp_m.c index 56ce59dc70..1301100cd5 100644 --- a/arch/x86/cpu/apollolake/fsp_m.c +++ b/arch/x86/cpu/apollolake/fsp_m.c @@ -8,184 +8,27 @@ #include #include #include -#include -#include +#include #include #include -/* - * ODT settings: - * If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A and HIGH for ODT_B, - * choose ODT_A_B_HIGH_HIGH. If ODT PIN to LP4 DRAM is pulled HIGH for ODT_A - * and LOW for ODT_B, choose ODT_A_B_HIGH_LOW. - * - * Note that the enum values correspond to the interpreted UPD fields - * within Ch[3:0]_OdtConfig parameters. - */ -enum { - ODT_A_B_HIGH_LOW = 0 << 1, - ODT_A_B_HIGH_HIGH = 1 << 1, - N_WR_24 = 1 << 5, -}; - -/* - * LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation. - * There are four physical LPDDR4 channels, each 32-bits wide. There are two - * logical channels using two physical channels together to form a 64-bit - * interface to memory for each logical channel. - */ - -enum { - LP4_PHYS_CH0A, - LP4_PHYS_CH0B, - LP4_PHYS_CH1A, - LP4_PHYS_CH1B, - - LP4_NUM_PHYS_CHANNELS, -}; - -/* - * 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 { - LP4_DQS0, - LP4_DQS1, - LP4_DQS2, - LP4_DQS3, - - LP4_NUM_BYTE_LANES, - DQ_BITS_PER_DQS = 8, -}; - -/* Provide bit swizzling per DQS and byte swapping within a channel */ -struct lpddr4_chan_swizzle_cfg { - u8 dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS]; -}; - -struct lpddr4_swizzle_cfg { - struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS]; -}; - -static void setup_sdram(struct fsp_m_config *cfg, - const struct lpddr4_swizzle_cfg *swizzle_cfg) -{ - const struct lpddr4_chan_swizzle_cfg *sch; - /* Number of bytes to copy per DQS */ - const size_t sz = DQ_BITS_PER_DQS; - int chan; - - cfg->memory_down = 1; - cfg->scrambler_support = 1; - cfg->channel_hash_mask = 0x36; - cfg->slice_hash_mask = 9; - cfg->interleaved_mode = 2; - cfg->channels_slices_enable = 0; - cfg->min_ref_rate2x_enable = 0; - cfg->dual_rank_support_enable = 1; - - /* LPDDR4 is memory down so no SPD addresses */ - cfg->dimm0_spd_address = 0; - cfg->dimm1_spd_address = 0; - - for (chan = 0; chan < 4; chan++) { - struct fsp_ram_channel *ch = &cfg->chan[chan]; - - ch->rank_enable = 1; - ch->device_width = 1; - ch->dram_density = 2; - ch->option = 3; - ch->odt_config = ODT_A_B_HIGH_HIGH; - } - - /* - * CH0_DQB byte lanes in the bit swizzle configuration field are - * not 1:1. The mapping within the swizzling field is: - * indices [0:7] - byte lane 1 (DQS1) DQ[8:15] - * indices [8:15] - byte lane 0 (DQS0) DQ[0:7] - * indices [16:23] - byte lane 3 (DQS3) DQ[24:31] - * indices [24:31] - byte lane 2 (DQS2) DQ[16:23] - */ - sch = &swizzle_cfg->phys[LP4_PHYS_CH0B]; - memcpy(&cfg->ch_bit_swizzling[0][0], &sch->dqs[LP4_DQS1], sz); - memcpy(&cfg->ch_bit_swizzling[0][8], &sch->dqs[LP4_DQS0], sz); - memcpy(&cfg->ch_bit_swizzling[0][16], &sch->dqs[LP4_DQS3], sz); - memcpy(&cfg->ch_bit_swizzling[0][24], &sch->dqs[LP4_DQS2], sz); - - /* - * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. - */ - sch = &swizzle_cfg->phys[LP4_PHYS_CH0A]; - memcpy(&cfg->ch_bit_swizzling[1][0], &sch->dqs[LP4_DQS0], sz); - memcpy(&cfg->ch_bit_swizzling[1][8], &sch->dqs[LP4_DQS1], sz); - memcpy(&cfg->ch_bit_swizzling[1][16], &sch->dqs[LP4_DQS2], sz); - memcpy(&cfg->ch_bit_swizzling[1][24], &sch->dqs[LP4_DQS3], sz); - - sch = &swizzle_cfg->phys[LP4_PHYS_CH1B]; - memcpy(&cfg->ch_bit_swizzling[2][0], &sch->dqs[LP4_DQS1], sz); - memcpy(&cfg->ch_bit_swizzling[2][8], &sch->dqs[LP4_DQS0], sz); - memcpy(&cfg->ch_bit_swizzling[2][16], &sch->dqs[LP4_DQS3], sz); - memcpy(&cfg->ch_bit_swizzling[2][24], &sch->dqs[LP4_DQS2], sz); - - /* - * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. - */ - sch = &swizzle_cfg->phys[LP4_PHYS_CH1A]; - memcpy(&cfg->ch_bit_swizzling[3][0], &sch->dqs[LP4_DQS0], sz); - memcpy(&cfg->ch_bit_swizzling[3][8], &sch->dqs[LP4_DQS1], sz); - memcpy(&cfg->ch_bit_swizzling[3][16], &sch->dqs[LP4_DQS2], sz); - memcpy(&cfg->ch_bit_swizzling[3][24], &sch->dqs[LP4_DQS3], sz); -} - int fspm_update_config(struct udevice *dev, struct fspm_upd *upd) { struct fsp_m_config *cfg = &upd->config; struct fspm_arch_upd *arch = &upd->arch; + ofnode node; arch->nvs_buffer_ptr = NULL; prepare_mrc_cache(upd); arch->stack_base = (void *)0xfef96000; arch->boot_loader_tolum_size = 0; - arch->boot_mode = FSP_BOOT_WITH_FULL_CONFIGURATION; - cfg->serial_debug_port_type = 2; - cfg->serial_debug_port_device = 2; - cfg->serial_debug_port_stride_size = 2; - cfg->serial_debug_port_address = 0; - cfg->package = 1; - /* Don't enforce a memory size limit */ - cfg->memory_size_limit = 0; - cfg->low_memory_max_value = 2048; /* 2 GB */ - /* No restrictions on memory above 4GiB */ - cfg->high_memory_max_value = 0; + node = dev_ofnode(dev); + if (!ofnode_valid(node)) + return log_msg_ret("fsp-m settings", -ENOENT); - /* Always default to attempt to use saved training data */ - cfg->disable_fast_boot = 0; - - const u8 *swizzle_data; - - swizzle_data = dev_read_u8_array_ptr(dev, "lpddr4-swizzle", - LP4_NUM_BYTE_LANES * - DQ_BITS_PER_DQS * - LP4_NUM_PHYS_CHANNELS); - if (!swizzle_data) - return log_msg_ret("Cannot read swizzel data", -EINVAL); - - setup_sdram(cfg, (struct lpddr4_swizzle_cfg *)swizzle_data); - - cfg->pre_mem_gpio_table_ptr = 0; - - cfg->profile = 0xb; - cfg->msg_level_mask = 0; - - /* other */ - cfg->skip_cse_rbp = 1; - cfg->periodic_retraining_disable = 0; - cfg->enable_s3_heci2 = 0; - - return 0; + return fsp_m_update_config_from_dtb(node, cfg); } /* diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index d48ef3573e..a34e2d78cd 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -21,6 +21,7 @@ #include #include #include +#include / { model = "Google Coral"; @@ -436,7 +437,42 @@ PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */ >; - lpddr4-swizzle = /bits/ 8 < + fspm,package = ; + fspm,profile = ; + fspm,memory-down = ; + fspm,scrambler-support = <1>; + fspm,interleaved-mode = ; + fspm,channel-hash-mask = <0x36>; + fspm,slice-hash-mask = <0x9>; + fspm,dual-rank-support-enable = <1>; + fspm,low-memory-max-value = <2048>; + fspm,ch0-rank-enable = <1>; + fspm,ch0-device-width = ; + fspm,ch0-dram-density = ; + fspm,ch0-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch0-odt-config = ; + fspm,ch1-rank-enable = <1>; + fspm,ch1-device-width = ; + fspm,ch1-dram-density = ; + fspm,ch1-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch1-odt-config = ; + fspm,ch2-rank-enable = <1>; + fspm,ch2-device-width = ; + fspm,ch2-dram-density = ; + fspm,ch2-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch2-odt-config = ; + fspm,ch3-rank-enable = <1>; + fspm,ch3-device-width = ; + fspm,ch3-dram-density = ; + fspm,ch3-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch3-odt-config = ; + fspm,fspm,skip-cse-rbp = <1>; + + fspm,ch-bit-swizzling = /bits/ 8 < /* LP4_PHYS_CH0A */ /* DQA[0:7] pins of LPDDR4 module */ diff --git a/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h index 93bee5b2d1..a77964f30c 100644 --- a/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h +++ b/arch/x86/include/asm/arch-apollolake/fsp/fsp_m_upd.h @@ -7,6 +7,7 @@ #ifndef __ASM_ARCH_FSP_M_UDP_H #define __ASM_ARCH_FSP_M_UDP_H +#ifndef __ASSEMBLY__ #include #define FSP_DRAM_CHANNELS 4 @@ -119,5 +120,172 @@ struct __packed fspm_upd { u8 unused_upd_space2[158]; u16 upd_terminator; }; +#endif + +#define SERIAL_DEBUG_PORT_TYPE_NONE 0 +#define SERIAL_DEBUG_PORT_TYPE_IO 1 +#define SERIAL_DEBUG_PORT_TYPE_MMIO 2 + +#define SERIAL_DEBUG_PORT_DEVICE_UART0 0 +#define SERIAL_DEBUG_PORT_DEVICE_UART1 1 +#define SERIAL_DEBUG_PORT_DEVICE_UART2 2 +#define SERIAL_DEBUG_PORT_DEVICE_EXTERNAL 3 + +#define SERIAL_DEBUG_PORT_STRIDE_SIZE_1 0 +#define SERIAL_DEBUG_PORT_STRIDE_SIZE_4 2 + +#define IGD_DVMT_50_PRE_ALLOC_64M 0x02 +#define IGD_DVMT_50_PRE_ALLOC_96M 0x03 +#define IGD_DVMT_50_PRE_ALLOC_128M 0x04 +#define IGD_DVMT_50_PRE_ALLOC_160M 0x05 +#define IGD_DVMT_50_PRE_ALLOC_192M 0x06 +#define IGD_DVMT_50_PRE_ALLOC_224M 0x07 +#define IGD_DVMT_50_PRE_ALLOC_256M 0x08 +#define IGD_DVMT_50_PRE_ALLOC_288M 0x09 +#define IGD_DVMT_50_PRE_ALLOC_320M 0x0a +#define IGD_DVMT_50_PRE_ALLOC_352M 0x0b +#define IGD_DVMT_50_PRE_ALLOC_384M 0x0c +#define IGD_DVMT_50_PRE_ALLOC_416M 0x0d +#define IGD_DVMT_50_PRE_ALLOC_448M 0x0e +#define IGD_DVMT_50_PRE_ALLOC_480M 0x0f +#define IGD_DVMT_50_PRE_ALLOC_512M 0x10 + +#define IGD_APERTURE_SIZE_128M 0x1 +#define IGD_APERTURE_SIZE_256M 0x2 +#define IGD_APERTURE_SIZE_512M 0x3 + +#define GTT_SIZE_2M 1 +#define GTT_SIZE_4M 2 +#define GTT_SIZE_8M 3 + +#define PRIMARY_VIDEO_ADAPTER_AUTO 0 +#define PRIMARY_VIDEO_ADAPTER_IGD 2 +#define PRIMARY_VIDEO_ADAPTER_PCI 3 + +#define PACKAGE_SODIMM 0 +#define PACKAGE_BGA 1 +#define PACKAGE_BGA_MIRRORED 2 +#define PACKAGE_SODIMM_UDIMM_RANK_MIRRORED 3 + +#define PROFILE_WIO2_800_7_8_8 0x1 +#define PROFILE_WIO2_1066_9_10_10 0x2 +#define PROFILE_LPDDR3_1066_8_10_10 0x3 +#define PROFILE_LPDDR3_1333_10_12_12 0x4 +#define PROFILE_LPDDR3_1600_12_15_15 0x5 +#define PROFILE_LPDDR3_1866_14_17_17 0x6 +#define PROFILE_LPDDR3_2133_16_20_20 0x7 +#define PROFILE_LPDDR4_1066_10_10_10 0x8 +#define PROFILE_LPDDR4_1600_14_15_15 0x9 +#define PROFILE_LPDDR4_2133_20_20_20 0xa +#define PROFILE_LPDDR4_2400_24_22_22 0xb +#define PROFILE_LPDDR4_2666_24_24_24 0xc +#define PROFILE_LPDDR4_2933_28_27_27 0xd +#define PROFILE_LPDDR4_3200_28_29_29 0xe +#define PROFILE_DDR3_1066_6_6_6 0xf +#define PROFILE_DDR3_1066_7_7_7 0x10 +#define PROFILE_DDR3_1066_8_8_8 0x11 +#define PROFILE_DDR3_1333_7_7_7 0x12 +#define PROFILE_DDR3_1333_8_8_8 0x13 +#define PROFILE_DDR3_1333_9_9_9 0x14 +#define PROFILE_DDR3_1333_10_10_10 0x15 +#define PROFILE_DDR3_1600_8_8_8 0x16 +#define PROFILE_DDR3_1600_9_9_9 0x17 +#define PROFILE_DDR3_1600_10_10_10 0x18 +#define PROFILE_DDR3_1600_11_11_11 0x19 +#define PROFILE_DDR3_1866_10_10_10 0x1a +#define PROFILE_DDR3_1866_11_11_11 0x1b +#define PROFILE_DDR3_1866_12_12_12 0x1c +#define PROFILE_DDR3_1866_13_13_13 0x1d +#define PROFILE_DDR3_2133_11_11_11 0x1e +#define PROFILE_DDR3_2133_12_12_12 0x1f +#define PROFILE_DDR3_2133_13_13_13 0x20 +#define PROFILE_DDR3_2133_14_14_14 0x21 +#define PROFILE_DDR4_1333_10_10_10 0x22 +#define PROFILE_DDR4_1600_10_10_10 0x23 +#define PROFILE_DDR4_1600_11_11_11 0x24 +#define PROFILE_DDR4_1600_12_12_12 0x25 +#define PROFILE_DDR4_1866_12_12_12 0x26 +#define PROFILE_DDR4_1866_13_13_13 0x27 +#define PROFILE_DDR4_1866_14_14_14 0x28 +#define PROFILE_DDR4_2133_14_14_14 0x29 +#define PROFILE_DDR4_2133_15_15_15 0x2a +#define PROFILE_DDR4_2133_16_16_16 0x2b +#define PROFILE_DDR4_2400_15_15_15 0x2c +#define PROFILE_DDR4_2400_16_16_16 0x2d +#define PROFILE_DDR4_2400_17_17_17 0x2e +#define PROFILE_DDR4_2400_18_18_18 0x2f + +#define MEMORY_DOWN_NO 0 +#define MEMORY_DOWN_YES 1 +#define MEMORY_DOWN_MD_SODIMM 2 +#define MEMORY_DOWN_LPDDR4 3 + +#define DDR3L_PAGE_SIZE_1KB 1 +#define DDR3L_PAGE_SIZE_2KB 2 + +#define INTERLEAVED_MODE_DISABLE 0 +#define INTERLEAVED_MODE_ENABLE 2 + +#define RMT_MODE_DISABLE 0 +#define RMT_MODE_ENABLE 3 + +#define CHX_DEVICE_WIDTH_X8 0 +#define CHX_DEVICE_WIDTH_X16 1 +#define CHX_DEVICE_WIDTH_X32 2 +#define CHX_DEVICE_WIDTH_X64 3 + +#define CHX_DEVICE_DENSITY_4GB 0 +#define CHX_DEVICE_DENSITY_6GB 1 +#define CHX_DEVICE_DENSITY_8GB 2 +#define CHX_DEVICE_DENSITY_12GB 3 +#define CHX_DEVICE_DENSITY_16GB 4 +#define CHX_DEVICE_DENSITY_2GB 5 + +#define CHX_OPTION_RANK_INTERLEAVING 0x1 +#define CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE 0x2 +#define CHX_OPTION_CH1_CLK_DISABLE 0x4 +#define CHX_OPTION_ADDRESS_MAP_2KB 0x10 + +#define CHX_ODT_CONFIG_DDR3_RX_ODT 0x1 +#define CHX_ODT_CONFIG_DDR4_CA_ODT 0x2 +#define CHX_ODT_CONFIG_DDR3L_TX_ODT 0x10 + +#define CHX_MODE2N_AUTO 0 +#define CHX_MODE2N_FORCE 1 + +#define CHX_ODT_LEVELS_CONNECTED_TO_SOC 0x0 +#define CHX_ODT_LEVELS_HELD_HIGH 0x1 + +#define NPK_EN_DISABLE 0 +#define NPK_EN_ENABLE 1 +#define NPK_EN_DEBUGGER 2 +#define NPK_EN_AUTO 3 + +#define FW_TRACE_DESTINATION_NPK_TRACE_TO_MEMORY 1 +#define FW_TRACE_DESTINATION_NPK_TRACE_TO_DCI 2 +#define FW_TRACE_DESTINATION_NPK_NPK_TRACE_TO_BSSB 3 +#define FW_TRACE_DESTINATION_NPK_TRACE_TO_PTI 4 + +#define MSC_X_WRAP_0 0 +#define MSC_X_WRAP_1 1 + +#define MSC_X_SIZE_0M 0 +#define MSC_X_SIZE_1M 1 +#define MSC_X_SIZE_8M 2 +#define MSC_X_SIZE_64M 3 +#define MSC_X_SIZE_128M 4 +#define MSC_X_SIZE_256M 5 +#define MSC_X_SIZE_512M 6 +#define MSC_X_SIZE_1GB 7 + +#define PTI_MODE_0 0 +#define PTI_MODE_x4 1 +#define PTI_MODE_x8 2 +#define PTI_MODE_x12 3 +#define PTI_MODE_x16 4 + +#define PTI_SPEED_FULL 0 +#define PTI_SPEED_HALF 1 +#define PTI_SPEED_QUARTER 2 #endif diff --git a/arch/x86/include/asm/arch-apollolake/fsp_bindings.h b/arch/x86/include/asm/arch-apollolake/fsp_bindings.h new file mode 100644 index 0000000000..7f778ead46 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/fsp_bindings.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + * Copyright 2020 B&R Industrial Automation GmbH - http://www.br-automation.com + */ + +#ifndef __ASM_ARCH_FSP_BINDINGS_H +#define __ASM_ARCH_FSP_BINDINGS_H + +#include + +#define ARRAY_SIZE_OF_MEMBER(s, m) (ARRAY_SIZE((((s *)0)->m))) +#define SIZE_OF_MEMBER(s, m) (sizeof((((s *)0)->m))) + +enum conf_type { + FSP_UINT8, + FSP_UINT16, + FSP_UINT32, + FSP_STRING, + FSP_LPDDR4_SWIZZLE, +}; + +/** + * struct fsp_binding - Binding describing devicetree/FSP relationships + * @offset: Offset within the FSP config structure + * @propname: Name of property to read + * @type: Type of the property to read + * @count: If the property is expected to be an array, this is the + * number of expected elements + * Set to 0 if the property is expected to be a scalar + * + * The struct fsp_binding is used to describe the relationship between + * values stored in devicetree and where they are placed in the FSP + * configuration structure. + */ +struct fsp_binding { + size_t offset; + char *propname; + enum conf_type type; + size_t count; +}; + +/* + * LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation. + * There are four physical LPDDR4 channels, each 32-bits wide. There are two + * logical channels using two physical channels together to form a 64-bit + * interface to memory for each logical channel. + */ + +enum { + LP4_PHYS_CH0A, + LP4_PHYS_CH0B, + LP4_PHYS_CH1A, + LP4_PHYS_CH1B, + + LP4_NUM_PHYS_CHANNELS, +}; + +/* + * 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 { + LP4_DQS0, + LP4_DQS1, + LP4_DQS2, + LP4_DQS3, + + LP4_NUM_BYTE_LANES, + DQ_BITS_PER_DQS = 8, +}; + +/* Provide bit swizzling per DQS and byte swapping within a channel */ +struct lpddr4_chan_swizzle_cfg { + u8 dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS]; +}; + +struct lpddr4_swizzle_cfg { + struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS]; +}; + +/** + * fsp_m_update_config_from_dtb() - Read FSP-M config from devicetree node + * @node: Valid node reference to read property from + * @cfg: Pointer to FSP-M config structure + * @return 0 on success, -ve on error + * + * This function reads the configuration for FSP-M from the provided + * devicetree node and saves it in the FSP-M configuration structure. + * Configuration options that are not present in the devicetree are + * left at their current value. + */ +int fsp_m_update_config_from_dtb(ofnode node, struct fsp_m_config *cfg); + +#endif diff --git a/doc/device-tree-bindings/fsp/fsp2/apollolake/fsp-m.txt b/doc/device-tree-bindings/fsp/fsp2/apollolake/fsp-m.txt new file mode 100644 index 0000000000..647a0862d4 --- /dev/null +++ b/doc/device-tree-bindings/fsp/fsp2/apollolake/fsp-m.txt @@ -0,0 +1,320 @@ +* Intel FSP-M configuration + +Several Intel platforms require the execution of the Intel FSP (Firmware +Support Package) for initialization. The FSP consists of multiple parts, one +of which is the FSP-M (Memory initialization phase). + +This binding applies to the FSP-M for the Intel Apollo Lake SoC. + +The FSP-M is available on Github [1]. +For detailed information on the FSP-M parameters see the documentation in +FSP/ApolloLakeFspBinPkg/Docs [2]. + +The properties of this binding are all optional. If no properties are set the +values of the FSP-M are used. + +[1] https://github.com/IntelFsp/FSP +[2] https://github.com/IntelFsp/FSP/tree/master/ApolloLakeFspBinPkg/Docs + +Optional properties: +- fspm,serial-debug-port-address: Debug Serial Port Base address +- fspm,serial-debug-port-type: Debug Serial Port Type + 0: NONE + 1: I/O + 2: MMIO (default) +- fspm,serial-debug-port-device: Serial Port Debug Device + 0: SOC UART0 + 1: SOC UART1 + 2: SOC UART2 (default) + 3: External Device +- fspm,serial-debug-port-stride-size: Debug Serial Port Stride Size + 0: 1 + 2: 4 (default) +- fspm,mrc-fast-boot: Memory Fast Boot +- fspm,igd: Integrated Graphics Device +- fspm,igd-dvmt50-pre-alloc: DVMT Pre-Allocated + 0x02: 64 MB (default) + 0x03: 96 MB + 0x04: 128 MB + 0x05: 160 MB + 0x06: 192 MB + 0x07: 224 MB + 0x08: 256 MB + 0x09: 288 MB + 0x0A: 320 MB + 0x0B: 352 MB + 0x0C: 384 MB + 0x0D: 416 MB + 0x0E: 448 MB + 0x0F: 480 MB + 0x10: 512 MB +- fspm,aperture-size: Aperture Size + 0x1: 128 MB (default) + 0x2: 256 MB + 0x3: 512 MB +- fspm,gtt-size: GTT Size + 0x1: 2 MB + 0x2: 4 MB + 0x3: 8 MB (default) +- fspm,primary-video-adaptor: Primary Display + 0x0: AUTO (default) + 0x2: IGD + 0x3: PCI +- fspm,package: Package + 0x0: SODIMM (default) + 0x1: BGA + 0x2: BGA mirrored (LPDDR3 only) + 0x3: SODIMM/UDIMM with Rank 1 Mirrored (DDR3L) +- fspm,profile: Profile + 0x01: WIO2_800_7_8_8 + 0x02: WIO2_1066_9_10_10 + 0x03: LPDDR3_1066_8_10_10 + 0x04: LPDDR3_1333_10_12_12 + 0x05: LPDDR3_1600_12_15_15 + 0x06: LPDDR3_1866_14_17_17 + 0x07: LPDDR3_2133_16_20_20 + 0x08: LPDDR4_1066_10_10_10 + 0x09: LPDDR4_1600_14_15_15 + 0x0A: LPDDR4_2133_20_20_20 + 0x0B: LPDDR4_2400_24_22_22 + 0x0C: LPDDR4_2666_24_24_24 + 0x0D: LPDDR4_2933_28_27_27 + 0x0E: LPDDR4_3200_28_29_29 + 0x0F: DDR3_1066_6_6_6 + 0x10: DDR3_1066_7_7_7 + 0x11: DDR3_1066_8_8_8 + 0x12: DDR3_1333_7_7_7 + 0x13: DDR3_1333_8_8_8 + 0x14: DDR3_1333_9_9_9 + 0x15: DDR3_1333_10_10_10 + 0x16: DDR3_1600_8_8_8 + 0x17: DDR3_1600_9_9_9 + 0x18: DDR3_1600_10_10_10 + 0x19: DDR3_1600_11_11_11 (default) + 0x1A: DDR3_1866_10_10_10 + 0x1B: DDR3_1866_11_11_11 + 0x1C: DDR3_1866_12_12_12 + 0x1D: DDR3_1866_13_13_13 + 0x1E: DDR3_2133_11_11_11 + 0x1F: DDR3_2133_12_12_12 + 0x20: DDR3_2133_13_13_13 + 0x21: DDR3_2133_14_14_14 + 0x22: DDR4_1333_10_10_10 + 0x23: DDR4_1600_10_10_10 + 0x24: DDR4_1600_11_11_11 + 0x25: DDR4_1600_12_12_12 + 0x26: DDR4_1866_12_12_12 + 0x27: DDR4_1866_13_13_13 + 0x28: DDR4_1866_14_14_14 + 0x29: DDR4_2133_14_14_14 + 0x2A: DDR4_2133_15_15_15 + 0x2B: DDR4_2133_16_16_16 + 0x2C: DDR4_2400_15_15_15 + 0x2D: DDR4_2400_16_16_16 + 0x2E: DDR4_2400_17_17_17 + 0x2F: DDR4_2400_18_18_18 +- fspm,memory-down: Memory Down + 0x0: No (default) + 0x1: Yes + 0x2: 1MD+SODIMM (for DDR3L only) ACRD + 0x3: 1x32 LPDDR4 +- fspm,ddr3l-page-size: DDR3LPageSize + 0x1: 1KB (default) + 0x2: 2KB +- fspm,ddr3-lasr: DDR3LASR +- fspm,scrambler-support: ScramblerSupport +- fspm,interleaved-mode: InterleavedMode +- fspm,channel-hash-mask: ChannelHashMask +- fspm,fspm,slice-hash-mask: SliceHashMask +- fspm,channels-slices-enable: ChannelsSlices +- fspm,min-ref-rate2x-enable: MinRefRate2x +- fspm,dual-rank-support-enable: DualRankSupport +- fspm,rmt-mode: RmtMode +- fspm,memory-size-limit: MemorySizeLimit +- fspm,low-memory-max-value: LowMemoryMaxValue +- fspm,high-memory-max-value: HighMemoryMaxValue +- fspm,disable-fast-boot: FastBoot +- fspm,dimm0-spd-address: DIMM0 SPD Address +- fspm,dimm1-spd-address: DIMM1 SPD Address +- fspm,chX-rank-enable: Must be set to enable rank (X = 0-3) +- fspm,chX-device-width: DRAM device width per DRAM channel (X = 0-3) + 0: x8 + 1: x16 + 2: x32 + 3: x64 +- fspm,chX-dram-density: Must specify the DRAM device density (X = 0-3) + 0: 4Gb + 1: 6Gb + 2: 8Gb + 3: 12Gb + 4: 16Gb + 5: 2Gb +- fspm,chX-option: Channel options (X = 0-3) +- fspm,chX-odt-config: Channel Odt Config (X = 0-3) +- fspm,chX-mode2-n: Force 2N Mode (X = 0-3) + 0x0: Auto + 0x1: Force 2N CMD Timing Mode +- fspm,chX-odt-levels: Channel Odt Levels (X = 0-3) + 0: ODT Connected to SoC + 1: ODT held high +- fspm,rmt-check-run: RmtCheckRun +- fspm,rmt-margin-check-scale-high-threshold: RmtMarginCheckScaleHighThreshold +- fspm,ch-bit-swizzling: Bit_swizzling +- fspm,msg-level-mask: MsgLevelMask +- fspm,pre-mem-gpio-table-pin-num: PreMem GPIO Pin Number for each table +- fspm,pre-mem-gpio-table-ptr: PreMem GPIO Table Pointer +- fspm,pre-mem-gpio-table-entry-num: PreMem GPIO Table Entry Number +- fspm,enhance-port8xh-decoding: Enhance the port 8xh decoding +- fspm,spd-write-enable: SPD Data Write +- fspm,mrc-data-saving: MRC Training Data Saving +- fspm,oem-loading-base: OEM File Loading Address +- fspm,oem-file-name: OEM File Name to Load +- fspm,mrc-boot-data-ptr: +- fspm,e-mmc-trace-len: eMMC Trace Length + 0x0: Long + 0x1: Short +- fspm,skip-cse-rbp: Skip CSE RBP to support zero sized IBB +- fspm,npk-en: Npk Enable + 0: Disable + 1: Enable + 2: Debugger + 3: Auto (default) +- fspm,fw-trace-en: FW Trace Enable +- fspm,fw-trace-destination: FW Trace Destination + 1: NPK_TRACE_TO_MEMORY + 2: NPK_TRACE_TO_DCI + 3: NPK_TRACE_TO_BSSB + 4: NPK_TRACE_TO_PTI (default) +- fspm,recover-dump: NPK Recovery Dump +- fspm,msc0-wrap: Memory Region 0 Buffer WrapAround + 0: n0-warp + 1: n1-warp (default) +- fspm,msc1-wrap: Memory Region 1 Buffer WrapAround + 0: n0-warp + 1: n1-warp (default) +- fspm,msc0-size: Memory Region 0 Buffer Size + 0: 0MB (default) + 1: 1MB + 2: 8MB + 3: 64MB + 4: 128MB + 5: 256MB + 6: 512MB + 7: 1GB +- fspm,msc1-size: Memory Region 1 Buffer Size + 0: 0MB (default) + 1: 1MB + 2: 8MB + 3: 64MB + 4: 128MB + 5: 256MB + 6: 512MB + 7: 1GB +- fspm,pti-mode: PTI Mode + 0: 0ff + 1: x4 (default) + 2: x8 + 3: x12 + 4: x16 +- fspm,pti-training: PTI Training + 0: off (default) + 1-6: 1-6 +- fspm,pti-speed: + 0: full + 1: half + 2: quarter (default) +- fspm,punit-mlvl: Punit Message Level + 0: + 1: (default) + 2-4: 2-4 +- fspm,pmc-mlvl: PMC Message Level + 0: + 1: (default) + 2-4: 2-4 +- fspm,sw-trace-en: SW Trace Enable +- fspm,periodic-retraining-disable: Periodic Retraining Disable +- fspm,enable-reset-system: Enable Reset System +- fspm,enable-s3-heci2: Enable HECI2 in S3 resume path +- fspm,variable-nvs-buffer-ptr: + +Example: + +&host_bridge { + fspm,package = ; + fspm,profile = ; + fspm,memory-down = ; + fspm,scrambler-support = <1>; + fspm,interleaved-mode = ; + fspm,channel-hash-mask = <0x36>; + fspm,slice-hash-mask = <0x9>; + fspm,low-memory-max-value = <2048>; + fspm,ch0-rank-enable = <1>; + fspm,ch0-device-width = ; + fspm,ch0-dram-density = ; + fspm,ch0-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch0-odt-config = ; + fspm,ch1-rank-enable = <1>; + fspm,ch1-device-width = ; + fspm,ch1-dram-density = ; + fspm,ch1-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch1-odt-config = ; + fspm,ch2-rank-enable = <1>; + fspm,ch2-device-width = ; + fspm,ch2-dram-density = ; + fspm,ch2-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch2-odt-config = ; + fspm,ch3-rank-enable = <1>; + fspm,ch3-device-width = ; + fspm,ch3-dram-density = ; + fspm,ch3-option = <(CHX_OPTION_RANK_INTERLEAVING | + CHX_OPTION_BANK_ADDRESS_HASHING_ENABLE)>; + fspm,ch3-odt-config = ; + fspm,fspm,skip-cse-rbp = <1>; + + fspm,ch-bit-swizzling = /bits/ 8 < + /* LP4_PHYS_CH0A */ + + /* DQA[0:7] pins of LPDDR4 module */ + 6 7 5 4 3 1 0 2 + /* DQA[8:15] pins of LPDDR4 module */ + 12 10 11 13 14 8 9 15 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 16 22 23 20 18 17 19 21 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 30 28 29 25 24 26 27 31 + + /* LP4_PHYS_CH0B */ + /* DQA[0:7] pins of LPDDR4 module */ + 7 3 5 2 6 0 1 4 + /* DQA[8:15] pins of LPDDR4 module */ + 9 14 12 13 10 11 8 15 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 20 22 23 16 19 17 18 21 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 28 24 26 27 29 30 31 25 + + /* LP4_PHYS_CH1A */ + + /* DQA[0:7] pins of LPDDR4 module */ + 2 1 6 7 5 4 3 0 + /* DQA[8:15] pins of LPDDR4 module */ + 11 10 8 9 12 15 13 14 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 17 23 19 16 21 22 20 18 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 31 29 26 25 28 27 24 30 + + /* LP4_PHYS_CH1B */ + + /* DQA[0:7] pins of LPDDR4 module */ + 4 3 7 5 6 1 0 2 + /* DQA[8:15] pins of LPDDR4 module */ + 15 9 8 11 14 13 12 10 + /* DQB[0:7] pins of LPDDR4 module with offset of 16 */ + 20 23 22 21 18 19 16 17 + /* DQB[7:15] pins of LPDDR4 module with offset of 16 */ + 25 28 30 31 26 27 24 29>; +}; -- 2.25.1