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