223 changes: 109 additions & 114 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -20,41 +20,6 @@
#include "haswell.h"
#include "chip.h"

/* Intel suggested latency times in units of 1024ns. */
#define C_STATE_LATENCY_CONTROL_0_LIMIT 0x42
#define C_STATE_LATENCY_CONTROL_1_LIMIT 0x73
#define C_STATE_LATENCY_CONTROL_2_LIMIT 0x91
#define C_STATE_LATENCY_CONTROL_3_LIMIT 0xe4
#define C_STATE_LATENCY_CONTROL_4_LIMIT 0x145
#define C_STATE_LATENCY_CONTROL_5_LIMIT 0x1ef

#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \
(((1 << ((base)*5)) * (limit)) / 1000)
#define C_STATE_LATENCY_FROM_LAT_REG(reg) \
C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \
(IRTL_1024_NS >> 10))

/*
* List of supported C-states in this processor. Only the ULT parts support C8,
* C9, and C10.
*/
enum {
C_STATE_C0, /* 0 */
C_STATE_C1, /* 1 */
C_STATE_C1E, /* 2 */
C_STATE_C3, /* 3 */
C_STATE_C6_SHORT_LAT, /* 4 */
C_STATE_C6_LONG_LAT, /* 5 */
C_STATE_C7_SHORT_LAT, /* 6 */
C_STATE_C7_LONG_LAT, /* 7 */
C_STATE_C7S_SHORT_LAT, /* 8 */
C_STATE_C7S_LONG_LAT, /* 9 */
C_STATE_C8, /* 10 */
C_STATE_C9, /* 11 */
C_STATE_C10, /* 12 */
NUM_C_STATES
};

#define MWAIT_RES(state, sub_state) \
{ \
.addrl = (((state) << 4) | (sub_state)), \
Expand Down Expand Up @@ -186,27 +151,6 @@ static const u8 power_limit_time_msr_to_sec[] = {
[0x11] = 128,
};

int haswell_family_model(void)
{
return cpuid_eax(1) & 0x0fff0ff0;
}

int haswell_stepping(void)
{
return cpuid_eax(1) & 0xf;
}

/* Dynamically determine if the part is ULT. */
int haswell_is_ult(void)
{
static int ult = -1;

if (ult < 0)
ult = !!(haswell_family_model() == HASWELL_FAMILY_ULT);

return ult;
}

/* The core 100MHz BCLK is disabled in deeper c-states. One needs to calibrate
* the 100MHz BCLK against the 24MHz BCLK to restore the clocks properly
* when a core is woken up. */
Expand Down Expand Up @@ -282,10 +226,39 @@ static u32 pcode_mailbox_read(u32 command)
return MCHBAR32(BIOS_MAILBOX_DATA);
}

static int pcode_mailbox_write(u32 command, u32 data)
{
if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n");
return -1;
}

MCHBAR32(BIOS_MAILBOX_DATA) = data;

/* Send command and start transaction */
MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY;

if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return -1;
}

return 0;
}

static void initialize_vr_config(void)
{
struct cpu_vr_config vr_config = { 0 };
msr_t msr;

const struct device *lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);

if (lapic && lapic->chip_info) {
const struct cpu_intel_haswell_config *conf = lapic->chip_info;

vr_config = conf->vr_config;
}

printk(BIOS_DEBUG, "Initializing VR config.\n");

/* Configure VR_CURRENT_CONFIG. */
Expand All @@ -295,7 +268,7 @@ static void initialize_vr_config(void)
msr.hi &= 0xc0000000;
msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A. */
msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A. */
msr.hi |= (0x0f << (32 - 32)); /* PSI1 threshold - 15A. */
msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A. */

if (haswell_is_ult())
msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */
Expand All @@ -315,24 +288,41 @@ static void initialize_vr_config(void)
msr.hi &= ~(1 << (51 - 32));
/* Enable decay mode on C-state entry. */
msr.hi |= (1 << (52 - 32));
/* Set the slow ramp rate */
if (haswell_is_ult()) {
/* Set the slow ramp rate to be fast ramp rate / 4 */
msr.hi &= ~(0x3 << (53 - 32));
msr.hi |= (0x01 << (53 - 32));
/* Configure the C-state exit ramp rate. */
if (vr_config.slow_ramp_rate_enable) {
/* Configured slow ramp rate. */
msr.hi |= ((vr_config.slow_ramp_rate_set & 0x3) << (53 - 32));
/* Set exit ramp rate to slow. */
msr.hi &= ~(1 << (50 - 32));
} else {
/* Fast ramp rate / 4. */
msr.hi |= (1 << (53 - 32));
}
}
/* Set MIN_VID (31:24) to allow CPU to have full control. */
msr.lo &= ~0xff000000;
msr.lo |= (vr_config.cpu_min_vid & 0xff) << 24;
wrmsr(MSR_VR_MISC_CONFIG, msr);

/* Configure VR_MISC_CONFIG2 MSR. */
if (haswell_is_ult()) {
msr = rdmsr(MSR_VR_MISC_CONFIG2);
msr.lo &= ~0xffff;
/* Allow CPU to control minimum voltage completely (15:8) and
* set the fast ramp voltage to 1110mV (0x6f in 10mV steps). */
msr.lo |= 0x006f;
wrmsr(MSR_VR_MISC_CONFIG2, msr);
}
if (!haswell_is_ult())
return;

msr = rdmsr(MSR_VR_MISC_CONFIG2);
msr.lo &= ~0xffff;
/* Allow CPU to control minimum voltage completely (15:8) and
set the fast ramp voltage in 10mV steps. */
if (cpu_family_model() == BROADWELL_FAMILY_ULT)
msr.lo |= 0x006a; /* 1.56V */
else
msr.lo |= 0x006f; /* 1.60V */
wrmsr(MSR_VR_MISC_CONFIG2, msr);

/* Set C9/C10 VCC Min */
pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
}

static void configure_pch_power_sharing(void)
Expand Down Expand Up @@ -403,8 +393,7 @@ void set_power_limits(u8 power_limit_1_time)
u8 power_limit_1_val;

if (power_limit_1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr))
power_limit_1_time = ARRAY_SIZE(power_limit_time_sec_to_msr)
- 1;
power_limit_1_time = ARRAY_SIZE(power_limit_time_sec_to_msr) - 1;

if (!(msr.lo & PLATFORM_INFO_SET_TDP))
return;
Expand Down Expand Up @@ -468,7 +457,9 @@ void set_power_limits(u8 power_limit_1_time)

static void configure_c_states(void)
{
msr_t msr;
msr_t msr = rdmsr(MSR_PLATFORM_INFO);

const bool timed_mwait_capable = !!(msr.hi & TIMED_MWAIT_SUPPORTED);

msr = rdmsr(MSR_PKG_CST_CONFIG_CONTROL);
msr.lo |= (1 << 30); // Package c-state Undemotion Enable
Expand All @@ -478,14 +469,12 @@ static void configure_c_states(void)
msr.lo |= (1 << 26); // C1 Auto Demotion Enable
msr.lo |= (1 << 25); // C3 Auto Demotion Enable
msr.lo &= ~(1 << 10); // Disable IO MWAIT redirection
/* The deepest package c-state defaults to factory-configured value. */
wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);

msr = rdmsr(MSR_PMG_IO_CAPTURE_BASE);
msr.lo &= ~0xffff;
msr.lo |= (get_pmbase() + 0x14); // LVL_2 base address
if (timed_mwait_capable)
msr.lo |= (1 << 31); // Timed MWAIT Enable

/* The deepest package c-state defaults to factory-configured value. */
wrmsr(MSR_PMG_IO_CAPTURE_BASE, msr);
wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);

msr = rdmsr(MSR_MISC_PWR_MGMT);
msr.lo &= ~(1 << 0); // Enable P-state HW_ALL coordination
Expand All @@ -512,26 +501,24 @@ static void configure_c_states(void)
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr);

/* Haswell ULT only supoprts the 3-5 latency response registers.*/
if (haswell_is_ult()) {
/* C-state Interrupt Response Latency Control 3 - package C8 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_3_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr);

/* C-state Interrupt Response Latency Control 4 - package C9 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_4_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr);

/* C-state Interrupt Response Latency Control 5 - package C10 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS |
C_STATE_LATENCY_CONTROL_5_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
}
/* Only Haswell ULT supports the 3-5 latency response registers */
if (!haswell_is_ult())
return;

/* C-state Interrupt Response Latency Control 3 - package C8 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr);

/* C-state Interrupt Response Latency Control 4 - package C9 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr);

/* C-state Interrupt Response Latency Control 5 - package C10 */
msr.hi = 0;
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
}

static void configure_thermal_target(void)
Expand Down Expand Up @@ -584,7 +571,10 @@ static void set_max_ratio(void)
perf_ctl.hi = 0;

/* Check for configurable TDP option */
if (cpu_config_tdp_levels()) {
if (get_turbo_state() == TURBO_ENABLED) {
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
perf_ctl.lo = (msr.lo & 0xff) << 8;
} else if (cpu_config_tdp_levels()) {
/* Set to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
perf_ctl.lo = (msr.lo & 0xff) << 8;
Expand All @@ -596,7 +586,7 @@ static void set_max_ratio(void)
wrmsr(IA32_PERF_CTL, perf_ctl);

printk(BIOS_DEBUG, "CPU: frequency set to %d\n",
((perf_ctl.lo >> 8) & 0xff) * HASWELL_BCLK);
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
}

static void configure_mca(void)
Expand All @@ -616,7 +606,7 @@ static void configure_mca(void)
}

/* All CPUs including BSP will run the following function. */
static void haswell_init(struct device *cpu)
static void cpu_core_init(struct device *cpu)
{
/* Clear out pending MCEs */
configure_mca();
Expand All @@ -643,9 +633,6 @@ static void haswell_init(struct device *cpu)
/* Set energy policy */
set_energy_perf_bias(ENERGY_POLICY_NORMAL);

/* Set Max Ratio */
set_max_ratio();

/* Enable Turbo */
enable_turbo();
}
Expand All @@ -661,10 +648,11 @@ static void pre_mp_init(void)

initialize_vr_config();

if (haswell_is_ult()) {
calibrate_24mhz_bclk();
configure_pch_power_sharing();
}
if (!haswell_is_ult())
return;

calibrate_24mhz_bclk();
configure_pch_power_sharing();
}

static int get_cpu_count(void)
Expand Down Expand Up @@ -700,6 +688,9 @@ static void per_cpu_smm_trigger(void)

static void post_mp_init(void)
{
/* Set Max Ratio */
set_max_ratio();

/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
global_smi_enable();
Expand All @@ -726,17 +717,21 @@ void mp_init_cpus(struct bus *cpu_bus)
}

static struct device_operations cpu_dev_ops = {
.init = haswell_init,
.init = cpu_core_init,
};

static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x306c1 }, /* Intel Haswell 4+2 A0 */
{ X86_VENDOR_INTEL, 0x306c2 }, /* Intel Haswell 4+2 B0 */
{ X86_VENDOR_INTEL, 0x306c3 }, /* Intel Haswell C0 */
{ X86_VENDOR_INTEL, 0x40650 }, /* Intel Haswell ULT B0 */
{ X86_VENDOR_INTEL, 0x40651 }, /* Intel Haswell ULT B1 */
{ X86_VENDOR_INTEL, 0x40660 }, /* Intel Crystal Well C0 */
{ X86_VENDOR_INTEL, 0x40661 }, /* Intel Crystal Well C1 */
{ X86_VENDOR_INTEL, CPUID_HASWELL_A0 },
{ X86_VENDOR_INTEL, CPUID_HASWELL_B0 },
{ X86_VENDOR_INTEL, CPUID_HASWELL_C0 },
{ X86_VENDOR_INTEL, CPUID_HASWELL_ULT_B0 },
{ X86_VENDOR_INTEL, CPUID_HASWELL_ULT_C0 },
{ X86_VENDOR_INTEL, CPUID_CRYSTALWELL_B0 },
{ X86_VENDOR_INTEL, CPUID_CRYSTALWELL_C0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_C0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_ULT_C0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_ULT_D0 },
{ X86_VENDOR_INTEL, CPUID_BROADWELL_ULT_E0 },
{ 0, 0 },
};

Expand Down
Expand Up @@ -2,10 +2,8 @@

#include <arch/cpu.h>
#include <console/console.h>
#include <cpu/intel/haswell/haswell.h>
#include <cpu/x86/msr.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/romstage.h>

