Merge xburst target.
[openwrt.git] / target / linux / xburst / files-2.6.32 / drivers / rtc / rtc-jz4740.c
1 /*
2  *  Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
3  *      JZ4720/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/spinlock.h>
20 #include <linux/rtc.h>
21
22 #define JZ_REG_RTC_CTRL         0x00
23 #define JZ_REG_RTC_SEC          0x04
24 #define JZ_REG_RTC_SEC_ALARM    0x08
25 #define JZ_REG_REGULATOR        0x0C
26
27 #define JZ_RTC_CTRL_WRDY        BIT(7)
28 #define JZ_RTC_CTRL_1HZ         BIT(6)
29 #define JZ_RTC_CTRL_1HZ_IRQ     BIT(5)
30 #define JZ_RTC_CTRL_AF          BIT(4)
31 #define JZ_RTC_CTRL_AF_IRQ      BIT(3)
32 #define JZ_RTC_CTRL_AE          BIT(2)
33 #define JZ_RTC_CTRL_ENABLE      BIT(0)
34
35 struct jz4740_rtc {
36         struct resource *mem;
37         void __iomem *base;
38
39         struct rtc_device *rtc;
40
41         unsigned int irq;
42
43         spinlock_t lock;
44 };
45
46 static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
47 {
48         return readl(rtc->base + reg);
49 }
50
51 static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
52 {
53         uint32_t ctrl;
54         do {
55                 ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
56         } while (!(ctrl & JZ_RTC_CTRL_WRDY));
57 }
58
59
60 static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
61                                         uint32_t val)
62 {
63         jz4740_rtc_wait_write_ready(rtc);
64         writel(val, rtc->base + reg);
65 }
66
67 static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
68                                         uint32_t val)
69 {
70         unsigned long flags;
71         uint32_t ctrl;
72
73         spin_lock_irqsave(&rtc->lock, flags);
74
75         ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
76
77         /* Don't clear interrupt flags by accident */
78         ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
79
80         ctrl &= ~mask;
81         ctrl |= val;
82
83         jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
84
85         spin_unlock_irqrestore(&rtc->lock, flags);
86 }
87
88 static inline struct jz4740_rtc *dev_to_rtc(struct device *dev)
89 {
90         return dev_get_drvdata(dev);
91 }
92
93 static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
94 {
95         struct jz4740_rtc *rtc = dev_to_rtc(dev);
96         uint32_t secs, secs2;
97
98         secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
99         secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
100
101         while (secs != secs2) {
102                 secs = secs2;
103                 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
104         }
105
106         rtc_time_to_tm(secs, time);
107
108         return rtc_valid_tm(time);
109 }
110
111 static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
112 {
113         struct jz4740_rtc *rtc = dev_to_rtc(dev);
114
115         if ((uint32_t)secs != secs)
116                 return -EINVAL;
117
118         jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs);
119
120         return 0;
121 }
122
123 static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
124 {
125         struct jz4740_rtc *rtc = dev_to_rtc(dev);
126         uint32_t secs, secs2;
127         uint32_t ctrl;
128
129         secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
130         secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
131
132         while (secs != secs2){
133                 secs = secs2;
134                 secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
135         }
136
137         ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
138
139         alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
140         alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
141
142         rtc_time_to_tm(secs, &alrm->time);
143
144         return rtc_valid_tm(&alrm->time);
145 }
146
147 static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
148 {
149         struct jz4740_rtc *rtc = dev_to_rtc(dev);
150         unsigned long secs;
151
152         rtc_tm_to_time(&alrm->time, &secs);
153
154         if ((uint32_t)secs != secs)
155                 return -EINVAL;
156
157         jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs);
158         jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE,
159                                         alrm->enabled ? JZ_RTC_CTRL_AE : 0);
160
161         return 0;
162 }
163
164 static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
165 {
166         struct jz4740_rtc *rtc = dev_to_rtc(dev);
167         jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ,
168                                         enabled ? JZ_RTC_CTRL_1HZ_IRQ : 0);
169         return 0;
170 }
171
172
173 static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
174 {
175         struct jz4740_rtc *rtc = dev_to_rtc(dev);
176         jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ,
177                                         enabled ? JZ_RTC_CTRL_AF_IRQ : 0);
178         return 0;
179 }
180
181 static 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
190 static 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         ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
196
197         if (ctrl & JZ_RTC_CTRL_1HZ)
198                 events |= (RTC_UF | RTC_IRQF);
199
200         if (ctrl & JZ_RTC_CTRL_AF)
201                 events |= (RTC_AF | RTC_IRQF);
202
203         rtc_update_irq(rtc->rtc, 1, events);
204
205         jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0);
206
207         return IRQ_HANDLED;
208 }
209
210 static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
211 {
212         int ret;
213         struct jz4740_rtc *rtc;
214
215         rtc = kmalloc(sizeof(*rtc), GFP_KERNEL);
216
217         rtc->irq = platform_get_irq(pdev, 0);
218
219         if (rtc->irq < 0) {
220                 ret = -ENOENT;
221                 dev_err(&pdev->dev, "Failed to get platform irq\n");
222                 goto err_free;
223         }
224
225         rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
226         if (!rtc->mem) {
227                 ret = -ENOENT;
228                 dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
229                 goto err_free;
230         }
231
232         rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem),
233                                         pdev->name);
234
235         if (!rtc->mem) {
236                 ret = -EBUSY;
237                 dev_err(&pdev->dev, "Failed to request mmio memory region\n");
238                 goto err_free;
239         }
240
241         rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem));
242
243         if (!rtc->base) {
244                 ret = -EBUSY;
245                 dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
246                 goto err_release_mem_region;
247         }
248
249         platform_set_drvdata(pdev, rtc);
250
251         rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops,
252                                         THIS_MODULE);
253
254         if (IS_ERR(rtc->rtc)) {
255                 ret = PTR_ERR(rtc->rtc);
256                 dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
257                 goto err_iounmap;
258         }
259
260         ret = request_irq(rtc->irq, jz4740_rtc_irq, 0,
261                                 pdev->name,  rtc);
262
263         if (ret) {
264                 dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
265                 goto err_unregister_rtc;
266         }
267         printk("rtc-ctrl: %d\n", jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL));
268
269         return 0;
270
271 err_unregister_rtc:
272         rtc_device_unregister(rtc->rtc);
273 err_iounmap:
274         platform_set_drvdata(pdev, NULL);
275         iounmap(rtc->base);
276 err_release_mem_region:
277         release_mem_region(rtc->mem->start, resource_size(rtc->mem));
278 err_free:
279         kfree(rtc);
280
281         return ret;
282 }
283
284 static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
285 {
286         struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
287
288         rtc_device_unregister(rtc->rtc);
289
290         iounmap(rtc->base);
291         release_mem_region(rtc->mem->start, resource_size(rtc->mem));
292
293         kfree(rtc);
294
295         platform_set_drvdata(pdev, NULL);
296
297         return 0;
298 }
299
300 struct platform_driver jz4740_rtc_driver = {
301         .probe = jz4740_rtc_probe,
302         .remove = __devexit_p(jz4740_rtc_remove),
303         .driver = {
304                 .name = "jz4740-rtc",
305                 .owner = THIS_MODULE,
306         },
307 };
308
309 static int __init jz4740_rtc_init(void)
310 {
311         return platform_driver_register(&jz4740_rtc_driver);
312 }
313 module_init(jz4740_rtc_init);
314
315 static void __exit jz4740_rtc_exit(void)
316 {
317         platform_driver_unregister(&jz4740_rtc_driver);
318 }
319 module_exit(jz4740_rtc_exit);
320
321 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
322 MODULE_LICENSE("GPL");
323 MODULE_DESCRIPTION("RTC driver for the JZ4720/JZ4740 SoC\n");
324 MODULE_ALIAS("platform:jz4740-rtc");
325 MODULE_ALIAS("platform:jz4720-rtc");