Merge tag 'io_uring-5.11-2020-12-23' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / rtc / rtc-sun6i.c
index 852f5f3..adec1b1 100644 (file)
  * driver, even though it is somewhat limited.
  */
 #define SUN6I_YEAR_MIN                         1970
-#define SUN6I_YEAR_MAX                         2033
 #define SUN6I_YEAR_OFF                         (SUN6I_YEAR_MIN - 1900)
 
 /*
@@ -250,19 +249,17 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
                writel(reg, rtc->base + SUN6I_LOSC_CTRL);
        }
 
-       /* Switch to the external, more precise, oscillator */
-       reg |= SUN6I_LOSC_CTRL_EXT_OSC;
-       if (rtc->data->has_losc_en)
-               reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+       /* Switch to the external, more precise, oscillator, if present */
+       if (of_get_property(node, "clocks", NULL)) {
+               reg |= SUN6I_LOSC_CTRL_EXT_OSC;
+               if (rtc->data->has_losc_en)
+                       reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+       }
        writel(reg, rtc->base + SUN6I_LOSC_CTRL);
 
        /* Yes, I know, this is ugly. */
        sun6i_rtc = rtc;
 
-       /* Deal with old DTs */
-       if (!of_get_property(node, "clocks", NULL))
-               goto err;
-
        /* Only read IOSC name from device tree if it is exported */
        if (rtc->data->export_iosc)
                of_property_read_string_index(node, "clock-output-names", 2,
@@ -275,15 +272,17 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
                                                                300000000);
        if (IS_ERR(rtc->int_osc)) {
                pr_crit("Couldn't register the internal oscillator\n");
-               return;
+               goto err;
        }
 
        parents[0] = clk_hw_get_name(rtc->int_osc);
+       /* If there is no external oscillator, this will be NULL and ... */
        parents[1] = of_clk_get_parent_name(node, 0);
 
        rtc->hw.init = &init;
 
        init.parent_names = parents;
+       /* ... number of clock parents will be 1. */
        init.num_parents = of_clk_get_parent_count(node) + 1;
        of_property_read_string_index(node, "clock-output-names", 0,
                                      &init.name);
@@ -291,7 +290,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
        rtc->losc = clk_register(NULL, &rtc->hw);
        if (IS_ERR(rtc->losc)) {
                pr_crit("Couldn't register the LOSC clock\n");
-               return;
+               goto err_register;
        }
 
        of_property_read_string_index(node, "clock-output-names", 1,
@@ -302,7 +301,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
                                          &rtc->lock);
        if (IS_ERR(rtc->ext_losc)) {
                pr_crit("Couldn't register the LOSC external gate\n");
-               return;
+               goto err_register;
        }
 
        clk_data->num = 2;
@@ -315,6 +314,8 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
        of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
        return;
 
+err_register:
+       clk_hw_unregister_fixed_rate(rtc->int_osc);
 err:
        kfree(clk_data);
 }
@@ -499,7 +500,7 @@ static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 
        wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
        wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
-       rtc_time_to_tm(chip->alarm, &wkalrm->time);
+       rtc_time64_to_tm(chip->alarm, &wkalrm->time);
 
        return 0;
 }
@@ -520,8 +521,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
                return -EINVAL;
        }
 
-       rtc_tm_to_time(alrm_tm, &time_set);
-       rtc_tm_to_time(&tm_now, &time_now);
+       time_set = rtc_tm_to_time64(alrm_tm);
+       time_now = rtc_tm_to_time64(&tm_now);
        if (time_set <= time_now) {
                dev_err(dev, "Date to set in the past\n");
                return -EINVAL;
@@ -569,14 +570,6 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
        struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
        u32 date = 0;
        u32 time = 0;
-       int year;
-
-       year = rtc_tm->tm_year + 1900;
-       if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) {
-               dev_err(dev, "rtc only supports year in range %d - %d\n",
-                       SUN6I_YEAR_MIN, SUN6I_YEAR_MAX);
-               return -EINVAL;
-       }
 
        rtc_tm->tm_year -= SUN6I_YEAR_OFF;
        rtc_tm->tm_mon += 1;
@@ -585,7 +578,7 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
                SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
                SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
 
-       if (is_leap_year(year))
+       if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
                date |= SUN6I_LEAP_SET_VALUE(1);
 
        time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
@@ -726,12 +719,16 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 1);
 
-       chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i",
-                                            &sun6i_rtc_ops, THIS_MODULE);
-       if (IS_ERR(chip->rtc)) {
-               dev_err(&pdev->dev, "unable to register device\n");
+       chip->rtc = devm_rtc_allocate_device(&pdev->dev);
+       if (IS_ERR(chip->rtc))
                return PTR_ERR(chip->rtc);
-       }
+
+       chip->rtc->ops = &sun6i_rtc_ops;
+       chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
+
+       ret = devm_rtc_register_device(chip->rtc);
+       if (ret)
+               return ret;
 
        dev_info(&pdev->dev, "RTC enabled\n");