1/* 2 * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net> 3 * 4 * Based on original Kirkwood support which is 5 * Copyright (C) Marvell International Ltd. and its affiliates 6 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 24 * MA 02110-1301 USA 25 */ 26 27#include <common.h> 28#include <asm/io.h> 29 30#define UBOOT_CNTR 0 /* counter to use for uboot timer */ 31 32/* Timer reload and current value registers */ 33struct orion5x_tmr_val { 34 u32 reload; /* Timer reload reg */ 35 u32 val; /* Timer value reg */ 36}; 37 38/* Timer registers */ 39struct orion5x_tmr_registers { 40 u32 ctrl; /* Timer control reg */ 41 u32 pad[3]; 42 struct orion5x_tmr_val tmr[2]; 43 u32 wdt_reload; 44 u32 wdt_val; 45}; 46 47struct orion5x_tmr_registers *orion5x_tmr_regs = 48 (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE; 49 50/* 51 * ARM Timers Registers Map 52 */ 53#define CNTMR_CTRL_REG (&orion5x_tmr_regs->ctrl) 54#define CNTMR_RELOAD_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].reload) 55#define CNTMR_VAL_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].val) 56 57/* 58 * ARM Timers Control Register 59 * CPU_TIMERS_CTRL_REG (CTCR) 60 */ 61#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) 62#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) 63#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) 64#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) 65 66#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) 67#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) 68#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) 69#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) 70 71/* 72 * ARM Timer\Watchdog Reload Register 73 * CNTMR_RELOAD_REG (TRR) 74 */ 75#define TRG_ARM_TIMER_REL_OFFS 0 76#define TRG_ARM_TIMER_REL_MASK 0xffffffff 77 78/* 79 * ARM Timer\Watchdog Register 80 * CNTMR_VAL_REG (TVRG) 81 */ 82#define TVR_ARM_TIMER_OFFS 0 83#define TVR_ARM_TIMER_MASK 0xffffffff 84#define TVR_ARM_TIMER_MAX 0xffffffff 85#define TIMER_LOAD_VAL 0xffffffff 86 87static inline ulong read_timer(void) 88{ 89 return readl(CNTMR_VAL_REG(UBOOT_CNTR)) 90 / (CONFIG_SYS_TCLK / 1000); 91} 92 93DECLARE_GLOBAL_DATA_PTR; 94 95#define timestamp gd->tbl 96#define lastdec gd->lastinc 97 98ulong get_timer_masked(void) 99{ 100 ulong now = read_timer(); 101 102 if (lastdec >= now) { 103 /* normal mode */ 104 timestamp += lastdec - now; 105 } else { 106 /* we have an overflow ... */ 107 timestamp += lastdec + 108 (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; 109 } 110 lastdec = now; 111 112 return timestamp; 113} 114 115ulong get_timer(ulong base) 116{ 117 return get_timer_masked() - base; 118} 119 120static inline ulong uboot_cntr_val(void) 121{ 122 return readl(CNTMR_VAL_REG(UBOOT_CNTR)); 123} 124 125void __udelay(unsigned long usec) 126{ 127 uint current; 128 ulong delayticks; 129 130 current = uboot_cntr_val(); 131 delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); 132 133 if (current < delayticks) { 134 delayticks -= current; 135 while (uboot_cntr_val() < current) 136 ; 137 while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val()) 138 ; 139 } else { 140 while (uboot_cntr_val() > (current - delayticks)) 141 ; 142 } 143} 144 145/* 146 * init the counter 147 */ 148int timer_init(void) 149{ 150 unsigned int cntmrctrl; 151 152 /* load value into timer */ 153 writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); 154 writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); 155 156 /* enable timer in auto reload mode */ 157 cntmrctrl = readl(CNTMR_CTRL_REG); 158 cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); 159 cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); 160 writel(cntmrctrl, CNTMR_CTRL_REG); 161 return 0; 162} 163 164void timer_init_r(void) 165{ 166 /* init the timestamp and lastdec value */ 167 lastdec = read_timer(); 168 timestamp = 0; 169} 170 171/* 172 * This function is derived from PowerPC code (read timebase as long long). 173 * On ARM it just returns the timer value. 174 */ 175unsigned long long get_ticks(void) 176{ 177 return get_timer(0); 178} 179 180/* 181 * This function is derived from PowerPC code (timebase clock frequency). 182 * On ARM it returns the number of timer ticks per second. 183 */ 184ulong get_tbclk (void) 185{ 186 return (ulong)CONFIG_SYS_HZ; 187} 188