Blame view

drivers/clocksource/arc_timer.c 9.02 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
d8005e6b9   Vineet Gupta   ARC: Timers/count...
2
  /*
c4c9a040e   Vineet Gupta   clocksource: impo...
3
   * Copyright (C) 2016-17 Synopsys, Inc. (www.synopsys.com)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
4
   * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
5
   */
c4c9a040e   Vineet Gupta   clocksource: impo...
6
7
8
  /* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1, Each can be
   * programmed to go from @count to @limit and optionally interrupt.
   * We've designated TIMER0 for clockevents and TIMER1 for clocksource
d8005e6b9   Vineet Gupta   ARC: Timers/count...
9
   *
c4c9a040e   Vineet Gupta   clocksource: impo...
10
11
   * ARCv2 based HS38 cores have RTC (in-core) and GFRC (inside ARConnect/MCIP)
   * which are suitable for UP and SMP based clocksources respectively
d8005e6b9   Vineet Gupta   ARC: Timers/count...
12
   */
d8005e6b9   Vineet Gupta   ARC: Timers/count...
13
  #include <linux/interrupt.h>
93665ab06   Masahiro Yamada   clocksource/drive...
14
  #include <linux/bits.h>
69fbd0987   Noam Camus   ARC: clockevent: ...
15
16
  #include <linux/clk.h>
  #include <linux/clk-provider.h>
d8005e6b9   Vineet Gupta   ARC: Timers/count...
17
18
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
eec3c58ef   Noam Camus   ARC: clockevent: ...
19
  #include <linux/cpu.h>
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
20
21
  #include <linux/of.h>
  #include <linux/of_irq.h>
bf287607c   Alexey Brodkin   clocksource/drive...
22
  #include <linux/sched_clock.h>
d8005e6b9   Vineet Gupta   ARC: Timers/count...
23

b26c2e382   Vineet Gupta   ARC: breakout tim...
24
  #include <soc/arc/timers.h>
2d7f5c48c   Vineet Gupta   ARC: move mcip.h ...
25
  #include <soc/arc/mcip.h>
72d728806   Vineet Gupta   ARCv2: SMP: clock...
26

d8005e6b9   Vineet Gupta   ARC: Timers/count...
27

