]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/rtc/rtc-armada38x.c
Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / rtc / rtc-armada38x.c
1 /*
2  * RTC driver for the Armada 38x Marvell SoCs
3  *
4  * Copyright (C) 2015 Marvell
5  *
6  * Gregory Clement <gregory.clement@free-electrons.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  */
14
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/platform_device.h>
20 #include <linux/rtc.h>
21
22 #define RTC_STATUS          0x0
23 #define RTC_STATUS_ALARM1           BIT(0)
24 #define RTC_STATUS_ALARM2           BIT(1)
25 #define RTC_IRQ1_CONF       0x4
26 #define RTC_IRQ1_AL_EN              BIT(0)
27 #define RTC_IRQ1_FREQ_EN            BIT(1)
28 #define RTC_IRQ1_FREQ_1HZ           BIT(2)
29 #define RTC_TIME            0xC
30 #define RTC_ALARM1          0x10
31
32 #define SOC_RTC_INTERRUPT   0x8
33 #define SOC_RTC_ALARM1          BIT(0)
34 #define SOC_RTC_ALARM2          BIT(1)
35 #define SOC_RTC_ALARM1_MASK     BIT(2)
36 #define SOC_RTC_ALARM2_MASK     BIT(3)
37
38 struct armada38x_rtc {
39         struct rtc_device   *rtc_dev;
40         void __iomem        *regs;
41         void __iomem        *regs_soc;
42         spinlock_t          lock;
43         int                 irq;
44 };
45
46 /*
47  * According to the datasheet, the OS should wait 5us after every
48  * register write to the RTC hard macro so that the required update
49  * can occur without holding off the system bus
50  */
51 static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
52 {
53         writel(val, rtc->regs + offset);
54         udelay(5);
55 }
56
57 static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
58 {
59         struct armada38x_rtc *rtc = dev_get_drvdata(dev);
60         unsigned long time, time_check, flags;
61
62         spin_lock_irqsave(&rtc->lock, flags);
63         time = readl(rtc->regs + RTC_TIME);
64         /*
65          * WA for failing time set attempts. As stated in HW ERRATA if
66          * more than one second between two time reads is detected
67          * then read once again.
68          */
69         time_check = readl(rtc->regs + RTC_TIME);
70         if ((time_check - time) > 1)
71                 time_check = readl(rtc->regs + RTC_TIME);
72
73         spin_unlock_irqrestore(&rtc->lock, flags);
74
75         rtc_time_to_tm(time_check, tm);
76
77         return 0;
78 }
79
80 static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
81 {
82         struct armada38x_rtc *rtc = dev_get_drvdata(dev);
83         int ret = 0;
84         unsigned long time, flags;
85
86         ret = rtc_tm_to_time(tm, &time);
87
88         if (ret)
89                 goto out;
90         /*
91          * According to errata FE-3124064, Write to RTC TIME register
92          * may fail. As a workaround, after writing to RTC TIME
93          * register, issue a dummy write of 0x0 twice to RTC Status
94          * register.
95          */
96         spin_lock_irqsave(&rtc->lock, flags);
97         rtc_delayed_write(time, rtc, RTC_TIME);
98         rtc_delayed_write(0, rtc, RTC_STATUS);
99         rtc_delayed_write(0, rtc, RTC_STATUS);
100         spin_unlock_irqrestore(&rtc->lock, flags);
101
102 out:
103         return ret;
104 }
105
106 static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
107 {
108         struct armada38x_rtc *rtc = dev_get_drvdata(dev);
109         unsigned long time, flags;
110         u32 val;
111
112         spin_lock_irqsave(&rtc->lock, flags);
113
114         time = readl(rtc->regs + RTC_ALARM1);
115         val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN;
116
117         spin_unlock_irqrestore(&rtc->lock, flags);
118
119         alrm->enabled = val ? 1 : 0;
120         rtc_time_to_tm(time,  &alrm->time);
121
122         return 0;
123 }
124
125 static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
126 {
127         struct armada38x_rtc *rtc = dev_get_drvdata(dev);
128         unsigned long time, flags;
129         int ret = 0;
130         u32 val;
131
132         ret = rtc_tm_to_time(&alrm->time, &time);
133
134         if (ret)
135                 goto out;
136
137         spin_lock_irqsave(&rtc->lock, flags);
138
139         rtc_delayed_write(time, rtc, RTC_ALARM1);
140
141         if (alrm->enabled) {
142                         rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
143                         val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
144                         writel(val | SOC_RTC_ALARM1_MASK,
145                                rtc->regs_soc + SOC_RTC_INTERRUPT);
146         }
147
148         spin_unlock_irqrestore(&rtc->lock, flags);
149
150 out:
151         return ret;
152 }
153
154 static int armada38x_rtc_alarm_irq_enable(struct device *dev,
155                                          unsigned int enabled)
156 {
157         struct armada38x_rtc *rtc = dev_get_drvdata(dev);
158         unsigned long flags;
159
160         spin_lock_irqsave(&rtc->lock, flags);
161
162         if (enabled)
163                 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
164         else
165                 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
166
167         spin_unlock_irqrestore(&rtc->lock, flags);
168
169         return 0;
170 }
171
172 static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
173 {
174         struct armada38x_rtc *rtc = data;
175         u32 val;
176         int event = RTC_IRQF | RTC_AF;
177
178         dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
179
180         spin_lock(&rtc->lock);
181
182         val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
183
184         writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
185         val = readl(rtc->regs + RTC_IRQ1_CONF);
186         /* disable all the interrupts for alarm 1 */
187         rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
188         /* Ack the event */
189         rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS);
190
191         spin_unlock(&rtc->lock);
192
193         if (val & RTC_IRQ1_FREQ_EN) {
194                 if (val & RTC_IRQ1_FREQ_1HZ)
195                         event |= RTC_UF;
196                 else
197                         event |= RTC_PF;
198         }
199
200         rtc_update_irq(rtc->rtc_dev, 1, event);
201
202         return IRQ_HANDLED;
203 }
204
205 static struct rtc_class_ops armada38x_rtc_ops = {
206         .read_time = armada38x_rtc_read_time,
207         .set_time = armada38x_rtc_set_time,
208         .read_alarm = armada38x_rtc_read_alarm,
209         .set_alarm = armada38x_rtc_set_alarm,
210         .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
211 };
212
213 static __init int armada38x_rtc_probe(struct platform_device *pdev)
214 {
215         struct resource *res;
216         struct armada38x_rtc *rtc;
217         int ret;
218
219         rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
220                             GFP_KERNEL);
221         if (!rtc)
222                 return -ENOMEM;
223
224         spin_lock_init(&rtc->lock);
225
226         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
227         rtc->regs = devm_ioremap_resource(&pdev->dev, res);
228         if (IS_ERR(rtc->regs))
229                 return PTR_ERR(rtc->regs);
230         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
231         rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
232         if (IS_ERR(rtc->regs_soc))
233                 return PTR_ERR(rtc->regs_soc);
234
235         rtc->irq = platform_get_irq(pdev, 0);
236
237         if (rtc->irq < 0) {
238                 dev_err(&pdev->dev, "no irq\n");
239                 return rtc->irq;
240         }
241         if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
242                                 0, pdev->name, rtc) < 0) {
243                 dev_warn(&pdev->dev, "Interrupt not available.\n");
244                 rtc->irq = -1;
245                 /*
246                  * If there is no interrupt available then we can't
247                  * use the alarm
248                  */
249                 armada38x_rtc_ops.set_alarm = NULL;
250                 armada38x_rtc_ops.alarm_irq_enable = NULL;
251         }
252         platform_set_drvdata(pdev, rtc);
253         if (rtc->irq != -1)
254                 device_init_wakeup(&pdev->dev, 1);
255
256         rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
257                                         &armada38x_rtc_ops, THIS_MODULE);
258         if (IS_ERR(rtc->rtc_dev)) {
259                 ret = PTR_ERR(rtc->rtc_dev);
260                 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
261                 return ret;
262         }
263         return 0;
264 }
265
266 #ifdef CONFIG_PM_SLEEP
267 static int armada38x_rtc_suspend(struct device *dev)
268 {
269         if (device_may_wakeup(dev)) {
270                 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
271
272                 return enable_irq_wake(rtc->irq);
273         }
274
275         return 0;
276 }
277
278 static int armada38x_rtc_resume(struct device *dev)
279 {
280         if (device_may_wakeup(dev)) {
281                 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
282
283                 return disable_irq_wake(rtc->irq);
284         }
285
286         return 0;
287 }
288 #endif
289
290 static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
291                          armada38x_rtc_suspend, armada38x_rtc_resume);
292
293 #ifdef CONFIG_OF
294 static const struct of_device_id armada38x_rtc_of_match_table[] = {
295         { .compatible = "marvell,armada-380-rtc", },
296         {}
297 };
298 MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
299 #endif
300
301 static struct platform_driver armada38x_rtc_driver = {
302         .driver         = {
303                 .name   = "armada38x-rtc",
304                 .pm     = &armada38x_rtc_pm_ops,
305                 .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
306         },
307 };
308
309 module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
310
311 MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
312 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
313 MODULE_LICENSE("GPL");