xref: /openbmc/linux/drivers/rtc/rtc-s3c.c (revision 9b93eb47)
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");
844