77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
28
29
30
31
32
33
34
35
36
  static unsigned long arc_timer_freq;
  
  static int noinline arc_get_timer_clk(struct device_node *node)
  {
  	struct clk *clk;
  	int ret;
  
  	clk = of_clk_get(node, 0);
  	if (IS_ERR(clk)) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
37
38
  		pr_err("timer missing clk
  ");
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  		return PTR_ERR(clk);
  	}
  
  	ret = clk_prepare_enable(clk);
  	if (ret) {
  		pr_err("Couldn't enable parent clk
  ");
  		return ret;
  	}
  
  	arc_timer_freq = clk_get_rate(clk);
  
  	return 0;
  }
d8005e6b9   Vineet Gupta   ARC: Timers/count...
53
  /********** Clock Source Device *********/
044214200   Vineet Gupta   ARC: timer: gfrc,...
54
  #ifdef CONFIG_ARC_TIMERS_64BIT
72d728806   Vineet Gupta   ARCv2: SMP: clock...
55

a5a1d1c29   Thomas Gleixner   clocksource: Use ...
56
  static u64 arc_read_gfrc(struct clocksource *cs)
72d728806   Vineet Gupta   ARCv2: SMP: clock...
57
58
  {
  	unsigned long flags;
2cd690ea6   Vineet Gupta   ARC: timer: gfrc,...
59
  	u32 l, h;
72d728806   Vineet Gupta   ARCv2: SMP: clock...
60

6bd9549d8   Eugeniy Paltsev   clocksource/drive...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  	/*
  	 * From a programming model pov, there seems to be just one instance of
  	 * MCIP_CMD/MCIP_READBACK however micro-architecturally there's
  	 * an instance PER ARC CORE (not per cluster), and there are dedicated
  	 * hardware decode logic (per core) inside ARConnect to handle
  	 * simultaneous read/write accesses from cores via those two registers.
  	 * So several concurrent commands to ARConnect are OK if they are
  	 * trying to access two different sub-components (like GFRC,
  	 * inter-core interrupt, etc...). HW also supports simultaneously
  	 * accessing GFRC by multiple cores.
  	 * That's why it is safe to disable hard interrupts on the local CPU
  	 * before access to GFRC instead of taking global MCIP spinlock
  	 * defined in arch/arc/kernel/mcip.c
  	 */
72d728806   Vineet Gupta   ARCv2: SMP: clock...
75
  	local_irq_save(flags);
d584f0fb0   Vineet Gupta   ARCv2: clocksourc...
76
  	__mcip_cmd(CMD_GFRC_READ_LO, 0);
2cd690ea6   Vineet Gupta   ARC: timer: gfrc,...
77
  	l = read_aux_reg(ARC_REG_MCIP_READBACK);
72d728806   Vineet Gupta   ARCv2: SMP: clock...
78

d584f0fb0   Vineet Gupta   ARCv2: clocksourc...
79
  	__mcip_cmd(CMD_GFRC_READ_HI, 0);
2cd690ea6   Vineet Gupta   ARC: timer: gfrc,...
80
  	h = read_aux_reg(ARC_REG_MCIP_READBACK);
72d728806   Vineet Gupta   ARCv2: SMP: clock...
81
82
  
  	local_irq_restore(flags);
a5a1d1c29   Thomas Gleixner   clocksource: Use ...
83
  	return (((u64)h) << 32) | l;
72d728806   Vineet Gupta   ARCv2: SMP: clock...
84
  }
bf287607c   Alexey Brodkin   clocksource/drive...
85
86
87
88
  static notrace u64 arc_gfrc_clock_read(void)
  {
  	return arc_read_gfrc(NULL);
  }
e608b53ea   Vineet Gupta   ARC: clocksource:...
89
  static struct clocksource arc_counter_gfrc = {
d584f0fb0   Vineet Gupta   ARCv2: clocksourc...
90
  	.name   = "ARConnect GFRC",
72d728806   Vineet Gupta   ARCv2: SMP: clock...
91
  	.rating = 400,
e608b53ea   Vineet Gupta   ARC: clocksource:...
92
  	.read   = arc_read_gfrc,
72d728806   Vineet Gupta   ARCv2: SMP: clock...
93
94
95
  	.mask   = CLOCKSOURCE_MASK(64),
  	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
  };
43d756049   Daniel Lezcano   clocksource/drive...
96
  static int __init arc_cs_setup_gfrc(struct device_node *node)
e608b53ea   Vineet Gupta   ARC: clocksource:...
97
  {
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
98
  	struct mcip_bcr mp;
e608b53ea   Vineet Gupta   ARC: clocksource:...
99
  	int ret;
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
100
101
  	READ_BCR(ARC_REG_MCIP_BCR, mp);
  	if (!mp.gfrc) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
102
103
  		pr_warn("Global-64-bit-Ctr clocksource not detected
  ");
43d756049   Daniel Lezcano   clocksource/drive...
104
  		return -ENXIO;
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
105
  	}
e608b53ea   Vineet Gupta   ARC: clocksource:...
106
107
108
  
  	ret = arc_get_timer_clk(node);
  	if (ret)
43d756049   Daniel Lezcano   clocksource/drive...
109
  		return ret;
e608b53ea   Vineet Gupta   ARC: clocksource:...
110

bf287607c   Alexey Brodkin   clocksource/drive...
111
  	sched_clock_register(arc_gfrc_clock_read, 64, arc_timer_freq);
43d756049   Daniel Lezcano   clocksource/drive...
112
  	return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
e608b53ea   Vineet Gupta   ARC: clocksource:...
113
  }
172733959   Daniel Lezcano   clocksource/drive...
114
  TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
e608b53ea   Vineet Gupta   ARC: clocksource:...
115

aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
116
117
118
  #define AUX_RTC_CTRL	0x103
  #define AUX_RTC_LOW	0x104
  #define AUX_RTC_HIGH	0x105
a5a1d1c29   Thomas Gleixner   clocksource: Use ...
119
  static u64 arc_read_rtc(struct clocksource *cs)
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
120
121
  {
  	unsigned long status;
2cd690ea6   Vineet Gupta   ARC: timer: gfrc,...
122
  	u32 l, h;
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
123

922cc1719   Vineet Gupta   ARC: timer: rtc: ...
124
125
126
127
128
129
130
  	/*
  	 * hardware has an internal state machine which tracks readout of
  	 * low/high and updates the CTRL.status if
  	 *  - interrupt/exception taken between the two reads
  	 *  - high increments after low has been read
  	 */
  	do {
2cd690ea6   Vineet Gupta   ARC: timer: gfrc,...
131
132
  		l = read_aux_reg(AUX_RTC_LOW);
  		h = read_aux_reg(AUX_RTC_HIGH);
922cc1719   Vineet Gupta   ARC: timer: rtc: ...
133
  		status = read_aux_reg(AUX_RTC_CTRL);
93665ab06   Masahiro Yamada   clocksource/drive...
134
  	} while (!(status & BIT(31)));
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
135

a5a1d1c29   Thomas Gleixner   clocksource: Use ...
136
  	return (((u64)h) << 32) | l;
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
137
  }
bf287607c   Alexey Brodkin   clocksource/drive...
138
139
140
141
  static notrace u64 arc_rtc_clock_read(void)
  {
  	return arc_read_rtc(NULL);
  }
e608b53ea   Vineet Gupta   ARC: clocksource:...
142
  static struct clocksource arc_counter_rtc = {
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
143
144
  	.name   = "ARCv2 RTC",
  	.rating = 350,
e608b53ea   Vineet Gupta   ARC: clocksource:...
145
  	.read   = arc_read_rtc,
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
146
147
148
  	.mask   = CLOCKSOURCE_MASK(64),
  	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
  };
43d756049   Daniel Lezcano   clocksource/drive...
149
  static int __init arc_cs_setup_rtc(struct device_node *node)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
150
  {
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
151
  	struct bcr_timer timer;
e608b53ea   Vineet Gupta   ARC: clocksource:...
152
  	int ret;
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
153
154
  	READ_BCR(ARC_REG_TIMERS_BCR, timer);
  	if (!timer.rtc) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
155
156
  		pr_warn("Local-64-bit-Ctr clocksource not detected
  ");
43d756049   Daniel Lezcano   clocksource/drive...
157
  		return -ENXIO;
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
158
  	}
e608b53ea   Vineet Gupta   ARC: clocksource:...
159
160
  
  	/* Local to CPU hence not usable in SMP */
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
161
  	if (IS_ENABLED(CONFIG_SMP)) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
162
163
  		pr_warn("Local-64-bit-Ctr not usable in SMP
  ");
43d756049   Daniel Lezcano   clocksource/drive...
164
  		return -EINVAL;
ec7cb87bf   Vineet Gupta   ARC: timer: gfrc,...
165
  	}
e608b53ea   Vineet Gupta   ARC: clocksource:...
166
167
168
  
  	ret = arc_get_timer_clk(node);
  	if (ret)
43d756049   Daniel Lezcano   clocksource/drive...
169
  		return ret;
d8005e6b9   Vineet Gupta   ARC: Timers/count...
170

e608b53ea   Vineet Gupta   ARC: clocksource:...
171
  	write_aux_reg(AUX_RTC_CTRL, 1);
bf287607c   Alexey Brodkin   clocksource/drive...
172
  	sched_clock_register(arc_rtc_clock_read, 64, arc_timer_freq);
43d756049   Daniel Lezcano   clocksource/drive...
173
  	return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
d8005e6b9   Vineet Gupta   ARC: Timers/count...
174
  }
172733959   Daniel Lezcano   clocksource/drive...
175
  TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
e608b53ea   Vineet Gupta   ARC: clocksource:...
176
177
  
  #endif
d8005e6b9   Vineet Gupta   ARC: Timers/count...
178

e608b53ea   Vineet Gupta   ARC: clocksource:...
179
180
181
  /*
   * 32bit TIMER1 to keep counting monotonically and wraparound
   */
a5a1d1c29   Thomas Gleixner   clocksource: Use ...
182
  static u64 arc_read_timer1(struct clocksource *cs)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
183
  {
a5a1d1c29   Thomas Gleixner   clocksource: Use ...
184
  	return (u64) read_aux_reg(ARC_REG_TIMER1_CNT);
d8005e6b9   Vineet Gupta   ARC: Timers/count...
185
  }
bf287607c   Alexey Brodkin   clocksource/drive...
186
187
188
189
  static notrace u64 arc_timer1_clock_read(void)
  {
  	return arc_read_timer1(NULL);
  }
e608b53ea   Vineet Gupta   ARC: clocksource:...
190
  static struct clocksource arc_counter_timer1 = {
d8005e6b9   Vineet Gupta   ARC: Timers/count...
191
192
  	.name   = "ARC Timer1",
  	.rating = 300,
e608b53ea   Vineet Gupta   ARC: clocksource:...
193
  	.read   = arc_read_timer1,
d8005e6b9   Vineet Gupta   ARC: Timers/count...
194
195
196
  	.mask   = CLOCKSOURCE_MASK(32),
  	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
  };
43d756049   Daniel Lezcano   clocksource/drive...
197
  static int __init arc_cs_setup_timer1(struct device_node *node)
e608b53ea   Vineet Gupta   ARC: clocksource:...
198
199
200
201
202
  {
  	int ret;
  
  	/* Local to CPU hence not usable in SMP */
  	if (IS_ENABLED(CONFIG_SMP))
43d756049   Daniel Lezcano   clocksource/drive...
203
  		return -EINVAL;
e608b53ea   Vineet Gupta   ARC: clocksource:...
204
205
206
  
  	ret = arc_get_timer_clk(node);
  	if (ret)
43d756049   Daniel Lezcano   clocksource/drive...
207
  		return ret;
e608b53ea   Vineet Gupta   ARC: clocksource:...
208

b26c2e382   Vineet Gupta   ARC: breakout tim...
209
  	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMERN_MAX);
e608b53ea   Vineet Gupta   ARC: clocksource:...
210
211
  	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
  	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
bf287607c   Alexey Brodkin   clocksource/drive...
212
  	sched_clock_register(arc_timer1_clock_read, 32, arc_timer_freq);
43d756049   Daniel Lezcano   clocksource/drive...
213
  	return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
e608b53ea   Vineet Gupta   ARC: clocksource:...
214
  }
