[coreboot-gerrit] Patch set updated for coreboot: baa285c Exynos5250: add a microsecond timer

Ronald G. Minnich (rminnich@gmail.com) gerrit at coreboot.org
Fri Apr 12 22:34:25 CEST 2013


Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3073

-gerrit

commit baa285c6846458f7669cc14ae02f8f15ddd013c7
Author: Ronald G. Minnich <rminnich at 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 timer_start().  From that point
    on, one can call timer_us() to find microseconds since the timer was
    started.
    
    We show its use in the bootblock. You want it started very early.
    
    Finally, the delay.h change having been (ironically) delayed, we
    create time.h and have it hold one declaration, for the timer_us() and
    timer_start() prototype.
    
    We feel that these two functions should become the hardware specific
    functions, allowing us to finally move udelay() into src/lib where it
    belongs.
    
    Change-Id: I19cbc2bb0089a3de88cfb94276266af38b9363c5
    Signed-off-by: Ronald G. Minnich <rminnich at gmail.com>
---
 src/arch/armv7/lib/Makefile.inc         |   2 -
 src/cpu/samsung/exynos5-common/timer.c  |  15 ++--
 src/cpu/samsung/exynos5250/Makefile.inc |   4 +-
 src/cpu/samsung/exynos5250/clk.h        |   5 ++
 src/cpu/samsung/exynos5250/clock_init.c |  13 ----
 src/cpu/samsung/exynos5250/mct.c        | 117 ++++++++++++++++++++++++++++++++
 src/include/time.h                      |  26 +++++++
 src/mainboard/google/snow/bootblock.c   |   6 ++
 src/mainboard/google/snow/romstage.c    |   1 +
 9 files changed, 169 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/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/clk.h b/src/cpu/samsung/exynos5250/clk.h
index dbddce0..4785894 100644
--- a/src/cpu/samsung/exynos5250/clk.h
+++ b/src/cpu/samsung/exynos5250/clk.h
@@ -25,6 +25,11 @@
 #include <cpu/samsung/exynos5-common/clk.h>
 #include <cpu/samsung/exynos5250/pinmux.h>
 
+
+#define MCT_ADDRESS 0x101c0000
+
+#define MCT_HZ 24000000
+
 /*
  * Set mshci controller instances clock drivder
  *
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 at 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..ddabbf7
--- /dev/null
+++ b/src/cpu/samsung/exynos5250/mct.c
@@ -0,0 +1,117 @@
+/*
+ * 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>
+#include "clk.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;
+};
+
+static int enabled = 0;
+static struct mct_regs *const mct =
+	(struct mct_regs *)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();
+	static uint32_t ticks_per_microsecond = MCT_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..2cfcb35
--- /dev/null
+++ b/src/include/time.h
@@ -0,0 +1,26 @@
+/*
+ * 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
+
+void timer_start(void);
+u32 timer_us(void);
+
+#endif /* TIME_H */
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index 2df0e4e..d2e0b50 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>
@@ -28,6 +29,11 @@
 void bootblock_mainboard_init(void);
 void bootblock_mainboard_init(void)
 {
+	/* kick off the microsecond timer. We want to do this as early
+	 * as we can.
+	 */
+	timer_start();
+
 	exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
 #if CONFIG_EARLY_CONSOLE
 	exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
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>



More information about the coreboot-gerrit mailing list