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