Lines Matching +full:rtc +full:-
1 // SPDX-License-Identifier: GPL-2.0+
6 * - 2014 Renesas Electronics Europe Limited
7 * - 2022 Schneider Electric
10 * - Michel Pollet <buserror@gmail.com>
11 * - Miquel Raynal <miquel.raynal@bootlin.com>
22 #include <linux/rtc.h>
75 static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm) in rzn1_rtc_get_time_snapshot() argument
79 val = readl(rtc->base + RZN1_RTC_TIMEC); in rzn1_rtc_get_time_snapshot()
80 tm->tm_sec = bcd2bin(val); in rzn1_rtc_get_time_snapshot()
81 tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT); in rzn1_rtc_get_time_snapshot()
82 tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT); in rzn1_rtc_get_time_snapshot()
84 val = readl(rtc->base + RZN1_RTC_CALC); in rzn1_rtc_get_time_snapshot()
85 tm->tm_wday = val & 0x0f; in rzn1_rtc_get_time_snapshot()
86 tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT); in rzn1_rtc_get_time_snapshot()
87 tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1; in rzn1_rtc_get_time_snapshot()
88 tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100; in rzn1_rtc_get_time_snapshot()
93 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_read_time() local
97 * The RTC was not started or is stopped and thus does not carry the in rzn1_rtc_read_time()
100 val = readl(rtc->base + RZN1_RTC_CTL2); in rzn1_rtc_read_time()
102 return -EINVAL; in rzn1_rtc_read_time()
104 rzn1_rtc_get_time_snapshot(rtc, tm); in rzn1_rtc_read_time()
105 secs = readl(rtc->base + RZN1_RTC_SECC); in rzn1_rtc_read_time()
106 if (tm->tm_sec != bcd2bin(secs)) in rzn1_rtc_read_time()
107 rzn1_rtc_get_time_snapshot(rtc, tm); in rzn1_rtc_read_time()
114 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_set_time() local
118 val = readl(rtc->base + RZN1_RTC_CTL2); in rzn1_rtc_set_time()
121 writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2); in rzn1_rtc_set_time()
125 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val, in rzn1_rtc_set_time()
131 val = bin2bcd(tm->tm_sec); in rzn1_rtc_set_time()
132 val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT; in rzn1_rtc_set_time()
133 val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT; in rzn1_rtc_set_time()
134 writel(val, rtc->base + RZN1_RTC_TIME); in rzn1_rtc_set_time()
136 val = tm->tm_wday; in rzn1_rtc_set_time()
137 val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT; in rzn1_rtc_set_time()
138 val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT; in rzn1_rtc_set_time()
139 val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT; in rzn1_rtc_set_time()
140 writel(val, rtc->base + RZN1_RTC_CAL); in rzn1_rtc_set_time()
142 writel(0, rtc->base + RZN1_RTC_CTL2); in rzn1_rtc_set_time()
149 struct rzn1_rtc *rtc = dev_id; in rzn1_rtc_alarm_irq() local
152 if (rtc->tm_alarm.tm_sec == 0) in rzn1_rtc_alarm_irq()
153 rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); in rzn1_rtc_alarm_irq()
158 guard(spinlock)(&rtc->ctl1_access_lock); in rzn1_rtc_alarm_irq()
160 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_alarm_irq()
163 writel(ctl1, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_alarm_irq()
170 struct rzn1_rtc *rtc = dev_id; in rzn1_rtc_1s_irq() local
173 if (readl(rtc->base + RZN1_RTC_SECC) == bin2bcd(rtc->tm_alarm.tm_sec)) { in rzn1_rtc_1s_irq()
174 guard(spinlock)(&rtc->ctl1_access_lock); in rzn1_rtc_1s_irq()
176 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_1s_irq()
178 writel(ctl1, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_1s_irq()
180 rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); in rzn1_rtc_1s_irq()
188 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_alarm_irq_enable() local
189 struct rtc_time *tm = &rtc->tm_alarm, tm_now; in rzn1_rtc_alarm_irq_enable()
193 guard(spinlock_irqsave)(&rtc->ctl1_access_lock); in rzn1_rtc_alarm_irq_enable()
195 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_alarm_irq_enable()
210 if (rtc_tm_sub(tm, &tm_now) > 59 || tm->tm_min != tm_now.tm_min) in rzn1_rtc_alarm_irq_enable()
215 writel(ctl1, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_alarm_irq_enable()
216 } while (readl(rtc->base + RZN1_RTC_SECC) != bin2bcd(tm_now.tm_sec)); in rzn1_rtc_alarm_irq_enable()
219 writel(ctl1, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_alarm_irq_enable()
227 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_read_alarm() local
228 struct rtc_time *tm = &alrm->time; in rzn1_rtc_read_alarm()
238 min = readl(rtc->base + RZN1_RTC_ALM); in rzn1_rtc_read_alarm()
239 hour = readl(rtc->base + RZN1_RTC_ALH); in rzn1_rtc_read_alarm()
240 wday = readl(rtc->base + RZN1_RTC_ALW); in rzn1_rtc_read_alarm()
242 tm->tm_sec = 0; in rzn1_rtc_read_alarm()
243 tm->tm_min = bcd2bin(min); in rzn1_rtc_read_alarm()
244 tm->tm_hour = bcd2bin(hour); in rzn1_rtc_read_alarm()
245 delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7; in rzn1_rtc_read_alarm()
246 tm->tm_wday = fls(wday) - 1; in rzn1_rtc_read_alarm()
253 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_read_alarm()
254 alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE)); in rzn1_rtc_read_alarm()
261 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_set_alarm() local
262 struct rtc_time *tm = &alrm->time, tm_now; in rzn1_rtc_set_alarm()
272 farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max; in rzn1_rtc_set_alarm()
275 return -ERANGE; in rzn1_rtc_set_alarm()
278 days_ahead = tm->tm_mday - tm_now.tm_mday; in rzn1_rtc_set_alarm()
281 writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM); in rzn1_rtc_set_alarm()
282 writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH); in rzn1_rtc_set_alarm()
283 writel(BIT(wday), rtc->base + RZN1_RTC_ALW); in rzn1_rtc_set_alarm()
285 rtc->tm_alarm = alrm->time; in rzn1_rtc_set_alarm()
287 rzn1_rtc_alarm_irq_enable(dev, alrm->enabled); in rzn1_rtc_set_alarm()
294 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_read_offset() local
299 val = readl(rtc->base + RZN1_RTC_SUBU); in rzn1_rtc_read_offset()
307 *offset = -(((~val) & 0x3F) + 1) * ppb_per_step; in rzn1_rtc_read_offset()
309 *offset = (val - 1) * ppb_per_step; in rzn1_rtc_read_offset()
316 struct rzn1_rtc *rtc = dev_get_drvdata(dev); in rzn1_rtc_set_offset() local
331 if (stepsh >= -0x3E && stepsh <= 0x3E) { in rzn1_rtc_set_offset()
335 } else if (stepsl >= -0x3E && stepsl <= 0x3E) { in rzn1_rtc_set_offset()
339 return -ERANGE; in rzn1_rtc_set_offset()
349 subu |= (~(-steps - 1)) & 0x3F; in rzn1_rtc_set_offset()
352 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, ctl2, in rzn1_rtc_set_offset()
357 writel(subu, rtc->base + RZN1_RTC_SUBU); in rzn1_rtc_set_offset()
382 struct rzn1_rtc *rtc; in rzn1_rtc_probe() local
388 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); in rzn1_rtc_probe()
389 if (!rtc) in rzn1_rtc_probe()
390 return -ENOMEM; in rzn1_rtc_probe()
392 platform_set_drvdata(pdev, rtc); in rzn1_rtc_probe()
394 rtc->base = devm_platform_ioremap_resource(pdev, 0); in rzn1_rtc_probe()
395 if (IS_ERR(rtc->base)) in rzn1_rtc_probe()
396 return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n"); in rzn1_rtc_probe()
402 rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev); in rzn1_rtc_probe()
403 if (IS_ERR(rtc->rtcdev)) in rzn1_rtc_probe()
404 return PTR_ERR(rtc->rtcdev); in rzn1_rtc_probe()
406 rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; in rzn1_rtc_probe()
407 rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099; in rzn1_rtc_probe()
408 rtc->rtcdev->alarm_offset_max = 7 * 86400; in rzn1_rtc_probe()
410 ret = devm_pm_runtime_enable(&pdev->dev); in rzn1_rtc_probe()
413 ret = pm_runtime_resume_and_get(&pdev->dev); in rzn1_rtc_probe()
418 xtal = devm_clk_get_optional(&pdev->dev, "xtal"); in rzn1_rtc_probe()
426 ret = -EOPNOTSUPP; in rzn1_rtc_probe()
435 val = readl(rtc->base + RZN1_RTC_CTL0) & ~RZN1_RTC_CTL0_CE; in rzn1_rtc_probe()
436 writel(val, rtc->base + RZN1_RTC_CTL0); in rzn1_rtc_probe()
437 /* Wait 2-4 32k clock cycles for the disabled controller */ in rzn1_rtc_probe()
438 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL0, val, in rzn1_rtc_probe()
444 writel(RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0); in rzn1_rtc_probe()
447 writel(rate - 1, rtc->base + RZN1_RTC_SCMP); in rzn1_rtc_probe()
448 rtc->rtcdev->ops = &rzn1_rtc_ops_scmp; in rzn1_rtc_probe()
450 rtc->rtcdev->ops = &rzn1_rtc_ops_subu; in rzn1_rtc_probe()
454 writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0); in rzn1_rtc_probe()
457 writel(0, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_probe()
459 spin_lock_init(&rtc->ctl1_access_lock); in rzn1_rtc_probe()
461 ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc); in rzn1_rtc_probe()
463 dev_err(&pdev->dev, "RTC alarm interrupt not available\n"); in rzn1_rtc_probe()
469 ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc); in rzn1_rtc_probe()
472 set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); in rzn1_rtc_probe()
473 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); in rzn1_rtc_probe()
474 dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n"); in rzn1_rtc_probe()
477 ret = devm_rtc_register_device(rtc->rtcdev); in rzn1_rtc_probe()
484 pm_runtime_put(&pdev->dev); in rzn1_rtc_probe()
491 struct rzn1_rtc *rtc = platform_get_drvdata(pdev); in rzn1_rtc_remove() local
494 writel(0, rtc->base + RZN1_RTC_CTL1); in rzn1_rtc_remove()
496 pm_runtime_put(&pdev->dev); in rzn1_rtc_remove()
500 { .compatible = "renesas,rzn1-rtc" },
509 .name = "rzn1-rtc",
517 MODULE_DESCRIPTION("RZ/N1 RTC driver");