xref: /linux/drivers/rtc/rtc-sh.c (revision 606d099cdd1080bbb50ea50dc52d98252f8f10a1)
1 /*
2  * SuperH On-Chip RTC Support
3  *
4  * Copyright (C) 2006  Paul Mundt
5  *
6  * Based on the old arch/sh/kernel/cpu/rtc.c by:
7  *
8  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
9  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
10  *
11  * This file is subject to the terms and conditions of the GNU General Public
12  * License.  See the file "COPYING" in the main directory of this archive
13  * for more details.
14  */
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/bcd.h>
18 #include <linux/rtc.h>
19 #include <linux/init.h>
20 #include <linux/platform_device.h>
21 #include <linux/seq_file.h>
22 #include <linux/interrupt.h>
23 #include <linux/spinlock.h>
24 #include <asm/io.h>
25 
26 #ifdef CONFIG_CPU_SH3
27 #define rtc_reg_size		sizeof(u16)
28 #define RTC_BIT_INVERTED	0	/* No bug on SH7708, SH7709A */
29 #elif defined(CONFIG_CPU_SH4)
30 #define rtc_reg_size		sizeof(u32)
31 #define RTC_BIT_INVERTED	0x40	/* bug on SH7750, SH7750S */
32 #endif
33 
34 #define RTC_REG(r)	((r) * rtc_reg_size)
35 
36 #define R64CNT  	RTC_REG(0)
37 #define RSECCNT 	RTC_REG(1)
38 #define RMINCNT 	RTC_REG(2)
39 #define RHRCNT  	RTC_REG(3)
40 #define RWKCNT  	RTC_REG(4)
41 #define RDAYCNT 	RTC_REG(5)
42 #define RMONCNT 	RTC_REG(6)
43 #define RYRCNT  	RTC_REG(7)
44 #define RSECAR  	RTC_REG(8)
45 #define RMINAR  	RTC_REG(9)
46 #define RHRAR   	RTC_REG(10)
47 #define RWKAR   	RTC_REG(11)
48 #define RDAYAR  	RTC_REG(12)
49 #define RMONAR  	RTC_REG(13)
50 #define RCR1    	RTC_REG(14)
51 #define RCR2    	RTC_REG(15)
52 
53 /* RCR1 Bits */
54 #define RCR1_CF		0x80	/* Carry Flag             */
55 #define RCR1_CIE	0x10	/* Carry Interrupt Enable */
56 #define RCR1_AIE	0x08	/* Alarm Interrupt Enable */
57 #define RCR1_AF		0x01	/* Alarm Flag             */
58 
59 /* RCR2 Bits */
60 #define RCR2_PEF	0x80	/* PEriodic interrupt Flag */
61 #define RCR2_PESMASK	0x70	/* Periodic interrupt Set  */
62 #define RCR2_RTCEN	0x08	/* ENable RTC              */
63 #define RCR2_ADJ	0x04	/* ADJustment (30-second)  */
64 #define RCR2_RESET	0x02	/* Reset bit               */
65 #define RCR2_START	0x01	/* Start bit               */
66 
67 struct sh_rtc {
68 	void __iomem *regbase;
69 	unsigned long regsize;
70 	struct resource *res;
71 	unsigned int alarm_irq, periodic_irq, carry_irq;
72 	struct rtc_device *rtc_dev;
73 	spinlock_t lock;
74 };
75 
76 static irqreturn_t sh_rtc_interrupt(int irq, void *id)
77 {
78 	struct platform_device *pdev = id;
79 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
80 	unsigned int tmp, events = 0;
81 
82 	spin_lock(&rtc->lock);
83 
84 	tmp = readb(rtc->regbase + RCR1);
85 
86 	if (tmp & RCR1_AF)
87 		events |= RTC_AF | RTC_IRQF;
88 
89 	tmp &= ~(RCR1_CF | RCR1_AF);
90 
91 	writeb(tmp, rtc->regbase + RCR1);
92 
93 	rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
94 
95 	spin_unlock(&rtc->lock);
96 
97 	return IRQ_HANDLED;
98 }
99 
100 static irqreturn_t sh_rtc_periodic(int irq, void *id)
101 {
102 	struct sh_rtc *rtc = dev_get_drvdata(id);
103 
104 	spin_lock(&rtc->lock);
105 
106 	rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF);
107 
108 	spin_unlock(&rtc->lock);
109 
110 	return IRQ_HANDLED;
111 }
112 
113 static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
114 {
115 	struct sh_rtc *rtc = dev_get_drvdata(dev);
116 	unsigned int tmp;
117 
118 	spin_lock_irq(&rtc->lock);
119 
120 	tmp = readb(rtc->regbase + RCR2);
121 
122 	if (enable) {
123 		tmp &= ~RCR2_PESMASK;
124 		tmp |= RCR2_PEF | (2 << 4);
125 	} else
126 		tmp &= ~(RCR2_PESMASK | RCR2_PEF);
127 
128 	writeb(tmp, rtc->regbase + RCR2);
129 
130 	spin_unlock_irq(&rtc->lock);
131 }
132 
133 static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
134 {
135 	struct sh_rtc *rtc = dev_get_drvdata(dev);
136 	unsigned int tmp;
137 
138 	spin_lock_irq(&rtc->lock);
139 
140 	tmp = readb(rtc->regbase + RCR1);
141 
142 	if (enable)
143 		tmp |= RCR1_AIE;
144 	else
145 		tmp &= ~RCR1_AIE;
146 
147 	writeb(tmp, rtc->regbase + RCR1);
148 
149 	spin_unlock_irq(&rtc->lock);
150 }
151 
152 static int sh_rtc_open(struct device *dev)
153 {
154 	struct sh_rtc *rtc = dev_get_drvdata(dev);
155 	unsigned int tmp;
156 	int ret;
157 
158 	tmp = readb(rtc->regbase + RCR1);
159 	tmp &= ~RCR1_CF;
160 	tmp |= RCR1_CIE;
161 	writeb(tmp, rtc->regbase + RCR1);
162 
163 	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
164 			  "sh-rtc period", dev);
165 	if (unlikely(ret)) {
166 		dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
167 			ret, rtc->periodic_irq);
168 		return ret;
169 	}
170 
171 	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
172 			  "sh-rtc carry", dev);
173 	if (unlikely(ret)) {
174 		dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
175 			ret, rtc->carry_irq);
176 		free_irq(rtc->periodic_irq, dev);
177 		goto err_bad_carry;
178 	}
179 
180 	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED,
181 			  "sh-rtc alarm", dev);
182 	if (unlikely(ret)) {
183 		dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
184 			ret, rtc->alarm_irq);
185 		goto err_bad_alarm;
186 	}
187 
188 	return 0;
189 
190 err_bad_alarm:
191 	free_irq(rtc->carry_irq, dev);
192 err_bad_carry:
193 	free_irq(rtc->periodic_irq, dev);
194 
195 	return ret;
196 }
197 
198 static void sh_rtc_release(struct device *dev)
199 {
200 	struct sh_rtc *rtc = dev_get_drvdata(dev);
201 
202 	sh_rtc_setpie(dev, 0);
203 
204 	free_irq(rtc->periodic_irq, dev);
205 	free_irq(rtc->carry_irq, dev);
206 	free_irq(rtc->alarm_irq, dev);
207 }
208 
209 static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
210 {
211 	struct sh_rtc *rtc = dev_get_drvdata(dev);
212 	unsigned int tmp;
213 
214 	tmp = readb(rtc->regbase + RCR1);
215 	seq_printf(seq, "alarm_IRQ\t: %s\n",
216 		   (tmp & RCR1_AIE) ? "yes" : "no");
217 	seq_printf(seq, "carry_IRQ\t: %s\n",
218 		   (tmp & RCR1_CIE) ? "yes" : "no");
219 
220 	tmp = readb(rtc->regbase + RCR2);
221 	seq_printf(seq, "periodic_IRQ\t: %s\n",
222 		   (tmp & RCR2_PEF) ? "yes" : "no");
223 
224 	return 0;
225 }
226 
227 static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
228 {
229 	unsigned int ret = -ENOIOCTLCMD;
230 
231 	switch (cmd) {
232 	case RTC_PIE_OFF:
233 	case RTC_PIE_ON:
234 		sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
235 		ret = 0;
236 		break;
237 	case RTC_AIE_OFF:
238 	case RTC_AIE_ON:
239 		sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
240 		ret = 0;
241 		break;
242 	}
243 
244 	return ret;
245 }
246 
247 static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
248 {
249 	struct platform_device *pdev = to_platform_device(dev);
250 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
251 	unsigned int sec128, sec2, yr, yr100, cf_bit;
252 
253 	do {
254 		unsigned int tmp;
255 
256 		spin_lock_irq(&rtc->lock);
257 
258 		tmp = readb(rtc->regbase + RCR1);
259 		tmp &= ~RCR1_CF; /* Clear CF-bit */
260 		tmp |= RCR1_CIE;
261 		writeb(tmp, rtc->regbase + RCR1);
262 
263 		sec128 = readb(rtc->regbase + R64CNT);
264 
265 		tm->tm_sec	= BCD2BIN(readb(rtc->regbase + RSECCNT));
266 		tm->tm_min	= BCD2BIN(readb(rtc->regbase + RMINCNT));
267 		tm->tm_hour	= BCD2BIN(readb(rtc->regbase + RHRCNT));
268 		tm->tm_wday	= BCD2BIN(readb(rtc->regbase + RWKCNT));
269 		tm->tm_mday	= BCD2BIN(readb(rtc->regbase + RDAYCNT));
270 		tm->tm_mon	= BCD2BIN(readb(rtc->regbase + RMONCNT));
271 
272 #if defined(CONFIG_CPU_SH4)
273 		yr  = readw(rtc->regbase + RYRCNT);
274 		yr100 = BCD2BIN(yr >> 8);
275 		yr &= 0xff;
276 #else
277 		yr  = readb(rtc->regbase + RYRCNT);
278 		yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
279 #endif
280 
281 		tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
282 
283 		sec2 = readb(rtc->regbase + R64CNT);
284 		cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;
285 
286 		spin_unlock_irq(&rtc->lock);
287 	} while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
288 
289 #if RTC_BIT_INVERTED != 0
290 	if ((sec128 & RTC_BIT_INVERTED))
291 		tm->tm_sec--;
292 #endif
293 
294 	dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
295 		"mday=%d, mon=%d, year=%d, wday=%d\n",
296 		__FUNCTION__,
297 		tm->tm_sec, tm->tm_min, tm->tm_hour,
298 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
299 
300 	if (rtc_valid_tm(tm) < 0)
301 		dev_err(dev, "invalid date\n");
302 
303 	return 0;
304 }
305 
306 static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
307 {
308 	struct platform_device *pdev = to_platform_device(dev);
309 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
310 	unsigned int tmp;
311 	int year;
312 
313 	spin_lock_irq(&rtc->lock);
314 
315 	/* Reset pre-scaler & stop RTC */
316 	tmp = readb(rtc->regbase + RCR2);
317 	tmp |= RCR2_RESET;
318 	writeb(tmp, rtc->regbase + RCR2);
319 
320 	writeb(BIN2BCD(tm->tm_sec),  rtc->regbase + RSECCNT);
321 	writeb(BIN2BCD(tm->tm_min),  rtc->regbase + RMINCNT);
322 	writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
323 	writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
324 	writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
325 	writeb(BIN2BCD(tm->tm_mon),  rtc->regbase + RMONCNT);
326 
327 #ifdef CONFIG_CPU_SH3
328 	year = tm->tm_year % 100;
329 	writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
330 #else
331 	year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
332 		BIN2BCD(tm->tm_year % 100);
333 	writew(year, rtc->regbase + RYRCNT);
334 #endif
335 
336 	/* Start RTC */
337 	tmp = readb(rtc->regbase + RCR2);
338 	tmp &= ~RCR2_RESET;
339 	tmp |= RCR2_RTCEN | RCR2_START;
340 	writeb(tmp, rtc->regbase + RCR2);
341 
342 	spin_unlock_irq(&rtc->lock);
343 
344 	return 0;
345 }
346 
347 static struct rtc_class_ops sh_rtc_ops = {
348 	.open		= sh_rtc_open,
349 	.release	= sh_rtc_release,
350 	.ioctl		= sh_rtc_ioctl,
351 	.read_time	= sh_rtc_read_time,
352 	.set_time	= sh_rtc_set_time,
353 	.proc		= sh_rtc_proc,
354 };
355 
356 static int __devinit sh_rtc_probe(struct platform_device *pdev)
357 {
358 	struct sh_rtc *rtc;
359 	struct resource *res;
360 	int ret = -ENOENT;
361 
362 	rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
363 	if (unlikely(!rtc))
364 		return -ENOMEM;
365 
366 	spin_lock_init(&rtc->lock);
367 
368 	rtc->periodic_irq = platform_get_irq(pdev, 0);
369 	if (unlikely(rtc->periodic_irq < 0)) {
370 		dev_err(&pdev->dev, "No IRQ for period\n");
371 		goto err_badres;
372 	}
373 
374 	rtc->carry_irq = platform_get_irq(pdev, 1);
375 	if (unlikely(rtc->carry_irq < 0)) {
376 		dev_err(&pdev->dev, "No IRQ for carry\n");
377 		goto err_badres;
378 	}
379 
380 	rtc->alarm_irq = platform_get_irq(pdev, 2);
381 	if (unlikely(rtc->alarm_irq < 0)) {
382 		dev_err(&pdev->dev, "No IRQ for alarm\n");
383 		goto err_badres;
384 	}
385 
386 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
387 	if (unlikely(res == NULL)) {
388 		dev_err(&pdev->dev, "No IO resource\n");
389 		goto err_badres;
390 	}
391 
392 	rtc->regsize = res->end - res->start + 1;
393 
394 	rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
395 	if (unlikely(!rtc->res)) {
396 		ret = -EBUSY;
397 		goto err_badres;
398 	}
399 
400 	rtc->regbase = (void __iomem *)rtc->res->start;
401 	if (unlikely(!rtc->regbase)) {
402 		ret = -EINVAL;
403 		goto err_badmap;
404 	}
405 
406 	rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
407 					   &sh_rtc_ops, THIS_MODULE);
408 	if (IS_ERR(rtc)) {
409 		ret = PTR_ERR(rtc->rtc_dev);
410 		goto err_badmap;
411 	}
412 
413 	platform_set_drvdata(pdev, rtc);
414 
415 	return 0;
416 
417 err_badmap:
418 	release_resource(rtc->res);
419 err_badres:
420 	kfree(rtc);
421 
422 	return ret;
423 }
424 
425 static int __devexit sh_rtc_remove(struct platform_device *pdev)
426 {
427 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
428 
429 	if (likely(rtc->rtc_dev))
430 		rtc_device_unregister(rtc->rtc_dev);
431 
432 	sh_rtc_setpie(&pdev->dev, 0);
433 	sh_rtc_setaie(&pdev->dev, 0);
434 
435 	release_resource(rtc->res);
436 
437 	platform_set_drvdata(pdev, NULL);
438 
439 	kfree(rtc);
440 
441 	return 0;
442 }
443 static struct platform_driver sh_rtc_platform_driver = {
444 	.driver		= {
445 		.name	= "sh-rtc",
446 		.owner	= THIS_MODULE,
447 	},
448 	.probe		= sh_rtc_probe,
449 	.remove		= __devexit_p(sh_rtc_remove),
450 };
451 
452 static int __init sh_rtc_init(void)
453 {
454 	return platform_driver_register(&sh_rtc_platform_driver);
455 }
456 
457 static void __exit sh_rtc_exit(void)
458 {
459 	platform_driver_unregister(&sh_rtc_platform_driver);
460 }
461 
462 module_init(sh_rtc_init);
463 module_exit(sh_rtc_exit);
464 
465 MODULE_DESCRIPTION("SuperH on-chip RTC driver");
466 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
467 MODULE_LICENSE("GPL");
468