aa93e8ef9   Vineet Gupta   ARCv2: clocksourc...
215

d8005e6b9   Vineet Gupta   ARC: Timers/count...
216
  /********** Clock Event Device *********/
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
217
  static int arc_timer_irq;
eec3c58ef   Noam Camus   ARC: clockevent: ...
218

d8005e6b9   Vineet Gupta   ARC: Timers/count...
219
  /*
c9a98e184   Vineet Gupta   ARC: update some ...
220
   * Arm the timer to interrupt after @cycles
d8005e6b9   Vineet Gupta   ARC: Timers/count...
221
222
   * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
   */
c9a98e184   Vineet Gupta   ARC: update some ...
223
  static void arc_timer_event_setup(unsigned int cycles)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
224
  {
c9a98e184   Vineet Gupta   ARC: update some ...
225
  	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
d8005e6b9   Vineet Gupta   ARC: Timers/count...
226
227
228
229
  	write_aux_reg(ARC_REG_TIMER0_CNT, 0);	/* start from 0 */
  
  	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
  }
d8005e6b9   Vineet Gupta   ARC: Timers/count...
230
231
232
233
234
235
236
  
  static int arc_clkevent_set_next_event(unsigned long delta,
  				       struct clock_event_device *dev)
  {
  	arc_timer_event_setup(delta);
  	return 0;
  }
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
237
  static int arc_clkevent_set_periodic(struct clock_event_device *dev)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
