1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013 Pengutronix
4  * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
5  */
6 
7 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
8 
9 #include <linux/kernel.h>
10 #include <linux/clocksource.h>
11 #include <linux/clockchips.h>
12 #include <linux/irq.h>
13 #include <linux/interrupt.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
17 #include <linux/clk.h>
18 
19 #define TIMERn_CTRL			0x00
20 #define TIMERn_CTRL_PRESC(val)			(((val) & 0xf) << 24)
21 #define TIMERn_CTRL_PRESC_1024			TIMERn_CTRL_PRESC(10)
22 #define TIMERn_CTRL_CLKSEL(val)			(((val) & 0x3) << 16)
23 #define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK	TIMERn_CTRL_CLKSEL(0)
24 #define TIMERn_CTRL_OSMEN			0x00000010
25 #define TIMERn_CTRL_MODE(val)			(((val) & 0x3) <<  0)
26 #define TIMERn_CTRL_MODE_UP			TIMERn_CTRL_MODE(0)
27 #define TIMERn_CTRL_MODE_DOWN			TIMERn_CTRL_MODE(1)
28 
29 #define TIMERn_CMD			0x04
30 #define TIMERn_CMD_START			0x00000001
31 #define TIMERn_CMD_STOP				0x00000002
32 
33 #define TIMERn_IEN			0x0c
34 #define TIMERn_IF			0x10
35 #define TIMERn_IFS			0x14
36 #define TIMERn_IFC			0x18
37 #define TIMERn_IRQ_UF				0x00000002
38 
39 #define TIMERn_TOP			0x1c
40 #define TIMERn_CNT			0x24
41 
42 struct efm32_clock_event_ddata {
43 	struct clock_event_device evtdev;
44 	void __iomem *base;
45 	unsigned periodic_top;
46 };
47 
efm32_clock_event_shutdown(struct clock_event_device * evtdev)48 static int efm32_clock_event_shutdown(struct clock_event_device *evtdev)
49 {
50 	struct efm32_clock_event_ddata *ddata =
51 		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
52 
53 	writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
54 	return 0;
55 }
56 
efm32_clock_event_set_oneshot(struct clock_event_device * evtdev)57 static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev)
58 {
59 	struct efm32_clock_event_ddata *ddata =
60 		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
61 
62 	writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
63 	writel_relaxed(TIMERn_CTRL_PRESC_1024 |
64 		       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
65 		       TIMERn_CTRL_OSMEN |
66 		       TIMERn_CTRL_MODE_DOWN,
67 		       ddata->base + TIMERn_CTRL);
68 	return 0;
69 }
70 
efm32_clock_event_set_periodic(struct clock_event_device * evtdev)71 static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev)
72 {
73 	struct efm32_clock_event_ddata *ddata =
74 		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
75 
76 	writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
77 	writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP);
78 	writel_relaxed(TIMERn_CTRL_PRESC_1024 |
79 		       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
80 		       TIMERn_CTRL_MODE_DOWN,
81 		       ddata->base + TIMERn_CTRL);
82 	writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
83 	return 0;
84 }
85 
efm32_clock_event_set_next_event(unsigned long evt,struct clock_event_device * evtdev)86 static int efm32_clock_event_set_next_event(unsigned long evt,
87 					    struct clock_event_device *evtdev)
88 {
89 	struct efm32_clock_event_ddata *ddata =
90 		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
91 
92 	writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
93 	writel_relaxed(evt, ddata->base + TIMERn_CNT);
94 	writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
95 
96 	return 0;
97 }
98 
efm32_clock_event_handler(int irq,void * dev_id)99 static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id)
100 {
101 	struct efm32_clock_event_ddata *ddata = dev_id;
102 
103 	writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC);
104 
105 	ddata->evtdev.event_handler(&ddata->evtdev);
106 
107 	return IRQ_HANDLED;
108 }
109 
110 static struct efm32_clock_event_ddata clock_event_ddata = {
111 	.evtdev = {
112 		.name = "efm32 clockevent",
113 		.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
114 		.set_state_shutdown = efm32_clock_event_shutdown,
115 		.set_state_periodic = efm32_clock_event_set_periodic,
116 		.set_state_oneshot = efm32_clock_event_set_oneshot,
117 		.set_next_event = efm32_clock_event_set_next_event,
118 		.rating = 200,
119 	},
120 };
121 
efm32_clocksource_init(struct device_node * np)122 static int __init efm32_clocksource_init(struct device_node *np)
123 {
124 	struct clk *clk;
125 	void __iomem *base;
126 	unsigned long rate;
127 	int ret;
128 
129 	clk = of_clk_get(np, 0);
130 	if (IS_ERR(clk)) {
131 		ret = PTR_ERR(clk);
132 		pr_err("failed to get clock for clocksource (%d)\n", ret);
133 		goto err_clk_get;
134 	}
135 
136 	ret = clk_prepare_enable(clk);
137 	if (ret) {
138 		pr_err("failed to enable timer clock for clocksource (%d)\n",
139 		       ret);
140 		goto err_clk_enable;
141 	}
142 	rate = clk_get_rate(clk);
143 
144 	base = of_iomap(np, 0);
145 	if (!base) {
146 		ret = -EADDRNOTAVAIL;
147 		pr_err("failed to map registers for clocksource\n");
148 		goto err_iomap;
149 	}
150 
151 	writel_relaxed(TIMERn_CTRL_PRESC_1024 |
152 		       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
153 		       TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL);
154 	writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD);
155 
156 	ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer",
157 				    DIV_ROUND_CLOSEST(rate, 1024), 200, 16,
158 				    clocksource_mmio_readl_up);
159 	if (ret) {
160 		pr_err("failed to init clocksource (%d)\n", ret);
161 		goto err_clocksource_init;
162 	}
163 
164 	return 0;
165 
166 err_clocksource_init:
167 
168 	iounmap(base);
169 err_iomap:
170 
171 	clk_disable_unprepare(clk);
172 err_clk_enable:
173 
174 	clk_put(clk);
175 err_clk_get:
176 
177 	return ret;
178 }
179 
efm32_clockevent_init(struct device_node * np)180 static int __init efm32_clockevent_init(struct device_node *np)
181 {
182 	struct clk *clk;
183 	void __iomem *base;
184 	unsigned long rate;
185 	int irq;
186 	int ret;
187 
188 	clk = of_clk_get(np, 0);
189 	if (IS_ERR(clk)) {
190 		ret = PTR_ERR(clk);
191 		pr_err("failed to get clock for clockevent (%d)\n", ret);
192 		goto err_clk_get;
193 	}
194 
195 	ret = clk_prepare_enable(clk);
196 	if (ret) {
197 		pr_err("failed to enable timer clock for clockevent (%d)\n",
198 		       ret);
199 		goto err_clk_enable;
200 	}
201 	rate = clk_get_rate(clk);
202 
203 	base = of_iomap(np, 0);
204 	if (!base) {
205 		ret = -EADDRNOTAVAIL;
206 		pr_err("failed to map registers for clockevent\n");
207 		goto err_iomap;
208 	}
209 
210 	irq = irq_of_parse_and_map(np, 0);
211 	if (!irq) {
212 		ret = -ENOENT;
213 		pr_err("failed to get irq for clockevent\n");
214 		goto err_get_irq;
215 	}
216 
217 	writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN);
218 
219 	clock_event_ddata.base = base;
220 	clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ);
221 
222 	clockevents_config_and_register(&clock_event_ddata.evtdev,
223 					DIV_ROUND_CLOSEST(rate, 1024),
224 					0xf, 0xffff);
225 
226 	ret = request_irq(irq, efm32_clock_event_handler, IRQF_TIMER,
227 			  "efm32 clockevent", &clock_event_ddata);
228 	if (ret) {
229 		pr_err("Failed setup irq\n");
230 		goto err_setup_irq;
231 	}
232 
233 	return 0;
234 
235 err_setup_irq:
236 err_get_irq:
237 
238 	iounmap(base);
239 err_iomap:
240 
241 	clk_disable_unprepare(clk);
242 err_clk_enable:
243 
244 	clk_put(clk);
245 err_clk_get:
246 
247 	return ret;
248 }
249 
250 /*
251  * This function asserts that we have exactly one clocksource and one
252  * clock_event_device in the end.
253  */
efm32_timer_init(struct device_node * np)254 static int __init efm32_timer_init(struct device_node *np)
255 {
256 	static int has_clocksource, has_clockevent;
257 	int ret = 0;
258 
259 	if (!has_clocksource) {
260 		ret = efm32_clocksource_init(np);
261 		if (!ret) {
262 			has_clocksource = 1;
263 			return 0;
264 		}
265 	}
266 
267 	if (!has_clockevent) {
268 		ret = efm32_clockevent_init(np);
269 		if (!ret) {
270 			has_clockevent = 1;
271 			return 0;
272 		}
273 	}
274 
275 	return ret;
276 }
277 TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
278 TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
279