summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/armv7/lib/Makefile.inc2
-rw-r--r--src/cpu/samsung/exynos5-common/timer.c15
-rw-r--r--src/cpu/samsung/exynos5250/Makefile.inc4
-rw-r--r--src/cpu/samsung/exynos5250/clk.h5
-rw-r--r--src/cpu/samsung/exynos5250/clock_init.c13
-rw-r--r--src/cpu/samsung/exynos5250/mct.c117
-rw-r--r--src/include/time.h26
-rw-r--r--src/mainboard/google/snow/bootblock.c6
-rw-r--r--src/mainboard/google/snow/romstage.c1
9 files changed, 169 insertions, 20 deletions
diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc
index 56a1bb72aa..0cb5737f25 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 6cd5f5dd35..ca15501bb7 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 74bc871f36..1046b8bc0b 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 dbddce0c6d..4785894668 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 618fdb6a86..c8479deef5 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@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 0000000000..ddabbf7957
--- /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 0000000000..2cfcb356c4
--- /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 2df0e4ef61..d2e0b50b54 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 7a26ed9b50..dda4e7ca60 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>