238
  {
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
239
240
241
242
  	/*
  	 * At X Hz, 1 sec = 1000ms -> X cycles;
  	 *		      10ms -> X / 100 cycles
  	 */
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
243
  	arc_timer_event_setup(arc_timer_freq / HZ);
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
244
  	return 0;
d8005e6b9   Vineet Gupta   ARC: Timers/count...
245
246
247
  }
  
  static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
248
249
250
251
  	.name			= "ARC Timer0",
  	.features		= CLOCK_EVT_FEAT_ONESHOT |
  				  CLOCK_EVT_FEAT_PERIODIC,
  	.rating			= 300,
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
252
253
  	.set_next_event		= arc_clkevent_set_next_event,
  	.set_state_periodic	= arc_clkevent_set_periodic,
d8005e6b9   Vineet Gupta   ARC: Timers/count...
254
255
256
257
  };
  
  static irqreturn_t timer_irq_handler(int irq, void *dev_id)
  {
f8b34c3fd   Vineet Gupta   ARC: [clockevent]...
258
259
260
261
262
  	/*
  	 * Note that generic IRQ core could have passed @evt for @dev_id if
  	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
  	 */
  	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
aeec6cdad   Viresh Kumar   ARC/time: Migrate...
263
  	int irq_reenable = clockevent_state_periodic(evt);
f8b34c3fd   Vineet Gupta   ARC: [clockevent]...
264
265
  
  	/*
a4f538573   Vineet Gupta   clocksource/drive...
266
267
268
269
270
271
272
273
  	 * 1. ACK the interrupt
  	 *    - For ARC700, any write to CTRL reg ACKs it, so just rewrite
  	 *      Count when [N]ot [H]alted bit.
  	 *    - For HS3x, it is a bit subtle. On taken count-down interrupt,
  	 *      IP bit [3] is set, which needs to be cleared for ACK'ing.
  	 *      The write below can only update the other two bits, hence
  	 *      explicitly clears IP bit
  	 * 2. Re-arm interrupt if periodic by writing to IE bit [0]
f8b34c3fd   Vineet Gupta   ARC: [clockevent]...
274
275
276
277
  	 */
  	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
  
  	evt->event_handler(evt);
d8005e6b9   Vineet Gupta   ARC: Timers/count...
278

d8005e6b9   Vineet Gupta   ARC: Timers/count...
279
280
  	return IRQ_HANDLED;
  }
ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
281
282
  
  static int arc_timer_starting_cpu(unsigned int cpu)
