Commit 1ed7a7f0f571b13d46530f8f8b9aff3957f15a96
Committed by
Jean-Christophe PLAGNIOL-VILLARD
1 parent
f41b144c11
Exists in
master
and in
54 other branches
i.MX31: switch to CFG_HZ=1000
Switch to the standard CFG_HZ=1000 value, while at it, minor white-space cleanup, remove CFG_CLKS_IN_HZ from config-headers. Tested on mx31ads, provides 2% or 0.4% precision depending on the CONFIG_MX31_TIMER_HIGH_PRECISION flag. Measured with stop-watch on 100s boot-delay. Signed-off-by: Guennadi Liakhovetski <lg@denx.de>
Showing 4 changed files with 53 additions and 36 deletions Side-by-side Diff
cpu/arm1136/mx31/interrupts.c
... | ... | @@ -27,30 +27,49 @@ |
27 | 27 | #define TIMER_BASE 0x53f90000 /* General purpose timer 1 */ |
28 | 28 | |
29 | 29 | /* General purpose timers registers */ |
30 | -#define GPTCR __REG(TIMER_BASE) /* Control register */ | |
31 | -#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ | |
32 | -#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ | |
33 | -#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ | |
30 | +#define GPTCR __REG(TIMER_BASE) /* Control register */ | |
31 | +#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ | |
32 | +#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ | |
33 | +#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ | |
34 | 34 | |
35 | 35 | /* General purpose timers bitfields */ |
36 | -#define GPTCR_SWR (1<<15) /* Software reset */ | |
37 | -#define GPTCR_FRR (1<<9) /* Freerun / restart */ | |
38 | -#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ | |
39 | -#define GPTCR_TEN (1) /* Timer enable */ | |
36 | +#define GPTCR_SWR (1 << 15) /* Software reset */ | |
37 | +#define GPTCR_FRR (1 << 9) /* Freerun / restart */ | |
38 | +#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */ | |
39 | +#define GPTCR_TEN 1 /* Timer enable */ | |
40 | 40 | |
41 | +/* "time" is measured in 1 / CFG_HZ seconds, "tick" is internal timer period */ | |
42 | +#ifdef CONFIG_MX31_TIMER_HIGH_PRECISION | |
43 | +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ | |
44 | +#define TICK_TO_TIME(t) ((t) * CFG_HZ / CONFIG_MX31_CLK32) | |
45 | +#define TIME_TO_TICK(t) ((unsigned long long)(t) * CONFIG_MX31_CLK32 / CFG_HZ) | |
46 | +#define US_TO_TICK(t) (((unsigned long long)(t) * CONFIG_MX31_CLK32 + \ | |
47 | + 999999) / 1000000) | |
48 | +#else | |
49 | +/* ~2% error */ | |
50 | +#define TICK_PER_TIME ((CONFIG_MX31_CLK32 + CFG_HZ / 2) / CFG_HZ) | |
51 | +#define US_PER_TICK (1000000 / CONFIG_MX31_CLK32) | |
52 | +#define TICK_TO_TIME(t) ((t) / TICK_PER_TIME) | |
53 | +#define TIME_TO_TICK(t) ((unsigned long long)(t) * TICK_PER_TIME) | |
54 | +#define US_TO_TICK(t) (((t) + US_PER_TICK - 1) / US_PER_TICK) | |
55 | +#endif | |
56 | + | |
41 | 57 | static ulong timestamp; |
42 | 58 | static ulong lastinc; |
43 | 59 | |
44 | 60 | /* nothing really to do with interrupts, just starts up a counter. */ |
61 | +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ | |
45 | 62 | int interrupt_init (void) |
46 | 63 | { |
47 | 64 | int i; |
48 | 65 | |
49 | 66 | /* setup GP Timer 1 */ |
50 | 67 | GPTCR = GPTCR_SWR; |
51 | - for ( i=0; i<100; i++) GPTCR = 0; /* We have no udelay by now */ | |
68 | + for (i = 0; i < 100; i++) | |
69 | + GPTCR = 0; /* We have no udelay by now */ | |
52 | 70 | GPTPR = 0; /* 32Khz */ |
53 | - GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; /* Freerun Mode, PERCLK1 input */ | |
71 | + /* Freerun Mode, PERCLK1 input */ | |
72 | + GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; | |
54 | 73 | |
55 | 74 | return 0; |
56 | 75 | } |
... | ... | @@ -67,7 +86,7 @@ |
67 | 86 | reset_timer_masked(); |
68 | 87 | } |
69 | 88 | |
70 | -ulong get_timer_masked (void) | |
89 | +unsigned long long get_ticks (void) | |
71 | 90 | { |
72 | 91 | ulong now = GPTCNT; /* current tick value */ |
73 | 92 | |
... | ... | @@ -80,6 +99,17 @@ |
80 | 99 | return timestamp; |
81 | 100 | } |
82 | 101 | |
102 | +ulong get_timer_masked (void) | |
103 | +{ | |
104 | + /* | |
105 | + * get_ticks() returns a long long (64 bit), it wraps in | |
106 | + * 2^64 / CONFIG_MX31_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ | |
107 | + * 5 * 10^9 days... and get_ticks() * CFG_HZ wraps in | |
108 | + * 5 * 10^6 days - long enough. | |
109 | + */ | |
110 | + return TICK_TO_TIME(get_ticks()); | |
111 | +} | |
112 | + | |
83 | 113 | ulong get_timer (ulong base) |
84 | 114 | { |
85 | 115 | return get_timer_masked () - base; |
86 | 116 | |
87 | 117 | |
88 | 118 | |
... | ... | @@ -87,29 +117,20 @@ |
87 | 117 | |
88 | 118 | void set_timer (ulong t) |
89 | 119 | { |
120 | + timestamp = TIME_TO_TICK(t); | |
90 | 121 | } |
91 | 122 | |
92 | 123 | /* delay x useconds AND perserve advance timstamp value */ |
93 | 124 | void udelay (unsigned long usec) |
94 | 125 | { |
95 | - ulong tmo, tmp; | |
126 | + unsigned long long tmp; | |
127 | + ulong tmo; | |
96 | 128 | |
97 | - if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ | |
98 | - tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ | |
99 | - tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ | |
100 | - tmo /= 1000; /* finish normalize. */ | |
101 | - } else { /* else small number, don't kill it prior to HZ multiply */ | |
102 | - tmo = usec * CFG_HZ; | |
103 | - tmo /= (1000*1000); | |
104 | - } | |
129 | + tmo = US_TO_TICK(usec); | |
130 | + tmp = get_ticks() + tmo; /* get current timestamp */ | |
105 | 131 | |
106 | - tmp = get_timer (0); /* get current timestamp */ | |
107 | - if ( (tmo + tmp + 1) < tmp )/* if setting this forward will roll time stamp */ | |
108 | - reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastinc value */ | |
109 | - else | |
110 | - tmo += tmp; /* else, set advancing stamp wake up time */ | |
111 | - while (get_timer_masked () < tmo)/* loop till event */ | |
112 | - /*NOP*/; | |
132 | + while (get_ticks() < tmp) /* loop till event */ | |
133 | + /*NOP*/; | |
113 | 134 | } |
114 | 135 | |
115 | 136 | void reset_cpu (ulong addr) |
include/configs/imx31_litekit.h
... | ... | @@ -122,11 +122,9 @@ |
122 | 122 | #define CFG_MEMTEST_START 0 /* memtest works on */ |
123 | 123 | #define CFG_MEMTEST_END 0x10000 |
124 | 124 | |
125 | -#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ | |
126 | - | |
127 | 125 | #define CFG_LOAD_ADDR 0 /* default load address */ |
128 | 126 | |
129 | -#define CFG_HZ 32000 | |
127 | +#define CFG_HZ 1000 | |
130 | 128 | |
131 | 129 | #define CONFIG_CMDLINE_EDITING 1 |
132 | 130 |
include/configs/imx31_phycore.h
include/configs/mx31ads.h
... | ... | @@ -139,11 +139,9 @@ |
139 | 139 | #define CFG_MEMTEST_START 0 /* memtest works on */ |
140 | 140 | #define CFG_MEMTEST_END 0x10000 |
141 | 141 | |
142 | -#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ | |
143 | - | |
144 | 142 | #define CFG_LOAD_ADDR CONFIG_LOADADDR |
145 | 143 | |
146 | -#define CFG_HZ CONFIG_MX31_CLK32 /* use 32kHz clock as source */ | |
144 | +#define CFG_HZ 1000 | |
147 | 145 | |
148 | 146 | #define CONFIG_CMDLINE_EDITING 1 |
149 | 147 |