Lines Matching +full:rtc +full:-
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * RTC driver for the Armada 38x Marvell SoCs
7 * Gregory Clement <gregory.clement@free-electrons.com>
15 #include <linux/rtc.h>
85 /* Initialize the RTC-MBUS bridge timing */
86 void (*update_mbus_timing)(struct armada38x_rtc *rtc);
87 u32 (*read_rtc_reg)(struct armada38x_rtc *rtc, u8 rtc_reg);
88 void (*clear_isr)(struct armada38x_rtc *rtc);
89 void (*unmask_interrupt)(struct armada38x_rtc *rtc);
95 * register write to the RTC hard macro so that the required update
97 * According to errata RES-3124064, Write to any RTC register
98 * may fail. As a workaround, before writing to RTC
99 * register, issue a dummy write of 0x0 twice to RTC Status
103 static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset) in rtc_delayed_write() argument
105 writel(0, rtc->regs + RTC_STATUS); in rtc_delayed_write()
106 writel(0, rtc->regs + RTC_STATUS); in rtc_delayed_write()
107 writel(val, rtc->regs + offset); in rtc_delayed_write()
111 /* Update RTC-MBUS bridge timing parameters */
112 static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc) in rtc_update_38x_mbus_timing_params() argument
116 reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); in rtc_update_38x_mbus_timing_params()
121 writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); in rtc_update_38x_mbus_timing_params()
124 static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc) in rtc_update_8k_mbus_timing_params() argument
128 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0); in rtc_update_8k_mbus_timing_params()
133 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0); in rtc_update_8k_mbus_timing_params()
135 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1); in rtc_update_8k_mbus_timing_params()
138 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1); in rtc_update_8k_mbus_timing_params()
141 static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg) in read_rtc_register() argument
143 return readl(rtc->regs + rtc_reg); in read_rtc_register()
146 static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg) in read_rtc_register_38x_wa() argument
151 rtc->val_to_freq[i].value = readl(rtc->regs + rtc_reg); in read_rtc_register_38x_wa()
152 rtc->val_to_freq[i].freq = 0; in read_rtc_register_38x_wa()
157 u32 value = rtc->val_to_freq[i].value; in read_rtc_register_38x_wa()
159 while (rtc->val_to_freq[j].freq) { in read_rtc_register_38x_wa()
160 if (rtc->val_to_freq[j].value == value) { in read_rtc_register_38x_wa()
161 rtc->val_to_freq[j].freq++; in read_rtc_register_38x_wa()
167 if (!rtc->val_to_freq[j].freq) { in read_rtc_register_38x_wa()
168 rtc->val_to_freq[j].value = value; in read_rtc_register_38x_wa()
169 rtc->val_to_freq[j].freq = 1; in read_rtc_register_38x_wa()
172 if (rtc->val_to_freq[j].freq > max) { in read_rtc_register_38x_wa()
174 max = rtc->val_to_freq[j].freq; in read_rtc_register_38x_wa()
185 return rtc->val_to_freq[index_max].value; in read_rtc_register_38x_wa()
188 static void armada38x_clear_isr(struct armada38x_rtc *rtc) in armada38x_clear_isr() argument
190 u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); in armada38x_clear_isr()
192 writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT); in armada38x_clear_isr()
195 static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc) in armada38x_unmask_interrupt() argument
197 u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); in armada38x_unmask_interrupt()
199 writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT); in armada38x_unmask_interrupt()
202 static void armada8k_clear_isr(struct armada38x_rtc *rtc) in armada8k_clear_isr() argument
204 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR); in armada8k_clear_isr()
207 static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc) in armada8k_unmask_interrupt() argument
209 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR); in armada8k_unmask_interrupt()
214 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_read_time() local
217 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_read_time()
218 time = rtc->data->read_rtc_reg(rtc, RTC_TIME); in armada38x_rtc_read_time()
219 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_read_time()
226 static void armada38x_rtc_reset(struct armada38x_rtc *rtc) in armada38x_rtc_reset() argument
230 reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST); in armada38x_rtc_reset()
231 /* If bits [7:0] are non-zero, assume RTC was uninitialized */ in armada38x_rtc_reset()
233 rtc_delayed_write(0, rtc, RTC_CONF_TEST); in armada38x_rtc_reset()
235 rtc_delayed_write(0, rtc, RTC_TIME); in armada38x_rtc_reset()
236 rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc, in armada38x_rtc_reset()
238 rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR); in armada38x_rtc_reset()
240 rtc->initialized = true; in armada38x_rtc_reset()
245 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_set_time() local
250 if (!rtc->initialized) in armada38x_rtc_set_time()
251 armada38x_rtc_reset(rtc); in armada38x_rtc_set_time()
253 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_set_time()
254 rtc_delayed_write(time, rtc, RTC_TIME); in armada38x_rtc_set_time()
255 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_set_time()
262 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_read_alarm() local
264 u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); in armada38x_rtc_read_alarm()
265 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); in armada38x_rtc_read_alarm()
268 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_read_alarm()
270 time = rtc->data->read_rtc_reg(rtc, reg); in armada38x_rtc_read_alarm()
271 val = rtc->data->read_rtc_reg(rtc, reg_irq) & RTC_IRQ_AL_EN; in armada38x_rtc_read_alarm()
273 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_read_alarm()
275 alrm->enabled = val ? 1 : 0; in armada38x_rtc_read_alarm()
276 rtc_time64_to_tm(time, &alrm->time); in armada38x_rtc_read_alarm()
283 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_set_alarm() local
284 u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); in armada38x_rtc_set_alarm()
285 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); in armada38x_rtc_set_alarm()
288 time = rtc_tm_to_time64(&alrm->time); in armada38x_rtc_set_alarm()
290 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_set_alarm()
292 rtc_delayed_write(time, rtc, reg); in armada38x_rtc_set_alarm()
294 if (alrm->enabled) { in armada38x_rtc_set_alarm()
295 rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq); in armada38x_rtc_set_alarm()
296 rtc->data->unmask_interrupt(rtc); in armada38x_rtc_set_alarm()
299 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_set_alarm()
307 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_alarm_irq_enable() local
308 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); in armada38x_rtc_alarm_irq_enable()
311 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_alarm_irq_enable()
314 rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq); in armada38x_rtc_alarm_irq_enable()
316 rtc_delayed_write(0, rtc, reg_irq); in armada38x_rtc_alarm_irq_enable()
318 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_alarm_irq_enable()
325 struct armada38x_rtc *rtc = data; in armada38x_rtc_alarm_irq() local
328 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); in armada38x_rtc_alarm_irq()
330 dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq); in armada38x_rtc_alarm_irq()
332 spin_lock(&rtc->lock); in armada38x_rtc_alarm_irq()
334 rtc->data->clear_isr(rtc); in armada38x_rtc_alarm_irq()
335 val = rtc->data->read_rtc_reg(rtc, reg_irq); in armada38x_rtc_alarm_irq()
337 rtc_delayed_write(0, rtc, reg_irq); in armada38x_rtc_alarm_irq()
339 rtc_delayed_write(1 << rtc->data->alarm, rtc, RTC_STATUS); in armada38x_rtc_alarm_irq()
341 spin_unlock(&rtc->lock); in armada38x_rtc_alarm_irq()
350 rtc_update_irq(rtc->rtc_dev, 1, event); in armada38x_rtc_alarm_irq()
358 * but when considering "Offset" as an 8-bit signed integer, they both
361 * val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768
364 * val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768
368 * "offset" in the RTC interface is defined as:
369 * t = t0 * (1 + offset * 1e-9)
372 * offset = (t_ideal / t_measured - 1) / 1e-9
374 * => t_ideal / t_measured = offset * 1e-9 + 1
378 * offset * 1e-9 + 1 = 1 / (val * resolution + 1)
380 * We want "resolution" to be an integer, so resolution = R * 1e-9, giving
381 * offset = 1e18 / (val * R + 1e9) - 1e9
382 * val = (1e18 / (offset + 1e9) - 1e9) / R
384 * f(x) = 1e18 / (x + 1e9) - 1e9
394 return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L; in armada38x_ppb_convert()
399 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_read_offset() local
403 spin_lock_irqsave(&rtc->lock, flags); in armada38x_rtc_read_offset()
404 ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR); in armada38x_rtc_read_offset()
405 spin_unlock_irqrestore(&rtc->lock, flags); in armada38x_rtc_read_offset()
416 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_set_offset() local
421 * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we in armada38x_rtc_set_offset()
422 * need to clamp the input. This equates to -484270 .. 488558. in armada38x_rtc_set_offset()
426 offset = clamp(offset, -484270L, 488558L); in armada38x_rtc_set_offset()
435 if (off > 127 || off < -128) { in armada38x_rtc_set_offset()
445 rtc_delayed_write(ccr, rtc, RTC_CCR); in armada38x_rtc_set_offset()
478 .compatible = "marvell,armada-380-rtc",
482 .compatible = "marvell,armada-8k-rtc",
491 struct armada38x_rtc *rtc; in armada38x_rtc_probe() local
493 rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc), in armada38x_rtc_probe()
495 if (!rtc) in armada38x_rtc_probe()
496 return -ENOMEM; in armada38x_rtc_probe()
498 rtc->data = of_device_get_match_data(&pdev->dev); in armada38x_rtc_probe()
500 rtc->val_to_freq = devm_kcalloc(&pdev->dev, SAMPLE_NR, in armada38x_rtc_probe()
502 if (!rtc->val_to_freq) in armada38x_rtc_probe()
503 return -ENOMEM; in armada38x_rtc_probe()
505 spin_lock_init(&rtc->lock); in armada38x_rtc_probe()
507 rtc->regs = devm_platform_ioremap_resource_byname(pdev, "rtc"); in armada38x_rtc_probe()
508 if (IS_ERR(rtc->regs)) in armada38x_rtc_probe()
509 return PTR_ERR(rtc->regs); in armada38x_rtc_probe()
510 rtc->regs_soc = devm_platform_ioremap_resource_byname(pdev, "rtc-soc"); in armada38x_rtc_probe()
511 if (IS_ERR(rtc->regs_soc)) in armada38x_rtc_probe()
512 return PTR_ERR(rtc->regs_soc); in armada38x_rtc_probe()
514 rtc->irq = platform_get_irq(pdev, 0); in armada38x_rtc_probe()
515 if (rtc->irq < 0) in armada38x_rtc_probe()
516 return rtc->irq; in armada38x_rtc_probe()
518 rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); in armada38x_rtc_probe()
519 if (IS_ERR(rtc->rtc_dev)) in armada38x_rtc_probe()
520 return PTR_ERR(rtc->rtc_dev); in armada38x_rtc_probe()
522 if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq, in armada38x_rtc_probe()
523 0, pdev->name, rtc) < 0) { in armada38x_rtc_probe()
524 dev_warn(&pdev->dev, "Interrupt not available.\n"); in armada38x_rtc_probe()
525 rtc->irq = -1; in armada38x_rtc_probe()
527 platform_set_drvdata(pdev, rtc); in armada38x_rtc_probe()
529 if (rtc->irq != -1) in armada38x_rtc_probe()
530 device_init_wakeup(&pdev->dev, 1); in armada38x_rtc_probe()
532 clear_bit(RTC_FEATURE_ALARM, rtc->rtc_dev->features); in armada38x_rtc_probe()
534 /* Update RTC-MBUS bridge timing parameters */ in armada38x_rtc_probe()
535 rtc->data->update_mbus_timing(rtc); in armada38x_rtc_probe()
537 rtc->rtc_dev->ops = &armada38x_rtc_ops; in armada38x_rtc_probe()
538 rtc->rtc_dev->range_max = U32_MAX; in armada38x_rtc_probe()
540 return devm_rtc_register_device(rtc->rtc_dev); in armada38x_rtc_probe()
547 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_suspend() local
549 return enable_irq_wake(rtc->irq); in armada38x_rtc_suspend()
558 struct armada38x_rtc *rtc = dev_get_drvdata(dev); in armada38x_rtc_resume() local
560 /* Update RTC-MBUS bridge timing parameters */ in armada38x_rtc_resume()
561 rtc->data->update_mbus_timing(rtc); in armada38x_rtc_resume()
563 return disable_irq_wake(rtc->irq); in armada38x_rtc_resume()
575 .name = "armada38x-rtc",
583 MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
584 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");