aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/arm/cpu/arm926ejs/mx27
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/arch/arm/cpu/arm926ejs/mx27')
-rw-r--r--roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile7
-rw-r--r--roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c378
-rw-r--r--roms/u-boot/arch/arm/cpu/arm926ejs/mx27/relocate.S50
-rw-r--r--roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c41
-rw-r--r--roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c166
5 files changed, 642 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile
new file mode 100644
index 000000000..ac5ebaf5e
--- /dev/null
+++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+
+obj-y += generic.o timer.o reset.o relocate.o
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c
new file mode 100644
index 000000000..8b9d3a272
--- /dev/null
+++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/generic.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <net.h>
+#include <netdev.h>
+#include <vsprintf.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-imx/sys_proto.h>
+#ifdef CONFIG_MMC_MXC
+#include <asm/arch/mxcmmc.h>
+#endif
+
+/*
+ * get the system pll clock in Hz
+ *
+ * mfi + mfn / (mfd +1)
+ * f = 2 * f_ref * --------------------
+ * pd + 1
+ */
+static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
+{
+ unsigned int mfi = (pll >> 10) & 0xf;
+ unsigned int mfn = pll & 0x3ff;
+ unsigned int mfd = (pll >> 16) & 0x3ff;
+ unsigned int pd = (pll >> 26) & 0xf;
+
+ mfi = mfi <= 5 ? 5 : mfi;
+
+ return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn),
+ (mfd + 1) * (pd + 1));
+}
+
+static ulong clk_in_32k(void)
+{
+ return 1024 * CONFIG_MX27_CLK32;
+}
+
+static ulong clk_in_26m(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) {
+ /* divide by 1.5 */
+ return 26000000 * 2 / 3;
+ } else {
+ return 26000000;
+ }
+}
+
+static ulong imx_get_mpllclk(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+ ulong cscr = readl(&pll->cscr);
+ ulong fref;
+
+ if (cscr & CSCR_MCU_SEL)
+ fref = clk_in_26m();
+ else
+ fref = clk_in_32k();
+
+ return imx_decode_pll(readl(&pll->mpctl0), fref);
+}
+
+static ulong imx_get_armclk(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+ ulong cscr = readl(&pll->cscr);
+ ulong fref = imx_get_mpllclk();
+ ulong div;
+
+ if (!(cscr & CSCR_ARM_SRC_MPLL))
+ fref = lldiv((fref * 2), 3);
+
+ div = ((cscr >> 12) & 0x3) + 1;
+
+ return lldiv(fref, div);
+}
+
+static ulong imx_get_ahbclk(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+ ulong cscr = readl(&pll->cscr);
+ ulong fref = imx_get_mpllclk();
+ ulong div;
+
+ div = ((cscr >> 8) & 0x3) + 1;
+
+ return lldiv(fref * 2, 3 * div);
+}
+
+static __attribute__((unused)) ulong imx_get_spllclk(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+ ulong cscr = readl(&pll->cscr);
+ ulong fref;
+
+ if (cscr & CSCR_SP_SEL)
+ fref = clk_in_26m();
+ else
+ fref = clk_in_32k();
+
+ return imx_decode_pll(readl(&pll->spctl0), fref);
+}
+
+static ulong imx_decode_perclk(ulong div)
+{
+ return lldiv((imx_get_mpllclk() * 2), (div * 3));
+}
+
+static ulong imx_get_perclk1(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1);
+}
+
+static ulong imx_get_perclk2(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1);
+}
+
+static __attribute__((unused)) ulong imx_get_perclk3(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1);
+}
+
+static __attribute__((unused)) ulong imx_get_perclk4(void)
+{
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1);
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+ switch (clk) {
+ case MXC_ARM_CLK:
+ return imx_get_armclk();
+ case MXC_I2C_CLK:
+ return imx_get_ahbclk()/2;
+ case MXC_UART_CLK:
+ return imx_get_perclk1();
+ case MXC_FEC_CLK:
+ return imx_get_ahbclk();
+ case MXC_ESDHC_CLK:
+ return imx_get_perclk2();
+ }
+ return -1;
+}
+
+
+u32 get_cpu_rev(void)
+{
+ return MXC_CPU_MX27 << 12;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo (void)
+{
+ char buf[32];
+
+ printf("CPU: Freescale i.MX27 at %s MHz\n\n",
+ strmhz(buf, imx_get_mpllclk()));
+ return 0;
+}
+#endif
+
+int cpu_eth_init(struct bd_info *bis)
+{
+#if defined(CONFIG_FEC_MXC)
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ /* enable FEC clock */
+ writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
+ writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+ return fecmxc_initialize(bis);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(struct bd_info *bis)
+{
+#ifdef CONFIG_MMC_MXC
+ return mxc_mmc_init(bis);
+#else
+ return 0;
+#endif
+}
+
+void imx_gpio_mode(int gpio_mode)
+{
+ struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE;
+ unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+ unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+ unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
+ unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
+ unsigned int tmp;
+
+ /* Pullup enable */
+ if (gpio_mode & GPIO_PUEN) {
+ writel(readl(&regs->port[port].puen) | (1 << pin),
+ &regs->port[port].puen);
+ } else {
+ writel(readl(&regs->port[port].puen) & ~(1 << pin),
+ &regs->port[port].puen);
+ }
+
+ /* Data direction */
+ if (gpio_mode & GPIO_OUT) {
+ writel(readl(&regs->port[port].gpio_dir) | 1 << pin,
+ &regs->port[port].gpio_dir);
+ } else {
+ writel(readl(&regs->port[port].gpio_dir) & ~(1 << pin),
+ &regs->port[port].gpio_dir);
+ }
+
+ /* Primary / alternate function */
+ if (gpio_mode & GPIO_AF) {
+ writel(readl(&regs->port[port].gpr) | (1 << pin),
+ &regs->port[port].gpr);
+ } else {
+ writel(readl(&regs->port[port].gpr) & ~(1 << pin),
+ &regs->port[port].gpr);
+ }
+
+ /* use as gpio? */
+ if (!(gpio_mode & (GPIO_PF | GPIO_AF))) {
+ writel(readl(&regs->port[port].gius) | (1 << pin),
+ &regs->port[port].gius);
+ } else {
+ writel(readl(&regs->port[port].gius) & ~(1 << pin),
+ &regs->port[port].gius);
+ }
+
+ /* Output / input configuration */
+ if (pin < 16) {
+ tmp = readl(&regs->port[port].ocr1);
+ tmp &= ~(3 << (pin * 2));
+ tmp |= (ocr << (pin * 2));
+ writel(tmp, &regs->port[port].ocr1);
+
+ writel(readl(&regs->port[port].iconfa1) & ~(3 << (pin * 2)),
+ &regs->port[port].iconfa1);
+ writel(readl(&regs->port[port].iconfa1) | aout << (pin * 2),
+ &regs->port[port].iconfa1);
+ writel(readl(&regs->port[port].iconfb1) & ~(3 << (pin * 2)),
+ &regs->port[port].iconfb1);
+ writel(readl(&regs->port[port].iconfb1) | bout << (pin * 2),
+ &regs->port[port].iconfb1);
+ } else {
+ pin -= 16;
+
+ tmp = readl(&regs->port[port].ocr2);
+ tmp &= ~(3 << (pin * 2));
+ tmp |= (ocr << (pin * 2));
+ writel(tmp, &regs->port[port].ocr2);
+
+ writel(readl(&regs->port[port].iconfa2) & ~(3 << (pin * 2)),
+ &regs->port[port].iconfa2);
+ writel(readl(&regs->port[port].iconfa2) | aout << (pin * 2),
+ &regs->port[port].iconfa2);
+ writel(readl(&regs->port[port].iconfb2) & ~(3 << (pin * 2)),
+ &regs->port[port].iconfb2);
+ writel(readl(&regs->port[port].iconfb2) | bout << (pin * 2),
+ &regs->port[port].iconfb2);
+ }
+}
+
+#ifdef CONFIG_MXC_UART
+void mx27_uart1_init_pins(void)
+{
+ int i;
+ unsigned int mode[] = {
+ PE12_PF_UART1_TXD,
+ PE13_PF_UART1_RXD,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(mode); i++)
+ imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MXC_UART */
+
+#ifdef CONFIG_FEC_MXC
+void mx27_fec_init_pins(void)
+{
+ int i;
+ unsigned int mode[] = {
+ PD0_AIN_FEC_TXD0,
+ PD1_AIN_FEC_TXD1,
+ PD2_AIN_FEC_TXD2,
+ PD3_AIN_FEC_TXD3,
+ PD4_AOUT_FEC_RX_ER,
+ PD5_AOUT_FEC_RXD1,
+ PD6_AOUT_FEC_RXD2,
+ PD7_AOUT_FEC_RXD3,
+ PD8_AF_FEC_MDIO,
+ PD9_AIN_FEC_MDC | GPIO_PUEN,
+ PD10_AOUT_FEC_CRS,
+ PD11_AOUT_FEC_TX_CLK,
+ PD12_AOUT_FEC_RXD0,
+ PD13_AOUT_FEC_RX_DV,
+ PD14_AOUT_FEC_CLR,
+ PD15_AOUT_FEC_COL,
+ PD16_AIN_FEC_TX_ER,
+ PF23_AIN_FEC_TX_EN,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(mode); i++)
+ imx_gpio_mode(mode[i]);
+}
+
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+ int i;
+ struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+ struct fuse_bank *bank = &iim->bank[0];
+ struct fuse_bank0_regs *fuse =
+ (struct fuse_bank0_regs *)bank->fuse_regs;
+
+ for (i = 0; i < 6; i++)
+ mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff;
+}
+#endif /* CONFIG_FEC_MXC */
+
+#ifdef CONFIG_MMC_MXC
+void mx27_sd1_init_pins(void)
+{
+ int i;
+ unsigned int mode[] = {
+ PE18_PF_SD1_D0,
+ PE19_PF_SD1_D1,
+ PE20_PF_SD1_D2,
+ PE21_PF_SD1_D3,
+ PE22_PF_SD1_CMD,
+ PE23_PF_SD1_CLK,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(mode); i++)
+ imx_gpio_mode(mode[i]);
+
+}
+
+void mx27_sd2_init_pins(void)
+{
+ int i;
+ unsigned int mode[] = {
+ PB4_PF_SD2_D0,
+ PB5_PF_SD2_D1,
+ PB6_PF_SD2_D2,
+ PB7_PF_SD2_D3,
+ PB8_PF_SD2_CMD,
+ PB9_PF_SD2_CLK,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(mode); i++)
+ imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MMC_MXC */
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/relocate.S b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/relocate.S
new file mode 100644
index 000000000..5dfa272be
--- /dev/null
+++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/relocate.S
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * relocate - i.MX27-specific vector relocation
+ *
+ * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+/*
+ * The i.MX27 SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM. Therefore, vectors cannot be changed at all.
+ *
+ * However, these ROM-based vectors actually just perform indirect
+ * calls through pointers located in RAM at SoC-specific addresses,
+ * as follows:
+ *
+ * Offset Exception Use by ROM code
+ * 0x00000000 reset indirect branch to [0x00000014]
+ * 0x00000004 undefined instruction indirect branch to [0xfffffef0]
+ * 0x00000008 software interrupt indirect branch to [0xfffffef4]
+ * 0x0000000c prefetch abort indirect branch to [0xfffffef8]
+ * 0x00000010 data abort indirect branch to [0xfffffefc]
+ * 0x00000014 (reserved in ARMv5) vector to ROM reset: 0xc0000000
+ * 0x00000018 IRQ indirect branch to [0xffffff00]
+ * 0x0000001c FIQ indirect branch to [0xffffff04]
+ *
+ * In order to initialize exceptions on i.MX27, we must copy U-Boot's
+ * indirect (not exception!) vector table into 0xfffffef0..0xffffff04
+ * taking care not to copy vectors number 5 (reserved exception).
+ */
+
+ .section .text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
+ ldr r1, =32 /* size of vector table */
+ add r0, r0, r1 /* skip to indirect table */
+ ldr r1, =0xFFFFFEF0 /* i.MX27 indirect table */
+ ldmia r0!, {r2-r8} /* load indirect vectors 1..7 */
+ stmia r1!, {r2-r5, r7,r8} /* write all but vector 5 */
+
+ bx lr
+
+ENDPROC(relocate_vectors)
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c
new file mode 100644
index 000000000..496fb3081
--- /dev/null
+++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/reset.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let it time out
+ */
+void reset_cpu(void)
+{
+ struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
+ /* Disable watchdog and set Time-Out field to 0 */
+ writew(0x0000, &regs->wcr);
+
+ /* Write Service Sequence */
+ writew(0x5555, &regs->wsr);
+ writew(0xAAAA, &regs->wsr);
+
+ /* Enable watchdog */
+ writew(WCR_WDE, &regs->wcr);
+
+ while (1);
+ /*NOTREACHED*/
+}
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c
new file mode 100644
index 000000000..4fd6a8059
--- /dev/null
+++ b/roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <init.h>
+#include <time.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/ptrace.h>
+#include <linux/delay.h>
+
+/* General purpose timers bitfields */
+#define GPTCR_SWR (1 << 15) /* Software reset */
+#define GPTCR_FRR (1 << 8) /* Freerun / restart */
+#define GPTCR_CLKSOURCE_32 (4 << 1) /* Clock source */
+#define GPTCR_TEN 1 /* Timer enable */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->arch.tbl)
+#define lastinc (gd->arch.lastinc)
+
+/*
+ * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
+ * "tick" is internal timer period
+ */
+#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION
+/* ~0.4% error - measured with stop-watch on 100s boot-delay */
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+ tick *= CONFIG_SYS_HZ;
+ do_div(tick, CONFIG_MX27_CLK32);
+ return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+ time *= CONFIG_MX27_CLK32;
+ do_div(time, CONFIG_SYS_HZ);
+ return time;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+ us = us * CONFIG_MX27_CLK32 + 999999;
+ do_div(us, 1000000);
+ return us;
+}
+#else
+/* ~2% error */
+#define TICK_PER_TIME ((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \
+ CONFIG_SYS_HZ)
+#define US_PER_TICK (1000000 / CONFIG_MX27_CLK32)
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+ do_div(tick, TICK_PER_TIME);
+ return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+ return time * TICK_PER_TIME;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+ us += US_PER_TICK - 1;
+ do_div(us, US_PER_TICK);
+ return us;
+}
+#endif
+
+/* nothing really to do with interrupts, just starts up a counter. */
+/* The 32768Hz 32-bit timer overruns in 131072 seconds */
+int timer_init(void)
+{
+ int i;
+ struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+ struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+ /* setup GP Timer 1 */
+ writel(GPTCR_SWR, &regs->gpt_tctl);
+
+ writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0);
+ writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1);
+
+ for (i = 0; i < 100; i++)
+ writel(0, &regs->gpt_tctl); /* We have no udelay by now */
+ writel(0, &regs->gpt_tprer); /* 32Khz */
+ /* Freerun Mode, PERCLK1 input */
+ writel(readl(&regs->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
+ &regs->gpt_tctl);
+ writel(readl(&regs->gpt_tctl) | GPTCR_TEN, &regs->gpt_tctl);
+
+ return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+ struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+ ulong now = readl(&regs->gpt_tcn); /* current tick value */
+
+ if (now >= lastinc) {
+ /*
+ * normal mode (non roll)
+ * move stamp forward with absolut diff ticks
+ */
+ timestamp += (now - lastinc);
+ } else {
+ /* we have rollover of incrementer */
+ timestamp += (0xFFFFFFFF - lastinc) + now;
+ }
+ lastinc = now;
+ return timestamp;
+}
+
+static ulong get_timer_masked(void)
+{
+ /*
+ * get_ticks() returns a long long (64 bit), it wraps in
+ * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
+ * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
+ * 5 * 10^6 days - long enough.
+ */
+ return tick_to_time(get_ticks());
+}
+
+ulong get_timer(ulong base)
+{
+ return get_timer_masked() - base;
+}
+
+/* delay x useconds AND preserve advance timstamp value */
+void __udelay(unsigned long usec)
+{
+ unsigned long long tmp;
+ ulong tmo;
+
+ tmo = us_to_tick(usec);
+ tmp = get_ticks() + tmo; /* get current timestamp */
+
+ while (get_ticks() < tmp) /* loop till event */
+ /*NOP*/;
+}
+
+ulong get_tbclk(void)
+{
+ return CONFIG_MX27_CLK32;
+}