Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14915
-gerrit
commit 8142256cea053aed705cb53049493b7ef7bbd95e
Author: Akshay Saraswat <akshay.s(a)samsung.com>
Date: Thu Aug 7 18:04:34 2014 +0530
Jazz: Add support for new mainboard
Adding new mainboard directory and corresponding files for
Exynos7 based Jazz reference board.
BUG=None
BRANCH=None
TEST=Compiled and booted coreboot over Jazz with this series
Change-Id: Iad84881bca253fa405c227815104e152b22fc4fc
Signed-off-by: Akshay Saraswat <akshay.s(a)samsung.com>
---
src/mainboard/samsung/jazz/Kconfig | 36 +++++++++++++++
src/mainboard/samsung/jazz/Kconfig.name | 2 +
src/mainboard/samsung/jazz/Makefile.inc | 24 ++++++++++
src/mainboard/samsung/jazz/board_info.txt | 1 +
src/mainboard/samsung/jazz/devicetree.cb | 18 ++++++++
src/mainboard/samsung/jazz/mainboard.c | 73 +++++++++++++++++++++++++++++++
src/mainboard/samsung/jazz/memlayout.ld | 16 +++++++
src/mainboard/samsung/jazz/romstage.c | 64 +++++++++++++++++++++++++++
8 files changed, 234 insertions(+)
diff --git a/src/mainboard/samsung/jazz/Kconfig b/src/mainboard/samsung/jazz/Kconfig
new file mode 100644
index 0000000..1d528b7
--- /dev/null
+++ b/src/mainboard/samsung/jazz/Kconfig
@@ -0,0 +1,36 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright 2014 Samsung Electronics Ltd.
+##
+## 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.
+##
+
+if BOARD_SAMSUNG_JAZZ
+
+config BOARD_SPECIFIC_OPTIONS
+ def_bool y
+ select SOC_SAMSUNG_EXYNOS7
+ select BOARD_ROMSIZE_KB_4096
+ select HAVE_INIT_TIMER
+
+config MAINBOARD_DIR
+ string
+ default samsung/jazz
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "Jazz"
+
+config DRAM_SIZE_MB
+ int
+ default 2048
+
+endif # BOARD_SAMSUNG_JAZZ
diff --git a/src/mainboard/samsung/jazz/Kconfig.name b/src/mainboard/samsung/jazz/Kconfig.name
new file mode 100644
index 0000000..0229585
--- /dev/null
+++ b/src/mainboard/samsung/jazz/Kconfig.name
@@ -0,0 +1,2 @@
+config BOARD_SAMSUNG_JAZZ
+ bool "Jazz"
diff --git a/src/mainboard/samsung/jazz/Makefile.inc b/src/mainboard/samsung/jazz/Makefile.inc
new file mode 100644
index 0000000..6879e79
--- /dev/null
+++ b/src/mainboard/samsung/jazz/Makefile.inc
@@ -0,0 +1,24 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 Samsung Electronics
+##
+## 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.
+##
+
+INCLUDES += -Isrc/soc/samsung/exynos7/include/
+
+bootblock-y += memlayout.ld
+
+romstage-y += memlayout.ld
+romstage-y += romstage.c
+
+ramstage-y += mainboard.c
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/samsung/jazz/board_info.txt b/src/mainboard/samsung/jazz/board_info.txt
new file mode 100644
index 0000000..b351b8e
--- /dev/null
+++ b/src/mainboard/samsung/jazz/board_info.txt
@@ -0,0 +1 @@
+Category: eval
diff --git a/src/mainboard/samsung/jazz/devicetree.cb b/src/mainboard/samsung/jazz/devicetree.cb
new file mode 100644
index 0000000..672a48e
--- /dev/null
+++ b/src/mainboard/samsung/jazz/devicetree.cb
@@ -0,0 +1,18 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 Samsung Electronics
+##
+## 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.
+##
+
+chip soc/samsung/exynos7
+ device cpu_cluster 0 on end
+end
diff --git a/src/mainboard/samsung/jazz/mainboard.c b/src/mainboard/samsung/jazz/mainboard.c
new file mode 100644
index 0000000..c2487ad
--- /dev/null
+++ b/src/mainboard/samsung/jazz/mainboard.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <string.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <cbmem.h>
+#include <delay.h>
+#include <vbe.h>
+#include <boot/coreboot_tables.h>
+#include <arch/transition.h>
+#include <armv8/arch/cpu.h>
+#include <soc/clock.h>
+#include <soc/cpu.h>
+#include <soc/gpio.h>
+#include <soc/i2c.h>
+#include <soc/pinmux.h>
+#include <soc/power.h>
+#include <stdlib.h>
+#include <symbols.h>
+
+/* Arbitrary range of DMA memory for depthcharge's drivers */
+#define DMA_START (0x77300000)
+#define DMA_SIZE (0x00100000)
+
+extern void switch_el3_to_el2(void);
+
+/* this happens after cpu_init where exynos resources are set */
+static void mainboard_init(device_t dev)
+{
+ int mmc_index, mmc_ratio = 3;
+
+ /* Sst GPIOs for SD and eMMC */
+ exynos_pinmux_mmc0();
+ exynos_pinmux_mmc2();
+
+ /* Set Clocks for SD & eMMC */
+ mmc_index = 2;
+ set_mmc_clk(mmc_index, mmc_ratio);
+ mmc_index = 0;
+ set_mmc_clk(mmc_index, mmc_ratio);
+
+ /* Load VBAR with PSCI SMC handler */
+ raw_write_vbar_el3(readl(_esram - 0x10));
+
+ switch_el3_to_el2();
+ printk(BIOS_INFO, "Switched to EL%d\n", get_current_el());
+
+ return;
+}
+
+static void mainboard_enable(device_t dev)
+{
+ dev->ops->init = &mainboard_init;
+}
+
+struct chip_operations mainboard_ops = {
+ .name = "Samsung Jazz",
+ .enable_dev = mainboard_enable,
+};
diff --git a/src/mainboard/samsung/jazz/memlayout.ld b/src/mainboard/samsung/jazz/memlayout.ld
new file mode 100644
index 0000000..a309bd3
--- /dev/null
+++ b/src/mainboard/samsung/jazz/memlayout.ld
@@ -0,0 +1,16 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <soc/samsung/exynos7/memlayout.ld>
diff --git a/src/mainboard/samsung/jazz/romstage.c b/src/mainboard/samsung/jazz/romstage.c
new file mode 100644
index 0000000..5142b25
--- /dev/null
+++ b/src/mainboard/samsung/jazz/romstage.c
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <cbfs.h>
+#include <cbmem.h>
+#include <stdlib.h>
+#include <types.h>
+#include <string.h>
+
+#include <console/console.h>
+#include <arch/cache.h>
+#include <arch/exception.h>
+#include <arch/stages.h>
+#include <soc/clock.h>
+#include <soc/cpu.h>
+#include <soc/gpio.h>
+#include <soc/i2c.h>
+#include <soc/periph.h>
+#include <soc/power.h>
+
+static int setup_power(void)
+{
+ return 0;
+}
+
+void main(void)
+{
+ void *entry;
+ int power_init_failed = setup_power();
+
+#if CONFIG_EARLY_CONSOLE
+ console_init();
+#endif
+
+ if (power_init_failed)
+ die("Failed to intialize power.\n");
+
+#if 0
+ bl31_entrypoint();
+
+ /*
+ * For now, let's store PSCI handler address in memory somewhere
+ * because it's highly probable that by the time we are ready to
+ * switch the exception level vbar_el3 has already have overwritten
+ */
+ writel((uint32_t) (uintptr_t) &runtime_exceptions, (_esram - 0x10));
+#endif
+
+ entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, CONFIG_CBFS_PREFIX "/ramstage");
+
+ stage_exit(entry);
+}
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14911
-gerrit
commit a562245965bcddce971277c9bb18e32d6dc2f6c1
Author: Akshay Saraswat <akshay.s(a)samsung.com>
Date: Thu Aug 7 15:40:03 2014 +0530
Exynos7: Add alternate CBFS
Adding alternate CBFS specific to Exynos7 to enable downloading
images from different boot media.
TEST=Compiled and booted coreboot over jazz board.
Downloaded and booted "Romstage" and "Ramstage" from both
SD and EMMC.
Change-Id: I58c38d83055867cce465d613c05fa672dec1da9c
Signed-off-by: Akshay Saraswat <akshay.s(a)samsung.com>
---
src/soc/samsung/exynos7/Makefile.inc | 3 +
src/soc/samsung/exynos7/alternate_cbfs.c | 293 +++++++++++++++++++++
.../samsung/exynos7/include/soc/alternate_cbfs.h | 83 ++++++
3 files changed, 379 insertions(+)
diff --git a/src/soc/samsung/exynos7/Makefile.inc b/src/soc/samsung/exynos7/Makefile.inc
index f17c2b0..fdf4dda 100644
--- a/src/soc/samsung/exynos7/Makefile.inc
+++ b/src/soc/samsung/exynos7/Makefile.inc
@@ -18,6 +18,7 @@ ifeq ($(CONFIG_SOC_SAMSUNG_EXYNOS7),y)
INCLUDES += -Isrc/soc/samsung/exynos7/include/
# BOOTBLOCK : UART related and minimum required hardware init
+bootblock-y += alternate_cbfs.c
bootblock-y += bootblock.c
bootblock-y += clock.c
bootblock-y += clock_init.c
@@ -33,6 +34,7 @@ bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
endif
# ROMSTAGE : Run primitive tests and remaining basic stuff
+romstage-y += alternate_cbfs.c
romstage-y += clock.c
romstage-y += gpio.c
romstage-y += mct.c
@@ -45,6 +47,7 @@ romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
endif
# RAMSTAGE : Prepare and load payload
+ramstage-y += alternate_cbfs.c
ramstage-y += clock.c
ramstage-y += cpu.c
ramstage-y += gpio.c
diff --git a/src/soc/samsung/exynos7/alternate_cbfs.c b/src/soc/samsung/exynos7/alternate_cbfs.c
new file mode 100644
index 0000000..2a9dd60
--- /dev/null
+++ b/src/soc/samsung/exynos7/alternate_cbfs.c
@@ -0,0 +1,293 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <assert.h>
+#include <cbfs.h> /* This driver serves as a CBFS media source. */
+#include <stdlib.h>
+#include <string.h>
+#include <arch/cache.h>
+#include <console/console.h>
+#include <soc/alternate_cbfs.h>
+#include <soc/power.h>
+
+/* This allows USB A-A firmware upload from a compatible host in four parts:
+ * The first two are the bare BL1 and the Coreboot boot block, which are just
+ * written to their respective loading addresses. These transfers are initiated
+ * by the IROM / BL1, so this code has nothing to do with them.
+ *
+ * The third transfer is a valid CBFS image that contains only the romstage,
+ * and must be small enough to fit into alternate_cbfs_size[__BOOT_BLOCK__] in
+ * IRAM. It is loaded when this function gets called in the boot block, and
+ * the normal CBFS code extracts the romstage from it.
+ *
+ * The fourth transfer is also a CBFS image, but can be of arbitrary size and
+ * should contain all available stages/payloads/etc. It is loaded when this
+ * function is called a second time at the end of the romstage, and copied to
+ * alternate_cbfs_buffer[!__BOOT_BLOCK__] in DRAM. It will reside there for the
+ * rest of the firmware's lifetime and all subsequent stages (which will not
+ * have __PRE_RAM__ defined) can just directly reference it there.
+ */
+static int usb_cbfs_open(struct cbfs_media *media)
+{
+#ifdef __PRE_RAM__
+ static int first_run = 1;
+ int (*irom_load_usb)(void) = (void *) (uintptr_t)
+ READ32(irom_load_image_from_usb_ptr);
+
+ if (!first_run)
+ return 0;
+
+ dcache_mmu_disable();
+ if (!irom_load_usb()) {
+ dcache_mmu_enable();
+ printk(BIOS_EMERG, "Unable to load CBFS image via USB!\n");
+ return -1;
+ }
+ dcache_mmu_enable();
+
+ /*
+ * We need to trust the host/irom to copy the image to our
+ * alternate_cbfs_buffer address... there is no way to control or even
+ * check the transfer size or target address from our side.
+ */
+
+ printk(BIOS_DEBUG,
+ "USB A-A transfer successful, CBFS image should now be at %p\n",
+ alternate_cbfs_buffer);
+ first_run = 0;
+#endif
+ return 0;
+}
+
+/*
+ * SDMMC works very similar to USB A-A: we copy the CBFS image into memory
+ * and read it from there. While SDMMC would also allow direct block by block
+ * on-demand reading, we might run into problems if we call back into the IROM
+ * in very late boot stages (e.g. after initializing/changing MMC clocks)... so
+ * this seems like a safer approach. It also makes it easy to pass our image
+ * down to payloads.
+ */
+static int sdmmc_cbfs_open(struct cbfs_media *media)
+{
+#ifdef __PRE_RAM__
+ /*
+ * In the bootblock, we just copy the small part that fits in the buffer
+ * and hope that it's enough (since the romstage is currently always the
+ * first component in the image, this should work out). In the romstage,
+ * we copy until our buffer is full (currently 12M) to avoid the pain of
+ * figuring out the true image size from in here. Since this is mainly a
+ * developer/debug boot mode, those shortcomings should be bearable.
+ */
+ const u32 count = alternate_cbfs_size / BLOCK_SIZE;
+ static int first_run = 1;
+ int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) =
+ (void *) (uintptr_t) READ32(irom_sdmmc_read_blocks_ptr);
+
+ if (!first_run)
+ return 0;
+
+ if (!irom_load_sdmmc(1, count, alternate_cbfs_buffer)) {
+ printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n");
+ return -1;
+ }
+
+ printk(BIOS_INFO,
+ "SDMMC read successful, CBFS image should now be at %p\n",
+ alternate_cbfs_buffer);
+
+ first_run = 0;
+#endif
+ return 0;
+}
+
+static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
+
+static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
+ size_t offset, size_t count)
+{
+ ASSERT(offset + count < alternate_cbfs_size);
+ memcpy(dest, alternate_cbfs_buffer + offset, count);
+ return count;
+}
+
+static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
+ size_t count)
+{
+ ASSERT(offset + count < alternate_cbfs_size);
+ return alternate_cbfs_buffer + offset;
+}
+
+static void *alternate_cbfs_unmap(struct cbfs_media *media,
+ const void *buffer) { return 0; }
+
+static int emmc_cbfs_open(struct cbfs_media *media)
+{
+#ifdef __PRE_RAM__
+ /*
+ * In the bootblock, we just copy the small part that fits in the buffer
+ * and hope that it's enough (since the romstage is currently always the
+ * first component in the image, this should work out). In the romstage,
+ * we copy until our buffer is full (currently 12M) to avoid the pain of
+ * figuring out the true image size from in here. Since this is mainly a
+ * developer/debug boot mode, those shortcomings should be bearable.
+ */
+ const u32 count = alternate_cbfs_size / BLOCK_SIZE;
+ static int first_run = 1;
+ uint32_t existing_magic = CONFIG_CBFS_HEADER_ROM_OFFSET;
+ existing_magic -= (BLOCK_SIZE *
+ TYPECAST32(read32((void *) (CONFIG_BOOTBLOCK_BASE - 0x10))));
+ existing_magic -= BL1_SIZE;
+ existing_magic += TYPECAST32(alternate_cbfs_buffer);
+ existing_magic = read32((void *) (uintptr_t) existing_magic);
+
+ int (*irom_load_emmc)(u32 count, void * dst) =
+ (void *) (uintptr_t) READ32(irom_msh_read_from_fifo_emmc_ptr);
+
+ if (!first_run)
+ return 0;
+
+ if (CBFS_HEADER_MAGIC == ntohl(existing_magic)) {
+ printk(BIOS_EMERG, "CBFS image already loaded from eMMC, read successful!\n");
+ first_run = 0;
+ return 0;
+ }
+
+ if (!irom_load_emmc(count, alternate_cbfs_buffer)) {
+ printk(BIOS_EMERG, "Unable to load CBFS image from eMMC!\n");
+ return -1;
+ }
+
+ printk(BIOS_DEBUG,
+ "EMMC read successful, CBFS image should now be at %p\n",
+ alternate_cbfs_buffer);
+ first_run = 0;
+#endif
+ return 0;
+}
+
+static int emmc_cbfs_close(struct cbfs_media *media)
+{
+#ifdef __PRE_RAM__
+ void (*irom_load_emmc_end)(void) = (void *) (uintptr_t)
+ READ32(irom_msh_end_boot_op_emmc_ptr);
+
+ irom_load_emmc_end();
+#endif
+ return 0;
+}
+
+/* Bootblock has a 16 byte long header required by the BL1.
+ * First 4 bytes provide size of the bootblock, next 4 bytes contain checksum,
+ * third set of 4 bytes contain a string "head" and the last set is reserved.
+ * Now, we will read the size of bootblock from the header.
+ *
+ * Why we need this size ?
+ *
+ * Because we have a limitation that eMMC driver starts reading from the point
+ * where it stopped last time. So, we download rest of the coreboot image once
+ * in the DRAM and subtract the size of BL1 + bootblock from the expected
+ * offset.
+ *
+ * For Example :
+ * Expected image address in DRAM = 0x80000000
+ * Expected offset for CBFS header = 0xa0000
+ *
+ * But, our function pointer is only going to read rest of the image i.e.
+ * romstage, ramstage, payload etc.
+ *
+ * Therefore,
+ * New offset for CBFS header = 0xa0000 - size_of_BL1 - size_of_bootblock
+ */
+
+
+static void *emmc_cbfs_map(struct cbfs_media *media, size_t offset,
+ size_t count)
+{
+ offset -= (BLOCK_SIZE *
+ TYPECAST32(read32((void *) (CONFIG_BOOTBLOCK_BASE - 0x10))));
+ offset -= BL1_SIZE;
+ ASSERT(offset + count < alternate_cbfs_size);
+ return alternate_cbfs_buffer + offset;
+}
+
+static size_t emmc_cbfs_read(struct cbfs_media *media, void *dest,
+ size_t offset, size_t count)
+{
+ offset -= (BLOCK_SIZE *
+ TYPECAST32(read32((void *) (CONFIG_BOOTBLOCK_BASE - 0x10))));
+ offset -= BL1_SIZE;
+ ASSERT(offset + count < alternate_cbfs_size);
+ memcpy(dest, alternate_cbfs_buffer + offset, count);
+ return count;
+}
+
+static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
+{
+ printk(BIOS_SPEW, "Using Exynos alternate boot mode SDMMC\n");
+
+ media->open = sdmmc_cbfs_open;
+ media->close = alternate_cbfs_close;
+ media->read = alternate_cbfs_read;
+ media->map = alternate_cbfs_map;
+ media->unmap = alternate_cbfs_unmap;
+
+ return 0;
+}
+
+static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
+{
+ printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
+
+ media->open = usb_cbfs_open;
+ media->close = alternate_cbfs_close;
+ media->read = alternate_cbfs_read;
+ media->map = alternate_cbfs_map;
+ media->unmap = alternate_cbfs_unmap;
+
+ return 0;
+}
+
+static int initialize_exynos_emmc_cbfs_media(struct cbfs_media *media)
+{
+ printk(BIOS_SPEW, "Using Exynos alternate boot mode eMMC\n");
+
+ media->open = emmc_cbfs_open;
+ media->close = emmc_cbfs_close;
+ media->read = emmc_cbfs_read;
+ media->map = emmc_cbfs_map;
+ media->unmap = alternate_cbfs_unmap;
+
+ return 0;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media)
+{
+ uint32_t bootmode;
+
+ if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
+ return initialize_exynos_usb_cbfs_media(media);
+
+ bootmode = read32((void *) (EXYNOS7_PMU_ALIVE_BASE)) & OM_STAT_MASK;
+
+ switch (bootmode) {
+ case OM_STAT_SDMMC:
+ return initialize_exynos_sdmmc_cbfs_media(media);
+ case OM_STAT_EMMC:
+ return initialize_exynos_emmc_cbfs_media(media);
+ default:
+ printk(BIOS_EMERG, "Exynos OM_STAT value not supported!\n");
+ }
+ return 0;
+}
diff --git a/src/soc/samsung/exynos7/include/soc/alternate_cbfs.h b/src/soc/samsung/exynos7/include/soc/alternate_cbfs.h
new file mode 100644
index 0000000..2d29c57
--- /dev/null
+++ b/src/soc/samsung/exynos7/include/soc/alternate_cbfs.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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/io.h>
+#include <types.h>
+
+#ifndef _CPU_SAMSUNG_EXYNOS7_ALTERNATE_CBFS_H_
+#define _CPU_SAMSUNG_EXYNOS7_ALTERNATE_CBFS_H_
+
+/* Size of a single block */
+#define BLOCK_SIZE 0x200
+
+/* Size of BL1 binary */
+#define BL1_SIZE (8 * 1024)
+
+/* OM Pin status for SD boot mode */
+#define OM_STAT_SDMMC 0x13
+
+/* OM Pin status for eMMC boot mode */
+#define OM_STAT_EMMC 0x1
+
+/* OM Pin status mask */
+#define OM_STAT_MASK 0x3f
+
+/* Starting address of IRAM */
+#define IRAM_BASE (0x21 << 20)
+
+/* Value for USB secondary boot mode.
+ * This is the fallback option when there is no BL1 in SD.
+ */
+#define SECONDARY_BASE_BOOT_USB 0xfeed0002
+
+/* Irom's function pointer for SD copy resides here */
+#define SD_COPY_ENTRY_POINT (IRAM_BASE + 0xa0)
+
+/* Irom's function pointer for eMMC copy resides here */
+#define EMMC_COPY_ENTRY_POINT (IRAM_BASE + 0xb4)
+
+/* Irom's function pointer for eMMC cleanup resides here */
+#define EMMC_CLEANUP_ENTRY_POINT (EMMC_COPY_ENTRY_POINT + 0x4)
+
+/* Irom's function pointer for SPI Flash copy resides here */
+#define SF_COPY_ENTRY_POINT (IRAM_BASE + 0xd0)
+
+/* Irom's function pointer for USB copy resides here */
+#define USB_COPY_ENTRY_POINT (IRAM_BASE + 0xdc)
+
+/* Read a 32 bit pointer */
+#define READ32(x) *((uint32_t *) (uintptr_t) x)
+
+/* Typecast to a 32 bit value */
+#define TYPECAST32(x) ((uint32_t) (uintptr_t) x)
+
+/* These are pointers to function pointers. Double indirection! */
+static void ** const irom_sdmmc_read_blocks_ptr =
+ (void **) SD_COPY_ENTRY_POINT;
+static void ** const irom_msh_read_from_fifo_emmc_ptr =
+ (void **) EMMC_COPY_ENTRY_POINT;
+static void ** const irom_msh_end_boot_op_emmc_ptr =
+ (void **) EMMC_CLEANUP_ENTRY_POINT;
+static void ** const irom_spi_sf_read_ptr =
+ (void **) SF_COPY_ENTRY_POINT;
+static void ** const irom_load_image_from_usb_ptr =
+ (void **) USB_COPY_ENTRY_POINT;
+
+static uint32_t * const iram_secondary_base = (uint32_t *) IRAM_BASE;
+
+static void * const alternate_cbfs_buffer = (void *) CONFIG_CBFS_CACHE_ADDRESS;
+static size_t const alternate_cbfs_size = CONFIG_CBFS_CACHE_SIZE;
+
+#endif /* _CPU_SAMSUNG_EXYNOS7_ALTERNATE_CBFS_H_ */
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14910
-gerrit
commit bd406a7814fc9d7181deaa2286c5827adddda5d7
Author: Akshay Saraswat <akshay.s(a)samsung.com>
Date: Thu Aug 7 15:34:50 2014 +0530
Exynos7: Add UART initialization
This patch adds UART setup for Exynos7. It also enables UART-2 as
default serial port.
TEST=Built and booted Coreboot Over Jazz. Saw prints over console.
Change-Id: Id5f3f69d6d3aef9efa888259534d3ad93cfed8ba
Signed-off-by: Akshay Saraswat <akshay.s(a)samsung.com>
Signed-off-by: Stefan Reinauer <stefan.reinauer(a)coreboot.org>
---
src/soc/samsung/exynos7/Makefile.inc | 7 ++
src/soc/samsung/exynos7/include/soc/uart.h | 39 ++++++++
src/soc/samsung/exynos7/uart.c | 153 +++++++++++++++++++++++++++++
3 files changed, 199 insertions(+)
diff --git a/src/soc/samsung/exynos7/Makefile.inc b/src/soc/samsung/exynos7/Makefile.inc
index 898260d..f17c2b0 100644
--- a/src/soc/samsung/exynos7/Makefile.inc
+++ b/src/soc/samsung/exynos7/Makefile.inc
@@ -28,6 +28,9 @@ bootblock-y += monotonic_timer.c
bootblock-y += pinmux.c
bootblock-y += power.c
bootblock-y += timer.c
+ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y)
+bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
+endif
# ROMSTAGE : Run primitive tests and remaining basic stuff
romstage-y += clock.c
@@ -37,6 +40,9 @@ romstage-y += monotonic_timer.c
romstage-y += pinmux.c
romstage-y += power.c
romstage-y += timer.c
+ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y)
+romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
+endif
# RAMSTAGE : Prepare and load payload
ramstage-y += clock.c
@@ -47,6 +53,7 @@ ramstage-y += monotonic_timer.c
ramstage-y += pinmux.c
ramstage-y += power.c
ramstage-y += timer.c
+ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf
cp $< $@
diff --git a/src/soc/samsung/exynos7/include/soc/uart.h b/src/soc/samsung/exynos7/include/soc/uart.h
new file mode 100644
index 0000000..d3abb43
--- /dev/null
+++ b/src/soc/samsung/exynos7/include/soc/uart.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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.
+ */
+
+#ifndef _CPU_SAMSUNG_EXYNOS7_UART_H_
+#define _CPU_SAMSUNG_EXYNOS7_UART_H_
+
+#include <stddef.h>
+
+struct exynos_uart {
+ unsigned int ulcon;
+ unsigned int ucon;
+ unsigned int ufcon;
+ unsigned int umcon;
+ unsigned int utrstat;
+ unsigned int uerstat;
+ unsigned int ufstat;
+ unsigned int umstat;
+ unsigned char utxh;
+ unsigned char res1[3];
+ unsigned char urxh;
+ unsigned char res2[3];
+ unsigned int ubrdiv;
+ unsigned char res3[0xffd0];
+};
+check_member(exynos_uart, ubrdiv, 0x28);
+
+#endif /* _CPU_SAMSUNG_EXYNOS7_UART_H_ */
diff --git a/src/soc/samsung/exynos7/uart.c b/src/soc/samsung/exynos7/uart.c
new file mode 100644
index 0000000..3c041a7
--- /dev/null
+++ b/src/soc/samsung/exynos7/uart.c
@@ -0,0 +1,153 @@
+/* This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <types.h>
+#include <uart.h>
+#include <arch/io.h>
+#include <console/console.h> /* for __console definition */
+#include <soc/clock.h>
+#include <soc/cpu.h>
+#include <soc/periph.h>
+#include <soc/uart.h>
+
+#define RX_FIFO_COUNT_MASK 0xff
+#define RX_FIFO_FULL_MASK (1 << 8)
+#define TX_FIFO_FULL_MASK (1 << 24)
+
+static struct exynos_uart * base_port =
+ (struct exynos_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
+
+static void serial_setbrg_dev(void)
+{
+ struct exynos_uart *uart = base_port;
+ u32 uclk;
+ u32 baudrate = CONFIG_TTYS0_BAUD;
+ u32 val;
+
+ /* All UARTs share the same clock */
+ uclk = get_uart_clk(PERIPH_ID_UART2);
+ val = uclk / baudrate;
+
+ write32(&uart->ubrdiv, val / 16 - 1);
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static void exynos7_init_dev(void)
+{
+ struct exynos_uart *uart = base_port;
+
+ /* enable FIFOs */
+ write32(&uart->ufcon, 0x1);
+ write32(&uart->umcon, 0);
+ /* 8N1 */
+ write32(&uart->ulcon, 0x3);
+ /* No interrupts, no DMA, pure polling */
+ write32(&uart->ucon, 0x245);
+
+ serial_setbrg_dev();
+}
+
+static int exynos7_uart_err_check(int op)
+{
+ struct exynos_uart *uart = base_port;
+ unsigned int mask;
+
+ /*
+ * UERSTAT
+ * Break Detect [3]
+ * Frame Err [2] : receive operation
+ * Parity Err [1] : receive operation
+ * Overrun Err [0] : receive operation
+ */
+ if (op)
+ mask = 0x8;
+ else
+ mask = 0xf;
+
+ return read32(&uart->uerstat) & mask;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+static unsigned char exynos7_uart_rx_byte(void)
+{
+ struct exynos_uart *uart = base_port;
+
+ /* wait for character to arrive */
+ while (!(read32(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
+ RX_FIFO_FULL_MASK))) {
+ if (exynos7_uart_err_check(0))
+ return 0;
+ }
+
+ return readb(&uart->urxh) & 0xff;
+}
+
+/*
+ * Output a single byte to the serial port.
+ */
+static void exynos7_uart_tx_byte(unsigned char data)
+{
+ struct exynos_uart *uart = base_port;
+
+ /* wait for room in the tx FIFO */
+ while ((read32(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
+ if (exynos7_uart_err_check(1))
+ return;
+ }
+
+ writeb(data, &uart->utxh);
+}
+
+#if !defined(__PRE_RAM__)
+
+static const struct console_driver exynos7_uart_console __console = {
+ .init = exynos7_init_dev,
+ .tx_byte = exynos7_uart_tx_byte,
+ .rx_byte = exynos7_uart_rx_byte,
+};
+
+uint32_t uartmem_getbaseaddr(void)
+{
+ return ((uint32_t) (uintptr_t) base_port);
+}
+
+#else
+
+void uart_init(void)
+{
+ exynos7_init_dev();
+}
+
+unsigned char uart_rx_byte(void)
+{
+ return exynos7_uart_rx_byte();
+}
+
+void uart_tx_byte(unsigned char data)
+{
+ exynos7_uart_tx_byte(data);
+}
+
+void uart_tx_flush(void)
+{
+}
+
+#endif
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14908
-gerrit
commit 51ab963149cb8c544c147aa672b5c0784ed20f8b
Author: Akshay Saraswat <akshay.s(a)samsung.com>
Date: Thu Aug 7 16:15:47 2014 +0530
Exynos7: Add timer initialization
Adding initial MCT setup for Exynos7.
Change-Id: I45df0ff9f95ca9165f3cc31d302b6616ee690d35
Signed-off-by: Akshay Saraswat <akshay.s(a)samsung.com>
Signed-off-by: Stefan Reinauer <stefan.reinauer(a)coreboot.org>
---
src/soc/samsung/exynos7/Makefile.inc | 9 ++++
src/soc/samsung/exynos7/bootblock.c | 6 +++
src/soc/samsung/exynos7/include/soc/mct.h | 88 +++++++++++++++++++++++++++++++
src/soc/samsung/exynos7/mct.c | 31 +++++++++++
src/soc/samsung/exynos7/monotonic_timer.c | 31 +++++++++++
src/soc/samsung/exynos7/timer.c | 52 ++++++++++++++++++
6 files changed, 217 insertions(+)
diff --git a/src/soc/samsung/exynos7/Makefile.inc b/src/soc/samsung/exynos7/Makefile.inc
index f2b7b16..eeb9fcf 100644
--- a/src/soc/samsung/exynos7/Makefile.inc
+++ b/src/soc/samsung/exynos7/Makefile.inc
@@ -22,16 +22,25 @@ bootblock-y += bootblock.c
bootblock-y += clock.c
bootblock-y += clock_init.c
bootblock-y += dmc_init_lpddr4.c
+bootblock-y += mct.c
+bootblock-y += monotonic_timer.c
bootblock-y += power.c
+bootblock-y += timer.c
# ROMSTAGE : Run primitive tests and remaining basic stuff
romstage-y += clock.c
+romstage-y += mct.c
+romstage-y += monotonic_timer.c
romstage-y += power.c
+romstage-y += timer.c
# RAMSTAGE : Prepare and load payload
ramstage-y += clock.c
ramstage-y += cpu.c
+ramstage-y += mct.c
+ramstage-y += monotonic_timer.c
ramstage-y += power.c
+ramstage-y += timer.c
$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf
cp $< $@
diff --git a/src/soc/samsung/exynos7/bootblock.c b/src/soc/samsung/exynos7/bootblock.c
index c197940..7183731 100644
--- a/src/soc/samsung/exynos7/bootblock.c
+++ b/src/soc/samsung/exynos7/bootblock.c
@@ -21,6 +21,7 @@
#include <soc/clock.h>
#include <soc/cpu.h>
#include <soc/dmc.h>
+#include <soc/mct.h>
#include <soc/power.h>
void bootblock_cpu_init(void)
@@ -32,6 +33,11 @@ void bootblock_cpu_init(void)
if (power_read_reset_status() == EXYNOS7_CHECK_SLEEP)
is_resume = 1;
+ /* kick off the multi-core timer.
+ * We want to do this as early as we can.
+ */
+ mct_start();
+
/* SCR_EL3.NS|IRQ|FIQ|EA */
raw_write_scr_el3(raw_read_scr_el3() | 0xf);
diff --git a/src/soc/samsung/exynos7/include/soc/mct.h b/src/soc/samsung/exynos7/include/soc/mct.h
new file mode 100644
index 0000000..2308daa
--- /dev/null
+++ b/src/soc/samsung/exynos7/include/soc/mct.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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.
+ */
+
+#ifndef _CPU_SAMSUNG_EXYNOS7_MCT_H_
+#define _CPU_SAMSUNG_EXYNOS7_MCT_H_
+
+#include <stddef.h>
+#include <soc/cpu.h>
+
+struct exynos_mct {
+ 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;
+};
+check_member(exynos_mct, l1_wstat, 0x440);
+
+static struct exynos_mct * const exynos_mct =
+ (void *)EXYNOS7_MCT_BASE;
+
+
+void mct_start(void);
+uint64_t mct_raw_value(void);
+
+#endif /* _CPU_SAMSUNG_EXYNOS7_MCT_H_ */
diff --git a/src/soc/samsung/exynos7/mct.c b/src/soc/samsung/exynos7/mct.c
new file mode 100644
index 0000000..d911b92
--- /dev/null
+++ b/src/soc/samsung/exynos7/mct.c
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <stdint.h>
+#include <arch/io.h>
+#include <soc/mct.h>
+
+uint64_t mct_raw_value(void)
+{
+ uint64_t upper = read32(&exynos_mct->g_cnt_u);
+ uint64_t lower = read32(&exynos_mct->g_cnt_l);
+
+ return (upper << 32) | lower;
+}
+
+void mct_start(void)
+{
+ write32(&exynos_mct->g_tcon, read32(&exynos_mct->g_tcon) | (0x1 << 8));
+}
diff --git a/src/soc/samsung/exynos7/monotonic_timer.c b/src/soc/samsung/exynos7/monotonic_timer.c
new file mode 100644
index 0000000..c8e94fc
--- /dev/null
+++ b/src/soc/samsung/exynos7/monotonic_timer.c
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <stdint.h>
+#include <timer.h>
+
+#include <soc/clock.h>
+#include <soc/mct.h>
+
+static const uint32_t clocks_per_usec = MCT_HZ/1000000;
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+ /* We don't have to call mct_start() here
+ * because it was already called int he bootblock
+ */
+
+ mono_time_set_usecs(mt, mct_raw_value() / clocks_per_usec);
+}
diff --git a/src/soc/samsung/exynos7/timer.c b/src/soc/samsung/exynos7/timer.c
new file mode 100644
index 0000000..d8add89
--- /dev/null
+++ b/src/soc/samsung/exynos7/timer.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * 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 <console/console.h>
+#include <timer.h>
+#include <delay.h>
+#include <thread.h>
+#include <soc/clock.h>
+
+void init_timer(void)
+{
+ /* Nothing to do because we manually
+ * call mct_start() in the bootblock
+ */
+}
+
+/* delay x useconds */
+void udelay(unsigned usec)
+{
+ struct mono_time current, end;
+
+ if (!thread_yield_microseconds(usec))
+ return;
+
+ timer_monotonic_get(¤t);
+ end = current;
+ mono_time_add_usecs(&end, usec);
+
+ if (mono_time_after(¤t, &end)) {
+ printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n",
+ usec);
+ /* There's not much we can do if usec is too big. Use a long,
+ * paranoid delay value and hope for the best... */
+ end = current;
+ mono_time_add_usecs(&end, USECS_PER_SEC);
+ }
+
+ while (mono_time_before(¤t, &end))
+ timer_monotonic_get(¤t);
+}