Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3153
-gerrit
commit 99a3c56c390ac8f64c6876d7b460a6ec4f458760
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Mon Apr 29 16:57:10 2013 -0500
haswell: 24MHz monotonic time implementation
Haswell ULT devices have a 24MHz package-level counter. Use
this counter to provide a time_monotonic_get() implementation.
Change-Id: Ic79843fcbfbbb6462ee5ebd12b39502307750dbb
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/cpu/intel/haswell/Kconfig | 7 ++++
src/cpu/intel/haswell/Makefile.inc | 1 +
src/cpu/intel/haswell/monotonic_timer.c | 62 +++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+)
diff --git a/src/cpu/intel/haswell/Kconfig b/src/cpu/intel/haswell/Kconfig
index 5f27d4c..13861f9 100644
--- a/src/cpu/intel/haswell/Kconfig
+++ b/src/cpu/intel/haswell/Kconfig
@@ -54,4 +54,11 @@ config RESET_ON_INVALID_RAMSTAGE_CACHE
the system will reset otherwise the ramstage will be reloaded from
cbfs.
+config MONOTONIC_TIMER_MSR
+ def_bool n
+ depends on INTEL_LYNXPOINT_LP
+ select HAVE_MONOTONIC_TIMER
+ help
+ Provide a monotonic timer using the 24MHz MSR counter.
+
endif
diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc
index a19a8c5..90ffd66 100644
--- a/src/cpu/intel/haswell/Makefile.inc
+++ b/src/cpu/intel/haswell/Makefile.inc
@@ -5,6 +5,7 @@ romstage-y += romstage.c
ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
+ramstage-$(CONFIG_MONOTONIC_TIMER_MSR) += monotonic_timer.c
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
diff --git a/src/cpu/intel/haswell/monotonic_timer.c b/src/cpu/intel/haswell/monotonic_timer.c
new file mode 100644
index 0000000..c51bcbd
--- /dev/null
+++ b/src/cpu/intel/haswell/monotonic_timer.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 <stdint.h>
+#include <cpu/x86/msr.h>
+#include <timer.h>
+
+#define MSR_COUNTER_24_MHz 0x637
+static struct monotonic_counter {
+ int initialized;
+ struct mono_time time;
+ uint32_t last_value;
+} mono_counter;
+
+static inline uint32_t read_counter_msr(void)
+{
+ /* Even though the MSR is 64-bit it is assumed that the hardware
+ * is polled frequently enough to only use the lower 32-bits. */
+ msr_t counter_msr;
+
+ counter_msr = rdmsr(MSR_COUNTER_24_MHz);
+
+ return counter_msr.lo;
+}
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+ uint32_t current_tick;
+ uint32_t usecs_elapsed;
+
+ if (!mono_counter.initialized) {
+ mono_counter.last_value = read_counter_msr();
+ mono_counter.initialized = 1;
+ }
+
+ current_tick = read_counter_msr();
+ usecs_elapsed = (current_tick - mono_counter.last_value) / 24;
+
+ /* Update current time and tick values only if a full tick occurred. */
+ if (usecs_elapsed) {
+ mono_time_add_usecs(&mono_counter.time, usecs_elapsed);
+ mono_counter.last_value = current_tick;
+ }
+
+ /* Save result. */
+ *mt = mono_counter.time;
+}
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3152
-gerrit
commit 3d55699e06625f18186f76d683c987e72ad38447
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Mon Apr 29 22:31:51 2013 -0500
coreboot: introduce monotonic timer API
The notion of a monotonic timer is introduced. Along with it
are helper functions and other types for comparing times. This
is just the framework where it is the responsibility of the
chipset/board to provide the implementation of timer_monotonic_get().
The reason structs are used instead of native types is to allow
for future changes to the data structure without chaning all the
call sites.
Change-Id: Ie56b9ab9dedb0da69dea86ef87ca744004eb1ae3
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/Kconfig | 5 ++
src/include/timer.h | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 156 insertions(+)
diff --git a/src/Kconfig b/src/Kconfig
index c3cc6bf..a49643e 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -313,6 +313,11 @@ config HAVE_INIT_TIMER
default n if UDELAY_IO
default y
+config HAVE_MONOTONIC_TIMER
+ def_bool n
+ help
+ The board/chipset provides a monotonic timer.
+
config HIGH_SCRATCH_MEMORY_SIZE
hex
default 0x0
diff --git a/src/include/timer.h b/src/include/timer.h
new file mode 100644
index 0000000..b4ac099
--- /dev/null
+++ b/src/include/timer.h
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 TIMER_H
+#define TIMER_H
+
+#define USECS_PER_SEC 1000000
+#define MSECS_PER_SEC 1000
+#define USECS_PER_MSEC (USECS_PER_SEC / MSECS_PER_SEC)
+
+/* The time structures are defined to be a representation of the time since
+ * coreboot started executing one of its stages. The reason for using structures
+ * is to allow for changes in the future. The structures' details are exposed
+ * so that the compiler can allocate space on the stack and use in other
+ * structures. In other words, accessing any field within this structure
+ * outside of the core timer code is not supported. */
+
+struct mono_time {
+ long microseconds;
+};
+
+struct rela_time {
+ long microseconds;
+};
+
+/* A timeout_callback structure is used for the book keeping for scheduling
+ * work in the future. When a callback is called the structure can be
+ * re-used for scheduling as it is not being tracked by the core timer
+ * library any more. */
+struct timeout_callback {
+ void *priv;
+ void (*callback)(struct timeout_callback *tocb);
+ /* Not for public use. The timer library uses the fields below. */
+ struct mono_time expiration;
+};
+
+/* Obtain the current monotonic time. The assumption is that the time counts
+ * up from the value 0 with value 0 being the point when the timer was
+ * initialized. Additionally, the timer is assumed to only be valid for the
+ * duration of the boot.
+ *
+ * Note that any implementations of timer_monotonic_get()
+ * need to ensure its timesource does not roll over within 10 secs. The reason
+ * is that the time between calls to timer_monotonic_get() may be on order
+ * of 10 seconds. */
+void timer_monotonic_get(struct mono_time *mt);
+
+/* Add microseconds to an absoute time. */
+static inline void mono_time_add_usecs(struct mono_time *mt, long us)
+{
+ mt->microseconds += us;
+}
+
+/* Add milliseconds to an absoute time. */
+static inline void mono_time_add_msecs(struct mono_time *mt, long ms)
+{
+ mono_time_add_usecs(mt, ms * USECS_PER_MSEC);
+}
+
+static inline void mono_time_add_rela_time(struct mono_time *mt,
+ const struct rela_time *t)
+{
+ mono_time_add_usecs(mt, t->microseconds);
+}
+
+/* Compare two absoluted times: Return -1, 0, or 1 if t1 is <, =, or > t2,
+ * respectively. */
+static inline int mono_time_cmp(const struct mono_time *t1,
+ const struct mono_time *t2)
+{
+ if (t1->microseconds == t2->microseconds)
+ return 0;
+
+ if (t1->microseconds < t2->microseconds)
+ return -1;
+
+ return 1;
+}
+
+static inline int rela_time_cmp(const struct rela_time *t1,
+ const struct rela_time *t2)
+{
+ if (t1->microseconds == t2->microseconds)
+ return 0;
+
+ if (t1->microseconds < t2->microseconds)
+ return -1;
+
+ return 1;
+}
+
+/* Iniitalize a rela_time structure. */
+static inline struct rela_time rela_time_init_usecs(long us)
+{
+ struct rela_time t;
+ t.microseconds = us;
+ return t;
+}
+
+/* Return time difference between t1 and t2. i.e. t2 - t1. */
+static struct rela_time mono_time_diff(const struct mono_time *t1,
+ const struct mono_time *t2)
+{
+ return rela_time_init_usecs(t2->microseconds - t1->microseconds);
+}
+
+/* Return true if t1 after t2 */
+static inline int mono_time_after(const struct mono_time *t1,
+ const struct mono_time *t2)
+{
+ return mono_time_cmp(t1, t2) > 0;
+}
+
+/* Return true if t1 before t2. */
+static inline int mono_time_before(const struct mono_time *t1,
+ const struct mono_time *t2)
+{
+ return mono_time_cmp(t1, t2) < 0;
+}
+
+/* Return the difference between now and t. */
+static inline struct rela_time current_time_from(const struct mono_time *t)
+{
+ struct mono_time now;
+
+ timer_monotonic_get(&now);
+ return mono_time_diff(t, &now);
+
+}
+
+static inline long rela_time_in_microseconds(const struct rela_time *rt)
+{
+ return rt->microseconds;
+}
+
+#endif /* TIMER_H */
Denis Carikli (GNUtoo(a)no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3142
-gerrit
commit cc8e3d343ca774d0f74c672a8429ebb77502d868
Author: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
Date: Fri Apr 26 12:21:41 2013 +0200
Lenovo ThinkPad X60: Init CBMEM early for CBMEM console support.
Enable `EARLY_CBMEM_INIT` for CBMEM console support by looking how
other boards do this.
This commit is tested by enabling the CBMEM console (`CONSOLE_CBMEM` in
Kconfig) and then in GRUB 2 (as a payload) with the cbmemc command from
the cbmemc module and in userspace with ./cbmem -c. Both worked.
Change-Id: I34618a55ded7292a411bc232eb76267eec17d91e
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
---
src/mainboard/lenovo/x60/Kconfig | 1 +
src/mainboard/lenovo/x60/romstage.c | 16 ++++++++++------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig
index 611f932..1431a2f 100644
--- a/src/mainboard/lenovo/x60/Kconfig
+++ b/src/mainboard/lenovo/x60/Kconfig
@@ -24,6 +24,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select HAVE_ACPI_RESUME
select USE_OPTION_TABLE
select MAINBOARD_HAS_NATIVE_VGA_INIT
+ select EARLY_CBMEM_INIT
config MAINBOARD_DIR
string
diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c
index 8d5f922..0acf3a2 100644
--- a/src/mainboard/lenovo/x60/romstage.c
+++ b/src/mainboard/lenovo/x60/romstage.c
@@ -29,6 +29,7 @@
#include <device/pnp_def.h>
#include <cpu/x86/lapic.h>
#include <lib.h>
+#include <cbmem.h>
#include <pc80/mc146818rtc.h>
#include <console/console.h>
#include <cpu/x86/bist.h>
@@ -210,12 +211,11 @@ static void early_ich7_init(void)
RCBA32(0x2034) = reg32;
}
-#include <cbmem.h>
-
void main(unsigned long bist)
{
u32 reg32;
int boot_mode = 0;
+ int cbmem_was_initted;
const u8 spd_addrmap[2 * DIMM_SOCKETS] = { 0x50, 0x52, 0x51, 0x53 };
if (bist == 0)
@@ -314,14 +314,13 @@ void main(unsigned long bist)
MCHBAR16(SSKPD) = 0xCAFE;
-#if CONFIG_HAVE_ACPI_RESUME
- /* Start address of high memory tables */
- unsigned long high_ram_base = get_top_of_ram() - HIGH_MEMORY_SIZE;
+ cbmem_was_initted = !cbmem_initialize();
+#if CONFIG_HAVE_ACPI_RESUME
/* If there is no high memory area, we didn't boot before, so
* this is not a resume. In that case we just create the cbmem toc.
*/
- if ((boot_mode == 2) && cbmem_reinit((u64)high_ram_base)) {
+ if ((boot_mode == 2) && cbmem_was_initted) {
void *resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
/* copy 1MB - 64K to high tables ram_base to prevent memory corruption
@@ -336,4 +335,9 @@ void main(unsigned long bist)
pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, SKPAD_ACPI_S3_MAGIC);
}
#endif
+
+#if CONFIG_CONSOLE_CBMEM
+ /* Keep this the last thing this function does. */
+ cbmemc_reinit();
+#endif
}
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3151
-gerrit
commit 57e5ac640e9009d0f33b4435cd743b7df243d2dc
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Tue Apr 30 16:14:35 2013 +0800
Google/Snow: Revise bootblock initialization.
It's fine to always start timer even in suspend/resume mode, so we can
move the timer_start() back to the very beginning of boot procedure.
That provides more precise boot time information.
With that timer change, the wake up state test procedure can be simplified.
Verified by building and booting firmware image on Google/Snow successfully,
and then suspend-resume without problem (suspend_stress_test).
Change-Id: I0d739650dbff4eb3a75acbbf1e4356f2569b487d
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
src/mainboard/google/snow/bootblock.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index fa87203..76ed567 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -30,17 +30,14 @@
void bootblock_mainboard_init(void);
void bootblock_mainboard_init(void)
{
- switch (snow_get_wakeup_state()) {
- case SNOW_WAKEUP_DIRECT:
- snow_wakeup();
- break;
+ /* kick off the microsecond timer.
+ * We want to do this as early as we can.
+ */
+ timer_start();
- case SNOW_IS_NOT_WAKEUP:
- /* kick off the microsecond timer.
- * We want to do this as early as we can.
- */
- timer_start();
- break;
+ if (snow_get_wakeup_state() == SNOW_WAKEUP_DIRECT) {
+ snow_wakeup();
+ /* Never returns. */
}
/* For most ARM systems, we have to initialize firmware media source
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3147
-gerrit
commit e7d72473ba665d0639ad8964b10ea007af0fc79e
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Tue Apr 30 16:11:32 2013 +0800
Google/Snow: Remove duplicated SPI1 initialization in bootblock.
The firmware media source (SPI1) is already initialized by Exynos iROM.
There is no need to do it again.
Verified by building and booting Google/Snow successfully.
Change-Id: I89390506aa825397c0d7e52ad7503f1cb808f7db
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
src/mainboard/google/snow/bootblock.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 09edbad..fa87203 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -40,9 +40,14 @@ void bootblock_mainboard_init(void)
* We want to do this as early as we can.
*/
timer_start();
- exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
break;
}
+
+ /* For most ARM systems, we have to initialize firmware media source
+ * (ex, SPI, SD/MMC, or eMMC) now; but for Exynos platform, that is
+ * already handled by iROM so there's no need to setup again.
+ */
+
#if CONFIG_EARLY_CONSOLE
exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3150
-gerrit
commit e023cfef20d1ca5298aeb0f2da384bb63fa263d3
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Tue Apr 30 15:31:48 2013 +0800
Google/Snow: Remove unnecessary serial console init code.
The "console_init" does initialize UART driver (which will setup peripheral and
pinmux) and print starting message. Duplicated initialization can be removed.
Also, console_init (from console.c) is always linked to bootblock (and will do
nothing if CONFIG_EARLY_CONSOLE is not defined) so it's safe to remove #ifdef.
Verified by building and booting on Google/Snow, with and without
CONFIG_EARLY_CONSOLE.
Change-Id: I0c6b4d4eb1a4e81af0f65bcb032978dfb945c63d
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
src/mainboard/google/snow/bootblock.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 09edbad..1746290 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -43,9 +43,5 @@ void bootblock_mainboard_init(void)
exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
break;
}
-#if CONFIG_EARLY_CONSOLE
- exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
- printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__);
-#endif
}
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3150
-gerrit
commit 6a0cc96e22c3e4a99e1c1cc19d46344fa48cf453
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Tue Apr 30 15:31:48 2013 +0800
Google/Snow: Remove unnecessary serial console init code.
The "console_init" does initialize UART driver (which will setup peripheral and
pinmux) and print starting message. Duplicated initialization can be removed.
Verified by building and booting on Google/Snow.
Change-Id: I0c6b4d4eb1a4e81af0f65bcb032978dfb945c63d
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
src/mainboard/google/snow/bootblock.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 09edbad..22d775c 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -44,8 +44,6 @@ void bootblock_mainboard_init(void)
break;
}
#if CONFIG_EARLY_CONSOLE
- exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
- printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__);
#endif
}