diff options
Diffstat (limited to 'arch/xtensa/kernel/time.c')
-rw-r--r-- | arch/xtensa/kernel/time.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 9af3dd88ad7e..08b769d3b3a1 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -36,7 +36,7 @@ static cycle_t ccount_read(struct clocksource *cs) | |||
36 | return (cycle_t)get_ccount(); | 36 | return (cycle_t)get_ccount(); |
37 | } | 37 | } |
38 | 38 | ||
39 | static u32 notrace ccount_sched_clock_read(void) | 39 | static u64 notrace ccount_sched_clock_read(void) |
40 | { | 40 | { |
41 | return get_ccount(); | 41 | return get_ccount(); |
42 | } | 42 | } |
@@ -46,24 +46,19 @@ static struct clocksource ccount_clocksource = { | |||
46 | .rating = 200, | 46 | .rating = 200, |
47 | .read = ccount_read, | 47 | .read = ccount_read, |
48 | .mask = CLOCKSOURCE_MASK(32), | 48 | .mask = CLOCKSOURCE_MASK(32), |
49 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | static int ccount_timer_set_next_event(unsigned long delta, | 52 | static int ccount_timer_set_next_event(unsigned long delta, |
52 | struct clock_event_device *dev); | 53 | struct clock_event_device *dev); |
53 | static void ccount_timer_set_mode(enum clock_event_mode mode, | 54 | static void ccount_timer_set_mode(enum clock_event_mode mode, |
54 | struct clock_event_device *evt); | 55 | struct clock_event_device *evt); |
55 | static struct ccount_timer_t { | 56 | struct ccount_timer { |
56 | struct clock_event_device evt; | 57 | struct clock_event_device evt; |
57 | int irq_enabled; | 58 | int irq_enabled; |
58 | } ccount_timer = { | 59 | char name[24]; |
59 | .evt = { | ||
60 | .name = "ccount_clockevent", | ||
61 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
62 | .rating = 300, | ||
63 | .set_next_event = ccount_timer_set_next_event, | ||
64 | .set_mode = ccount_timer_set_mode, | ||
65 | }, | ||
66 | }; | 60 | }; |
61 | static DEFINE_PER_CPU(struct ccount_timer, ccount_timer); | ||
67 | 62 | ||
68 | static int ccount_timer_set_next_event(unsigned long delta, | 63 | static int ccount_timer_set_next_event(unsigned long delta, |
69 | struct clock_event_device *dev) | 64 | struct clock_event_device *dev) |
@@ -84,8 +79,8 @@ static int ccount_timer_set_next_event(unsigned long delta, | |||
84 | static void ccount_timer_set_mode(enum clock_event_mode mode, | 79 | static void ccount_timer_set_mode(enum clock_event_mode mode, |
85 | struct clock_event_device *evt) | 80 | struct clock_event_device *evt) |
86 | { | 81 | { |
87 | struct ccount_timer_t *timer = | 82 | struct ccount_timer *timer = |
88 | container_of(evt, struct ccount_timer_t, evt); | 83 | container_of(evt, struct ccount_timer, evt); |
89 | 84 | ||
90 | /* | 85 | /* |
91 | * There is no way to disable the timer interrupt at the device level, | 86 | * There is no way to disable the timer interrupt at the device level, |
@@ -117,9 +112,28 @@ static struct irqaction timer_irqaction = { | |||
117 | .handler = timer_interrupt, | 112 | .handler = timer_interrupt, |
118 | .flags = IRQF_TIMER, | 113 | .flags = IRQF_TIMER, |
119 | .name = "timer", | 114 | .name = "timer", |
120 | .dev_id = &ccount_timer, | ||
121 | }; | 115 | }; |
122 | 116 | ||
117 | void local_timer_setup(unsigned cpu) | ||
118 | { | ||
119 | struct ccount_timer *timer = &per_cpu(ccount_timer, cpu); | ||
120 | struct clock_event_device *clockevent = &timer->evt; | ||
121 | |||
122 | timer->irq_enabled = 1; | ||
123 | clockevent->name = timer->name; | ||
124 | snprintf(timer->name, sizeof(timer->name), "ccount_clockevent_%u", cpu); | ||
125 | clockevent->features = CLOCK_EVT_FEAT_ONESHOT; | ||
126 | clockevent->rating = 300; | ||
127 | clockevent->set_next_event = ccount_timer_set_next_event; | ||
128 | clockevent->set_mode = ccount_timer_set_mode; | ||
129 | clockevent->cpumask = cpumask_of(cpu); | ||
130 | clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); | ||
131 | if (WARN(!clockevent->irq, "error: can't map timer irq")) | ||
132 | return; | ||
133 | clockevents_config_and_register(clockevent, ccount_freq, | ||
134 | 0xf, 0xffffffff); | ||
135 | } | ||
136 | |||
123 | void __init time_init(void) | 137 | void __init time_init(void) |
124 | { | 138 | { |
125 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 139 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
@@ -131,28 +145,21 @@ void __init time_init(void) | |||
131 | ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL; | 145 | ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL; |
132 | #endif | 146 | #endif |
133 | clocksource_register_hz(&ccount_clocksource, ccount_freq); | 147 | clocksource_register_hz(&ccount_clocksource, ccount_freq); |
134 | 148 | local_timer_setup(0); | |
135 | ccount_timer.evt.cpumask = cpumask_of(0); | 149 | setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction); |
136 | ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); | 150 | sched_clock_register(ccount_sched_clock_read, 32, ccount_freq); |
137 | if (WARN(!ccount_timer.evt.irq, "error: can't map timer irq")) | 151 | clocksource_of_init(); |
138 | return; | ||
139 | clockevents_config_and_register(&ccount_timer.evt, ccount_freq, 0xf, | ||
140 | 0xffffffff); | ||
141 | setup_irq(ccount_timer.evt.irq, &timer_irqaction); | ||
142 | ccount_timer.irq_enabled = 1; | ||
143 | |||
144 | setup_sched_clock(ccount_sched_clock_read, 32, ccount_freq); | ||
145 | } | 152 | } |
146 | 153 | ||
147 | /* | 154 | /* |
148 | * The timer interrupt is called HZ times per second. | 155 | * The timer interrupt is called HZ times per second. |
149 | */ | 156 | */ |
150 | 157 | ||
151 | irqreturn_t timer_interrupt (int irq, void *dev_id) | 158 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
152 | { | 159 | { |
153 | struct ccount_timer_t *timer = dev_id; | 160 | struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; |
154 | struct clock_event_device *evt = &timer->evt; | ||
155 | 161 | ||
162 | set_linux_timer(get_linux_timer()); | ||
156 | evt->event_handler(evt); | 163 | evt->event_handler(evt); |
157 | 164 | ||
158 | /* Allow platform to do something useful (Wdog). */ | 165 | /* Allow platform to do something useful (Wdog). */ |