.. | .. |
---|
52 | 52 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
---|
53 | 53 | }; |
---|
54 | 54 | |
---|
55 | | -static int ccount_timer_set_next_event(unsigned long delta, |
---|
56 | | - struct clock_event_device *dev); |
---|
57 | 55 | struct ccount_timer { |
---|
58 | 56 | struct clock_event_device evt; |
---|
59 | 57 | int irq_enabled; |
---|
60 | 58 | char name[24]; |
---|
61 | 59 | }; |
---|
62 | | -static DEFINE_PER_CPU(struct ccount_timer, ccount_timer); |
---|
63 | 60 | |
---|
64 | 61 | static int ccount_timer_set_next_event(unsigned long delta, |
---|
65 | 62 | struct clock_event_device *dev) |
---|
.. | .. |
---|
107 | 104 | return 0; |
---|
108 | 105 | } |
---|
109 | 106 | |
---|
110 | | -static irqreturn_t timer_interrupt(int irq, void *dev_id); |
---|
111 | | -static struct irqaction timer_irqaction = { |
---|
112 | | - .handler = timer_interrupt, |
---|
113 | | - .flags = IRQF_TIMER, |
---|
114 | | - .name = "timer", |
---|
| 107 | +static DEFINE_PER_CPU(struct ccount_timer, ccount_timer) = { |
---|
| 108 | + .evt = { |
---|
| 109 | + .features = CLOCK_EVT_FEAT_ONESHOT, |
---|
| 110 | + .rating = 300, |
---|
| 111 | + .set_next_event = ccount_timer_set_next_event, |
---|
| 112 | + .set_state_shutdown = ccount_timer_shutdown, |
---|
| 113 | + .set_state_oneshot = ccount_timer_set_oneshot, |
---|
| 114 | + .tick_resume = ccount_timer_set_oneshot, |
---|
| 115 | + }, |
---|
115 | 116 | }; |
---|
| 117 | + |
---|
| 118 | +static irqreturn_t timer_interrupt(int irq, void *dev_id) |
---|
| 119 | +{ |
---|
| 120 | + struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; |
---|
| 121 | + |
---|
| 122 | + set_linux_timer(get_linux_timer()); |
---|
| 123 | + evt->event_handler(evt); |
---|
| 124 | + |
---|
| 125 | + /* Allow platform to do something useful (Wdog). */ |
---|
| 126 | + platform_heartbeat(); |
---|
| 127 | + |
---|
| 128 | + return IRQ_HANDLED; |
---|
| 129 | +} |
---|
116 | 130 | |
---|
117 | 131 | void local_timer_setup(unsigned cpu) |
---|
118 | 132 | { |
---|
.. | .. |
---|
120 | 134 | struct clock_event_device *clockevent = &timer->evt; |
---|
121 | 135 | |
---|
122 | 136 | timer->irq_enabled = 1; |
---|
123 | | - clockevent->name = timer->name; |
---|
124 | 137 | 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_state_shutdown = ccount_timer_shutdown; |
---|
129 | | - clockevent->set_state_oneshot = ccount_timer_set_oneshot; |
---|
130 | | - clockevent->tick_resume = ccount_timer_set_oneshot; |
---|
| 138 | + clockevent->name = timer->name; |
---|
131 | 139 | clockevent->cpumask = cpumask_of(cpu); |
---|
132 | 140 | clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); |
---|
133 | 141 | if (WARN(!clockevent->irq, "error: can't map timer irq")) |
---|
.. | .. |
---|
146 | 154 | cpu = of_find_compatible_node(NULL, NULL, "cdns,xtensa-cpu"); |
---|
147 | 155 | if (cpu) { |
---|
148 | 156 | clk = of_clk_get(cpu, 0); |
---|
| 157 | + of_node_put(cpu); |
---|
149 | 158 | if (!IS_ERR(clk)) { |
---|
150 | 159 | ccount_freq = clk_get_rate(clk); |
---|
151 | 160 | return; |
---|
.. | .. |
---|
170 | 179 | |
---|
171 | 180 | void __init time_init(void) |
---|
172 | 181 | { |
---|
| 182 | + int irq; |
---|
| 183 | + |
---|
173 | 184 | of_clk_init(NULL); |
---|
174 | 185 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
---|
175 | 186 | pr_info("Calibrating CPU frequency "); |
---|
.. | .. |
---|
185 | 196 | __func__); |
---|
186 | 197 | clocksource_register_hz(&ccount_clocksource, ccount_freq); |
---|
187 | 198 | local_timer_setup(0); |
---|
188 | | - setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction); |
---|
| 199 | + irq = this_cpu_ptr(&ccount_timer)->evt.irq; |
---|
| 200 | + if (request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL)) |
---|
| 201 | + pr_err("Failed to request irq %d (timer)\n", irq); |
---|
189 | 202 | sched_clock_register(ccount_sched_clock_read, 32, ccount_freq); |
---|
190 | 203 | timer_probe(); |
---|
191 | | -} |
---|
192 | | - |
---|
193 | | -/* |
---|
194 | | - * The timer interrupt is called HZ times per second. |
---|
195 | | - */ |
---|
196 | | - |
---|
197 | | -irqreturn_t timer_interrupt(int irq, void *dev_id) |
---|
198 | | -{ |
---|
199 | | - struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; |
---|
200 | | - |
---|
201 | | - set_linux_timer(get_linux_timer()); |
---|
202 | | - evt->event_handler(evt); |
---|
203 | | - |
---|
204 | | - /* Allow platform to do something useful (Wdog). */ |
---|
205 | | - platform_heartbeat(); |
---|
206 | | - |
---|
207 | | - return IRQ_HANDLED; |
---|
208 | 204 | } |
---|
209 | 205 | |
---|
210 | 206 | #ifndef CONFIG_GENERIC_CALIBRATE_DELAY |
---|