1e66c49faSVikas Manocha /* 2e66c49faSVikas Manocha * (C) Copyright 2016 3e66c49faSVikas Manocha * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com. 4e66c49faSVikas Manocha * 5e66c49faSVikas Manocha * SPDX-License-Identifier: GPL-2.0+ 6e66c49faSVikas Manocha */ 7e66c49faSVikas Manocha 8e66c49faSVikas Manocha #include <common.h> 9e66c49faSVikas Manocha #include <asm/io.h> 10e66c49faSVikas Manocha #include <asm/arch/stm32.h> 11*081de09dSMichael Kurz #include <asm/arch/stm32_defs.h> 12e66c49faSVikas Manocha #include <asm/arch/gpt.h> 13e66c49faSVikas Manocha 14e66c49faSVikas Manocha #define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING) 15e66c49faSVikas Manocha #define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK/CONFIG_STM32_HZ) 16e66c49faSVikas Manocha 17e66c49faSVikas Manocha DECLARE_GLOBAL_DATA_PTR; 18e66c49faSVikas Manocha 19e66c49faSVikas Manocha #define timestamp gd->arch.tbl 20e66c49faSVikas Manocha #define lastdec gd->arch.lastinc 21e66c49faSVikas Manocha timer_init(void)22e66c49faSVikas Manochaint timer_init(void) 23e66c49faSVikas Manocha { 24e66c49faSVikas Manocha /* Timer2 clock configuration */ 25*081de09dSMichael Kurz clock_setup(TIMER2_CLOCK_CFG); 26e66c49faSVikas Manocha /* Stop the timer */ 27e66c49faSVikas Manocha writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1); 28e66c49faSVikas Manocha 29e66c49faSVikas Manocha writel((CONFIG_SYS_CLK_FREQ/CONFIG_SYS_HZ_CLOCK) - 1, 30e66c49faSVikas Manocha &gpt1_regs_ptr->psc); 31e66c49faSVikas Manocha 32e66c49faSVikas Manocha /* Configure timer for auto-reload */ 33e66c49faSVikas Manocha writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD, 34e66c49faSVikas Manocha &gpt1_regs_ptr->cr1); 35e66c49faSVikas Manocha 36e66c49faSVikas Manocha /* load value for free running */ 37e66c49faSVikas Manocha writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr); 38e66c49faSVikas Manocha 39e66c49faSVikas Manocha /* start timer */ 40e66c49faSVikas Manocha writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN, &gpt1_regs_ptr->cr1); 41e66c49faSVikas Manocha 42e66c49faSVikas Manocha writel(readl(&gpt1_regs_ptr->egr) | TIM_EGR_UG, &gpt1_regs_ptr->egr); 43e66c49faSVikas Manocha 44e66c49faSVikas Manocha /* Reset the timer */ 45e66c49faSVikas Manocha lastdec = READ_TIMER(); 46e66c49faSVikas Manocha timestamp = 0; 47e66c49faSVikas Manocha 48e66c49faSVikas Manocha return 0; 49e66c49faSVikas Manocha } 50e66c49faSVikas Manocha 51e66c49faSVikas Manocha /* 52e66c49faSVikas Manocha * timer without interrupts 53e66c49faSVikas Manocha */ get_timer(ulong base)54e66c49faSVikas Manochaulong get_timer(ulong base) 55e66c49faSVikas Manocha { 56e66c49faSVikas Manocha return (get_timer_masked() / GPT_RESOLUTION) - base; 57e66c49faSVikas Manocha } 58e66c49faSVikas Manocha __udelay(unsigned long usec)59e66c49faSVikas Manochavoid __udelay(unsigned long usec) 60e66c49faSVikas Manocha { 61e66c49faSVikas Manocha ulong tmo; 62e66c49faSVikas Manocha ulong start = get_timer_masked(); 63e66c49faSVikas Manocha ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100); 64e66c49faSVikas Manocha ulong rndoff; 65e66c49faSVikas Manocha 66e66c49faSVikas Manocha rndoff = (usec % 10) ? 1 : 0; 67e66c49faSVikas Manocha 68e66c49faSVikas Manocha /* tenudelcnt timer tick gives 10 microsecconds delay */ 69e66c49faSVikas Manocha tmo = ((usec / 10) + rndoff) * tenudelcnt; 70e66c49faSVikas Manocha 71e66c49faSVikas Manocha while ((ulong) (get_timer_masked() - start) < tmo) 72e66c49faSVikas Manocha ; 73e66c49faSVikas Manocha } 74e66c49faSVikas Manocha get_timer_masked(void)75e66c49faSVikas Manochaulong get_timer_masked(void) 76e66c49faSVikas Manocha { 77e66c49faSVikas Manocha ulong now = READ_TIMER(); 78e66c49faSVikas Manocha 79e66c49faSVikas Manocha if (now >= lastdec) { 80e66c49faSVikas Manocha /* normal mode */ 81e66c49faSVikas Manocha timestamp += now - lastdec; 82e66c49faSVikas Manocha } else { 83e66c49faSVikas Manocha /* we have an overflow ... */ 84e66c49faSVikas Manocha timestamp += now + GPT_FREE_RUNNING - lastdec; 85e66c49faSVikas Manocha } 86e66c49faSVikas Manocha lastdec = now; 87e66c49faSVikas Manocha 88e66c49faSVikas Manocha return timestamp; 89e66c49faSVikas Manocha } 90e66c49faSVikas Manocha udelay_masked(unsigned long usec)91e66c49faSVikas Manochavoid udelay_masked(unsigned long usec) 92e66c49faSVikas Manocha { 93e66c49faSVikas Manocha return udelay(usec); 94e66c49faSVikas Manocha } 95e66c49faSVikas Manocha 96e66c49faSVikas Manocha /* 97e66c49faSVikas Manocha * This function is derived from PowerPC code (read timebase as long long). 98e66c49faSVikas Manocha * On ARM it just returns the timer value. 99e66c49faSVikas Manocha */ get_ticks(void)100e66c49faSVikas Manochaunsigned long long get_ticks(void) 101e66c49faSVikas Manocha { 102e66c49faSVikas Manocha return get_timer(0); 103e66c49faSVikas Manocha } 104e66c49faSVikas Manocha 105e66c49faSVikas Manocha /* 106e66c49faSVikas Manocha * This function is derived from PowerPC code (timebase clock frequency). 107e66c49faSVikas Manocha * On ARM it returns the number of timer ticks per second. 108e66c49faSVikas Manocha */ get_tbclk(void)109e66c49faSVikas Manochaulong get_tbclk(void) 110e66c49faSVikas Manocha { 111e66c49faSVikas Manocha return CONFIG_STM32_HZ; 112e66c49faSVikas Manocha } 113