Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us