void set_max_freq(void)
{
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/microcode/microcode_asm.S
Expand Up @@ -44,7 +44,7 @@
*/

.code32
.section .text
.section .init
.global update_bsp_microcode

update_bsp_microcode:
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/model_1067x/model_1067x_init.c
Expand Up @@ -264,9 +264,6 @@ static void model_1067x_init(struct device *cpu)
/* Test for TM2 only if EIST is available. */
const char tm2 = eist && (cpuid1.ecx & (1 << 8));

/* Turn on caching if we haven't already */
x86_enable_cache();

/* Print processor name */
fill_processor_name(processor_name);
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_1067x/mp_init.c
Expand Up @@ -33,7 +33,7 @@ static int get_cpu_count(void)
static void get_microcode_info(const void **microcode, int *parallel)
{
*microcode = microcode_patch;
*parallel = 1;
*parallel = !intel_ht_supported();
}

/* the SMRR enable and lock bit need to be set in IA32_FEATURE_CONTROL
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/model_106cx/model_106cx_init.c
Expand Up @@ -63,9 +63,6 @@ static void model_106cx_init(struct device *cpu)
{
char processor_name[49];

/* Turn on caching if we haven't already */
x86_enable_cache();

/* Print processor name */
fill_processor_name(processor_name);
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
Expand Down
85 changes: 4 additions & 81 deletions src/cpu/intel/model_2065x/acpi.c
Expand Up @@ -28,80 +28,9 @@ static int get_cores_per_package(void)
return cores;
}

static void generate_cstate_entries(acpi_cstate_t *cstates,
int c1, int c2, int c3)
{
int cstate_count = 0;

/* Count number of active C-states */
if (c1 > 0)
++cstate_count;
if (c2 > 0)
++cstate_count;
if (c3 > 0)
++cstate_count;
if (!cstate_count)
return;

acpigen_write_package(cstate_count + 1);
acpigen_write_byte(cstate_count);

/* Add an entry if the level is enabled */
if (c1 > 0) {
cstates[c1].ctype = 1;
acpigen_write_CST_package_entry(&cstates[c1]);
}
if (c2 > 0) {
cstates[c2].ctype = 2;
acpigen_write_CST_package_entry(&cstates[c2]);
}
if (c3 > 0) {
cstates[c3].ctype = 3;
acpigen_write_CST_package_entry(&cstates[c3]);
}

acpigen_pop_len();
}

static void generate_C_state_entries(void)
{
struct cpu_info *info;
struct cpu_driver *cpu;
struct device *lapic;
struct cpu_intel_model_2065x_config *conf = NULL;

/* Find the SpeedStep CPU in the device tree using magic APIC ID */
lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
if (!lapic)
return;
conf = lapic->chip_info;
if (!conf)
return;

/* Find CPU map of supported C-states */
info = cpu_info();
if (!info)
return;
cpu = find_cpu_driver(info->cpu);
if (!cpu || !cpu->cstates)
return;

acpigen_write_method("_CST", 0);

/* If running on AC power */
acpigen_emit_byte(0xa0); /* IfOp */
acpigen_write_len_f(); /* PkgLength */
acpigen_emit_namestring("PWRS");
acpigen_emit_byte(0xa4); /* ReturnOp */
generate_cstate_entries(cpu->cstates, conf->c1_acpower,
conf->c2_acpower, conf->c3_acpower);
acpigen_pop_len();

/* Else on battery power */
acpigen_emit_byte(0xa4); /* ReturnOp */
generate_cstate_entries(cpu->cstates, conf->c1_battery,
conf->c2_battery, conf->c3_battery);
acpigen_pop_len();
/* TODO */
}

