1/* 2 * (C) Copyright 2015 3 * Kamil Lulko, <kamil.lulko@gmail.com> 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 16DECLARE_GLOBAL_DATA_PTR; 17 18#define STM32_TIM2_BASE (STM32_APB1PERIPH_BASE + 0x0000) 19 20#define RCC_APB1ENR_TIM2EN (1 << 0) 21 22struct 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 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 74ulong get_timer(ulong base) 75{ 76 return (get_ticks() / (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)) - base; 77} 78 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 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 */ 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 */ 118ulong get_tbclk(void) 119{ 120 return CONFIG_SYS_HZ_CLOCK; 121} 122