]> Git Repo - J-linux.git/blob - drivers/rtc/rtc-rzn1.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / rtc / rtc-rzn1.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Renesas RZ/N1 Real Time Clock interface for Linux
4  *
5  * Copyright:
6  * - 2014 Renesas Electronics Europe Limited
7  * - 2022 Schneider Electric
8  *
9  * Authors:
10  * - Michel Pollet <[email protected]>
11  * - Miquel Raynal <[email protected]>
12  */
13
14 #include <linux/bcd.h>
15 #include <linux/init.h>
16 #include <linux/iopoll.h>
17 #include <linux/module.h>
18 #include <linux/mod_devicetable.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/rtc.h>
22
23 #define RZN1_RTC_CTL0 0x00
24 #define   RZN1_RTC_CTL0_SLSB_SUBU 0
25 #define   RZN1_RTC_CTL0_SLSB_SCMP BIT(4)
26 #define   RZN1_RTC_CTL0_AMPM BIT(5)
27 #define   RZN1_RTC_CTL0_CE BIT(7)
28
29 #define RZN1_RTC_CTL1 0x04
30 #define   RZN1_RTC_CTL1_ALME BIT(4)
31
32 #define RZN1_RTC_CTL2 0x08
33 #define   RZN1_RTC_CTL2_WAIT BIT(0)
34 #define   RZN1_RTC_CTL2_WST BIT(1)
35 #define   RZN1_RTC_CTL2_WUST BIT(5)
36 #define   RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST)
37
38 #define RZN1_RTC_TIME 0x30
39 #define RZN1_RTC_TIME_MIN_SHIFT 8
40 #define RZN1_RTC_TIME_HOUR_SHIFT 16
41 #define RZN1_RTC_CAL 0x34
42 #define RZN1_RTC_CAL_DAY_SHIFT 8
43 #define RZN1_RTC_CAL_MON_SHIFT 16
44 #define RZN1_RTC_CAL_YEAR_SHIFT 24
45
46 #define RZN1_RTC_SUBU 0x38
47 #define   RZN1_RTC_SUBU_DEV BIT(7)
48 #define   RZN1_RTC_SUBU_DECR BIT(6)
49
50 #define RZN1_RTC_ALM 0x40
51 #define RZN1_RTC_ALH 0x44
52 #define RZN1_RTC_ALW 0x48
53
54 #define RZN1_RTC_SECC 0x4c
55 #define RZN1_RTC_TIMEC 0x68
56 #define RZN1_RTC_CALC 0x6c
57
58 struct rzn1_rtc {
59         struct rtc_device *rtcdev;
60         void __iomem *base;
61 };
62
63 static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
64 {
65         u32 val;
66
67         val = readl(rtc->base + RZN1_RTC_TIMEC);
68         tm->tm_sec = bcd2bin(val);
69         tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT);
70         tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT);
71
72         val = readl(rtc->base + RZN1_RTC_CALC);
73         tm->tm_wday = val & 0x0f;
74         tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT);
75         tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1;
76         tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100;
77 }
78
79 static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
80 {
81         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
82         u32 val, secs;
83
84         /*
85          * The RTC was not started or is stopped and thus does not carry the
86          * proper time/date.
87          */
88         val = readl(rtc->base + RZN1_RTC_CTL2);
89         if (val & RZN1_RTC_CTL2_STOPPED)
90                 return -EINVAL;
91
92         rzn1_rtc_get_time_snapshot(rtc, tm);
93         secs = readl(rtc->base + RZN1_RTC_SECC);
94         if (tm->tm_sec != bcd2bin(secs))
95                 rzn1_rtc_get_time_snapshot(rtc, tm);
96
97         return 0;
98 }
99
100 static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
101 {
102         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
103         u32 val;
104         int ret;
105
106         val = readl(rtc->base + RZN1_RTC_CTL2);
107         if (!(val & RZN1_RTC_CTL2_STOPPED)) {
108                 /* Hold the counter if it was counting up */
109                 writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2);
110
111                 /* Wait for the counter to stop: two 32k clock cycles */
112                 usleep_range(61, 100);
113                 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val,
114                                          val & RZN1_RTC_CTL2_WST, 0, 100);
115                 if (ret)
116                         return ret;
117         }
118
119         val = bin2bcd(tm->tm_sec);
120         val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT;
121         val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT;
122         writel(val, rtc->base + RZN1_RTC_TIME);
123
124         val = tm->tm_wday;
125         val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT;
126         val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT;
127         val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT;
128         writel(val, rtc->base + RZN1_RTC_CAL);
129
130         writel(0, rtc->base + RZN1_RTC_CTL2);
131
132         return 0;
133 }
134
135 static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id)
136 {
137         struct rzn1_rtc *rtc = dev_id;
138
139         rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
140
141         return IRQ_HANDLED;
142 }
143
144 static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
145 {
146         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
147         u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
148
149         if (enable)
150                 ctl1 |= RZN1_RTC_CTL1_ALME;
151         else
152                 ctl1 &= ~RZN1_RTC_CTL1_ALME;
153
154         writel(ctl1, rtc->base + RZN1_RTC_CTL1);
155
156         return 0;
157 }
158
159 static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
160 {
161         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
162         struct rtc_time *tm = &alrm->time;
163         unsigned int min, hour, wday, delta_days;
164         time64_t alarm;
165         u32 ctl1;
166         int ret;
167
168         ret = rzn1_rtc_read_time(dev, tm);
169         if (ret)
170                 return ret;
171
172         min = readl(rtc->base + RZN1_RTC_ALM);
173         hour = readl(rtc->base + RZN1_RTC_ALH);
174         wday = readl(rtc->base + RZN1_RTC_ALW);
175
176         tm->tm_sec = 0;
177         tm->tm_min = bcd2bin(min);
178         tm->tm_hour = bcd2bin(hour);
179         delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
180         tm->tm_wday = fls(wday) - 1;
181
182         if (delta_days) {
183                 alarm = rtc_tm_to_time64(tm) + (delta_days * 86400);
184                 rtc_time64_to_tm(alarm, tm);
185         }
186
187         ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
188         alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME);
189
190         return 0;
191 }
192
193 static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
194 {
195         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
196         struct rtc_time *tm = &alrm->time, tm_now;
197         unsigned long alarm, farest;
198         unsigned int days_ahead, wday;
199         int ret;
200
201         ret = rzn1_rtc_read_time(dev, &tm_now);
202         if (ret)
203                 return ret;
204
205         /* We cannot set alarms more than one week ahead */
206         farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max;
207         alarm = rtc_tm_to_time64(tm);
208         if (time_after(alarm, farest))
209                 return -ERANGE;
210
211         /* Convert alarm day into week day */
212         days_ahead = tm->tm_mday - tm_now.tm_mday;
213         wday = (tm_now.tm_wday + days_ahead) % 7;
214
215         writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
216         writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
217         writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
218
219         rzn1_rtc_alarm_irq_enable(dev, alrm->enabled);
220
221         return 0;
222 }
223
224 static int rzn1_rtc_read_offset(struct device *dev, long *offset)
225 {
226         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
227         unsigned int ppb_per_step;
228         bool subtract;
229         u32 val;
230
231         val = readl(rtc->base + RZN1_RTC_SUBU);
232         ppb_per_step = val & RZN1_RTC_SUBU_DEV ? 1017 : 3051;
233         subtract = val & RZN1_RTC_SUBU_DECR;
234         val &= 0x3F;
235
236         if (!val)
237                 *offset = 0;
238         else if (subtract)
239                 *offset = -(((~val) & 0x3F) + 1) * ppb_per_step;
240         else
241                 *offset = (val - 1) * ppb_per_step;
242
243         return 0;
244 }
245
246 static int rzn1_rtc_set_offset(struct device *dev, long offset)
247 {
248         struct rzn1_rtc *rtc = dev_get_drvdata(dev);
249         int stepsh, stepsl, steps;
250         u32 subu = 0, ctl2;
251         int ret;
252
253         /*
254          * Check which resolution mode (every 20 or 60s) can be used.
255          * Between 2 and 124 clock pulses can be added or substracted.
256          *
257          * In 20s mode, the minimum resolution is 2 / (32768 * 20) which is
258          * close to 3051 ppb. In 60s mode, the resolution is closer to 1017.
259          */
260         stepsh = DIV_ROUND_CLOSEST(offset, 1017);
261         stepsl = DIV_ROUND_CLOSEST(offset, 3051);
262
263         if (stepsh >= -0x3E && stepsh <= 0x3E) {
264                 /* 1017 ppb per step */
265                 steps = stepsh;
266                 subu |= RZN1_RTC_SUBU_DEV;
267         } else if (stepsl >= -0x3E && stepsl <= 0x3E) {
268                 /* 3051 ppb per step */
269                 steps = stepsl;
270         } else {
271                 return -ERANGE;
272         }
273
274         if (!steps)
275                 return 0;
276
277         if (steps > 0) {
278                 subu |= steps + 1;
279         } else {
280                 subu |= RZN1_RTC_SUBU_DECR;
281                 subu |= (~(-steps - 1)) & 0x3F;
282         }
283
284         ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, ctl2,
285                                  !(ctl2 & RZN1_RTC_CTL2_WUST), 100, 2000000);
286         if (ret)
287                 return ret;
288
289         writel(subu, rtc->base + RZN1_RTC_SUBU);
290
291         return 0;
292 }
293
294 static const struct rtc_class_ops rzn1_rtc_ops = {
295         .read_time = rzn1_rtc_read_time,
296         .set_time = rzn1_rtc_set_time,
297         .read_alarm = rzn1_rtc_read_alarm,
298         .set_alarm = rzn1_rtc_set_alarm,
299         .alarm_irq_enable = rzn1_rtc_alarm_irq_enable,
300         .read_offset = rzn1_rtc_read_offset,
301         .set_offset = rzn1_rtc_set_offset,
302 };
303
304 static int rzn1_rtc_probe(struct platform_device *pdev)
305 {
306         struct rzn1_rtc *rtc;
307         int alarm_irq;
308         int ret;
309
310         rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
311         if (!rtc)
312                 return -ENOMEM;
313
314         platform_set_drvdata(pdev, rtc);
315
316         rtc->base = devm_platform_ioremap_resource(pdev, 0);
317         if (IS_ERR(rtc->base))
318                 return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n");
319
320         alarm_irq = platform_get_irq(pdev, 0);
321         if (alarm_irq < 0)
322                 return alarm_irq;
323
324         rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
325         if (IS_ERR(rtc->rtcdev))
326                 return PTR_ERR(rtc->rtcdev);
327
328         rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
329         rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
330         rtc->rtcdev->alarm_offset_max = 7 * 86400;
331         rtc->rtcdev->ops = &rzn1_rtc_ops;
332         set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);
333         clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features);
334
335         ret = devm_pm_runtime_enable(&pdev->dev);
336         if (ret < 0)
337                 return ret;
338         ret = pm_runtime_resume_and_get(&pdev->dev);
339         if (ret < 0)
340                 return ret;
341
342         /*
343          * Ensure the clock counter is enabled.
344          * Set 24-hour mode and possible oscillator offset compensation in SUBU mode.
345          */
346         writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | RZN1_RTC_CTL0_SLSB_SUBU,
347                rtc->base + RZN1_RTC_CTL0);
348
349         /* Disable all interrupts */
350         writel(0, rtc->base + RZN1_RTC_CTL1);
351
352         ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0,
353                                dev_name(&pdev->dev), rtc);
354         if (ret) {
355                 dev_err(&pdev->dev, "RTC timer interrupt not available\n");
356                 goto dis_runtime_pm;
357         }
358
359         ret = devm_rtc_register_device(rtc->rtcdev);
360         if (ret)
361                 goto dis_runtime_pm;
362
363         return 0;
364
365 dis_runtime_pm:
366         pm_runtime_put(&pdev->dev);
367
368         return ret;
369 }
370
371 static void rzn1_rtc_remove(struct platform_device *pdev)
372 {
373         pm_runtime_put(&pdev->dev);
374 }
375
376 static const struct of_device_id rzn1_rtc_of_match[] = {
377         { .compatible   = "renesas,rzn1-rtc" },
378         {},
379 };
380 MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
381
382 static struct platform_driver rzn1_rtc_driver = {
383         .probe = rzn1_rtc_probe,
384         .remove = rzn1_rtc_remove,
385         .driver = {
386                 .name   = "rzn1-rtc",
387                 .of_match_table = rzn1_rtc_of_match,
388         },
389 };
390 module_platform_driver(rzn1_rtc_driver);
391
392 MODULE_AUTHOR("Michel Pollet <[email protected]>");
393 MODULE_AUTHOR("Miquel Raynal <[email protected]");
394 MODULE_DESCRIPTION("RZ/N1 RTC driver");
395 MODULE_LICENSE("GPL");
This page took 0.050937 seconds and 4 git commands to generate.