• Home
  • Raw
  • Download

Lines Matching +full:chip +full:- +full:relative

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org>
7 * based on rtc-sunxi.c
15 #include <linux/clk-provider.h>
103 * The year parameter passed to the driver is usually an offset relative to
105 * relative to the minimum year allowed by the hardware.
107 * The year range is 1970 - 2033. This range is selected to match Allwinner's
111 #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900)
116 * - number of GPIO pins that can be configured to hold a certain level
117 * - crypto-key related registers (H5, H6)
118 * - boot process related (super standby, secondary processor entry address)
120 * - SYS power domain controls (R40)
121 * - DCXO controls (H6)
122 * - RC oscillator calibration (H6)
158 val = readl(rtc->base + SUN6I_LOSC_CTRL); in sun6i_rtc_osc_recalc_rate()
162 if (rtc->data->fixed_prescaler) in sun6i_rtc_osc_recalc_rate()
163 parent_rate /= rtc->data->fixed_prescaler; in sun6i_rtc_osc_recalc_rate()
165 if (rtc->data->has_prescaler) { in sun6i_rtc_osc_recalc_rate()
166 val = readl(rtc->base + SUN6I_LOSC_CLK_PRESCAL); in sun6i_rtc_osc_recalc_rate()
177 return readl(rtc->base + SUN6I_LOSC_CTRL) & SUN6I_LOSC_CTRL_EXT_OSC; in sun6i_rtc_osc_get_parent()
187 return -EINVAL; in sun6i_rtc_osc_set_parent()
189 spin_lock_irqsave(&rtc->lock, flags); in sun6i_rtc_osc_set_parent()
190 val = readl(rtc->base + SUN6I_LOSC_CTRL); in sun6i_rtc_osc_set_parent()
194 if (rtc->data->has_losc_en) { in sun6i_rtc_osc_set_parent()
198 writel(val, rtc->base + SUN6I_LOSC_CTRL); in sun6i_rtc_osc_set_parent()
199 spin_unlock_irqrestore(&rtc->lock, flags); in sun6i_rtc_osc_set_parent()
220 const char *iosc_name = "rtc-int-osc"; in sun6i_rtc_clk_init()
221 const char *clkout_name = "osc32k-out"; in sun6i_rtc_clk_init()
229 rtc->data = data; in sun6i_rtc_clk_init()
236 spin_lock_init(&rtc->lock); in sun6i_rtc_clk_init()
238 rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node)); in sun6i_rtc_clk_init()
239 if (IS_ERR(rtc->base)) { in sun6i_rtc_clk_init()
245 if (rtc->data->has_auto_swt) { in sun6i_rtc_clk_init()
246 /* Bypass auto-switch to int osc, on ext losc failure */ in sun6i_rtc_clk_init()
248 writel(reg, rtc->base + SUN6I_LOSC_CTRL); in sun6i_rtc_clk_init()
254 if (rtc->data->has_losc_en) in sun6i_rtc_clk_init()
257 writel(reg, rtc->base + SUN6I_LOSC_CTRL); in sun6i_rtc_clk_init()
262 of_property_read_string_index(node, "clock-output-names", 2, in sun6i_rtc_clk_init()
265 rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, in sun6i_rtc_clk_init()
268 rtc->data->rc_osc_rate, in sun6i_rtc_clk_init()
270 if (IS_ERR(rtc->int_osc)) { in sun6i_rtc_clk_init()
275 parents[0] = clk_hw_get_name(rtc->int_osc); in sun6i_rtc_clk_init()
279 rtc->hw.init = &init; in sun6i_rtc_clk_init()
284 of_property_read_string_index(node, "clock-output-names", 0, in sun6i_rtc_clk_init()
287 rtc->losc = clk_register(NULL, &rtc->hw); in sun6i_rtc_clk_init()
288 if (IS_ERR(rtc->losc)) { in sun6i_rtc_clk_init()
293 of_property_read_string_index(node, "clock-output-names", 1, in sun6i_rtc_clk_init()
295 rtc->ext_losc = clk_register_gate(NULL, clkout_name, init.name, in sun6i_rtc_clk_init()
296 0, rtc->base + SUN6I_LOSC_OUT_GATING, in sun6i_rtc_clk_init()
298 &rtc->lock); in sun6i_rtc_clk_init()
299 if (IS_ERR(rtc->ext_losc)) { in sun6i_rtc_clk_init()
304 clk_data->num = 3; in sun6i_rtc_clk_init()
305 clk_data->hws[0] = &rtc->hw; in sun6i_rtc_clk_init()
306 clk_data->hws[1] = __clk_get_hw(rtc->ext_losc); in sun6i_rtc_clk_init()
307 clk_data->hws[2] = rtc->int_osc; in sun6i_rtc_clk_init()
312 clk_hw_unregister_fixed_rate(rtc->int_osc); in sun6i_rtc_clk_init()
326 CLK_OF_DECLARE_DRIVER(sun6i_a31_rtc_clk, "allwinner,sun6i-a31-rtc",
339 CLK_OF_DECLARE_DRIVER(sun8i_a23_rtc_clk, "allwinner,sun8i-a23-rtc",
353 CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc",
356 CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc",
372 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
376 * The R40 user manual is self-conflicting on whether the prescaler is
388 CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc",
400 CLK_OF_DECLARE_DRIVER(sun8i_v3_rtc_clk, "allwinner,sun8i-v3-rtc",
405 struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; in sun6i_rtc_alarmirq() local
409 spin_lock(&chip->lock); in sun6i_rtc_alarmirq()
410 val = readl(chip->base + SUN6I_ALRM_IRQ_STA); in sun6i_rtc_alarmirq()
414 writel(val, chip->base + SUN6I_ALRM_IRQ_STA); in sun6i_rtc_alarmirq()
416 rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); in sun6i_rtc_alarmirq()
420 spin_unlock(&chip->lock); in sun6i_rtc_alarmirq()
425 static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) in sun6i_rtc_setaie() argument
438 chip->base + SUN6I_ALRM_IRQ_STA); in sun6i_rtc_setaie()
441 spin_lock_irqsave(&chip->lock, flags); in sun6i_rtc_setaie()
442 writel(alrm_val, chip->base + SUN6I_ALRM_EN); in sun6i_rtc_setaie()
443 writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); in sun6i_rtc_setaie()
444 writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); in sun6i_rtc_setaie()
445 spin_unlock_irqrestore(&chip->lock, flags); in sun6i_rtc_setaie()
450 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_gettime() local
457 date = readl(chip->base + SUN6I_RTC_YMD); in sun6i_rtc_gettime()
458 time = readl(chip->base + SUN6I_RTC_HMS); in sun6i_rtc_gettime()
459 } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || in sun6i_rtc_gettime()
460 (time != readl(chip->base + SUN6I_RTC_HMS))); in sun6i_rtc_gettime()
462 rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); in sun6i_rtc_gettime()
463 rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); in sun6i_rtc_gettime()
464 rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); in sun6i_rtc_gettime()
466 rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); in sun6i_rtc_gettime()
467 rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); in sun6i_rtc_gettime()
468 rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); in sun6i_rtc_gettime()
470 rtc_tm->tm_mon -= 1; in sun6i_rtc_gettime()
473 * switch from (data_year->min)-relative offset to in sun6i_rtc_gettime()
474 * a (1900)-relative one in sun6i_rtc_gettime()
476 rtc_tm->tm_year += SUN6I_YEAR_OFF; in sun6i_rtc_gettime()
483 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_getalarm() local
488 spin_lock_irqsave(&chip->lock, flags); in sun6i_rtc_getalarm()
489 alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); in sun6i_rtc_getalarm()
490 alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); in sun6i_rtc_getalarm()
491 spin_unlock_irqrestore(&chip->lock, flags); in sun6i_rtc_getalarm()
493 wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); in sun6i_rtc_getalarm()
494 wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); in sun6i_rtc_getalarm()
495 rtc_time64_to_tm(chip->alarm, &wkalrm->time); in sun6i_rtc_getalarm()
502 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_setalarm() local
503 struct rtc_time *alrm_tm = &wkalrm->time; in sun6i_rtc_setalarm()
511 return -EINVAL; in sun6i_rtc_setalarm()
518 return -EINVAL; in sun6i_rtc_setalarm()
521 if ((time_set - time_now) > U32_MAX) { in sun6i_rtc_setalarm()
523 return -EINVAL; in sun6i_rtc_setalarm()
526 sun6i_rtc_setaie(0, chip); in sun6i_rtc_setalarm()
527 writel(0, chip->base + SUN6I_ALRM_COUNTER); in sun6i_rtc_setalarm()
530 writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER); in sun6i_rtc_setalarm()
531 chip->alarm = time_set; in sun6i_rtc_setalarm()
533 sun6i_rtc_setaie(wkalrm->enabled, chip); in sun6i_rtc_setalarm()
538 static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset, in sun6i_rtc_wait() argument
545 reg = readl(chip->base + offset); in sun6i_rtc_wait()
553 return -ETIMEDOUT; in sun6i_rtc_wait()
558 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_settime() local
562 rtc_tm->tm_year -= SUN6I_YEAR_OFF; in sun6i_rtc_settime()
563 rtc_tm->tm_mon += 1; in sun6i_rtc_settime()
565 date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | in sun6i_rtc_settime()
566 SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | in sun6i_rtc_settime()
567 SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); in sun6i_rtc_settime()
569 if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) in sun6i_rtc_settime()
572 time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | in sun6i_rtc_settime()
573 SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | in sun6i_rtc_settime()
574 SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); in sun6i_rtc_settime()
577 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, in sun6i_rtc_settime()
580 return -EBUSY; in sun6i_rtc_settime()
583 writel(time, chip->base + SUN6I_RTC_HMS); in sun6i_rtc_settime()
586 * After writing the RTC HH-MM-SS register, the in sun6i_rtc_settime()
591 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, in sun6i_rtc_settime()
594 return -ETIMEDOUT; in sun6i_rtc_settime()
597 writel(date, chip->base + SUN6I_RTC_YMD); in sun6i_rtc_settime()
600 * After writing the RTC YY-MM-DD register, the in sun6i_rtc_settime()
605 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, in sun6i_rtc_settime()
608 return -ETIMEDOUT; in sun6i_rtc_settime()
616 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_alarm_irq_enable() local
619 sun6i_rtc_setaie(enabled, chip); in sun6i_rtc_alarm_irq_enable()
636 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_suspend() local
639 enable_irq_wake(chip->irq); in sun6i_rtc_suspend()
647 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); in sun6i_rtc_resume() local
650 disable_irq_wake(chip->irq); in sun6i_rtc_resume()
661 struct sun6i_rtc_dev *chip = sun6i_rtc; in sun6i_rtc_probe() local
664 if (!chip) in sun6i_rtc_probe()
665 return -ENODEV; in sun6i_rtc_probe()
667 platform_set_drvdata(pdev, chip); in sun6i_rtc_probe()
669 chip->irq = platform_get_irq(pdev, 0); in sun6i_rtc_probe()
670 if (chip->irq < 0) in sun6i_rtc_probe()
671 return chip->irq; in sun6i_rtc_probe()
673 ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, in sun6i_rtc_probe()
674 0, dev_name(&pdev->dev), chip); in sun6i_rtc_probe()
676 dev_err(&pdev->dev, "Could not request IRQ\n"); in sun6i_rtc_probe()
681 writel(0, chip->base + SUN6I_ALRM_COUNTER); in sun6i_rtc_probe()
684 writel(0, chip->base + SUN6I_ALRM_EN); in sun6i_rtc_probe()
687 writel(0, chip->base + SUN6I_ALRM_IRQ_EN); in sun6i_rtc_probe()
690 writel(0, chip->base + SUN6I_ALRM1_EN); in sun6i_rtc_probe()
693 writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); in sun6i_rtc_probe()
697 chip->base + SUN6I_ALRM_IRQ_STA); in sun6i_rtc_probe()
701 chip->base + SUN6I_ALRM1_IRQ_STA); in sun6i_rtc_probe()
704 writel(0, chip->base + SUN6I_ALARM_CONFIG); in sun6i_rtc_probe()
706 clk_prepare_enable(chip->losc); in sun6i_rtc_probe()
708 device_init_wakeup(&pdev->dev, 1); in sun6i_rtc_probe()
710 chip->rtc = devm_rtc_allocate_device(&pdev->dev); in sun6i_rtc_probe()
711 if (IS_ERR(chip->rtc)) in sun6i_rtc_probe()
712 return PTR_ERR(chip->rtc); in sun6i_rtc_probe()
714 chip->rtc->ops = &sun6i_rtc_ops; in sun6i_rtc_probe()
715 chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */ in sun6i_rtc_probe()
717 ret = rtc_register_device(chip->rtc); in sun6i_rtc_probe()
721 dev_info(&pdev->dev, "RTC enabled\n"); in sun6i_rtc_probe()
729 * registers available for non-volatile storage, but experiments show
733 { .compatible = "allwinner,sun6i-a31-rtc" },
734 { .compatible = "allwinner,sun8i-a23-rtc" },
735 { .compatible = "allwinner,sun8i-h3-rtc" },
736 { .compatible = "allwinner,sun8i-r40-rtc" },
737 { .compatible = "allwinner,sun8i-v3-rtc" },
738 { .compatible = "allwinner,sun50i-h5-rtc" },
739 { .compatible = "allwinner,sun50i-h6-rtc" },
747 .name = "sun6i-rtc",