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