eec3c58ef   Noam Camus   ARC: clockevent: ...
283
284
285
286
  {
  	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
  
  	evt->cpumask = cpumask_of(smp_processor_id());
b26c2e382   Vineet Gupta   ARC: breakout tim...
287
  	clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMERN_MAX);
ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
288
289
  	enable_percpu_irq(arc_timer_irq, 0);
  	return 0;
eec3c58ef   Noam Camus   ARC: clockevent: ...
290
  }
ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
291
292
293
294
295
  static int arc_timer_dying_cpu(unsigned int cpu)
  {
  	disable_percpu_irq(arc_timer_irq);
  	return 0;
  }
eec3c58ef   Noam Camus   ARC: clockevent: ...
296

d8005e6b9   Vineet Gupta   ARC: Timers/count...
297
  /*
eec3c58ef   Noam Camus   ARC: clockevent: ...
298
   * clockevent setup for boot CPU
d8005e6b9   Vineet Gupta   ARC: Timers/count...
299
   */
43d756049   Daniel Lezcano   clocksource/drive...
300
  static int __init arc_clockevent_setup(struct device_node *node)
d8005e6b9   Vineet Gupta   ARC: Timers/count...
301
  {
2d4899f6b   Vineet Gupta   ARC: arc_local_ti...
302
  	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
eec3c58ef   Noam Camus   ARC: clockevent: ...
303
  	int ret;
d8005e6b9   Vineet Gupta   ARC: Timers/count...
304

77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
305
  	arc_timer_irq = irq_of_parse_and_map(node, 0);
43d756049   Daniel Lezcano   clocksource/drive...
306
  	if (arc_timer_irq <= 0) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
307
308
  		pr_err("clockevent: missing irq
  ");
43d756049   Daniel Lezcano   clocksource/drive...
309
310
  		return -EINVAL;
  	}
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
311
312
  
  	ret = arc_get_timer_clk(node);
311fb70aa   Dejin Zheng   clocksource/drive...
313
  	if (ret)
43d756049   Daniel Lezcano   clocksource/drive...
314
  		return ret;
77c8d0d6b   Vineet Gupta   ARC: clockevent: ...
315

eec3c58ef   Noam Camus   ARC: clockevent: ...
316
317
318
  	/* Needs apriori irq_set_percpu_devid() done in intc map function */
  	ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
  				 "Timer0 (per-cpu-tick)", evt);
