aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Spranger <b.spranger@linutronix.de>2010-03-08 12:57:04 -0500
committerThomas Gleixner <tglx@linutronix.de>2010-05-02 14:13:54 -0400
commit917c377817e393775fb6a2eaf961c153e38760fd (patch)
tree1208f7406f55cfb88978e3ff46f4a39baa637eed
parentb16bd4fb3290b5d380c2a67cc4c5109d65cee1d7 (diff)
Atmel TCLIB: Allow higher clock rates for clock events
As default the TCLIB uses the 32KiHz base clock rate for clock events. Add a compile time selection to allow higher clock resulution. Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/clocksource/tcb_clksrc.c44
-rw-r--r--drivers/misc/Kconfig11
2 files changed, 35 insertions, 20 deletions
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 01b886e68822..90350b6612bb 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -21,8 +21,7 @@
21 * resolution better than 200 nsec). 21 * resolution better than 200 nsec).
22 * 22 *
23 * - The third channel may be used to provide a 16-bit clockevent 23 * - The third channel may be used to provide a 16-bit clockevent
24 * source, used in either periodic or oneshot mode. This runs 24 * source, used in either periodic or oneshot mode.
25 * at 32 KiHZ, and can handle delays of up to two seconds.
26 * 25 *
27 * A boot clocksource and clockevent source are also currently needed, 26 * A boot clocksource and clockevent source are also currently needed,
28 * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so 27 * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
@@ -68,6 +67,7 @@ static struct clocksource clksrc = {
68struct tc_clkevt_device { 67struct tc_clkevt_device {
69 struct clock_event_device clkevt; 68 struct clock_event_device clkevt;
70 struct clk *clk; 69 struct clk *clk;
70 u32 freq;
71 void __iomem *regs; 71 void __iomem *regs;
72}; 72};
73 73
@@ -76,13 +76,6 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
76 return container_of(clkevt, struct tc_clkevt_device, clkevt); 76 return container_of(clkevt, struct tc_clkevt_device, clkevt);
77} 77}
78 78
79/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
80 * because using one of the divided clocks would usually mean the
81 * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
82 *
83 * A divided clock could be good for high resolution timers, since
84 * 30.5 usec resolution can seem "low".
85 */
86static u32 timer_clock; 79static u32 timer_clock;
87 80
88static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) 81static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
@@ -105,11 +98,12 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
105 case CLOCK_EVT_MODE_PERIODIC: 98 case CLOCK_EVT_MODE_PERIODIC:
106 clk_enable(tcd->clk); 99 clk_enable(tcd->clk);
107 100
108 /* slow clock, count up to RC, then irq and restart */ 101 /* count up to RC, then irq and restart */
109 __raw_writel(timer_clock 102 __raw_writel(timer_clock
110 | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, 103 | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
111 regs + ATMEL_TC_REG(2, CMR)); 104 regs + ATMEL_TC_REG(2, CMR));
112 __raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); 105 __raw_writel((tcd->freq + HZ/2)/HZ,
106 tcaddr + ATMEL_TC_REG(2, RC));
113 107
114 /* Enable clock and interrupts on RC compare */ 108 /* Enable clock and interrupts on RC compare */
115 __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); 109 __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
@@ -122,7 +116,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
122 case CLOCK_EVT_MODE_ONESHOT: 116 case CLOCK_EVT_MODE_ONESHOT:
123 clk_enable(tcd->clk); 117 clk_enable(tcd->clk);
124 118
125 /* slow clock, count up to RC, then irq and stop */ 119 /* count up to RC, then irq and stop */
126 __raw_writel(timer_clock | ATMEL_TC_CPCSTOP 120 __raw_writel(timer_clock | ATMEL_TC_CPCSTOP
127 | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, 121 | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
128 regs + ATMEL_TC_REG(2, CMR)); 122 regs + ATMEL_TC_REG(2, CMR));
@@ -152,8 +146,12 @@ static struct tc_clkevt_device clkevt = {
152 .features = CLOCK_EVT_FEAT_PERIODIC 146 .features = CLOCK_EVT_FEAT_PERIODIC
153 | CLOCK_EVT_FEAT_ONESHOT, 147 | CLOCK_EVT_FEAT_ONESHOT,
154 .shift = 32, 148 .shift = 32,
149#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
155 /* Should be lower than at91rm9200's system timer */ 150 /* Should be lower than at91rm9200's system timer */
156 .rating = 125, 151 .rating = 125,
152#else
153 .rating = 200,
154#endif
157 .set_next_event = tc_next_event, 155 .set_next_event = tc_next_event,
158 .set_mode = tc_mode, 156 .set_mode = tc_mode,
159 }, 157 },
@@ -179,8 +177,9 @@ static struct irqaction tc_irqaction = {
179 .handler = ch2_irq, 177 .handler = ch2_irq,
180}; 178};
181 179
182static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) 180static void __init setup_clkevents(struct atmel_tc *tc, int divisor_idx)
183{ 181{
182 unsigned divisor = atmel_tc_divisors[divisor_idx];
184 struct clk *t2_clk = tc->clk[2]; 183 struct clk *t2_clk = tc->clk[2];
185 int irq = tc->irq[2]; 184 int irq = tc->irq[2];
186 185
@@ -188,11 +187,17 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
188 clkevt.clk = t2_clk; 187 clkevt.clk = t2_clk;
189 tc_irqaction.dev_id = &clkevt; 188 tc_irqaction.dev_id = &clkevt;
190 189
191 timer_clock = clk32k_divisor_idx; 190 timer_clock = divisor_idx;
192 191
193 clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift); 192 if (!divisor)
194 clkevt.clkevt.max_delta_ns 193 clkevt.freq = 32768;
195 = clockevent_delta2ns(0xffff, &clkevt.clkevt); 194 else
195 clkevt.freq = clk_get_rate(t2_clk)/divisor;
196
197 clkevt.clkevt.mult = div_sc(clkevt.freq, NSEC_PER_SEC,
198 clkevt.clkevt.shift);
199 clkevt.clkevt.max_delta_ns =
200 clockevent_delta2ns(0xffff, &clkevt.clkevt);
196 clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1; 201 clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
197 clkevt.clkevt.cpumask = cpumask_of(0); 202 clkevt.clkevt.cpumask = cpumask_of(0);
198 203
@@ -295,8 +300,11 @@ static int __init tcb_clksrc_init(void)
295 clocksource_register(&clksrc); 300 clocksource_register(&clksrc);
296 301
297 /* channel 2: periodic and oneshot timer support */ 302 /* channel 2: periodic and oneshot timer support */
303#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
298 setup_clkevents(tc, clk32k_divisor_idx); 304 setup_clkevents(tc, clk32k_divisor_idx);
299 305#else
306 setup_clkevents(tc, best_divisor_idx);
307#endif
300 return 0; 308 return 0;
301} 309}
302arch_initcall(tcb_clksrc_init); 310arch_initcall(tcb_clksrc_init);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 9eaa6477cec2..3f3a4c864735 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -54,8 +54,7 @@ config ATMEL_TCB_CLKSRC
54 are combined to make a single 32-bit timer. 54 are combined to make a single 32-bit timer.
55 55
56 When GENERIC_CLOCKEVENTS is defined, the third timer channel 56 When GENERIC_CLOCKEVENTS is defined, the third timer channel
57 may be used as a clock event device supporting oneshot mode 57 may be used as a clock event device supporting oneshot mode.
58 (delays of up to two seconds) based on the 32 KiHz clock.
59 58
60config ATMEL_TCB_CLKSRC_BLOCK 59config ATMEL_TCB_CLKSRC_BLOCK
61 int 60 int
@@ -69,6 +68,14 @@ config ATMEL_TCB_CLKSRC_BLOCK
69 TC can be used for other purposes, such as PWM generation and 68 TC can be used for other purposes, such as PWM generation and
70 interval timing. 69 interval timing.
71 70
71config ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
72 bool "TC Block use 32 KiHz clock"
73 depends on ATMEL_TCB_CLKSRC
74 default y
75 help
76 Select this to use 32 KiHz base clock rate as TC block clock
77 source for clock events.
78
72config IBM_ASM 79config IBM_ASM
73 tristate "Device driver for IBM RSA service processor" 80 tristate "Device driver for IBM RSA service processor"
74 depends on X86 && PCI && INPUT && EXPERIMENTAL 81 depends on X86 && PCI && INPUT && EXPERIMENTAL