blob: 43e04af39e0964e3dccd24e251f484d04a680bc9 [file] [log] [blame]
Gregory CLEMENTa3a42802015-02-13 14:41:11 -08001/*
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
38struct 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 */
51static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
52{
53 writel(val, rtc->regs + offset);
54 udelay(5);
55}
56
57static 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
64 time = readl(rtc->regs + RTC_TIME);
65 /*
66 * WA for failing time set attempts. As stated in HW ERRATA if
67 * more than one second between two time reads is detected
68 * then read once again.
69 */
70 time_check = readl(rtc->regs + RTC_TIME);
71 if ((time_check - time) > 1)
72 time_check = readl(rtc->regs + RTC_TIME);
73
74 spin_unlock_irqrestore(&rtc->lock, flags);
75
76 rtc_time_to_tm(time_check, tm);
77
78 return 0;
79}
80
81static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
82{
83 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
84 int ret = 0;
85 unsigned long time, flags;
86
87 ret = rtc_tm_to_time(tm, &time);
88
89 if (ret)
90 goto out;
91 /*
92 * Setting the RTC time not always succeeds. According to the
93 * errata we need to first write on the status register and
94 * then wait for 100ms before writing to the time register to be
95 * sure that the data will be taken into account.
96 */
97 spin_lock_irqsave(&rtc->lock, flags);
98
99 rtc_delayed_write(0, rtc, RTC_STATUS);
100
101 spin_unlock_irqrestore(&rtc->lock, flags);
102
103 msleep(100);
104
105 spin_lock_irqsave(&rtc->lock, flags);
106
107 rtc_delayed_write(time, rtc, RTC_TIME);
108
109 spin_unlock_irqrestore(&rtc->lock, flags);
110out:
111 return ret;
112}
113
114static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
115{
116 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
117 unsigned long time, flags;
118 u32 val;
119
120 spin_lock_irqsave(&rtc->lock, flags);
121
122 time = readl(rtc->regs + RTC_ALARM1);
123 val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN;
124
125 spin_unlock_irqrestore(&rtc->lock, flags);
126
127 alrm->enabled = val ? 1 : 0;
128 rtc_time_to_tm(time, &alrm->time);
129
130 return 0;
131}
132
133static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
134{
135 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
136 unsigned long time, flags;
137 int ret = 0;
138 u32 val;
139
140 ret = rtc_tm_to_time(&alrm->time, &time);
141
142 if (ret)
143 goto out;
144
145 spin_lock_irqsave(&rtc->lock, flags);
146
147 rtc_delayed_write(time, rtc, RTC_ALARM1);
148
149 if (alrm->enabled) {
150 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
151 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
152 writel(val | SOC_RTC_ALARM1_MASK,
153 rtc->regs_soc + SOC_RTC_INTERRUPT);
154 }
155
156 spin_unlock_irqrestore(&rtc->lock, flags);
157
158out:
159 return ret;
160}
161
162static int armada38x_rtc_alarm_irq_enable(struct device *dev,
163 unsigned int enabled)
164{
165 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
166 unsigned long flags;
167
168 spin_lock_irqsave(&rtc->lock, flags);
169
170 if (enabled)
171 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
172 else
173 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
174
175 spin_unlock_irqrestore(&rtc->lock, flags);
176
177 return 0;
178}
179
180static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
181{
182 struct armada38x_rtc *rtc = data;
183 u32 val;
184 int event = RTC_IRQF | RTC_AF;
185
186 dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
187
188 spin_lock(&rtc->lock);
189
190 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
191
192 writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
193 val = readl(rtc->regs + RTC_IRQ1_CONF);
194 /* disable all the interrupts for alarm 1 */
195 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
196 /* Ack the event */
197 rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS);
198
199 spin_unlock(&rtc->lock);
200
201 if (val & RTC_IRQ1_FREQ_EN) {
202 if (val & RTC_IRQ1_FREQ_1HZ)
203 event |= RTC_UF;
204 else
205 event |= RTC_PF;
206 }
207
208 rtc_update_irq(rtc->rtc_dev, 1, event);
209
210 return IRQ_HANDLED;
211}
212
213static struct rtc_class_ops armada38x_rtc_ops = {
214 .read_time = armada38x_rtc_read_time,
215 .set_time = armada38x_rtc_set_time,
216 .read_alarm = armada38x_rtc_read_alarm,
217 .set_alarm = armada38x_rtc_set_alarm,
218 .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
219};
220
221static __init int armada38x_rtc_probe(struct platform_device *pdev)
222{
223 struct resource *res;
224 struct armada38x_rtc *rtc;
225 int ret;
226
227 rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
228 GFP_KERNEL);
229 if (!rtc)
230 return -ENOMEM;
231
232 spin_lock_init(&rtc->lock);
233
234 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
235 rtc->regs = devm_ioremap_resource(&pdev->dev, res);
236 if (IS_ERR(rtc->regs))
237 return PTR_ERR(rtc->regs);
238 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
239 rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
240 if (IS_ERR(rtc->regs_soc))
241 return PTR_ERR(rtc->regs_soc);
242
243 rtc->irq = platform_get_irq(pdev, 0);
244
245 if (rtc->irq < 0) {
246 dev_err(&pdev->dev, "no irq\n");
247 return rtc->irq;
248 }
249 if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
250 0, pdev->name, rtc) < 0) {
251 dev_warn(&pdev->dev, "Interrupt not available.\n");
252 rtc->irq = -1;
253 /*
254 * If there is no interrupt available then we can't
255 * use the alarm
256 */
257 armada38x_rtc_ops.set_alarm = NULL;
258 armada38x_rtc_ops.alarm_irq_enable = NULL;
259 }
260 platform_set_drvdata(pdev, rtc);
261 if (rtc->irq != -1)
262 device_init_wakeup(&pdev->dev, 1);
263
264 rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
265 &armada38x_rtc_ops, THIS_MODULE);
266 if (IS_ERR(rtc->rtc_dev)) {
267 ret = PTR_ERR(rtc->rtc_dev);
268 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
269 return ret;
270 }
271 return 0;
272}
273
274#ifdef CONFIG_PM_SLEEP
275static int armada38x_rtc_suspend(struct device *dev)
276{
277 if (device_may_wakeup(dev)) {
278 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
279
280 return enable_irq_wake(rtc->irq);
281 }
282
283 return 0;
284}
285
286static int armada38x_rtc_resume(struct device *dev)
287{
288 if (device_may_wakeup(dev)) {
289 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
290
291 return disable_irq_wake(rtc->irq);
292 }
293
294 return 0;
295}
296#endif
297
298static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
299 armada38x_rtc_suspend, armada38x_rtc_resume);
300
301#ifdef CONFIG_OF
302static const struct of_device_id armada38x_rtc_of_match_table[] = {
303 { .compatible = "marvell,armada-380-rtc", },
304 {}
305};
306#endif
307
308static struct platform_driver armada38x_rtc_driver = {
309 .driver = {
310 .name = "armada38x-rtc",
311 .pm = &armada38x_rtc_pm_ops,
312 .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
313 },
314};
315
316module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
317
318MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
319MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
320MODULE_LICENSE("GPL");