| .. | .. |
|---|
| 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 |
|---|