Merge tag 'drm-misc-fixes-2023-05-11' of git://anongit.freedesktop.org/drm/drm-misc...
[platform/kernel/linux-rpi.git] / drivers / rtc / rtc-cadence.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright 2019 Cadence
5  *
6  * Authors:
7  *  Jan Kotas <jank@cadence.com>
8  */
9
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/of.h>
13 #include <linux/io.h>
14 #include <linux/rtc.h>
15 #include <linux/clk.h>
16 #include <linux/bcd.h>
17 #include <linux/bitfield.h>
18 #include <linux/interrupt.h>
19 #include <linux/pm_wakeirq.h>
20
21 /* Registers */
22 #define CDNS_RTC_CTLR           0x00
23 #define CDNS_RTC_HMR            0x04
24 #define CDNS_RTC_TIMR           0x08
25 #define CDNS_RTC_CALR           0x0C
26 #define CDNS_RTC_TIMAR          0x10
27 #define CDNS_RTC_CALAR          0x14
28 #define CDNS_RTC_AENR           0x18
29 #define CDNS_RTC_EFLR           0x1C
30 #define CDNS_RTC_IENR           0x20
31 #define CDNS_RTC_IDISR          0x24
32 #define CDNS_RTC_IMSKR          0x28
33 #define CDNS_RTC_STSR           0x2C
34 #define CDNS_RTC_KRTCR          0x30
35
36 /* Control */
37 #define CDNS_RTC_CTLR_TIME      BIT(0)
38 #define CDNS_RTC_CTLR_CAL       BIT(1)
39 #define CDNS_RTC_CTLR_TIME_CAL  (CDNS_RTC_CTLR_TIME | CDNS_RTC_CTLR_CAL)
40
41 /* Status */
42 #define CDNS_RTC_STSR_VT        BIT(0)
43 #define CDNS_RTC_STSR_VC        BIT(1)
44 #define CDNS_RTC_STSR_VTA       BIT(2)
45 #define CDNS_RTC_STSR_VCA       BIT(3)
46 #define CDNS_RTC_STSR_VT_VC     (CDNS_RTC_STSR_VT | CDNS_RTC_STSR_VC)
47 #define CDNS_RTC_STSR_VTA_VCA   (CDNS_RTC_STSR_VTA | CDNS_RTC_STSR_VCA)
48
49 /* Keep RTC */
50 #define CDNS_RTC_KRTCR_KRTC     BIT(0)
51
52 /* Alarm, Event, Interrupt */
53 #define CDNS_RTC_AEI_HOS        BIT(0)
54 #define CDNS_RTC_AEI_SEC        BIT(1)
55 #define CDNS_RTC_AEI_MIN        BIT(2)
56 #define CDNS_RTC_AEI_HOUR       BIT(3)
57 #define CDNS_RTC_AEI_DATE       BIT(4)
58 #define CDNS_RTC_AEI_MNTH       BIT(5)
59 #define CDNS_RTC_AEI_ALRM       BIT(6)
60
61 /* Time */
62 #define CDNS_RTC_TIME_H         GENMASK(7, 0)
63 #define CDNS_RTC_TIME_S         GENMASK(14, 8)
64 #define CDNS_RTC_TIME_M         GENMASK(22, 16)
65 #define CDNS_RTC_TIME_HR        GENMASK(29, 24)
66 #define CDNS_RTC_TIME_PM        BIT(30)
67 #define CDNS_RTC_TIME_CH        BIT(31)
68
69 /* Calendar */
70 #define CDNS_RTC_CAL_DAY        GENMASK(2, 0)
71 #define CDNS_RTC_CAL_M          GENMASK(7, 3)
72 #define CDNS_RTC_CAL_D          GENMASK(13, 8)
73 #define CDNS_RTC_CAL_Y          GENMASK(23, 16)
74 #define CDNS_RTC_CAL_C          GENMASK(29, 24)
75 #define CDNS_RTC_CAL_CH         BIT(31)
76
77 #define CDNS_RTC_MAX_REGS_TRIES 3
78
79 struct cdns_rtc {
80         struct rtc_device *rtc_dev;
81         struct clk *pclk;
82         struct clk *ref_clk;
83         void __iomem *regs;
84         int irq;
85 };
86
87 static void cdns_rtc_set_enabled(struct cdns_rtc *crtc, bool enabled)
88 {
89         u32 reg = enabled ? 0x0 : CDNS_RTC_CTLR_TIME_CAL;
90
91         writel(reg, crtc->regs + CDNS_RTC_CTLR);
92 }
93
94 static bool cdns_rtc_get_enabled(struct cdns_rtc *crtc)
95 {
96         return !(readl(crtc->regs + CDNS_RTC_CTLR) & CDNS_RTC_CTLR_TIME_CAL);
97 }
98
99 static irqreturn_t cdns_rtc_irq_handler(int irq, void *id)
100 {
101         struct device *dev = id;
102         struct cdns_rtc *crtc = dev_get_drvdata(dev);
103
104         /* Reading the register clears it */
105         if (!(readl(crtc->regs + CDNS_RTC_EFLR) & CDNS_RTC_AEI_ALRM))
106                 return IRQ_NONE;
107
108         rtc_update_irq(crtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
109         return IRQ_HANDLED;
110 }
111
112 static u32 cdns_rtc_time2reg(struct rtc_time *tm)
113 {
114         return FIELD_PREP(CDNS_RTC_TIME_S,  bin2bcd(tm->tm_sec))
115              | FIELD_PREP(CDNS_RTC_TIME_M,  bin2bcd(tm->tm_min))
116              | FIELD_PREP(CDNS_RTC_TIME_HR, bin2bcd(tm->tm_hour));
117 }
118
119 static void cdns_rtc_reg2time(u32 reg, struct rtc_time *tm)
120 {
121         tm->tm_sec  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_S, reg));
122         tm->tm_min  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_M, reg));
123         tm->tm_hour = bcd2bin(FIELD_GET(CDNS_RTC_TIME_HR, reg));
124 }
125
126 static int cdns_rtc_read_time(struct device *dev, struct rtc_time *tm)
127 {
128         struct cdns_rtc *crtc = dev_get_drvdata(dev);
129         u32 reg;
130
131         /* If the RTC is disabled, assume the values are invalid */
132         if (!cdns_rtc_get_enabled(crtc))
133                 return -EINVAL;
134
135         cdns_rtc_set_enabled(crtc, false);
136
137         reg = readl(crtc->regs + CDNS_RTC_TIMR);
138         cdns_rtc_reg2time(reg, tm);
139
140         reg = readl(crtc->regs + CDNS_RTC_CALR);
141         tm->tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
142         tm->tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
143         tm->tm_year = bcd2bin(FIELD_GET(CDNS_RTC_CAL_Y, reg))
144                     + bcd2bin(FIELD_GET(CDNS_RTC_CAL_C, reg)) * 100 - 1900;
145         tm->tm_wday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_DAY, reg)) - 1;
146
147         cdns_rtc_set_enabled(crtc, true);
148         return 0;
149 }
150
151 static int cdns_rtc_set_time(struct device *dev, struct rtc_time *tm)
152 {
153         struct cdns_rtc *crtc = dev_get_drvdata(dev);
154         u32 timr, calr, stsr;
155         int ret = -EIO;
156         int year = tm->tm_year + 1900;
157         int tries;
158
159         cdns_rtc_set_enabled(crtc, false);
160
161         timr = cdns_rtc_time2reg(tm);
162
163         calr = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(tm->tm_mday))
164              | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(tm->tm_mon + 1))
165              | FIELD_PREP(CDNS_RTC_CAL_Y, bin2bcd(year % 100))
166              | FIELD_PREP(CDNS_RTC_CAL_C, bin2bcd(year / 100))
167              | FIELD_PREP(CDNS_RTC_CAL_DAY, tm->tm_wday + 1);
168
169         /* Update registers, check valid flags */
170         for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
171                 writel(timr, crtc->regs + CDNS_RTC_TIMR);
172                 writel(calr, crtc->regs + CDNS_RTC_CALR);
173                 stsr = readl(crtc->regs + CDNS_RTC_STSR);
174
175                 if ((stsr & CDNS_RTC_STSR_VT_VC) == CDNS_RTC_STSR_VT_VC) {
176                         ret = 0;
177                         break;
178                 }
179         }
180
181         cdns_rtc_set_enabled(crtc, true);
182         return ret;
183 }
184
185 static int cdns_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
186 {
187         struct cdns_rtc *crtc = dev_get_drvdata(dev);
188
189         if (enabled) {
190                 writel((CDNS_RTC_AEI_SEC | CDNS_RTC_AEI_MIN | CDNS_RTC_AEI_HOUR
191                         | CDNS_RTC_AEI_DATE | CDNS_RTC_AEI_MNTH),
192                        crtc->regs + CDNS_RTC_AENR);
193                 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IENR);
194         } else {
195                 writel(0, crtc->regs + CDNS_RTC_AENR);
196                 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IDISR);
197         }
198
199         return 0;
200 }
201
202 static int cdns_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
203 {
204         struct cdns_rtc *crtc = dev_get_drvdata(dev);
205         u32 reg;
206
207         reg = readl(crtc->regs + CDNS_RTC_TIMAR);
208         cdns_rtc_reg2time(reg, &alarm->time);
209
210         reg = readl(crtc->regs + CDNS_RTC_CALAR);
211         alarm->time.tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
212         alarm->time.tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
213
214         return 0;
215 }
216
217 static int cdns_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
218 {
219         struct cdns_rtc *crtc = dev_get_drvdata(dev);
220         int ret = -EIO;
221         int tries;
222         u32 timar, calar, stsr;
223
224         cdns_rtc_alarm_irq_enable(dev, 0);
225
226         timar = cdns_rtc_time2reg(&alarm->time);
227         calar = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(alarm->time.tm_mday))
228               | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(alarm->time.tm_mon + 1));
229
230         /* Update registers, check valid alarm flags */
231         for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
232                 writel(timar, crtc->regs + CDNS_RTC_TIMAR);
233                 writel(calar, crtc->regs + CDNS_RTC_CALAR);
234                 stsr = readl(crtc->regs + CDNS_RTC_STSR);
235
236                 if ((stsr & CDNS_RTC_STSR_VTA_VCA) == CDNS_RTC_STSR_VTA_VCA) {
237                         ret = 0;
238                         break;
239                 }
240         }
241
242         if (!ret)
243                 cdns_rtc_alarm_irq_enable(dev, alarm->enabled);
244         return ret;
245 }
246
247 static const struct rtc_class_ops cdns_rtc_ops = {
248         .read_time      = cdns_rtc_read_time,
249         .set_time       = cdns_rtc_set_time,
250         .read_alarm     = cdns_rtc_read_alarm,
251         .set_alarm      = cdns_rtc_set_alarm,
252         .alarm_irq_enable = cdns_rtc_alarm_irq_enable,
253 };
254
255 static int cdns_rtc_probe(struct platform_device *pdev)
256 {
257         struct cdns_rtc *crtc;
258         int ret;
259         unsigned long ref_clk_freq;
260
261         crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL);
262         if (!crtc)
263                 return -ENOMEM;
264
265         crtc->regs = devm_platform_ioremap_resource(pdev, 0);
266         if (IS_ERR(crtc->regs))
267                 return PTR_ERR(crtc->regs);
268
269         crtc->irq = platform_get_irq(pdev, 0);
270         if (crtc->irq < 0)
271                 return -EINVAL;
272
273         crtc->pclk = devm_clk_get(&pdev->dev, "pclk");
274         if (IS_ERR(crtc->pclk)) {
275                 ret = PTR_ERR(crtc->pclk);
276                 dev_err(&pdev->dev,
277                         "Failed to retrieve the peripheral clock, %d\n", ret);
278                 return ret;
279         }
280
281         crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
282         if (IS_ERR(crtc->ref_clk)) {
283                 ret = PTR_ERR(crtc->ref_clk);
284                 dev_err(&pdev->dev,
285                         "Failed to retrieve the reference clock, %d\n", ret);
286                 return ret;
287         }
288
289         crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
290         if (IS_ERR(crtc->rtc_dev))
291                 return PTR_ERR(crtc->rtc_dev);
292
293         platform_set_drvdata(pdev, crtc);
294
295         ret = clk_prepare_enable(crtc->pclk);
296         if (ret) {
297                 dev_err(&pdev->dev,
298                         "Failed to enable the peripheral clock, %d\n", ret);
299                 return ret;
300         }
301
302         ret = clk_prepare_enable(crtc->ref_clk);
303         if (ret) {
304                 dev_err(&pdev->dev,
305                         "Failed to enable the reference clock, %d\n", ret);
306                 goto err_disable_pclk;
307         }
308
309         ref_clk_freq = clk_get_rate(crtc->ref_clk);
310         if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) {
311                 dev_err(&pdev->dev,
312                         "Invalid reference clock frequency %lu Hz.\n",
313                         ref_clk_freq);
314                 ret = -EINVAL;
315                 goto err_disable_ref_clk;
316         }
317
318         ret = devm_request_irq(&pdev->dev, crtc->irq,
319                                cdns_rtc_irq_handler, 0,
320                                dev_name(&pdev->dev), &pdev->dev);
321         if (ret) {
322                 dev_err(&pdev->dev,
323                         "Failed to request interrupt for the device, %d\n",
324                         ret);
325                 goto err_disable_ref_clk;
326         }
327
328         /* The RTC supports 01.01.1900 - 31.12.2999 */
329         crtc->rtc_dev->range_min = mktime64(1900,  1,  1,  0,  0,  0);
330         crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59);
331
332         crtc->rtc_dev->ops = &cdns_rtc_ops;
333         device_init_wakeup(&pdev->dev, true);
334
335         /* Always use 24-hour mode and keep the RTC values */
336         writel(0, crtc->regs + CDNS_RTC_HMR);
337         writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);
338
339         ret = devm_rtc_register_device(crtc->rtc_dev);
340         if (ret)
341                 goto err_disable_wakeup;
342
343         return 0;
344
345 err_disable_wakeup:
346         device_init_wakeup(&pdev->dev, false);
347
348 err_disable_ref_clk:
349         clk_disable_unprepare(crtc->ref_clk);
350
351 err_disable_pclk:
352         clk_disable_unprepare(crtc->pclk);
353
354         return ret;
355 }
356
357 static void cdns_rtc_remove(struct platform_device *pdev)
358 {
359         struct cdns_rtc *crtc = platform_get_drvdata(pdev);
360
361         cdns_rtc_alarm_irq_enable(&pdev->dev, 0);
362         device_init_wakeup(&pdev->dev, 0);
363
364         clk_disable_unprepare(crtc->pclk);
365         clk_disable_unprepare(crtc->ref_clk);
366 }
367
368 #ifdef CONFIG_PM_SLEEP
369 static int cdns_rtc_suspend(struct device *dev)
370 {
371         struct cdns_rtc *crtc = dev_get_drvdata(dev);
372
373         if (device_may_wakeup(dev))
374                 enable_irq_wake(crtc->irq);
375
376         return 0;
377 }
378
379 static int cdns_rtc_resume(struct device *dev)
380 {
381         struct cdns_rtc *crtc = dev_get_drvdata(dev);
382
383         if (device_may_wakeup(dev))
384                 disable_irq_wake(crtc->irq);
385
386         return 0;
387 }
388 #endif
389
390 static SIMPLE_DEV_PM_OPS(cdns_rtc_pm_ops, cdns_rtc_suspend, cdns_rtc_resume);
391
392 static const struct of_device_id cdns_rtc_of_match[] = {
393         { .compatible = "cdns,rtc-r109v3" },
394         { },
395 };
396 MODULE_DEVICE_TABLE(of, cdns_rtc_of_match);
397
398 static struct platform_driver cdns_rtc_driver = {
399         .driver = {
400                 .name = "cdns-rtc",
401                 .of_match_table = cdns_rtc_of_match,
402                 .pm = &cdns_rtc_pm_ops,
403         },
404         .probe = cdns_rtc_probe,
405         .remove_new = cdns_rtc_remove,
406 };
407 module_platform_driver(cdns_rtc_driver);
408
409 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
410 MODULE_DESCRIPTION("Cadence RTC driver");
411 MODULE_LICENSE("GPL v2");
412 MODULE_ALIAS("platform:cdns-rtc");