Arthur Heymans (arthur(a)aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18320
-gerrit
commit e66f2169f8cc2f8f977ed2265abde5fb3d615baf
Author: Arthur Heymans <arthur(a)aheymans.xyz>
Date: Fri Feb 10 12:08:16 2017 +0100
device/dram/ddr2: Add common function to select common CAS en freq
This function has CAS and Frequency masks as inputs to support
northbridges that have different limits on those. The CAS mask is
used as defined in SPD and frequency mask is bitwise mask for
supported frequency so e.g. : DDR2_200MH is (1 << 0), DDR2_266MHZ
is (1 << 1), etc.
Change-Id: I3ab39d38a243edddfde8f70ebd23f79ff774e90e
Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz>
---
src/device/dram/ddr2.c | 86 ++++++++++++++++++++++++++++++++++++++++++
src/include/device/dram/ddr2.h | 15 +++++++-
2 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/src/device/dram/ddr2.c b/src/device/dram/ddr2.c
index b712192..f520904 100644
--- a/src/device/dram/ddr2.c
+++ b/src/device/dram/ddr2.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2017 Patrick Rudolph <siro(a)das-labor.org>
+ * Copyright (C) 2017 Arthur Heymans <arthur(a)aheymans.xyz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -110,6 +111,21 @@ static u8 spd_get_msbs(u8 c)
}
/**
+ * \brief Return index of MSB set
+ *
+ * Returns the index fof MSB set.
+ */
+static u8 spd_get_lsbs(u8 c)
+{
+ int i;
+ for (i = 0; i > 7; i++)
+ if (c & (1 << i))
+ return i;
+
+ return 0;
+}
+
+/**
* \brief Decode SPD tck cycle time
*
* Decodes a raw SPD data from a DDR2 DIMM.
@@ -593,3 +609,73 @@ void dram_print_spd_ddr2(const dimm_attr *dimm)
print_us(" tPLL : ", dimm->tPLL);
print_us(" tRR : ", dimm->tRR);
}
+
+int get_common_freq_cas(u8 freq_mask, u8 cas_mask, const dimm_attr **dimm,
+ int num_dimms, u8 *selected_freq, u8 *selected_cas)
+{
+ int i, found, high_supp_cas, low_supp_cas;
+ u8 curr_freq, curr_cas;
+
+ const int ddr2_speeds_table[] = {
+ TCK_200MHZ,
+ TCK_266MHZ,
+ TCK_333MHZ,
+ TCK_400MHZ,
+ TCK_533MHZ,
+ TCK_666MHZ,
+ TCK_700MHZ,
+ TCK_800MHZ,
+ };
+
+ for (i = 0; i < num_dimms; i++) {
+ if (dimm[i]->dimm_type == SPD_DIMM_TYPE_UNDEFINED)
+ continue;
+ cas_mask &= dimm[i]->cas_supported;
+ }
+
+ if (!cas_mask) {
+ printk(BIOS_DEBUG, "No common supported CAS\n");
+ return 1;
+ }
+
+ high_supp_cas = spd_get_msbs(cas_mask);
+ low_supp_cas = spd_get_lsbs(cas_mask);
+
+ /* Loop from fast to slow frequency, from low to high CAS latency */
+ for (curr_freq = spd_get_msbs(freq_mask);
+ curr_freq >= spd_get_lsbs(freq_mask); curr_freq--) {
+ printram("Trying speed: %d\n", curr_freq);
+ for (curr_cas = low_supp_cas;
+ curr_cas <= low_supp_cas; curr_cas++) {
+ printram(" Trying CAS: %d\n"; curr_freq);
+ found = 1;
+ for (i = 0; i < num_dimms; i++) {
+ if (dimm[i]->dimm_type ==
+ SPD_DIMM_TYPE_UNDEFINED)
+ continue;
+
+ printram(" Testing DIMM: %d\n", i);
+ if (dimm[i]->cycle_time[curr_cas] == 0) {
+ printram(" CAS not supported");
+ found = 0;
+ break;
+ }
+
+ if (dimm[i]->cycle_time[curr_cas] >
+ ddr2_speeds_table[curr_freq]) {
+ printram(" Timing too fast\n");
+ found = 0;
+ break;
+ }
+ }
+ if (found) {
+ *selected_freq = curr_freq;
+ *selected_cas = curr_cas;
+ return 0;
+ }
+ }
+ }
+
+ printk(BIOS_DEBUG, "No common CAS Frequency combination possible!\n");
+ return 1;
+}
diff --git a/src/include/device/dram/ddr2.h b/src/include/device/dram/ddr2.h
index 236be49..24d3379 100644
--- a/src/include/device/dram/ddr2.h
+++ b/src/include/device/dram/ddr2.h
@@ -46,6 +46,18 @@
#define TCK_333MHZ 768
#define TCK_266MHZ 960
#define TCK_200MHZ 1280
+
+enum dram_freq {
+ DDR2_200MHZ,
+ DDR2_266MHZ,
+ DDR2_333MHZ,
+ DDR2_400MHZ,
+ DDR2_533MHZ,
+ DDR2_666MHZ,
+ DDR2_700MHZ,
+ DDR2_800MHZ,
+};
+
/** @} */
/**
@@ -198,6 +210,7 @@ u32 spd_decode_spd_size_ddr2(u8 byte0);
u32 spd_decode_eeprom_size_ddr2(u8 byte1);
int spd_decode_ddr2(dimm_attr *dimm, spd_raw_data spd);
void dram_print_spd_ddr2(const dimm_attr *dimm);
-
+int get_common_freq_cas(u8 freq_mask, u8 cas_mask, const dimm_attr **dimm,
+ int num_dimms, u8 *selected_freq, u8 *selected_cas);
#endif /* DEVICE_DRAM_DDR2L_H */
Subrata Banik (subrata.banik(a)intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18287
-gerrit
commit 72258324998c72b8562c8d007446ceecc1a9718c
Author: Subrata Banik <subrata.banik(a)intel.com>
Date: Fri Feb 3 18:57:49 2017 +0530
soc/intel/skylake: Perform CPU MP Init before FSP-S Init
As per BWG, CPU MP Init (loading ucode) should be done prior
to BIOS_RESET_CPL. Hence, pull MP Init to BS_DEV_INIT_CHIPS Entry
(before FSP-S call).
BUG=chrome-os-partner:62438
BRANCH=NONE
TEST=Boot to OS with all threads enabled.
Change-Id: Ia6f83d466fb27e1290da84abe7832dc814b5273a
Signed-off-by: Subrata Banik <subrata.banik(a)intel.com>
---
src/soc/intel/skylake/chip.c | 4 +--
src/soc/intel/skylake/chip_fsp20.c | 4 +--
src/soc/intel/skylake/cpu.c | 33 +++++++++++++++-------
src/soc/intel/skylake/include/fsp11/soc/ramstage.h | 3 +-
src/soc/intel/skylake/include/fsp20/soc/ramstage.h | 3 +-
5 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/src/soc/intel/skylake/chip.c b/src/soc/intel/skylake/chip.c
index c64a8df..060c4ee 100644
--- a/src/soc/intel/skylake/chip.c
+++ b/src/soc/intel/skylake/chip.c
@@ -2,7 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
- * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,7 +49,7 @@ static struct device_operations pci_domain_ops = {
};
static struct device_operations cpu_bus_ops = {
- .init = &soc_init_cpus,
+ .init = DEVICE_NOOP,
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
.acpi_fill_ssdt_generator = generate_cpu_entries,
#endif
diff --git a/src/soc/intel/skylake/chip_fsp20.c b/src/soc/intel/skylake/chip_fsp20.c
index ebd3134..f1a32c4 100644
--- a/src/soc/intel/skylake/chip_fsp20.c
+++ b/src/soc/intel/skylake/chip_fsp20.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2016 Intel Corporation.
+ * Copyright (C) 2016-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@ static struct device_operations cpu_bus_ops = {
.read_resources = DEVICE_NOOP,
.set_resources = DEVICE_NOOP,
.enable_resources = DEVICE_NOOP,
- .init = &soc_init_cpus,
+ .init = DEVICE_NOOP,
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
.acpi_fill_ssdt_generator = generate_cpu_entries,
#endif
diff --git a/src/soc/intel/skylake/cpu.c b/src/soc/intel/skylake/cpu.c
index e8616f0..684680d 100644
--- a/src/soc/intel/skylake/cpu.c
+++ b/src/soc/intel/skylake/cpu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2014 Google Inc.
- * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,6 +15,7 @@
* GNU General Public License for more details.
*/
+#include <bootstate.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
@@ -397,13 +398,6 @@ static const struct cpu_driver driver __cpu_driver = {
static const void *microcode_patch;
static int ht_disabled;
-static void pre_mp_init(void)
-{
- /* Setup MTRRs based on physical address size. */
- x86_setup_mtrrs_with_detect();
- x86_mtrr_check();
-}
-
static int get_cpu_count(void)
{
msr_t msr;
@@ -463,7 +457,12 @@ static void post_mp_init(void)
}
static const struct mp_ops mp_ops = {
- .pre_mp_init = pre_mp_init,
+ /*
+ * Skip Pre MP init MTRR programming as MTRRs are mirrored from BSP,
+ * that are set prior to ramstage.
+ * Real MTRRs programming are being done after resource allocation.
+ */
+ .pre_mp_init = NULL,
.get_cpu_count = get_cpu_count,
.get_smm_info = smm_info,
.get_microcode_info = get_microcode_info,
@@ -474,8 +473,9 @@ static const struct mp_ops mp_ops = {
.post_mp_init = post_mp_init,
};
-void soc_init_cpus(device_t dev)
+static void soc_init_cpus(void *unused)
{
+ device_t dev = dev_find_path(NULL, DEVICE_PATH_CPU_CLUSTER);
struct bus *cpu_bus = dev->link_list;
if (mp_init_with_smm(cpu_bus, &mp_ops)) {
@@ -486,6 +486,13 @@ void soc_init_cpus(device_t dev)
configure_thermal_target();
}
+/* Ensure to re-program all MTRRs based on DRAM resource settings */
+static void soc_post_cpus_init(void *unused)
+{
+ if (mp_run_on_all_cpus(&x86_setup_mtrrs_with_detect, 1000) < 0)
+ printk(BIOS_ERR, "MTRR programming failure\n");
+}
+
int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id)
{
msr_t msr;
@@ -498,3 +505,9 @@ int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id)
msr = rdmsr(MTRR_CAP_MSR);
return (msr.lo & PRMRR_SUPPORTED) && (current_patch_id == new_patch_id - 1);
}
+
+/*
+ * Do CPU MP Init before FSP Silicon Init
+ */
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, soc_init_cpus, NULL);
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, soc_post_cpus_init, NULL);
\ No newline at end of file
diff --git a/src/soc/intel/skylake/include/fsp11/soc/ramstage.h b/src/soc/intel/skylake/include/fsp11/soc/ramstage.h
index 8df7796..f1a9e53 100644
--- a/src/soc/intel/skylake/include/fsp11/soc/ramstage.h
+++ b/src/soc/intel/skylake/include/fsp11/soc/ramstage.h
@@ -2,7 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
- * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,6 @@
void soc_irq_settings(FSP_SIL_UPD *params);
void pch_enable_dev(device_t dev);
void soc_init_pre_device(void *chip_info);
-void soc_init_cpus(device_t dev);
const char *soc_acpi_name(struct device *dev);
int init_igd_opregion(igd_opregion_t *igd_opregion);
extern struct pci_operations soc_pci_ops;
diff --git a/src/soc/intel/skylake/include/fsp20/soc/ramstage.h b/src/soc/intel/skylake/include/fsp20/soc/ramstage.h
index 0ae87f4..136c4f2 100644
--- a/src/soc/intel/skylake/include/fsp20/soc/ramstage.h
+++ b/src/soc/intel/skylake/include/fsp20/soc/ramstage.h
@@ -2,7 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
- * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015-2017 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,6 @@
void mainboard_silicon_init_params(FSP_S_CONFIG *params);
void pch_enable_dev(device_t dev);
void soc_init_pre_device(void *chip_info);
-void soc_init_cpus(device_t dev);
void soc_irq_settings(FSP_SIL_UPD *params);
const char *soc_acpi_name(struct device *dev);
Rizwan Qureshi (rizwan.qureshi(a)intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18211
-gerrit
commit fea57bfe71bffb02c79590a943e6319dd606436a
Author: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
Date: Fri Jan 13 22:17:01 2017 +0530
driver/i2c/max98927: add i2c driver for Maxim 98927 codec
Maxim 98927 kernel driver requires entries in the ACPI SSDT table,
add a SSDT generator as part of this driver.
BUG=None
BRANCH=None
TEST=After boot, dump and verify that the generated SSDT ACPI table has the
required entries.
Change-Id: Ic2d4d8449288bc00d085852220b2e1e7a208e9ef
Signed-off-by: Naresh G Solanki <naresh.solanki(a)intel.com>
Signed-off-by: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
Signed-off-by: M Naveen <naveen.m(a)intel.com>
Signed-off-by: Dylan Reid <dgreid(a)chromium.org>
---
src/drivers/i2c/max98927/Kconfig | 2 +
src/drivers/i2c/max98927/Makefile.inc | 1 +
src/drivers/i2c/max98927/chip.h | 30 ++++++++++
src/drivers/i2c/max98927/max98927.c | 108 ++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+)
diff --git a/src/drivers/i2c/max98927/Kconfig b/src/drivers/i2c/max98927/Kconfig
new file mode 100644
index 0000000..1007442
--- /dev/null
+++ b/src/drivers/i2c/max98927/Kconfig
@@ -0,0 +1,2 @@
+config DRIVERS_I2C_MAX98927
+ bool
diff --git a/src/drivers/i2c/max98927/Makefile.inc b/src/drivers/i2c/max98927/Makefile.inc
new file mode 100644
index 0000000..3bafee1
--- /dev/null
+++ b/src/drivers/i2c/max98927/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_I2C_MAX98927) += max98927.c
diff --git a/src/drivers/i2c/max98927/chip.h b/src/drivers/i2c/max98927/chip.h
new file mode 100644
index 0000000..d63244f
--- /dev/null
+++ b/src/drivers/i2c/max98927/chip.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Maxim MAX98927 audio codec devicetree bindings
+ */
+struct drivers_i2c_max98927_config {
+ /* I2C Bus Frequency in Hertz (default 400kHz) */
+ unsigned int bus_speed;
+ /* Set ‘1’ if I2S channel size is not 32bit. */
+ unsigned int interleave_mode;
+ /*Identifier for chips*/
+ unsigned int uid;
+ /* Device Description */
+ const char *desc;
+ /* ACPI Device Name */
+ const char *name;
+};
diff --git a/src/drivers/i2c/max98927/max98927.c b/src/drivers/i2c/max98927/max98927.c
new file mode 100644
index 0000000..1f5fabf
--- /dev/null
+++ b/src/drivers/i2c/max98927/max98927.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpi_device.h>
+#include <arch/acpigen.h>
+#include <console/console.h>
+#include <device/i2c.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <stdint.h>
+#include <string.h>
+#include "chip.h"
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+
+#define MAX98927_ACPI_NAME "MAXI"
+#define MAX98927_ACPI_HID "MX98927"
+
+#define MAX98927_DP_INT(key, val) \
+ acpi_dp_add_integer(dp, "maxim," key, (val))
+
+static void max98927_fill_ssdt(struct device *dev)
+{
+ struct drivers_i2c_max98927_config *config = dev->chip_info;
+ const char *scope = acpi_device_scope(dev);
+ struct acpi_i2c i2c = {
+ .address = dev->path.i2c.device,
+ .mode_10bit = dev->path.i2c.mode_10bit,
+ .speed = config->bus_speed ? : I2C_SPEED_FAST,
+ .resource = scope,
+ };
+ struct acpi_dp *dp = NULL;
+
+ if (!dev->enabled || !scope)
+ return;
+
+ /* Device */
+ acpigen_write_scope(scope);
+ acpigen_write_device(acpi_device_name(dev));
+ acpigen_write_name_string("_HID", MAX98927_ACPI_HID);
+ acpigen_write_name_integer("_UID", config->uid);
+ acpigen_write_name_string("_DDN", config->desc);
+ acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
+
+ /* Resources */
+ acpigen_write_name("_CRS");
+ acpigen_write_resourcetemplate_header();
+ acpi_device_write_i2c(&i2c);
+ acpigen_write_resourcetemplate_footer();
+
+ /* Device Properties */
+ dp = acpi_dp_new_table("_DSD");
+
+ acpi_dp_add_integer(dp, "interleave_mode", config->interleave_mode);
+
+ acpi_dp_write(dp);
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s address 0%xh\n",
+ acpi_device_path(dev), dev->chip_ops->name,
+ dev->path.i2c.device);
+}
+
+static const char *max98927_acpi_name(struct device *dev)
+{
+ struct drivers_i2c_max98927_config *config = dev->chip_info;
+
+ if (config->name)
+ return config->name;
+
+ return MAX98927_ACPI_NAME;
+}
+#endif
+
+static struct device_operations max98927_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ .acpi_name = &max98927_acpi_name,
+ .acpi_fill_ssdt_generator = &max98927_fill_ssdt,
+#endif
+};
+
+static void max98927_enable(struct device *dev)
+{
+ dev->ops = &max98927_ops;
+}
+
+struct chip_operations drivers_i2c_max98927_ops = {
+ CHIP_NAME("Maxim MAX98927 Codec")
+ .enable_dev = &max98927_enable
+};