mvebu: armada-385-rd has been renamed to armada-388-rd upstream
[openwrt.git] / target / linux / mvebu / patches-3.18 / 600-armada_38x_rtc.patch
1 --- /dev/null
2 +++ b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
3 @@ -0,0 +1,22 @@
4 +* Real Time Clock of the Armada 38x SoCs
5 +
6 +RTC controller for the Armada 38x SoCs
7 +
8 +Required properties:
9 +- compatible : Should be "marvell,armada-380-rtc"
10 +- reg: a list of base address and size pairs, one for each entry in
11 +  reg-names
12 +- reg names: should contain:
13 +  * "rtc" for the RTC registers
14 +  * "rtc-soc" for the SoC related registers and among them the one
15 +    related to the interrupt.
16 +- interrupts: IRQ line for the RTC.
17 +
18 +Example:
19 +
20 +rtc@a3800 {
21 +       compatible = "marvell,armada-380-rtc";
22 +       reg = <0xa3800 0x20>, <0x184a0 0x0c>;
23 +       reg-names = "rtc", "rtc-soc";
24 +       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
25 +};
26 --- a/drivers/rtc/Kconfig
27 +++ b/drivers/rtc/Kconfig
28 @@ -1262,6 +1262,16 @@ config RTC_DRV_MV
29           This driver can also be built as a module. If so, the module
30           will be called rtc-mv.
31  
32 +config RTC_DRV_ARMADA38X
33 +       tristate "Armada 38x Marvell SoC RTC"
34 +       depends on ARCH_MVEBU
35 +       help
36 +         If you say yes here you will get support for the in-chip RTC
37 +         that can be found in the Armada 38x Marvell's SoC device
38 +
39 +         This driver can also be built as a module. If so, the module
40 +         will be called armada38x-rtc.
41 +
42  config RTC_DRV_PS3
43         tristate "PS3 RTC"
44         depends on PPC_PS3
45 --- a/drivers/rtc/Makefile
46 +++ b/drivers/rtc/Makefile
47 @@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-8
48  obj-$(CONFIG_RTC_DRV_88PM80X)  += rtc-88pm80x.o
49  obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
50  obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
51 +obj-$(CONFIG_RTC_DRV_ARMADA38X)        += rtc-armada38x.o
52  obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
53  obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
54  obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
55 --- /dev/null
56 +++ b/drivers/rtc/rtc-armada38x.c
57 @@ -0,0 +1,320 @@
58 +/*
59 + * RTC driver for the Armada 38x Marvell SoCs
60 + *
61 + * Copyright (C) 2015 Marvell
62 + *
63 + * Gregory Clement <gregory.clement@free-electrons.com>
64 + *
65 + * This program is free software; you can redistribute it and/or
66 + * modify it under the terms of the GNU General Public License as
67 + * published by the Free Software Foundation; either version 2 of the
68 + * License, or (at your option) any later version.
69 + *
70 + */
71 +
72 +#include <linux/delay.h>
73 +#include <linux/io.h>
74 +#include <linux/module.h>
75 +#include <linux/of.h>
76 +#include <linux/platform_device.h>
77 +#include <linux/rtc.h>
78 +
79 +#define RTC_STATUS         0x0
80 +#define RTC_STATUS_ALARM1          BIT(0)
81 +#define RTC_STATUS_ALARM2          BIT(1)
82 +#define RTC_IRQ1_CONF      0x4
83 +#define RTC_IRQ1_AL_EN             BIT(0)
84 +#define RTC_IRQ1_FREQ_EN           BIT(1)
85 +#define RTC_IRQ1_FREQ_1HZ          BIT(2)
86 +#define RTC_TIME           0xC
87 +#define RTC_ALARM1         0x10
88 +
89 +#define SOC_RTC_INTERRUPT   0x8
90 +#define SOC_RTC_ALARM1         BIT(0)
91 +#define SOC_RTC_ALARM2         BIT(1)
92 +#define SOC_RTC_ALARM1_MASK    BIT(2)
93 +#define SOC_RTC_ALARM2_MASK    BIT(3)
94 +
95 +struct armada38x_rtc {
96 +       struct rtc_device   *rtc_dev;
97 +       void __iomem        *regs;
98 +       void __iomem        *regs_soc;
99 +       spinlock_t          lock;
100 +       int                 irq;
101 +};
102 +
103 +/*
104 + * According to the datasheet, the OS should wait 5us after every
105 + * register write to the RTC hard macro so that the required update
106 + * can occur without holding off the system bus
107 + */
108 +static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
109 +{
110 +       writel(val, rtc->regs + offset);
111 +       udelay(5);
112 +}
113 +
114 +static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
115 +{
116 +       struct armada38x_rtc *rtc = dev_get_drvdata(dev);
117 +       unsigned long time, time_check, flags;
118 +
119 +       spin_lock_irqsave(&rtc->lock, flags);
120 +
121 +       time = readl(rtc->regs + RTC_TIME);
122 +       /*
123 +        * WA for failing time set attempts. As stated in HW ERRATA if
124 +        * more than one second between two time reads is detected
125 +        * then read once again.
126 +        */
127 +       time_check = readl(rtc->regs + RTC_TIME);
128 +       if ((time_check - time) > 1)
129 +               time_check = readl(rtc->regs + RTC_TIME);
130 +
131 +       spin_unlock_irqrestore(&rtc->lock, flags);
132 +
133 +       rtc_time_to_tm(time_check, tm);
134 +
135 +       return 0;
136 +}
137 +
138 +static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
139 +{
140 +       struct armada38x_rtc *rtc = dev_get_drvdata(dev);
141 +       int ret = 0;
142 +       unsigned long time, flags;
143 +
144 +       ret = rtc_tm_to_time(tm, &time);
145 +
146 +       if (ret)
147 +               goto out;
148 +       /*
149 +        * Setting the RTC time not always succeeds. According to the
150 +        * errata we need to first write on the status register and
151 +        * then wait for 100ms before writing to the time register to be
152 +        * sure that the data will be taken into account.
153 +        */
154 +       spin_lock_irqsave(&rtc->lock, flags);
155 +
156 +       rtc_delayed_write(0, rtc, RTC_STATUS);
157 +
158 +       spin_unlock_irqrestore(&rtc->lock, flags);
159 +
160 +       msleep(100);
161 +
162 +       spin_lock_irqsave(&rtc->lock, flags);
163 +
164 +       rtc_delayed_write(time, rtc, RTC_TIME);
165 +
166 +       spin_unlock_irqrestore(&rtc->lock, flags);
167 +out:
168 +       return ret;
169 +}
170 +
171 +static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
172 +{
173 +       struct armada38x_rtc *rtc = dev_get_drvdata(dev);
174 +       unsigned long time, flags;
175 +       u32 val;
176 +
177 +       spin_lock_irqsave(&rtc->lock, flags);
178 +
179 +       time = readl(rtc->regs + RTC_ALARM1);
180 +       val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN;
181 +
182 +       spin_unlock_irqrestore(&rtc->lock, flags);
183 +
184 +       alrm->enabled = val ? 1 : 0;
185 +       rtc_time_to_tm(time,  &alrm->time);
186 +
187 +       return 0;
188 +}
189 +
190 +static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
191 +{
192 +       struct armada38x_rtc *rtc = dev_get_drvdata(dev);
193 +       unsigned long time, flags;
194 +       int ret = 0;
195 +       u32 val;
196 +
197 +       ret = rtc_tm_to_time(&alrm->time, &time);
198 +
199 +       if (ret)
200 +               goto out;
201 +
202 +       spin_lock_irqsave(&rtc->lock, flags);
203 +
204 +       rtc_delayed_write(time, rtc, RTC_ALARM1);
205 +
206 +       if (alrm->enabled) {
207 +                       rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
208 +                       val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
209 +                       writel(val | SOC_RTC_ALARM1_MASK,
210 +                              rtc->regs_soc + SOC_RTC_INTERRUPT);
211 +       }
212 +
213 +       spin_unlock_irqrestore(&rtc->lock, flags);
214 +
215 +out:
216 +       return ret;
217 +}
218 +
219 +static int armada38x_rtc_alarm_irq_enable(struct device *dev,
220 +                                        unsigned int enabled)
221 +{
222 +       struct armada38x_rtc *rtc = dev_get_drvdata(dev);
223 +       unsigned long flags;
224 +
225 +       spin_lock_irqsave(&rtc->lock, flags);
226 +
227 +       if (enabled)
228 +               rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
229 +       else
230 +               rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
231 +
232 +       spin_unlock_irqrestore(&rtc->lock, flags);
233 +
234 +       return 0;
235 +}
236 +
237 +static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
238 +{
239 +       struct armada38x_rtc *rtc = data;
240 +       u32 val;
241 +       int event = RTC_IRQF | RTC_AF;
242 +
243 +       dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
244 +
245 +       spin_lock(&rtc->lock);
246 +
247 +       val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
248 +
249 +       writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
250 +       val = readl(rtc->regs + RTC_IRQ1_CONF);
251 +       /* disable all the interrupts for alarm 1 */
252 +       rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
253 +       /* Ack the event */
254 +       rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS);
255 +
256 +       spin_unlock(&rtc->lock);
257 +
258 +       if (val & RTC_IRQ1_FREQ_EN) {
259 +               if (val & RTC_IRQ1_FREQ_1HZ)
260 +                       event |= RTC_UF;
261 +               else
262 +                       event |= RTC_PF;
263 +       }
264 +
265 +       rtc_update_irq(rtc->rtc_dev, 1, event);
266 +
267 +       return IRQ_HANDLED;
268 +}
269 +
270 +static struct rtc_class_ops armada38x_rtc_ops = {
271 +       .read_time = armada38x_rtc_read_time,
272 +       .set_time = armada38x_rtc_set_time,
273 +       .read_alarm = armada38x_rtc_read_alarm,
274 +       .set_alarm = armada38x_rtc_set_alarm,
275 +       .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
276 +};
277 +
278 +static __init int armada38x_rtc_probe(struct platform_device *pdev)
279 +{
280 +       struct resource *res;
281 +       struct armada38x_rtc *rtc;
282 +       int ret;
283 +
284 +       rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
285 +                           GFP_KERNEL);
286 +       if (!rtc)
287 +               return -ENOMEM;
288 +
289 +       spin_lock_init(&rtc->lock);
290 +
291 +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
292 +       rtc->regs = devm_ioremap_resource(&pdev->dev, res);
293 +       if (IS_ERR(rtc->regs))
294 +               return PTR_ERR(rtc->regs);
295 +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
296 +       rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
297 +       if (IS_ERR(rtc->regs_soc))
298 +               return PTR_ERR(rtc->regs_soc);
299 +
300 +       rtc->irq = platform_get_irq(pdev, 0);
301 +
302 +       if (rtc->irq < 0) {
303 +               dev_err(&pdev->dev, "no irq\n");
304 +               return rtc->irq;
305 +       }
306 +       if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
307 +                               0, pdev->name, rtc) < 0) {
308 +               dev_warn(&pdev->dev, "Interrupt not available.\n");
309 +               rtc->irq = -1;
310 +               /*
311 +                * If there is no interrupt available then we can't
312 +                * use the alarm
313 +                */
314 +               armada38x_rtc_ops.set_alarm = NULL;
315 +               armada38x_rtc_ops.alarm_irq_enable = NULL;
316 +       }
317 +       platform_set_drvdata(pdev, rtc);
318 +       if (rtc->irq != -1)
319 +               device_init_wakeup(&pdev->dev, 1);
320 +
321 +       rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
322 +                                       &armada38x_rtc_ops, THIS_MODULE);
323 +       if (IS_ERR(rtc->rtc_dev)) {
324 +               ret = PTR_ERR(rtc->rtc_dev);
325 +               dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
326 +               return ret;
327 +       }
328 +       return 0;
329 +}
330 +
331 +#ifdef CONFIG_PM_SLEEP
332 +static int armada38x_rtc_suspend(struct device *dev)
333 +{
334 +       if (device_may_wakeup(dev)) {
335 +               struct armada38x_rtc *rtc = dev_get_drvdata(dev);
336 +
337 +               return enable_irq_wake(rtc->irq);
338 +       }
339 +
340 +       return 0;
341 +}
342 +
343 +static int armada38x_rtc_resume(struct device *dev)
344 +{
345 +       if (device_may_wakeup(dev)) {
346 +               struct armada38x_rtc *rtc = dev_get_drvdata(dev);
347 +
348 +               return disable_irq_wake(rtc->irq);
349 +       }
350 +
351 +       return 0;
352 +}
353 +#endif
354 +
355 +static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
356 +                        armada38x_rtc_suspend, armada38x_rtc_resume);
357 +
358 +#ifdef CONFIG_OF
359 +static const struct of_device_id armada38x_rtc_of_match_table[] = {
360 +       { .compatible = "marvell,armada-380-rtc", },
361 +       {}
362 +};
363 +#endif
364 +
365 +static struct platform_driver armada38x_rtc_driver = {
366 +       .driver         = {
367 +               .name   = "armada38x-rtc",
368 +               .pm     = &armada38x_rtc_pm_ops,
369 +               .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
370 +       },
371 +};
372 +
373 +module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
374 +
375 +MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
376 +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
377 +MODULE_LICENSE("GPL");
378 --- a/MAINTAINERS
379 +++ b/MAINTAINERS
380 @@ -1136,6 +1136,7 @@ M:        Sebastian Hesselbarth <sebastian.hess
381  L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
382  S:     Maintained
383  F:     arch/arm/mach-mvebu/
384 +F:     drivers/rtc/armada38x-rtc
385  
386  ARM/Marvell Berlin SoC support
387  M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
388 --- a/arch/arm/boot/dts/armada-38x.dtsi
389 +++ b/arch/arm/boot/dts/armada-38x.dtsi
390 @@ -420,6 +420,13 @@
391                                 clocks = <&gateclk 4>;
392                         };
393  
394 +                       rtc@a3800 {
395 +                               compatible = "marvell,armada-380-rtc";
396 +                               reg = <0xa3800 0x20>, <0x184a0 0x0c>;
397 +                               reg-names = "rtc", "rtc-soc";
398 +                               interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
399 +                       };
400 +
401                         sata@a8000 {
402                                 compatible = "marvell,armada-380-ahci";
403                                 reg = <0xa8000 0x2000>;