aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig13
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-fm3130.c2
-rw-r--r--drivers/rtc/rtc-jz4740.c345
-rw-r--r--drivers/rtc/rtc-pl031.c2
-rw-r--r--drivers/rtc/rtc-rx8025.c2
6 files changed, 361 insertions, 4 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c43732ff180..9238c8f40f0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -781,7 +781,7 @@ config RTC_DRV_AT91SAM9_GPBR
781 781
782config RTC_DRV_AU1XXX 782config RTC_DRV_AU1XXX
783 tristate "Au1xxx Counter0 RTC support" 783 tristate "Au1xxx Counter0 RTC support"
784 depends on SOC_AU1X00 784 depends on MIPS_ALCHEMY
785 help 785 help
786 This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year 786 This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year
787 counter) to be used as a RTC. 787 counter) to be used as a RTC.
@@ -912,4 +912,15 @@ config RTC_DRV_MPC5121
912 This driver can also be built as a module. If so, the module 912 This driver can also be built as a module. If so, the module
913 will be called rtc-mpc5121. 913 will be called rtc-mpc5121.
914 914
915config RTC_DRV_JZ4740
916 tristate "Ingenic JZ4740 SoC"
917 depends on RTC_CLASS
918 depends on MACH_JZ4740
919 help
920 If you say yes here you get support for the Ingenic JZ4740 SoC RTC
921 controller.
922
923 This driver can also be buillt as a module. If so, the module
924 will be called rtc-jz4740.
925
915endif # RTC_CLASS 926endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 5adbba7cf89..fedf9bb3659 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
47obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o 47obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
48obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o 48obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
49obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o 49obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
50obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
50obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o 51obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
51obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o 52obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
52obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o 53obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index ff6fce61ea4..e4de8f37ae4 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -104,7 +104,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
104 if (!fm3130->data_valid) { 104 if (!fm3130->data_valid) {
105 /* We have invalid data in RTC, probably due 105 /* We have invalid data in RTC, probably due
106 to battery faults or other problems. Return EIO 106 to battery faults or other problems. Return EIO
107 for now, it will allow us to set data later insted 107 for now, it will allow us to set data later instead
108 of error during probing which disables device */ 108 of error during probing which disables device */
109 return -EIO; 109 return -EIO;
110 } 110 }
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
new file mode 100644
index 00000000000..2619d57b91d
--- /dev/null
+++ b/drivers/rtc/rtc-jz4740.c
@@ -0,0 +1,345 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 SoC RTC driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/rtc.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h>
22
23#define JZ_REG_RTC_CTRL 0x00
24#define JZ_REG_RTC_SEC 0x04
25#define JZ_REG_RTC_SEC_ALARM 0x08
26#define JZ_REG_RTC_REGULATOR 0x0C
27#define JZ_REG_RTC_HIBERNATE 0x20
28#define JZ_REG_RTC_SCRATCHPAD 0x34
29
30#define JZ_RTC_CTRL_WRDY BIT(7)
31#define JZ_RTC_CTRL_1HZ BIT(6)
32#define JZ_RTC_CTRL_1HZ_IRQ BIT(5)
33#define JZ_RTC_CTRL_AF BIT(4)
34#define JZ_RTC_CTRL_AF_IRQ BIT(3)
35#define JZ_RTC_CTRL_AE BIT(2)
36#define JZ_RTC_CTRL_ENABLE BIT(0)
37
38struct jz4740_rtc {
39 struct resource *mem;
40 void __iomem *base;
41
42 struct rtc_device *rtc;
43
44 unsigned int irq;
45
46 spinlock_t lock;
47};
48
49static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
50{
51 return readl(rtc->base + reg);
52}
53
54static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
55{
56 uint32_t ctrl;
57 int timeout = 1000;
58
59 do {
60 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
61 } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout);
62
63 return timeout ? 0 : -EIO;
64}
65
66static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
67 uint32_t val)
68{
69 int ret;
70 ret = jz4740_rtc_wait_write_ready(rtc);
71 if (ret == 0)
72 writel(val, rtc->base + reg);
73
74 return ret;
75}
76
77static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
78 bool set)
79{
80 int ret;
81 unsigned long flags;
82 uint32_t ctrl;
83
84 spin_lock_irqsave(&rtc->lock, flags);
85
86 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
87
88 /* Don't clear interrupt flags by accident */
89 ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
90
91 if (set)
92 ctrl |= mask;
93 else
94 ctrl &= ~mask;
95
96 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
97
98 spin_unlock_irqrestore(&rtc->lock, flags);
99
100 return ret;
101}
102
103static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
104{
105 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
106 uint32_t secs, secs2;
107 int timeout = 5;
108
109 /* If the seconds register is read while it is updated, it can contain a
110 * bogus value. This can be avoided by making sure that two consecutive
111 * reads have the same value.
112 */
113 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
114 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
115
116 while (secs != secs2 && --timeout) {
117 secs = secs2;
118 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
119 }
120
121 if (timeout == 0)
122 return -EIO;
123
124 rtc_time_to_tm(secs, time);
125
126 return rtc_valid_tm(time);
127}
128
129static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
130{
131 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
132
133 return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs);
134}
135
136static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
137{
138 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
139 uint32_t secs;
140 uint32_t ctrl;
141
142 secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
143
144 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
145
146 alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
147 alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
148
149 rtc_time_to_tm(secs, &alrm->time);
150
151 return rtc_valid_tm(&alrm->time);
152}
153
154static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
155{
156 int ret;
157 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
158 unsigned long secs;
159
160 rtc_tm_to_time(&alrm->time, &secs);
161
162 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs);
163 if (!ret)
164 ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled);
165
166 return ret;
167}
168
169static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
170{
171 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
172 return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable);
173}
174
175static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
176{
177 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
178 return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable);
179}
180
181static struct rtc_class_ops jz4740_rtc_ops = {
182 .read_time = jz4740_rtc_read_time,
183 .set_mmss = jz4740_rtc_set_mmss,
184 .read_alarm = jz4740_rtc_read_alarm,
185 .set_alarm = jz4740_rtc_set_alarm,
186 .update_irq_enable = jz4740_rtc_update_irq_enable,
187 .alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
188};
189
190static irqreturn_t jz4740_rtc_irq(int irq, void *data)
191{
192 struct jz4740_rtc *rtc = data;
193 uint32_t ctrl;
194 unsigned long events = 0;
195
196 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
197
198 if (ctrl & JZ_RTC_CTRL_1HZ)
199 events |= (RTC_UF | RTC_IRQF);
200
201 if (ctrl & JZ_RTC_CTRL_AF)
202 events |= (RTC_AF | RTC_IRQF);
203
204 rtc_update_irq(rtc->rtc, 1, events);
205
206 jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false);
207
208 return IRQ_HANDLED;
209}
210
211void jz4740_rtc_poweroff(struct device *dev)
212{
213 struct jz4740_rtc *rtc = dev_get_drvdata(dev);
214 jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1);
215}
216EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff);
217
218static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
219{
220 int ret;
221 struct jz4740_rtc *rtc;
222 uint32_t scratchpad;
223
224 rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
225 if (!rtc)
226 return -ENOMEM;
227
228 rtc->irq = platform_get_irq(pdev, 0);
229 if (rtc->irq < 0) {
230 ret = -ENOENT;
231 dev_err(&pdev->dev, "Failed to get platform irq\n");
232 goto err_free;
233 }
234
235 rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
236 if (!rtc->mem) {
237 ret = -ENOENT;
238 dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
239 goto err_free;
240 }
241
242 rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem),
243 pdev->name);
244 if (!rtc->mem) {
245 ret = -EBUSY;
246 dev_err(&pdev->dev, "Failed to request mmio memory region\n");
247 goto err_free;
248 }
249
250 rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem));
251 if (!rtc->base) {
252 ret = -EBUSY;
253 dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
254 goto err_release_mem_region;
255 }
256
257 spin_lock_init(&rtc->lock);
258
259 platform_set_drvdata(pdev, rtc);
260
261 rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops,
262 THIS_MODULE);
263 if (IS_ERR(rtc->rtc)) {
264 ret = PTR_ERR(rtc->rtc);
265 dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
266 goto err_iounmap;
267 }
268
269 ret = request_irq(rtc->irq, jz4740_rtc_irq, 0,
270 pdev->name, rtc);
271 if (ret) {
272 dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
273 goto err_unregister_rtc;
274 }
275
276 scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
277 if (scratchpad != 0x12345678) {
278 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
279 ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
280 if (ret) {
281 dev_err(&pdev->dev, "Could not write write to RTC registers\n");
282 goto err_free_irq;
283 }
284 }
285
286 return 0;
287
288err_free_irq:
289 free_irq(rtc->irq, rtc);
290err_unregister_rtc:
291 rtc_device_unregister(rtc->rtc);
292err_iounmap:
293 platform_set_drvdata(pdev, NULL);
294 iounmap(rtc->base);
295err_release_mem_region:
296 release_mem_region(rtc->mem->start, resource_size(rtc->mem));
297err_free:
298 kfree(rtc);
299
300 return ret;
301}
302
303static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
304{
305 struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
306
307 free_irq(rtc->irq, rtc);
308
309 rtc_device_unregister(rtc->rtc);
310
311 iounmap(rtc->base);
312 release_mem_region(rtc->mem->start, resource_size(rtc->mem));
313
314 kfree(rtc);
315
316 platform_set_drvdata(pdev, NULL);
317
318 return 0;
319}
320
321struct platform_driver jz4740_rtc_driver = {
322 .probe = jz4740_rtc_probe,
323 .remove = __devexit_p(jz4740_rtc_remove),
324 .driver = {
325 .name = "jz4740-rtc",
326 .owner = THIS_MODULE,
327 },
328};
329
330static int __init jz4740_rtc_init(void)
331{
332 return platform_driver_register(&jz4740_rtc_driver);
333}
334module_init(jz4740_rtc_init);
335
336static void __exit jz4740_rtc_exit(void)
337{
338 platform_driver_unregister(&jz4740_rtc_driver);
339}
340module_exit(jz4740_rtc_exit);
341
342MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
343MODULE_LICENSE("GPL");
344MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n");
345MODULE_ALIAS("platform:jz4740-rtc");
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 3587d9922f2..71bbefc3544 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -456,7 +456,7 @@ static struct rtc_class_ops stv2_pl031_ops = {
456 .irq_set_freq = pl031_irq_set_freq, 456 .irq_set_freq = pl031_irq_set_freq,
457}; 457};
458 458
459static struct amba_id pl031_ids[] __initdata = { 459static struct amba_id pl031_ids[] = {
460 { 460 {
461 .id = 0x00041031, 461 .id = 0x00041031,
462 .mask = 0x000fffff, 462 .mask = 0x000fffff,
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 789f62f9b47..1146e3522d3 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -461,7 +461,7 @@ static struct rtc_class_ops rx8025_rtc_ops = {
461 * Clock precision adjustment support 461 * Clock precision adjustment support
462 * 462 *
463 * According to the RX8025 SA/NB application manual the frequency and 463 * According to the RX8025 SA/NB application manual the frequency and
464 * temperature charateristics can be approximated using the following 464 * temperature characteristics can be approximated using the following
465 * equation: 465 * equation:
466 * 466 *
467 * df = a * (ut - t)**2 467 * df = a * (ut - t)**2