1*3e93b4e6SMasahiro Yamada /* 2*3e93b4e6SMasahiro Yamada * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> 3*3e93b4e6SMasahiro Yamada * 4*3e93b4e6SMasahiro Yamada * Based on original Kirkwood support which is 5*3e93b4e6SMasahiro Yamada * Copyright (C) Marvell International Ltd. and its affiliates 6*3e93b4e6SMasahiro Yamada * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 7*3e93b4e6SMasahiro Yamada * 8*3e93b4e6SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 9*3e93b4e6SMasahiro Yamada */ 10*3e93b4e6SMasahiro Yamada 11*3e93b4e6SMasahiro Yamada #include <common.h> 12*3e93b4e6SMasahiro Yamada #include <asm/io.h> 13*3e93b4e6SMasahiro Yamada 14*3e93b4e6SMasahiro Yamada #define UBOOT_CNTR 0 /* counter to use for uboot timer */ 15*3e93b4e6SMasahiro Yamada 16*3e93b4e6SMasahiro Yamada /* Timer reload and current value registers */ 17*3e93b4e6SMasahiro Yamada struct orion5x_tmr_val { 18*3e93b4e6SMasahiro Yamada u32 reload; /* Timer reload reg */ 19*3e93b4e6SMasahiro Yamada u32 val; /* Timer value reg */ 20*3e93b4e6SMasahiro Yamada }; 21*3e93b4e6SMasahiro Yamada 22*3e93b4e6SMasahiro Yamada /* Timer registers */ 23*3e93b4e6SMasahiro Yamada struct orion5x_tmr_registers { 24*3e93b4e6SMasahiro Yamada u32 ctrl; /* Timer control reg */ 25*3e93b4e6SMasahiro Yamada u32 pad[3]; 26*3e93b4e6SMasahiro Yamada struct orion5x_tmr_val tmr[2]; 27*3e93b4e6SMasahiro Yamada u32 wdt_reload; 28*3e93b4e6SMasahiro Yamada u32 wdt_val; 29*3e93b4e6SMasahiro Yamada }; 30*3e93b4e6SMasahiro Yamada 31*3e93b4e6SMasahiro Yamada struct orion5x_tmr_registers *orion5x_tmr_regs = 32*3e93b4e6SMasahiro Yamada (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE; 33*3e93b4e6SMasahiro Yamada 34*3e93b4e6SMasahiro Yamada /* 35*3e93b4e6SMasahiro Yamada * ARM Timers Registers Map 36*3e93b4e6SMasahiro Yamada */ 37*3e93b4e6SMasahiro Yamada #define CNTMR_CTRL_REG (&orion5x_tmr_regs->ctrl) 38*3e93b4e6SMasahiro Yamada #define CNTMR_RELOAD_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].reload) 39*3e93b4e6SMasahiro Yamada #define CNTMR_VAL_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].val) 40*3e93b4e6SMasahiro Yamada 41*3e93b4e6SMasahiro Yamada /* 42*3e93b4e6SMasahiro Yamada * ARM Timers Control Register 43*3e93b4e6SMasahiro Yamada * CPU_TIMERS_CTRL_REG (CTCR) 44*3e93b4e6SMasahiro Yamada */ 45*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) 46*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) 47*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) 48*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) 49*3e93b4e6SMasahiro Yamada 50*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) 51*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) 52*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) 53*3e93b4e6SMasahiro Yamada #define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) 54*3e93b4e6SMasahiro Yamada 55*3e93b4e6SMasahiro Yamada /* 56*3e93b4e6SMasahiro Yamada * ARM Timer\Watchdog Reload Register 57*3e93b4e6SMasahiro Yamada * CNTMR_RELOAD_REG (TRR) 58*3e93b4e6SMasahiro Yamada */ 59*3e93b4e6SMasahiro Yamada #define TRG_ARM_TIMER_REL_OFFS 0 60*3e93b4e6SMasahiro Yamada #define TRG_ARM_TIMER_REL_MASK 0xffffffff 61*3e93b4e6SMasahiro Yamada 62*3e93b4e6SMasahiro Yamada /* 63*3e93b4e6SMasahiro Yamada * ARM Timer\Watchdog Register 64*3e93b4e6SMasahiro Yamada * CNTMR_VAL_REG (TVRG) 65*3e93b4e6SMasahiro Yamada */ 66*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_OFFS 0 67*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_MASK 0xffffffff 68*3e93b4e6SMasahiro Yamada #define TVR_ARM_TIMER_MAX 0xffffffff 69*3e93b4e6SMasahiro Yamada #define TIMER_LOAD_VAL 0xffffffff 70*3e93b4e6SMasahiro Yamada read_timer(void)71*3e93b4e6SMasahiro Yamadastatic inline ulong read_timer(void) 72*3e93b4e6SMasahiro Yamada { 73*3e93b4e6SMasahiro Yamada return readl(CNTMR_VAL_REG(UBOOT_CNTR)) 74*3e93b4e6SMasahiro Yamada / (CONFIG_SYS_TCLK / 1000); 75*3e93b4e6SMasahiro Yamada } 76*3e93b4e6SMasahiro Yamada 77*3e93b4e6SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR; 78*3e93b4e6SMasahiro Yamada 79*3e93b4e6SMasahiro Yamada #define timestamp gd->arch.tbl 80*3e93b4e6SMasahiro Yamada #define lastdec gd->arch.lastinc 81*3e93b4e6SMasahiro Yamada get_timer_masked(void)82*3e93b4e6SMasahiro Yamadaulong get_timer_masked(void) 83*3e93b4e6SMasahiro Yamada { 84*3e93b4e6SMasahiro Yamada ulong now = read_timer(); 85*3e93b4e6SMasahiro Yamada 86*3e93b4e6SMasahiro Yamada if (lastdec >= now) { 87*3e93b4e6SMasahiro Yamada /* normal mode */ 88*3e93b4e6SMasahiro Yamada timestamp += lastdec - now; 89*3e93b4e6SMasahiro Yamada } else { 90*3e93b4e6SMasahiro Yamada /* we have an overflow ... */ 91*3e93b4e6SMasahiro Yamada timestamp += lastdec + 92*3e93b4e6SMasahiro Yamada (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; 93*3e93b4e6SMasahiro Yamada } 94*3e93b4e6SMasahiro Yamada lastdec = now; 95*3e93b4e6SMasahiro Yamada 96*3e93b4e6SMasahiro Yamada return timestamp; 97*3e93b4e6SMasahiro Yamada } 98*3e93b4e6SMasahiro Yamada get_timer(ulong base)99*3e93b4e6SMasahiro Yamadaulong get_timer(ulong base) 100*3e93b4e6SMasahiro Yamada { 101*3e93b4e6SMasahiro Yamada return get_timer_masked() - base; 102*3e93b4e6SMasahiro Yamada } 103*3e93b4e6SMasahiro Yamada uboot_cntr_val(void)104*3e93b4e6SMasahiro Yamadastatic inline ulong uboot_cntr_val(void) 105*3e93b4e6SMasahiro Yamada { 106*3e93b4e6SMasahiro Yamada return readl(CNTMR_VAL_REG(UBOOT_CNTR)); 107*3e93b4e6SMasahiro Yamada } 108*3e93b4e6SMasahiro Yamada __udelay(unsigned long usec)109*3e93b4e6SMasahiro Yamadavoid __udelay(unsigned long usec) 110*3e93b4e6SMasahiro Yamada { 111*3e93b4e6SMasahiro Yamada uint current; 112*3e93b4e6SMasahiro Yamada ulong delayticks; 113*3e93b4e6SMasahiro Yamada 114*3e93b4e6SMasahiro Yamada current = uboot_cntr_val(); 115*3e93b4e6SMasahiro Yamada delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); 116*3e93b4e6SMasahiro Yamada 117*3e93b4e6SMasahiro Yamada if (current < delayticks) { 118*3e93b4e6SMasahiro Yamada delayticks -= current; 119*3e93b4e6SMasahiro Yamada while (uboot_cntr_val() < current) 120*3e93b4e6SMasahiro Yamada ; 121*3e93b4e6SMasahiro Yamada while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val()) 122*3e93b4e6SMasahiro Yamada ; 123*3e93b4e6SMasahiro Yamada } else { 124*3e93b4e6SMasahiro Yamada while (uboot_cntr_val() > (current - delayticks)) 125*3e93b4e6SMasahiro Yamada ; 126*3e93b4e6SMasahiro Yamada } 127*3e93b4e6SMasahiro Yamada } 128*3e93b4e6SMasahiro Yamada 129*3e93b4e6SMasahiro Yamada /* 130*3e93b4e6SMasahiro Yamada * init the counter 131*3e93b4e6SMasahiro Yamada */ timer_init(void)132*3e93b4e6SMasahiro Yamadaint timer_init(void) 133*3e93b4e6SMasahiro Yamada { 134*3e93b4e6SMasahiro Yamada unsigned int cntmrctrl; 135*3e93b4e6SMasahiro Yamada 136*3e93b4e6SMasahiro Yamada /* load value into timer */ 137*3e93b4e6SMasahiro Yamada writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); 138*3e93b4e6SMasahiro Yamada writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); 139*3e93b4e6SMasahiro Yamada 140*3e93b4e6SMasahiro Yamada /* enable timer in auto reload mode */ 141*3e93b4e6SMasahiro Yamada cntmrctrl = readl(CNTMR_CTRL_REG); 142*3e93b4e6SMasahiro Yamada cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); 143*3e93b4e6SMasahiro Yamada cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); 144*3e93b4e6SMasahiro Yamada writel(cntmrctrl, CNTMR_CTRL_REG); 145*3e93b4e6SMasahiro Yamada return 0; 146*3e93b4e6SMasahiro Yamada } 147*3e93b4e6SMasahiro Yamada timer_init_r(void)148*3e93b4e6SMasahiro Yamadavoid timer_init_r(void) 149*3e93b4e6SMasahiro Yamada { 150*3e93b4e6SMasahiro Yamada /* init the timestamp and lastdec value */ 151*3e93b4e6SMasahiro Yamada lastdec = read_timer(); 152*3e93b4e6SMasahiro Yamada timestamp = 0; 153*3e93b4e6SMasahiro Yamada } 154*3e93b4e6SMasahiro Yamada 155*3e93b4e6SMasahiro Yamada /* 156*3e93b4e6SMasahiro Yamada * This function is derived from PowerPC code (read timebase as long long). 157*3e93b4e6SMasahiro Yamada * On ARM it just returns the timer value. 158*3e93b4e6SMasahiro Yamada */ get_ticks(void)159*3e93b4e6SMasahiro Yamadaunsigned long long get_ticks(void) 160*3e93b4e6SMasahiro Yamada { 161*3e93b4e6SMasahiro Yamada return get_timer(0); 162*3e93b4e6SMasahiro Yamada } 163*3e93b4e6SMasahiro Yamada 164*3e93b4e6SMasahiro Yamada /* 165*3e93b4e6SMasahiro Yamada * This function is derived from PowerPC code (timebase clock frequency). 166*3e93b4e6SMasahiro Yamada * On ARM it returns the number of timer ticks per second. 167*3e93b4e6SMasahiro Yamada */ get_tbclk(void)168*3e93b4e6SMasahiro Yamadaulong get_tbclk (void) 169*3e93b4e6SMasahiro Yamada { 170*3e93b4e6SMasahiro Yamada return (ulong)CONFIG_SYS_HZ; 171*3e93b4e6SMasahiro Yamada } 172