diff options
Diffstat (limited to 'src/cpu/samsung')
-rw-r--r-- | src/cpu/samsung/exynos5-common/timer.c | 15 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/Makefile.inc | 4 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/clk.h | 5 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/clock_init.c | 13 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/mct.c | 117 |
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; +} + |