static acpi_tstate_t tss_table_fine[] = {
Expand Down Expand Up @@ -195,15 +124,9 @@ static void generate_P_state_entries(int core, int cores_per_package)
msr = rdmsr(MSR_PLATFORM_INFO);
ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */

/* Determine if this CPU has configurable TDP */
if (cpu_config_tdp_levels()) {
/* Set max ratio to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
ratio_max = msr.lo & 0xff;
} else {
/* Max Non-Turbo Ratio */
ratio_max = (msr.lo >> 8) & 0xff;
}
/* Max Non-Turbo Ratio */
ratio_max = (msr.lo >> 8) & 0xff;

clock_max = ratio_max * IRONLAKE_BCLK + ratio_max / 3;

/* Calculate CPU TDP in mW */
Expand Down
10 changes: 0 additions & 10 deletions src/cpu/intel/model_2065x/chip.h
Expand Up @@ -4,15 +4,5 @@
#define SPEEDSTEP_APIC_MAGIC 0xACAC

struct cpu_intel_model_2065x_config {
u8 disable_acpi; /* Do not generate CPU ACPI tables */

int c1_battery; /* ACPI C1 on Battery Power */
int c2_battery; /* ACPI C2 on Battery Power */
int c3_battery; /* ACPI C3 on Battery Power */

int c1_acpower; /* ACPI C1 on AC Power */
int c2_acpower; /* ACPI C2 on AC Power */
int c3_acpower; /* ACPI C3 on AC Power */

int tcc_offset; /* TCC Activation Offset */
};
8 changes: 0 additions & 8 deletions src/cpu/intel/model_2065x/model_2065x.h
Expand Up @@ -43,13 +43,6 @@
#define PKG_POWER_LIMIT_TIME_SHIFT 17
#define PKG_POWER_LIMIT_TIME_MASK 0x7f

#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
#define MSR_CONFIG_TDP_NOMINAL 0x648
#define MSR_CONFIG_TDP_LEVEL1 0x649
#define MSR_CONFIG_TDP_LEVEL2 0x64a
#define MSR_CONFIG_TDP_CONTROL 0x64b
#define MSR_TURBO_ACTIVATION_RATIO 0x64c

/* P-state configuration */
#define PSS_MAX_ENTRIES 16
#define PSS_RATIO_STEP 1
Expand All @@ -61,7 +54,6 @@ void intel_model_2065x_finalize_smm(void);

/* Configure power limits for turbo mode */
void set_power_limits(u8 power_limit_1_time);
int cpu_config_tdp_levels(void);

/* Sanity check config options. */
#if (CONFIG_SMM_TSEG_SIZE <= CONFIG_SMM_RESERVED_SIZE)
Expand Down
111 changes: 5 additions & 106 deletions src/cpu/intel/model_2065x/model_2065x_init.c
Expand Up @@ -20,96 +20,6 @@
#include <cpu/intel/common/common.h>
#include <smp/node.h>

/*
* List of supported C-states in this processor
*
* Latencies are typical worst-case package exit time in uS
* taken from the SandyBridge BIOS specification.
*/
static acpi_cstate_t cstate_map[] = {
{ /* 0: C0 */
}, { /* 1: C1 */
.latency = 1,
.power = 1000,
.resource = {
.addrl = 0x00, /* MWAIT State 0 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 2: C1E */
.latency = 1,
.power = 1000,
.resource = {
.addrl = 0x01, /* MWAIT State 0 Sub-state 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 3: C3 */
.latency = 63,
.power = 500,
.resource = {
.addrl = 0x10, /* MWAIT State 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 4: C6 */
.latency = 87,
.power = 350,
.resource = {
.addrl = 0x20, /* MWAIT State 2 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 5: C7 */
.latency = 90,
.power = 200,
.resource = {
.addrl = 0x30, /* MWAIT State 3 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 6: C7S */
.latency = 90,
.power = 200,
.resource = {
.addrl = 0x31, /* MWAIT State 3 Sub-state 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ 0 }
};

int cpu_config_tdp_levels(void)
{
msr_t platform_info;

/* Minimum CPU revision */
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
return 0;

/* Bits 34:33 indicate how many levels supported */
platform_info = rdmsr(MSR_PLATFORM_INFO);
return (platform_info.hi >> 1) & 3;
}

static void configure_thermal_target(void)
{
struct cpu_intel_model_2065x_config *conf;
Expand Down Expand Up @@ -154,19 +64,12 @@ static void set_max_ratio(void)

perf_ctl.hi = 0;

/* Check for configurable TDP option */
if (cpu_config_tdp_levels()) {
/* Set to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
perf_ctl.lo = (msr.lo & 0xff) << 8;
} else {
/* Platform Info bits 15:8 give max ratio */
msr = rdmsr(MSR_PLATFORM_INFO);
perf_ctl.lo = msr.lo & 0xff00;
}
/* Platform Info bits 15:8 give max ratio */
msr = rdmsr(MSR_PLATFORM_INFO);
perf_ctl.lo = msr.lo & 0xff00;
wrmsr(IA32_PERF_CTL, perf_ctl);

printk(BIOS_DEBUG, "model_x06ax: frequency set to %d\n",
printk(BIOS_DEBUG, "model_x065x: frequency set to %d\n",
((perf_ctl.lo >> 8) & 0xff) * IRONLAKE_BCLK);
}

Expand All @@ -185,9 +88,6 @@ static void model_2065x_init(struct device *cpu)
{
char processor_name[49];

/* Turn on caching if we haven't already */
x86_enable_cache();

/* Clear out pending MCEs */
configure_mca();

Expand Down Expand Up @@ -251,7 +151,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
{
microcode_patch = intel_microcode_find();
*microcode = microcode_patch;
*parallel = 1;
*parallel = !intel_ht_supported();
}

static void per_cpu_smm_trigger(void)
Expand Down Expand Up @@ -307,5 +207,4 @@ static const struct cpu_device_id cpu_table[] = {
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
.cstates = cstate_map,
};
18 changes: 2 additions & 16 deletions src/cpu/intel/model_206ax/acpi.c
Expand Up @@ -31,8 +31,6 @@ static void generate_cstate_entries(acpi_cstate_t *cstates,
++cstate_count;
if (c3 > 0)
++cstate_count;
if (!cstate_count)
return;

acpigen_write_package(cstate_count + 1);
acpigen_write_byte(cstate_count);
Expand Down Expand Up @@ -78,20 +76,8 @@ static void generate_C_state_entries(void)
return;

acpigen_write_method("_CST", 0);

/* If running on AC power */
acpigen_emit_byte(0xa0); /* IfOp */
acpigen_write_len_f(); /* PkgLength */
acpigen_emit_namestring("PWRS");
acpigen_emit_byte(0xa4); /* ReturnOp */
generate_cstate_entries(cpu->cstates, conf->c1_acpower,
conf->c2_acpower, conf->c3_acpower);
acpigen_pop_len();

/* Else on battery power */
acpigen_emit_byte(0xa4); /* ReturnOp */
generate_cstate_entries(cpu->cstates, conf->c1_battery,
conf->c2_battery, conf->c3_battery);
acpigen_emit_byte(RETURN_OP);
generate_cstate_entries(cpu->cstates, conf->acpi_c1, conf->acpi_c2, conf->acpi_c3);
acpigen_pop_len();
}

Expand Down
12 changes: 3 additions & 9 deletions src/cpu/intel/model_206ax/chip.h
Expand Up @@ -4,15 +4,9 @@
#define SPEEDSTEP_APIC_MAGIC 0xACAC

struct cpu_intel_model_206ax_config {
u8 disable_acpi; /* Do not generate CPU ACPI tables */

int c1_battery; /* ACPI C1 on Battery Power */
int c2_battery; /* ACPI C2 on Battery Power */
int c3_battery; /* ACPI C3 on Battery Power */

int c1_acpower; /* ACPI C1 on AC Power */
int c2_acpower; /* ACPI C2 on AC Power */
int c3_acpower; /* ACPI C3 on AC Power */
int acpi_c1; /* ACPI C1 */
int acpi_c2; /* ACPI C2 */
int acpi_c3; /* ACPI C3 */

int tcc_offset; /* TCC Activation Offset */
};
28 changes: 28 additions & 0 deletions src/cpu/intel/model_206ax/model_206ax.h
Expand Up @@ -6,6 +6,34 @@
#include <arch/cpu.h>
#include <stdint.h>

/* SandyBridge CPU stepping */
#define SNB_STEP_B2 2
#define SNB_STEP_C0 3
#define SNB_STEP_D0 5 /* Also J0 */
#define SNB_STEP_D1 6
#define SNB_STEP_D2 7 /* Also J1/Q0 */

/* IvyBridge CPU stepping */
#define IVB_STEP_A0 0
#define IVB_STEP_B0 2
#define IVB_STEP_C0 4
#define IVB_STEP_K0 5
#define IVB_STEP_D0 6
#define IVB_STEP_E0 8
#define IVB_STEP_E1 9

#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)

#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)

/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */
#define SANDYBRIDGE_BCLK 100

Expand Down
5 changes: 1 addition & 4 deletions src/cpu/intel/model_206ax/model_206ax_init.c
Expand Up @@ -425,9 +425,6 @@ static void model_206ax_report(void)
static void model_206ax_init(struct device *cpu)
{

/* Turn on caching if we haven't already */
x86_enable_cache();

/* Clear out pending MCEs */
configure_mca();

Expand Down Expand Up @@ -497,7 +494,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
{
microcode_patch = intel_microcode_find();
*microcode = microcode_patch;
*parallel = 1;
*parallel = !intel_ht_supported();
}

static void per_cpu_smm_trigger(void)
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/smm/gen1/smmrelocate.c
Expand Up @@ -134,7 +134,7 @@ void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
if (smm_reloc_params.ied_size)
setup_ied_area(&smm_reloc_params);

/* This may not be be correct for older CPU's supported by this code,
/* This may not be correct for older CPU's supported by this code,
but given that em64t101_smm_state_save_area_t is larger than the
save_state of these CPU's it works. */
*smm_save_state_size = sizeof(em64t101_smm_state_save_area_t);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/socket_LGA775/Kconfig
Expand Up @@ -17,7 +17,7 @@ config SOCKET_SPECIFIC_OPTIONS # dummy

config DCACHE_RAM_SIZE
hex
default 0x4000 # 16 kB
default 0x8000 # 32 kB

config DCACHE_BSP_STACK_SIZE
hex
Expand Down
1 change: 1 addition & 0 deletions src/cpu/qemu-x86/Makefile.inc
Expand Up @@ -2,6 +2,7 @@

bootblock-y += cache_as_ram_bootblock.S
bootblock-y += bootblock.c
bootblock-$(CONFIG_ARCH_BOOTBLOCK_X86_64) += $(top)/src/arch/x86/walkcbfs.S

romstage-y += ../intel/car/romstage.c

Expand Down
57 changes: 56 additions & 1 deletion src/cpu/qemu-x86/cache_as_ram_bootblock.S
Expand Up @@ -2,6 +2,15 @@

#include <cpu/x86/post_code.h>

#define CBFS_FILE_MAGIC 0
#define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
#define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
#define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
#define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)

.section .init, "ax", @progbits
.code32

.global bootblock_pre_c_entry
bootblock_pre_c_entry:

Expand All @@ -22,12 +31,55 @@ cache_as_ram:

post_code(0x21)

#if defined(__x86_64__)
/*
* Copy page tables to final location in DRAM. This prevents some strange
* bugs when running KVM enabled:
* Accessing MMX instructions in long mode causes an abort
* Some physical addresses aren't properly translated
* Emulation fault on every instruction fetched due to page tables in ROM
* Enabling or disabling paging causes a fault
*
* First, find page tables in CBFS:
*/
lea pagetables_name, %esi
mov $1f, %esp
jmp walkcbfs_asm
1:
cmpl $0, %eax
je .Lhlt

/* Test if page tables are memory-mapped and skip relocation */
cmpl $(CONFIG_ARCH_X86_64_PGTBL_LOC), %eax
je pages_done

movl CBFS_FILE_OFFSET(%eax), %ebx
bswap %ebx
addl %eax, %ebx
movl %ebx, %esi

movl CBFS_FILE_LEN(%eax), %ecx
bswap %ecx
shr $2, %ecx

movl $(CONFIG_ARCH_X86_64_PGTBL_LOC), %edi

loop:
movl (%esi), %eax
movl %eax, (%edi)
addl $4, %esi
addl $4, %edi
decl %ecx
jnz loop
pages_done:
#endif

movl $_ecar_stack, %esp

/* Align the stack and keep aligned for call to bootblock_c_entry() */
and $0xfffffff0, %esp

/* entry64.inc preserves ebx. */
/* entry64.inc preserves ebx. */
#include <cpu/x86/64bit/entry64.inc>

/* Restore the BIST result and timestamps. */
Expand Down Expand Up @@ -58,3 +110,6 @@ before_c_entry:
post_code(POST_DEAD_CODE)
hlt
jmp .Lhlt

pagetables_name:
.string "pagetables"
4 changes: 2 additions & 2 deletions src/cpu/x86/mp_init.c
Expand Up @@ -344,9 +344,9 @@ static atomic_t *load_sipi_vector(struct mp_params *mp_params)
sp->microcode_ptr = (uintptr_t)mp_params->microcode_pointer;
/* Pass on ability to load microcode in parallel. */
if (mp_params->parallel_microcode_load)
sp->microcode_lock = 0;
else
sp->microcode_lock = ~0;
else
sp->microcode_lock = 0;
sp->c_handler = (uintptr_t)&ap_init;
ap_count = &sp->ap_count;
atomic_set(ap_count, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/mtrr/earlymtrr.c
Expand Up @@ -32,7 +32,7 @@ void set_var_mtrr(
unsigned int reg, unsigned int base, unsigned int size,
unsigned int type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
/* Bit 32-35 of MTRRphysMask should be set to 1 */
/* FIXME: It only support 4G less range */
msr_t basem, maskm;

Expand Down
26 changes: 23 additions & 3 deletions src/cpu/x86/sipi_vector.S
Expand Up @@ -84,10 +84,9 @@ _start:
mov idt_ptr, %ebx
lidt (%ebx)

/* Obtain CPU number. */
movl ap_count, %eax
1:
movl %eax, %ecx
/* Obtain CPU number. */
movl ap_count, %ecx
inc %ecx
lock cmpxchg %ecx, ap_count
jnz 1b
Expand All @@ -103,12 +102,23 @@ _start:
/* Save CPU number. */
mov %ecx, %esi

/*
* The following code only needs to run on Intel platforms and thus the caller
* doesn't provide a microcode_ptr if not on Intel.
* On Intel platforms which update microcode using FIT the version check will
* also skip the microcode update.
*/

/* Determine if one should check microcode versions. */
mov microcode_ptr, %edi
test %edi, %edi
jz microcode_done /* Bypass if no microde exists. */

/* Get the Microcode version. */
xorl %eax, %eax
xorl %edx, %edx
movl $IA32_BIOS_SIGN_ID, %ecx
wrmsr
mov $1, %eax
cpuid
mov $IA32_BIOS_SIGN_ID, %ecx
Expand All @@ -117,6 +127,16 @@ _start:
test %edx, %edx
jnz microcode_done

/*
* Intel SDM and various BWGs specify to use a semaphore to update microcode
* on one thread per core on Hyper-Threading enabled CPUs. Due to this complex
* code would be necessary to determine the core #ID, initializing and picking
* the right semaphore out of CONFIG_MAX_CPUS / 2.
* Instead of the per core approachm, as recommended, use one global spinlock.
* Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
* most 8 threads will ever run into this condition, the boot delay is negligible.
*/

/* Determine if parallel microcode loading is allowed. */
cmpl $0xffffffff, microcode_lock
je load_microcode
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/smm/Makefile.inc
Expand Up @@ -17,7 +17,7 @@ endif

smmstub-generic-ccopts += -D__SMM__
smm-generic-ccopts += -D__SMM__
smm-c-deps:=$$(OPTION_TABLE_H)
smm-c-deps+=$$(OPTION_TABLE_H)

$(obj)/smm/smm.o: $$(smm-objs) $(COMPILER_RT_smm)
$(LD_smm) -nostdlib -r -o $@ $(COMPILER_RT_FLAGS_smm) --whole-archive --start-group $(filter-out %.ld, $(smm-objs)) --no-whole-archive $(COMPILER_RT_smm) --end-group
Expand Down
35 changes: 0 additions & 35 deletions src/cpu/x86/smm/smi_trigger.c
@@ -1,12 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_gnvs.h>
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/smm.h>

static void set_smm_gnvs_ptr(void);

int apm_control(u8 cmd)
{
if (!CONFIG(HAVE_SMI_HANDLER))
Expand All @@ -23,9 +20,6 @@ int apm_control(u8 cmd)
case APM_CNT_ACPI_ENABLE:
printk(BIOS_DEBUG, "Enabling ACPI via APMC.\n");
break;
case APM_CNT_GNVS_UPDATE:
set_smm_gnvs_ptr();
return 0;
case APM_CNT_FINALIZE:
printk(BIOS_DEBUG, "Finalizing SMM.\n");
break;
Expand All @@ -45,32 +39,3 @@ int apm_control(u8 cmd)
printk(BIOS_DEBUG, "APMC done.\n");
return 0;
}

static void set_smm_gnvs_ptr(void)
{
uintptr_t gnvs_address;

if (CONFIG(ACPI_NO_SMI_GNVS)) {
printk(BIOS_WARNING, "%s() is not implemented\n", __func__);
return;
}

gnvs_address = (uintptr_t)acpi_get_gnvs();
if (!gnvs_address)
return;

/*
* Issue SMI to set the gnvs pointer in SMM.
*
* EAX = APM_CNT_GNVS_UPDATE
* EBX = gnvs pointer
* EDX = APM_CNT
*/
asm volatile (
"outb %%al, %%dx\n\t"
: /* ignore result */
: "a" (APM_CNT_GNVS_UPDATE),
"b" (gnvs_address),
"d" (APM_CNT)
);
}
4 changes: 3 additions & 1 deletion src/cpu/x86/smm/smm_module_handler.c
Expand Up @@ -134,8 +134,10 @@ asmlinkage void smm_handler_start(void *arg)

/* Make sure to set the global runtime. It's OK to race as the value
* will be the same across CPUs as well as multiple SMIs. */
if (smm_runtime == NULL)
if (smm_runtime == NULL) {
smm_runtime = runtime;
gnvs = (void *)(uintptr_t)smm_runtime->gnvs_ptr;
}

if (cpu >= CONFIG_MAX_CPUS) {
console_init();
Expand Down
4 changes: 3 additions & 1 deletion src/cpu/x86/smm/smm_module_loaderv2.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_gnvs.h>
#include <stdint.h>
#include <string.h>
#include <rmodule.h>
Expand Down Expand Up @@ -332,7 +333,7 @@ static int smm_stub_place_staggered_entry_points(char *base,
*
* The save state and smm stack are treated as contiguous for the number of
* concurrent areas requested. The save state always lives at the top of the
* the CPUS smbase (and the entry point is at offset 0x8000). This allows only a certain
* CPUS smbase (and the entry point is at offset 0x8000). This allows only a certain
* number of CPUs with staggered entry points until the save state area comes
* down far enough to overwrite/corrupt the entry code (stub code). Therefore,
* an SMM map is created to avoid this corruption, see smm_create_map() above.
Expand Down Expand Up @@ -447,6 +448,7 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
stub_params->runtime.smm_size = smm_size;
stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
stub_params->runtime.num_cpus = params->num_concurrent_stacks;
stub_params->runtime.gnvs_ptr = (uintptr_t)acpi_get_gnvs();

printk(BIOS_DEBUG, "%s: stack_end = 0x%lx\n",
__func__, stub_params->stack_top - total_stack_size);
Expand Down
11 changes: 9 additions & 2 deletions src/device/Kconfig
Expand Up @@ -46,6 +46,12 @@ config MAINBOARD_FORCE_NATIVE_VGA_INIT
Selected by mainboards / chipsets whose graphics driver can't or
shouldn't be disabled.

config VGA_ROM_RUN_DEFAULT
def_bool n
help
Selected by mainboards whose graphics initialization depends on VGA OpROM.
coreboot needs to load/execute legacy VGA OpROM in order to initialize GFX.

config MAINBOARD_HAS_LIBGFXINIT
def_bool n
help
Expand All @@ -54,8 +60,8 @@ config MAINBOARD_HAS_LIBGFXINIT

choice
prompt "Graphics initialization"
default NO_GFX_INIT if VGA_BIOS && PAYLOAD_SEABIOS
default VGA_ROM_RUN if VGA_BIOS
default NO_GFX_INIT if VGA_ROM_RUN_DEFAULT && PAYLOAD_SEABIOS
default VGA_ROM_RUN if VGA_ROM_RUN_DEFAULT
default MAINBOARD_DO_NATIVE_VGA_INIT
default MAINBOARD_USE_LIBGFXINIT
default RUN_FSP_GOP if INTEL_GMA_HAVE_VBT
Expand Down Expand Up @@ -690,6 +696,7 @@ config SUBSYSTEM_DEVICE_ID
config VGA_BIOS
bool "Add a VGA BIOS image"
depends on ARCH_X86
select VGA_ROM_RUN_DEFAULT
help
Select this option if you have a VGA BIOS image that you would
like to add to your ROM.
Expand Down
2 changes: 2 additions & 0 deletions src/device/Makefile.inc
Expand Up @@ -63,3 +63,5 @@ ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V3) += resource_allocator_v3.c
ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V4) += resource_allocator_v4.c

ramstage-$(CONFIG_XHCI_UTILS) += xhci.c

ramstage-y += gpio.c
3 changes: 3 additions & 0 deletions src/device/device_const.c
Expand Up @@ -162,6 +162,9 @@ static int path_eq(const struct device_path *path1,
case DEVICE_PATH_LPC:
equal = (path1->lpc.addr == path2->lpc.addr);
break;
case DEVICE_PATH_GPIO:
equal = (path1->gpio.id == path2->gpio.id);
break;
default:
printk(BIOS_ERR, "Unknown device type: %d\n", path1->type);
break;
Expand Down
6 changes: 6 additions & 0 deletions src/device/device_util.c
Expand Up @@ -130,6 +130,9 @@ u32 dev_path_encode(const struct device *dev)
case DEVICE_PATH_USB:
ret |= dev->path.usb.port_type << 8 | dev->path.usb.port_id;
break;
case DEVICE_PATH_GPIO:
ret |= dev->path.gpio.id;
break;
case DEVICE_PATH_NONE:
case DEVICE_PATH_MMIO: /* don't care */
default:
Expand Down Expand Up @@ -223,6 +226,9 @@ const char *dev_path(const struct device *dev)
snprintf(buffer, sizeof(buffer), "LPC: %08lx",
dev->path.lpc.addr);
break;
case DEVICE_PATH_GPIO:
snprintf(buffer, sizeof(buffer), "GPIO: %d", dev->path.gpio.id);
break;
default:
printk(BIOS_ERR, "Unknown device path type: %d\n",
dev->path.type);
Expand Down
21 changes: 21 additions & 0 deletions src/device/gpio.c
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <device/device.h>
#include <device/gpio.h>

const struct gpio_operations *dev_get_gpio_ops(struct device *dev)
{
if (!dev) {
printk(BIOS_ERR, "Could not get gpio operations, device is NULL.");
return NULL;
} else if (!dev->ops) {
printk(BIOS_ERR, "Could not get gpio operations, dev->ops is NULL.");
return NULL;
} else if (!dev->ops->ops_gpio) {
printk(BIOS_ERR, "Could not get gpio operations, ops_gpio is NULL.");
return NULL;
}

return dev->ops->ops_gpio;
}
2 changes: 1 addition & 1 deletion src/device/oprom/x86emu/sys.c
Expand Up @@ -64,7 +64,7 @@ static u8 *mem_ptr(u32 addr, int size)
u8 *retaddr = 0;

if (addr > M.mem_size - size) {
DB(printf("mem_ptr: address %#x out of range!\n", addr);)
DB(printf("%s: address %#x out of range!\n", __func__, addr);)
HALT_SYS();
}
if (addr < 0x200) {
Expand Down
4 changes: 2 additions & 2 deletions src/device/pci_device.c
Expand Up @@ -967,7 +967,7 @@ static void set_pci_ops(struct device *dev)
dev->ops = &default_cardbus_ops_bus;
break;
#endif
default:
default:
bad:
if (dev->enabled) {
printk(BIOS_ERR, "%s [%04x/%04x/%06x] has unknown "
Expand Down Expand Up @@ -1263,7 +1263,7 @@ void pci_scan_bus(struct bus *bus, unsigned int min_devfn,
post_code(0x25);

/*
* Warn if any leftover static devices are are found.
* Warn if any leftover static devices are found.
* There's probably a problem in devicetree.cb.
*/

Expand Down
2 changes: 1 addition & 1 deletion src/device/pci_rom.c
Expand Up @@ -207,7 +207,7 @@ pci_rom_acpi_fill_vfct(const struct device *device, acpi_vfct_t *vfct_struct,
if (!rom)
rom = pci_rom_probe(device);
if (!rom) {
printk(BIOS_ERR, "pci_rom_acpi_fill_vfct failed\n");
printk(BIOS_ERR, "%s failed\n", __func__);
return current;
}

Expand Down
2 changes: 2 additions & 0 deletions src/device/pnp_device.c
Expand Up @@ -249,6 +249,8 @@ static void get_resources(struct device *dev, struct pnp_info *info)
pnp_get_ioresource(dev, PNP_IDX_IO2, info->io2);
if (info->flags & PNP_IO3)
pnp_get_ioresource(dev, PNP_IDX_IO3, info->io3);
if (info->flags & PNP_IO4)
pnp_get_ioresource(dev, PNP_IDX_IO4, info->io4);

if (info->flags & PNP_IRQ0) {
resource = new_resource(dev, PNP_IDX_IRQ0);
Expand Down
2 changes: 1 addition & 1 deletion src/device/xhci.c
Expand Up @@ -36,7 +36,7 @@ enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
}

if (!(res->flags & IORESOURCE_ASSIGNED)) {
printk(BIOS_ERR, "%s: BAR is is not assigned\n", __func__);
printk(BIOS_ERR, "%s: BAR is not assigned\n", __func__);
return CB_ERR;
}

Expand Down
7 changes: 5 additions & 2 deletions src/drivers/amd/agesa/cache_as_ram.S
Expand Up @@ -10,16 +10,19 @@
******************************************************************************
*/

#include "gcccar.inc"
#include <cpu/x86/lapic_def.h>
#include <cpu/x86/post_code.h>

.section .init

.code32
.globl _cache_as_ram_setup, _cache_as_ram_setup_end

.global bootblock_pre_c_entry

_cache_as_ram_setup:

#include "gcccar.inc"

/*
* on entry:
* mm0: BIST (ignored)
Expand Down
16 changes: 8 additions & 8 deletions src/drivers/elog/elog.c
Expand Up @@ -212,7 +212,7 @@ static int elog_is_buffer_clear(size_t offset)
uint8_t *buffer = rdev_mmap(rdev, offset, size);
int ret = 1;

elog_debug("elog_is_buffer_clear(offset=%zu size=%zu)\n", offset, size);
elog_debug("%s(offset=%zu size=%zu)\n", __func__, offset, size);

if (buffer == NULL)
return 0;
Expand All @@ -235,7 +235,7 @@ static int elog_is_header_valid(void)
{
struct elog_header *header;

elog_debug("elog_is_header_valid()\n");
elog_debug("%s()\n", __func__);

header = rdev_mmap(mirror_dev_get(), 0, sizeof(*header));

Expand Down Expand Up @@ -348,7 +348,7 @@ static int elog_update_event_buffer_state(void)
{
size_t offset = elog_events_start();

elog_debug("elog_update_event_buffer_state()\n");
elog_debug("%s()\n", __func__);

/* Go through each event and validate it */
while (1) {
Expand Down Expand Up @@ -392,7 +392,7 @@ static int elog_update_event_buffer_state(void)

static int elog_scan_flash(void)
{
elog_debug("elog_scan_flash()\n");
elog_debug("%s()\n", __func__);
void *mirror_buffer;
const struct region_device *rdev = mirror_dev_get();

Expand Down Expand Up @@ -558,7 +558,7 @@ static int elog_shrink_by_size(size_t requested_size)

static int elog_prepare_empty(void)
{
elog_debug("elog_prepare_empty()\n");
elog_debug("%s()\n", __func__);
return elog_shrink_by_size(elog_events_total_space());
}

Expand Down Expand Up @@ -638,7 +638,7 @@ int elog_smbios_write_type15(unsigned long *current, int handle)
*/
int elog_clear(void)
{
elog_debug("elog_clear()\n");
elog_debug("%s()\n", __func__);

/* Make sure ELOG structures are initialized */
if (elog_init() < 0)
Expand Down Expand Up @@ -786,7 +786,7 @@ int elog_init(void)
}
elog_state.elog_initialized = ELOG_BROKEN;

elog_debug("elog_init()\n");
elog_debug("%s()\n", __func__);

/* Set up the backing store */
if (elog_find_flash() < 0)
Expand Down Expand Up @@ -860,7 +860,7 @@ int elog_add_event_raw(u8 event_type, void *data, u8 data_size)
struct event_header *event;
u8 event_size;

elog_debug("elog_add_event_raw(type=%X)\n", event_type);
elog_debug("%s(type=%X)\n", __func__, event_type);

/* Make sure ELOG structures are initialized */
if (elog_init() < 0)
Expand Down
13 changes: 13 additions & 0 deletions src/drivers/generic/bayhub/bh720.c
Expand Up @@ -44,6 +44,19 @@ static void bh720_init(struct device *dev)
}

board_bh720(dev);

if (config && config->vih_tuning_value) {
/* Tune VIH */
u32 bh720_pcr_data;
pci_write_config32(dev, BH720_PROTECT,
BH720_PROTECT_OFF | BH720_PROTECT_LOCK_OFF);
bh720_pcr_data = pci_read_config32(dev, BH720_PCR_DrvStrength_PLL);
bh720_pcr_data &= 0xFFFFFF00;
bh720_pcr_data |= config->vih_tuning_value;
pci_write_config32(dev, BH720_PCR_DrvStrength_PLL, bh720_pcr_data);
pci_write_config32(dev, BH720_PROTECT,
BH720_PROTECT_ON | BH720_PROTECT_LOCK_ON);
}
}

static struct device_operations bh720_ops = {
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/generic/bayhub/chip.h
Expand Up @@ -8,4 +8,7 @@
struct drivers_generic_bayhub_config {
/* 1 to enable power-saving mode, 0 to disable */
int power_saving;

/* CLK and DAT tuning values */
uint8_t vih_tuning_value;
};
12 changes: 12 additions & 0 deletions src/drivers/genesyslogic/gl9763e/gl9763e.c
Expand Up @@ -12,6 +12,8 @@

static void gl9763e_init(struct device *dev)
{
uint32_t ver;

printk(BIOS_INFO, "GL9763E: init\n");
pci_dev_init(dev);

Expand All @@ -25,6 +27,16 @@ static void gl9763e_init(struct device *dev)
pci_update_config32(dev, PLL_CTL_2, ~PLL_CTL_2_MAX_SSC_MASK, MAX_SSC_30000PPM);
/* Enable SSC */
pci_or_config32(dev, PLL_CTL, PLL_CTL_SSC);
/* Check chip version */
ver = pci_read_config32(dev, HW_VER_2);
if ((ver & HW_VER_MASK) == REVISION_03) {
/* Set clock source for RX path */
pci_update_config32(dev, SD_CLKRX_DLY, ~CLK_SRC_MASK, AFTER_OUTPUT_BUFF);
}
/* Modify DS delay */
pci_update_config32(dev, SD_CLKRX_DLY, ~HS400_RX_DELAY_MASK, HS400_RX_DELAY);
/* Disable Slow mode */
pci_and_config32(dev, EMMC_CTL, ~SLOW_MODE);
/* Set VHS to read-only */
pci_update_config32(dev, VHS, ~VHS_REV_MASK, VHS_REV_R);
}
Expand Down
13 changes: 13 additions & 0 deletions src/drivers/genesyslogic/gl9763e/gl9763e.h
Expand Up @@ -18,6 +18,19 @@
#define PLL_CTL 0x938
#define PLL_CTL_SSC BIT(19)

#define EMMC_CTL 0x960
#define SLOW_MODE BIT(3)

#define PLL_CTL_2 0x93C
#define PLL_CTL_2_MAX_SSC_MASK (0xFFFF << 16)
#define MAX_SSC_30000PPM (0xF5C3 << 16)

#define HW_VER_2 0x8F8
#define HW_VER_MASK 0xFFFF
#define REVISION_03 0x0011

#define SD_CLKRX_DLY 0x934
#define CLK_SRC_MASK (0x3 << 24)
#define AFTER_OUTPUT_BUFF (0x0 << 24)
#define HS400_RX_DELAY_MASK (0xF << 28)
#define HS400_RX_DELAY (0x5 << 28)
1 change: 1 addition & 0 deletions src/drivers/i2c/sx9324/registers.h
Expand Up @@ -47,6 +47,7 @@ REGISTER(reg_gnrl_ctrl1);

REGISTER(reg_irq_msk);
REGISTER(reg_irq_cfg0);
REGISTER(reg_irq_cfg1);
REGISTER(reg_irq_cfg2);

REGISTER(reg_prox_ctrl0);
Expand Down
3 changes: 2 additions & 1 deletion src/drivers/i2c/tpm/cr50.c
Expand Up @@ -49,7 +49,8 @@ __weak int tis_plat_irq_status(void)
static int warning_displayed;

if (!warning_displayed) {
printk(BIOS_WARNING, "WARNING: tis_plat_irq_status() not implemented, wasting 20ms to wait on Cr50!\n");
printk(BIOS_WARNING, "WARNING: %s() not implemented, wasting 20ms to wait on"
" Cr50!\n", __func__);
warning_displayed = 1;
}
mdelay(CR50_TIMEOUT_NOIRQ_MS);
Expand Down
14 changes: 7 additions & 7 deletions src/drivers/i2c/tpm/tis.c
Expand Up @@ -24,7 +24,7 @@ int tis_open(void)
int rc;

if (chip.is_open) {
printk(BIOS_DEBUG, "tis_open() called twice.\n");
printk(BIOS_DEBUG, "%s() called twice.\n", __func__);
return -1;
}

Expand Down Expand Up @@ -68,19 +68,19 @@ static ssize_t tpm_transmit(const uint8_t *sbuf, size_t sbufsiz, void *rbuf,
return -1;

if (count == 0) {
printk(BIOS_DEBUG, "tpm_transmit: no data\n");
printk(BIOS_DEBUG, "%s: no data\n", __func__);
return -1;
}
if (count > sbufsiz) {
printk(BIOS_DEBUG, "tpm_transmit: invalid count value %x %zx\n",
printk(BIOS_DEBUG, "%s: invalid count value %x %zx\n", __func__,
count, sbufsiz);
return -1;
}

ASSERT(chip.vendor.send);
rc = chip.vendor.send(&chip, (uint8_t *) sbuf, count);
if (rc < 0) {
printk(BIOS_DEBUG, "tpm_transmit: tpm_send error\n");
printk(BIOS_DEBUG, "%s: tpm_send error\n", __func__);
goto out;
}

Expand All @@ -95,7 +95,7 @@ static ssize_t tpm_transmit(const uint8_t *sbuf, size_t sbufsiz, void *rbuf,

if (status == chip.vendor.req_canceled) {
printk(BIOS_DEBUG,
"tpm_transmit: Operation Canceled\n");
"%s: Operation Canceled\n", __func__);
rc = -1;
goto out;
}
Expand All @@ -105,15 +105,15 @@ static ssize_t tpm_transmit(const uint8_t *sbuf, size_t sbufsiz, void *rbuf,

ASSERT(chip.vendor.cancel);
chip.vendor.cancel(&chip);
printk(BIOS_DEBUG, "tpm_transmit: Operation Timed out\n");
printk(BIOS_DEBUG, "%s: Operation Timed out\n", __func__);
rc = -1; //ETIME;
goto out;

out_recv:

rc = chip.vendor.recv(&chip, (uint8_t *) rbuf, rbufsiz);
if (rc < 0)
printk(BIOS_DEBUG, "tpm_transmit: tpm_recv: error %d\n", rc);
printk(BIOS_DEBUG, "%s: tpm_recv: error %d\n", __func__, rc);
out:
return rc;
}
Expand Down
7 changes: 3 additions & 4 deletions src/drivers/i2c/tpm/tpm.c
Expand Up @@ -365,7 +365,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */
size = recv_data(chip, buf, TPM_HEADER_SIZE);
if (size < TPM_HEADER_SIZE) {
printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Unable to read header\n");
printk(BIOS_DEBUG, "%s: Unable to read header\n", __func__);
goto out;
}

Expand All @@ -379,15 +379,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf, size_t count)
size += recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE);
if (size < expected) {
printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Unable to "
"read remainder of result\n");
printk(BIOS_DEBUG, "%s: Unable to read remainder of result\n", __func__);
size = -1;
goto out;
}

wait_for_stat(chip, TPM_STS_VALID, &status);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Error left over data\n");
printk(BIOS_DEBUG, "%s: Error left over data\n", __func__);
size = -1;
goto out;
}
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/intel/fsp1_1/cache_as_ram.S
Expand Up @@ -14,6 +14,8 @@

#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */

.section .init, "ax", @progbits

.global bootblock_pre_c_entry
bootblock_pre_c_entry:
/*
Expand Down
5 changes: 5 additions & 0 deletions src/drivers/intel/fsp1_1/temp_ram_exit.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <cbmem.h>
#include <console/console.h>
#include <fsp/util.h>

Expand All @@ -10,6 +11,10 @@ asmlinkage void chipset_teardown_car_main(void)
FSP_TEMP_RAM_EXIT temp_ram_exit;
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");

/* CBMEM_ID_VBOOT_WORKBUF is used as vboot workbuffer.
* Init CBMEM before loading fsp, to have buffer available */
cbmem_initialize();

if (prog_locate(&fsp)) {
die("Unable to locate fsp.bin\n");
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/drivers/intel/fsp2_0/Kconfig
Expand Up @@ -117,6 +117,15 @@ config FSP_CAR
help
Use FSP APIs to initialize & Tear Down the Cache-As-Ram

config FSP_T_RESERVED_SIZE
hex
default 0x100 if FSP_CAR
default 0x0
help
This is the size of the area reserved by FSP-T. This is not
defined in the FSP specification but in the SOC integration
guides.

config FSP_M_XIP
bool
default n
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/fsp2_0/Makefile.inc
Expand Up @@ -73,7 +73,7 @@ $(FSP_S_CBFS)-compression := LZ4
endif

ifeq ($(CONFIG_FSP_FULL_FD),y)
$(obj)/Fsp_M.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH))
$(obj)/Fsp_M.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH)) $(DOTCONFIG)
python2 3rdparty/fsp/Tools/SplitFspBin.py split -f $(CONFIG_FSP_FD_PATH) -o "$(obj)" -n "Fsp.fd"

$(obj)/Fsp_S.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH)) $(obj)/Fsp_M.fd
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/fsp2_0/header_display.c
Expand Up @@ -18,7 +18,7 @@ void fsp_print_header_info(const struct fsp_header *hdr)
revision.rev.bld_num);
printk(BIOS_SPEW, "Type: %s/%s\n",
(hdr->component_attribute & 1) ? "release" : "debug",
(hdr->component_attribute & 2) ? "test" : "official");
(hdr->component_attribute & 2) ? "official" : "test");
printk(BIOS_SPEW, "image ID: %s, base 0x%lx + 0x%zx\n",
hdr->image_id, hdr->image_base, hdr->image_size);
printk(BIOS_SPEW, "\tConfig region 0x%zx + 0x%zx\n",
Expand Down
7 changes: 3 additions & 4 deletions src/drivers/intel/fsp2_0/memory_init.c
Expand Up @@ -36,7 +36,7 @@ static void save_memory_training_data(bool s3wake, uint32_t fsp_version)

mrc_data = fsp_find_nv_storage_data(&mrc_data_size);
if (!mrc_data) {
printk(BIOS_ERR, "Couldn't find memory training data HOB.\n");
printk(BIOS_ERR, "ERROR: FSP_NON_VOLATILE_STORAGE_HOB missing!\n");
return;
}

Expand All @@ -48,7 +48,7 @@ static void save_memory_training_data(bool s3wake, uint32_t fsp_version)
*/
if (mrc_cache_stash_data(MRC_TRAINING_DATA, fsp_version, mrc_data,
mrc_data_size) < 0)
printk(BIOS_ERR, "Failed to stash MRC data\n");
printk(BIOS_ERR, "ERROR: Failed to stash MRC data\n");
}

static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)
Expand All @@ -64,8 +64,7 @@ static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)
} else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
range_entry_size(&fsp_mem))) {
if (CONFIG(HAVE_ACPI_RESUME)) {
printk(BIOS_ERR,
"Failed to recover CBMEM in S3 resume.\n");
printk(BIOS_ERR, "ERROR: Failed to recover CBMEM in S3 resume.\n");
/* Failed S3 resume, reset to come up cleanly */
/* FIXME: A "system" reset is likely enough: */
full_reset();
Expand Down
14 changes: 12 additions & 2 deletions src/drivers/intel/gma/Kconfig
Expand Up @@ -87,7 +87,7 @@ config GFX_GMA
|| NORTHBRIDGE_INTEL_HASWELL \
|| SOC_INTEL_BROADWELL || SOC_INTEL_SKYLAKE || SOC_INTEL_APOLLOLAKE \
|| SOC_INTEL_KABYLAKE || SOC_INTEL_COFFEELAKE \
|| SOC_INTEL_WHISKEYLAKE
|| SOC_INTEL_WHISKEYLAKE || SOC_INTEL_COMETLAKE
depends on MAINBOARD_USE_LIBGFXINIT || INTEL_GMA_LIBGFXINIT_EDID
select RAMSTAGE_LIBHWBASE

Expand All @@ -114,11 +114,21 @@ config GFX_GMA_GENERATION
string
default "Broxton" if SOC_INTEL_APOLLOLAKE
default "Skylake" if SOC_INTEL_SKYLAKE || SOC_INTEL_KABYLAKE || \
SOC_INTEL_COFFEELAKE || SOC_INTEL_WHISKEYLAKE
SOC_INTEL_COFFEELAKE || SOC_INTEL_WHISKEYLAKE || \
SOC_INTEL_COMETLAKE
default "Haswell" if NORTHBRIDGE_INTEL_HASWELL || SOC_INTEL_BROADWELL
default "Ironlake" if NORTHBRIDGE_INTEL_IRONLAKE || NORTHBRIDGE_INTEL_SANDYBRIDGE
default "G45" if NORTHBRIDGE_INTEL_GM45 || NORTHBRIDGE_INTEL_X4X

config GFX_GMA_PCH
string
default "Ibex_Peak" if NORTHBRIDGE_INTEL_IRONLAKE
default "Cougar_Point" if NORTHBRIDGE_INTEL_SANDYBRIDGE
default "Lynx_Point" if NORTHBRIDGE_INTEL_HASWELL || SOC_INTEL_BROADWELL
default "Sunrise_Point" if SOC_INTEL_COMMON_SKYLAKE_BASE
default "Cannon_Point" if SOC_INTEL_CANNONLAKE_BASE
default "No_PCH"

config GFX_GMA_PANEL_1_PORT
string
default "eDP" if GFX_GMA_PANEL_1_ON_EDP
Expand Down
File renamed without changes.
7 changes: 4 additions & 3 deletions src/drivers/intel/gma/acpi/gma.asl
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */

Device (GFX0)
Scope (GFX0)
{
Name (_ADR, 0x00020000)

OperationRegion (GFXC, PCI_Config, 0x00, 0x0100)
Field (GFXC, DWordAcc, NoLock, Preserve)
{
Expand All @@ -20,6 +18,9 @@ Device (GFX0)
{
Offset (CONFIG_INTEL_GMA_BCLV_OFFSET),
BCLV, CONFIG_INTEL_GMA_BCLV_WIDTH,
}
Field (GFRG, DWordAcc, NoLock, Preserve)
{
Offset (CONFIG_INTEL_GMA_BCLM_OFFSET),
BCLM, CONFIG_INTEL_GMA_BCLM_WIDTH
}
Expand Down
20 changes: 20 additions & 0 deletions src/drivers/intel/gma/gma.h
Expand Up @@ -11,11 +11,31 @@ struct i915_gpu_controller_info {
u32 did[5];
};

/* Devicetree panel configuration */
struct i915_gpu_panel_config {
unsigned int up_delay_ms;
unsigned int down_delay_ms;
unsigned int cycle_delay_ms;
unsigned int backlight_on_delay_ms;
unsigned int backlight_off_delay_ms;
unsigned int backlight_pwm_hz;
enum {
GPU_BACKLIGHT_POLARITY_HIGH = 0,
GPU_BACKLIGHT_POLARITY_LOW,
} backlight_polarity;
};

#define GMA_STATIC_DISPLAYS(ssc) { \
.use_spread_spectrum_clock = (ssc), \
.ndid = 3, .did = { 0x0100, 0x0240, 0x0410, } \
}

/* Shortcut for one internal panel at port A */
#define GMA_DEFAULT_PANEL(ssc) { \
.use_spread_spectrum_clock = (ssc), \
.ndid = 1, .did = { 0x0400 } \
}

void drivers_intel_gma_displays_ssdt_generate(const struct i915_gpu_controller_info *conf);

#endif
1 change: 0 additions & 1 deletion src/drivers/intel/gma/i915_reg.h
Expand Up @@ -549,7 +549,6 @@
#define I915_BSD_USER_INTERRUPT (1<<25)
#define EIR 0x020b0
#define EMR 0x020b4
#define ESR 0x020b8
#define GM45_ERROR_PAGE_TABLE (1<<5)
#define GM45_ERROR_MEM_PRIV (1<<4)
#define I915_ERROR_PAGE_TABLE (1<<4)
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/gma/intel_bios.h
Expand Up @@ -206,8 +206,8 @@ struct old_child_dev_config {
} __packed;

/* This one contains field offsets that are known to be common for all BDB
* versions. Notice that the meaning of the contents contents may still change,
* but at least the offsets are consistent. */
* versions. Notice that the meaning of the contents may still change, but
* at least the offsets are consistent. */
struct common_child_dev_config {
u16 handle;
u16 device_type;
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/gma/opregion.c
Expand Up @@ -155,7 +155,7 @@ static enum cb_err locate_vbt_vbios(const u8 *vbios, struct region_device *rdev)
return CB_ERR;
}

printk(BIOS_DEBUG, "GMA: locate_vbt_vbios: %x %x %x %x %x\n",
printk(BIOS_DEBUG, "GMA: %s: %x %x %x %x %x\n", __func__,
oprom->signature, pcir->vendor, pcir->classcode[0],
pcir->classcode[1], pcir->classcode[2]);

Expand Down
46 changes: 40 additions & 6 deletions src/drivers/intel/usb4/retimer/retimer.c
Expand Up @@ -8,6 +8,7 @@
#include <gpio.h>
#include <string.h>
#include "chip.h"
#include "retimer.h"

/* Unique ID for the retimer _DSM. */
#define INTEL_USB4_RETIMER_DSM_UUID "61788900-C470-42BB-80F0-23A313864593"
Expand All @@ -19,6 +20,8 @@
* 0: Query command implemented
* 1: Query force power enable state
* 2: Set force power state
* 3: Get Retimer FW Update EC Ram value
* 4: Set Retimer FW Update EC Ram value
* Arg3: A package containing parameters for the function specified
* by the UUID, revision ID and function index.
*/
Expand All @@ -28,15 +31,15 @@ static void usb4_retimer_cb_standard_query(void *arg)
/*
* ToInteger (Arg1, Local2)
* If (Local2 == 1) {
* Return(Buffer() {0x07})
* Return(Buffer() {0x1f})
* }
* Return (Buffer() {0x01})
*/
acpigen_write_to_integer(ARG1_OP, LOCAL2_OP);

/* Revision 1 supports 2 Functions beyond the standard query */
/* Revision 1 supports 4 Functions beyond the standard query */
acpigen_write_if_lequal_op_int(LOCAL2_OP, 1);
acpigen_write_return_singleton_buffer(0x07);
acpigen_write_return_singleton_buffer(0x1f);
acpigen_pop_len(); /* If */

/* Other revisions support no additional functions */
Expand All @@ -48,7 +51,7 @@ static void usb4_retimer_cb_get_power_state(void *arg)
struct acpi_gpio *power_gpio = arg;

/*
* // Read power gpio into Local0
* Read power gpio into Local0
* Store (\_SB.PCI0.GTXS (power_gpio), Local0)
* Return (Local0)
*/
Expand All @@ -61,7 +64,7 @@ static void usb4_retimer_cb_set_power_state(void *arg)
struct acpi_gpio *power_gpio = arg;

/*
* // Get argument for on/off from Arg3[0]
* Get information to set to retimer info from Arg3[0]
* Local0 = DeRefOf (Arg3[0])
*/
acpigen_get_package_op_element(ARG3_OP, 0, LOCAL0_OP);
Expand Down Expand Up @@ -90,10 +93,32 @@ static void usb4_retimer_cb_set_power_state(void *arg)
acpigen_write_return_integer(0);
}

static void (*usb4_retimer_callbacks[3])(void *) = {
static void usb4_retimer_cb_get_retimer_info(void *arg)
{
const char *RFWU = ec_retimer_fw_update_path();

/*
* Read Mux Retimer info from EC RAM
* Return RFWU if RFWU is not NULL. Otherwise return -1 to
* inform kernel about error.
*/
if (!RFWU)
acpigen_write_return_byte(-1);
else
acpigen_write_return_namestr(RFWU);
}

static void usb4_retimer_cb_set_retimer_info(void *arg)
{
ec_retimer_fw_update(arg);
}

static void (*usb4_retimer_callbacks[5])(void *) = {
usb4_retimer_cb_standard_query, /* Function 0 */
usb4_retimer_cb_get_power_state, /* Function 1 */
usb4_retimer_cb_set_power_state, /* Function 2 */
usb4_retimer_cb_get_retimer_info, /* Function 3 */
usb4_retimer_cb_set_retimer_info, /* Function 4 */
};

static void usb4_retimer_fill_ssdt(const struct device *dev)
Expand Down Expand Up @@ -134,3 +159,12 @@ struct chip_operations drivers_intel_usb4_retimer_ops = {
CHIP_NAME("Intel USB4 Retimer")
.enable_dev = usb4_retimer_enable
};

__weak const char *ec_retimer_fw_update_path(void)
{
return NULL;
}

__weak void ec_retimer_fw_update(void *arg)
{
}
9 changes: 9 additions & 0 deletions src/drivers/intel/usb4/retimer/retimer.h
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef _DRIVERS_INTEL_USB4_RETIMER_H_
#define _DRIVERS_INTEL_USB4_RETIMER_H_

const char *ec_retimer_fw_update_path(void);
void ec_retimer_fw_update(void *arg);

#endif /* _DRIVERS_INTEL_USB4_RETIMER_H_ */
11 changes: 11 additions & 0 deletions src/drivers/ipmi/Kconfig
Expand Up @@ -42,3 +42,14 @@ config IPMI_KCS_TIMEOUT_MS
The time unit is millisecond for each IPMI KCS transfer.
IPMI spec v2.0 rev 1.1 Sec. 9.15, a five-second timeout or
greater is recommended.

config DRIVERS_IPMI_SUPERMICRO_OEM
bool "Supermicro IPMI OEM BMC support"
depends on IPMI_KCS
default n
help
Tested on X11SSH only. Different BMCs might not support these OEM
commands.
The following features are implemented:
* Communicates the BIOS version to the BMC
* Communicates the BIOS date to the BMC
1 change: 1 addition & 0 deletions src/drivers/ipmi/Makefile.inc
Expand Up @@ -2,6 +2,7 @@ ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_fru.c
ramstage-$(CONFIG_DRIVERS_IPMI_SUPERMICRO_OEM) += supermicro_oem.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs_ops_premem.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_ops.c
14 changes: 14 additions & 0 deletions src/drivers/ipmi/chip.h
@@ -1,8 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <device/device.h>

#ifndef _IMPI_CHIP_H_
#define _IPMI_CHIP_H_

#include <stdint.h>

struct drivers_ipmi_config {
u8 bmc_i2c_address;
u8 have_nv_storage;
Expand All @@ -11,6 +15,16 @@ struct drivers_ipmi_config {
u8 gpe_interrupt;
u8 have_apic;
u32 apic_interrupt;
/* Device to use for GPIO operations */
DEVTREE_CONST struct device *gpio_dev;
/*
* Jumper GPIO for enabling / disabling BMC/IPMI
* If present, the jumper overrides the devicetree.
*/
u32 bmc_jumper_gpio;
/* "POST complete" GPIO and polarity */
u32 post_complete_gpio;
bool post_complete_invert;
/*
* Wait for BMC to boot.
* This can be used if the BMC takes a long time to boot after PoR:
Expand Down
57 changes: 54 additions & 3 deletions src/drivers/ipmi/ipmi_kcs_ops.c
Expand Up @@ -9,8 +9,10 @@
*/

#include <arch/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <device/device.h>
#include <device/gpio.h>
#include <device/pnp.h>
#if CONFIG(HAVE_ACPI_TABLES)
#include <acpi/acpi.h>
Expand All @@ -23,6 +25,7 @@
#include <delay.h>
#include <timer.h>
#include "ipmi_kcs.h"
#include "ipmi_supermicro_oem.h"
#include "chip.h"

/* 4 bit encoding */
Expand All @@ -32,6 +35,8 @@ static u8 ipmi_revision_minor = 0x0;
static u8 bmc_revision_major = 0x0;
static u8 bmc_revision_minor = 0x0;

static struct boot_state_callback bscb_post_complete;

static int ipmi_get_device_id(struct device *dev, struct ipmi_devid_rsp *rsp)
{
int ret;
Expand Down Expand Up @@ -72,22 +77,62 @@ static int ipmi_get_bmc_self_test_result(struct device *dev, struct ipmi_selftes
return 0;
}

static void bmc_set_post_complete_gpio_callback(void *arg)
{
struct drivers_ipmi_config *conf = arg;
const struct gpio_operations *gpio_ops;

if (!conf || !conf->post_complete_gpio)
return;

gpio_ops = dev_get_gpio_ops(conf->gpio_dev);
if (!gpio_ops) {
printk(BIOS_WARNING, "IPMI: specified gpio device is missing gpio ops!\n");
return;
}

/* Set POST Complete pin. The `invert` field controls the polarity. */
gpio_ops->output(conf->post_complete_gpio, conf->post_complete_invert ^ 1);

printk(BIOS_DEBUG, "BMC: POST complete gpio set\n");
}

static void ipmi_kcs_init(struct device *dev)
{
struct ipmi_devid_rsp rsp;
uint32_t man_id = 0, prod_id = 0;
struct drivers_ipmi_config *conf = dev->chip_info;
const struct gpio_operations *gpio_ops;
struct ipmi_selftest_rsp selftestrsp = {0};
uint8_t retry_count;

if (!conf) {
printk(BIOS_WARNING, "IPMI: chip_info is missing! Skip init.\n");
return;
}

if (conf->bmc_jumper_gpio) {
gpio_ops = dev_get_gpio_ops(conf->gpio_dev);
if (!gpio_ops) {
printk(BIOS_WARNING, "IPMI: gpio device is missing gpio ops!\n");
} else {
/* Get jumper value and set device state accordingly */
dev->enabled = gpio_ops->get(conf->bmc_jumper_gpio);
if (!dev->enabled)
printk(BIOS_INFO, "IPMI: Disabled by jumper\n");
}
}

if (!dev->enabled)
return;

printk(BIOS_DEBUG, "IPMI: PNP KCS 0x%x\n", dev->path.pnp.port);

if (!conf) {
printk(BIOS_WARNING, "IPMI: chip_info is missing! Skip init.\n");
return;
/* Set up boot state callback for POST_COMPLETE# */
if (conf->post_complete_gpio) {
bscb_post_complete.callback = bmc_set_post_complete_gpio_callback;
bscb_post_complete.arg = conf;
boot_state_sched_on_entry(&bscb_post_complete, BS_PAYLOAD_BOOT);
}

/* Get IPMI version for ACPI and SMBIOS */
Expand Down Expand Up @@ -167,6 +212,12 @@ static void ipmi_kcs_init(struct device *dev)
/* Don't write tables if communication failed */
dev->enabled = 0;
}

if (!dev->enabled)
return;

if (CONFIG(DRIVERS_IPMI_SUPERMICRO_OEM))
supermicro_ipmi_oem(dev->path.pnp.port);
}

#if CONFIG(HAVE_ACPI_TABLES)
Expand Down
10 changes: 10 additions & 0 deletions src/drivers/ipmi/ipmi_supermicro_oem.h
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __IPMI_SUPERMICRO_OEM_H
#define __IPMI_SUPERMICRO_OEM_H

#include <stdint.h>

void supermicro_ipmi_oem(const uint16_t kcs_port);

#endif /* __IPMI_SUPERMICRO_OEM_H */
70 changes: 70 additions & 0 deletions src/drivers/ipmi/supermicro_oem.c
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <types.h>

#include <console/console.h>
#include <drivers/ipmi/ipmi_kcs.h>
#include <string.h>
#include <build.h>
#include "ipmi_supermicro_oem.h"

#define IPMI_NETFN_OEM 0x30
#define IPMI_LUN0_AC_SET_BIOS_VER 0x100
#define IPMI_LUN0_AC_SET_BIOS_DATE 0x101
#define IPMI_LUN0_SET_BIOS_STRING 0xac

struct ipmi_oem_set_bios_str {
uint16_t ver;
char str[16]; // NULL terminated string
} __packed;

static void set_coreboot_ver(const uint16_t kcs_port)
{
const char *coreboot_ver = COREBOOT_VERSION;
struct ipmi_oem_set_bios_str bios_ver;
struct ipmi_rsp rsp;
int ret;
size_t i;

/* Only 8 charactars are visible in UI. Cut of on first dash */
for (i = 0; i < 15; i++) {
if (coreboot_ver[i] == '-')
break;
bios_ver.str[i] = coreboot_ver[i];
}
bios_ver.str[i] = 0;
bios_ver.ver = IPMI_LUN0_AC_SET_BIOS_VER;

ret = ipmi_kcs_message(kcs_port, IPMI_NETFN_OEM, 0, IPMI_LUN0_SET_BIOS_STRING,
(const unsigned char *) &bios_ver, sizeof(bios_ver),
(unsigned char *) &rsp, sizeof(rsp));
if (ret < sizeof(rsp) || rsp.completion_code) {
printk(BIOS_ERR, "BMC_IPMI: %s command failed (ret=%d resp=0x%x)\n",
__func__, ret, rsp.completion_code);
}
}

static void set_coreboot_date(const uint16_t kcs_port)
{
struct ipmi_oem_set_bios_str bios_ver;
struct ipmi_rsp rsp;
int ret;

strncpy(bios_ver.str, COREBOOT_DMI_DATE, 15);
bios_ver.str[15] = 0;
bios_ver.ver = IPMI_LUN0_AC_SET_BIOS_DATE;

ret = ipmi_kcs_message(kcs_port, IPMI_NETFN_OEM, 0, IPMI_LUN0_SET_BIOS_STRING,
(const unsigned char *) &bios_ver, sizeof(bios_ver),
(unsigned char *) &rsp, sizeof(rsp));
if (ret < sizeof(rsp) || rsp.completion_code) {
printk(BIOS_ERR, "BMC_IPMI: %s command failed (ret=%d resp=0x%x)\n",
__func__, ret, rsp.completion_code);
}
}

void supermicro_ipmi_oem(const uint16_t kcs_port)
{
set_coreboot_ver(kcs_port);
set_coreboot_date(kcs_port);
}
2 changes: 1 addition & 1 deletion src/drivers/maxim/max77686/max77686.h
Expand Up @@ -48,7 +48,7 @@ enum max77686_regnum {
* @param vol_bitpos bit position to be set or clear within register
* @param vol_bitmask bit mask value
* @param reg_enaddr control register address, which enable the given
* given buck/ldo.
* buck/ldo.
* @param reg_enbitpos bit position to be enabled
* @param reg_enbiton value to be written to buck/ldo to make it ON
* @param reg_enbitoff value to be written to buck/ldo to make it OFF
Expand Down
1 change: 1 addition & 0 deletions src/drivers/ocp/dmi/Kconfig
Expand Up @@ -10,3 +10,4 @@ config OCP_DMI
config FRU_DEVICE_ID
int
default 0
depends on OCP_DMI
2 changes: 1 addition & 1 deletion src/drivers/smmstore/smi.c
Expand Up @@ -143,7 +143,7 @@ static uint32_t smmstorev2_exec(uint8_t command, void *param)

uint32_t smmstore_exec(uint8_t command, void *param)
{
if (!param)
if (command != SMMSTORE_CMD_CLEAR && !param)
return SMMSTORE_RET_FAILURE;

if (CONFIG(SMMSTORE_V2))
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/spi/tpm/tis.c
Expand Up @@ -31,7 +31,7 @@ static const char *tis_get_dev_name(struct tpm2_info *info)
int tis_open(void)
{
if (tpm_is_open) {
printk(BIOS_ERR, "tis_open() called twice.\n");
printk(BIOS_ERR, "%s() called twice.\n", __func__);
return -1;
}
return 0;
Expand Down
3 changes: 2 additions & 1 deletion src/drivers/spi/tpm/tpm.c
Expand Up @@ -74,7 +74,8 @@ __weak int tis_plat_irq_status(void)
static int warning_displayed;

if (!warning_displayed) {
printk(BIOS_WARNING, "WARNING: tis_plat_irq_status() not implemented, wasting 10ms to wait on Cr50!\n");
printk(BIOS_WARNING, "WARNING: %s() not implemented, wasting 10ms to wait on"
" Cr50!\n", __func__);
warning_displayed = 1;
}
mdelay(10);
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/ti/sn65dsi86bridge/sn65dsi86bridge.c
Expand Up @@ -10,8 +10,8 @@
#include <soc/addressmap.h>
#include "sn65dsi86bridge.h"

#define BRIDGE_GETHIGHERBYTE(x) (uint8_t)((x & 0xff00) >> 8)
#define BRIDGE_GETLOWERBYTE(x) (uint8_t)((x & 0x00ff))
#define BRIDGE_GETHIGHERBYTE(x) ((uint8_t)((x & 0xff00) >> 8))
#define BRIDGE_GETLOWERBYTE(x) ((uint8_t)(x & 0x00ff))

/* fudge factor required to account for 8b/10b encoding */
#define DP_CLK_FUDGE_NUM 10
Expand Down
11 changes: 11 additions & 0 deletions src/drivers/tpm/Kconfig
Expand Up @@ -5,3 +5,14 @@ config TPM_INIT
help
This driver automatically initializes the TPM if vboot is not used.
The TPM driver init is done during the ramstage chip init phase.

config TPM_PPI
bool "Generate ACPI code to implement TPM physical presence interface"
depends on TPM1 || TPM2
depends on HAVE_ACPI_TABLES
depends on !CHROMEOS
default y if PAYLOAD_TIANOCORE
help
This driver automatically generates ACPI tables for the Physical
Presence Interface defined by the TCG. If not activated only a stub
will be generated without any functionality.
4 changes: 4 additions & 0 deletions src/drivers/tpm/Makefile.inc
@@ -1,3 +1,7 @@
ramstage-$(CONFIG_TPM_INIT) += tpm.c

ifeq ($(CONFIG_TPM_PPI),y)
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += ppi.c
else
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += ppi_stub.c
endif
726 changes: 726 additions & 0 deletions src/drivers/tpm/ppi.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/drivers/tpm/ppi_stub.c
Expand Up @@ -18,8 +18,8 @@ static void tpm_ppi_func0_cb(void *arg)
static void tpm_ppi_func1_cb(void *arg)
{
if (CONFIG(TPM2))
/* Interface version: 2.0 */
acpigen_write_return_string("2.0");
/* Interface version: 1.3 */
acpigen_write_return_string("1.3");
else
/* Interface version: 1.2 */
acpigen_write_return_string("1.2");
Expand Down
90 changes: 89 additions & 1 deletion src/drivers/tpm/tpm_ppi.h
Expand Up @@ -4,6 +4,7 @@
#define _TPM_PPI_H_

#include <device/device.h>
#include <boot/coreboot_tables.h>

#if CONFIG(HAVE_ACPI_TABLES)
void tpm_ppi_acpi_fill_ssdt(const struct device *dev);
Expand All @@ -13,7 +14,6 @@ static inline void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
}
#endif


/* Return codes */
/* Function 2 */
#define PPI2_RET_SUCCESS 0
Expand Down Expand Up @@ -55,4 +55,92 @@ static inline void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
/* TCG Memory Clear Interface */
#define TPM_MCI_UUID "376054ed-cc13-4675-901c-4756d7f2d45d"

/*
* Physical Presence Interface Specification Version 1.30 Revision 00.52
* Table 1 Physical Presence Interface Operation Summary for TPM 1.2
*/
#define TPM_NOOP 0
#define TPM_ENABLE 1
#define TPM_DISABLE 2
#define TPM_ACTIVATE 3
#define TPM_DEACTIVATE 4
#define TPM_CLEAR 5
#define TPM_ENABLE_ACTIVATE 6
#define TPM_DEACTIVATE_DISABLE 7
#define TPM_SETOWNERINSTALL_TRUE 8
#define TPM_SETOWNERINSTALL_FALSE 9
#define TPM_ENABLE_ACTIVATE_SETOWNERINSTALL_TRUE 10
#define TPM_SETOWNERINSTALL_FALSE_DEACTIVATE_DISABLE 11
#define TPM_CLEAR_ENABLE_ACTIVATE 14
#define TPM_SET_NOPPIPROVISION_FALSE 15
#define TPM_SET_NOPPIPROVISION_TRUE 16
#define TPM_SET_NOPPICLEAR_FALSE 17
#define TPM_SET_NOPPICLEAR_TRUE 18
#define TPM_SET_NOPPIMAINTAINANCE_FALSE 19
#define TPM_SET_NOPPIMAINTAINANCE_TRUE 20
#define TPM_ENABLE_ACTIVE_CLEAR 21
#define TPM_ENABLE_ACTIVE_CLEAR_ENABLE_ACTIVE 22

/*
* Physical Presence Interface Specification Version 1.30 Revision 00.52
* Table 2 Physical Presence Interface Operation Summary for TPM 2.0
*/
#define TPM2_NOOP 0
#define TPM2_ENABLE 1
#define TPM2_DISABLE 2
#define TPM2_CLEAR 5
#define TPM2_CLEAR_ENABLE_ACTIVE 14
#define TPM2_SET_PP_REQUIRED_FOR_CLEAR_TRUE 17
#define TPM2_SET_PP_REQUIRED_FOR_CLEAR_FALSE 18
#define TPM2_ENABLE_CLEAR 21
#define TPM2_ENABLE_CLEAR2 22
#define TPM2_SET_PCR_BANKS 23
#define TPM2_CHANGE_EPS 24
#define TPM2_SET_PP_REQUIRED_FOR_CHANGE_PCRS_FALSE 25
#define TPM2_SET_PP_REQUIRED_FOR_CHANGE_PCRS_TRUE 26
#define TPM2_SET_PP_REQUIRED_FOR_TURN_ON_FALSE 27
#define TPM2_SET_PP_REQUIRED_FOR_TURN_ON_TRUE 28
#define TPM2_SET_PP_REQUIRED_FOR_TURN_OFF_FALSE 29
#define TPM2_SET_PP_REQUIRED_FOR_TURN_OFF_TRUE 30
#define TPM2_SET_PP_REQUIRED_FOR_CHANGE_EPS_FALSE 31
#define TPM2_SET_PP_REQUIRED_FOR_CHANGE_EPS_TRUE 32
#define TPM2_LOG_ALL_DIGEST 33
#define TPM2_DISABLE_ENDORSMENT_ENABLE_STORAGE_HISTORY 34
#define TPM2_ENABLE_BLOCK_SID 96
#define TPM2_DISABLE_BLOCK_SID 97
#define TPM2_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_TRUE 98
#define TPM2_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FALSE 99
#define TPM2_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_TRUE 100
#define TPM2_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FALSE 101

#define VENDOR_SPECIFIC_OFFSET 0x80

/*
* The layout of the buffer matches the QEMU virtual memory device that is generated
* by QEMU. See files 'hw/i386/acpi-build.c' and 'include/hw/acpi/tpm.h' for details.
*/
struct cb_tpm_ppi_payload_handshake {
uint8_t func[256]; /* Firmware sets values for each supported operation.
* See defined values below. */
uint8_t ppin; /* SMI interrupt to use. Set by firmware.
* Not supported. */
uint32_t ppip; /* ACPI function index to pass to SMM code.
* Set by ACPI. Not supported. */
uint32_t pprp; /* Result of last executed operation.
* Set by firmware. See function index 5 for values. */
uint32_t pprq; /* Operation request number to execute.
* See 'Physical Presence Interface Operation Summary'
* tables in specs. Set by ACPI. */
uint32_t pprm; /* Operation request optional parameter.
* Values depend on operation. Set by ACPI. */
uint32_t lppr; /* Last executed operation request number.
* Copied from pprq field by firmware. */
uint32_t fret; /* Result code from SMM function. Not supported. */
uint8_t res1[0x040]; /* Reserved */
uint8_t next_step; /* Operation to execute after reboot by firmware.
* Used by firmware. */
} __packed;

void lb_tpm_ppi(struct lb_header *header);

#endif /* _TPM_PPI_H_ */
19 changes: 19 additions & 0 deletions src/drivers/vpd/Kconfig
Expand Up @@ -5,3 +5,22 @@ config VPD
default n
help
Enable support for flash based vital product data.

config VPD_FMAP_NAME
string
depends on VPD
default "RO_VPD"
help
Name of the FMAP region created in the default FMAP to store VPD tables.

config VPD_FMAP_SIZE
hex
depends on VPD
default 0x4000
help
Size in bytes of the FMAP region created to store VPD tables.

config SMBIOS_SERIAL_FROM_VPD
bool "Load device serial from VPD"
depends on VPD && GENERATE_SMBIOS_TABLES
default n
1 change: 1 addition & 0 deletions src/drivers/vpd/Makefile.inc
Expand Up @@ -5,3 +5,4 @@ verstage-$(CONFIG_VPD) += vpd_decode.c vpd.c
romstage-$(CONFIG_VPD) += vpd_decode.c vpd.c
postcar-$(CONFIG_VPD) += vpd_decode.c vpd.c
ramstage-$(CONFIG_VPD) += vpd_decode.c vpd.c
ramstage-$(CONFIG_SMBIOS_SERIAL_FROM_VPD) += vpd_serial.c
23 changes: 23 additions & 0 deletions src/drivers/vpd/vpd.c
Expand Up @@ -3,10 +3,12 @@
#include <assert.h>
#include <console/console.h>
#include <cbmem.h>
#include <ctype.h>
#include <fmap.h>
#include <program_loading.h>
#include <string.h>
#include <timestamp.h>
#include <types.h>

#include "vpd.h"
#include "vpd_decode.h"
Expand Down Expand Up @@ -274,4 +276,25 @@ bool vpd_get_bool(const char *key, enum vpd_region region, uint8_t *val)
return false;
}

/*
* Find value of integer type by vpd key.
*
* Expects to find a decimal string, trailing chars are ignored.
* Returns true if the key is found and the value is not too long and
* starts with a decimal digit. Leaves `val` untouched if unsuccessful.
*/
bool vpd_get_int(const char *const key, const enum vpd_region region, int *const val)
{
char value[11];

if (!vpd_gets(key, value, sizeof(value), region))
return false;

if (!isdigit(*value))
return false;

*val = (int)atol(value);
return true;
}

ROMSTAGE_CBMEM_INIT_HOOK(cbmem_add_cros_vpd)
9 changes: 9 additions & 0 deletions src/drivers/vpd/vpd.h
Expand Up @@ -50,4 +50,13 @@ const void *vpd_find(const char *key, int *size, enum vpd_region region);
bool vpd_get_bool(const char *key, enum vpd_region region,
uint8_t *val);

/*
* Find value of integer type by vpd key.
*
* Expects to find a decimal string, trailing chars are ignored.
* Returns true if the key is found and the value is not too long and
* starts with a decimal digit.
*/
bool vpd_get_int(const char *key, enum vpd_region region, int *val);

#endif /* __VPD_H__ */
26 changes: 26 additions & 0 deletions src/drivers/vpd/vpd_serial.c
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#include <smbios.h>

#include "vpd.h"
#include "vpd_tables.h"

#define VPD_KEY_SYSTEM_SERIAL "serial_number"
#define VPD_KEY_MAINBOARD_SERIAL "mlb_serial_number"
#define VPD_SERIAL_LEN 64

const char *smbios_system_serial_number(void)
{
static char serial[VPD_SERIAL_LEN];
if (vpd_gets(VPD_KEY_SYSTEM_SERIAL, serial, VPD_SERIAL_LEN, VPD_RO))
return serial;
return "";
}

const char *smbios_mainboard_serial_number(void)
{
static char serial[VPD_SERIAL_LEN];
if (vpd_gets(VPD_KEY_MAINBOARD_SERIAL, serial, VPD_SERIAL_LEN, VPD_RO))
return serial;
return "";
}
38 changes: 19 additions & 19 deletions src/ec/acpi/ec.asl
Expand Up @@ -45,8 +45,8 @@ Field(ERDT, ByteAcc, NoLock, Preserve) { EC_DATA, 8 }
*/
Method (WAIT_EC_SC, 2)
{
Store (0x7ff, Local0) /* Timeout */
While (LAnd (LNotEqual (And (EC_SC, Arg0), Arg1), Decrement (Local0))) {
Local0 = 0x7ff /* Timeout */
While (((EC_SC & Arg0) != Arg1) && Local0--) {
Stall (10)
}
If (Local0) {
Expand All @@ -66,8 +66,8 @@ Method (WAIT_EC_SC, 2)
*/
Method (SEND_EC_COMMAND, 1)
{
Store (WAIT_EC_SC (EC_IBF, 0), Local0)
If (LNot (Local0)) {
Local0 = WAIT_EC_SC (EC_IBF, 0)
If (!Local0) {
Store (Arg0, EC_SC)
}
Return (Local0)
Expand All @@ -83,9 +83,9 @@ Method (SEND_EC_COMMAND, 1)
*/
Method (SEND_EC_DATA, 1)
{
Store (WAIT_EC_SC (EC_IBF, 0), Local0)
If (LNot (Local0)) {
Store (Arg0, EC_DATA)
Local0 = WAIT_EC_SC (EC_IBF, 0)
If (!Local0) {
EC_DATA = Arg0
}
Return (Local0)
}
Expand All @@ -100,8 +100,8 @@ Method (SEND_EC_DATA, 1)
*/
Method (RECV_EC_DATA)
{
Store (WAIT_EC_SC (EC_OBF, EC_OBF), Local0)
If (LNot (Local0)) {
Local0 = WAIT_EC_SC (EC_OBF, EC_OBF)
If (!Local0) {
Return (EC_DATA)
} Else {
Return (Local0)
Expand All @@ -117,12 +117,12 @@ Method (RECV_EC_DATA)
Method (EC_READ, 1)
{
Acquire (EC_MUTEX, 0xffff)
Store (SEND_EC_COMMAND (EC_READ_CMD), Local0)
If (LNot (Local0)) {
Store (SEND_EC_DATA (Arg0), Local0)
Local0 = SEND_EC_COMMAND (EC_READ_CMD)
If (!Local0) {
Local0 = SEND_EC_DATA (Arg0)
}
If (LNot (Local0)) {
Store (RECV_EC_DATA (), Local0)
If (!Local0) {
Local0 = RECV_EC_DATA ()
}
Release (EC_MUTEX)

Expand All @@ -139,12 +139,12 @@ Method (EC_READ, 1)
Method (EC_WRITE, 2)
{
Acquire (EC_MUTEX, 0xffff)
Store (SEND_EC_COMMAND (EC_WRITE_CMD), Local0)
If (LNot (Local0)) {
Store (SEND_EC_DATA (Arg0), Local0)
Local0 = SEND_EC_COMMAND (EC_WRITE_CMD)
If (!Local0) {
Local0 = SEND_EC_DATA (Arg0)
}
If (LNot (Local0)) {
Store (SEND_EC_DATA (Arg1), Local0)
If (!Local0) {
Local0 = SEND_EC_DATA (Arg1)
}
Release (EC_MUTEX)

Expand Down
2 changes: 1 addition & 1 deletion src/ec/acpi/ec.c
Expand Up @@ -84,7 +84,7 @@ u8 recv_ec_data(void)
udelay(10);

data = inb(ec_data_reg);
printk(BIOS_SPEW, "recv_ec_data: 0x%02x\n", data);
printk(BIOS_SPEW, "%s: 0x%02x\n", __func__, data);

return data;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ec/compal/ene932/acpi/ac.asl
Expand Up @@ -9,7 +9,7 @@ Device (AC)

Method (_PSR)
{
Store(ADPT, Local0)
Local0 = ADPT
Return(Local0)
}

Expand Down
68 changes: 34 additions & 34 deletions src/ec/compal/ene932/acpi/battery.asl
Expand Up @@ -38,13 +38,13 @@ Device (BATX)
// Method to enable full battery workaround
Method (BFWE)
{
Store (One, BFWK)
BFWK = 1
}

// Method to disable full battery workaround
Method (BFWD)
{
Store (Zero, BFWK)
BFWK = 0
}

Method (_STA, 0, Serialized)
Expand All @@ -59,22 +59,22 @@ Device (BATX)
Method (_BIF, 0, Serialized)
{
// Update fields from EC
Store (BAM0, Index (PBIF, 0))
Store (BDC0, Index (PBIF, 1))
Store (BFC0, Index (PBIF, 2))
Store (BDV0, Index (PBIF, 4))
Divide(BFC0, 0x64, , Local1)
Multiply(Local1, 0x0A, Local1)
Store(Local1, Index(PBIF, 5))
Divide(BFC0, 0x64, , Local1)
Multiply(Local1, 0x03, Local1)
Store (Local1, Index (PBIF, 6))

Store (ToString(Concatenate(BATD, 0x00)), Index (PBIF, 9)) // model
Store (ToHexString(BSN0), Index (PBIF, 10)) // serial
Store (ToString(BMFN), Index (PBIF, 12)) // vendor

Store(BDN0, BTNM) // Save the battery number
PBIF [0] = BAM0
PBIF [1] = BDC0
PBIF [2] = BFC0
PBIF [4] = BDV0
Local1 = BFC0 / 100
Local1 *= 10
PBIF [5] = Local1
Local1 = BFC0 / 100
Local1 *= 3
PBIF [6] = Local1

PBIF [9] = ToString (Concatenate (BATD, 0x00)) // model
PBIF [10] = ToHexString (BSN0) // serial
PBIF [12] = ToString (BMFN) // vendor

BTNM = BDN0 // Save the battery number

Return (PBIF)
}
Expand All @@ -90,47 +90,47 @@ Device (BATX)
//

// Get battery state from EC and save it for the charging workaround
Store (BST0, Local0)
Store (Local0, Index (PBST, 0))
Local0 = BST0
PBST [0] = Local0

//
// 1: BATTERY PRESENT RATE/CURRENT
//

Store (BAC0, Local1)
Subtract(0xFFFF, Local1, Local1)
Store (Local1, Index (PBST, 1))
Local1 = BAC0
Local1 = 0xFFFF - Local1
PBST [1] = Local1

//
// 2: BATTERY REMAINING CAPACITY
//
Multiply(BFC0, GAU0, Local1)
Divide(Local1, 0x64, Local2, Local1)
Local1 = BFC0 * GAU0
Local2 = Local1 % 100
Local1 /= 100

If (LAnd (BFWK, LAnd (ADPT, LNot (Local0)))) {
If (BFWK && ADPT && !Local0) {
// On AC power and battery is neither charging
// nor discharging. Linux expects a full battery
// to report same capacity as last full charge.
// https://bugzilla.kernel.org/show_bug.cgi?id=12632
Store (GAU0, Local2)
Local2 = GAU0

// See if within ~3% of full
ShiftRight (Local2, 5, Local3)
If (LAnd (LGreater (Local1, Subtract (Local2, Local3)),
LLess (Local1, Add (Local2, Local3))))
Local3 = Local2 >> 5
If ((Local1 > (Local2 - Local3)) && (Local1 < (Local2 + Local3)))
{
Store (Local2, Local1)
Local1 = Local2
}
}
Store (Local1, Index (PBST, 2))
PBST [2] = Local1

//
// 3: BATTERY PRESENT VOLTAGE
//
Store (BPV0, Index (PBST, 3))
PBST [3] = BPV0

// Check the Battery Number
If(LNotEqual(BDN0, BTNM)) {
If(BDN0 != BTNM) {
Notify(BATX, 0x81)
}

Expand Down
12 changes: 6 additions & 6 deletions src/ec/compal/ene932/acpi/ec.asl
Expand Up @@ -252,12 +252,12 @@ Device (EC0)
Method (_REG, 2, NotSerialized)
{
// Initialize AC power state
Store (ADPT, \PWRS)
\PWRS = ADPT

// Force a read of CPU temperature
Store (CTML, Local0)
Local0 = CTML
/* So that we don't get a warning that Local0 is unused. */
Increment (Local0)
Local0++
}


Expand Down Expand Up @@ -322,7 +322,7 @@ Device (EC0)
// AC Power Connected
Method (_Q37, 0, NotSerialized)
{
Store (One, \PWRS)
\PWRS = 1
Notify (AC, 0x80)
Notify (BATX, 0x80)
// TODO ADD CPU power profile
Expand All @@ -332,7 +332,7 @@ Device (EC0)
// AC Power Removed
Method (_Q38, 0, NotSerialized)
{
Store (Zero, \PWRS)
\PWRS = 0
Notify (AC, 0x80)
Notify (BATX, 0x80)
// TODO ADD CPU power profile
Expand Down Expand Up @@ -363,7 +363,7 @@ Device (EC0)
{
IF(WLEX) //if Wlan exist
{
//TODO Store(WLAT, LANE)
//TODO LANE = WLAT
}
}

Expand Down
1 change: 1 addition & 0 deletions src/ec/google/chromeec/acpi/ec.asl
Expand Up @@ -81,6 +81,7 @@ Device (EC0)
Offset (0x12),
BTID, 8, // Battery index that host wants to read
USPP, 8, // USB Port Power
RFWU, 8, // Retimer Firmware Update
}

#if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
Expand Down
24 changes: 22 additions & 2 deletions src/ec/google/chromeec/ec.c
Expand Up @@ -863,6 +863,11 @@ int google_chromeec_cbi_get_board_version(uint32_t *version)
return cbi_get_uint32(version, CBI_TAG_BOARD_VERSION);
}

int google_chromeec_cbi_get_ssfc(uint32_t *ssfc)
{
return cbi_get_uint32(ssfc, CBI_TAG_SSFC);
}

static int cbi_get_string(char *buf, size_t bufsize, uint32_t tag)
{
struct ec_params_get_cbi params = {
Expand Down Expand Up @@ -993,9 +998,24 @@ static uint16_t google_chromeec_get_uptime_info(

bool google_chromeec_get_ap_watchdog_flag(void)
{
int i;
struct ec_response_uptime_info resp;
return (!google_chromeec_get_uptime_info(&resp) &&
(resp.ec_reset_flags & EC_RESET_FLAG_AP_WATCHDOG));

if (google_chromeec_get_uptime_info(&resp))
return false;

if (resp.ec_reset_flags & EC_RESET_FLAG_AP_WATCHDOG)
return true;

/* Find the last valid entry */
for (i = ARRAY_SIZE(resp.recent_ap_reset) - 1; i >= 0; i--) {
if (resp.recent_ap_reset[i].reset_time_ms == 0)
continue;
return (resp.recent_ap_reset[i].reset_cause ==
CHIPSET_RESET_AP_WATCHDOG);
}

return false;
}

int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen,
Expand Down
5 changes: 3 additions & 2 deletions src/ec/google/chromeec/ec.h
Expand Up @@ -29,7 +29,7 @@ void google_chromeec_init(void);
int google_chromeec_pd_get_amode(uint16_t svid);
/* Check for the current mux state in EC
* in: int port physical port number of the type-c port
* out: uint8_t flags flags representing the status of the mux such as
* out: uint8_t flags representing the status of the mux such as
* usb capability, dp capability, cable type, etc
*/
int google_chromeec_usb_get_pd_mux_info(int port, uint8_t *flags);
Expand Down Expand Up @@ -78,7 +78,7 @@ int google_chromeec_reboot(int dev_idx, enum ec_reboot_cmd type, uint8_t flags);
/**
* Get data from Cros Board Info
*
* @param id/fw_config/buf [OUT] value from from CBI.
* @param id/fw_config/buf [OUT] value from CBI.
* @return 0 on success or negative integer for errors.
*/
int google_chromeec_cbi_get_oem_id(uint32_t *id);
Expand All @@ -89,6 +89,7 @@ int google_chromeec_cbi_get_oem_name(char *buf, size_t bufsize);
/* version may be stored in CBI as a smaller integer width, but the EC code
handles it correctly. */
int google_chromeec_cbi_get_board_version(uint32_t *version);
int google_chromeec_cbi_get_ssfc(uint32_t *ssfc);

#define CROS_SKU_UNKNOWN 0xFFFFFFFF
#define CROS_SKU_UNPROVISIONED 0x7FFFFFFF
Expand Down
28 changes: 28 additions & 0 deletions src/ec/google/chromeec/ec_acpi.c
Expand Up @@ -7,6 +7,7 @@
#include <acpi/acpigen_usb.h>
#include <console/console.h>
#include <drivers/usb/acpi/chip.h>
#include <drivers/intel/usb4/retimer/retimer.h>
#include <ec/google/common/dptf.h>

#include "chip.h"
Expand Down Expand Up @@ -235,3 +236,30 @@ void google_chromeec_fill_ssdt_generator(const struct device *dev)
fill_ssdt_typec_device(dev);
fill_ssdt_ps2_keyboard(dev);
}

const char *ec_retimer_fw_update_path(void)
{
return "\\_SB_.PCI0.LPCB.EC0_.RFWU";
}

void ec_retimer_fw_update(void *arg)
{
const char *RFWU = ec_retimer_fw_update_path();

/*
* Get information to set retimer info from Arg3[0]
* Local0 = DeRefOf (Arg3[0])
*/
acpigen_get_package_op_element(ARG3_OP, 0, LOCAL0_OP);

/*
* Write the EC RAM for Retimer Upgrade
* RFWU = LOCAL0
*/
acpigen_write_store();
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_namestring(RFWU);

/* Return (Zero) */
acpigen_write_return_integer(0);
}