~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/arm/cpu/arm926ejs/at91/timer.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2007-2008
 
3
 * Stelian Pop <stelian@popies.net>
 
4
 * Lead Tech Design <www.leadtechdesign.com>
 
5
 *
 
6
 * SPDX-License-Identifier:     GPL-2.0+
 
7
 */
 
8
 
 
9
#include <common.h>
 
10
#include <asm/io.h>
 
11
#include <asm/arch/hardware.h>
 
12
#include <asm/arch/at91_pit.h>
 
13
#include <asm/arch/at91_pmc.h>
 
14
#include <asm/arch/clk.h>
 
15
#include <div64.h>
 
16
 
 
17
#if !defined(CONFIG_AT91FAMILY)
 
18
# error You need to define CONFIG_AT91FAMILY in your board config!
 
19
#endif
 
20
 
 
21
DECLARE_GLOBAL_DATA_PTR;
 
22
 
 
23
/*
 
24
 * We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by
 
25
 * setting the 20 bit counter period to its maximum (0xfffff).
 
26
 * (See the relevant data sheets to understand that this really works)
 
27
 *
 
28
 * We do also mimic the typical powerpc way of incrementing
 
29
 * two 32 bit registers called tbl and tbu.
 
30
 *
 
31
 * Those registers increment at 1/16 the main clock rate.
 
32
 */
 
33
 
 
34
#define TIMER_LOAD_VAL  0xfffff
 
35
 
 
36
static inline unsigned long long tick_to_time(unsigned long long tick)
 
37
{
 
38
        tick *= CONFIG_SYS_HZ;
 
39
        do_div(tick, gd->arch.timer_rate_hz);
 
40
 
 
41
        return tick;
 
42
}
 
43
 
 
44
static inline unsigned long long usec_to_tick(unsigned long long usec)
 
45
{
 
46
        usec *= gd->arch.timer_rate_hz;
 
47
        do_div(usec, 1000000);
 
48
 
 
49
        return usec;
 
50
}
 
51
 
 
52
/*
 
53
 * Use the PITC in full 32 bit incrementing mode
 
54
 */
 
55
int timer_init(void)
 
56
{
 
57
        at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
 
58
        at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
 
59
 
 
60
        /* Enable PITC Clock */
 
61
        writel(1 << ATMEL_ID_SYS, &pmc->pcer);
 
62
 
 
63
        /* Enable PITC */
 
64
        writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
 
65
 
 
66
        gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16;
 
67
        gd->arch.tbu = gd->arch.tbl = 0;
 
68
 
 
69
        return 0;
 
70
}
 
71
 
 
72
/*
 
73
 * Get the current 64 bit timer tick count
 
74
 */
 
75
unsigned long long get_ticks(void)
 
76
{
 
77
        at91_pit_t *pit = (at91_pit_t *) ATMEL_BASE_PIT;
 
78
 
 
79
        ulong now = readl(&pit->piir);
 
80
 
 
81
        /* increment tbu if tbl has rolled over */
 
82
        if (now < gd->arch.tbl)
 
83
                gd->arch.tbu++;
 
84
        gd->arch.tbl = now;
 
85
        return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
 
86
}
 
87
 
 
88
void __udelay(unsigned long usec)
 
89
{
 
90
        unsigned long long start;
 
91
        ulong tmo;
 
92
 
 
93
        start = get_ticks();            /* get current timestamp */
 
94
        tmo = usec_to_tick(usec);       /* convert usecs to ticks */
 
95
        while ((get_ticks() - start) < tmo)
 
96
                ;                       /* loop till time has passed */
 
97
}
 
98
 
 
99
/*
 
100
 * get_timer(base) can be used to check for timeouts or
 
101
 * to measure elasped time relative to an event:
 
102
 *
 
103
 * ulong start_time = get_timer(0) sets start_time to the current
 
104
 * time value.
 
105
 * get_timer(start_time) returns the time elapsed since then.
 
106
 *
 
107
 * The time is used in CONFIG_SYS_HZ units!
 
108
 */
 
109
ulong get_timer(ulong base)
 
110
{
 
111
        return tick_to_time(get_ticks()) - base;
 
112
}
 
113
 
 
114
/*
 
115
 * Return the number of timer ticks per second.
 
116
 */
 
117
ulong get_tbclk(void)
 
118
{
 
119
        return gd->arch.timer_rate_hz;
 
120
}