File Index
Files and directories
Sign in
FILE

rtc-rzn1.c

File preview with syntax highlighting.

linux-6.19.14/drivers/rtc/rtc-rzn1.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Renesas RZ/N1 Real Time Clock interface for Linux
  4 *
  5 * Copyright:
  6 * - 2014 Renesas Electronics Europe Limited
  7 * - 2022 Schneider Electric
  8 *
  9 * Authors:
 10 * - Michel Pollet <buserror@gmail.com>
 11 * - Miquel Raynal <miquel.raynal@bootlin.com>
 12 */
 13
 14#include <linux/bcd.h>
 15#include <linux/clk.h>
 16#include <linux/init.h>
 17#include <linux/iopoll.h>
 18#include <linux/module.h>
 19#include <linux/mod_devicetable.h>
 20#include <linux/platform_device.h>
 21#include <linux/pm_runtime.h>
 22#include <linux/rtc.h>
 23#include <linux/spinlock.h>
 24
 25#define RZN1_RTC_CTL0 0x00
 26#define   RZN1_RTC_CTL0_SLSB_SCMP BIT(4)
 27#define   RZN1_RTC_CTL0_AMPM BIT(5)
 28#define   RZN1_RTC_CTL0_CEST BIT(6)
 29#define   RZN1_RTC_CTL0_CE BIT(7)
 30
 31#define RZN1_RTC_CTL1 0x04
 32#define   RZN1_RTC_CTL1_1SE BIT(3)
 33#define   RZN1_RTC_CTL1_ALME BIT(4)
 34
 35#define RZN1_RTC_CTL2 0x08
 36#define   RZN1_RTC_CTL2_WAIT BIT(0)
 37#define   RZN1_RTC_CTL2_WST BIT(1)
 38#define   RZN1_RTC_CTL2_WUST BIT(5)
 39#define   RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST)
 40
 41#define RZN1_RTC_TIME 0x30
 42#define RZN1_RTC_TIME_MIN_SHIFT 8
 43#define RZN1_RTC_TIME_HOUR_SHIFT 16
 44#define RZN1_RTC_CAL 0x34
 45#define RZN1_RTC_CAL_DAY_SHIFT 8
 46#define RZN1_RTC_CAL_MON_SHIFT 16
 47#define RZN1_RTC_CAL_YEAR_SHIFT 24
 48
 49#define RZN1_RTC_SUBU 0x38
 50#define   RZN1_RTC_SUBU_DEV BIT(7)
 51#define   RZN1_RTC_SUBU_DECR BIT(6)
 52
 53#define RZN1_RTC_SCMP 0x3c
 54
 55#define RZN1_RTC_ALM 0x40
 56#define RZN1_RTC_ALH 0x44
 57#define RZN1_RTC_ALW 0x48
 58
 59#define RZN1_RTC_SECC 0x4c
 60#define RZN1_RTC_TIMEC 0x68
 61#define RZN1_RTC_CALC 0x6c
 62
 63struct rzn1_rtc {
 64	struct rtc_device *rtcdev;
 65	void __iomem *base;
 66	/*
 67	 * Protects access to RZN1_RTC_CTL1 reg. rtc_lock with threaded_irqs
 68	 * would introduce race conditions when switching interrupts because
 69	 * of potential sleeps
 70	 */
 71	spinlock_t ctl1_access_lock;
 72	struct rtc_time tm_alarm;
 73};
 74
 75static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
 76{
 77	u32 val;
 78
 79	val = readl(rtc->base + RZN1_RTC_TIMEC);
 80	tm->tm_sec = bcd2bin(val);
 81	tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT);
 82	tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT);
 83
 84	val = readl(rtc->base + RZN1_RTC_CALC);
 85	tm->tm_wday = val & 0x0f;
 86	tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT);
 87	tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1;
 88	tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100;
 89}
 90
 91static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
 92{
 93	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
 94	u32 val, secs;
 95
 96	/*
 97	 * The RTC was not started or is stopped and thus does not carry the
 98	 * proper time/date.
 99	 */
100	val = readl(rtc->base + RZN1_RTC_CTL2);
101	if (val & RZN1_RTC_CTL2_STOPPED)
102		return -EINVAL;
103
104	rzn1_rtc_get_time_snapshot(rtc, tm);
105	secs = readl(rtc->base + RZN1_RTC_SECC);
106	if (tm->tm_sec != bcd2bin(secs))
107		rzn1_rtc_get_time_snapshot(rtc, tm);
108
109	return 0;
110}
111
112static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
113{
114	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
115	u32 val;
116	int ret;
117
118	val = readl(rtc->base + RZN1_RTC_CTL2);
119	if (!(val & RZN1_RTC_CTL2_STOPPED)) {
120		/* Hold the counter if it was counting up */
121		writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2);
122
123		/* Wait for the counter to stop: two 32k clock cycles */
124		usleep_range(61, 100);
125		ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val,
126					 val & RZN1_RTC_CTL2_WST, 0, 100);
127		if (ret)
128			return ret;
129	}
130
131	val = bin2bcd(tm->tm_sec);
132	val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT;
133	val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT;
134	writel(val, rtc->base + RZN1_RTC_TIME);
135
136	val = tm->tm_wday;
137	val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT;
138	val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT;
139	val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT;
140	writel(val, rtc->base + RZN1_RTC_CAL);
141
142	writel(0, rtc->base + RZN1_RTC_CTL2);
143
144	return 0;
145}
146
147static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id)
148{
149	struct rzn1_rtc *rtc = dev_id;
150	u32 ctl1, set_irq_bits = 0;
151
152	if (rtc->tm_alarm.tm_sec == 0)
153		rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
154	else
155		/* Switch to 1s interrupts */
156		set_irq_bits = RZN1_RTC_CTL1_1SE;
157
158	guard(spinlock)(&rtc->ctl1_access_lock);
159
160	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
161	ctl1 &= ~RZN1_RTC_CTL1_ALME;
162	ctl1 |= set_irq_bits;
163	writel(ctl1, rtc->base + RZN1_RTC_CTL1);
164
165	return IRQ_HANDLED;
166}
167
168static irqreturn_t rzn1_rtc_1s_irq(int irq, void *dev_id)
169{
170	struct rzn1_rtc *rtc = dev_id;
171	u32 ctl1;
172
173	if (readl(rtc->base + RZN1_RTC_SECC) == bin2bcd(rtc->tm_alarm.tm_sec)) {
174		guard(spinlock)(&rtc->ctl1_access_lock);
175
176		ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
177		ctl1 &= ~RZN1_RTC_CTL1_1SE;
178		writel(ctl1, rtc->base + RZN1_RTC_CTL1);
179
180		rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
181	}
182
183	return IRQ_HANDLED;
184}
185
186static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
187{
188	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
189	struct rtc_time *tm = &rtc->tm_alarm, tm_now;
190	u32 ctl1;
191	int ret;
192
193	guard(spinlock_irqsave)(&rtc->ctl1_access_lock);
194
195	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
196
197	if (enable) {
198		/*
199		 * Use alarm interrupt if alarm time is at least a minute away
200		 * or less than a minute but in the next minute. Otherwise use
201		 * 1 second interrupt to wait for the proper second
202		 */
203		do {
204			ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE);
205
206			ret = rzn1_rtc_read_time(dev, &tm_now);
207			if (ret)
208				return ret;
209
210			if (rtc_tm_sub(tm, &tm_now) > 59 || tm->tm_min != tm_now.tm_min)
211				ctl1 |= RZN1_RTC_CTL1_ALME;
212			else
213				ctl1 |= RZN1_RTC_CTL1_1SE;
214
215			writel(ctl1, rtc->base + RZN1_RTC_CTL1);
216		} while (readl(rtc->base + RZN1_RTC_SECC) != bin2bcd(tm_now.tm_sec));
217	} else {
218		ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE);
219		writel(ctl1, rtc->base + RZN1_RTC_CTL1);
220	}
221
222	return 0;
223}
224
225static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
226{
227	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
228	struct rtc_time *tm = &alrm->time;
229	unsigned int min, hour, wday, delta_days;
230	time64_t alarm;
231	u32 ctl1;
232	int ret;
233
234	ret = rzn1_rtc_read_time(dev, tm);
235	if (ret)
236		return ret;
237
238	min = readl(rtc->base + RZN1_RTC_ALM);
239	hour = readl(rtc->base + RZN1_RTC_ALH);
240	wday = readl(rtc->base + RZN1_RTC_ALW);
241
242	tm->tm_sec = 0;
243	tm->tm_min = bcd2bin(min);
244	tm->tm_hour = bcd2bin(hour);
245	delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
246	tm->tm_wday = fls(wday) - 1;
247
248	if (delta_days) {
249		alarm = rtc_tm_to_time64(tm) + (delta_days * 86400);
250		rtc_time64_to_tm(alarm, tm);
251	}
252
253	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
254	alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
255
256	return 0;
257}
258
259static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
260{
261	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
262	struct rtc_time *tm = &alrm->time, tm_now;
263	unsigned long alarm, farest;
264	unsigned int days_ahead, wday;
265	int ret;
266
267	ret = rzn1_rtc_read_time(dev, &tm_now);
268	if (ret)
269		return ret;
270
271	/* We cannot set alarms more than one week ahead */
272	farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max;
273	alarm = rtc_tm_to_time64(tm);
274	if (time_after(alarm, farest))
275		return -ERANGE;
276
277	/* Convert alarm day into week day */
278	days_ahead = tm->tm_mday - tm_now.tm_mday;
279	wday = (tm_now.tm_wday + days_ahead) % 7;
280
281	writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
282	writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
283	writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
284
285	rtc->tm_alarm = alrm->time;
286
287	rzn1_rtc_alarm_irq_enable(dev, alrm->enabled);
288
289	return 0;
290}
291
292static int rzn1_rtc_read_offset(struct device *dev, long *offset)
293{
294	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
295	unsigned int ppb_per_step;
296	bool subtract;
297	u32 val;
298
299	val = readl(rtc->base + RZN1_RTC_SUBU);
300	ppb_per_step = val & RZN1_RTC_SUBU_DEV ? 1017 : 3051;
301	subtract = val & RZN1_RTC_SUBU_DECR;
302	val &= 0x3F;
303
304	if (!val)
305		*offset = 0;
306	else if (subtract)
307		*offset = -(((~val) & 0x3F) + 1) * ppb_per_step;
308	else
309		*offset = (val - 1) * ppb_per_step;
310
311	return 0;
312}
313
314static int rzn1_rtc_set_offset(struct device *dev, long offset)
315{
316	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
317	int stepsh, stepsl, steps;
318	u32 subu = 0, ctl2;
319	int ret;
320
321	/*
322	 * Check which resolution mode (every 20 or 60s) can be used.
323	 * Between 2 and 124 clock pulses can be added or substracted.
324	 *
325	 * In 20s mode, the minimum resolution is 2 / (32768 * 20) which is
326	 * close to 3051 ppb. In 60s mode, the resolution is closer to 1017.
327	 */
328	stepsh = DIV_ROUND_CLOSEST(offset, 1017);
329	stepsl = DIV_ROUND_CLOSEST(offset, 3051);
330
331	if (stepsh >= -0x3E && stepsh <= 0x3E) {
332		/* 1017 ppb per step */
333		steps = stepsh;
334		subu |= RZN1_RTC_SUBU_DEV;
335	} else if (stepsl >= -0x3E && stepsl <= 0x3E) {
336		/* 3051 ppb per step */
337		steps = stepsl;
338	} else {
339		return -ERANGE;
340	}
341
342	if (!steps)
343		return 0;
344
345	if (steps > 0) {
346		subu |= steps + 1;
347	} else {
348		subu |= RZN1_RTC_SUBU_DECR;
349		subu |= (~(-steps - 1)) & 0x3F;
350	}
351
352	ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, ctl2,
353				 !(ctl2 & RZN1_RTC_CTL2_WUST), 100, 2000000);
354	if (ret)
355		return ret;
356
357	writel(subu, rtc->base + RZN1_RTC_SUBU);
358
359	return 0;
360}
361
362static const struct rtc_class_ops rzn1_rtc_ops_subu = {
363	.read_time = rzn1_rtc_read_time,
364	.set_time = rzn1_rtc_set_time,
365	.read_alarm = rzn1_rtc_read_alarm,
366	.set_alarm = rzn1_rtc_set_alarm,
367	.alarm_irq_enable = rzn1_rtc_alarm_irq_enable,
368	.read_offset = rzn1_rtc_read_offset,
369	.set_offset = rzn1_rtc_set_offset,
370};
371
372static const struct rtc_class_ops rzn1_rtc_ops_scmp = {
373	.read_time = rzn1_rtc_read_time,
374	.set_time = rzn1_rtc_set_time,
375	.read_alarm = rzn1_rtc_read_alarm,
376	.set_alarm = rzn1_rtc_set_alarm,
377	.alarm_irq_enable = rzn1_rtc_alarm_irq_enable,
378};
379
380static int rzn1_rtc_probe(struct platform_device *pdev)
381{
382	struct rzn1_rtc *rtc;
383	u32 val, scmp_val = 0;
384	struct clk *xtal;
385	unsigned long rate;
386	int irq, ret;
387
388	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
389	if (!rtc)
390		return -ENOMEM;
391
392	platform_set_drvdata(pdev, rtc);
393
394	rtc->base = devm_platform_ioremap_resource(pdev, 0);
395	if (IS_ERR(rtc->base))
396		return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n");
397
398	irq = platform_get_irq_byname(pdev, "alarm");
399	if (irq < 0)
400		return irq;
401
402	rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
403	if (IS_ERR(rtc->rtcdev))
404		return PTR_ERR(rtc->rtcdev);
405
406	rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
407	rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
408	rtc->rtcdev->alarm_offset_max = 7 * 86400;
409
410	ret = devm_pm_runtime_enable(&pdev->dev);
411	if (ret < 0)
412		return ret;
413	ret = pm_runtime_resume_and_get(&pdev->dev);
414	if (ret < 0)
415		return ret;
416
417	/* Only switch to scmp if we have an xtal clock with a valid rate and != 32768 */
418	xtal = devm_clk_get_optional(&pdev->dev, "xtal");
419	if (IS_ERR(xtal)) {
420		ret = PTR_ERR(xtal);
421		goto dis_runtime_pm;
422	} else if (xtal) {
423		rate = clk_get_rate(xtal);
424
425		if (rate < 32000 || rate > BIT(22)) {
426			ret = -EOPNOTSUPP;
427			goto dis_runtime_pm;
428		}
429
430		if (rate != 32768)
431			scmp_val = RZN1_RTC_CTL0_SLSB_SCMP;
432	}
433
434	/* Disable controller during SUBU/SCMP setup */
435	val = readl(rtc->base + RZN1_RTC_CTL0) & ~RZN1_RTC_CTL0_CE;
436	writel(val, rtc->base + RZN1_RTC_CTL0);
437	/* Wait 2-4 32k clock cycles for the disabled controller */
438	ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL0, val,
439				 !(val & RZN1_RTC_CTL0_CEST), 62, 123);
440	if (ret)
441		goto dis_runtime_pm;
442
443	/* Set desired modes leaving the controller disabled */
444	writel(RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0);
445
446	if (scmp_val) {
447		writel(rate - 1, rtc->base + RZN1_RTC_SCMP);
448		rtc->rtcdev->ops = &rzn1_rtc_ops_scmp;
449	} else {
450		rtc->rtcdev->ops = &rzn1_rtc_ops_subu;
451	}
452
453	/* Enable controller finally */
454	writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0);
455
456	/* Disable all interrupts */
457	writel(0, rtc->base + RZN1_RTC_CTL1);
458
459	spin_lock_init(&rtc->ctl1_access_lock);
460
461	ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc);
462	if (ret) {
463		dev_err(&pdev->dev, "RTC alarm interrupt not available\n");
464		goto dis_runtime_pm;
465	}
466
467	irq = platform_get_irq_byname_optional(pdev, "pps");
468	if (irq >= 0)
469		ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc);
470
471	if (irq < 0 || ret) {
472		set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);
473		clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features);
474		dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n");
475	}
476
477	ret = devm_rtc_register_device(rtc->rtcdev);
478	if (ret)
479		goto dis_runtime_pm;
480
481	return 0;
482
483dis_runtime_pm:
484	pm_runtime_put(&pdev->dev);
485
486	return ret;
487}
488
489static void rzn1_rtc_remove(struct platform_device *pdev)
490{
491	struct rzn1_rtc *rtc = platform_get_drvdata(pdev);
492
493	/* Disable all interrupts */
494	writel(0, rtc->base + RZN1_RTC_CTL1);
495
496	pm_runtime_put(&pdev->dev);
497}
498
499static const struct of_device_id rzn1_rtc_of_match[] = {
500	{ .compatible	= "renesas,rzn1-rtc" },
501	{},
502};
503MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
504
505static struct platform_driver rzn1_rtc_driver = {
506	.probe = rzn1_rtc_probe,
507	.remove = rzn1_rtc_remove,
508	.driver = {
509		.name	= "rzn1-rtc",
510		.of_match_table = rzn1_rtc_of_match,
511	},
512};
513module_platform_driver(rzn1_rtc_driver);
514
515MODULE_AUTHOR("Michel Pollet <buserror@gmail.com>");
516MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com");
517MODULE_DESCRIPTION("RZ/N1 RTC driver");
518MODULE_LICENSE("GPL");
~/ Read-only file preview.