Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9540
-gerrit
commit 007fd2135601cfdc6de5e8d0e6daa35b4d40181a
Author: Furquan Shaikh <furquan(a)google.com>
Date: Fri Nov 21 15:42:40 2014 -0800
arm64: Add support for save/restore registers for CPU startup.
startup.c provides function to enable CPU in any stage to save register data
that can be used by secondary CPU (for normal boot) or any CPU (for resume
boot). stage_entry.S defines space for saving arm64_startup_data. This can be
filled by:
1) Primary CPU before bringing up secondary CPUs so that the secondary can use
register values to initialize MMU-related and other required registers to
appropriate values.
2) CPU suspend path to ensure that on resume the values which were saved are
restored appropriately.
stage_entry.S provides a common path for both normal and resume boot to
initialize saved registers. For resume path, it is important to set the
secondary entry point for startup since x26 needs to be 1 for enabling MMU and
cache.
This also ensures that we do not fall into false memory cache errors which
caused CPU to fail during normal / resume boot. Thus, we can get rid of the
stack cache invalidate for secondary CPUs.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=Compiles and boots both CPU0 and CPU1 on ryu without mmu_enable and stack
cache invalidate for CPU1.
Change-Id: Ia4ca0e7d35c0738dbbaa926cce4268143c6f9de3
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 9f5e78469313ddd144ad7cf5abc3e07cb712183a
Original-Signed-off-by: Furquan Shaikh <furquan(a)google.com>
Original-Change-Id: I527a95779cf3fed37392b6605b096f54f8286d64
Original-Reviewed-on: https://chromium-review.googlesource.com/231561
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/Makefile.inc | 2 +
src/arch/arm64/armv8/secmon/secmon_init.c | 40 ++--------------
src/arch/arm64/c_entry.c | 17 ++-----
src/arch/arm64/cpu_ramstage.c | 14 ++++--
src/arch/arm64/include/arch/startup.h | 46 ++++++++++++++++++
src/arch/arm64/include/armv8/arch/cpu.h | 11 +++++
src/arch/arm64/stage_entry.S | 78 ++++++++++++++++++++++++++++---
src/arch/arm64/startup.c | 54 +++++++++++++++++++++
8 files changed, 201 insertions(+), 61 deletions(-)
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index bb3cab5..f81e76a 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -138,6 +138,7 @@ ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM64),y)
ramstage-y += c_entry.c
ramstage-y += stages.c
+ramstage-y += startup.c
ramstage-y += div0.c
ramstage-y += cpu.c
ramstage-y += cpu_ramstage.c
@@ -157,6 +158,7 @@ rmodules_arm64-y += ../../lib/memmove.c
rmodules_arm64-y += eabi_compat.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += stage_entry.S
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += startup.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/malloc.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memset.c
secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcmp.c
diff --git a/src/arch/arm64/armv8/secmon/secmon_init.c b/src/arch/arm64/armv8/secmon/secmon_init.c
index 63bd490..7d7f8bb 100644
--- a/src/arch/arm64/armv8/secmon/secmon_init.c
+++ b/src/arch/arm64/armv8/secmon/secmon_init.c
@@ -27,20 +27,11 @@
#include <arch/psci.h>
#include <arch/secmon.h>
#include <arch/smc.h>
+#include <arch/startup.h>
#include <console/console.h>
#include <stddef.h>
#include "secmon.h"
-/* Common CPU state for all CPUs running in secmon. */
-struct cpu_resume_data {
- uint64_t mair;
- uint64_t tcr;
- uint64_t ttbr0;
- uint64_t scr;
-};
-
-static struct cpu_resume_data resume_data;
-
static void secmon_init(struct secmon_params *params, int bsp);
static void secmon_init_bsp(void *arg)
@@ -61,27 +52,6 @@ void (*c_entry[2])(void *) = { &secmon_init_bsp, &secmon_init_nonbsp };
static void cpu_resume(void *unused)
{
- uint32_t sctlr;
-
- /* Re-enable exception vector. */
- exception_hwinit();
-
- tlbiall_el3();
- raw_write_mair_el3(resume_data.mair);
- raw_write_tcr_el3(resume_data.tcr);
- raw_write_ttbr0_el3(resume_data.ttbr0);
- dsb();
- isb();
-
- /* Enable MMU */
- sctlr = raw_read_sctlr_el3();
- sctlr |= SCTLR_C | SCTLR_M | SCTLR_I;
- raw_write_sctlr_el3(sctlr);
- isb();
-
- raw_write_scr_el3(resume_data.scr);
- isb();
-
psci_cpu_entry();
}
@@ -92,11 +62,7 @@ static void cpu_resume_init(void)
dcache_clean_by_mva(&c_entry, sizeof(c_entry));
/* Back up state. */
- resume_data.mair = raw_read_mair_el3();
- resume_data.tcr = raw_read_tcr_el3();
- resume_data.ttbr0 = raw_read_ttbr0_el3();
- resume_data.scr = raw_read_scr_el3();
- dcache_clean_by_mva(&resume_data, sizeof(resume_data));
+ startup_save_cpu_data();
}
static void start_up_cpu(void *arg)
@@ -150,7 +116,7 @@ static void secmon_init(struct secmon_params *params, int bsp)
wait_for_all_cpus(params->online_cpus);
smc_init();
- psci_init((uintptr_t)arm64_cpu_startup);
+ psci_init((uintptr_t)arm64_cpu_startup_resume);
/* Initialize the resume path. */
cpu_resume_init();
diff --git a/src/arch/arm64/c_entry.c b/src/arch/arm64/c_entry.c
index de8ebcd..bf7a335 100644
--- a/src/arch/arm64/c_entry.c
+++ b/src/arch/arm64/c_entry.c
@@ -19,9 +19,9 @@
#include <arch/cache.h>
#include <arch/cpu.h>
-#include <arch/exception.h>
#include <arch/mmu.h>
#include <arch/stages.h>
+#include <arch/startup.h>
#include "cpu-internal.h"
void __attribute__((weak)) arm64_soc_init(void)
@@ -55,22 +55,15 @@ static void arm64_init(void)
main();
}
-static void secondary_cpu_start(void)
-{
- mmu_enable();
- exception_hwinit();
-
- /* This will never return. */
- arch_secondary_cpu_init();
-}
-
/*
* This variable holds entry point for CPUs starting up. The first
* element is the BSP path, and the second is the non-BSP path.
*/
-void (*c_entry[2])(void) = { &arm64_init, &secondary_cpu_start };
+void (*c_entry[2])(void) = { &arm64_init, &arch_secondary_cpu_init };
void *prepare_secondary_cpu_startup(void)
{
- return secondary_entry_point(&arm64_cpu_startup);
+ startup_save_cpu_data();
+
+ return secondary_entry_point(&arm64_cpu_startup_resume);
}
diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c
index ec1ac0f..e6d0e8c 100644
--- a/src/arch/arm64/cpu_ramstage.c
+++ b/src/arch/arm64/cpu_ramstage.c
@@ -109,8 +109,6 @@ static void init_this_cpu(void *arg)
printk(BIOS_DEBUG, "CPU%x: MPIDR: %llx\n", ci->id, ci->mpidr);
- el3_init();
-
/* Initialize the GIC. */
gic_init();
@@ -151,9 +149,6 @@ static void init_cpu_info(struct bus *bus)
ci->cpu = cur;
ci->id = cur->path.cpu.id;
}
-
- /* Mark current cpu online. */
- cpu_mark_online(cpu_info());
}
static void invalidate_cpu_stack_top(unsigned int id)
@@ -184,6 +179,15 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
if (bus == NULL)
return;
+ /*
+ * el3_init must be performed prior to prepare_secondary_cpu_startup.
+ * This is important since el3_init initializes SCR values on BSP CPU
+ * and then prepare_secondary_cpu_startup reads the initialized SCR
+ * value and saves it for use by non-BSP CPUs.
+ */
+ el3_init();
+ /* Mark current cpu online. */
+ cpu_mark_online(cpu_info());
entry = prepare_secondary_cpu_startup();
/* Initialize the cpu_info structures. */
diff --git a/src/arch/arm64/include/arch/startup.h b/src/arch/arm64/include/arch/startup.h
new file mode 100644
index 0000000..bb3a863
--- /dev/null
+++ b/src/arch/arm64/include/arch/startup.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__
+#define __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__
+
+/* Every element occupies 8 bytes (64-bit entries) */
+#define PER_ELEMENT_SIZE_BYTES 8
+#define MAIR_INDEX 0
+#define TCR_INDEX 1
+#define TTBR0_INDEX 2
+#define SCR_INDEX 3
+#define VBAR_INDEX 4
+/* IMPORTANT!!! If any new element is added please update NUM_ELEMENTS */
+#define NUM_ELEMENTS 5
+
+#ifndef __ASSEMBLY__
+
+/*
+ * startup_save_cpu_data is used to save register values that need to be setup
+ * when a CPU starts booting. This is used by secondary CPUs as well as resume
+ * path to directly setup MMU and other related registers.
+ */
+void startup_save_cpu_data(void);
+
+#endif
+
+#endif /* __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__ */
diff --git a/src/arch/arm64/include/armv8/arch/cpu.h b/src/arch/arm64/include/armv8/arch/cpu.h
index d968a06..34220d9 100644
--- a/src/arch/arm64/include/armv8/arch/cpu.h
+++ b/src/arch/arm64/include/armv8/arch/cpu.h
@@ -170,4 +170,15 @@ static inline void *secondary_entry_point(void *e)
*/
void arm64_cpu_startup(void);
+/*
+ * The arm64_cpu_startup_resume() initializes a CPU's exception stack and
+ * regular stack as well initializing the C environment for the processor. It
+ * calls into the array of function pointers at symbol c_entry depending
+ * on BSP state. Note that arm64_cpu_startup contains secondary entry
+ * point which can be obtained by secondary_entry_point().
+ * Additionally, it also restores saved register data and enables MMU, caches
+ * and exceptions before jumping to C environment for both BSP and non-BSP CPUs.
+ */
+void arm64_cpu_startup_resume(void);
+
#endif /* __ARCH_CPU_H__ */
diff --git a/src/arch/arm64/stage_entry.S b/src/arch/arm64/stage_entry.S
index 5a5ddab..fa2064e 100644
--- a/src/arch/arm64/stage_entry.S
+++ b/src/arch/arm64/stage_entry.S
@@ -29,6 +29,7 @@
#include <arch/asm.h>
#define __ASSEMBLY__
#include <arch/lib_helpers.h>
+#include <arch/startup.h>
#define STACK_SZ CONFIG_STACK_SIZE
#define EXCEPTION_STACK_SZ CONFIG_STACK_SIZE
@@ -38,6 +39,12 @@
* according to MAX_CPUS. Additionally provide exception stacks for each CPU.
*/
.section .bss, "aw", @nobits
+
+.global _arm64_startup_data
+.balign 8
+_arm64_startup_data:
+.space NUM_ELEMENTS*PER_ELEMENT_SIZE_BYTES
+
.global _stack
.global _estack
.balign STACK_SZ
@@ -136,23 +143,80 @@ ENTRY(__rmodule_entry)
b arm64_c_environment
ENDPROC(__rmodule_entry)
-ENTRY(_arm64_cpu_startup)
+/*
+ * Setup SCTLR so that:
+ * Little endian mode is setup, XN is not enforced, MMU and caches are disabled.
+ * Alignment and stack alignment checks are disabled.
+ */
+.macro setup_sctlr
read_current x0, sctlr
bic x0, x0, #(1 << 25) /* Little Endian */
bic x0, x0, #(1 << 19) /* XN not enforced */
bic x0, x0, #(1 << 12) /* Disable Instruction Cache */
- bic x0, x0, #0xf /* Clear SA, C, A, and M */
+ bic x0, x0, #0xf /* Clear SA, C, A and M */
+ write_current sctlr, x0, x1
+.endm
+
+/*
+ * This macro assumes x2 has base address and returns value read in x0
+ * x1 is used as temporary register.
+ */
+.macro get_element_addr index
+ add x1, x2, #(\index * PER_ELEMENT_SIZE_BYTES)
+ ldr x0, [x1]
+.endm
+
+/*
+ * Uses following registers:
+ * x0 = reading stored value
+ * x1 = temp reg
+ * x2 = base address of saved data region
+ */
+.macro startup_restore
+ adr x2, _arm64_startup_data
+
+ get_element_addr MAIR_INDEX
+ write_current mair, x0, x1
+
+ get_element_addr TCR_INDEX
+ write_current tcr, x0, x1
+
+ get_element_addr TTBR0_INDEX
+ write_current ttbr0, x0, x1
+
+ get_element_addr SCR_INDEX
+ write_el3 scr, x0, x1
+
+ get_element_addr VBAR_INDEX
+ write_current vbar, x0, x1
+
+ dsb sy
+ isb
+
+ tlbiall_current x1
+ read_current x0, sctlr
+ orr x0, x0, #(1 << 12) /* Enable Instruction Cache */
+ orr x0, x0, #(1 << 2) /* Enable Data/Unified Cache */
+ orr x0, x0, #(1 << 0) /* Enable MMU */
write_current sctlr, x0, x1
+
+ dsb sy
isb
- b arm64_c_environment
-ENDPROC(_arm64_cpu_startup)
+.endm
CPU_RESET_ENTRY(arm64_cpu_startup)
split_bsp_path
- b _arm64_cpu_startup
+ setup_sctlr
+ b arm64_c_environment
ENDPROC(arm64_cpu_startup)
-ENTRY(stage_entry)
+CPU_RESET_ENTRY(arm64_cpu_startup_resume)
split_bsp_path
- b _arm64_cpu_startup
+ setup_sctlr
+ startup_restore
+ b arm64_c_environment
+ENDPROC(arm64_cpu_startup_resume)
+
+ENTRY(stage_entry)
+ b arm64_cpu_startup
ENDPROC(stage_entry)
diff --git a/src/arch/arm64/startup.c b/src/arch/arm64/startup.c
new file mode 100644
index 0000000..d2b7691
--- /dev/null
+++ b/src/arch/arm64/startup.c
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <arch/cache.h>
+#include <arch/lib_helpers.h>
+#include <arch/startup.h>
+#include <console/console.h>
+
+/* This space is defined in stage_entry.S. */
+extern u8 _arm64_startup_data[];
+
+static inline void save_element(size_t index, uint64_t val)
+{
+ uint64_t *ptr = (uint64_t *)_arm64_startup_data;
+
+ ptr[index] = val;
+}
+
+/*
+ * startup_save_cpu_data is used to save register values that need to be setup
+ * when a CPU starts booting. This is used by secondary CPUs as well as resume
+ * path to directly setup MMU and other related registers.
+ */
+void startup_save_cpu_data(void)
+{
+ save_element(MAIR_INDEX, raw_read_mair_current());
+ save_element(TCR_INDEX, raw_read_tcr_current());
+ save_element(TTBR0_INDEX, raw_read_ttbr0_current());
+ save_element(VBAR_INDEX, raw_read_vbar_current());
+
+ if (get_current_el() == EL3)
+ save_element(SCR_INDEX, raw_read_scr_el3());
+
+ dcache_clean_by_mva(_arm64_startup_data,
+ NUM_ELEMENTS * PER_ELEMENT_SIZE_BYTES);
+}
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9524
-gerrit
commit 1c7596123cc7ce1cd5d87ae120a0a725a6dbccb4
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Wed Nov 19 11:57:47 2014 -0600
tegra132: rename clock_display() to clock_configure_plld()
Provide an explicit name for configuring PLLD. The new name,
clock_configure_plld(), provides an explicit semantic to
what it is doing. Also, provide the printk() about actual
frequency vs requested frequency as most of the callers
were doing this themselves.
BUG=chrome-os-partner:33825
BRANCH=None
TEST=Built and booted on ryu.
Change-Id: I1880f0f305e69674922b070d282aac3acdc86aad
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: c51d5b0864d8bd0db5927380803cec46ccd74d48
Original-Change-Id: If744332b466d9486f83b08d0ab4e9006fadfecdd
Original-Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/230773
Original-Reviewed-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Reviewed-by: Tom Warren <twarren(a)nvidia.com>
Original-Reviewed-by: Sean Paul <seanpaul(a)chromium.org>
---
src/soc/nvidia/tegra132/clock.c | 11 +++++------
src/soc/nvidia/tegra132/display.c | 7 +++----
src/soc/nvidia/tegra132/include/soc/clock.h | 6 +++++-
src/soc/nvidia/tegra132/tegra_dsi.c | 2 +-
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c
index 49c2f19..661d38a 100644
--- a/src/soc/nvidia/tegra132/clock.c
+++ b/src/soc/nvidia/tegra132/clock.c
@@ -291,10 +291,6 @@ static void graphics_pll(void)
/* leave dither and undoc bits set, release clamp */
scfg = (1<<28) | (1<<24);
writel(scfg, cfg);
-
- /* disp1 will be set when panel information (pixel clock) is
- * retrieved (clock_display).
- */
}
/*
@@ -304,8 +300,7 @@ static void graphics_pll(void)
*
* Return the plld frequency if success, otherwise return 0.
*/
-u32
-clock_display(u32 frequency)
+u32 clock_configure_plld(u32 frequency)
{
/**
* plld (fo) = vco >> p, where 500MHz < vco < 1000MHz
@@ -388,6 +383,10 @@ clock_display(u32 frequency)
init_pll(CLK_RST_REG(plld_base), CLK_RST_REG(plld_misc), plld,
(PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE));
+ if (rounded_rate != frequency)
+ printk(BIOS_DEBUG, "PLLD rate: %u vs %u\n", rounded_rate,
+ frequency);
+
return rounded_rate;
}
diff --git a/src/soc/nvidia/tegra132/display.c b/src/soc/nvidia/tegra132/display.c
index 4fc312e..d616b73 100644
--- a/src/soc/nvidia/tegra132/display.c
+++ b/src/soc/nvidia/tegra132/display.c
@@ -135,7 +135,8 @@ static int update_display_mode(struct display_controller *disp_ctrl,
* has some requirements to have VCO in range 500MHz~1000MHz (see
* clock.c for more detail). To simplify calculation, we set
* PixelClockDiv to 1 and ShiftClockDiv to 1. In future these values
- * may be calculated by clock_display, to allow wider frequency range.
+ * may be calculated by clock_configure_plld(), to allow wider
+ * frequency range.
*
* Note ShiftClockDiv is a 7.1 format value.
*/
@@ -265,12 +266,10 @@ void display_startup(device_t dev)
* update_display_mode() for detail.
*/
/* set default plld */
- plld_rate = clock_display(config->pixel_clock * 2);
+ plld_rate = clock_configure_plld(config->pixel_clock * 2);
if (plld_rate == 0) {
printk(BIOS_ERR, "dc: clock init failed\n");
return;
- } else if (plld_rate != config->pixel_clock * 2) {
- printk(BIOS_WARNING, "dc: plld rounded to %u\n", plld_rate);
}
/* set disp1's clock source to PLLD_OUT0 */
diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h
index 7fabff7..5fadbd0 100644
--- a/src/soc/nvidia/tegra132/include/soc/clock.h
+++ b/src/soc/nvidia/tegra132/include/soc/clock.h
@@ -378,7 +378,11 @@ static inline void _clock_set_div(u32 *reg, const char *name, u32 div,
int clock_get_osc_khz(void);
int clock_get_pll_input_khz(void);
-u32 clock_display(u32 frequency);
+/*
+ * Configure PLLD to requested frequency. Returned value is closest match
+ * within the PLLD's constraints or 0 if an error.
+ */
+u32 clock_configure_plld(u32 frequency);
void clock_early_uart(void);
void clock_external_output(int clk_id);
void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
diff --git a/src/soc/nvidia/tegra132/tegra_dsi.c b/src/soc/nvidia/tegra132/tegra_dsi.c
index 3a7949d..f1e7c9f 100644
--- a/src/soc/nvidia/tegra132/tegra_dsi.c
+++ b/src/soc/nvidia/tegra132/tegra_dsi.c
@@ -463,7 +463,7 @@ static int tegra_output_dsi_setup_clock(struct tegra_dsi *dsi,
dsi->slave->clk_rate = dsi->clk_rate;
/* set up plld */
- plld = clock_display(plld);
+ plld = clock_configure_plld(plld);
if (plld == 0) {
printk(BIOS_ERR, "%s: clock init failed\n", __func__);
return -1;
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9525
-gerrit
commit 1b0485113a43f8d7a7a772d39a4dfb5709f000ac
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Wed Nov 19 12:01:39 2014 -0600
tegra132: always bring up PLLD
The kernel does not correctly function without PLLD being enabled.
Additionally, PLLD can be the source for other clocks in the system.
Therefore, initialize PLLD to 300MHz unconditionally at BS_DEV_INIT
time in ramstage.
BUG=chrome-os-partner:33825
BRANCH=None
TEST=Built and booted ryu with display coming up both in dev mode as
well as normal mode.
Change-Id: Ib2a60bb9aafc03dc23aa932a480184d87f677c65
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 4c49f964b55c3c33d03b95363277b262b679e740
Original-Change-Id: Ic5905e25051a042cea5010b8c6d61b1fb89a0a81
Original-Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/230774
Original-Reviewed-by: Tom Warren <twarren(a)nvidia.com>
Original-Reviewed-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Tested-by: Sean Paul <seanpaul(a)chromium.org>
---
src/soc/nvidia/tegra132/soc.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/soc/nvidia/tegra132/soc.c b/src/soc/nvidia/tegra132/soc.c
index b91260e..a77ffbb 100644
--- a/src/soc/nvidia/tegra132/soc.c
+++ b/src/soc/nvidia/tegra132/soc.c
@@ -22,6 +22,7 @@
#include <arch/cache.h>
#include <arch/spintable.h>
#include <cpu/cpu.h>
+#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
@@ -143,3 +144,20 @@ static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = ids,
};
+
+static void enable_plld(void *unused)
+{
+ /*
+ * Configure a conservative 300MHz clock for PLLD. The kernel cannot
+ * handle PLLD not being configured so enable PLLD unconditionally
+ * with a default clock rate.
+ */
+ clock_configure_plld(300 * MHz);
+}
+
+/*
+ * The PLLD being enabled is done at BS_DEV_INIT time because mainboard_init()
+ * is the first thing called. This ensures PLLD is up and functional before
+ * anything that mainboard can do that implicitly relies on PLLD.
+ */
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, enable_plld, NULL);
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9526
-gerrit
commit f7c0962124a9e092d210175bae71f17f2795a715
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Thu Nov 20 11:11:01 2014 -0600
arm64: add timeout waiting for CPUs to come online
The initial MP code assumed all CPUs would come online. That's not
very defensive, and it is a bad assumption. Provide a timeout
mechanism for bring CPUs online.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=Multiple times with CPUs working and not working. Boot to kernel.
Change-Id: Ib0aef31f5c732816d65c2e4b3c6a89e159974fdc
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 9cf5bc2844c8f4ad987cfcb69ef33c73551f0083
Original-Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Change-Id: Ifb3b72e3f122b79e9def554c037c9b3d6049a151
Original-Reviewed-on: https://chromium-review.googlesource.com/231070
Original-Reviewed-by: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/cpu_ramstage.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c
index f286678..ce81f93 100644
--- a/src/arch/arm64/cpu_ramstage.c
+++ b/src/arch/arm64/cpu_ramstage.c
@@ -23,6 +23,7 @@
#include <cpu/cpu.h>
#include <console/console.h>
#include <gic.h>
+#include <timer.h>
#include "cpu-internal.h"
static inline void cpu_disable_dev(device_t dev)
@@ -191,6 +192,7 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
for (i = 0; i < max_cpus; i++) {
device_t dev;
struct cpu_action action;
+ struct stopwatch sw;
ci = cpu_info_for_cpu(i);
dev = ci->cpu;
@@ -211,9 +213,23 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
"Failed to start CPU%x\n", ci->id);
continue;
}
+ stopwatch_init_msecs_expire(&sw, 1000);
/* Wait for CPU to come online. */
- while (!cpu_online(ci));
- printk(BIOS_DEBUG, "CPU%x online.\n", ci->id);
+ while (!stopwatch_expired(&sw)) {
+ if (!cpu_online(ci))
+ continue;
+ printk(BIOS_DEBUG,
+ "CPU%x online in %ld usecs.\n",
+ ci->id, stopwatch_duration_usecs(&sw));
+ break;
+ }
+ }
+
+ if (!cpu_online(ci)) {
+ printk(BIOS_DEBUG,
+ "CPU%x failed to come online in %ld usecs.\n",
+ ci->id, stopwatch_duration_usecs(&sw));
+ continue;
}
/* Send it the init action. */
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9527
-gerrit
commit 69d08bf850d43daa58393895e2d2f0029a8306d3
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Thu Nov 20 22:17:54 2014 -0600
arm64: ensure secondary CPU's stack tops are not in the cache
Secondary CPUs were intermittently not coming online as expected.
Upon investigation it was found that a cache line needed to be
invalidated that corresponded to the top of the stack for the
failing CPU.
Currently the secondary CPUs come online with caching disabled.
However, the code paths are using C and thus the stack it is assigned.
The MMU is enabled in C after it's pushed its return path onto the
stack that went directly to ram. When the cache line corresponding
to its stack is valid in the cache it will hit once the MMU is enabled.
That hit will have invalid data w.r.t. the return addresses pushed
directly into ram.
This is not the best solution as the only way to guarantee we don't
hit such a situation is to tightly manage resource usage up until
the point of MMU enablement. That can be done in a followup patch.
BUG=chrome-os-partner:33962
BRANCH=None
TEST=On ryu where secondary CPUs weren't coming online consistently,
they now come up.
Change-Id: I03237656da180d1f74df3a8e00029ba8d778bca8
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 06ab6afc996cf92c45d4cd6850e31167c2946a95
Original-Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Change-Id: I32de749ea48c19e23442e6dc5678c5369ac3b2b6
Original-Reviewed-on: https://chromium-review.googlesource.com/231219
Original-Reviewed-by: Furquan Shaikh <furquan(a)chromium.org>
Original-Tested-by: Furquan Shaikh <furquan(a)chromium.org>
---
src/arch/arm64/cpu_ramstage.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c
index ce81f93..ec1ac0f 100644
--- a/src/arch/arm64/cpu_ramstage.c
+++ b/src/arch/arm64/cpu_ramstage.c
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include <arch/cache.h>
#include <arch/lib_helpers.h>
#include <cpu/cpu.h>
#include <console/console.h>
@@ -155,6 +156,13 @@ static void init_cpu_info(struct bus *bus)
cpu_mark_online(cpu_info());
}
+static void invalidate_cpu_stack_top(unsigned int id)
+{
+ const size_t size = 128;
+ char *stack = cpu_get_stack(id);
+ dcache_invalidate_by_mva(stack - size, size);
+}
+
void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
{
size_t max_cpus;
@@ -208,6 +216,10 @@ void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
if (!cpu_online(ci)) {
/* Start the CPU. */
printk(BIOS_DEBUG, "Starting CPU%x\n", ci->id);
+
+ /* Ensure CPU's top of stack is not in the cache. */
+ invalidate_cpu_stack_top(ci->id);
+
if (cntrl_ops->start_cpu(ci->id, entry)) {
printk(BIOS_ERR,
"Failed to start CPU%x\n", ci->id);
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9520
-gerrit
commit 944bfdb6b5232c609e051228a49d6b5330e6f520
Author: Jimmy Zhang <jimmzhang(a)nvidia.com>
Date: Fri Nov 14 20:44:40 2014 -0800
tegra132: Add framebuffer parameters
Framebuffer line size and number of lines can have different
values than panel's resolution.
BRANCH=none
BUG=chrome-os-partner:31936
TEST=build and test on ryu
Change-Id: I228f1dd7fafc6577a8e8a987ff31ba73f7a655ed
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 9a4929dc5831076f2f2a5dd2e13f24b3477e197b
Original-Change-Id: Iedeef796f02286bb03920413420f8952cf34334a
Original-Signed-off-by: Jimmy Zhang <jimmzhang(a)nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/229915
Original-Tested-by: Jimmy Zhang <jimmzhang(a)nvidia.com>
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Commit-Queue: Aaron Durbin <adurbin(a)chromium.org>
---
src/soc/nvidia/tegra132/chip.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/soc/nvidia/tegra132/chip.h b/src/soc/nvidia/tegra132/chip.h
index 35e72d5..2468870 100644
--- a/src/soc/nvidia/tegra132/chip.h
+++ b/src/soc/nvidia/tegra132/chip.h
@@ -27,7 +27,8 @@ struct soc_nvidia_tegra132_config {
uintptr_t spintable_addr;
/*
- * panel default specification
+ * panel resolution
+ * The two parameters below provides dc about panel spec.
*/
u32 xres; /* the width of H display active area */
u32 yres; /* the height of V display active area */
@@ -45,6 +46,15 @@ struct soc_nvidia_tegra132_config {
*/
u32 framebuffer_size;
+ /*
+ * Framebuffer resolution
+ * The two parameters below provides dc about framebuffer's sdram size.
+ * When they are not the same as panel resolution, we need to program
+ * dc's DDA_INCREMENT and some other registers to resize dc output.
+ */
+ u32 display_xres;
+ u32 display_yres;
+
int href_to_sync; /* HSYNC position with respect to line start */
int hsync_width; /* the width of HSYNC pulses */
int hback_porch; /* the distance between HSYNC trailing edge to
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9521
-gerrit
commit 15d203914b44f976d4989fded7369770835a06eb
Author: Jimmy Zhang <jimmzhang(a)nvidia.com>
Date: Fri Nov 14 15:47:12 2014 -0800
google/rush_ryu: devicetree: Add framebuffer resolution settings
When displaying a 800x600 bitmap on 2560x1800 panel, the image
is shown very small. So, set the fb to 1280x800 (based on tegra
dsi driver default mode setting), a 800x600 image can be shown
relatively proportional to panel size.
BRANCH=none
BUG=chrome-os-partner:31936
TEST=build and test on ryu
Signed-off-by: Jimmy Zhang <jimmzhang(a)nvidia.com>
Change-Id: I1e360aeaec97b9df5d86e46951ab1326610260d2
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 67c2a381322721a24b1b7f9ac366073b7e3c490c
Original-Change-Id: I62cbe9de1d1002293df20f8b1d752905c6ef33aa
Original-Reviewed-on: https://chromium-review.googlesource.com/229912
Original-Tested-by: Jimmy Zhang <jimmzhang(a)nvidia.com>
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Original-Commit-Queue: Aaron Durbin <adurbin(a)chromium.org>
---
src/mainboard/google/rush_ryu/devicetree.cb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/mainboard/google/rush_ryu/devicetree.cb b/src/mainboard/google/rush_ryu/devicetree.cb
index c0af141..b5c9981 100644
--- a/src/mainboard/google/rush_ryu/devicetree.cb
+++ b/src/mainboard/google/rush_ryu/devicetree.cb
@@ -33,6 +33,10 @@ chip soc/nvidia/tegra132
register "framebuffer_bits_per_pixel" = "32"
register "color_depth" = "12"
+ # framebuffer resolution
+ register "display_xres" = "1280"
+ register "display_yres" = "800"
+
register "href_to_sync" = "1"
register "hfront_porch" = "80"
register "hsync_width" = "80"
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9523
-gerrit
commit 723503d45a06994968aeb5e59719cc776b143a6f
Author: Tom Warren <twarren(a)nvidia.com>
Date: Mon Nov 17 16:09:38 2014 -0700
google/rush_ryu: audio: Setup clocks for AHUB, I2S1, codec, etc.
The Ryu RT5677 audio codec uses EXTPERIPH1 clock (12MHz)
for MCLK1, I2S1 for input. AHUB needs all of its child
peripherals taken out of reset and enabled, too.
This just sets up the audio clocks. More work still to
be done in the codec driver, and some kind of stub needs
to be created/hacked to set up the AD4567 speaker amp
regs for mono output on P1.
BUG=chrome-os-partner:32582
BRANCH=none
TEST=Dumped clock regs and saw correct values
Change-Id: Ifb6551f1e09b38f440f3bb7c759b5e6c0b9e4e44
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 48f989a0291044f5fb4340cc89546325d819d82f
Original-Change-Id: I6c9e760ac39def92a6054d673f781facdbfd70a2
Original-Signed-off-by: Tom Warren <twarren(a)nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/229993
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/mainboard/google/rush_ryu/mainboard.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/src/mainboard/google/rush_ryu/mainboard.c b/src/mainboard/google/rush_ryu/mainboard.c
index 2b71c98..81c15b4 100644
--- a/src/mainboard/google/rush_ryu/mainboard.c
+++ b/src/mainboard/google/rush_ryu/mainboard.c
@@ -57,8 +57,8 @@ static const struct pad_config mmcpads[] = {
static const struct pad_config audio_codec_pads[] = {
/* H1 is CODEC_RST_L and R2(ROW2) is AUDIO_ENABLE */
- PAD_CFG_GPIO_OUT1(GPIO_PH1, PINMUX_PULL_DOWN),
- PAD_CFG_GPIO_OUT1(KB_ROW2, PINMUX_PULL_DOWN),
+ PAD_CFG_GPIO_OUT1(GPIO_PH1, PINMUX_PULL_DOWN),
+ PAD_CFG_GPIO_OUT1(KB_ROW2, PINMUX_PULL_DOWN),
};
static const struct funit_cfg funits[] = {
@@ -186,6 +186,30 @@ static int configure_display_blocks(void)
return 0;
}
+/* Audio init: clocks and enables/resets */
+static void setup_audio(void)
+{
+ /* External peripheral 1: audio codec (RT5677) using 12MHz CLK1 */
+ clock_configure_source(extperiph1, CLK_M, 12000);
+
+ /*
+ * We need 1.5MHz for I2S1. So, we use CLK_M. CLK_DIVIDER macro
+ * returns a divisor (0xe) a little bit off from the ideal value (0xd),
+ * but it's good enough for beeps.
+ */
+ clock_configure_source(i2s1, CLK_M, 1500);
+
+ clock_external_output(1); /* For external RT5677 audio codec. */
+
+ /*
+ * Confirmed by NVIDIA hardware team, we need to take ALL audio devices
+ * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out
+ * of reset and clock-enabled, otherwise reading AHUB devices (in our
+ * case, I2S/APBIF/AUDIO<XBAR>) will hang.
+ */
+ clock_enable_audio();
+}
+
static void mainboard_init(device_t dev)
{
soc_configure_funits(funits, ARRAY_SIZE(funits));
@@ -193,6 +217,9 @@ static void mainboard_init(device_t dev)
/* I2C6 bus (audio, etc.) */
soc_configure_i2c6pad();
i2c_init(I2C6_BUS);
+
+ setup_audio();
+
elog_init();
elog_add_boot_reason();