1/*
2 * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
3 *
4 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License
6 * Version 2 or later at the following locations:
7 *
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
10 */
11
12#include <linux/init.h>
13#include <linux/io.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/platform_device.h>
19#include <linux/rtc.h>
20
21/* These register offsets are relative to LP (Low Power) range */
22#define SNVS_LPCR		0x04
23#define SNVS_LPSR		0x18
24#define SNVS_LPSRTCMR		0x1c
25#define SNVS_LPSRTCLR		0x20
26#define SNVS_LPTAR		0x24
27#define SNVS_LPPGDR		0x30
28
29#define SNVS_LPCR_SRTC_ENV	(1 << 0)
30#define SNVS_LPCR_LPTA_EN	(1 << 1)
31#define SNVS_LPCR_LPWUI_EN	(1 << 3)
32#define SNVS_LPSR_LPTA		(1 << 0)
33
34#define SNVS_LPPGDR_INIT	0x41736166
35#define CNTR_TO_SECS_SH		15
36
37struct snvs_rtc_data {
38	struct rtc_device *rtc;
39	void __iomem *ioaddr;
40	int irq;
41	spinlock_t lock;
42};
43
44static u32 rtc_read_lp_counter(void __iomem *ioaddr)
45{
46	u64 read1, read2;
47
48	do {
49		read1 = readl(ioaddr + SNVS_LPSRTCMR);
50		read1 <<= 32;
51		read1 |= readl(ioaddr + SNVS_LPSRTCLR);
52
53		read2 = readl(ioaddr + SNVS_LPSRTCMR);
54		read2 <<= 32;
55		read2 |= readl(ioaddr + SNVS_LPSRTCLR);
56	} while (read1 != read2);
57
58	/* Convert 47-bit counter to 32-bit raw second count */
59	return (u32) (read1 >> CNTR_TO_SECS_SH);
60}
61
62static void rtc_write_sync_lp(void __iomem *ioaddr)
63{
64	u32 count1, count2, count3;
65	int i;
66
67	/* Wait for 3 CKIL cycles */
68	for (i = 0; i < 3; i++) {
69		do {
70			count1 = readl(ioaddr + SNVS_LPSRTCLR);
71			count2 = readl(ioaddr + SNVS_LPSRTCLR);
72		} while (count1 != count2);
73
74		/* Now wait until counter value changes */
75		do {
76			do {
77				count2 = readl(ioaddr + SNVS_LPSRTCLR);
78				count3 = readl(ioaddr + SNVS_LPSRTCLR);
79			} while (count2 != count3);
80		} while (count3 == count1);
81	}
82}
83
84static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
85{
86	unsigned long flags;
87	int timeout = 1000;
88	u32 lpcr;
89
90	spin_lock_irqsave(&data->lock, flags);
91
92	lpcr = readl(data->ioaddr + SNVS_LPCR);
93	if (enable)
94		lpcr |= SNVS_LPCR_SRTC_ENV;
95	else
96		lpcr &= ~SNVS_LPCR_SRTC_ENV;
97	writel(lpcr, data->ioaddr + SNVS_LPCR);
98
99	spin_unlock_irqrestore(&data->lock, flags);
100
101	while (--timeout) {
102		lpcr = readl(data->ioaddr + SNVS_LPCR);
103
104		if (enable) {
105			if (lpcr & SNVS_LPCR_SRTC_ENV)
106				break;
107		} else {
108			if (!(lpcr & SNVS_LPCR_SRTC_ENV))
109				break;
110		}
111	}
112
113	if (!timeout)
114		return -ETIMEDOUT;
115
116	return 0;
117}
118
119static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
120{
121	struct snvs_rtc_data *data = dev_get_drvdata(dev);
122	unsigned long time = rtc_read_lp_counter(data->ioaddr);
123
124	rtc_time_to_tm(time, tm);
125
126	return 0;
127}
128
129static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
130{
131	struct snvs_rtc_data *data = dev_get_drvdata(dev);
132	unsigned long time;
133
134	rtc_tm_to_time(tm, &time);
135
136	/* Disable RTC first */
137	snvs_rtc_enable(data, false);
138
139	/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
140	writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR);
141	writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR);
142
143	/* Enable RTC again */
144	snvs_rtc_enable(data, true);
145
146	return 0;
147}
148
149static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
150{
151	struct snvs_rtc_data *data = dev_get_drvdata(dev);
152	u32 lptar, lpsr;
153
154	lptar = readl(data->ioaddr + SNVS_LPTAR);
155	rtc_time_to_tm(lptar, &alrm->time);
156
157	lpsr = readl(data->ioaddr + SNVS_LPSR);
158	alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
159
160	return 0;
161}
162
163static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
164{
165	struct snvs_rtc_data *data = dev_get_drvdata(dev);
166	u32 lpcr;
167	unsigned long flags;
168
169	spin_lock_irqsave(&data->lock, flags);
170
171	lpcr = readl(data->ioaddr + SNVS_LPCR);
172	if (enable)
173		lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
174	else
175		lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
176	writel(lpcr, data->ioaddr + SNVS_LPCR);
177
178	spin_unlock_irqrestore(&data->lock, flags);
179
180	rtc_write_sync_lp(data->ioaddr);
181
182	return 0;
183}
184
185static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
186{
187	struct snvs_rtc_data *data = dev_get_drvdata(dev);
188	struct rtc_time *alrm_tm = &alrm->time;
189	unsigned long time;
190	unsigned long flags;
191	u32 lpcr;
192
193	rtc_tm_to_time(alrm_tm, &time);
194
195	spin_lock_irqsave(&data->lock, flags);
196
197	/* Have to clear LPTA_EN before programming new alarm time in LPTAR */
198	lpcr = readl(data->ioaddr + SNVS_LPCR);
199	lpcr &= ~SNVS_LPCR_LPTA_EN;
200	writel(lpcr, data->ioaddr + SNVS_LPCR);
201
202	spin_unlock_irqrestore(&data->lock, flags);
203
204	writel(time, data->ioaddr + SNVS_LPTAR);
205
206	/* Clear alarm interrupt status bit */
207	writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR);
208
209	return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
210}
211
212static const struct rtc_class_ops snvs_rtc_ops = {
213	.read_time = snvs_rtc_read_time,
214	.set_time = snvs_rtc_set_time,
215	.read_alarm = snvs_rtc_read_alarm,
216	.set_alarm = snvs_rtc_set_alarm,
217	.alarm_irq_enable = snvs_rtc_alarm_irq_enable,
218};
219
220static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
221{
222	struct device *dev = dev_id;
223	struct snvs_rtc_data *data = dev_get_drvdata(dev);
224	u32 lpsr;
225	u32 events = 0;
226
227	lpsr = readl(data->ioaddr + SNVS_LPSR);
228
229	if (lpsr & SNVS_LPSR_LPTA) {
230		events |= (RTC_AF | RTC_IRQF);
231
232		/* RTC alarm should be one-shot */
233		snvs_rtc_alarm_irq_enable(dev, 0);
234
235		rtc_update_irq(data->rtc, 1, events);
236	}
237
238	/* clear interrupt status */
239	writel(lpsr, data->ioaddr + SNVS_LPSR);
240
241	return events ? IRQ_HANDLED : IRQ_NONE;
242}
243
244static int snvs_rtc_probe(struct platform_device *pdev)
245{
246	struct snvs_rtc_data *data;
247	struct resource *res;
248	int ret;
249
250	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
251	if (!data)
252		return -ENOMEM;
253
254	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
255	data->ioaddr = devm_ioremap_resource(&pdev->dev, res);
256	if (IS_ERR(data->ioaddr))
257		return PTR_ERR(data->ioaddr);
258
259	data->irq = platform_get_irq(pdev, 0);
260	if (data->irq < 0)
261		return data->irq;
262
263	platform_set_drvdata(pdev, data);
264
265	spin_lock_init(&data->lock);
266
267	/* Initialize glitch detect */
268	writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR);
269
270	/* Clear interrupt status */
271	writel(0xffffffff, data->ioaddr + SNVS_LPSR);
272
273	/* Enable RTC */
274	snvs_rtc_enable(data, true);
275
276	device_init_wakeup(&pdev->dev, true);
277
278	ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
279			       IRQF_SHARED, "rtc alarm", &pdev->dev);
280	if (ret) {
281		dev_err(&pdev->dev, "failed to request irq %d: %d\n",
282			data->irq, ret);
283		return ret;
284	}
285
286	data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
287					&snvs_rtc_ops, THIS_MODULE);
288	if (IS_ERR(data->rtc)) {
289		ret = PTR_ERR(data->rtc);
290		dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
291		return ret;
292	}
293
294	return 0;
295}
296
297#ifdef CONFIG_PM_SLEEP
298static int snvs_rtc_suspend(struct device *dev)
299{
300	struct snvs_rtc_data *data = dev_get_drvdata(dev);
301
302	if (device_may_wakeup(dev))
303		enable_irq_wake(data->irq);
304
305	return 0;
306}
307
308static int snvs_rtc_resume(struct device *dev)
309{
310	struct snvs_rtc_data *data = dev_get_drvdata(dev);
311
312	if (device_may_wakeup(dev))
313		disable_irq_wake(data->irq);
314
315	return 0;
316}
317#endif
318
319static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume);
320
321static const struct of_device_id snvs_dt_ids[] = {
322	{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
323	{ /* sentinel */ }
324};
325MODULE_DEVICE_TABLE(of, snvs_dt_ids);
326
327static struct platform_driver snvs_rtc_driver = {
328	.driver = {
329		.name	= "snvs_rtc",
330		.owner	= THIS_MODULE,
331		.pm	= &snvs_rtc_pm_ops,
332		.of_match_table = snvs_dt_ids,
333	},
334	.probe		= snvs_rtc_probe,
335};
336module_platform_driver(snvs_rtc_driver);
337
338MODULE_AUTHOR("Freescale Semiconductor, Inc.");
339MODULE_DESCRIPTION("Freescale SNVS RTC Driver");
340MODULE_LICENSE("GPL");
341