xref: /linux/drivers/clocksource/arm_arch_timer_mmio.c (revision 4891f01527bbbb0cf0e515c803ade67a17e247bb)
1*4891f015SMarc Zyngier // SPDX-License-Identifier: GPL-2.0-only
2*4891f015SMarc Zyngier /*
3*4891f015SMarc Zyngier  *  ARM Generic Memory Mapped Timer support
4*4891f015SMarc Zyngier  *
5*4891f015SMarc Zyngier  *  Split from drivers/clocksource/arm_arch_timer.c
6*4891f015SMarc Zyngier  *
7*4891f015SMarc Zyngier  *  Copyright (C) 2011 ARM Ltd.
8*4891f015SMarc Zyngier  *  All Rights Reserved
9*4891f015SMarc Zyngier  */
10*4891f015SMarc Zyngier 
11*4891f015SMarc Zyngier #define pr_fmt(fmt) 	"arch_timer_mmio: " fmt
12*4891f015SMarc Zyngier 
13*4891f015SMarc Zyngier #include <linux/clockchips.h>
14*4891f015SMarc Zyngier #include <linux/interrupt.h>
15*4891f015SMarc Zyngier #include <linux/io-64-nonatomic-lo-hi.h>
16*4891f015SMarc Zyngier #include <linux/of_irq.h>
17*4891f015SMarc Zyngier #include <linux/of_address.h>
18*4891f015SMarc Zyngier #include <linux/platform_device.h>
19*4891f015SMarc Zyngier 
20*4891f015SMarc Zyngier #include <clocksource/arm_arch_timer.h>
21*4891f015SMarc Zyngier 
22*4891f015SMarc Zyngier #define CNTTIDR		0x08
23*4891f015SMarc Zyngier #define CNTTIDR_VIRT(n)	(BIT(1) << ((n) * 4))
24*4891f015SMarc Zyngier 
25*4891f015SMarc Zyngier #define CNTACR(n)	(0x40 + ((n) * 4))
26*4891f015SMarc Zyngier #define CNTACR_RPCT	BIT(0)
27*4891f015SMarc Zyngier #define CNTACR_RVCT	BIT(1)
28*4891f015SMarc Zyngier #define CNTACR_RFRQ	BIT(2)
29*4891f015SMarc Zyngier #define CNTACR_RVOFF	BIT(3)
30*4891f015SMarc Zyngier #define CNTACR_RWVT	BIT(4)
31*4891f015SMarc Zyngier #define CNTACR_RWPT	BIT(5)
32*4891f015SMarc Zyngier 
33*4891f015SMarc Zyngier #define CNTPCT_LO	0x00
34*4891f015SMarc Zyngier #define CNTVCT_LO	0x08
35*4891f015SMarc Zyngier #define CNTFRQ		0x10
36*4891f015SMarc Zyngier #define CNTP_CVAL_LO	0x20
37*4891f015SMarc Zyngier #define CNTP_CTL	0x2c
38*4891f015SMarc Zyngier #define CNTV_CVAL_LO	0x30
39*4891f015SMarc Zyngier #define CNTV_CTL	0x3c
40*4891f015SMarc Zyngier 
41*4891f015SMarc Zyngier enum arch_timer_access {
42*4891f015SMarc Zyngier 	PHYS_ACCESS,
43*4891f015SMarc Zyngier 	VIRT_ACCESS,
44*4891f015SMarc Zyngier };
45*4891f015SMarc Zyngier 
46*4891f015SMarc Zyngier struct arch_timer {
47*4891f015SMarc Zyngier 	struct clock_event_device	evt;
48*4891f015SMarc Zyngier 	struct arch_timer_mem		*gt_block;
49*4891f015SMarc Zyngier 	void __iomem			*base;
50*4891f015SMarc Zyngier 	enum arch_timer_access		access;
51*4891f015SMarc Zyngier 	u32				rate;
52*4891f015SMarc Zyngier };
53*4891f015SMarc Zyngier 
54*4891f015SMarc Zyngier #define evt_to_arch_timer(e) container_of(e, struct arch_timer, evt)
55*4891f015SMarc Zyngier 
56*4891f015SMarc Zyngier static void arch_timer_mmio_write(struct arch_timer *timer,
57*4891f015SMarc Zyngier 				  enum arch_timer_reg reg, u64 val)
58*4891f015SMarc Zyngier {
59*4891f015SMarc Zyngier 	switch (timer->access) {
60*4891f015SMarc Zyngier 	case PHYS_ACCESS:
61*4891f015SMarc Zyngier 		switch (reg) {
62*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
63*4891f015SMarc Zyngier 			writel_relaxed((u32)val, timer->base + CNTP_CTL);
64*4891f015SMarc Zyngier 			return;
65*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CVAL:
66*4891f015SMarc Zyngier 			/*
67*4891f015SMarc Zyngier 			 * Not guaranteed to be atomic, so the timer
68*4891f015SMarc Zyngier 			 * must be disabled at this point.
69*4891f015SMarc Zyngier 			 */
70*4891f015SMarc Zyngier 			writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
71*4891f015SMarc Zyngier 			return;
72*4891f015SMarc Zyngier 		}
73*4891f015SMarc Zyngier 		break;
74*4891f015SMarc Zyngier 	case VIRT_ACCESS:
75*4891f015SMarc Zyngier 		switch (reg) {
76*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
77*4891f015SMarc Zyngier 			writel_relaxed((u32)val, timer->base + CNTV_CTL);
78*4891f015SMarc Zyngier 			return;
79*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CVAL:
80*4891f015SMarc Zyngier 			/* Same restriction as above */
81*4891f015SMarc Zyngier 			writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
82*4891f015SMarc Zyngier 			return;
83*4891f015SMarc Zyngier 		}
84*4891f015SMarc Zyngier 		break;
85*4891f015SMarc Zyngier 	}
86*4891f015SMarc Zyngier 
87*4891f015SMarc Zyngier 	/* Should never be here */
88*4891f015SMarc Zyngier 	WARN_ON_ONCE(1);
89*4891f015SMarc Zyngier }
90*4891f015SMarc Zyngier 
91*4891f015SMarc Zyngier static u32 arch_timer_mmio_read(struct arch_timer *timer, enum arch_timer_reg reg)
92*4891f015SMarc Zyngier {
93*4891f015SMarc Zyngier 	switch (timer->access) {
94*4891f015SMarc Zyngier 	case PHYS_ACCESS:
95*4891f015SMarc Zyngier 		switch (reg) {
96*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
97*4891f015SMarc Zyngier 			return readl_relaxed(timer->base + CNTP_CTL);
98*4891f015SMarc Zyngier 		default:
99*4891f015SMarc Zyngier 			break;
100*4891f015SMarc Zyngier 		}
101*4891f015SMarc Zyngier 		break;
102*4891f015SMarc Zyngier 	case VIRT_ACCESS:
103*4891f015SMarc Zyngier 		switch (reg) {
104*4891f015SMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
105*4891f015SMarc Zyngier 			return readl_relaxed(timer->base + CNTV_CTL);
106*4891f015SMarc Zyngier 		default:
107*4891f015SMarc Zyngier 			break;
108*4891f015SMarc Zyngier 		}
109*4891f015SMarc Zyngier 		break;
110*4891f015SMarc Zyngier 	}
111*4891f015SMarc Zyngier 
112*4891f015SMarc Zyngier 	/* Should never be here */
113*4891f015SMarc Zyngier 	WARN_ON_ONCE(1);
114*4891f015SMarc Zyngier 	return 0;
115*4891f015SMarc Zyngier }
116*4891f015SMarc Zyngier 
117*4891f015SMarc Zyngier static noinstr u64 arch_counter_mmio_get_cnt(struct arch_timer *t)
118*4891f015SMarc Zyngier {
119*4891f015SMarc Zyngier 	int offset_lo = t->access == VIRT_ACCESS ? CNTVCT_LO : CNTPCT_LO;
120*4891f015SMarc Zyngier 	u32 cnt_lo, cnt_hi, tmp_hi;
121*4891f015SMarc Zyngier 
122*4891f015SMarc Zyngier 	do {
123*4891f015SMarc Zyngier 		cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
124*4891f015SMarc Zyngier 		cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));
125*4891f015SMarc Zyngier 		tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
126*4891f015SMarc Zyngier 	} while (cnt_hi != tmp_hi);
127*4891f015SMarc Zyngier 
128*4891f015SMarc Zyngier 	return ((u64) cnt_hi << 32) | cnt_lo;
129*4891f015SMarc Zyngier }
130*4891f015SMarc Zyngier 
131*4891f015SMarc Zyngier static int arch_timer_mmio_shutdown(struct clock_event_device *clk)
132*4891f015SMarc Zyngier {
133*4891f015SMarc Zyngier 	struct arch_timer *at = evt_to_arch_timer(clk);
134*4891f015SMarc Zyngier 	unsigned long ctrl;
135*4891f015SMarc Zyngier 
136*4891f015SMarc Zyngier 	ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);
137*4891f015SMarc Zyngier 	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
138*4891f015SMarc Zyngier 	arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);
139*4891f015SMarc Zyngier 
140*4891f015SMarc Zyngier 	return 0;
141*4891f015SMarc Zyngier }
142*4891f015SMarc Zyngier 
143*4891f015SMarc Zyngier static int arch_timer_mmio_set_next_event(unsigned long evt,
144*4891f015SMarc Zyngier 					  struct clock_event_device *clk)
145*4891f015SMarc Zyngier {
146*4891f015SMarc Zyngier 	struct arch_timer *timer = evt_to_arch_timer(clk);
147*4891f015SMarc Zyngier 	unsigned long ctrl;
148*4891f015SMarc Zyngier 	u64 cnt;
149*4891f015SMarc Zyngier 
150*4891f015SMarc Zyngier 	ctrl = arch_timer_mmio_read(timer, ARCH_TIMER_REG_CTRL);
151*4891f015SMarc Zyngier 
152*4891f015SMarc Zyngier 	/* Timer must be disabled before programming CVAL */
153*4891f015SMarc Zyngier 	if (ctrl & ARCH_TIMER_CTRL_ENABLE) {
154*4891f015SMarc Zyngier 		ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
155*4891f015SMarc Zyngier 		arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);
156*4891f015SMarc Zyngier 	}
157*4891f015SMarc Zyngier 
158*4891f015SMarc Zyngier 	ctrl |= ARCH_TIMER_CTRL_ENABLE;
159*4891f015SMarc Zyngier 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
160*4891f015SMarc Zyngier 
161*4891f015SMarc Zyngier 	cnt = arch_counter_mmio_get_cnt(timer);
162*4891f015SMarc Zyngier 
163*4891f015SMarc Zyngier 	arch_timer_mmio_write(timer, ARCH_TIMER_REG_CVAL, evt + cnt);
164*4891f015SMarc Zyngier 	arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);
165*4891f015SMarc Zyngier 	return 0;
166*4891f015SMarc Zyngier }
167*4891f015SMarc Zyngier 
168*4891f015SMarc Zyngier static irqreturn_t arch_timer_mmio_handler(int irq, void *dev_id)
169*4891f015SMarc Zyngier {
170*4891f015SMarc Zyngier 	struct clock_event_device *evt = dev_id;
171*4891f015SMarc Zyngier 	struct arch_timer *at = evt_to_arch_timer(evt);
172*4891f015SMarc Zyngier 	unsigned long ctrl;
173*4891f015SMarc Zyngier 
174*4891f015SMarc Zyngier 	ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);
175*4891f015SMarc Zyngier 	if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
176*4891f015SMarc Zyngier 		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
177*4891f015SMarc Zyngier 		arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);
178*4891f015SMarc Zyngier 		evt->event_handler(evt);
179*4891f015SMarc Zyngier 		return IRQ_HANDLED;
180*4891f015SMarc Zyngier 	}
181*4891f015SMarc Zyngier 
182*4891f015SMarc Zyngier 	return IRQ_NONE;
183*4891f015SMarc Zyngier }
184*4891f015SMarc Zyngier 
185*4891f015SMarc Zyngier static struct arch_timer_mem_frame *find_best_frame(struct platform_device *pdev)
186*4891f015SMarc Zyngier {
187*4891f015SMarc Zyngier 	struct arch_timer_mem_frame *frame, *best_frame = NULL;
188*4891f015SMarc Zyngier 	struct arch_timer *at = platform_get_drvdata(pdev);
189*4891f015SMarc Zyngier 	void __iomem *cntctlbase;
190*4891f015SMarc Zyngier 	u32 cnttidr;
191*4891f015SMarc Zyngier 
192*4891f015SMarc Zyngier 	cntctlbase = ioremap(at->gt_block->cntctlbase, at->gt_block->size);
193*4891f015SMarc Zyngier 	if (!cntctlbase) {
194*4891f015SMarc Zyngier 		dev_err(&pdev->dev, "Can't map CNTCTLBase @ %pa\n",
195*4891f015SMarc Zyngier 			&at->gt_block->cntctlbase);
196*4891f015SMarc Zyngier 		return NULL;
197*4891f015SMarc Zyngier 	}
198*4891f015SMarc Zyngier 
199*4891f015SMarc Zyngier 	cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
200*4891f015SMarc Zyngier 
201*4891f015SMarc Zyngier 	/*
202*4891f015SMarc Zyngier 	 * Try to find a virtual capable frame. Otherwise fall back to a
203*4891f015SMarc Zyngier 	 * physical capable frame.
204*4891f015SMarc Zyngier 	 */
205*4891f015SMarc Zyngier 	for (int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
206*4891f015SMarc Zyngier 		u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
207*4891f015SMarc Zyngier 			     CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
208*4891f015SMarc Zyngier 
209*4891f015SMarc Zyngier 		frame = &at->gt_block->frame[i];
210*4891f015SMarc Zyngier 		if (!frame->valid)
211*4891f015SMarc Zyngier 			continue;
212*4891f015SMarc Zyngier 
213*4891f015SMarc Zyngier 		/* Try enabling everything, and see what sticks */
214*4891f015SMarc Zyngier 		writel_relaxed(cntacr, cntctlbase + CNTACR(i));
215*4891f015SMarc Zyngier 		cntacr = readl_relaxed(cntctlbase + CNTACR(i));
216*4891f015SMarc Zyngier 
217*4891f015SMarc Zyngier 		/* Pick a suitable frame for which we have an IRQ */
218*4891f015SMarc Zyngier 		if ((cnttidr & CNTTIDR_VIRT(i)) &&
219*4891f015SMarc Zyngier 		    !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT)) &&
220*4891f015SMarc Zyngier 		    frame->virt_irq) {
221*4891f015SMarc Zyngier 			best_frame = frame;
222*4891f015SMarc Zyngier 			at->access = VIRT_ACCESS;
223*4891f015SMarc Zyngier 			break;
224*4891f015SMarc Zyngier 		}
225*4891f015SMarc Zyngier 
226*4891f015SMarc Zyngier 		if ((~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) ||
227*4891f015SMarc Zyngier 		     !frame->phys_irq)
228*4891f015SMarc Zyngier 			continue;
229*4891f015SMarc Zyngier 
230*4891f015SMarc Zyngier 		at->access = PHYS_ACCESS;
231*4891f015SMarc Zyngier 		best_frame = frame;
232*4891f015SMarc Zyngier 	}
233*4891f015SMarc Zyngier 
234*4891f015SMarc Zyngier 	iounmap(cntctlbase);
235*4891f015SMarc Zyngier 
236*4891f015SMarc Zyngier 	return best_frame;
237*4891f015SMarc Zyngier }
238*4891f015SMarc Zyngier 
239*4891f015SMarc Zyngier static void arch_timer_mmio_setup(struct arch_timer *at, int irq)
240*4891f015SMarc Zyngier {
241*4891f015SMarc Zyngier 	at->evt = (struct clock_event_device) {
242*4891f015SMarc Zyngier 		.features		   = (CLOCK_EVT_FEAT_ONESHOT |
243*4891f015SMarc Zyngier 					      CLOCK_EVT_FEAT_DYNIRQ),
244*4891f015SMarc Zyngier 		.name			   = "arch_mem_timer",
245*4891f015SMarc Zyngier 		.rating			   = 400,
246*4891f015SMarc Zyngier 		.cpumask		   = cpu_possible_mask,
247*4891f015SMarc Zyngier 		.irq 			   = irq,
248*4891f015SMarc Zyngier 		.set_next_event		   = arch_timer_mmio_set_next_event,
249*4891f015SMarc Zyngier 		.set_state_oneshot_stopped = arch_timer_mmio_shutdown,
250*4891f015SMarc Zyngier 		.set_state_shutdown	   = arch_timer_mmio_shutdown,
251*4891f015SMarc Zyngier 	};
252*4891f015SMarc Zyngier 
253*4891f015SMarc Zyngier 	at->evt.set_state_shutdown(&at->evt);
254*4891f015SMarc Zyngier 
255*4891f015SMarc Zyngier 	clockevents_config_and_register(&at->evt, at->rate, 0xf,
256*4891f015SMarc Zyngier 					(unsigned long)CLOCKSOURCE_MASK(56));
257*4891f015SMarc Zyngier 
258*4891f015SMarc Zyngier 	enable_irq(at->evt.irq);
259*4891f015SMarc Zyngier }
260*4891f015SMarc Zyngier 
261*4891f015SMarc Zyngier static int arch_timer_mmio_frame_register(struct platform_device *pdev,
262*4891f015SMarc Zyngier 					  struct arch_timer_mem_frame *frame)
263*4891f015SMarc Zyngier {
264*4891f015SMarc Zyngier 	struct arch_timer *at = platform_get_drvdata(pdev);
265*4891f015SMarc Zyngier 	struct device_node *np = pdev->dev.of_node;
266*4891f015SMarc Zyngier 	int ret, irq;
267*4891f015SMarc Zyngier 	u32 rate;
268*4891f015SMarc Zyngier 
269*4891f015SMarc Zyngier 	if (!devm_request_mem_region(&pdev->dev, frame->cntbase, frame->size,
270*4891f015SMarc Zyngier 				     "arch_mem_timer"))
271*4891f015SMarc Zyngier 		return -EBUSY;
272*4891f015SMarc Zyngier 
273*4891f015SMarc Zyngier 	at->base = devm_ioremap(&pdev->dev, frame->cntbase, frame->size);
274*4891f015SMarc Zyngier 	if (!at->base) {
275*4891f015SMarc Zyngier 		dev_err(&pdev->dev, "Can't map frame's registers\n");
276*4891f015SMarc Zyngier 		return -ENXIO;
277*4891f015SMarc Zyngier 	}
278*4891f015SMarc Zyngier 
279*4891f015SMarc Zyngier 	/*
280*4891f015SMarc Zyngier 	 * Allow "clock-frequency" to override the probed rate. If neither
281*4891f015SMarc Zyngier 	 * lead to something useful, use the CPU timer frequency as the
282*4891f015SMarc Zyngier 	 * fallback. The nice thing about that last point is that we woudn't
283*4891f015SMarc Zyngier 	 * made it here if we didn't have a valid frequency.
284*4891f015SMarc Zyngier 	 */
285*4891f015SMarc Zyngier 	rate = readl_relaxed(at->base + CNTFRQ);
286*4891f015SMarc Zyngier 
287*4891f015SMarc Zyngier 	if (!np || of_property_read_u32(np, "clock-frequency", &at->rate))
288*4891f015SMarc Zyngier 		at->rate = rate;
289*4891f015SMarc Zyngier 
290*4891f015SMarc Zyngier 	if (!at->rate)
291*4891f015SMarc Zyngier 		at->rate = arch_timer_get_rate();
292*4891f015SMarc Zyngier 
293*4891f015SMarc Zyngier 	irq = at->access == VIRT_ACCESS ? frame->virt_irq : frame->phys_irq;
294*4891f015SMarc Zyngier 	ret = devm_request_irq(&pdev->dev, irq, arch_timer_mmio_handler,
295*4891f015SMarc Zyngier 			       IRQF_TIMER | IRQF_NO_AUTOEN, "arch_mem_timer",
296*4891f015SMarc Zyngier 			       &at->evt);
297*4891f015SMarc Zyngier 	if (ret) {
298*4891f015SMarc Zyngier 		dev_err(&pdev->dev, "Failed to request mem timer irq\n");
299*4891f015SMarc Zyngier 		return ret;
300*4891f015SMarc Zyngier 	}
301*4891f015SMarc Zyngier 
302*4891f015SMarc Zyngier 	/* Afer this point, we're not allowed to fail anymore */
303*4891f015SMarc Zyngier 	arch_timer_mmio_setup(at, irq);
304*4891f015SMarc Zyngier 	return 0;
305*4891f015SMarc Zyngier }
306*4891f015SMarc Zyngier 
307*4891f015SMarc Zyngier static int of_populate_gt_block(struct platform_device *pdev,
308*4891f015SMarc Zyngier 				struct arch_timer *at)
309*4891f015SMarc Zyngier {
310*4891f015SMarc Zyngier 	struct resource res;
311*4891f015SMarc Zyngier 
312*4891f015SMarc Zyngier 	if (of_address_to_resource(pdev->dev.of_node, 0, &res))
313*4891f015SMarc Zyngier 		return -EINVAL;
314*4891f015SMarc Zyngier 
315*4891f015SMarc Zyngier 	at->gt_block->cntctlbase = res.start;
316*4891f015SMarc Zyngier 	at->gt_block->size = resource_size(&res);
317*4891f015SMarc Zyngier 
318*4891f015SMarc Zyngier 	for_each_available_child_of_node_scoped(pdev->dev.of_node, frame_node) {
319*4891f015SMarc Zyngier 		struct arch_timer_mem_frame *frame;
320*4891f015SMarc Zyngier 		u32 n;
321*4891f015SMarc Zyngier 
322*4891f015SMarc Zyngier 		if (of_property_read_u32(frame_node, "frame-number", &n)) {
323*4891f015SMarc Zyngier 			dev_err(&pdev->dev, FW_BUG "Missing frame-number\n");
324*4891f015SMarc Zyngier 			return -EINVAL;
325*4891f015SMarc Zyngier 		}
326*4891f015SMarc Zyngier 		if (n >= ARCH_TIMER_MEM_MAX_FRAMES) {
327*4891f015SMarc Zyngier 			dev_err(&pdev->dev,
328*4891f015SMarc Zyngier 				FW_BUG "Wrong frame-number, only 0-%u are permitted\n",
329*4891f015SMarc Zyngier 			       ARCH_TIMER_MEM_MAX_FRAMES - 1);
330*4891f015SMarc Zyngier 			return -EINVAL;
331*4891f015SMarc Zyngier 		}
332*4891f015SMarc Zyngier 
333*4891f015SMarc Zyngier 		frame = &at->gt_block->frame[n];
334*4891f015SMarc Zyngier 
335*4891f015SMarc Zyngier 		if (frame->valid) {
336*4891f015SMarc Zyngier 			dev_err(&pdev->dev, FW_BUG "Duplicated frame-number\n");
337*4891f015SMarc Zyngier 			return -EINVAL;
338*4891f015SMarc Zyngier 		}
339*4891f015SMarc Zyngier 
340*4891f015SMarc Zyngier 		if (of_address_to_resource(frame_node, 0, &res))
341*4891f015SMarc Zyngier 			return -EINVAL;
342*4891f015SMarc Zyngier 
343*4891f015SMarc Zyngier 		frame->cntbase = res.start;
344*4891f015SMarc Zyngier 		frame->size = resource_size(&res);
345*4891f015SMarc Zyngier 
346*4891f015SMarc Zyngier 		frame->phys_irq = irq_of_parse_and_map(frame_node, 0);
347*4891f015SMarc Zyngier 		frame->virt_irq = irq_of_parse_and_map(frame_node, 1);
348*4891f015SMarc Zyngier 
349*4891f015SMarc Zyngier 		frame->valid = true;
350*4891f015SMarc Zyngier 	}
351*4891f015SMarc Zyngier 
352*4891f015SMarc Zyngier 	return 0;
353*4891f015SMarc Zyngier }
354*4891f015SMarc Zyngier 
355*4891f015SMarc Zyngier static int arch_timer_mmio_probe(struct platform_device *pdev)
356*4891f015SMarc Zyngier {
357*4891f015SMarc Zyngier 	struct arch_timer_mem_frame *frame;
358*4891f015SMarc Zyngier 	struct arch_timer *at;
359*4891f015SMarc Zyngier 	struct device_node *np;
360*4891f015SMarc Zyngier 	int ret;
361*4891f015SMarc Zyngier 
362*4891f015SMarc Zyngier 	np = pdev->dev.of_node;
363*4891f015SMarc Zyngier 
364*4891f015SMarc Zyngier 	at = devm_kmalloc(&pdev->dev, sizeof(*at), GFP_KERNEL | __GFP_ZERO);
365*4891f015SMarc Zyngier 	if (!at)
366*4891f015SMarc Zyngier 		return -ENOMEM;
367*4891f015SMarc Zyngier 
368*4891f015SMarc Zyngier 	if (np) {
369*4891f015SMarc Zyngier 		at->gt_block = devm_kmalloc(&pdev->dev, sizeof(*at->gt_block),
370*4891f015SMarc Zyngier 					    GFP_KERNEL | __GFP_ZERO);
371*4891f015SMarc Zyngier 		if (!at->gt_block)
372*4891f015SMarc Zyngier 			return -ENOMEM;
373*4891f015SMarc Zyngier 		ret = of_populate_gt_block(pdev, at);
374*4891f015SMarc Zyngier 		if (ret)
375*4891f015SMarc Zyngier 			return ret;
376*4891f015SMarc Zyngier 	} else {
377*4891f015SMarc Zyngier 		at->gt_block = dev_get_platdata(&pdev->dev);
378*4891f015SMarc Zyngier 	}
379*4891f015SMarc Zyngier 
380*4891f015SMarc Zyngier 	platform_set_drvdata(pdev, at);
381*4891f015SMarc Zyngier 
382*4891f015SMarc Zyngier 	frame = find_best_frame(pdev);
383*4891f015SMarc Zyngier 	if (!frame) {
384*4891f015SMarc Zyngier 		dev_err(&pdev->dev,
385*4891f015SMarc Zyngier 			"Unable to find a suitable frame in timer @ %pa\n",
386*4891f015SMarc Zyngier 			&at->gt_block->cntctlbase);
387*4891f015SMarc Zyngier 		return -EINVAL;
388*4891f015SMarc Zyngier 	}
389*4891f015SMarc Zyngier 
390*4891f015SMarc Zyngier 	ret = arch_timer_mmio_frame_register(pdev, frame);
391*4891f015SMarc Zyngier 	if (!ret)
392*4891f015SMarc Zyngier 		dev_info(&pdev->dev,
393*4891f015SMarc Zyngier 			 "mmio timer running at %lu.%02luMHz (%s)\n",
394*4891f015SMarc Zyngier 			 (unsigned long)at->rate / 1000000,
395*4891f015SMarc Zyngier 			 (unsigned long)(at->rate / 10000) % 100,
396*4891f015SMarc Zyngier 			 at->access == VIRT_ACCESS ? "virt" : "phys");
397*4891f015SMarc Zyngier 
398*4891f015SMarc Zyngier 	return ret;
399*4891f015SMarc Zyngier }
400*4891f015SMarc Zyngier 
401*4891f015SMarc Zyngier static const struct of_device_id arch_timer_mmio_of_table[] = {
402*4891f015SMarc Zyngier 	{ .compatible = "arm,armv7-timer-mem", },
403*4891f015SMarc Zyngier 	{}
404*4891f015SMarc Zyngier };
405*4891f015SMarc Zyngier 
406*4891f015SMarc Zyngier static struct platform_driver arch_timer_mmio_drv = {
407*4891f015SMarc Zyngier 	.driver	= {
408*4891f015SMarc Zyngier 		.name = "arch-timer-mmio",
409*4891f015SMarc Zyngier 		.of_match_table	= arch_timer_mmio_of_table,
410*4891f015SMarc Zyngier 	},
411*4891f015SMarc Zyngier 	.probe	= arch_timer_mmio_probe,
412*4891f015SMarc Zyngier };
413*4891f015SMarc Zyngier builtin_platform_driver(arch_timer_mmio_drv);
414*4891f015SMarc Zyngier 
415*4891f015SMarc Zyngier static struct platform_driver arch_timer_mmio_acpi_drv = {
416*4891f015SMarc Zyngier 	.driver	= {
417*4891f015SMarc Zyngier 		.name = "gtdt-arm-mmio-timer",
418*4891f015SMarc Zyngier 	},
419*4891f015SMarc Zyngier 	.probe	= arch_timer_mmio_probe,
420*4891f015SMarc Zyngier };
421*4891f015SMarc Zyngier builtin_platform_driver(arch_timer_mmio_acpi_drv);
422