1852bd07cSMinkyu Kang /* 2852bd07cSMinkyu Kang * Copyright (C) 2009 Samsung Electronics 3852bd07cSMinkyu Kang * Heungjun Kim <riverful.kim@samsung.com> 4852bd07cSMinkyu Kang * Inki Dae <inki.dae@samsung.com> 5852bd07cSMinkyu Kang * Minkyu Kang <mk7.kang@samsung.com> 6852bd07cSMinkyu Kang * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8852bd07cSMinkyu Kang */ 9852bd07cSMinkyu Kang 10852bd07cSMinkyu Kang #include <common.h> 11dc47e2bcSSimon Glass #include <div64.h> 12852bd07cSMinkyu Kang #include <asm/io.h> 13852bd07cSMinkyu Kang #include <asm/arch/pwm.h> 14852bd07cSMinkyu Kang #include <asm/arch/clk.h> 15*5c2dd4cdSSimon Glass 16*5c2dd4cdSSimon Glass /* Use the old PWM interface for now */ 17*5c2dd4cdSSimon Glass #undef CONFIG_DM_PWM 1870fc52dfSMinkyu Kang #include <pwm.h> 19852bd07cSMinkyu Kang 209aca34d6SMinkyu Kang DECLARE_GLOBAL_DATA_PTR; 21852bd07cSMinkyu Kang 223936b4f0SZhong Hongbo unsigned long get_current_tick(void); 233936b4f0SZhong Hongbo 24852bd07cSMinkyu Kang /* macro to read the 16 bit timer */ s5p_get_base_timer(void)2537168dabSMinkyu Kangstatic inline struct s5p_timer *s5p_get_base_timer(void) 26852bd07cSMinkyu Kang { 2737168dabSMinkyu Kang return (struct s5p_timer *)samsung_get_base_timer(); 28852bd07cSMinkyu Kang } 29852bd07cSMinkyu Kang 303d00c0cbSSimon Glass /** 313d00c0cbSSimon Glass * Read the countdown timer. 323d00c0cbSSimon Glass * 333d00c0cbSSimon Glass * This operates at 1MHz and counts downwards. It will wrap about every 343d00c0cbSSimon Glass * hour (2^32 microseconds). 353d00c0cbSSimon Glass * 363d00c0cbSSimon Glass * @return current value of timer 373d00c0cbSSimon Glass */ timer_get_us_down(void)383d00c0cbSSimon Glassstatic unsigned long timer_get_us_down(void) 393d00c0cbSSimon Glass { 403d00c0cbSSimon Glass struct s5p_timer *const timer = s5p_get_base_timer(); 413d00c0cbSSimon Glass 423d00c0cbSSimon Glass return readl(&timer->tcnto4); 433d00c0cbSSimon Glass } 443d00c0cbSSimon Glass timer_init(void)45852bd07cSMinkyu Kangint timer_init(void) 46852bd07cSMinkyu Kang { 4770fc52dfSMinkyu Kang /* PWM Timer 4 */ 483d00c0cbSSimon Glass pwm_init(4, MUX_DIV_4, 0); 4934b5ee1fSGabe Black pwm_config(4, 100000, 100000); 5070fc52dfSMinkyu Kang pwm_enable(4); 51852bd07cSMinkyu Kang 523d00c0cbSSimon Glass /* Use this as the current monotonic time in us */ 533d00c0cbSSimon Glass gd->arch.timer_reset_value = 0; 543d00c0cbSSimon Glass 553d00c0cbSSimon Glass /* Use this as the last timer value we saw */ 563d00c0cbSSimon Glass gd->arch.lastinc = timer_get_us_down(); 573936b4f0SZhong Hongbo reset_timer_masked(); 583936b4f0SZhong Hongbo 59852bd07cSMinkyu Kang return 0; 60852bd07cSMinkyu Kang } 61852bd07cSMinkyu Kang 62852bd07cSMinkyu Kang /* 63852bd07cSMinkyu Kang * timer without interrupts 64852bd07cSMinkyu Kang */ get_timer(unsigned long base)65852bd07cSMinkyu Kangunsigned long get_timer(unsigned long base) 66852bd07cSMinkyu Kang { 67dc47e2bcSSimon Glass unsigned long long time_ms; 68dc47e2bcSSimon Glass 693d00c0cbSSimon Glass ulong now = timer_get_us_down(); 703d00c0cbSSimon Glass 713d00c0cbSSimon Glass /* 723d00c0cbSSimon Glass * Increment the time by the amount elapsed since the last read. 733d00c0cbSSimon Glass * The timer may have wrapped around, but it makes no difference to 743d00c0cbSSimon Glass * our arithmetic here. 753d00c0cbSSimon Glass */ 763d00c0cbSSimon Glass gd->arch.timer_reset_value += gd->arch.lastinc - now; 773d00c0cbSSimon Glass gd->arch.lastinc = now; 783d00c0cbSSimon Glass 793d00c0cbSSimon Glass /* Divide by 1000 to convert from us to ms */ 80dc47e2bcSSimon Glass time_ms = gd->arch.timer_reset_value; 81dc47e2bcSSimon Glass do_div(time_ms, 1000); 82dc47e2bcSSimon Glass return time_ms - base; 83852bd07cSMinkyu Kang } 84852bd07cSMinkyu Kang timer_get_us(void)85ca35a0cdSSimon Glassunsigned long __attribute__((no_instrument_function)) timer_get_us(void) 86f24869d3SChe-Liang Chiou { 87f24869d3SChe-Liang Chiou static unsigned long base_time_us; 88f24869d3SChe-Liang Chiou 89f24869d3SChe-Liang Chiou struct s5p_timer *const timer = 90f24869d3SChe-Liang Chiou (struct s5p_timer *)samsung_get_base_timer(); 91f24869d3SChe-Liang Chiou unsigned long now_downward_us = readl(&timer->tcnto4); 92f24869d3SChe-Liang Chiou 93f24869d3SChe-Liang Chiou if (!base_time_us) 94f24869d3SChe-Liang Chiou base_time_us = now_downward_us; 95f24869d3SChe-Liang Chiou 96f24869d3SChe-Liang Chiou /* Note that this timer counts downward. */ 97f24869d3SChe-Liang Chiou return base_time_us - now_downward_us; 98f24869d3SChe-Liang Chiou } 99f24869d3SChe-Liang Chiou 100852bd07cSMinkyu Kang /* delay x useconds */ __udelay(unsigned long usec)101852bd07cSMinkyu Kangvoid __udelay(unsigned long usec) 102852bd07cSMinkyu Kang { 1033d00c0cbSSimon Glass unsigned long count_value; 104852bd07cSMinkyu Kang 1053d00c0cbSSimon Glass count_value = timer_get_us_down(); 1063d00c0cbSSimon Glass while ((int)(count_value - timer_get_us_down()) < (int)usec) 1073d00c0cbSSimon Glass ; 108852bd07cSMinkyu Kang } 109852bd07cSMinkyu Kang reset_timer_masked(void)110852bd07cSMinkyu Kangvoid reset_timer_masked(void) 111852bd07cSMinkyu Kang { 11237168dabSMinkyu Kang struct s5p_timer *const timer = s5p_get_base_timer(); 113852bd07cSMinkyu Kang 114852bd07cSMinkyu Kang /* reset time */ 115582601daSSimon Glass gd->arch.lastinc = readl(&timer->tcnto4); 11666ee6923SSimon Glass gd->arch.tbl = 0; 117852bd07cSMinkyu Kang } 118852bd07cSMinkyu Kang 119852bd07cSMinkyu Kang /* 120852bd07cSMinkyu Kang * This function is derived from PowerPC code (read timebase as long long). 121852bd07cSMinkyu Kang * On ARM it just returns the timer value. 122852bd07cSMinkyu Kang */ get_ticks(void)123852bd07cSMinkyu Kangunsigned long long get_ticks(void) 124852bd07cSMinkyu Kang { 125852bd07cSMinkyu Kang return get_timer(0); 126852bd07cSMinkyu Kang } 127852bd07cSMinkyu Kang 128852bd07cSMinkyu Kang /* 129852bd07cSMinkyu Kang * This function is derived from PowerPC code (timebase clock frequency). 130852bd07cSMinkyu Kang * On ARM it returns the number of timer ticks per second. 131852bd07cSMinkyu Kang */ get_tbclk(void)132852bd07cSMinkyu Kangunsigned long get_tbclk(void) 133852bd07cSMinkyu Kang { 134852bd07cSMinkyu Kang return CONFIG_SYS_HZ; 135852bd07cSMinkyu Kang } 136