~ubuntu-branches/ubuntu/saucy/u-boot/saucy

« back to all changes in this revision

Viewing changes to arch/arm/cpu/arm1136/mx35/timer.c

  • Committer: Package Import Robot
  • Author(s): Clint Adams
  • Date: 2012-05-01 18:07:19 UTC
  • mfrom: (16.1.23 sid)
  • Revision ID: package-import@ubuntu.com-20120501180719-rjntk3287im4a0ns
Tags: 2012.04.01-1
* New upstream version.
  - Update mipsel-native-endianness.diff.
  - Update no-error-on-set-but-unused-variables.diff (partially merged).
  - Drop kirkwood_spi-irq_mask.diff (merged).
  - Drop kirkwood-disable-l2c.diff (merged).

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
#include <common.h>
27
27
#include <asm/io.h>
 
28
#include <div64.h>
28
29
#include <asm/arch/imx-regs.h>
 
30
#include <asm/arch/clock.h>
 
31
 
 
32
DECLARE_GLOBAL_DATA_PTR;
 
33
 
 
34
#define timestamp       (gd->tbl)
 
35
#define lastinc         (gd->lastinc)
29
36
 
30
37
/* General purpose timers bitfields */
31
38
#define GPTCR_SWR       (1<<15) /* Software reset */
33
40
#define GPTCR_CLKSOURCE_32   (0x100<<6) /* Clock source */
34
41
#define GPTCR_CLKSOURCE_IPG (0x001<<6)  /* Clock source */
35
42
#define GPTCR_TEN       (1)     /* Timer enable */
36
 
#define GPTPR_VAL       (66)
 
43
 
 
44
#define TIMER_FREQ_HZ   mxc_get_clock(MXC_IPG_CLK)
 
45
 
 
46
static inline unsigned long long tick_to_time(unsigned long long tick)
 
47
{
 
48
        tick *= CONFIG_SYS_HZ;
 
49
        do_div(tick, TIMER_FREQ_HZ);
 
50
 
 
51
        return tick;
 
52
}
 
53
 
 
54
static inline unsigned long long us_to_tick(unsigned long long usec)
 
55
{
 
56
        usec *= TIMER_FREQ_HZ;
 
57
        do_div(usec, 1000000);
 
58
 
 
59
        return usec;
 
60
}
37
61
 
38
62
int timer_init(void)
39
63
{
45
69
        for (i = 0; i < 100; i++)
46
70
                writel(0, &gpt->ctrl);  /* We have no udelay by now */
47
71
 
48
 
        writel(GPTPR_VAL, &gpt->pre);
 
72
        writel(0, &gpt->pre);
49
73
        /* Freerun Mode, PERCLK1 input */
50
74
        writel(readl(&gpt->ctrl) |
51
75
                GPTCR_CLKSOURCE_IPG | GPTCR_TEN,
54
78
        return 0;
55
79
}
56
80
 
57
 
void reset_timer_masked(void)
 
81
unsigned long long get_ticks(void)
58
82
{
59
83
        struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
 
84
        ulong now = readl(&gpt->counter); /* current tick value */
60
85
 
61
 
        writel(0, &gpt->ctrl);
62
 
        /* Freerun Mode, PERCLK1 input */
63
 
        writel(GPTCR_CLKSOURCE_IPG | GPTCR_TEN,
64
 
                &gpt->ctrl);
 
86
        if (now >= lastinc) {
 
87
                /*
 
88
                 * normal mode (non roll)
 
89
                 * move stamp forward with absolut diff ticks
 
90
                 */
 
91
                timestamp += (now - lastinc);
 
92
        } else {
 
93
                /* we have rollover of incrementer */
 
94
                timestamp += (0xFFFFFFFF - lastinc) + now;
 
95
        }
 
96
        lastinc = now;
 
97
        return timestamp;
65
98
}
66
99
 
67
 
inline ulong get_timer_masked(void)
 
100
ulong get_timer_masked(void)
68
101
{
69
 
 
70
 
        struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
71
 
        ulong val = readl(&gpt->counter);
72
 
 
73
 
        return val;
 
102
        /*
 
103
         * get_ticks() returns a long long (64 bit), it wraps in
 
104
         * 2^64 / CONFIG_MX25_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
 
105
         * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
 
106
         * 5 * 10^6 days - long enough.
 
107
         */
 
108
        return tick_to_time(get_ticks());
74
109
}
75
110
 
76
111
ulong get_timer(ulong base)
77
112
{
78
 
        ulong tmp;
79
 
 
80
 
        tmp = get_timer_masked();
81
 
 
82
 
        if (tmp <= (base * 1000)) {
83
 
                /* Overflow */
84
 
                tmp += (0xffffffff -  base);
85
 
        }
86
 
 
87
 
        return (tmp / 1000) - base;
 
113
        return get_timer_masked() - base;
88
114
}
89
115
 
90
 
/*
91
 
 * delay x useconds AND preserve advance timstamp value
92
 
 * GPTCNT is now supposed to tick 1 by 1 us.
93
 
 */
 
116
/* delay x useconds AND preserve advance timstamp value */
94
117
void __udelay(unsigned long usec)
95
118
{
96
 
        ulong tmp;
97
 
 
98
 
        tmp = get_timer_masked();       /* get current timestamp */
99
 
 
100
 
        /* if setting this forward will roll time stamp */
101
 
        if ((usec + tmp + 1) < tmp) {
102
 
                /* reset "advancing" timestamp to 0, set lastinc value */
103
 
                reset_timer_masked();
104
 
        } else {
105
 
                /* else, set advancing stamp wake up time */
106
 
                tmp += usec;
107
 
        }
108
 
 
109
 
        while (get_timer_masked() < tmp)        /* loop till event */
 
119
        unsigned long long tmp;
 
120
        ulong tmo;
 
121
 
 
122
        tmo = us_to_tick(usec);
 
123
        tmp = get_ticks() + tmo;        /* get current timestamp */
 
124
 
 
125
        while (get_ticks() < tmp)       /* loop till event */
110
126
                 /*NOP*/;
111
127
}
 
128
 
 
129
/*
 
130
 * This function is derived from PowerPC code (timebase clock frequency).
 
131
 * On ARM it returns the number of timer ticks per second.
 
132
 */
 
133
ulong get_tbclk(void)
 
134
{
 
135
        return TIMER_FREQ_HZ;
 
136
}