Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  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
 79struct 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
 87static 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
 94static 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
 99static 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
112static 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
119static 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
126static 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
151static 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
185static 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
202static 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
217static 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
247static 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
255static int cdns_rtc_probe(struct platform_device *pdev)
256{
257	struct cdns_rtc *crtc;
258	int ret;
259	unsigned long ref_clk_freq;
260
261	crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL);
262	if (!crtc)
263		return -ENOMEM;
264
265	crtc->regs = devm_platform_ioremap_resource(pdev, 0);
266	if (IS_ERR(crtc->regs))
267		return PTR_ERR(crtc->regs);
268
269	crtc->irq = platform_get_irq(pdev, 0);
270	if (crtc->irq < 0)
271		return -EINVAL;
272
273	crtc->pclk = devm_clk_get(&pdev->dev, "pclk");
274	if (IS_ERR(crtc->pclk)) {
275		ret = PTR_ERR(crtc->pclk);
276		dev_err(&pdev->dev,
277			"Failed to retrieve the peripheral clock, %d\n", ret);
278		return ret;
279	}
280
281	crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
282	if (IS_ERR(crtc->ref_clk)) {
283		ret = PTR_ERR(crtc->ref_clk);
284		dev_err(&pdev->dev,
285			"Failed to retrieve the reference clock, %d\n", ret);
286		return ret;
287	}
288
289	crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
290	if (IS_ERR(crtc->rtc_dev))
291		return PTR_ERR(crtc->rtc_dev);
292
293	platform_set_drvdata(pdev, crtc);
294
295	ret = clk_prepare_enable(crtc->pclk);
296	if (ret) {
297		dev_err(&pdev->dev,
298			"Failed to enable the peripheral clock, %d\n", ret);
299		return ret;
300	}
301
302	ret = clk_prepare_enable(crtc->ref_clk);
303	if (ret) {
304		dev_err(&pdev->dev,
305			"Failed to enable the reference clock, %d\n", ret);
306		goto err_disable_pclk;
307	}
308
309	ref_clk_freq = clk_get_rate(crtc->ref_clk);
310	if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) {
311		dev_err(&pdev->dev,
312			"Invalid reference clock frequency %lu Hz.\n",
313			ref_clk_freq);
314		ret = -EINVAL;
315		goto err_disable_ref_clk;
316	}
317
318	ret = devm_request_irq(&pdev->dev, crtc->irq,
319			       cdns_rtc_irq_handler, 0,
320			       dev_name(&pdev->dev), &pdev->dev);
321	if (ret) {
322		dev_err(&pdev->dev,
323			"Failed to request interrupt for the device, %d\n",
324			ret);
325		goto err_disable_ref_clk;
326	}
327
328	/* The RTC supports 01.01.1900 - 31.12.2999 */
329	crtc->rtc_dev->range_min = mktime64(1900,  1,  1,  0,  0,  0);
330	crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59);
331
332	crtc->rtc_dev->ops = &cdns_rtc_ops;
333	device_init_wakeup(&pdev->dev, true);
334
335	/* Always use 24-hour mode and keep the RTC values */
336	writel(0, crtc->regs + CDNS_RTC_HMR);
337	writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);
338
339	ret = devm_rtc_register_device(crtc->rtc_dev);
340	if (ret)
341		goto err_disable_wakeup;
342
343	return 0;
344
345err_disable_wakeup:
346	device_init_wakeup(&pdev->dev, false);
347
348err_disable_ref_clk:
349	clk_disable_unprepare(crtc->ref_clk);
350
351err_disable_pclk:
352	clk_disable_unprepare(crtc->pclk);
353
354	return ret;
355}
356
357static void cdns_rtc_remove(struct platform_device *pdev)
358{
359	struct cdns_rtc *crtc = platform_get_drvdata(pdev);
360
361	cdns_rtc_alarm_irq_enable(&pdev->dev, 0);
362	device_init_wakeup(&pdev->dev, 0);
363
364	clk_disable_unprepare(crtc->pclk);
365	clk_disable_unprepare(crtc->ref_clk);
366}
367
368#ifdef CONFIG_PM_SLEEP
369static int cdns_rtc_suspend(struct device *dev)
370{
371	struct cdns_rtc *crtc = dev_get_drvdata(dev);
372
373	if (device_may_wakeup(dev))
374		enable_irq_wake(crtc->irq);
375
376	return 0;
377}
378
379static int cdns_rtc_resume(struct device *dev)
380{
381	struct cdns_rtc *crtc = dev_get_drvdata(dev);
382
383	if (device_may_wakeup(dev))
384		disable_irq_wake(crtc->irq);
385
386	return 0;
387}
388#endif
389
390static SIMPLE_DEV_PM_OPS(cdns_rtc_pm_ops, cdns_rtc_suspend, cdns_rtc_resume);
391
392static const struct of_device_id cdns_rtc_of_match[] = {
393	{ .compatible = "cdns,rtc-r109v3" },
394	{ },
395};
396MODULE_DEVICE_TABLE(of, cdns_rtc_of_match);
397
398static struct platform_driver cdns_rtc_driver = {
399	.driver = {
400		.name = "cdns-rtc",
401		.of_match_table = cdns_rtc_of_match,
402		.pm = &cdns_rtc_pm_ops,
403	},
404	.probe = cdns_rtc_probe,
405	.remove = cdns_rtc_remove,
406};
407module_platform_driver(cdns_rtc_driver);
408
409MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
410MODULE_DESCRIPTION("Cadence RTC driver");
411MODULE_LICENSE("GPL v2");
412MODULE_ALIAS("platform:cdns-rtc");