Merge tag 'dmaengine-5.1-rc1' of git://git.infradead.org/users/vkoul/slave-dma
[linux-2.6-microblaze.git] / drivers / rtc / rtc-s3c.c
1 /* drivers/rtc/rtc-s3c.c
2  *
3  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
6  * Copyright (c) 2004,2006 Simtec Electronics
7  *      Ben Dooks, <ben@simtec.co.uk>
8  *      http://armlinux.simtec.co.uk/
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * S3C2410/S3C2440/S3C24XX Internal RTC Driver
15 */
16
17 #include <linux/module.h>
18 #include <linux/fs.h>
19 #include <linux/string.h>
20 #include <linux/init.h>
21 #include <linux/platform_device.h>
22 #include <linux/interrupt.h>
23 #include <linux/rtc.h>
24 #include <linux/bcd.h>
25 #include <linux/clk.h>
26 #include <linux/log2.h>
27 #include <linux/slab.h>
28 #include <linux/of.h>
29 #include <linux/of_device.h>
30 #include <linux/uaccess.h>
31 #include <linux/io.h>
32
33 #include <asm/irq.h>
34 #include "rtc-s3c.h"
35
36 struct s3c_rtc {
37         struct device *dev;
38         struct rtc_device *rtc;
39
40         void __iomem *base;
41         struct clk *rtc_clk;
42         struct clk *rtc_src_clk;
43         bool alarm_enabled;
44
45         const struct s3c_rtc_data *data;
46
47         int irq_alarm;
48         int irq_tick;
49
50         spinlock_t pie_lock;
51         spinlock_t alarm_lock;
52
53         int ticnt_save;
54         int ticnt_en_save;
55         bool wake_en;
56 };
57
58 struct s3c_rtc_data {
59         int max_user_freq;
60         bool needs_src_clk;
61
62         void (*irq_handler) (struct s3c_rtc *info, int mask);
63         void (*set_freq) (struct s3c_rtc *info, int freq);
64         void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq);
65         void (*select_tick_clk) (struct s3c_rtc *info);
66         void (*save_tick_cnt) (struct s3c_rtc *info);
67         void (*restore_tick_cnt) (struct s3c_rtc *info);
68         void (*enable) (struct s3c_rtc *info);
69         void (*disable) (struct s3c_rtc *info);
70 };
71
72 static int s3c_rtc_enable_clk(struct s3c_rtc *info)
73 {
74         int ret;
75
76         ret = clk_enable(info->rtc_clk);
77         if (ret)
78                 return ret;
79
80         if (info->data->needs_src_clk) {
81                 ret = clk_enable(info->rtc_src_clk);
82                 if (ret) {
83                         clk_disable(info->rtc_clk);
84                         return ret;
85                 }
86         }
87         return 0;
88 }
89
90 static void s3c_rtc_disable_clk(struct s3c_rtc *info)
91 {
92         if (info->data->needs_src_clk)
93                 clk_disable(info->rtc_src_clk);
94         clk_disable(info->rtc_clk);
95 }
96
97 /* IRQ Handlers */
98 static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
99 {
100         struct s3c_rtc *info = (struct s3c_rtc *)id;
101
102         if (info->data->irq_handler)
103                 info->data->irq_handler(info, S3C2410_INTP_TIC);
104
105         return IRQ_HANDLED;
106 }
107
108 static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
109 {
110         struct s3c_rtc *info = (struct s3c_rtc *)id;
111
112         if (info->data->irq_handler)
113                 info->data->irq_handler(info, S3C2410_INTP_ALM);
114
115         return IRQ_HANDLED;
116 }
117
118 /* Update control registers */
119 static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
120 {
121         struct s3c_rtc *info = dev_get_drvdata(dev);
122         unsigned long flags;
123         unsigned int tmp;
124         int ret;
125
126         dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
127
128         ret = s3c_rtc_enable_clk(info);
129         if (ret)
130                 return ret;
131
132         tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
133
134         if (enabled)
135                 tmp |= S3C2410_RTCALM_ALMEN;
136
137         writeb(tmp, info->base + S3C2410_RTCALM);
138
139         spin_lock_irqsave(&info->alarm_lock, flags);
140
141         if (info->alarm_enabled && !enabled)
142                 s3c_rtc_disable_clk(info);
143         else if (!info->alarm_enabled && enabled)
144                 ret = s3c_rtc_enable_clk(info);
145
146         info->alarm_enabled = enabled;
147         spin_unlock_irqrestore(&info->alarm_lock, flags);
148
149         s3c_rtc_disable_clk(info);
150
151         return ret;
152 }
153
154 /* Set RTC frequency */
155 static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
156 {
157         int ret;
158
159         if (!is_power_of_2(freq))
160                 return -EINVAL;
161
162         ret = s3c_rtc_enable_clk(info);
163         if (ret)
164                 return ret;
165         spin_lock_irq(&info->pie_lock);
166
167         if (info->data->set_freq)
168                 info->data->set_freq(info, freq);
169
170         spin_unlock_irq(&info->pie_lock);
171         s3c_rtc_disable_clk(info);
172
173         return 0;
174 }
175
176 /* Time read/write */
177 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
178 {
179         struct s3c_rtc *info = dev_get_drvdata(dev);
180         unsigned int have_retried = 0;
181         int ret;
182
183         ret = s3c_rtc_enable_clk(info);
184         if (ret)
185                 return ret;
186
187 retry_get_time:
188         rtc_tm->tm_min  = readb(info->base + S3C2410_RTCMIN);
189         rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
190         rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
191         rtc_tm->tm_mon  = readb(info->base + S3C2410_RTCMON);
192         rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
193         rtc_tm->tm_sec  = readb(info->base + S3C2410_RTCSEC);
194
195         /* the only way to work out whether the system was mid-update
196          * when we read it is to check the second counter, and if it
197          * is zero, then we re-try the entire read
198          */
199
200         if (rtc_tm->tm_sec == 0 && !have_retried) {
201                 have_retried = 1;
202                 goto retry_get_time;
203         }
204
205         rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
206         rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
207         rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
208         rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
209         rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
210         rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
211
212         s3c_rtc_disable_clk(info);
213
214         rtc_tm->tm_year += 100;
215         rtc_tm->tm_mon -= 1;
216
217         dev_dbg(dev, "read time %ptR\n", rtc_tm);
218         return 0;
219 }
220
221 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
222 {
223         struct s3c_rtc *info = dev_get_drvdata(dev);
224         int year = tm->tm_year - 100;
225         int ret;
226
227         dev_dbg(dev, "set time %ptR\n", tm);
228
229         /* we get around y2k by simply not supporting it */
230
231         if (year < 0 || year >= 100) {
232                 dev_err(dev, "rtc only supports 100 years\n");
233                 return -EINVAL;
234         }
235
236         ret = s3c_rtc_enable_clk(info);
237         if (ret)
238                 return ret;
239
240         writeb(bin2bcd(tm->tm_sec),  info->base + S3C2410_RTCSEC);
241         writeb(bin2bcd(tm->tm_min),  info->base + S3C2410_RTCMIN);
242         writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
243         writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
244         writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
245         writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
246
247         s3c_rtc_disable_clk(info);
248
249         return 0;
250 }
251
252 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
253 {
254         struct s3c_rtc *info = dev_get_drvdata(dev);
255         struct rtc_time *alm_tm = &alrm->time;
256         unsigned int alm_en;
257         int ret;
258
259         ret = s3c_rtc_enable_clk(info);
260         if (ret)
261                 return ret;
262
263         alm_tm->tm_sec  = readb(info->base + S3C2410_ALMSEC);
264         alm_tm->tm_min  = readb(info->base + S3C2410_ALMMIN);
265         alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
266         alm_tm->tm_mon  = readb(info->base + S3C2410_ALMMON);
267         alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE);
268         alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR);
269
270         alm_en = readb(info->base + S3C2410_RTCALM);
271
272         s3c_rtc_disable_clk(info);
273
274         alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
275
276         dev_dbg(dev, "read alarm %d, %ptR\n", alm_en, alm_tm);
277
278         /* decode the alarm enable field */
279         if (alm_en & S3C2410_RTCALM_SECEN)
280                 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
281
282         if (alm_en & S3C2410_RTCALM_MINEN)
283                 alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
284
285         if (alm_en & S3C2410_RTCALM_HOUREN)
286                 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
287
288         if (alm_en & S3C2410_RTCALM_DAYEN)
289                 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
290
291         if (alm_en & S3C2410_RTCALM_MONEN) {
292                 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
293                 alm_tm->tm_mon -= 1;
294         }
295
296         if (alm_en & S3C2410_RTCALM_YEAREN)
297                 alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
298
299         return 0;
300 }
301
302 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
303 {
304         struct s3c_rtc *info = dev_get_drvdata(dev);
305         struct rtc_time *tm = &alrm->time;
306         unsigned int alrm_en;
307         int ret;
308
309         dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR\n", alrm->enabled, tm);
310
311         ret = s3c_rtc_enable_clk(info);
312         if (ret)
313                 return ret;
314
315         alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
316         writeb(0x00, info->base + S3C2410_RTCALM);
317
318         if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
319                 alrm_en |= S3C2410_RTCALM_SECEN;
320                 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC);
321         }
322
323         if (tm->tm_min < 60 && tm->tm_min >= 0) {
324                 alrm_en |= S3C2410_RTCALM_MINEN;
325                 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN);
326         }
327
328         if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
329                 alrm_en |= S3C2410_RTCALM_HOUREN;
330                 writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
331         }
332
333         if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
334                 alrm_en |= S3C2410_RTCALM_MONEN;
335                 writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
336         }
337
338         if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
339                 alrm_en |= S3C2410_RTCALM_DAYEN;
340                 writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
341         }
342
343         dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
344
345         writeb(alrm_en, info->base + S3C2410_RTCALM);
346
347         s3c_rtc_setaie(dev, alrm->enabled);
348
349         s3c_rtc_disable_clk(info);
350
351         return 0;
352 }
353
354 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
355 {
356         struct s3c_rtc *info = dev_get_drvdata(dev);
357         int ret;
358
359         ret = s3c_rtc_enable_clk(info);
360         if (ret)
361                 return ret;
362
363         if (info->data->enable_tick)
364                 info->data->enable_tick(info, seq);
365
366         s3c_rtc_disable_clk(info);
367
368         return 0;
369 }
370
371 static const struct rtc_class_ops s3c_rtcops = {
372         .read_time      = s3c_rtc_gettime,
373         .set_time       = s3c_rtc_settime,
374         .read_alarm     = s3c_rtc_getalarm,
375         .set_alarm      = s3c_rtc_setalarm,
376         .proc           = s3c_rtc_proc,
377         .alarm_irq_enable = s3c_rtc_setaie,
378 };
379
380 static void s3c24xx_rtc_enable(struct s3c_rtc *info)
381 {
382         unsigned int con, tmp;
383
384         con = readw(info->base + S3C2410_RTCCON);
385         /* re-enable the device, and check it is ok */
386         if ((con & S3C2410_RTCCON_RTCEN) == 0) {
387                 dev_info(info->dev, "rtc disabled, re-enabling\n");
388
389                 tmp = readw(info->base + S3C2410_RTCCON);
390                 writew(tmp | S3C2410_RTCCON_RTCEN, info->base + S3C2410_RTCCON);
391         }
392
393         if (con & S3C2410_RTCCON_CNTSEL) {
394                 dev_info(info->dev, "removing RTCCON_CNTSEL\n");
395
396                 tmp = readw(info->base + S3C2410_RTCCON);
397                 writew(tmp & ~S3C2410_RTCCON_CNTSEL,
398                        info->base + S3C2410_RTCCON);
399         }
400
401         if (con & S3C2410_RTCCON_CLKRST) {
402                 dev_info(info->dev, "removing RTCCON_CLKRST\n");
403
404                 tmp = readw(info->base + S3C2410_RTCCON);
405                 writew(tmp & ~S3C2410_RTCCON_CLKRST,
406                        info->base + S3C2410_RTCCON);
407         }
408 }
409
410 static void s3c24xx_rtc_disable(struct s3c_rtc *info)
411 {
412         unsigned int con;
413
414         con = readw(info->base + S3C2410_RTCCON);
415         con &= ~S3C2410_RTCCON_RTCEN;
416         writew(con, info->base + S3C2410_RTCCON);
417
418         con = readb(info->base + S3C2410_TICNT);
419         con &= ~S3C2410_TICNT_ENABLE;
420         writeb(con, info->base + S3C2410_TICNT);
421 }
422
423 static void s3c6410_rtc_disable(struct s3c_rtc *info)
424 {
425         unsigned int con;
426
427         con = readw(info->base + S3C2410_RTCCON);
428         con &= ~S3C64XX_RTCCON_TICEN;
429         con &= ~S3C2410_RTCCON_RTCEN;
430         writew(con, info->base + S3C2410_RTCCON);
431 }
432
433 static int s3c_rtc_remove(struct platform_device *pdev)
434 {
435         struct s3c_rtc *info = platform_get_drvdata(pdev);
436
437         s3c_rtc_setaie(info->dev, 0);
438
439         if (info->data->needs_src_clk)
440                 clk_unprepare(info->rtc_src_clk);
441         clk_unprepare(info->rtc_clk);
442
443         return 0;
444 }
445
446 static int s3c_rtc_probe(struct platform_device *pdev)
447 {
448         struct s3c_rtc *info = NULL;
449         struct rtc_time rtc_tm;
450         struct resource *res;
451         int ret;
452
453         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
454         if (!info)
455                 return -ENOMEM;
456
457         /* find the IRQs */
458         info->irq_tick = platform_get_irq(pdev, 1);
459         if (info->irq_tick < 0) {
460                 dev_err(&pdev->dev, "no irq for rtc tick\n");
461                 return info->irq_tick;
462         }
463
464         info->dev = &pdev->dev;
465         info->data = of_device_get_match_data(&pdev->dev);
466         if (!info->data) {
467                 dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
468                 return -EINVAL;
469         }
470         spin_lock_init(&info->pie_lock);
471         spin_lock_init(&info->alarm_lock);
472
473         platform_set_drvdata(pdev, info);
474
475         info->irq_alarm = platform_get_irq(pdev, 0);
476         if (info->irq_alarm < 0) {
477                 dev_err(&pdev->dev, "no irq for alarm\n");
478                 return info->irq_alarm;
479         }
480
481         dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",
482                 info->irq_tick, info->irq_alarm);
483
484         /* get the memory region */
485         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
486         info->base = devm_ioremap_resource(&pdev->dev, res);
487         if (IS_ERR(info->base))
488                 return PTR_ERR(info->base);
489
490         info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
491         if (IS_ERR(info->rtc_clk)) {
492                 ret = PTR_ERR(info->rtc_clk);
493                 if (ret != -EPROBE_DEFER)
494                         dev_err(&pdev->dev, "failed to find rtc clock\n");
495                 else
496                         dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n");
497                 return ret;
498         }
499         ret = clk_prepare_enable(info->rtc_clk);
500         if (ret)
501                 return ret;
502
503         if (info->data->needs_src_clk) {
504                 info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
505                 if (IS_ERR(info->rtc_src_clk)) {
506                         ret = PTR_ERR(info->rtc_src_clk);
507                         if (ret != -EPROBE_DEFER)
508                                 dev_err(&pdev->dev,
509                                         "failed to find rtc source clock\n");
510                         else
511                                 dev_dbg(&pdev->dev,
512                                         "probe deferred due to missing rtc src clk\n");
513                         goto err_src_clk;
514                 }
515                 ret = clk_prepare_enable(info->rtc_src_clk);
516                 if (ret)
517                         goto err_src_clk;
518         }
519
520         /* check to see if everything is setup correctly */
521         if (info->data->enable)
522                 info->data->enable(info);
523
524         dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
525                 readw(info->base + S3C2410_RTCCON));
526
527         device_init_wakeup(&pdev->dev, 1);
528
529         /* Check RTC Time */
530         if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) {
531                 rtc_tm.tm_year  = 100;
532                 rtc_tm.tm_mon   = 0;
533                 rtc_tm.tm_mday  = 1;
534                 rtc_tm.tm_hour  = 0;
535                 rtc_tm.tm_min   = 0;
536                 rtc_tm.tm_sec   = 0;
537
538                 s3c_rtc_settime(&pdev->dev, &rtc_tm);
539
540                 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
541         }
542
543         /* register RTC and exit */
544         info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
545                                              THIS_MODULE);
546         if (IS_ERR(info->rtc)) {
547                 dev_err(&pdev->dev, "cannot attach rtc\n");
548                 ret = PTR_ERR(info->rtc);
549                 goto err_nortc;
550         }
551
552         ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
553                                0, "s3c2410-rtc alarm", info);
554         if (ret) {
555                 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
556                 goto err_nortc;
557         }
558
559         ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq,
560                                0, "s3c2410-rtc tick", info);
561         if (ret) {
562                 dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret);
563                 goto err_nortc;
564         }
565
566         if (info->data->select_tick_clk)
567                 info->data->select_tick_clk(info);
568
569         s3c_rtc_setfreq(info, 1);
570
571         s3c_rtc_disable_clk(info);
572
573         return 0;
574
575 err_nortc:
576         if (info->data->disable)
577                 info->data->disable(info);
578
579         if (info->data->needs_src_clk)
580                 clk_disable_unprepare(info->rtc_src_clk);
581 err_src_clk:
582         clk_disable_unprepare(info->rtc_clk);
583
584         return ret;
585 }
586
587 #ifdef CONFIG_PM_SLEEP
588
589 static int s3c_rtc_suspend(struct device *dev)
590 {
591         struct s3c_rtc *info = dev_get_drvdata(dev);
592         int ret;
593
594         ret = s3c_rtc_enable_clk(info);
595         if (ret)
596                 return ret;
597
598         /* save TICNT for anyone using periodic interrupts */
599         if (info->data->save_tick_cnt)
600                 info->data->save_tick_cnt(info);
601
602         if (info->data->disable)
603                 info->data->disable(info);
604
605         if (device_may_wakeup(dev) && !info->wake_en) {
606                 if (enable_irq_wake(info->irq_alarm) == 0)
607                         info->wake_en = true;
608                 else
609                         dev_err(dev, "enable_irq_wake failed\n");
610         }
611
612         return 0;
613 }
614
615 static int s3c_rtc_resume(struct device *dev)
616 {
617         struct s3c_rtc *info = dev_get_drvdata(dev);
618
619         if (info->data->enable)
620                 info->data->enable(info);
621
622         if (info->data->restore_tick_cnt)
623                 info->data->restore_tick_cnt(info);
624
625         s3c_rtc_disable_clk(info);
626
627         if (device_may_wakeup(dev) && info->wake_en) {
628                 disable_irq_wake(info->irq_alarm);
629                 info->wake_en = false;
630         }
631
632         return 0;
633 }
634 #endif
635 static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
636
637 static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
638 {
639         rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
640 }
641
642 static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
643 {
644         rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
645         writeb(mask, info->base + S3C2410_INTP);
646 }
647
648 static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq)
649 {
650         unsigned int tmp = 0;
651         int val;
652
653         tmp = readb(info->base + S3C2410_TICNT);
654         tmp &= S3C2410_TICNT_ENABLE;
655
656         val = (info->rtc->max_user_freq / freq) - 1;
657         tmp |= val;
658
659         writel(tmp, info->base + S3C2410_TICNT);
660 }
661
662 static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq)
663 {
664         unsigned int tmp = 0;
665         int val;
666
667         tmp = readb(info->base + S3C2410_TICNT);
668         tmp &= S3C2410_TICNT_ENABLE;
669
670         val = (info->rtc->max_user_freq / freq) - 1;
671
672         tmp |= S3C2443_TICNT_PART(val);
673         writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
674
675         writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2);
676
677         writel(tmp, info->base + S3C2410_TICNT);
678 }
679
680 static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq)
681 {
682         unsigned int tmp = 0;
683         int val;
684
685         tmp = readb(info->base + S3C2410_TICNT);
686         tmp &= S3C2410_TICNT_ENABLE;
687
688         val = (info->rtc->max_user_freq / freq) - 1;
689
690         tmp |= S3C2443_TICNT_PART(val);
691         writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
692
693         writel(tmp, info->base + S3C2410_TICNT);
694 }
695
696 static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq)
697 {
698         int val;
699
700         val = (info->rtc->max_user_freq / freq) - 1;
701         writel(val, info->base + S3C2410_TICNT);
702 }
703
704 static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
705 {
706         unsigned int ticnt;
707
708         ticnt = readb(info->base + S3C2410_TICNT);
709         ticnt &= S3C2410_TICNT_ENABLE;
710
711         seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
712 }
713
714 static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info)
715 {
716         unsigned int con;
717
718         con = readw(info->base + S3C2410_RTCCON);
719         con |= S3C2443_RTCCON_TICSEL;
720         writew(con, info->base + S3C2410_RTCCON);
721 }
722
723 static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
724 {
725         unsigned int ticnt;
726
727         ticnt = readw(info->base + S3C2410_RTCCON);
728         ticnt &= S3C64XX_RTCCON_TICEN;
729
730         seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
731 }
732
733 static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info)
734 {
735         info->ticnt_save = readb(info->base + S3C2410_TICNT);
736 }
737
738 static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info)
739 {
740         writeb(info->ticnt_save, info->base + S3C2410_TICNT);
741 }
742
743 static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info)
744 {
745         info->ticnt_en_save = readw(info->base + S3C2410_RTCCON);
746         info->ticnt_en_save &= S3C64XX_RTCCON_TICEN;
747         info->ticnt_save = readl(info->base + S3C2410_TICNT);
748 }
749
750 static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info)
751 {
752         unsigned int con;
753
754         writel(info->ticnt_save, info->base + S3C2410_TICNT);
755         if (info->ticnt_en_save) {
756                 con = readw(info->base + S3C2410_RTCCON);
757                 writew(con | info->ticnt_en_save, info->base + S3C2410_RTCCON);
758         }
759 }
760
761 static struct s3c_rtc_data const s3c2410_rtc_data = {
762         .max_user_freq          = 128,
763         .irq_handler            = s3c24xx_rtc_irq,
764         .set_freq               = s3c2410_rtc_setfreq,
765         .enable_tick            = s3c24xx_rtc_enable_tick,
766         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
767         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
768         .enable                 = s3c24xx_rtc_enable,
769         .disable                = s3c24xx_rtc_disable,
770 };
771
772 static struct s3c_rtc_data const s3c2416_rtc_data = {
773         .max_user_freq          = 32768,
774         .irq_handler            = s3c24xx_rtc_irq,
775         .set_freq               = s3c2416_rtc_setfreq,
776         .enable_tick            = s3c24xx_rtc_enable_tick,
777         .select_tick_clk        = s3c2416_rtc_select_tick_clk,
778         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
779         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
780         .enable                 = s3c24xx_rtc_enable,
781         .disable                = s3c24xx_rtc_disable,
782 };
783
784 static struct s3c_rtc_data const s3c2443_rtc_data = {
785         .max_user_freq          = 32768,
786         .irq_handler            = s3c24xx_rtc_irq,
787         .set_freq               = s3c2443_rtc_setfreq,
788         .enable_tick            = s3c24xx_rtc_enable_tick,
789         .select_tick_clk        = s3c2416_rtc_select_tick_clk,
790         .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
791         .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
792         .enable                 = s3c24xx_rtc_enable,
793         .disable                = s3c24xx_rtc_disable,
794 };
795
796 static struct s3c_rtc_data const s3c6410_rtc_data = {
797         .max_user_freq          = 32768,
798         .needs_src_clk          = true,
799         .irq_handler            = s3c6410_rtc_irq,
800         .set_freq               = s3c6410_rtc_setfreq,
801         .enable_tick            = s3c6410_rtc_enable_tick,
802         .save_tick_cnt          = s3c6410_rtc_save_tick_cnt,
803         .restore_tick_cnt       = s3c6410_rtc_restore_tick_cnt,
804         .enable                 = s3c24xx_rtc_enable,
805         .disable                = s3c6410_rtc_disable,
806 };
807
808 static const struct of_device_id s3c_rtc_dt_match[] = {
809         {
810                 .compatible = "samsung,s3c2410-rtc",
811                 .data = &s3c2410_rtc_data,
812         }, {
813                 .compatible = "samsung,s3c2416-rtc",
814                 .data = &s3c2416_rtc_data,
815         }, {
816                 .compatible = "samsung,s3c2443-rtc",
817                 .data = &s3c2443_rtc_data,
818         }, {
819                 .compatible = "samsung,s3c6410-rtc",
820                 .data = &s3c6410_rtc_data,
821         }, {
822                 .compatible = "samsung,exynos3250-rtc",
823                 .data = &s3c6410_rtc_data,
824         },
825         { /* sentinel */ },
826 };
827 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
828
829 static struct platform_driver s3c_rtc_driver = {
830         .probe          = s3c_rtc_probe,
831         .remove         = s3c_rtc_remove,
832         .driver         = {
833                 .name   = "s3c-rtc",
834                 .pm     = &s3c_rtc_pm_ops,
835                 .of_match_table = of_match_ptr(s3c_rtc_dt_match),
836         },
837 };
838 module_platform_driver(s3c_rtc_driver);
839
840 MODULE_DESCRIPTION("Samsung S3C RTC Driver");
841 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
842 MODULE_LICENSE("GPL");
843 MODULE_ALIAS("platform:s3c2410-rtc");