mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
AT91 clock/timer: move static data to global_data struct
clock.c / timer.c used static data and are called before relocation. Move all static variables into global_data structure. Also cleanup timer.c from unused stubs and make it truly use 64 bit tick values. Signed-off-by: Reinhard Meyer <u-boot@emk-elektronik.de>
This commit is contained in:
parent
3b83522bcf
commit
5dca710a3d
3 changed files with 83 additions and 71 deletions
|
@ -11,47 +11,46 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/io.h>
|
||||
#include <asm/arch/at91_pmc.h>
|
||||
#include <asm/arch/clk.h>
|
||||
|
||||
static unsigned long cpu_clk_rate_hz;
|
||||
static unsigned long main_clk_rate_hz;
|
||||
static unsigned long mck_rate_hz;
|
||||
static unsigned long plla_rate_hz;
|
||||
static unsigned long pllb_rate_hz;
|
||||
static u32 at91_pllb_usb_init;
|
||||
#if !defined(CONFIG_AT91FAMILY)
|
||||
# error You need to define CONFIG_AT91FAMILY in your board config!
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
unsigned long get_cpu_clk_rate(void)
|
||||
{
|
||||
return cpu_clk_rate_hz;
|
||||
return gd->cpu_clk_rate_hz;
|
||||
}
|
||||
|
||||
unsigned long get_main_clk_rate(void)
|
||||
{
|
||||
return main_clk_rate_hz;
|
||||
return gd->main_clk_rate_hz;
|
||||
}
|
||||
|
||||
unsigned long get_mck_clk_rate(void)
|
||||
{
|
||||
return mck_rate_hz;
|
||||
return gd->mck_rate_hz;
|
||||
}
|
||||
|
||||
unsigned long get_plla_clk_rate(void)
|
||||
{
|
||||
return plla_rate_hz;
|
||||
return gd->plla_rate_hz;
|
||||
}
|
||||
|
||||
unsigned long get_pllb_clk_rate(void)
|
||||
{
|
||||
return pllb_rate_hz;
|
||||
return gd->pllb_rate_hz;
|
||||
}
|
||||
|
||||
u32 get_pllb_init(void)
|
||||
{
|
||||
return at91_pllb_usb_init;
|
||||
return gd->at91_pllb_usb_init;
|
||||
}
|
||||
|
||||
static unsigned long at91_css_to_rate(unsigned long css)
|
||||
|
@ -60,11 +59,11 @@ static unsigned long at91_css_to_rate(unsigned long css)
|
|||
case AT91_PMC_MCKR_CSS_SLOW:
|
||||
return AT91_SLOW_CLOCK;
|
||||
case AT91_PMC_MCKR_CSS_MAIN:
|
||||
return main_clk_rate_hz;
|
||||
return gd->main_clk_rate_hz;
|
||||
case AT91_PMC_MCKR_CSS_PLLA:
|
||||
return plla_rate_hz;
|
||||
return gd->plla_rate_hz;
|
||||
case AT91_PMC_MCKR_CSS_PLLB:
|
||||
return pllb_rate_hz;
|
||||
return gd->pllb_rate_hz;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -163,10 +162,10 @@ int at91_clock_init(unsigned long main_clock)
|
|||
main_clock = tmp * (AT91_SLOW_CLOCK / 16);
|
||||
}
|
||||
#endif
|
||||
main_clk_rate_hz = main_clock;
|
||||
gd->main_clk_rate_hz = main_clock;
|
||||
|
||||
/* report if PLLA is more than mildly overclocked */
|
||||
plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
|
||||
gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
|
||||
|
||||
#ifdef CONFIG_USB_ATMEL
|
||||
/*
|
||||
|
@ -175,9 +174,9 @@ int at91_clock_init(unsigned long main_clock)
|
|||
*
|
||||
* REVISIT: assumes MCK doesn't derive from PLLB!
|
||||
*/
|
||||
at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
|
||||
gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
|
||||
AT91_PMC_PLLBR_USBDIV_2;
|
||||
pllb_rate_hz = at91_pll_rate(main_clock, at91_pllb_usb_init);
|
||||
gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -187,30 +186,30 @@ int at91_clock_init(unsigned long main_clock)
|
|||
mckr = readl(&pmc->mckr);
|
||||
#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
|
||||
/* plla divisor by 2 */
|
||||
plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
|
||||
gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
|
||||
#endif
|
||||
mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
|
||||
freq = mck_rate_hz;
|
||||
gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
|
||||
freq = gd->mck_rate_hz;
|
||||
|
||||
freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
|
||||
#if defined(CONFIG_AT91RM9200)
|
||||
/* mdiv */
|
||||
mck_rate_hz = freq / (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
gd->mck_rate_hz = freq / (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
#elif defined(CONFIG_AT91SAM9G20)
|
||||
/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
|
||||
mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
|
||||
gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
|
||||
freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq;
|
||||
if (mckr & AT91_PMC_MCKR_MDIV_MASK)
|
||||
freq /= 2; /* processor clock division */
|
||||
#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
|
||||
mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
|
||||
gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
|
||||
(AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
|
||||
? freq / 3
|
||||
: freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
#else
|
||||
mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
gd->mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
|
||||
#endif
|
||||
cpu_clk_rate_hz = freq;
|
||||
gd->cpu_clk_rate_hz = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,55 +30,63 @@
|
|||
#include <asm/arch/io.h>
|
||||
#include <div64.h>
|
||||
|
||||
#if !defined(CONFIG_AT91FAMILY)
|
||||
# error You need to define CONFIG_AT91FAMILY in your board config!
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by
|
||||
* setting the 20 bit counter period to its maximum (0xfffff).
|
||||
* (See the relevant data sheets to understand that this really works)
|
||||
*
|
||||
* We do also mimic the typical powerpc way of incrementing
|
||||
* two 32 bit registers called tbl and tbu.
|
||||
*
|
||||
* Those registers increment at 1/16 the main clock rate.
|
||||
*/
|
||||
#define TIMER_LOAD_VAL 0xfffff
|
||||
|
||||
static ulong timestamp;
|
||||
static ulong lastinc;
|
||||
static ulong timer_freq;
|
||||
#define TIMER_LOAD_VAL 0xfffff
|
||||
|
||||
static inline unsigned long long tick_to_time(unsigned long long tick)
|
||||
{
|
||||
tick *= CONFIG_SYS_HZ;
|
||||
do_div(tick, timer_freq);
|
||||
do_div(tick, gd->timer_rate_hz);
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
static inline unsigned long long usec_to_tick(unsigned long long usec)
|
||||
{
|
||||
usec *= timer_freq;
|
||||
usec *= gd->timer_rate_hz;
|
||||
do_div(usec, 1000000);
|
||||
|
||||
return usec;
|
||||
}
|
||||
|
||||
/* nothing really to do with interrupts, just starts up a counter. */
|
||||
/*
|
||||
* Use the PITC in full 32 bit incrementing mode
|
||||
*/
|
||||
int timer_init(void)
|
||||
{
|
||||
at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE;
|
||||
at91_pit_t *pit = (at91_pit_t *) AT91_PIT_BASE;
|
||||
/*
|
||||
* Enable PITC Clock
|
||||
* The clock is already enabled for system controller in boot
|
||||
*/
|
||||
|
||||
/* Enable PITC Clock */
|
||||
writel(1 << AT91_ID_SYS, &pmc->pcer);
|
||||
|
||||
/* Enable PITC */
|
||||
writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
|
||||
|
||||
reset_timer_masked();
|
||||
|
||||
timer_freq = get_mck_clk_rate() >> 4;
|
||||
gd->timer_rate_hz = gd->mck_rate_hz / 16;
|
||||
gd->tbu = gd->tbl = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer without interrupts
|
||||
* Get the current 64 bit timer tick count
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
|
@ -86,28 +94,11 @@ unsigned long long get_ticks(void)
|
|||
|
||||
ulong now = readl(&pit->piir);
|
||||
|
||||
if (now >= lastinc) /* normal mode (non roll) */
|
||||
/* move stamp forward with absolut diff ticks */
|
||||
timestamp += (now - lastinc);
|
||||
else /* we have rollover of incrementer */
|
||||
timestamp += (0xFFFFFFFF - lastinc) + now;
|
||||
lastinc = now;
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void reset_timer_masked(void)
|
||||
{
|
||||
/* reset time */
|
||||
at91_pit_t *pit = (at91_pit_t *) AT91_PIT_BASE;
|
||||
|
||||
/* capture current incrementer value time */
|
||||
lastinc = readl(&pit->piir);
|
||||
timestamp = 0; /* start "advancing" time stamp from 0 */
|
||||
}
|
||||
|
||||
ulong get_timer_masked(void)
|
||||
{
|
||||
return tick_to_time(get_ticks());
|
||||
/* increment tbu if tbl has rolled over */
|
||||
if (now < gd->tbl)
|
||||
gd->tbu++;
|
||||
gd->tbl = now;
|
||||
return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
|
@ -119,24 +110,32 @@ void __udelay(unsigned long usec)
|
|||
tmp = get_ticks() + tmo; /* get current timestamp */
|
||||
|
||||
while (get_ticks() < tmp) /* loop till event */
|
||||
/*NOP*/;
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* reset_timer() and get_timer(base) are a pair of functions that are used by
|
||||
* some timeout/sleep mechanisms in u-boot.
|
||||
*
|
||||
* reset_timer() marks the current time as epoch and
|
||||
* get_timer(base) works relative to that epoch.
|
||||
*
|
||||
* The time is used in CONFIG_SYS_HZ units!
|
||||
*/
|
||||
void reset_timer(void)
|
||||
{
|
||||
reset_timer_masked();
|
||||
gd->timer_reset_value = get_ticks();
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return get_timer_masked () - base;
|
||||
return tick_to_time(get_ticks() - gd->timer_reset_value) - base;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (timebase clock frequency).
|
||||
* On ARM it returns the number of timer ticks per second.
|
||||
* Return the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return timer_freq;
|
||||
return gd->timer_rate_hz;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,20 @@ typedef struct global_data {
|
|||
#ifdef CONFIG_FSL_ESDHC
|
||||
unsigned long sdhc_clk;
|
||||
#endif
|
||||
#ifdef CONFIG_AT91FAMILY
|
||||
/* "static data" needed by at91's clock.c */
|
||||
unsigned long cpu_clk_rate_hz;
|
||||
unsigned long main_clk_rate_hz;
|
||||
unsigned long mck_rate_hz;
|
||||
unsigned long plla_rate_hz;
|
||||
unsigned long pllb_rate_hz;
|
||||
unsigned long at91_pllb_usb_init;
|
||||
/* "static data" needed by at91's timer.c */
|
||||
unsigned long timer_rate_hz;
|
||||
unsigned long tbl;
|
||||
unsigned long tbu;
|
||||
unsigned long long timer_reset_value;
|
||||
#endif
|
||||
#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
|
||||
unsigned long relocaddr; /* Start address of U-Boot in RAM */
|
||||
phys_size_t ram_size; /* RAM size */
|
||||
|
|
Loading…
Reference in a new issue