xref: /OK3568_Linux_fs/kernel/arch/mips/ralink/cevt-rt3352.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * This file is subject to the terms and conditions of the GNU General Public
3*4882a593Smuzhiyun  * License.  See the file "COPYING" in the main directory of this archive
4*4882a593Smuzhiyun  * for more details.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2013 by John Crispin <john@phrozen.org>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/clockchips.h>
10*4882a593Smuzhiyun #include <linux/clocksource.h>
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/reset.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/time.h>
15*4882a593Smuzhiyun #include <linux/of.h>
16*4882a593Smuzhiyun #include <linux/of_irq.h>
17*4882a593Smuzhiyun #include <linux/of_address.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <asm/mach-ralink/ralink_regs.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define SYSTICK_FREQ		(50 * 1000)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define SYSTICK_CONFIG		0x00
24*4882a593Smuzhiyun #define SYSTICK_COMPARE		0x04
25*4882a593Smuzhiyun #define SYSTICK_COUNT		0x08
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* route systick irq to mips irq 7 instead of the r4k-timer */
28*4882a593Smuzhiyun #define CFG_EXT_STK_EN		0x2
29*4882a593Smuzhiyun /* enable the counter */
30*4882a593Smuzhiyun #define CFG_CNT_EN		0x1
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun struct systick_device {
33*4882a593Smuzhiyun 	void __iomem *membase;
34*4882a593Smuzhiyun 	struct clock_event_device dev;
35*4882a593Smuzhiyun 	int irq_requested;
36*4882a593Smuzhiyun 	int freq_scale;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun static int systick_set_oneshot(struct clock_event_device *evt);
40*4882a593Smuzhiyun static int systick_shutdown(struct clock_event_device *evt);
41*4882a593Smuzhiyun 
systick_next_event(unsigned long delta,struct clock_event_device * evt)42*4882a593Smuzhiyun static int systick_next_event(unsigned long delta,
43*4882a593Smuzhiyun 				struct clock_event_device *evt)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	struct systick_device *sdev;
46*4882a593Smuzhiyun 	u32 count;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	sdev = container_of(evt, struct systick_device, dev);
49*4882a593Smuzhiyun 	count = ioread32(sdev->membase + SYSTICK_COUNT);
50*4882a593Smuzhiyun 	count = (count + delta) % SYSTICK_FREQ;
51*4882a593Smuzhiyun 	iowrite32(count, sdev->membase + SYSTICK_COMPARE);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	return 0;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
systick_event_handler(struct clock_event_device * dev)56*4882a593Smuzhiyun static void systick_event_handler(struct clock_event_device *dev)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	/* noting to do here */
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
systick_interrupt(int irq,void * dev_id)61*4882a593Smuzhiyun static irqreturn_t systick_interrupt(int irq, void *dev_id)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	struct clock_event_device *dev = (struct clock_event_device *) dev_id;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	dev->event_handler(dev);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	return IRQ_HANDLED;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static struct systick_device systick = {
71*4882a593Smuzhiyun 	.dev = {
72*4882a593Smuzhiyun 		/*
73*4882a593Smuzhiyun 		 * cevt-r4k uses 300, make sure systick
74*4882a593Smuzhiyun 		 * gets used if available
75*4882a593Smuzhiyun 		 */
76*4882a593Smuzhiyun 		.rating			= 310,
77*4882a593Smuzhiyun 		.features		= CLOCK_EVT_FEAT_ONESHOT,
78*4882a593Smuzhiyun 		.set_next_event		= systick_next_event,
79*4882a593Smuzhiyun 		.set_state_shutdown	= systick_shutdown,
80*4882a593Smuzhiyun 		.set_state_oneshot	= systick_set_oneshot,
81*4882a593Smuzhiyun 		.event_handler		= systick_event_handler,
82*4882a593Smuzhiyun 	},
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun 
systick_shutdown(struct clock_event_device * evt)85*4882a593Smuzhiyun static int systick_shutdown(struct clock_event_device *evt)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	struct systick_device *sdev;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	sdev = container_of(evt, struct systick_device, dev);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (sdev->irq_requested)
92*4882a593Smuzhiyun 		free_irq(systick.dev.irq, &systick.dev);
93*4882a593Smuzhiyun 	sdev->irq_requested = 0;
94*4882a593Smuzhiyun 	iowrite32(0, systick.membase + SYSTICK_CONFIG);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	return 0;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
systick_set_oneshot(struct clock_event_device * evt)99*4882a593Smuzhiyun static int systick_set_oneshot(struct clock_event_device *evt)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	const char *name = systick.dev.name;
102*4882a593Smuzhiyun 	struct systick_device *sdev;
103*4882a593Smuzhiyun 	int irq = systick.dev.irq;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	sdev = container_of(evt, struct systick_device, dev);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (!sdev->irq_requested) {
108*4882a593Smuzhiyun 		if (request_irq(irq, systick_interrupt,
109*4882a593Smuzhiyun 				IRQF_PERCPU | IRQF_TIMER, name, &systick.dev))
110*4882a593Smuzhiyun 			pr_err("Failed to request irq %d (%s)\n", irq, name);
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	sdev->irq_requested = 1;
113*4882a593Smuzhiyun 	iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
114*4882a593Smuzhiyun 		  systick.membase + SYSTICK_CONFIG);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
ralink_systick_init(struct device_node * np)119*4882a593Smuzhiyun static int __init ralink_systick_init(struct device_node *np)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	int ret;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	systick.membase = of_iomap(np, 0);
124*4882a593Smuzhiyun 	if (!systick.membase)
125*4882a593Smuzhiyun 		return -ENXIO;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	systick.dev.name = np->name;
128*4882a593Smuzhiyun 	clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
129*4882a593Smuzhiyun 	systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
130*4882a593Smuzhiyun 	systick.dev.max_delta_ticks = 0x7fff;
131*4882a593Smuzhiyun 	systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
132*4882a593Smuzhiyun 	systick.dev.min_delta_ticks = 0x3;
133*4882a593Smuzhiyun 	systick.dev.irq = irq_of_parse_and_map(np, 0);
134*4882a593Smuzhiyun 	if (!systick.dev.irq) {
135*4882a593Smuzhiyun 		pr_err("%pOFn: request_irq failed", np);
136*4882a593Smuzhiyun 		return -EINVAL;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
140*4882a593Smuzhiyun 				    SYSTICK_FREQ, 301, 16,
141*4882a593Smuzhiyun 				    clocksource_mmio_readl_up);
142*4882a593Smuzhiyun 	if (ret)
143*4882a593Smuzhiyun 		return ret;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	clockevents_register_device(&systick.dev);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	pr_info("%pOFn: running - mult: %d, shift: %d\n",
148*4882a593Smuzhiyun 			np, systick.dev.mult, systick.dev.shift);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
154