xref: /openbmc/linux/drivers/rtc/rtc-cadence.c (revision de528723)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2019 Cadence
5  *
6  * Authors:
7  *  Jan Kotas <jank@cadence.com>
8  */
9 
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/of.h>
13 #include <linux/io.h>
14 #include <linux/rtc.h>
15 #include <linux/clk.h>
16 #include <linux/bcd.h>
17 #include <linux/bitfield.h>
18 #include <linux/interrupt.h>
19 #include <linux/pm_wakeirq.h>
20 
21 /* Registers */
22 #define CDNS_RTC_CTLR		0x00
23 #define CDNS_RTC_HMR		0x04
24 #define CDNS_RTC_TIMR		0x08
25 #define CDNS_RTC_CALR		0x0C
26 #define CDNS_RTC_TIMAR		0x10
27 #define CDNS_RTC_CALAR		0x14
28 #define CDNS_RTC_AENR		0x18
29 #define CDNS_RTC_EFLR		0x1C
30 #define CDNS_RTC_IENR		0x20
31 #define CDNS_RTC_IDISR		0x24
32 #define CDNS_RTC_IMSKR		0x28
33 #define CDNS_RTC_STSR		0x2C
34 #define CDNS_RTC_KRTCR		0x30
35 
36 /* Control */
37 #define CDNS_RTC_CTLR_TIME	BIT(0)
38 #define CDNS_RTC_CTLR_CAL	BIT(1)
39 #define CDNS_RTC_CTLR_TIME_CAL	(CDNS_RTC_CTLR_TIME | CDNS_RTC_CTLR_CAL)
40 
41 /* Status */
42 #define CDNS_RTC_STSR_VT	BIT(0)
43 #define CDNS_RTC_STSR_VC	BIT(1)
44 #define CDNS_RTC_STSR_VTA	BIT(2)
45 #define CDNS_RTC_STSR_VCA	BIT(3)
46 #define CDNS_RTC_STSR_VT_VC	(CDNS_RTC_STSR_VT | CDNS_RTC_STSR_VC)
47 #define CDNS_RTC_STSR_VTA_VCA	(CDNS_RTC_STSR_VTA | CDNS_RTC_STSR_VCA)
48 
49 /* Keep RTC */
50 #define CDNS_RTC_KRTCR_KRTC	BIT(0)
51 
52 /* Alarm, Event, Interrupt */
53 #define CDNS_RTC_AEI_HOS	BIT(0)
54 #define CDNS_RTC_AEI_SEC	BIT(1)
55 #define CDNS_RTC_AEI_MIN	BIT(2)
56 #define CDNS_RTC_AEI_HOUR	BIT(3)
57 #define CDNS_RTC_AEI_DATE	BIT(4)
58 #define CDNS_RTC_AEI_MNTH	BIT(5)
59 #define CDNS_RTC_AEI_ALRM	BIT(6)
60 
61 /* Time */
62 #define CDNS_RTC_TIME_H		GENMASK(7, 0)
63 #define CDNS_RTC_TIME_S		GENMASK(14, 8)
64 #define CDNS_RTC_TIME_M		GENMASK(22, 16)
65 #define CDNS_RTC_TIME_HR	GENMASK(29, 24)
66 #define CDNS_RTC_TIME_PM	BIT(30)
67 #define CDNS_RTC_TIME_CH	BIT(31)
68 
69 /* Calendar */
70 #define CDNS_RTC_CAL_DAY	GENMASK(2, 0)
71 #define CDNS_RTC_CAL_M		GENMASK(7, 3)
72 #define CDNS_RTC_CAL_D		GENMASK(13, 8)
73 #define CDNS_RTC_CAL_Y		GENMASK(23, 16)
74 #define CDNS_RTC_CAL_C		GENMASK(29, 24)
75 #define CDNS_RTC_CAL_CH		BIT(31)
76 
77 #define CDNS_RTC_MAX_REGS_TRIES	3
78 
79 struct cdns_rtc {
80 	struct rtc_device *rtc_dev;
81 	struct clk *pclk;
82 	struct clk *ref_clk;
83 	void __iomem *regs;
84 	int irq;
85 };
86 
87 static void cdns_rtc_set_enabled(struct cdns_rtc *crtc, bool enabled)
88 {
89 	u32 reg = enabled ? 0x0 : CDNS_RTC_CTLR_TIME_CAL;
90 
91 	writel(reg, crtc->regs + CDNS_RTC_CTLR);
92 }
93 
94 static bool cdns_rtc_get_enabled(struct cdns_rtc *crtc)
95 {
96 	return !(readl(crtc->regs + CDNS_RTC_CTLR) & CDNS_RTC_CTLR_TIME_CAL);
97 }
98 
99 static irqreturn_t cdns_rtc_irq_handler(int irq, void *id)
100 {
101 	struct device *dev = id;
102 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
103 
104 	/* Reading the register clears it */
105 	if (!(readl(crtc->regs + CDNS_RTC_EFLR) & CDNS_RTC_AEI_ALRM))
106 		return IRQ_NONE;
107 
108 	rtc_update_irq(crtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
109 	return IRQ_HANDLED;
110 }
111 
112 static u32 cdns_rtc_time2reg(struct rtc_time *tm)
113 {
114 	return FIELD_PREP(CDNS_RTC_TIME_S,  bin2bcd(tm->tm_sec))
115 	     | FIELD_PREP(CDNS_RTC_TIME_M,  bin2bcd(tm->tm_min))
116 	     | FIELD_PREP(CDNS_RTC_TIME_HR, bin2bcd(tm->tm_hour));
117 }
118 
119 static void cdns_rtc_reg2time(u32 reg, struct rtc_time *tm)
120 {
121 	tm->tm_sec  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_S, reg));
122 	tm->tm_min  = bcd2bin(FIELD_GET(CDNS_RTC_TIME_M, reg));
123 	tm->tm_hour = bcd2bin(FIELD_GET(CDNS_RTC_TIME_HR, reg));
124 }
125 
126 static int cdns_rtc_read_time(struct device *dev, struct rtc_time *tm)
127 {
128 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
129 	u32 reg;
130 
131 	/* If the RTC is disabled, assume the values are invalid */
132 	if (!cdns_rtc_get_enabled(crtc))
133 		return -EINVAL;
134 
135 	cdns_rtc_set_enabled(crtc, false);
136 
137 	reg = readl(crtc->regs + CDNS_RTC_TIMR);
138 	cdns_rtc_reg2time(reg, tm);
139 
140 	reg = readl(crtc->regs + CDNS_RTC_CALR);
141 	tm->tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
142 	tm->tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
143 	tm->tm_year = bcd2bin(FIELD_GET(CDNS_RTC_CAL_Y, reg))
144 		    + bcd2bin(FIELD_GET(CDNS_RTC_CAL_C, reg)) * 100 - 1900;
145 	tm->tm_wday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_DAY, reg)) - 1;
146 
147 	cdns_rtc_set_enabled(crtc, true);
148 	return 0;
149 }
150 
151 static int cdns_rtc_set_time(struct device *dev, struct rtc_time *tm)
152 {
153 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
154 	u32 timr, calr, stsr;
155 	int ret = -EIO;
156 	int year = tm->tm_year + 1900;
157 	int tries;
158 
159 	cdns_rtc_set_enabled(crtc, false);
160 
161 	timr = cdns_rtc_time2reg(tm);
162 
163 	calr = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(tm->tm_mday))
164 	     | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(tm->tm_mon + 1))
165 	     | FIELD_PREP(CDNS_RTC_CAL_Y, bin2bcd(year % 100))
166 	     | FIELD_PREP(CDNS_RTC_CAL_C, bin2bcd(year / 100))
167 	     | FIELD_PREP(CDNS_RTC_CAL_DAY, tm->tm_wday + 1);
168 
169 	/* Update registers, check valid flags */
170 	for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
171 		writel(timr, crtc->regs + CDNS_RTC_TIMR);
172 		writel(calr, crtc->regs + CDNS_RTC_CALR);
173 		stsr = readl(crtc->regs + CDNS_RTC_STSR);
174 
175 		if ((stsr & CDNS_RTC_STSR_VT_VC) == CDNS_RTC_STSR_VT_VC) {
176 			ret = 0;
177 			break;
178 		}
179 	}
180 
181 	cdns_rtc_set_enabled(crtc, true);
182 	return ret;
183 }
184 
185 static int cdns_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
186 {
187 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
188 
189 	if (enabled) {
190 		writel((CDNS_RTC_AEI_SEC | CDNS_RTC_AEI_MIN | CDNS_RTC_AEI_HOUR
191 			| CDNS_RTC_AEI_DATE | CDNS_RTC_AEI_MNTH),
192 		       crtc->regs + CDNS_RTC_AENR);
193 		writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IENR);
194 	} else {
195 		writel(0, crtc->regs + CDNS_RTC_AENR);
196 		writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IDISR);
197 	}
198 
199 	return 0;
200 }
201 
202 static int cdns_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
203 {
204 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
205 	u32 reg;
206 
207 	reg = readl(crtc->regs + CDNS_RTC_TIMAR);
208 	cdns_rtc_reg2time(reg, &alarm->time);
209 
210 	reg = readl(crtc->regs + CDNS_RTC_CALAR);
211 	alarm->time.tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg));
212 	alarm->time.tm_mon  = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1;
213 
214 	return 0;
215 }
216 
217 static int cdns_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
218 {
219 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
220 	int ret = -EIO;
221 	int tries;
222 	u32 timar, calar, stsr;
223 
224 	cdns_rtc_alarm_irq_enable(dev, 0);
225 
226 	timar = cdns_rtc_time2reg(&alarm->time);
227 	calar = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(alarm->time.tm_mday))
228 	      | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(alarm->time.tm_mon + 1));
229 
230 	/* Update registers, check valid alarm flags */
231 	for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) {
232 		writel(timar, crtc->regs + CDNS_RTC_TIMAR);
233 		writel(calar, crtc->regs + CDNS_RTC_CALAR);
234 		stsr = readl(crtc->regs + CDNS_RTC_STSR);
235 
236 		if ((stsr & CDNS_RTC_STSR_VTA_VCA) == CDNS_RTC_STSR_VTA_VCA) {
237 			ret = 0;
238 			break;
239 		}
240 	}
241 
242 	if (!ret)
243 		cdns_rtc_alarm_irq_enable(dev, alarm->enabled);
244 	return ret;
245 }
246 
247 static const struct rtc_class_ops cdns_rtc_ops = {
248 	.read_time	= cdns_rtc_read_time,
249 	.set_time	= cdns_rtc_set_time,
250 	.read_alarm	= cdns_rtc_read_alarm,
251 	.set_alarm	= cdns_rtc_set_alarm,
252 	.alarm_irq_enable = cdns_rtc_alarm_irq_enable,
253 };
254 
255 static int cdns_rtc_probe(struct platform_device *pdev)
256 {
257 	struct cdns_rtc *crtc;
258 	struct resource *res;
259 	int ret;
260 	unsigned long ref_clk_freq;
261 
262 	crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL);
263 	if (!crtc)
264 		return -ENOMEM;
265 
266 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
267 	crtc->regs = devm_ioremap_resource(&pdev->dev, res);
268 	if (IS_ERR(crtc->regs))
269 		return PTR_ERR(crtc->regs);
270 
271 	crtc->irq = platform_get_irq(pdev, 0);
272 	if (crtc->irq < 0)
273 		return -EINVAL;
274 
275 	crtc->pclk = devm_clk_get(&pdev->dev, "pclk");
276 	if (IS_ERR(crtc->pclk)) {
277 		ret = PTR_ERR(crtc->pclk);
278 		dev_err(&pdev->dev,
279 			"Failed to retrieve the peripheral clock, %d\n", ret);
280 		return ret;
281 	}
282 
283 	crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
284 	if (IS_ERR(crtc->ref_clk)) {
285 		ret = PTR_ERR(crtc->ref_clk);
286 		dev_err(&pdev->dev,
287 			"Failed to retrieve the reference clock, %d\n", ret);
288 		return ret;
289 	}
290 
291 	crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
292 	if (IS_ERR(crtc->rtc_dev))
293 		return PTR_ERR(crtc->rtc_dev);
294 
295 	platform_set_drvdata(pdev, crtc);
296 
297 	ret = clk_prepare_enable(crtc->pclk);
298 	if (ret) {
299 		dev_err(&pdev->dev,
300 			"Failed to enable the peripheral clock, %d\n", ret);
301 		return ret;
302 	}
303 
304 	ret = clk_prepare_enable(crtc->ref_clk);
305 	if (ret) {
306 		dev_err(&pdev->dev,
307 			"Failed to enable the reference clock, %d\n", ret);
308 		goto err_disable_pclk;
309 	}
310 
311 	ref_clk_freq = clk_get_rate(crtc->ref_clk);
312 	if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) {
313 		dev_err(&pdev->dev,
314 			"Invalid reference clock frequency %lu Hz.\n",
315 			ref_clk_freq);
316 		ret = -EINVAL;
317 		goto err_disable_ref_clk;
318 	}
319 
320 	ret = devm_request_irq(&pdev->dev, crtc->irq,
321 			       cdns_rtc_irq_handler, 0,
322 			       dev_name(&pdev->dev), &pdev->dev);
323 	if (ret) {
324 		dev_err(&pdev->dev,
325 			"Failed to request interrupt for the device, %d\n",
326 			ret);
327 		goto err_disable_ref_clk;
328 	}
329 
330 	/* The RTC supports 01.01.1900 - 31.12.2999 */
331 	crtc->rtc_dev->range_min = mktime64(1900,  1,  1,  0,  0,  0);
332 	crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59);
333 
334 	crtc->rtc_dev->ops = &cdns_rtc_ops;
335 	device_init_wakeup(&pdev->dev, true);
336 
337 	/* Always use 24-hour mode and keep the RTC values */
338 	writel(0, crtc->regs + CDNS_RTC_HMR);
339 	writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);
340 
341 	ret = rtc_register_device(crtc->rtc_dev);
342 	if (ret)
343 		goto err_disable_wakeup;
344 
345 	return 0;
346 
347 err_disable_wakeup:
348 	device_init_wakeup(&pdev->dev, false);
349 
350 err_disable_ref_clk:
351 	clk_disable_unprepare(crtc->ref_clk);
352 
353 err_disable_pclk:
354 	clk_disable_unprepare(crtc->pclk);
355 
356 	return ret;
357 }
358 
359 static int cdns_rtc_remove(struct platform_device *pdev)
360 {
361 	struct cdns_rtc *crtc = platform_get_drvdata(pdev);
362 
363 	cdns_rtc_alarm_irq_enable(&pdev->dev, 0);
364 	device_init_wakeup(&pdev->dev, 0);
365 
366 	clk_disable_unprepare(crtc->pclk);
367 	clk_disable_unprepare(crtc->ref_clk);
368 
369 	return 0;
370 }
371 
372 #ifdef CONFIG_PM_SLEEP
373 static int cdns_rtc_suspend(struct device *dev)
374 {
375 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
376 
377 	if (device_may_wakeup(dev))
378 		enable_irq_wake(crtc->irq);
379 
380 	return 0;
381 }
382 
383 static int cdns_rtc_resume(struct device *dev)
384 {
385 	struct cdns_rtc *crtc = dev_get_drvdata(dev);
386 
387 	if (device_may_wakeup(dev))
388 		disable_irq_wake(crtc->irq);
389 
390 	return 0;
391 }
392 #endif
393 
394 static SIMPLE_DEV_PM_OPS(cdns_rtc_pm_ops, cdns_rtc_suspend, cdns_rtc_resume);
395 
396 static const struct of_device_id cdns_rtc_of_match[] = {
397 	{ .compatible = "cdns,rtc-r109v3" },
398 	{ },
399 };
400 MODULE_DEVICE_TABLE(of, cdns_rtc_of_match);
401 
402 static struct platform_driver cdns_rtc_driver = {
403 	.driver = {
404 		.name = "cdns-rtc",
405 		.of_match_table = cdns_rtc_of_match,
406 		.pm = &cdns_rtc_pm_ops,
407 	},
408 	.probe = cdns_rtc_probe,
409 	.remove = cdns_rtc_remove,
410 };
411 module_platform_driver(cdns_rtc_driver);
412 
413 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
414 MODULE_DESCRIPTION("Cadence RTC driver");
415 MODULE_LICENSE("GPL v2");
416 MODULE_ALIAS("platform:cdns-rtc");
417