summaryrefslogtreecommitdiff
path: root/src/cpu/samsung
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/samsung')
-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
5 files changed, 136 insertions, 18 deletions
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;
+}
+