Merge tag 'rtc-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[sfrench/cifs-2.6.git] / drivers / rtc / rtc-lpc32xx.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2010 NXP Semiconductors
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/platform_device.h>
10 #include <linux/spinlock.h>
11 #include <linux/rtc.h>
12 #include <linux/slab.h>
13 #include <linux/io.h>
14 #include <linux/of.h>
15
16 /*
17  * Clock and Power control register offsets
18  */
19 #define LPC32XX_RTC_UCOUNT              0x00
20 #define LPC32XX_RTC_DCOUNT              0x04
21 #define LPC32XX_RTC_MATCH0              0x08
22 #define LPC32XX_RTC_MATCH1              0x0C
23 #define LPC32XX_RTC_CTRL                0x10
24 #define LPC32XX_RTC_INTSTAT             0x14
25 #define LPC32XX_RTC_KEY                 0x18
26 #define LPC32XX_RTC_SRAM                0x80
27
28 #define LPC32XX_RTC_CTRL_MATCH0         (1 << 0)
29 #define LPC32XX_RTC_CTRL_MATCH1         (1 << 1)
30 #define LPC32XX_RTC_CTRL_ONSW_MATCH0    (1 << 2)
31 #define LPC32XX_RTC_CTRL_ONSW_MATCH1    (1 << 3)
32 #define LPC32XX_RTC_CTRL_SW_RESET       (1 << 4)
33 #define LPC32XX_RTC_CTRL_CNTR_DIS       (1 << 6)
34 #define LPC32XX_RTC_CTRL_ONSW_FORCE_HI  (1 << 7)
35
36 #define LPC32XX_RTC_INTSTAT_MATCH0      (1 << 0)
37 #define LPC32XX_RTC_INTSTAT_MATCH1      (1 << 1)
38 #define LPC32XX_RTC_INTSTAT_ONSW        (1 << 2)
39
40 #define LPC32XX_RTC_KEY_ONSW_LOADVAL    0xB5C13F27
41
42 #define rtc_readl(dev, reg) \
43         __raw_readl((dev)->rtc_base + (reg))
44 #define rtc_writel(dev, reg, val) \
45         __raw_writel((val), (dev)->rtc_base + (reg))
46
47 struct lpc32xx_rtc {
48         void __iomem *rtc_base;
49         int irq;
50         unsigned char alarm_enabled;
51         struct rtc_device *rtc;
52         spinlock_t lock;
53 };
54
55 static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time)
56 {
57         unsigned long elapsed_sec;
58         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
59
60         elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT);
61         rtc_time64_to_tm(elapsed_sec, time);
62
63         return 0;
64 }
65
66 static int lpc32xx_rtc_set_time(struct device *dev, struct rtc_time *time)
67 {
68         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
69         u32 secs = rtc_tm_to_time64(time);
70         u32 tmp;
71
72         spin_lock_irq(&rtc->lock);
73
74         /* RTC must be disabled during count update */
75         tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
76         rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS);
77         rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs);
78         rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs);
79         rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS);
80
81         spin_unlock_irq(&rtc->lock);
82
83         return 0;
84 }
85
86 static int lpc32xx_rtc_read_alarm(struct device *dev,
87         struct rtc_wkalrm *wkalrm)
88 {
89         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
90
91         rtc_time64_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time);
92         wkalrm->enabled = rtc->alarm_enabled;
93         wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) &
94                 LPC32XX_RTC_INTSTAT_MATCH0);
95
96         return rtc_valid_tm(&wkalrm->time);
97 }
98
99 static int lpc32xx_rtc_set_alarm(struct device *dev,
100         struct rtc_wkalrm *wkalrm)
101 {
102         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
103         unsigned long alarmsecs;
104         u32 tmp;
105
106         alarmsecs = rtc_tm_to_time64(&wkalrm->time);
107
108         spin_lock_irq(&rtc->lock);
109
110         /* Disable alarm during update */
111         tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
112         rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0);
113
114         rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs);
115
116         rtc->alarm_enabled = wkalrm->enabled;
117         if (wkalrm->enabled) {
118                 rtc_writel(rtc, LPC32XX_RTC_INTSTAT,
119                            LPC32XX_RTC_INTSTAT_MATCH0);
120                 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp |
121                            LPC32XX_RTC_CTRL_MATCH0);
122         }
123
124         spin_unlock_irq(&rtc->lock);
125
126         return 0;
127 }
128
129 static int lpc32xx_rtc_alarm_irq_enable(struct device *dev,
130         unsigned int enabled)
131 {
132         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
133         u32 tmp;
134
135         spin_lock_irq(&rtc->lock);
136         tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
137
138         if (enabled) {
139                 rtc->alarm_enabled = 1;
140                 tmp |= LPC32XX_RTC_CTRL_MATCH0;
141         } else {
142                 rtc->alarm_enabled = 0;
143                 tmp &= ~LPC32XX_RTC_CTRL_MATCH0;
144         }
145
146         rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp);
147         spin_unlock_irq(&rtc->lock);
148
149         return 0;
150 }
151
152 static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev)
153 {
154         struct lpc32xx_rtc *rtc = dev;
155
156         spin_lock(&rtc->lock);
157
158         /* Disable alarm interrupt */
159         rtc_writel(rtc, LPC32XX_RTC_CTRL,
160                 rtc_readl(rtc, LPC32XX_RTC_CTRL) &
161                           ~LPC32XX_RTC_CTRL_MATCH0);
162         rtc->alarm_enabled = 0;
163
164         /*
165          * Write a large value to the match value so the RTC won't
166          * keep firing the match status
167          */
168         rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF);
169         rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0);
170
171         spin_unlock(&rtc->lock);
172
173         rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
174
175         return IRQ_HANDLED;
176 }
177
178 static const struct rtc_class_ops lpc32xx_rtc_ops = {
179         .read_time              = lpc32xx_rtc_read_time,
180         .set_time               = lpc32xx_rtc_set_time,
181         .read_alarm             = lpc32xx_rtc_read_alarm,
182         .set_alarm              = lpc32xx_rtc_set_alarm,
183         .alarm_irq_enable       = lpc32xx_rtc_alarm_irq_enable,
184 };
185
186 static int lpc32xx_rtc_probe(struct platform_device *pdev)
187 {
188         struct lpc32xx_rtc *rtc;
189         int err;
190         u32 tmp;
191
192         rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
193         if (unlikely(!rtc))
194                 return -ENOMEM;
195
196         rtc->rtc_base = devm_platform_ioremap_resource(pdev, 0);
197         if (IS_ERR(rtc->rtc_base))
198                 return PTR_ERR(rtc->rtc_base);
199
200         spin_lock_init(&rtc->lock);
201
202         /*
203          * The RTC is on a separate power domain and can keep it's state
204          * across a chip power cycle. If the RTC has never been previously
205          * setup, then set it up now for the first time.
206          */
207         tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL);
208         if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) {
209                 tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET |
210                         LPC32XX_RTC_CTRL_CNTR_DIS |
211                         LPC32XX_RTC_CTRL_MATCH0 |
212                         LPC32XX_RTC_CTRL_MATCH1 |
213                         LPC32XX_RTC_CTRL_ONSW_MATCH0 |
214                         LPC32XX_RTC_CTRL_ONSW_MATCH1 |
215                         LPC32XX_RTC_CTRL_ONSW_FORCE_HI);
216                 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp);
217
218                 /* Clear latched interrupt states */
219                 rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF);
220                 rtc_writel(rtc, LPC32XX_RTC_INTSTAT,
221                            LPC32XX_RTC_INTSTAT_MATCH0 |
222                            LPC32XX_RTC_INTSTAT_MATCH1 |
223                            LPC32XX_RTC_INTSTAT_ONSW);
224
225                 /* Write key value to RTC so it won't reload on reset */
226                 rtc_writel(rtc, LPC32XX_RTC_KEY,
227                            LPC32XX_RTC_KEY_ONSW_LOADVAL);
228         } else {
229                 rtc_writel(rtc, LPC32XX_RTC_CTRL,
230                            tmp & ~LPC32XX_RTC_CTRL_MATCH0);
231         }
232
233         platform_set_drvdata(pdev, rtc);
234
235         rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
236         if (IS_ERR(rtc->rtc))
237                 return PTR_ERR(rtc->rtc);
238
239         rtc->rtc->ops = &lpc32xx_rtc_ops;
240         rtc->rtc->range_max = U32_MAX;
241
242         err = rtc_register_device(rtc->rtc);
243         if (err)
244                 return err;
245
246         /*
247          * IRQ is enabled after device registration in case alarm IRQ
248          * is pending upon suspend exit.
249          */
250         rtc->irq = platform_get_irq(pdev, 0);
251         if (rtc->irq < 0) {
252                 dev_warn(&pdev->dev, "Can't get interrupt resource\n");
253         } else {
254                 if (devm_request_irq(&pdev->dev, rtc->irq,
255                                      lpc32xx_rtc_alarm_interrupt,
256                                      0, pdev->name, rtc) < 0) {
257                         dev_warn(&pdev->dev, "Can't request interrupt.\n");
258                         rtc->irq = -1;
259                 } else {
260                         device_init_wakeup(&pdev->dev, 1);
261                 }
262         }
263
264         return 0;
265 }
266
267 #ifdef CONFIG_PM
268 static int lpc32xx_rtc_suspend(struct device *dev)
269 {
270         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
271
272         if (rtc->irq >= 0) {
273                 if (device_may_wakeup(dev))
274                         enable_irq_wake(rtc->irq);
275                 else
276                         disable_irq_wake(rtc->irq);
277         }
278
279         return 0;
280 }
281
282 static int lpc32xx_rtc_resume(struct device *dev)
283 {
284         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
285
286         if (rtc->irq >= 0 && device_may_wakeup(dev))
287                 disable_irq_wake(rtc->irq);
288
289         return 0;
290 }
291
292 /* Unconditionally disable the alarm */
293 static int lpc32xx_rtc_freeze(struct device *dev)
294 {
295         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
296
297         spin_lock_irq(&rtc->lock);
298
299         rtc_writel(rtc, LPC32XX_RTC_CTRL,
300                 rtc_readl(rtc, LPC32XX_RTC_CTRL) &
301                           ~LPC32XX_RTC_CTRL_MATCH0);
302
303         spin_unlock_irq(&rtc->lock);
304
305         return 0;
306 }
307
308 static int lpc32xx_rtc_thaw(struct device *dev)
309 {
310         struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
311
312         if (rtc->alarm_enabled) {
313                 spin_lock_irq(&rtc->lock);
314
315                 rtc_writel(rtc, LPC32XX_RTC_CTRL,
316                            rtc_readl(rtc, LPC32XX_RTC_CTRL) |
317                            LPC32XX_RTC_CTRL_MATCH0);
318
319                 spin_unlock_irq(&rtc->lock);
320         }
321
322         return 0;
323 }
324
325 static const struct dev_pm_ops lpc32xx_rtc_pm_ops = {
326         .suspend = lpc32xx_rtc_suspend,
327         .resume = lpc32xx_rtc_resume,
328         .freeze = lpc32xx_rtc_freeze,
329         .thaw = lpc32xx_rtc_thaw,
330         .restore = lpc32xx_rtc_resume
331 };
332
333 #define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops)
334 #else
335 #define LPC32XX_RTC_PM_OPS NULL
336 #endif
337
338 #ifdef CONFIG_OF
339 static const struct of_device_id lpc32xx_rtc_match[] = {
340         { .compatible = "nxp,lpc3220-rtc" },
341         { }
342 };
343 MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match);
344 #endif
345
346 static struct platform_driver lpc32xx_rtc_driver = {
347         .probe          = lpc32xx_rtc_probe,
348         .driver = {
349                 .name   = "rtc-lpc32xx",
350                 .pm     = LPC32XX_RTC_PM_OPS,
351                 .of_match_table = of_match_ptr(lpc32xx_rtc_match),
352         },
353 };
354
355 module_platform_driver(lpc32xx_rtc_driver);
356
357 MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com");
358 MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC");
359 MODULE_LICENSE("GPL");
360 MODULE_ALIAS("platform:rtc-lpc32xx");