Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3073
-gerrit
commit 9d03e206c871189091c9f0b3f878e4d5e9929285
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Thu Apr 11 15:03:28 2013 -0700
Exynos5250: add a microsecond timer
Add a microsecond timer, its declaration, the function to start it,
and its usage. To start it, one calls microsecond() for any reason,
using the result or not. From that point on, it returns microseconds
from the first call.
We show its use in romstage. You want it started very early.
Finally, the delay.h changed having been (ironically) delayed,
we create time.h and have it hold one declaration, for the
microseconds prototype.
Change-Id: I19cbc2bb0089a3de88cfb94276266af38b9363c5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/arch/armv7/lib/Makefile.inc | 2 -
src/cpu/samsung/exynos5-common/timer.c | 15 ++--
src/cpu/samsung/exynos5250/Kconfig | 8 +++
src/cpu/samsung/exynos5250/Makefile.inc | 4 +-
src/cpu/samsung/exynos5250/clock_init.c | 13 ----
src/cpu/samsung/exynos5250/mct.c | 122 ++++++++++++++++++++++++++++++++
src/include/time.h | 28 ++++++++
src/mainboard/google/snow/bootblock.c | 5 ++
src/mainboard/google/snow/romstage.c | 1 +
9 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc
index 56a1bb7..0cb5737 100644
--- a/src/arch/armv7/lib/Makefile.inc
+++ b/src/arch/armv7/lib/Makefile.inc
@@ -1,6 +1,5 @@
#FIXME: cache_v7 and cache-cp15 will go away eventually
-bootblock-y += syslib.c
bootblock-$(CONFIG_EARLY_CONSOLE) += early_console.c
bootblock-y += cache.c
@@ -13,7 +12,6 @@ ramstage-y += div0.c
#ramstage-y += interrupts.c
#ramstage-y += memcpy.S
#ramstage-y += memset.S
-ramstage-y += syslib.c
ramstage-y += cache.c
ramstage-y += mmu.c
diff --git a/src/cpu/samsung/exynos5-common/timer.c b/src/cpu/samsung/exynos5-common/timer.c
index 6cd5f5d..ca15501 100644
--- a/src/cpu/samsung/exynos5-common/timer.c
+++ b/src/cpu/samsung/exynos5-common/timer.c
@@ -25,6 +25,8 @@
#include <common.h>
#include <arch/io.h>
+#include <time.h>
+#include <console/console.h>
#include <cpu/samsung/exynos5-common/pwm.h>
#include <cpu/samsung/exynos5-common/clk.h>
#include <cpu/samsung/exynos5250/cpu.h>
@@ -117,12 +119,17 @@ unsigned long timer_get_us(void)
}
/* delay x useconds */
-void __udelay(unsigned long usec)
+void udelay(unsigned long usec)
{
- unsigned long count_value;
+ unsigned long start;
- count_value = timer_get_us_down();
- while ((int)(count_value - timer_get_us_down()) < (int)usec)
+ start = timer_us();
+ if ((start + usec) < start){
+ printk(BIOS_EMERG, "udelay: %08lx is impossibly large\n",
+ usec);
+ usec = 1000000;
+ }
+ while ((timer_us() - start) < usec)
;
}
diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig
index cc67abd..a63ccd7 100644
--- a/src/cpu/samsung/exynos5250/Kconfig
+++ b/src/cpu/samsung/exynos5250/Kconfig
@@ -97,3 +97,11 @@ config SYS_TEXT_BASE
config COREBOOT_TABLES_SIZE
hex
default 0x4000000
+
+config MCT_ADDRESS
+ hex
+ default 0x101c0000
+
+config MCT_HZ
+ int
+ default 24000000
diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc
index 74bc871..1046b8b 100644
--- a/src/cpu/samsung/exynos5250/Makefile.inc
+++ b/src/cpu/samsung/exynos5250/Makefile.inc
@@ -3,7 +3,7 @@
# image outside of CBFS
#INTERMEDIATE += exynos5250_add_bl1
-bootblock-y += pinmux.c
+bootblock-y += pinmux.c mct.c
# Clock is required for UART
bootblock-$(CONFIG_EARLY_CONSOLE) += clock_init.c
bootblock-$(CONFIG_EARLY_CONSOLE) += clock.c
@@ -16,6 +16,7 @@ romstage-y += pinmux.c # required by s3c24x0_i2c (exynos5-common) and uart.
romstage-y += dmc_common.c
romstage-y += dmc_init_ddr3.c
romstage-y += power.c
+romstage-y += mct.c
romstage-$(CONFIG_EARLY_CONSOLE) += soc.c
romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
@@ -27,6 +28,7 @@ ramstage-y += power.c
ramstage-y += soc.c
ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
ramstage-y += cpu.c
+ramstage-y += mct.c
#ramstage-$(CONFIG_SATA_AHCI) += sata.c
diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c
index 618fdb6..c8479de 100644
--- a/src/cpu/samsung/exynos5250/clock_init.c
+++ b/src/cpu/samsung/exynos5250/clock_init.c
@@ -452,16 +452,3 @@ void clock_init_dp_clock(void)
setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
}
-/*
- * This is a custom implementation for the udelay(), as we do not the timer
- * initialise during the SPL boot. We are assuming the cpu takes 3 instruction
- * pre cycle. This is based on the implementation of sdelay() function.
- */
-void udelay(unsigned usec)
-{
- unsigned long count;
-
- /* TODO(alim.akhtar(a)samsung.com): Comment on why divided by 30000000 */
- count = usec * (get_pll_clk(APLL) / (3 * 10000000));
- sdelay(count);
-}
diff --git a/src/cpu/samsung/exynos5250/mct.c b/src/cpu/samsung/exynos5250/mct.c
new file mode 100644
index 0000000..8342982
--- /dev/null
+++ b/src/cpu/samsung/exynos5250/mct.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/io.h>
+#include <stdint.h>
+#include <time.h>
+
+struct __attribute__((packed)) mct_regs
+{
+ uint32_t mct_cfg;
+ uint8_t reserved0[0xfc];
+ uint32_t g_cnt_l;
+ uint32_t g_cnt_u;
+ uint8_t reserved1[0x8];
+ uint32_t g_cnt_wstat;
+ uint8_t reserved2[0xec];
+ uint32_t g_comp0_l;
+ uint32_t g_comp0_u;
+ uint32_t g_comp0_addr_incr;
+ uint8_t reserved3[0x4];
+ uint32_t g_comp1_l;
+ uint32_t g_comp1_u;
+ uint32_t g_comp1_addr_incr;
+ uint8_t reserved4[0x4];
+ uint32_t g_comp2_l;
+ uint32_t g_comp2_u;
+ uint32_t g_comp2_addr_incr;
+ uint8_t reserved5[0x4];
+ uint32_t g_comp3_l;
+ uint32_t g_comp3_u;
+ uint32_t g_comp3_addr_incr;
+ uint8_t reserved6[0x4];
+ uint32_t g_tcon;
+ uint32_t g_int_cstat;
+ uint32_t g_int_enb;
+ uint32_t g_wstat;
+ uint8_t reserved7[0xb0];
+ uint32_t l0_tcntb;
+ uint32_t l0_tcnto;
+ uint32_t l0_icntb;
+ uint32_t l0_icnto;
+ uint32_t l0_frcntb;
+ uint32_t l0_frcnto;
+ uint8_t reserved8[0x8];
+ uint32_t l0_tcon;
+ uint8_t reserved9[0xc];
+ uint32_t l0_int_cstat;
+ uint32_t l0_int_enb;
+ uint8_t reserved10[0x8];
+ uint32_t l0_wstat;
+ uint8_t reserved11[0xbc];
+ uint32_t l1_tcntb;
+ uint32_t l1_tcnto;
+ uint32_t l1_icntb;
+ uint32_t l1_icnto;
+ uint32_t l1_frcntb;
+ uint32_t l1_frcnto;
+ uint8_t reserved12[0x8];
+ uint32_t l1_tcon;
+ uint8_t reserved13[0xc];
+ uint32_t l1_int_cstat;
+ uint32_t l1_int_enb;
+ uint8_t reserved14[0x8];
+ uint32_t l1_wstat;
+};
+
+/* I would prefer not to export these for now. */
+static uint64_t timer_hz(void)
+{
+ return CONFIG_MCT_HZ;
+}
+
+static int enabled = 0;
+static struct mct_regs *const mct =
+ (struct mct_regs *)CONFIG_MCT_ADDRESS;
+
+static uint64_t timer_raw_value(void)
+{
+ if (!enabled) {
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+ }
+
+ uint64_t upper = readl(&mct->g_cnt_u);
+ uint64_t lower = readl(&mct->g_cnt_l);
+
+ return (upper << 32) | lower;
+}
+
+void timer_start(void)
+{
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+}
+
+u32 timer_us(void)
+{
+ uint64_t raw = timer_raw_value();
+ uint32_t ticks_per_microsecond = timer_hz()/1000000;
+ uint32_t usec = raw / ticks_per_microsecond;
+ return usec;
+}
+
diff --git a/src/include/time.h b/src/include/time.h
new file mode 100644
index 0000000..6bd9e08
--- /dev/null
+++ b/src/include/time.h
@@ -0,0 +1,28 @@
+/*
+ * 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 TIME_H
+#define TIME_H
+
+#if !defined( __ROMCC__)
+
+void timer_start(void);
+u32 timer_us(void);
+#endif
+#endif /* TIME_H */
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 2df0e4e..a0fe72b 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -21,6 +21,7 @@
#include <arch/io.h>
#include <cbfs.h>
#include <uart.h>
+#include <time.h>
#include <console/console.h>
#include <cpu/samsung/exynos5250/periph.h>
#include <cpu/samsung/exynos5250/pinmux.h>
@@ -34,4 +35,8 @@ void bootblock_mainboard_init(void)
console_init();
printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__);
#endif
+ /* kick off the microsecond timer. We want to do this as early
+ * as we can.
+ */
+ timer_start();
}
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 7a26ed9..dda4e7c 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -36,6 +36,7 @@
#include <cpu/samsung/exynos5250/clock_init.h>
#include <console/console.h>
#include <arch/stages.h>
+#include <time.h>
#include <drivers/maxim/max77686/max77686.h>
#include <device/i2c.h>
Paul Menzel (paulepanter(a)users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3069
-gerrit
commit a96170b8e41367e8f269780396bdab9ae698b88b
Author: Paul Menzel <paulepanter(a)users.sourceforge.net>
Date: Thu Apr 11 10:45:11 2013 +0200
cbfstool: cbfs-mkstage.c: Free `buffer` on error path
Cppcheck warns about a memory leak, present since adding romtool,
which was renamed to cbfstool, in commit 5d01ec0f.
$ cppcheck --version
Cppcheck 1.59
[…]
[cbfs-mkstage.c:170]: (error) Memory leak: buffer
[…]
Indeed the memory pointed to by `buffer` is not freed on the error path,
so add `free(buffer)` to fix this.
Change-Id: I6cbf82479027747c800c5fe847f20b779e261ef4
Signed-off-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
---
util/cbfstool/cbfs-mkstage.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c
index 4008367..dfc93c2 100644
--- a/util/cbfstool/cbfs-mkstage.c
+++ b/util/cbfstool/cbfs-mkstage.c
@@ -167,6 +167,7 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
if (buffer_create(output, sizeof(*stage) + data_end - data_start,
input->name) != 0) {
ERROR("Unable to allocate memory: %m\n");
+ free(buffer);
return -1;
}
memset(output->data, 0, output->size);
Paul Menzel (paulepanter(a)users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3069
-gerrit
commit ae04944bc40b2bdc19b878fffc5471dac3695289
Author: Paul Menzel <paulepanter(a)users.sourceforge.net>
Date: Thu Apr 11 10:45:11 2013 +0200
cbfstool: cbfs-mkstage.c: Free `buffer` on error path
Cppcheck warns about a memory leak, present since adding romtool,
the former name of cbfstool, in commit 5d01ec0f.
$ cppcheck --version
Cppcheck 1.59
[…]
[cbfs-mkstage.c:170]: (error) Memory leak: buffer
[…]
Indeed the memory pointed to by `buffer` is not free’d on the error path,
so add `free(buffer)` to fix this.
Change-Id: I6cbf82479027747c800c5fe847f20b779e261ef4
Signed-off-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
---
util/cbfstool/cbfs-mkstage.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c
index 4008367..dfc93c2 100644
--- a/util/cbfstool/cbfs-mkstage.c
+++ b/util/cbfstool/cbfs-mkstage.c
@@ -167,6 +167,7 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
if (buffer_create(output, sizeof(*stage) + data_end - data_start,
input->name) != 0) {
ERROR("Unable to allocate memory: %m\n");
+ free(buffer);
return -1;
}
memset(output->data, 0, output->size);
the following patch was just integrated into master:
commit 8ecec215be54fc15ba1cc6f2e5c452ffb833c29a
Author: Nico Huber <nico.h(a)gmx.de>
Date: Wed Apr 10 19:14:41 2013 +0200
Revert "siemens/sitemp_g1p1: Make ACPI report the right mmconf region"
This reverts commit 1fde22c54cacb15493bbde8835ec9e20f1d39bf5:
commit 1fde22c54cacb15493bbde8835ec9e20f1d39bf5
Author: Patrick Georgi <patrick.georgi(a)secunet.com>
Date: Tue Apr 9 15:41:23 2013 +0200
siemens/sitemp_g1p1: Make ACPI report the right mmconf region
ACPI reported the entire space between top-of-memory and some
(relatively) arbitrary limit as useful for MMIO. Unfortunately
the HyperTransport configuration disagreed. Make them match up.
Other boards are not affected since they don't report any region
for that purpose at all (it seems).
Change-Id: I432a679481fd1c271f14ecd6fe74f0b7a15a698e
Signed-off-by: Patrick Georgi <patrick.georgi(a)secunet.com>
Reviewed-on: http://review.coreboot.org/3047
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich(a)gmail.com>
It sneaked in without it's dependencies and, therefore, broke the build for
all amdk8 targets. Paul Menzel already commented on the issue in [1]. It
also doesn't look like the dependencies would be pulled soon [2].
[1] http://review.coreboot.org/#/c/3047/
[2] http://review.coreboot.org/#/c/2662/
Change-Id: Ica89563aae4af3f0f35cacfe37fb608782329523
Signed-off-by: Nico Huber <nico.h(a)gmx.de>
Reviewed-on: http://review.coreboot.org/3063
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
Reviewed-by: Patrick Georgi <patrick(a)georgi-clan.de>
Reviewed-By: Patrick Georgi <patrick(a)georgi-clan.de> at Fri Apr 12 11:48:14 2013, giving +2
See http://review.coreboot.org/3063 for details.
-gerrit
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3073
-gerrit
commit 40fb35eeaf59acb0bb1231b28552df653165eb1e
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Thu Apr 11 15:03:28 2013 -0700
Exynos5250: add a microsecond timer
Add a microsecond timer, its declaration, the function to start it,
and its usage. To start it, one calls microsecond() for any reason,
using the result or not. From that point on, it returns microseconds
from the first call.
We show its use in romstage. You want it started very early.
Finally, the delay.h changed having been (ironically) delayed,
we create time.h and have it hold one declaration, for the
microseconds prototype.
Change-Id: I19cbc2bb0089a3de88cfb94276266af38b9363c5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/arch/armv7/lib/Makefile.inc | 2 -
src/cpu/samsung/exynos5-common/timer.c | 15 ++--
src/cpu/samsung/exynos5250/Kconfig | 8 +++
src/cpu/samsung/exynos5250/Makefile.inc | 4 +-
src/cpu/samsung/exynos5250/clock_init.c | 13 ----
src/cpu/samsung/exynos5250/mct.c | 122 ++++++++++++++++++++++++++++++++
src/include/time.h | 28 ++++++++
src/mainboard/google/snow/bootblock.c | 5 ++
src/mainboard/google/snow/romstage.c | 1 +
9 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc
index 56a1bb7..0cb5737 100644
--- a/src/arch/armv7/lib/Makefile.inc
+++ b/src/arch/armv7/lib/Makefile.inc
@@ -1,6 +1,5 @@
#FIXME: cache_v7 and cache-cp15 will go away eventually
-bootblock-y += syslib.c
bootblock-$(CONFIG_EARLY_CONSOLE) += early_console.c
bootblock-y += cache.c
@@ -13,7 +12,6 @@ ramstage-y += div0.c
#ramstage-y += interrupts.c
#ramstage-y += memcpy.S
#ramstage-y += memset.S
-ramstage-y += syslib.c
ramstage-y += cache.c
ramstage-y += mmu.c
diff --git a/src/cpu/samsung/exynos5-common/timer.c b/src/cpu/samsung/exynos5-common/timer.c
index 6cd5f5d..ca15501 100644
--- a/src/cpu/samsung/exynos5-common/timer.c
+++ b/src/cpu/samsung/exynos5-common/timer.c
@@ -25,6 +25,8 @@
#include <common.h>
#include <arch/io.h>
+#include <time.h>
+#include <console/console.h>
#include <cpu/samsung/exynos5-common/pwm.h>
#include <cpu/samsung/exynos5-common/clk.h>
#include <cpu/samsung/exynos5250/cpu.h>
@@ -117,12 +119,17 @@ unsigned long timer_get_us(void)
}
/* delay x useconds */
-void __udelay(unsigned long usec)
+void udelay(unsigned long usec)
{
- unsigned long count_value;
+ unsigned long start;
- count_value = timer_get_us_down();
- while ((int)(count_value - timer_get_us_down()) < (int)usec)
+ start = timer_us();
+ if ((start + usec) < start){
+ printk(BIOS_EMERG, "udelay: %08lx is impossibly large\n",
+ usec);
+ usec = 1000000;
+ }
+ while ((timer_us() - start) < usec)
;
}
diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig
index cc67abd..a63ccd7 100644
--- a/src/cpu/samsung/exynos5250/Kconfig
+++ b/src/cpu/samsung/exynos5250/Kconfig
@@ -97,3 +97,11 @@ config SYS_TEXT_BASE
config COREBOOT_TABLES_SIZE
hex
default 0x4000000
+
+config MCT_ADDRESS
+ hex
+ default 0x101c0000
+
+config MCT_HZ
+ int
+ default 24000000
diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc
index 74bc871..1046b8b 100644
--- a/src/cpu/samsung/exynos5250/Makefile.inc
+++ b/src/cpu/samsung/exynos5250/Makefile.inc
@@ -3,7 +3,7 @@
# image outside of CBFS
#INTERMEDIATE += exynos5250_add_bl1
-bootblock-y += pinmux.c
+bootblock-y += pinmux.c mct.c
# Clock is required for UART
bootblock-$(CONFIG_EARLY_CONSOLE) += clock_init.c
bootblock-$(CONFIG_EARLY_CONSOLE) += clock.c
@@ -16,6 +16,7 @@ romstage-y += pinmux.c # required by s3c24x0_i2c (exynos5-common) and uart.
romstage-y += dmc_common.c
romstage-y += dmc_init_ddr3.c
romstage-y += power.c
+romstage-y += mct.c
romstage-$(CONFIG_EARLY_CONSOLE) += soc.c
romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
@@ -27,6 +28,7 @@ ramstage-y += power.c
ramstage-y += soc.c
ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
ramstage-y += cpu.c
+ramstage-y += mct.c
#ramstage-$(CONFIG_SATA_AHCI) += sata.c
diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c
index 618fdb6..c8479de 100644
--- a/src/cpu/samsung/exynos5250/clock_init.c
+++ b/src/cpu/samsung/exynos5250/clock_init.c
@@ -452,16 +452,3 @@ void clock_init_dp_clock(void)
setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
}
-/*
- * This is a custom implementation for the udelay(), as we do not the timer
- * initialise during the SPL boot. We are assuming the cpu takes 3 instruction
- * pre cycle. This is based on the implementation of sdelay() function.
- */
-void udelay(unsigned usec)
-{
- unsigned long count;
-
- /* TODO(alim.akhtar(a)samsung.com): Comment on why divided by 30000000 */
- count = usec * (get_pll_clk(APLL) / (3 * 10000000));
- sdelay(count);
-}
diff --git a/src/cpu/samsung/exynos5250/mct.c b/src/cpu/samsung/exynos5250/mct.c
new file mode 100644
index 0000000..8342982
--- /dev/null
+++ b/src/cpu/samsung/exynos5250/mct.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/io.h>
+#include <stdint.h>
+#include <time.h>
+
+struct __attribute__((packed)) mct_regs
+{
+ uint32_t mct_cfg;
+ uint8_t reserved0[0xfc];
+ uint32_t g_cnt_l;
+ uint32_t g_cnt_u;
+ uint8_t reserved1[0x8];
+ uint32_t g_cnt_wstat;
+ uint8_t reserved2[0xec];
+ uint32_t g_comp0_l;
+ uint32_t g_comp0_u;
+ uint32_t g_comp0_addr_incr;
+ uint8_t reserved3[0x4];
+ uint32_t g_comp1_l;
+ uint32_t g_comp1_u;
+ uint32_t g_comp1_addr_incr;
+ uint8_t reserved4[0x4];
+ uint32_t g_comp2_l;
+ uint32_t g_comp2_u;
+ uint32_t g_comp2_addr_incr;
+ uint8_t reserved5[0x4];
+ uint32_t g_comp3_l;
+ uint32_t g_comp3_u;
+ uint32_t g_comp3_addr_incr;
+ uint8_t reserved6[0x4];
+ uint32_t g_tcon;
+ uint32_t g_int_cstat;
+ uint32_t g_int_enb;
+ uint32_t g_wstat;
+ uint8_t reserved7[0xb0];
+ uint32_t l0_tcntb;
+ uint32_t l0_tcnto;
+ uint32_t l0_icntb;
+ uint32_t l0_icnto;
+ uint32_t l0_frcntb;
+ uint32_t l0_frcnto;
+ uint8_t reserved8[0x8];
+ uint32_t l0_tcon;
+ uint8_t reserved9[0xc];
+ uint32_t l0_int_cstat;
+ uint32_t l0_int_enb;
+ uint8_t reserved10[0x8];
+ uint32_t l0_wstat;
+ uint8_t reserved11[0xbc];
+ uint32_t l1_tcntb;
+ uint32_t l1_tcnto;
+ uint32_t l1_icntb;
+ uint32_t l1_icnto;
+ uint32_t l1_frcntb;
+ uint32_t l1_frcnto;
+ uint8_t reserved12[0x8];
+ uint32_t l1_tcon;
+ uint8_t reserved13[0xc];
+ uint32_t l1_int_cstat;
+ uint32_t l1_int_enb;
+ uint8_t reserved14[0x8];
+ uint32_t l1_wstat;
+};
+
+/* I would prefer not to export these for now. */
+static uint64_t timer_hz(void)
+{
+ return CONFIG_MCT_HZ;
+}
+
+static int enabled = 0;
+static struct mct_regs *const mct =
+ (struct mct_regs *)CONFIG_MCT_ADDRESS;
+
+static uint64_t timer_raw_value(void)
+{
+ if (!enabled) {
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+ }
+
+ uint64_t upper = readl(&mct->g_cnt_u);
+ uint64_t lower = readl(&mct->g_cnt_l);
+
+ return (upper << 32) | lower;
+}
+
+void timer_start(void)
+{
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+}
+
+u32 timer_us(void)
+{
+ uint64_t raw = timer_raw_value();
+ uint32_t ticks_per_microsecond = timer_hz()/1000000;
+ uint32_t usec = raw / ticks_per_microsecond;
+ return usec;
+}
+
diff --git a/src/include/time.h b/src/include/time.h
new file mode 100644
index 0000000..6bd9e08
--- /dev/null
+++ b/src/include/time.h
@@ -0,0 +1,28 @@
+/*
+ * 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 TIME_H
+#define TIME_H
+
+#if !defined( __ROMCC__)
+
+void timer_start(void);
+u32 timer_us(void);
+#endif
+#endif /* TIME_H */
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 2df0e4e..a0fe72b 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -21,6 +21,7 @@
#include <arch/io.h>
#include <cbfs.h>
#include <uart.h>
+#include <time.h>
#include <console/console.h>
#include <cpu/samsung/exynos5250/periph.h>
#include <cpu/samsung/exynos5250/pinmux.h>
@@ -34,4 +35,8 @@ void bootblock_mainboard_init(void)
console_init();
printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__);
#endif
+ /* kick off the microsecond timer. We want to do this as early
+ * as we can.
+ */
+ timer_start();
}
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 7a26ed9..dda4e7c 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -36,6 +36,7 @@
#include <cpu/samsung/exynos5250/clock_init.h>
#include <console/console.h>
#include <arch/stages.h>
+#include <time.h>
#include <drivers/maxim/max77686/max77686.h>
#include <device/i2c.h>
the following patch was just integrated into master:
commit 7f23aeb05d57d4989783b35afce0017d3772fde6
Author: Siyuan Wang <wangsiyuanbuaa(a)gmail.com>
Date: Tue Apr 2 10:49:09 2013 +0800
AMD Thatcher: Fix PCIE link issues
1). Thatcher PCIE x8 slot is reverse order.
Although the PCIE slot is x16, it actually uses 8 lanes(15:8).
Because the PCIE slot is configured by PortList[0], fix this item can enable the slot.
A x1 PCIE network adapter works well in this slot.
2). Fix DdiList to detect DP monitor or HDMI monitor.
GPIO50 can be used to detect DP0/HDMI0 monitor.
If GPIO50 is 1, it is DP monitor. If GPIO50 is 0, it is HDMI monitor.
GPIO51 can be used to detect DP1/HDMI1 in the same way.
3). Disable unused PCIE port and clean up code in PlatformGnbPcie.c and devicetree.cb.
PCIE port 3 and 7 are not used in Thatcher.
Change-Id: I8524b6fc1b6cdc03ba92e7191186bfb0986767c8
Signed-off-by: Siyuan Wang <SiYuan.Wang(a)amd.com>
Signed-off-by: Siyuan Wang <wangsiyuanbuaa(a)gmail.com>
Reviewed-on: http://review.coreboot.org/3011
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
Reviewed-by: Martin Roth <martin.roth(a)se-eng.com>
Build-Tested: build bot (Jenkins) at Mon Apr 8 09:39:16 2013, giving +1
Reviewed-By: Martin Roth <martin.roth(a)se-eng.com> at Fri Apr 12 05:59:52 2013, giving +2
See http://review.coreboot.org/3011 for details.
-gerrit
the following patch was just integrated into master:
commit a904f9ef691062a43baa5542cf63daed45a1185a
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Thu Apr 11 15:58:12 2013 +0800
ec/google: Isolate EC bus protocol implementation.
The Chrome EC can be connected by different types of bus like LPC / I2C / SPI,
and the current implementation is only for LPC.
To support other types, we must first isolate the LPC protocol stuff and add
configuration variable (EC_GOOGLE_CHROMEEC_LPC) to specify bus type.
Verified by building google/link (with chromeec) configuration successfully.
Change-Id: Ib2920d8d935bcc77a5394e818f69e9265e26e8a0
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
Reviewed-on: http://review.coreboot.org/3068
Reviewed-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
Tested-by: build bot (Jenkins)
Reviewed-by: David Hendricks <dhendrix(a)chromium.org>
Build-Tested: build bot (Jenkins) at Thu Apr 11 10:54:59 2013, giving +1
Reviewed-By: David Hendricks <dhendrix(a)chromium.org> at Fri Apr 12 04:57:39 2013, giving +2
See http://review.coreboot.org/3068 for details.
-gerrit
the following patch was just integrated into master:
commit d9de6c4f0eb1c863f8fd81ede326973ad1aab0f2
Author: Steven Sherk <steven.sherk(a)se-eng.com>
Date: Thu Apr 11 08:40:57 2013 -0600
Add new superio device
- Added in new support for Nuvoton NCT5104D LPC device.
Change-Id: I0af8c5e3e46fdd0a549475b30917897ae9e144a7
Signed-off-by: Steven Sherk <steven.sherk(a)se-eng.com>
Reviewed-on: http://review.coreboot.org/3072
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich(a)gmail.com>
Build-Tested: build bot (Jenkins) at Thu Apr 11 17:19:53 2013, giving +1
Reviewed-By: Ronald G. Minnich <rminnich(a)gmail.com> at Fri Apr 12 00:37:30 2013, giving +2
See http://review.coreboot.org/3072 for details.
-gerrit
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3073
-gerrit
commit f9e2962377f10d94411cea4fac77e30737c63058
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Thu Apr 11 15:03:28 2013 -0700
Exynos5250: add a microsecond timer
Add a microsecond timer, its declaration, the function to start it,
and its usage. To start it, one calls microsecond() for any reason,
using the result or not. From that point on, it returns microseconds
from the first call.
We show its use in romstage. You want it started very early.
Finally, the delay.h changed having been (ironically) delayed,
we create time.h and have it hold one declaration, for the
microseconds prototype.
Change-Id: I19cbc2bb0089a3de88cfb94276266af38b9363c5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/arch/armv7/lib/Makefile.inc | 2 -
src/cpu/samsung/exynos5-common/timer.c | 15 ++--
src/cpu/samsung/exynos5250/Kconfig | 8 +++
src/cpu/samsung/exynos5250/Makefile.inc | 4 +-
src/cpu/samsung/exynos5250/clock_init.c | 13 ----
src/cpu/samsung/exynos5250/mct.c | 122 ++++++++++++++++++++++++++++++++
src/include/time.h | 28 ++++++++
src/mainboard/google/snow/bootblock.c | 5 ++
src/mainboard/google/snow/romstage.c | 1 +
9 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc
index 56a1bb7..0cb5737 100644
--- a/src/arch/armv7/lib/Makefile.inc
+++ b/src/arch/armv7/lib/Makefile.inc
@@ -1,6 +1,5 @@
#FIXME: cache_v7 and cache-cp15 will go away eventually
-bootblock-y += syslib.c
bootblock-$(CONFIG_EARLY_CONSOLE) += early_console.c
bootblock-y += cache.c
@@ -13,7 +12,6 @@ ramstage-y += div0.c
#ramstage-y += interrupts.c
#ramstage-y += memcpy.S
#ramstage-y += memset.S
-ramstage-y += syslib.c
ramstage-y += cache.c
ramstage-y += mmu.c
diff --git a/src/cpu/samsung/exynos5-common/timer.c b/src/cpu/samsung/exynos5-common/timer.c
index 6cd5f5d..ca15501 100644
--- a/src/cpu/samsung/exynos5-common/timer.c
+++ b/src/cpu/samsung/exynos5-common/timer.c
@@ -25,6 +25,8 @@
#include <common.h>
#include <arch/io.h>
+#include <time.h>
+#include <console/console.h>
#include <cpu/samsung/exynos5-common/pwm.h>
#include <cpu/samsung/exynos5-common/clk.h>
#include <cpu/samsung/exynos5250/cpu.h>
@@ -117,12 +119,17 @@ unsigned long timer_get_us(void)
}
/* delay x useconds */
-void __udelay(unsigned long usec)
+void udelay(unsigned long usec)
{
- unsigned long count_value;
+ unsigned long start;
- count_value = timer_get_us_down();
- while ((int)(count_value - timer_get_us_down()) < (int)usec)
+ start = timer_us();
+ if ((start + usec) < start){
+ printk(BIOS_EMERG, "udelay: %08lx is impossibly large\n",
+ usec);
+ usec = 1000000;
+ }
+ while ((timer_us() - start) < usec)
;
}
diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig
index cc67abd..a63ccd7 100644
--- a/src/cpu/samsung/exynos5250/Kconfig
+++ b/src/cpu/samsung/exynos5250/Kconfig
@@ -97,3 +97,11 @@ config SYS_TEXT_BASE
config COREBOOT_TABLES_SIZE
hex
default 0x4000000
+
+config MCT_ADDRESS
+ hex
+ default 0x101c0000
+
+config MCT_HZ
+ int
+ default 24000000
diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc
index 74bc871..1046b8b 100644
--- a/src/cpu/samsung/exynos5250/Makefile.inc
+++ b/src/cpu/samsung/exynos5250/Makefile.inc
@@ -3,7 +3,7 @@
# image outside of CBFS
#INTERMEDIATE += exynos5250_add_bl1
-bootblock-y += pinmux.c
+bootblock-y += pinmux.c mct.c
# Clock is required for UART
bootblock-$(CONFIG_EARLY_CONSOLE) += clock_init.c
bootblock-$(CONFIG_EARLY_CONSOLE) += clock.c
@@ -16,6 +16,7 @@ romstage-y += pinmux.c # required by s3c24x0_i2c (exynos5-common) and uart.
romstage-y += dmc_common.c
romstage-y += dmc_init_ddr3.c
romstage-y += power.c
+romstage-y += mct.c
romstage-$(CONFIG_EARLY_CONSOLE) += soc.c
romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
@@ -27,6 +28,7 @@ ramstage-y += power.c
ramstage-y += soc.c
ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
ramstage-y += cpu.c
+ramstage-y += mct.c
#ramstage-$(CONFIG_SATA_AHCI) += sata.c
diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c
index 618fdb6..c8479de 100644
--- a/src/cpu/samsung/exynos5250/clock_init.c
+++ b/src/cpu/samsung/exynos5250/clock_init.c
@@ -452,16 +452,3 @@ void clock_init_dp_clock(void)
setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
}
-/*
- * This is a custom implementation for the udelay(), as we do not the timer
- * initialise during the SPL boot. We are assuming the cpu takes 3 instruction
- * pre cycle. This is based on the implementation of sdelay() function.
- */
-void udelay(unsigned usec)
-{
- unsigned long count;
-
- /* TODO(alim.akhtar(a)samsung.com): Comment on why divided by 30000000 */
- count = usec * (get_pll_clk(APLL) / (3 * 10000000));
- sdelay(count);
-}
diff --git a/src/cpu/samsung/exynos5250/mct.c b/src/cpu/samsung/exynos5250/mct.c
new file mode 100644
index 0000000..8342982
--- /dev/null
+++ b/src/cpu/samsung/exynos5250/mct.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/io.h>
+#include <stdint.h>
+#include <time.h>
+
+struct __attribute__((packed)) mct_regs
+{
+ uint32_t mct_cfg;
+ uint8_t reserved0[0xfc];
+ uint32_t g_cnt_l;
+ uint32_t g_cnt_u;
+ uint8_t reserved1[0x8];
+ uint32_t g_cnt_wstat;
+ uint8_t reserved2[0xec];
+ uint32_t g_comp0_l;
+ uint32_t g_comp0_u;
+ uint32_t g_comp0_addr_incr;
+ uint8_t reserved3[0x4];
+ uint32_t g_comp1_l;
+ uint32_t g_comp1_u;
+ uint32_t g_comp1_addr_incr;
+ uint8_t reserved4[0x4];
+ uint32_t g_comp2_l;
+ uint32_t g_comp2_u;
+ uint32_t g_comp2_addr_incr;
+ uint8_t reserved5[0x4];
+ uint32_t g_comp3_l;
+ uint32_t g_comp3_u;
+ uint32_t g_comp3_addr_incr;
+ uint8_t reserved6[0x4];
+ uint32_t g_tcon;
+ uint32_t g_int_cstat;
+ uint32_t g_int_enb;
+ uint32_t g_wstat;
+ uint8_t reserved7[0xb0];
+ uint32_t l0_tcntb;
+ uint32_t l0_tcnto;
+ uint32_t l0_icntb;
+ uint32_t l0_icnto;
+ uint32_t l0_frcntb;
+ uint32_t l0_frcnto;
+ uint8_t reserved8[0x8];
+ uint32_t l0_tcon;
+ uint8_t reserved9[0xc];
+ uint32_t l0_int_cstat;
+ uint32_t l0_int_enb;
+ uint8_t reserved10[0x8];
+ uint32_t l0_wstat;
+ uint8_t reserved11[0xbc];
+ uint32_t l1_tcntb;
+ uint32_t l1_tcnto;
+ uint32_t l1_icntb;
+ uint32_t l1_icnto;
+ uint32_t l1_frcntb;
+ uint32_t l1_frcnto;
+ uint8_t reserved12[0x8];
+ uint32_t l1_tcon;
+ uint8_t reserved13[0xc];
+ uint32_t l1_int_cstat;
+ uint32_t l1_int_enb;
+ uint8_t reserved14[0x8];
+ uint32_t l1_wstat;
+};
+
+/* I would prefer not to export these for now. */
+static uint64_t timer_hz(void)
+{
+ return CONFIG_MCT_HZ;
+}
+
+static int enabled = 0;
+static struct mct_regs *const mct =
+ (struct mct_regs *)CONFIG_MCT_ADDRESS;
+
+static uint64_t timer_raw_value(void)
+{
+ if (!enabled) {
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+ }
+
+ uint64_t upper = readl(&mct->g_cnt_u);
+ uint64_t lower = readl(&mct->g_cnt_l);
+
+ return (upper << 32) | lower;
+}
+
+void timer_start(void)
+{
+ writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon);
+ enabled = 1;
+}
+
+u32 timer_us(void)
+{
+ uint64_t raw = timer_raw_value();
+ uint32_t ticks_per_microsecond = timer_hz()/1000000;
+ uint32_t usec = raw / ticks_per_microsecond;
+ return usec;
+}
+
diff --git a/src/include/time.h b/src/include/time.h
new file mode 100644
index 0000000..6bd9e08
--- /dev/null
+++ b/src/include/time.h
@@ -0,0 +1,28 @@
+/*
+ * 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 TIME_H
+#define TIME_H
+
+#if !defined( __ROMCC__)
+
+void timer_start(void);
+u32 timer_us(void);
+#endif
+#endif /* TIME_H */
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 2df0e4e..a0fe72b 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -21,6 +21,7 @@
#include <arch/io.h>
#include <cbfs.h>
#include <uart.h>
+#include <time.h>
#include <console/console.h>
#include <cpu/samsung/exynos5250/periph.h>
#include <cpu/samsung/exynos5250/pinmux.h>
@@ -34,4 +35,8 @@ void bootblock_mainboard_init(void)
console_init();
printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__);
#endif
+ /* kick off the microsecond timer. We want to do this as early
+ * as we can.
+ */
+ timer_start();
}
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 7a26ed9..dda4e7c 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -36,6 +36,7 @@
#include <cpu/samsung/exynos5250/clock_init.h>
#include <console/console.h>
#include <arch/stages.h>
+#include <time.h>
#include <drivers/maxim/max77686/max77686.h>
#include <device/i2c.h>