1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * An RTC driver for Allwinner A31/A23 |
4 | * |
5 | * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org> |
6 | * |
7 | * based on rtc-sunxi.c |
8 | * |
9 | * An RTC driver for Allwinner A10/A20 |
10 | * |
11 | * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com> |
12 | */ |
13 | |
14 | #include <linux/clk.h> |
15 | #include <linux/clk-provider.h> |
16 | #include <linux/clk/sunxi-ng.h> |
17 | #include <linux/delay.h> |
18 | #include <linux/err.h> |
19 | #include <linux/fs.h> |
20 | #include <linux/init.h> |
21 | #include <linux/interrupt.h> |
22 | #include <linux/io.h> |
23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> |
25 | #include <linux/of.h> |
26 | #include <linux/of_address.h> |
27 | #include <linux/platform_device.h> |
28 | #include <linux/rtc.h> |
29 | #include <linux/slab.h> |
30 | #include <linux/types.h> |
31 | |
32 | /* Control register */ |
33 | #define SUN6I_LOSC_CTRL 0x0000 |
34 | #define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) |
35 | #define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS BIT(15) |
36 | #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) |
37 | #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) |
38 | #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) |
39 | #define SUN6I_LOSC_CTRL_EXT_LOSC_EN BIT(4) |
40 | #define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) |
41 | #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) |
42 | |
43 | #define SUN6I_LOSC_CLK_PRESCAL 0x0008 |
44 | |
45 | /* RTC */ |
46 | #define SUN6I_RTC_YMD 0x0010 |
47 | #define SUN6I_RTC_HMS 0x0014 |
48 | |
49 | /* Alarm 0 (counter) */ |
50 | #define SUN6I_ALRM_COUNTER 0x0020 |
51 | /* This holds the remaining alarm seconds on older SoCs (current value) */ |
52 | #define SUN6I_ALRM_COUNTER_HMS 0x0024 |
53 | #define SUN6I_ALRM_EN 0x0028 |
54 | #define SUN6I_ALRM_EN_CNT_EN BIT(0) |
55 | #define SUN6I_ALRM_IRQ_EN 0x002c |
56 | #define SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) |
57 | #define SUN6I_ALRM_IRQ_STA 0x0030 |
58 | #define SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) |
59 | |
60 | /* Alarm 1 (wall clock) */ |
61 | #define SUN6I_ALRM1_EN 0x0044 |
62 | #define SUN6I_ALRM1_IRQ_EN 0x0048 |
63 | #define SUN6I_ALRM1_IRQ_STA 0x004c |
64 | #define SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND BIT(0) |
65 | |
66 | /* Alarm config */ |
67 | #define SUN6I_ALARM_CONFIG 0x0050 |
68 | #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) |
69 | |
70 | #define SUN6I_LOSC_OUT_GATING 0x0060 |
71 | #define SUN6I_LOSC_OUT_GATING_EN_OFFSET 0 |
72 | |
73 | /* General-purpose data */ |
74 | #define SUN6I_GP_DATA 0x0100 |
75 | #define SUN6I_GP_DATA_SIZE 0x20 |
76 | |
77 | /* |
78 | * Get date values |
79 | */ |
80 | #define SUN6I_DATE_GET_DAY_VALUE(x) ((x) & 0x0000001f) |
81 | #define SUN6I_DATE_GET_MON_VALUE(x) (((x) & 0x00000f00) >> 8) |
82 | #define SUN6I_DATE_GET_YEAR_VALUE(x) (((x) & 0x003f0000) >> 16) |
83 | #define SUN6I_LEAP_GET_VALUE(x) (((x) & 0x00400000) >> 22) |
84 | |
85 | /* |
86 | * Get time values |
87 | */ |
88 | #define SUN6I_TIME_GET_SEC_VALUE(x) ((x) & 0x0000003f) |
89 | #define SUN6I_TIME_GET_MIN_VALUE(x) (((x) & 0x00003f00) >> 8) |
90 | #define SUN6I_TIME_GET_HOUR_VALUE(x) (((x) & 0x001f0000) >> 16) |
91 | |
92 | /* |
93 | * Set date values |
94 | */ |
95 | #define SUN6I_DATE_SET_DAY_VALUE(x) ((x) & 0x0000001f) |
96 | #define SUN6I_DATE_SET_MON_VALUE(x) ((x) << 8 & 0x00000f00) |
97 | #define SUN6I_DATE_SET_YEAR_VALUE(x) ((x) << 16 & 0x003f0000) |
98 | #define SUN6I_LEAP_SET_VALUE(x) ((x) << 22 & 0x00400000) |
99 | |
100 | /* |
101 | * Set time values |
102 | */ |
103 | #define SUN6I_TIME_SET_SEC_VALUE(x) ((x) & 0x0000003f) |
104 | #define SUN6I_TIME_SET_MIN_VALUE(x) ((x) << 8 & 0x00003f00) |
105 | #define SUN6I_TIME_SET_HOUR_VALUE(x) ((x) << 16 & 0x001f0000) |
106 | |
107 | /* |
108 | * The year parameter passed to the driver is usually an offset relative to |
109 | * the year 1900. This macro is used to convert this offset to another one |
110 | * relative to the minimum year allowed by the hardware. |
111 | * |
112 | * The year range is 1970 - 2033. This range is selected to match Allwinner's |
113 | * driver, even though it is somewhat limited. |
114 | */ |
115 | #define SUN6I_YEAR_MIN 1970 |
116 | #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) |
117 | |
118 | #define SECS_PER_DAY (24 * 3600ULL) |
119 | |
120 | /* |
121 | * There are other differences between models, including: |
122 | * |
123 | * - number of GPIO pins that can be configured to hold a certain level |
124 | * - crypto-key related registers (H5, H6) |
125 | * - boot process related (super standby, secondary processor entry address) |
126 | * registers (R40, H6) |
127 | * - SYS power domain controls (R40) |
128 | * - DCXO controls (H6) |
129 | * - RC oscillator calibration (H6) |
130 | * |
131 | * These functions are not covered by this driver. |
132 | */ |
133 | struct sun6i_rtc_clk_data { |
134 | unsigned long rc_osc_rate; |
135 | unsigned int fixed_prescaler : 16; |
136 | unsigned int has_prescaler : 1; |
137 | unsigned int has_out_clk : 1; |
138 | unsigned int has_losc_en : 1; |
139 | unsigned int has_auto_swt : 1; |
140 | }; |
141 | |
142 | #define RTC_LINEAR_DAY BIT(0) |
143 | |
144 | struct sun6i_rtc_dev { |
145 | struct rtc_device *rtc; |
146 | const struct sun6i_rtc_clk_data *data; |
147 | void __iomem *base; |
148 | int irq; |
149 | time64_t alarm; |
150 | unsigned long flags; |
151 | |
152 | struct clk_hw hw; |
153 | struct clk_hw *int_osc; |
154 | struct clk *losc; |
155 | struct clk *ext_losc; |
156 | |
157 | spinlock_t lock; |
158 | }; |
159 | |
160 | static struct sun6i_rtc_dev *sun6i_rtc; |
161 | |
162 | static unsigned long sun6i_rtc_osc_recalc_rate(struct clk_hw *hw, |
163 | unsigned long parent_rate) |
164 | { |
165 | struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); |
166 | u32 val = 0; |
167 | |
168 | val = readl(addr: rtc->base + SUN6I_LOSC_CTRL); |
169 | if (val & SUN6I_LOSC_CTRL_EXT_OSC) |
170 | return parent_rate; |
171 | |
172 | if (rtc->data->fixed_prescaler) |
173 | parent_rate /= rtc->data->fixed_prescaler; |
174 | |
175 | if (rtc->data->has_prescaler) { |
176 | val = readl(addr: rtc->base + SUN6I_LOSC_CLK_PRESCAL); |
177 | val &= GENMASK(4, 0); |
178 | } |
179 | |
180 | return parent_rate / (val + 1); |
181 | } |
182 | |
183 | static u8 sun6i_rtc_osc_get_parent(struct clk_hw *hw) |
184 | { |
185 | struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); |
186 | |
187 | return readl(addr: rtc->base + SUN6I_LOSC_CTRL) & SUN6I_LOSC_CTRL_EXT_OSC; |
188 | } |
189 | |
190 | static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index) |
191 | { |
192 | struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); |
193 | unsigned long flags; |
194 | u32 val; |
195 | |
196 | if (index > 1) |
197 | return -EINVAL; |
198 | |
199 | spin_lock_irqsave(&rtc->lock, flags); |
200 | val = readl(addr: rtc->base + SUN6I_LOSC_CTRL); |
201 | val &= ~SUN6I_LOSC_CTRL_EXT_OSC; |
202 | val |= SUN6I_LOSC_CTRL_KEY; |
203 | val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0; |
204 | if (rtc->data->has_losc_en) { |
205 | val &= ~SUN6I_LOSC_CTRL_EXT_LOSC_EN; |
206 | val |= index ? SUN6I_LOSC_CTRL_EXT_LOSC_EN : 0; |
207 | } |
208 | writel(val, addr: rtc->base + SUN6I_LOSC_CTRL); |
209 | spin_unlock_irqrestore(lock: &rtc->lock, flags); |
210 | |
211 | return 0; |
212 | } |
213 | |
214 | static const struct clk_ops sun6i_rtc_osc_ops = { |
215 | .recalc_rate = sun6i_rtc_osc_recalc_rate, |
216 | .determine_rate = clk_hw_determine_rate_no_reparent, |
217 | |
218 | .get_parent = sun6i_rtc_osc_get_parent, |
219 | .set_parent = sun6i_rtc_osc_set_parent, |
220 | }; |
221 | |
222 | static void __init sun6i_rtc_clk_init(struct device_node *node, |
223 | const struct sun6i_rtc_clk_data *data) |
224 | { |
225 | struct clk_hw_onecell_data *clk_data; |
226 | struct sun6i_rtc_dev *rtc; |
227 | struct clk_init_data init = { |
228 | .ops = &sun6i_rtc_osc_ops, |
229 | .name = "losc" , |
230 | }; |
231 | const char *iosc_name = "rtc-int-osc" ; |
232 | const char *clkout_name = "osc32k-out" ; |
233 | const char *parents[2]; |
234 | u32 reg; |
235 | |
236 | rtc = kzalloc(size: sizeof(*rtc), GFP_KERNEL); |
237 | if (!rtc) |
238 | return; |
239 | |
240 | rtc->data = data; |
241 | clk_data = kzalloc(struct_size(clk_data, hws, 3), GFP_KERNEL); |
242 | if (!clk_data) { |
243 | kfree(objp: rtc); |
244 | return; |
245 | } |
246 | |
247 | spin_lock_init(&rtc->lock); |
248 | |
249 | rtc->base = of_io_request_and_map(device: node, index: 0, name: of_node_full_name(np: node)); |
250 | if (IS_ERR(ptr: rtc->base)) { |
251 | pr_crit("Can't map RTC registers" ); |
252 | goto err; |
253 | } |
254 | |
255 | reg = SUN6I_LOSC_CTRL_KEY; |
256 | if (rtc->data->has_auto_swt) { |
257 | /* Bypass auto-switch to int osc, on ext losc failure */ |
258 | reg |= SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS; |
259 | writel(val: reg, addr: rtc->base + SUN6I_LOSC_CTRL); |
260 | } |
261 | |
262 | /* Switch to the external, more precise, oscillator, if present */ |
263 | if (of_property_present(np: node, propname: "clocks" )) { |
264 | reg |= SUN6I_LOSC_CTRL_EXT_OSC; |
265 | if (rtc->data->has_losc_en) |
266 | reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; |
267 | } |
268 | writel(val: reg, addr: rtc->base + SUN6I_LOSC_CTRL); |
269 | |
270 | /* Yes, I know, this is ugly. */ |
271 | sun6i_rtc = rtc; |
272 | |
273 | of_property_read_string_index(np: node, propname: "clock-output-names" , index: 2, |
274 | output: &iosc_name); |
275 | |
276 | rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, |
277 | iosc_name, |
278 | NULL, 0, |
279 | rtc->data->rc_osc_rate, |
280 | 300000000); |
281 | if (IS_ERR(ptr: rtc->int_osc)) { |
282 | pr_crit("Couldn't register the internal oscillator\n" ); |
283 | goto err; |
284 | } |
285 | |
286 | parents[0] = clk_hw_get_name(hw: rtc->int_osc); |
287 | /* If there is no external oscillator, this will be NULL and ... */ |
288 | parents[1] = of_clk_get_parent_name(np: node, index: 0); |
289 | |
290 | rtc->hw.init = &init; |
291 | |
292 | init.parent_names = parents; |
293 | /* ... number of clock parents will be 1. */ |
294 | init.num_parents = of_clk_get_parent_count(np: node) + 1; |
295 | of_property_read_string_index(np: node, propname: "clock-output-names" , index: 0, |
296 | output: &init.name); |
297 | |
298 | rtc->losc = clk_register(NULL, hw: &rtc->hw); |
299 | if (IS_ERR(ptr: rtc->losc)) { |
300 | pr_crit("Couldn't register the LOSC clock\n" ); |
301 | goto err_register; |
302 | } |
303 | |
304 | of_property_read_string_index(np: node, propname: "clock-output-names" , index: 1, |
305 | output: &clkout_name); |
306 | rtc->ext_losc = clk_register_gate(NULL, name: clkout_name, parent_name: init.name, |
307 | flags: 0, reg: rtc->base + SUN6I_LOSC_OUT_GATING, |
308 | SUN6I_LOSC_OUT_GATING_EN_OFFSET, clk_gate_flags: 0, |
309 | lock: &rtc->lock); |
310 | if (IS_ERR(ptr: rtc->ext_losc)) { |
311 | pr_crit("Couldn't register the LOSC external gate\n" ); |
312 | goto err_register; |
313 | } |
314 | |
315 | clk_data->num = 3; |
316 | clk_data->hws[0] = &rtc->hw; |
317 | clk_data->hws[1] = __clk_get_hw(clk: rtc->ext_losc); |
318 | clk_data->hws[2] = rtc->int_osc; |
319 | of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data); |
320 | return; |
321 | |
322 | err_register: |
323 | clk_hw_unregister_fixed_rate(hw: rtc->int_osc); |
324 | err: |
325 | kfree(objp: clk_data); |
326 | } |
327 | |
328 | static const struct sun6i_rtc_clk_data sun6i_a31_rtc_data = { |
329 | .rc_osc_rate = 667000, /* datasheet says 600 ~ 700 KHz */ |
330 | .has_prescaler = 1, |
331 | }; |
332 | |
333 | static void __init sun6i_a31_rtc_clk_init(struct device_node *node) |
334 | { |
335 | sun6i_rtc_clk_init(node, data: &sun6i_a31_rtc_data); |
336 | } |
337 | CLK_OF_DECLARE_DRIVER(sun6i_a31_rtc_clk, "allwinner,sun6i-a31-rtc" , |
338 | sun6i_a31_rtc_clk_init); |
339 | |
340 | static const struct sun6i_rtc_clk_data sun8i_a23_rtc_data = { |
341 | .rc_osc_rate = 667000, /* datasheet says 600 ~ 700 KHz */ |
342 | .has_prescaler = 1, |
343 | .has_out_clk = 1, |
344 | }; |
345 | |
346 | static void __init sun8i_a23_rtc_clk_init(struct device_node *node) |
347 | { |
348 | sun6i_rtc_clk_init(node, data: &sun8i_a23_rtc_data); |
349 | } |
350 | CLK_OF_DECLARE_DRIVER(sun8i_a23_rtc_clk, "allwinner,sun8i-a23-rtc" , |
351 | sun8i_a23_rtc_clk_init); |
352 | |
353 | static const struct sun6i_rtc_clk_data sun8i_h3_rtc_data = { |
354 | .rc_osc_rate = 16000000, |
355 | .fixed_prescaler = 32, |
356 | .has_prescaler = 1, |
357 | .has_out_clk = 1, |
358 | }; |
359 | |
360 | static void __init sun8i_h3_rtc_clk_init(struct device_node *node) |
361 | { |
362 | sun6i_rtc_clk_init(node, data: &sun8i_h3_rtc_data); |
363 | } |
364 | CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc" , |
365 | sun8i_h3_rtc_clk_init); |
366 | /* As far as we are concerned, clocks for H5 are the same as H3 */ |
367 | CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc" , |
368 | sun8i_h3_rtc_clk_init); |
369 | |
370 | static const struct sun6i_rtc_clk_data sun50i_h6_rtc_data = { |
371 | .rc_osc_rate = 16000000, |
372 | .fixed_prescaler = 32, |
373 | .has_prescaler = 1, |
374 | .has_out_clk = 1, |
375 | .has_losc_en = 1, |
376 | .has_auto_swt = 1, |
377 | }; |
378 | |
379 | static void __init sun50i_h6_rtc_clk_init(struct device_node *node) |
380 | { |
381 | sun6i_rtc_clk_init(node, data: &sun50i_h6_rtc_data); |
382 | } |
383 | CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc" , |
384 | sun50i_h6_rtc_clk_init); |
385 | |
386 | /* |
387 | * The R40 user manual is self-conflicting on whether the prescaler is |
388 | * fixed or configurable. The clock diagram shows it as fixed, but there |
389 | * is also a configurable divider in the RTC block. |
390 | */ |
391 | static const struct sun6i_rtc_clk_data sun8i_r40_rtc_data = { |
392 | .rc_osc_rate = 16000000, |
393 | .fixed_prescaler = 512, |
394 | }; |
395 | static void __init sun8i_r40_rtc_clk_init(struct device_node *node) |
396 | { |
397 | sun6i_rtc_clk_init(node, data: &sun8i_r40_rtc_data); |
398 | } |
399 | CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc" , |
400 | sun8i_r40_rtc_clk_init); |
401 | |
402 | static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = { |
403 | .rc_osc_rate = 32000, |
404 | .has_out_clk = 1, |
405 | }; |
406 | |
407 | static void __init sun8i_v3_rtc_clk_init(struct device_node *node) |
408 | { |
409 | sun6i_rtc_clk_init(node, data: &sun8i_v3_rtc_data); |
410 | } |
411 | CLK_OF_DECLARE_DRIVER(sun8i_v3_rtc_clk, "allwinner,sun8i-v3-rtc" , |
412 | sun8i_v3_rtc_clk_init); |
413 | |
414 | static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) |
415 | { |
416 | struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; |
417 | irqreturn_t ret = IRQ_NONE; |
418 | u32 val; |
419 | |
420 | spin_lock(lock: &chip->lock); |
421 | val = readl(addr: chip->base + SUN6I_ALRM_IRQ_STA); |
422 | |
423 | if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { |
424 | val |= SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND; |
425 | writel(val, addr: chip->base + SUN6I_ALRM_IRQ_STA); |
426 | |
427 | rtc_update_irq(rtc: chip->rtc, num: 1, RTC_AF | RTC_IRQF); |
428 | |
429 | ret = IRQ_HANDLED; |
430 | } |
431 | spin_unlock(lock: &chip->lock); |
432 | |
433 | return ret; |
434 | } |
435 | |
436 | static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) |
437 | { |
438 | u32 alrm_val = 0; |
439 | u32 alrm_irq_val = 0; |
440 | u32 alrm_wake_val = 0; |
441 | unsigned long flags; |
442 | |
443 | if (to) { |
444 | alrm_val = SUN6I_ALRM_EN_CNT_EN; |
445 | alrm_irq_val = SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN; |
446 | alrm_wake_val = SUN6I_ALARM_CONFIG_WAKEUP; |
447 | } else { |
448 | writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, |
449 | addr: chip->base + SUN6I_ALRM_IRQ_STA); |
450 | } |
451 | |
452 | spin_lock_irqsave(&chip->lock, flags); |
453 | writel(val: alrm_val, addr: chip->base + SUN6I_ALRM_EN); |
454 | writel(val: alrm_irq_val, addr: chip->base + SUN6I_ALRM_IRQ_EN); |
455 | writel(val: alrm_wake_val, addr: chip->base + SUN6I_ALARM_CONFIG); |
456 | spin_unlock_irqrestore(lock: &chip->lock, flags); |
457 | } |
458 | |
459 | static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) |
460 | { |
461 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
462 | u32 date, time; |
463 | |
464 | /* |
465 | * read again in case it changes |
466 | */ |
467 | do { |
468 | date = readl(addr: chip->base + SUN6I_RTC_YMD); |
469 | time = readl(addr: chip->base + SUN6I_RTC_HMS); |
470 | } while ((date != readl(addr: chip->base + SUN6I_RTC_YMD)) || |
471 | (time != readl(addr: chip->base + SUN6I_RTC_HMS))); |
472 | |
473 | if (chip->flags & RTC_LINEAR_DAY) { |
474 | /* |
475 | * Newer chips store a linear day number, the manual |
476 | * does not mandate any epoch base. The BSP driver uses |
477 | * the UNIX epoch, let's just copy that, as it's the |
478 | * easiest anyway. |
479 | */ |
480 | rtc_time64_to_tm(time: (date & 0xffff) * SECS_PER_DAY, tm: rtc_tm); |
481 | } else { |
482 | rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); |
483 | rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date) - 1; |
484 | rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); |
485 | |
486 | /* |
487 | * switch from (data_year->min)-relative offset to |
488 | * a (1900)-relative one |
489 | */ |
490 | rtc_tm->tm_year += SUN6I_YEAR_OFF; |
491 | } |
492 | |
493 | rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); |
494 | rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); |
495 | rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); |
496 | |
497 | return 0; |
498 | } |
499 | |
500 | static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
501 | { |
502 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
503 | unsigned long flags; |
504 | u32 alrm_st; |
505 | u32 alrm_en; |
506 | |
507 | spin_lock_irqsave(&chip->lock, flags); |
508 | alrm_en = readl(addr: chip->base + SUN6I_ALRM_IRQ_EN); |
509 | alrm_st = readl(addr: chip->base + SUN6I_ALRM_IRQ_STA); |
510 | spin_unlock_irqrestore(lock: &chip->lock, flags); |
511 | |
512 | wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); |
513 | wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); |
514 | rtc_time64_to_tm(time: chip->alarm, tm: &wkalrm->time); |
515 | |
516 | return 0; |
517 | } |
518 | |
519 | static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
520 | { |
521 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
522 | struct rtc_time *alrm_tm = &wkalrm->time; |
523 | struct rtc_time tm_now; |
524 | time64_t time_set; |
525 | u32 counter_val, counter_val_hms; |
526 | int ret; |
527 | |
528 | time_set = rtc_tm_to_time64(tm: alrm_tm); |
529 | |
530 | if (chip->flags & RTC_LINEAR_DAY) { |
531 | /* |
532 | * The alarm registers hold the actual alarm time, encoded |
533 | * in the same way (linear day + HMS) as the current time. |
534 | */ |
535 | counter_val_hms = SUN6I_TIME_SET_SEC_VALUE(alrm_tm->tm_sec) | |
536 | SUN6I_TIME_SET_MIN_VALUE(alrm_tm->tm_min) | |
537 | SUN6I_TIME_SET_HOUR_VALUE(alrm_tm->tm_hour); |
538 | /* The division will cut off the H:M:S part of alrm_tm. */ |
539 | counter_val = div_u64(dividend: rtc_tm_to_time64(tm: alrm_tm), SECS_PER_DAY); |
540 | } else { |
541 | /* The alarm register holds the number of seconds left. */ |
542 | time64_t time_now; |
543 | |
544 | ret = sun6i_rtc_gettime(dev, rtc_tm: &tm_now); |
545 | if (ret < 0) { |
546 | dev_err(dev, "Error in getting time\n" ); |
547 | return -EINVAL; |
548 | } |
549 | |
550 | time_now = rtc_tm_to_time64(tm: &tm_now); |
551 | if (time_set <= time_now) { |
552 | dev_err(dev, "Date to set in the past\n" ); |
553 | return -EINVAL; |
554 | } |
555 | if ((time_set - time_now) > U32_MAX) { |
556 | dev_err(dev, "Date too far in the future\n" ); |
557 | return -EINVAL; |
558 | } |
559 | |
560 | counter_val = time_set - time_now; |
561 | } |
562 | |
563 | sun6i_rtc_setaie(to: 0, chip); |
564 | writel(val: 0, addr: chip->base + SUN6I_ALRM_COUNTER); |
565 | if (chip->flags & RTC_LINEAR_DAY) |
566 | writel(val: 0, addr: chip->base + SUN6I_ALRM_COUNTER_HMS); |
567 | usleep_range(min: 100, max: 300); |
568 | |
569 | writel(val: counter_val, addr: chip->base + SUN6I_ALRM_COUNTER); |
570 | if (chip->flags & RTC_LINEAR_DAY) |
571 | writel(val: counter_val_hms, addr: chip->base + SUN6I_ALRM_COUNTER_HMS); |
572 | chip->alarm = time_set; |
573 | |
574 | sun6i_rtc_setaie(to: wkalrm->enabled, chip); |
575 | |
576 | return 0; |
577 | } |
578 | |
579 | static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset, |
580 | unsigned int mask, unsigned int ms_timeout) |
581 | { |
582 | const unsigned long timeout = jiffies + msecs_to_jiffies(m: ms_timeout); |
583 | u32 reg; |
584 | |
585 | do { |
586 | reg = readl(addr: chip->base + offset); |
587 | reg &= mask; |
588 | |
589 | if (!reg) |
590 | return 0; |
591 | |
592 | } while (time_before(jiffies, timeout)); |
593 | |
594 | return -ETIMEDOUT; |
595 | } |
596 | |
597 | static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) |
598 | { |
599 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
600 | u32 date = 0; |
601 | u32 time = 0; |
602 | |
603 | time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | |
604 | SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | |
605 | SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); |
606 | |
607 | if (chip->flags & RTC_LINEAR_DAY) { |
608 | /* The division will cut off the H:M:S part of rtc_tm. */ |
609 | date = div_u64(dividend: rtc_tm_to_time64(tm: rtc_tm), SECS_PER_DAY); |
610 | } else { |
611 | rtc_tm->tm_year -= SUN6I_YEAR_OFF; |
612 | rtc_tm->tm_mon += 1; |
613 | |
614 | date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | |
615 | SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | |
616 | SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); |
617 | |
618 | if (is_leap_year(year: rtc_tm->tm_year + SUN6I_YEAR_MIN)) |
619 | date |= SUN6I_LEAP_SET_VALUE(1); |
620 | } |
621 | |
622 | /* Check whether registers are writable */ |
623 | if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, |
624 | SUN6I_LOSC_CTRL_ACC_MASK, ms_timeout: 50)) { |
625 | dev_err(dev, "rtc is still busy.\n" ); |
626 | return -EBUSY; |
627 | } |
628 | |
629 | writel(val: time, addr: chip->base + SUN6I_RTC_HMS); |
630 | |
631 | /* |
632 | * After writing the RTC HH-MM-SS register, the |
633 | * SUN6I_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not |
634 | * be cleared until the real writing operation is finished |
635 | */ |
636 | |
637 | if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, |
638 | SUN6I_LOSC_CTRL_RTC_HMS_ACC, ms_timeout: 50)) { |
639 | dev_err(dev, "Failed to set rtc time.\n" ); |
640 | return -ETIMEDOUT; |
641 | } |
642 | |
643 | writel(val: date, addr: chip->base + SUN6I_RTC_YMD); |
644 | |
645 | /* |
646 | * After writing the RTC YY-MM-DD register, the |
647 | * SUN6I_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not |
648 | * be cleared until the real writing operation is finished |
649 | */ |
650 | |
651 | if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, |
652 | SUN6I_LOSC_CTRL_RTC_YMD_ACC, ms_timeout: 50)) { |
653 | dev_err(dev, "Failed to set rtc time.\n" ); |
654 | return -ETIMEDOUT; |
655 | } |
656 | |
657 | return 0; |
658 | } |
659 | |
660 | static int sun6i_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
661 | { |
662 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
663 | |
664 | if (!enabled) |
665 | sun6i_rtc_setaie(to: enabled, chip); |
666 | |
667 | return 0; |
668 | } |
669 | |
670 | static const struct rtc_class_ops sun6i_rtc_ops = { |
671 | .read_time = sun6i_rtc_gettime, |
672 | .set_time = sun6i_rtc_settime, |
673 | .read_alarm = sun6i_rtc_getalarm, |
674 | .set_alarm = sun6i_rtc_setalarm, |
675 | .alarm_irq_enable = sun6i_rtc_alarm_irq_enable |
676 | }; |
677 | |
678 | static int sun6i_rtc_nvmem_read(void *priv, unsigned int offset, void *_val, size_t bytes) |
679 | { |
680 | struct sun6i_rtc_dev *chip = priv; |
681 | u32 *val = _val; |
682 | int i; |
683 | |
684 | for (i = 0; i < bytes / 4; ++i) |
685 | val[i] = readl(addr: chip->base + SUN6I_GP_DATA + offset + 4 * i); |
686 | |
687 | return 0; |
688 | } |
689 | |
690 | static int sun6i_rtc_nvmem_write(void *priv, unsigned int offset, void *_val, size_t bytes) |
691 | { |
692 | struct sun6i_rtc_dev *chip = priv; |
693 | u32 *val = _val; |
694 | int i; |
695 | |
696 | for (i = 0; i < bytes / 4; ++i) |
697 | writel(val: val[i], addr: chip->base + SUN6I_GP_DATA + offset + 4 * i); |
698 | |
699 | return 0; |
700 | } |
701 | |
702 | static struct nvmem_config sun6i_rtc_nvmem_cfg = { |
703 | .type = NVMEM_TYPE_BATTERY_BACKED, |
704 | .reg_read = sun6i_rtc_nvmem_read, |
705 | .reg_write = sun6i_rtc_nvmem_write, |
706 | .size = SUN6I_GP_DATA_SIZE, |
707 | .word_size = 4, |
708 | .stride = 4, |
709 | }; |
710 | |
711 | #ifdef CONFIG_PM_SLEEP |
712 | /* Enable IRQ wake on suspend, to wake up from RTC. */ |
713 | static int sun6i_rtc_suspend(struct device *dev) |
714 | { |
715 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
716 | |
717 | if (device_may_wakeup(dev)) |
718 | enable_irq_wake(irq: chip->irq); |
719 | |
720 | return 0; |
721 | } |
722 | |
723 | /* Disable IRQ wake on resume. */ |
724 | static int sun6i_rtc_resume(struct device *dev) |
725 | { |
726 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
727 | |
728 | if (device_may_wakeup(dev)) |
729 | disable_irq_wake(irq: chip->irq); |
730 | |
731 | return 0; |
732 | } |
733 | #endif |
734 | |
735 | static SIMPLE_DEV_PM_OPS(sun6i_rtc_pm_ops, |
736 | sun6i_rtc_suspend, sun6i_rtc_resume); |
737 | |
738 | static void sun6i_rtc_bus_clk_cleanup(void *data) |
739 | { |
740 | struct clk *bus_clk = data; |
741 | |
742 | clk_disable_unprepare(clk: bus_clk); |
743 | } |
744 | |
745 | static int sun6i_rtc_probe(struct platform_device *pdev) |
746 | { |
747 | struct sun6i_rtc_dev *chip = sun6i_rtc; |
748 | struct device *dev = &pdev->dev; |
749 | struct clk *bus_clk; |
750 | int ret; |
751 | |
752 | bus_clk = devm_clk_get_optional(dev, id: "bus" ); |
753 | if (IS_ERR(ptr: bus_clk)) |
754 | return PTR_ERR(ptr: bus_clk); |
755 | |
756 | if (bus_clk) { |
757 | ret = clk_prepare_enable(clk: bus_clk); |
758 | if (ret) |
759 | return ret; |
760 | |
761 | ret = devm_add_action_or_reset(dev, sun6i_rtc_bus_clk_cleanup, |
762 | bus_clk); |
763 | if (ret) |
764 | return ret; |
765 | } |
766 | |
767 | if (!chip) { |
768 | chip = devm_kzalloc(dev: &pdev->dev, size: sizeof(*chip), GFP_KERNEL); |
769 | if (!chip) |
770 | return -ENOMEM; |
771 | |
772 | spin_lock_init(&chip->lock); |
773 | |
774 | chip->base = devm_platform_ioremap_resource(pdev, index: 0); |
775 | if (IS_ERR(ptr: chip->base)) |
776 | return PTR_ERR(ptr: chip->base); |
777 | |
778 | if (IS_REACHABLE(CONFIG_SUN6I_RTC_CCU)) { |
779 | ret = sun6i_rtc_ccu_probe(dev, reg: chip->base); |
780 | if (ret) |
781 | return ret; |
782 | } |
783 | } |
784 | |
785 | platform_set_drvdata(pdev, data: chip); |
786 | |
787 | chip->flags = (unsigned long)of_device_get_match_data(dev: &pdev->dev); |
788 | |
789 | chip->irq = platform_get_irq(pdev, 0); |
790 | if (chip->irq < 0) |
791 | return chip->irq; |
792 | |
793 | ret = devm_request_irq(dev: &pdev->dev, irq: chip->irq, handler: sun6i_rtc_alarmirq, |
794 | irqflags: 0, devname: dev_name(dev: &pdev->dev), dev_id: chip); |
795 | if (ret) { |
796 | dev_err(&pdev->dev, "Could not request IRQ\n" ); |
797 | return ret; |
798 | } |
799 | |
800 | /* clear the alarm counter value */ |
801 | writel(val: 0, addr: chip->base + SUN6I_ALRM_COUNTER); |
802 | |
803 | /* disable counter alarm */ |
804 | writel(val: 0, addr: chip->base + SUN6I_ALRM_EN); |
805 | |
806 | /* disable counter alarm interrupt */ |
807 | writel(val: 0, addr: chip->base + SUN6I_ALRM_IRQ_EN); |
808 | |
809 | /* disable week alarm */ |
810 | writel(val: 0, addr: chip->base + SUN6I_ALRM1_EN); |
811 | |
812 | /* disable week alarm interrupt */ |
813 | writel(val: 0, addr: chip->base + SUN6I_ALRM1_IRQ_EN); |
814 | |
815 | /* clear counter alarm pending interrupts */ |
816 | writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, |
817 | addr: chip->base + SUN6I_ALRM_IRQ_STA); |
818 | |
819 | /* clear week alarm pending interrupts */ |
820 | writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, |
821 | addr: chip->base + SUN6I_ALRM1_IRQ_STA); |
822 | |
823 | /* disable alarm wakeup */ |
824 | writel(val: 0, addr: chip->base + SUN6I_ALARM_CONFIG); |
825 | |
826 | clk_prepare_enable(clk: chip->losc); |
827 | |
828 | device_init_wakeup(dev: &pdev->dev, enable: 1); |
829 | |
830 | chip->rtc = devm_rtc_allocate_device(dev: &pdev->dev); |
831 | if (IS_ERR(ptr: chip->rtc)) |
832 | return PTR_ERR(ptr: chip->rtc); |
833 | |
834 | chip->rtc->ops = &sun6i_rtc_ops; |
835 | if (chip->flags & RTC_LINEAR_DAY) |
836 | chip->rtc->range_max = (65536 * SECS_PER_DAY) - 1; |
837 | else |
838 | chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */ |
839 | |
840 | ret = devm_rtc_register_device(chip->rtc); |
841 | if (ret) |
842 | return ret; |
843 | |
844 | sun6i_rtc_nvmem_cfg.priv = chip; |
845 | ret = devm_rtc_nvmem_register(rtc: chip->rtc, nvmem_config: &sun6i_rtc_nvmem_cfg); |
846 | if (ret) |
847 | return ret; |
848 | |
849 | return 0; |
850 | } |
851 | |
852 | /* |
853 | * As far as RTC functionality goes, all models are the same. The |
854 | * datasheets claim that different models have different number of |
855 | * registers available for non-volatile storage, but experiments show |
856 | * that all SoCs have 16 registers available for this purpose. |
857 | */ |
858 | static const struct of_device_id sun6i_rtc_dt_ids[] = { |
859 | { .compatible = "allwinner,sun6i-a31-rtc" }, |
860 | { .compatible = "allwinner,sun8i-a23-rtc" }, |
861 | { .compatible = "allwinner,sun8i-h3-rtc" }, |
862 | { .compatible = "allwinner,sun8i-r40-rtc" }, |
863 | { .compatible = "allwinner,sun8i-v3-rtc" }, |
864 | { .compatible = "allwinner,sun50i-h5-rtc" }, |
865 | { .compatible = "allwinner,sun50i-h6-rtc" }, |
866 | { .compatible = "allwinner,sun50i-h616-rtc" , |
867 | .data = (void *)RTC_LINEAR_DAY }, |
868 | { .compatible = "allwinner,sun50i-r329-rtc" , |
869 | .data = (void *)RTC_LINEAR_DAY }, |
870 | { /* sentinel */ }, |
871 | }; |
872 | MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); |
873 | |
874 | static struct platform_driver sun6i_rtc_driver = { |
875 | .probe = sun6i_rtc_probe, |
876 | .driver = { |
877 | .name = "sun6i-rtc" , |
878 | .of_match_table = sun6i_rtc_dt_ids, |
879 | .pm = &sun6i_rtc_pm_ops, |
880 | }, |
881 | }; |
882 | builtin_platform_driver(sun6i_rtc_driver); |
883 | |