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