1 /* 2 * (C) Copyright 2015 3 * Kamil Lulko, <kamil.lulko@gmail.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <asm/io.h> 10 #include <asm/armv7m.h> 11 #include <asm/arch/stm32.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 #define STM32_TIM2_BASE (STM32_APB1PERIPH_BASE + 0x0000) 16 17 #define RCC_APB1ENR_TIM2EN (1 << 0) 18 19 struct stm32_tim2_5 { 20 u32 cr1; 21 u32 cr2; 22 u32 smcr; 23 u32 dier; 24 u32 sr; 25 u32 egr; 26 u32 ccmr1; 27 u32 ccmr2; 28 u32 ccer; 29 u32 cnt; 30 u32 psc; 31 u32 arr; 32 u32 reserved1; 33 u32 ccr1; 34 u32 ccr2; 35 u32 ccr3; 36 u32 ccr4; 37 u32 reserved2; 38 u32 dcr; 39 u32 dmar; 40 u32 or; 41 }; 42 43 #define TIM_CR1_CEN (1 << 0) 44 45 #define TIM_EGR_UG (1 << 0) 46 timer_init(void)47int timer_init(void) 48 { 49 struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; 50 51 setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); 52 53 if (clock_get(CLOCK_AHB) == clock_get(CLOCK_APB1)) 54 writel((clock_get(CLOCK_APB1) / CONFIG_SYS_HZ_CLOCK) - 1, 55 &tim->psc); 56 else 57 writel(((clock_get(CLOCK_APB1) * 2) / CONFIG_SYS_HZ_CLOCK) - 1, 58 &tim->psc); 59 60 writel(0xFFFFFFFF, &tim->arr); 61 writel(TIM_CR1_CEN, &tim->cr1); 62 setbits_le32(&tim->egr, TIM_EGR_UG); 63 64 gd->arch.tbl = 0; 65 gd->arch.tbu = 0; 66 gd->arch.lastinc = 0; 67 68 return 0; 69 } 70 get_timer(ulong base)71ulong get_timer(ulong base) 72 { 73 return (get_ticks() / (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)) - base; 74 } 75 get_ticks(void)76unsigned long long get_ticks(void) 77 { 78 struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; 79 u32 now; 80 81 now = readl(&tim->cnt); 82 83 if (now >= gd->arch.lastinc) 84 gd->arch.tbl += (now - gd->arch.lastinc); 85 else 86 gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now; 87 88 gd->arch.lastinc = now; 89 90 return gd->arch.tbl; 91 } 92 reset_timer(void)93void reset_timer(void) 94 { 95 struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; 96 97 gd->arch.lastinc = readl(&tim->cnt); 98 gd->arch.tbl = 0; 99 } 100 101 /* delay x useconds */ __udelay(ulong usec)102void __udelay(ulong usec) 103 { 104 unsigned long long start; 105 106 start = get_ticks(); /* get current timestamp */ 107 while ((get_ticks() - start) < usec) 108 ; /* loop till time has passed */ 109 } 110 111 /* 112 * This function is derived from PowerPC code (timebase clock frequency). 113 * On ARM it returns the number of timer ticks per second. 114 */ get_tbclk(void)115ulong get_tbclk(void) 116 { 117 return CONFIG_SYS_HZ_CLOCK; 118 } 119