43d756049   Daniel Lezcano   clocksource/drive...
319
320
321
322
323
  	if (ret) {
  		pr_err("clockevent: unable to request irq
  ");
  		return ret;
  	}
569579401   Vineet Gupta   ARC: opencode arc...
324

ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
325
  	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
73c1b41e6   Thomas Gleixner   cpu/hotplug: Clea...
326
  				"clockevents/arc/timer:starting",
ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
327
328
329
  				arc_timer_starting_cpu,
  				arc_timer_dying_cpu);
  	if (ret) {
ac9ce6d1a   Rafał Miłecki   clocksource: Add ...
330
331
  		pr_err("Failed to setup hotplug state
  ");
ecd8081f6   Anna-Maria Gleixner   ARC/time: Convert...
332
333
  		return ret;
  	}
43d756049   Daniel Lezcano   clocksource/drive...
334
  	return 0;
d8005e6b9   Vineet Gupta   ARC: Timers/count...
335
  }
e608b53ea   Vineet Gupta   ARC: clocksource:...
336

43d756049   Daniel Lezcano   clocksource/drive...
337
  static int __init arc_of_timer_init(struct device_node *np)
e608b53ea   Vineet Gupta   ARC: clocksource:...
338
339
  {
  	static int init_count = 0;
43d756049   Daniel Lezcano   clocksource/drive...
340
  	int ret;
e608b53ea   Vineet Gupta   ARC: clocksource:...
341
342
343
  
  	if (!init_count) {
  		init_count = 1;
43d756049   Daniel Lezcano   clocksource/drive...
344
  		ret = arc_clockevent_setup(np);
e608b53ea   Vineet Gupta   ARC: clocksource:...
345
  	} else {
43d756049   Daniel Lezcano   clocksource/drive...
346
  		ret = arc_cs_setup_timer1(np);
e608b53ea   Vineet Gupta   ARC: clocksource:...
347
  	}
43d756049   Daniel Lezcano   clocksource/drive...
348
349
  
  	return ret;
e608b53ea   Vineet Gupta   ARC: clocksource:...
350
  }
172733959   Daniel Lezcano   clocksource/drive...
351
  TIMER_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);