diff options
| author | Li Jie <eltshanli@gmail.com> | 2009-12-31 09:57:53 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-01-05 15:52:10 -0500 |
| commit | 1368c51c501978e5c4148322b7c77d4f49549557 (patch) | |
| tree | faf0beee26ecee8944b78dbf493f3d4c141125ab /arch | |
| parent | 070f1f178c4377c09f72e414513aeacd8403f6d6 (diff) | |
ARM: 5863/1: fix bugs of clock source of NUC900
This patch fix following bugs:
1. typo error, CLOCK_EVT_MODE_PERIODIC -> CLOCK_EVT_FEAT_PERIODIC
2. TCSR register of timer1 missed PRESCALE
3. timer1 should be enabled before register it to clock source.
Signed-off-by: lijie <eltshanli@gmail.com>
Acked-by: Wan ZongShun <mcuos.com@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm/mach-w90x900/time.c | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 4128af870b41..b80f769bc135 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c | |||
| @@ -42,7 +42,10 @@ | |||
| 42 | #define TICKS_PER_SEC 100 | 42 | #define TICKS_PER_SEC 100 |
| 43 | #define PRESCALE 0x63 /* Divider = prescale + 1 */ | 43 | #define PRESCALE 0x63 /* Divider = prescale + 1 */ |
| 44 | 44 | ||
| 45 | unsigned int timer0_load; | 45 | #define TDR_SHIFT 24 |
| 46 | #define TDR_MASK ((1 << TDR_SHIFT) - 1) | ||
| 47 | |||
| 48 | static unsigned int timer0_load; | ||
| 46 | 49 | ||
| 47 | static void nuc900_clockevent_setmode(enum clock_event_mode mode, | 50 | static void nuc900_clockevent_setmode(enum clock_event_mode mode, |
| 48 | struct clock_event_device *clk) | 51 | struct clock_event_device *clk) |
| @@ -88,7 +91,7 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, | |||
| 88 | static struct clock_event_device nuc900_clockevent_device = { | 91 | static struct clock_event_device nuc900_clockevent_device = { |
| 89 | .name = "nuc900-timer0", | 92 | .name = "nuc900-timer0", |
| 90 | .shift = 32, | 93 | .shift = 32, |
| 91 | .features = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 94 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
| 92 | .set_mode = nuc900_clockevent_setmode, | 95 | .set_mode = nuc900_clockevent_setmode, |
| 93 | .set_next_event = nuc900_clockevent_setnextevent, | 96 | .set_next_event = nuc900_clockevent_setnextevent, |
| 94 | .rating = 300, | 97 | .rating = 300, |
| @@ -112,8 +115,23 @@ static struct irqaction nuc900_timer0_irq = { | |||
| 112 | .handler = nuc900_timer0_interrupt, | 115 | .handler = nuc900_timer0_interrupt, |
| 113 | }; | 116 | }; |
| 114 | 117 | ||
| 115 | static void __init nuc900_clockevents_init(unsigned int rate) | 118 | static void __init nuc900_clockevents_init(void) |
| 116 | { | 119 | { |
| 120 | unsigned int rate; | ||
| 121 | struct clk *clk = clk_get(NULL, "timer0"); | ||
| 122 | |||
| 123 | BUG_ON(IS_ERR(clk)); | ||
| 124 | |||
| 125 | __raw_writel(0x00, REG_TCSR0); | ||
| 126 | |||
| 127 | clk_enable(clk); | ||
| 128 | rate = clk_get_rate(clk) / (PRESCALE + 1); | ||
| 129 | |||
| 130 | timer0_load = (rate / TICKS_PER_SEC); | ||
| 131 | |||
| 132 | __raw_writel(RESETINT, REG_TISR); | ||
| 133 | setup_irq(IRQ_TIMER0, &nuc900_timer0_irq); | ||
| 134 | |||
| 117 | nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, | 135 | nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, |
| 118 | nuc900_clockevent_device.shift); | 136 | nuc900_clockevent_device.shift); |
| 119 | nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, | 137 | nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, |
| @@ -127,26 +145,35 @@ static void __init nuc900_clockevents_init(unsigned int rate) | |||
| 127 | 145 | ||
| 128 | static cycle_t nuc900_get_cycles(struct clocksource *cs) | 146 | static cycle_t nuc900_get_cycles(struct clocksource *cs) |
| 129 | { | 147 | { |
| 130 | return ~__raw_readl(REG_TDR1); | 148 | return (~__raw_readl(REG_TDR1)) & TDR_MASK; |
| 131 | } | 149 | } |
| 132 | 150 | ||
| 133 | static struct clocksource clocksource_nuc900 = { | 151 | static struct clocksource clocksource_nuc900 = { |
| 134 | .name = "nuc900-timer1", | 152 | .name = "nuc900-timer1", |
| 135 | .rating = 200, | 153 | .rating = 200, |
| 136 | .read = nuc900_get_cycles, | 154 | .read = nuc900_get_cycles, |
| 137 | .mask = CLOCKSOURCE_MASK(32), | 155 | .mask = CLOCKSOURCE_MASK(TDR_SHIFT), |
| 138 | .shift = 20, | 156 | .shift = 10, |
| 139 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 157 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| 140 | }; | 158 | }; |
| 141 | 159 | ||
| 142 | static void __init nuc900_clocksource_init(unsigned int rate) | 160 | static void __init nuc900_clocksource_init(void) |
| 143 | { | 161 | { |
| 144 | unsigned int val; | 162 | unsigned int val; |
| 163 | unsigned int rate; | ||
| 164 | struct clk *clk = clk_get(NULL, "timer1"); | ||
| 165 | |||
| 166 | BUG_ON(IS_ERR(clk)); | ||
| 167 | |||
| 168 | __raw_writel(0x00, REG_TCSR1); | ||
| 169 | |||
| 170 | clk_enable(clk); | ||
| 171 | rate = clk_get_rate(clk) / (PRESCALE + 1); | ||
| 145 | 172 | ||
| 146 | __raw_writel(0xffffffff, REG_TICR1); | 173 | __raw_writel(0xffffffff, REG_TICR1); |
| 147 | 174 | ||
| 148 | val = __raw_readl(REG_TCSR1); | 175 | val = __raw_readl(REG_TCSR1); |
| 149 | val |= (COUNTEN | PERIOD); | 176 | val |= (COUNTEN | PERIOD | PRESCALE); |
| 150 | __raw_writel(val, REG_TCSR1); | 177 | __raw_writel(val, REG_TCSR1); |
| 151 | 178 | ||
| 152 | clocksource_nuc900.mult = | 179 | clocksource_nuc900.mult = |
| @@ -156,25 +183,8 @@ static void __init nuc900_clocksource_init(unsigned int rate) | |||
| 156 | 183 | ||
| 157 | static void __init nuc900_timer_init(void) | 184 | static void __init nuc900_timer_init(void) |
| 158 | { | 185 | { |
| 159 | struct clk *ck_ext = clk_get(NULL, "ext"); | 186 | nuc900_clocksource_init(); |
| 160 | unsigned int rate; | 187 | nuc900_clockevents_init(); |
| 161 | |||
| 162 | BUG_ON(IS_ERR(ck_ext)); | ||
| 163 | |||
| 164 | rate = clk_get_rate(ck_ext); | ||
| 165 | clk_put(ck_ext); | ||
| 166 | rate = rate / (PRESCALE + 0x01); | ||
| 167 | |||
| 168 | /* set a known state */ | ||
| 169 | __raw_writel(0x00, REG_TCSR0); | ||
| 170 | __raw_writel(0x00, REG_TCSR1); | ||
| 171 | __raw_writel(RESETINT, REG_TISR); | ||
| 172 | timer0_load = (rate / TICKS_PER_SEC); | ||
| 173 | |||
| 174 | setup_irq(IRQ_TIMER0, &nuc900_timer0_irq); | ||
| 175 | |||
| 176 | nuc900_clocksource_init(rate); | ||
| 177 | nuc900_clockevents_init(rate); | ||
| 178 | } | 188 | } |
| 179 | 189 | ||
| 180 | struct sys_timer nuc900_timer = { | 190 | struct sys_timer nuc900_timer = { |
