Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / rtc / rtc-s3c.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* drivers/rtc/rtc-s3c.c
3  *
4  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5  *              http://www.samsung.com/
6  *
7  * Copyright (c) 2004,2006 Simtec Electronics
8  *      Ben Dooks, <ben@simtec.co.uk>
9  *      http://armlinux.simtec.co.uk/
10  *
11  * S3C2410/S3C2440/S3C24XX Internal RTC Driver
12 */
13
14 #include <linux/module.h>
15 #include <linux/fs.h>
16 #include <linux/string.h>
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/interrupt.h>
20 #include <linux/rtc.h>
21 #include <linux/bcd.h>
22 #include <linux/clk.h>
23 #include <linux/log2.h>
24 #include <linux/slab.h>
25 #include <linux/of.h>
26 #include <linux/of_device.h>
27 #include <linux/uaccess.h>
28 #include <linux/io.h>
29
30 #include <asm/irq.h>
31 #include "rtc-s3c.h"
32
33 struct s3c_rtc {
34         struct device *dev;
35         struct rtc_device *rtc;
36
37         void __iomem *base;
38         struct clk *rtc_clk;
39         struct clk *rtc_src_clk;
40         bool alarm_enabled;
41
42         const struct s3c_rtc_data *data;
43
44         int irq_alarm;
45         spinlock_t alarm_lock;
46
47         bool wake_en;
48 };
49
50 struct s3c_rtc_data {
51         bool needs_src_clk;
52
53         void (*irq_handler) (struct s3c_rtc *info, int mask);
54         void (*enable) (struct s3c_rtc *info);
55         void (*disable) (struct s3c_rtc *info);
56 };
57
58 static int s3c_rtc_enable_clk(struct s3c_rtc *info)
59 {
60         int ret;
61
62         ret = clk_enable(info->rtc_clk);
63         if (ret)
64                 return ret;
65
66         if (info->data->needs_src_clk) {
67                 ret = clk_enable(info->rtc_src_clk);
68                 if (ret) {
69                         clk_disable(info->rtc_clk);
70                         return ret;
71                 }
72         }
73         return 0;
74 }
75
76 static void s3c_rtc_disable_clk(struct s3c_rtc *info)
77 {
78         if (info->data->needs_src_clk)
79                 clk_disable(info->rtc_src_clk);
80         clk_disable(info->rtc_clk);
81 }
82
83 /* IRQ Handler */
84 static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
85 {
86         struct s3c_rtc *info = (struct s3c_rtc *)id;
87
88         if (info->data->irq_handler)
89                 info->data->irq_handler(info, S3C2410_INTP_ALM);
90
91         return IRQ_HANDLED;
92 }
93
94 /* Update control registers */
95 static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
96 {
97         struct s3c_rtc *info = dev_get_drvdata(dev);
98         unsigned long flags;
99         unsigned int tmp;
100         int ret;
101
102         dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
103
104         ret = s3c_rtc_enable_clk(info);
105         if (ret)
106                 return ret;
107
108         tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
109
110         if (enabled)
111                 tmp |= S3C2410_RTCALM_ALMEN;
112
113         writeb(tmp, info->base + S3C2410_RTCALM);
114
115         spin_lock_irqsave(&info->alarm_lock, flags);
116
117         if (info->alarm_enabled && !enabled)
118                 s3c_rtc_disable_clk(info);
119         else if (!info->alarm_enabled && enabled)
120                 ret = s3c_rtc_enable_clk(info);
121
122         info->alarm_enabled = enabled;
123         spin_unlock_irqrestore(&info->alarm_lock, flags);
124
125         s3c_rtc_disable_clk(info);
126
127         return ret;
128 }
129
130 /* Time read/write */
131 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
132 {
133         struct s3c_rtc *info = dev_get_drvdata(dev);
134         unsigned int have_retried = 0;
135         int ret;
136
137         ret = s3c_rtc_enable_clk(info);
138         if (ret)
139                 return ret;
140
141 retry_get_time:
142         rtc_tm->tm_min  = readb(info->base + S3C2410_RTCMIN);
143         rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
144         rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
145         rtc_tm->tm_mon  = readb(info->base + S3C2410_RTCMON);
146         rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
147         rtc_tm->tm_sec  = readb(info->base + S3C2410_RTCSEC);
148
149         /* the only way to work out whether the system was mid-update
150          * when we read it is to check the second counter, and if it
151          * is zero, then we re-try the entire read
152          */
153
154         if (rtc_tm->tm_sec == 0 && !have_retried) {
155                 have_retried = 1;
156                 goto retry_get_time;
157         }
158
159         rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
160         rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
161         rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
162         rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
163         rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
164         rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
165
166         s3c_rtc_disable_clk(info);
167
168         rtc_tm->tm_year += 100;
169         rtc_tm->tm_mon -= 1;
170
171         dev_dbg(dev, "read time %ptR\n", rtc_tm);
172         return 0;
173 }
174
175 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
176 {
177         struct s3c_rtc *info = dev_get_drvdata(dev);
178         int year = tm->tm_year - 100;
179         int ret;
180
181         dev_dbg(dev, "set time %ptR\n", tm);
182
183         /* we get around y2k by simply not supporting it */
184
185         if (year < 0 || year >= 100) {
186                 dev_err(dev, "rtc only supports 100 years\n");
187                 return -EINVAL;
188         }
189
190         ret = s3c_rtc_enable_clk(info);
191         if (ret)
192                 return ret;
193
194         writeb(bin2bcd(tm->tm_sec),  info->base + S3C2410_RTCSEC);
195         writeb(bin2bcd(tm->tm_min),  info->base + S3C2410_RTCMIN);
196         writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
197         writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
198         writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
199         writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
200
201         s3c_rtc_disable_clk(info);
202
203         return 0;
204 }
205
206 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
207 {
208         struct s3c_rtc *info = dev_get_drvdata(dev);
209         struct rtc_time *alm_tm = &alrm->time;
210         unsigned int alm_en;
211         int ret;
212
213         ret = s3c_rtc_enable_clk(info);
214         if (ret)
215                 return ret;
216
217         alm_tm->tm_sec  = readb(info->base + S3C2410_ALMSEC);
218         alm_tm->tm_min  = readb(info->base + S3C2410_ALMMIN);
219         alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
220         alm_tm->tm_mon  = readb(info->base + S3C2410_ALMMON);
221         alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE);
222         alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR);
223
224         alm_en = readb(info->base + S3C2410_RTCALM);
225
226         s3c_rtc_disable_clk(info);
227
228         alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
229
230         dev_dbg(dev, "read alarm %d, %ptR\n", alm_en, alm_tm);
231
232         /* decode the alarm enable field */
233         if (alm_en & S3C2410_RTCALM_SECEN)
234                 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
235
236         if (alm_en & S3C2410_RTCALM_MINEN)
237                 alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
238
239         if (alm_en & S3C2410_RTCALM_HOUREN)
240                 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
241
242         if (alm_en & S3C2410_RTCALM_DAYEN)
243                 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
244
245         if (alm_en & S3C2410_RTCALM_MONEN) {
246                 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
247                 alm_tm->tm_mon -= 1;
248         }
249
250         if (alm_en & S3C2410_RTCALM_YEAREN)
251                 alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
252
253         return 0;
254 }
255
256 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
257 {
258         struct s3c_rtc *info = dev_get_drvdata(dev);
259         struct rtc_time *tm = &alrm->time;
260         unsigned int alrm_en;
261         int ret;
262
263         dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR\n", alrm->enabled, tm);
264
265         ret = s3c_rtc_enable_clk(info);
266         if (ret)
267                 return ret;
268
269         alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
270         writeb(0x00, info->base + S3C2410_RTCALM);
271
272         if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
273                 alrm_en |= S3C2410_RTCALM_SECEN;
274                 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC);
275         }
276
277         if (tm->tm_min < 60 && tm->tm_min >= 0) {
278                 alrm_en |= S3C2410_RTCALM_MINEN;
279                 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN);
280         }
281
282         if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
283                 alrm_en |= S3C2410_RTCALM_HOUREN;
284                 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
285         }
286
287         if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
288                 alrm_en |= S3C2410_RTCALM_MONEN;
289                 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
290         }
291
292         if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
293                 alrm_en |= S3C2410_RTCALM_DAYEN;
294                 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
295         }
296
297         dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
298
299         writeb(alrm_en, info->base + S3C2410_RTCALM);
300
301         s3c_rtc_setaie(dev, alrm->enabled);
302
303         s3c_rtc_disable_clk(info);
304
305         return 0;
306 }
307
308 static const struct rtc_class_ops s3c_rtcops = {
309         .read_time      = s3c_rtc_gettime,
310         .set_time       = s3c_rtc_settime,
311         .read_alarm     = s3c_rtc_getalarm,
312         .set_alarm      = s3c_rtc_setalarm,
313         .alarm_irq_enable = s3c_rtc_setaie,
314 };
315
316 static void s3c24xx_rtc_enable(struct s3c_rtc *info)
317 {
318         unsigned int con, tmp;
319
320         con = readw(info->base + S3C2410_RTCCON);
321         /* re-enable the device, and check it is ok */
322         if ((con & S3C2410_RTCCON_RTCEN) == 0) {
323                 dev_info(info->dev, "rtc disabled, re-enabling\n");
324
325                 tmp = readw(info->base + S3C2410_RTCCON);
326                 writew(tmp | S3C2410_RTCCON_RTCEN, info->base + S3C2410_RTCCON);
327         }
328
329         if (con & S3C2410_RTCCON_CNTSEL) {
330                 dev_info(info->dev, "removing RTCCON_CNTSEL\n");
331
332                 tmp = readw(info->base + S3C2410_RTCCON);
333                 writew(tmp & ~S3C2410_RTCCON_CNTSEL,
334                        info->base + S3C2410_RTCCON);
335         }
336
337         if (con & S3C2410_RTCCON_CLKRST) {
338                 dev_info(info->dev, "removing RTCCON_CLKRST\n");
339
340                 tmp = readw(info->base + S3C2410_RTCCON);
341                 writew(tmp & ~S3C2410_RTCCON_CLKRST,
342                        info->base + S3C2410_RTCCON);
343         }
344 }
345
346 static void s3c24xx_rtc_disable(struct s3c_rtc *info)
347 {
348         unsigned int con;
349
350         con = readw(info->base + S3C2410_RTCCON);
351         con &= ~S3C2410_RTCCON_RTCEN;
352         writew(con, info->base + S3C2410_RTCCON);
353
354         con = readb(info->base + S3C2410_TICNT);
355         con &= ~S3C2410_TICNT_ENABLE;
356         writeb(con, info->base + S3C2410_TICNT);
357 }
358
359 static void s3c6410_rtc_disable(struct s3c_rtc *info)
360 {
361         unsigned int con;
362
363         con = readw(info->base + S3C2410_RTCCON);
364         con &= ~S3C64XX_RTCCON_TICEN;
365         con &= ~S3C2410_RTCCON_RTCEN;
366         writew(con, info->base + S3C2410_RTCCON);
367 }
368
369 static int s3c_rtc_remove(struct platform_device *pdev)
370 {
371         struct s3c_rtc *info = platform_get_drvdata(pdev);
372
373         s3c_rtc_setaie(info->dev, 0);
374
375         if (info->data->needs_src_clk)
376                 clk_unprepare(info->rtc_src_clk);
377         clk_unprepare(info->rtc_clk);
378
379         return 0;
380 }
381
382 static int s3c_rtc_probe(struct platform_device *pdev)
383 {
384         struct s3c_rtc *info = NULL;
385         struct rtc_time rtc_tm;
386         int ret;
387
388         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
389         if (!info)
390                 return -ENOMEM;
391
392         info->dev = &pdev->dev;
393         info->data = of_device_get_match_data(&pdev->dev);
394         if (!info->data) {
395                 dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
396                 return -EINVAL;
397         }
398         spin_lock_init(&info->alarm_lock);
399
400         platform_set_drvdata(pdev, info);
401
402         info->irq_alarm = platform_get_irq(pdev, 0);
403         if (info->irq_alarm < 0)
404                 return info->irq_alarm;
405
406         dev_dbg(&pdev->dev, "s3c2410_rtc: alarm irq %d\n", info->irq_alarm);
407
408         /* get the memory region */
409         info->base = devm_platform_ioremap_resource(pdev, 0);
410         if (IS_ERR(info->base))
411                 return PTR_ERR(info->base);
412
413         info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
414         if (IS_ERR(info->rtc_clk)) {
415                 ret = PTR_ERR(info->rtc_clk);
416                 if (ret != -EPROBE_DEFER)
417                         dev_err(&pdev->dev, "failed to find rtc clock\n");
418                 else
419                         dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n");
420                 return ret;
421         }
422         ret = clk_prepare_enable(info->rtc_clk);
423         if (ret)
424                 return ret;
425
426         if (info->data->needs_src_clk) {
427                 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
428                 if (IS_ERR(info->rtc_src_clk)) {
429                         ret = dev_err_probe(&pdev->dev, PTR_ERR(info->rtc_src_clk),
430                                             "failed to find rtc source clock\n");
431                         goto err_src_clk;
432                 }
433                 ret = clk_prepare_enable(info->rtc_src_clk);
434                 if (ret)
435                         goto err_src_clk;
436         }
437
438         /* disable RTC enable bits potentially set by the bootloader */
439         if (info->data->disable)
440                 info->data->disable(info);
441
442         /* check to see if everything is setup correctly */
443         if (info->data->enable)
444                 info->data->enable(info);
445
446         dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
447                 readw(info->base + S3C2410_RTCCON));
448
449         device_init_wakeup(&pdev->dev, 1);
450
451         /* Check RTC Time */
452         if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) {
453                 rtc_tm.tm_year  = 100;
454                 rtc_tm.tm_mon   = 0;
455                 rtc_tm.tm_mday  = 1;
456                 rtc_tm.tm_hour  = 0;
457                 rtc_tm.tm_min   = 0;
458                 rtc_tm.tm_sec   = 0;
459
460                 s3c_rtc_settime(&pdev->dev, &rtc_tm);
461
462                 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
463         }
464
465         /* register RTC and exit */
466         info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
467                                              THIS_MODULE);
468         if (IS_ERR(info->rtc)) {
469                 dev_err(&pdev->dev, "cannot attach rtc\n");
470                 ret = PTR_ERR(info->rtc);
471                 goto err_nortc;
472         }
473
474         ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
475                                0, "s3c2410-rtc alarm", info);
476         if (ret) {
477                 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
478                 goto err_nortc;
479         }
480
481         s3c_rtc_disable_clk(info);
482
483         return 0;
484
485 err_nortc:
486         if (info->data->disable)
487                 info->data->disable(info);
488
489         if (info->data->needs_src_clk)
490                 clk_disable_unprepare(info->rtc_src_clk);
491 err_src_clk:
492         clk_disable_unprepare(info->rtc_clk);
493
494         return ret;
495 }
496
497 #ifdef CONFIG_PM_SLEEP
498
499 static int s3c_rtc_suspend(struct device *dev)
500 {
501         struct s3c_rtc *info = dev_get_drvdata(dev);
502         int ret;
503
504         ret = s3c_rtc_enable_clk(info);
505         if (ret)
506                 return ret;
507
508         if (info->data->disable)
509                 info->data->disable(info);
510
511         if (device_may_wakeup(dev) && !info->wake_en) {
512                 if (enable_irq_wake(info->irq_alarm) == 0)
513                         info->wake_en = true;
514                 else
515                         dev_err(dev, "enable_irq_wake failed\n");
516         }
517
518         return 0;
519 }
520
521 static int s3c_rtc_resume(struct device *dev)
522 {
523         struct s3c_rtc *info = dev_get_drvdata(dev);
524
525         if (info->data->enable)
526                 info->data->enable(info);
527
528         s3c_rtc_disable_clk(info);
529
530         if (device_may_wakeup(dev) && info->wake_en) {
531                 disable_irq_wake(info->irq_alarm);
532                 info->wake_en = false;
533         }
534
535         return 0;
536 }
537 #endif
538 static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
539
540 static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
541 {
542         rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
543 }
544
545 static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
546 {
547         rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
548         writeb(mask, info->base + S3C2410_INTP);
549 }
550
551 static struct s3c_rtc_data const s3c2410_rtc_data = {
552         .irq_handler            = s3c24xx_rtc_irq,
553         .enable                 = s3c24xx_rtc_enable,
554         .disable                = s3c24xx_rtc_disable,
555 };
556
557 static struct s3c_rtc_data const s3c2416_rtc_data = {
558         .irq_handler            = s3c24xx_rtc_irq,
559         .enable                 = s3c24xx_rtc_enable,
560         .disable                = s3c24xx_rtc_disable,
561 };
562
563 static struct s3c_rtc_data const s3c2443_rtc_data = {
564         .irq_handler            = s3c24xx_rtc_irq,
565         .enable                 = s3c24xx_rtc_enable,
566         .disable                = s3c24xx_rtc_disable,
567 };
568
569 static struct s3c_rtc_data const s3c6410_rtc_data = {
570         .needs_src_clk          = true,
571         .irq_handler            = s3c6410_rtc_irq,
572         .enable                 = s3c24xx_rtc_enable,
573         .disable                = s3c6410_rtc_disable,
574 };
575
576 static const struct of_device_id s3c_rtc_dt_match[] = {
577         {
578                 .compatible = "samsung,s3c2410-rtc",
579                 .data = &s3c2410_rtc_data,
580         }, {
581                 .compatible = "samsung,s3c2416-rtc",
582                 .data = &s3c2416_rtc_data,
583         }, {
584                 .compatible = "samsung,s3c2443-rtc",
585                 .data = &s3c2443_rtc_data,
586         }, {
587                 .compatible = "samsung,s3c6410-rtc",
588                 .data = &s3c6410_rtc_data,
589         }, {
590                 .compatible = "samsung,exynos3250-rtc",
591                 .data = &s3c6410_rtc_data,
592         },
593         { /* sentinel */ },
594 };
595 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
596
597 static struct platform_driver s3c_rtc_driver = {
598         .probe          = s3c_rtc_probe,
599         .remove         = s3c_rtc_remove,
600         .driver         = {
601                 .name   = "s3c-rtc",
602                 .pm     = &s3c_rtc_pm_ops,
603                 .of_match_table = of_match_ptr(s3c_rtc_dt_match),
604         },
605 };
606 module_platform_driver(s3c_rtc_driver);
607
608 MODULE_DESCRIPTION("Samsung S3C RTC Driver");
609 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
610 MODULE_LICENSE("GPL");
611 MODULE_ALIAS("platform:s3c2410-rtc");