u-boot/arch/nds32/cpu/n1213/ag101/timer.c
Tom Rini 2f8a6db5d8 Finish conversion of CONFIG_SYS_CLK_FREQ to Kconfig
In order to finish moving this symbol to Kconfig for all platforms, we
need to do a few more things.  First, for all platforms that define this
to a function, introduce CONFIG_DYNAMIC_SYS_CLK_FREQ, similar to
CONFIG_DYNAMIC_DDR_CLK_FREQ and populate clock_legacy.h.  This entails
also switching all users from CONFIG_SYS_CLK_FREQ to get_board_sys_clk()
and updating a few preprocessor tests.

With that done, all platforms that define a value here can be converted
to Kconfig, and a fall-back of zero is sufficiently safe to use (and
what is used today in cases where code may or may not have this
available).  Make sure that code which calls this function includes
<clock_legacy.h> to get the prototype.

Signed-off-by: Tom Rini <trini@konsulko.com>
2021-12-27 16:20:18 -05:00

197 lines
4.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2009 Faraday Technology
* Po-Yu Chuang <ratbert@faraday-tech.com>
*
* Copyright (C) 2011 Andes Technology Corporation
* Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
* Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
*/
#ifndef CONFIG_TIMER
#include <common.h>
#include <clock_legacy.h>
#include <init.h>
#include <irq_func.h>
#include <log.h>
#include <time.h>
#include <asm/io.h>
#include <faraday/fttmr010.h>
#include <linux/delay.h>
static ulong timestamp;
static ulong lastdec;
int timer_init(void)
{
struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
unsigned int cr;
debug("%s()\n", __func__);
/* disable timers */
writel(0, &tmr->cr);
#ifdef CONFIG_FTTMR010_EXT_CLK
/* use 32768Hz oscillator for RTC, WDT, TIMER */
ftpmu010_32768osc_enable();
#endif
/* setup timer */
writel(TIMER_LOAD_VAL, &tmr->timer3_load);
writel(TIMER_LOAD_VAL, &tmr->timer3_counter);
writel(0, &tmr->timer3_match1);
writel(0, &tmr->timer3_match2);
/* we don't want timer to issue interrupts */
writel(FTTMR010_TM3_MATCH1 |
FTTMR010_TM3_MATCH2 |
FTTMR010_TM3_OVERFLOW,
&tmr->interrupt_mask);
cr = readl(&tmr->cr);
#ifdef CONFIG_FTTMR010_EXT_CLK
cr |= FTTMR010_TM3_CLOCK; /* use external clock */
#endif
cr |= FTTMR010_TM3_ENABLE;
writel(cr, &tmr->cr);
/* init the timestamp and lastdec value */
reset_timer_masked();
return 0;
}
/*
* timer without interrupts
*/
/*
* reset time
*/
void reset_timer_masked(void)
{
struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
/* capure current decrementer value time */
#ifdef CONFIG_FTTMR010_EXT_CLK
lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
#else
lastdec = readl(&tmr->timer3_counter) /
(get_board_sys_clk() / 2 / CONFIG_SYS_HZ);
#endif
timestamp = 0; /* start "advancing" time stamp from 0 */
debug("%s(): lastdec = %lx\n", __func__, lastdec);
}
void reset_timer(void)
{
debug("%s()\n", __func__);
reset_timer_masked();
}
/*
* return timer ticks
*/
ulong get_timer_masked(void)
{
struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
/* current tick value */
#ifdef CONFIG_FTTMR010_EXT_CLK
ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
#else
ulong now = readl(&tmr->timer3_counter) /
(get_board_sys_clk() / 2 / CONFIG_SYS_HZ);
#endif
debug("%s(): now = %lx, lastdec = %lx\n", __func__, now, lastdec);
if (lastdec >= now) {
/*
* normal mode (non roll)
* move stamp fordward with absoulte diff ticks
*/
timestamp += lastdec - now;
} else {
/*
* we have overflow of the count down timer
*
* nts = ts + ld + (TLV - now)
* ts=old stamp, ld=time that passed before passing through -1
* (TLV-now) amount of time after passing though -1
* nts = new "advancing time stamp"...it could also roll and
* cause problems.
*/
timestamp += lastdec + TIMER_LOAD_VAL - now;
}
lastdec = now;
debug("%s() returns %lx\n", __func__, timestamp);
return timestamp;
}
/*
* return difference between timer ticks and base
*/
ulong get_timer(ulong base)
{
debug("%s(%lx)\n", __func__, base);
return get_timer_masked() - base;
}
void set_timer(ulong t)
{
debug("%s(%lx)\n", __func__, t);
timestamp = t;
}
/* delay x useconds AND preserve advance timestamp value */
void __udelay(unsigned long usec)
{
struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
#ifdef CONFIG_FTTMR010_EXT_CLK
long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
#else
long tmo = usec * ((get_board_sys_clk() / 2) / 1000) / 1000;
#endif
unsigned long now, last = readl(&tmr->timer3_counter);
debug("%s(%lu)\n", __func__, usec);
while (tmo > 0) {
now = readl(&tmr->timer3_counter);
if (now > last) /* count down timer overflow */
tmo -= TIMER_LOAD_VAL + last - now;
else
tmo -= last - now;
last = now;
}
}
/*
* This function is derived from PowerPC code (read timebase as long long).
* On ARM it just returns the timer value.
*/
unsigned long long get_ticks(void)
{
debug("%s()\n", __func__);
return get_timer(0);
}
/*
* This function is derived from PowerPC code (timebase clock frequency).
* On ARM it returns the number of timer ticks per second.
*/
ulong get_tbclk(void)
{
debug("%s()\n", __func__);
#ifdef CONFIG_FTTMR010_EXT_CLK
return CONFIG_SYS_HZ;
#else
return get_board_sys_clk();
#endif
}
#endif /* CONFIG_TIMER */