Author: manu
Date: Tue Apr 16 12:39:31 2019
New Revision: 346271
URL: https://svnweb.freebsd.org/changeset/base/346271

Log:
  aw_rtc: Register the clocks
  
  Since latest DTS update the rtc is supposed to register two clocks :
  
  - osc32k (the 32k oscillator on the board that the RTC uses directly and
  that other peripheral can use)
  - iosc (the internal oscillator of the RTC when available which frequency
  depend on the SoC revision)
  
  Since we need the RTC before the proper clock control unit (because it uses
  those clocks) attach it a BUS_PASS_BUS + MIDDLE and attach the clock control
  unit at BUS_PASS_BUS + LAST for the SoC that requires it.
  
  Tested On:         A20, H3, A64
  
  MFC after:    1 month

Modified:
  head/sys/arm/allwinner/aw_rtc.c
  head/sys/arm/allwinner/clkng/ccu_a31.c
  head/sys/arm/allwinner/clkng/ccu_a64.c
  head/sys/arm/allwinner/clkng/ccu_a83t.c
  head/sys/arm/allwinner/clkng/ccu_h3.c

Modified: head/sys/arm/allwinner/aw_rtc.c
==============================================================================
--- head/sys/arm/allwinner/aw_rtc.c     Tue Apr 16 12:25:15 2019        
(r346270)
+++ head/sys/arm/allwinner/aw_rtc.c     Tue Apr 16 12:39:31 2019        
(r346271)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2019 Emmanuel Vadot <m...@freebsd.org>
  * Copyright (c) 2016 Vladimir Belian <fat...@gmail.com>
  * All rights reserved.
  *
@@ -43,6 +44,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
+#include <dev/extres/clk/clk_fixed.h>
+
 #include <arm/allwinner/aw_machdep.h>
 
 #include "clock_if.h"
@@ -62,7 +65,7 @@ __FBSDID("$FreeBSD$");
 #define        LOSC_MAGIC                      0x16aa0000
 #define        LOSC_BUSY_MASK                  0x00000380
 
-#define        IS_SUN7I                        (sc->type == A20_RTC)
+#define        IS_SUN7I                        (sc->conf->is_a20 == true)
 
 #define        YEAR_MIN                        (IS_SUN7I ? 1970 : 2010)
 #define        YEAR_MAX                        (IS_SUN7I ? 2100 : 2073)
@@ -92,27 +95,68 @@ __FBSDID("$FreeBSD$");
 #define        RTC_READ(sc, reg)               bus_read_4((sc)->res, (reg))
 #define        RTC_WRITE(sc, reg, val)         bus_write_4((sc)->res, (reg), 
(val))
 
-#define        IS_LEAP_YEAR(y) \
-       (((y) % 400) == 0 || (((y) % 100) != 0 && ((y) % 4) == 0))
+#define        IS_LEAP_YEAR(y) (((y) % 400) == 0 || (((y) % 100) != 0 && ((y) 
% 4) == 0))
 
-#define        A10_RTC 1
-#define        A20_RTC 2
-#define        A31_RTC 3
+struct aw_rtc_conf {
+       uint64_t        iosc_freq;
+       bus_size_t      rtc_date;
+       bus_size_t      rtc_time;
+       bus_size_t      rtc_losc_sta;
+       bool            is_a20;
+};
 
+struct aw_rtc_conf a10_conf = {
+       .rtc_date = A10_RTC_DATE_REG,
+       .rtc_time = A10_RTC_TIME_REG,
+       .rtc_losc_sta = LOSC_CTRL_REG,
+};
+
+struct aw_rtc_conf a20_conf = {
+       .rtc_date = A10_RTC_DATE_REG,
+       .rtc_time = A10_RTC_TIME_REG,
+       .rtc_losc_sta = LOSC_CTRL_REG,
+       .is_a20 = true,
+};
+
+struct aw_rtc_conf a31_conf = {
+       .iosc_freq = 650000,                    /* between 600 and 700 Khz */
+       .rtc_date = A31_RTC_DATE_REG,
+       .rtc_time = A31_RTC_TIME_REG,
+       .rtc_losc_sta = A31_LOSC_AUTO_SWT_STA,
+};
+
+struct aw_rtc_conf h3_conf = {
+       .iosc_freq = 16000000,
+       .rtc_date = A31_RTC_DATE_REG,
+       .rtc_time = A31_RTC_TIME_REG,
+       .rtc_losc_sta = A31_LOSC_AUTO_SWT_STA,
+};
+
 static struct ofw_compat_data compat_data[] = {
-       { "allwinner,sun4i-a10-rtc", A10_RTC },
-       { "allwinner,sun7i-a20-rtc", A20_RTC },
-       { "allwinner,sun6i-a31-rtc", A31_RTC },
+       { "allwinner,sun4i-a10-rtc", (uintptr_t) &a10_conf },
+       { "allwinner,sun7i-a20-rtc", (uintptr_t) &a20_conf },
+       { "allwinner,sun6i-a31-rtc", (uintptr_t) &a31_conf },
+       { "allwinner,sun8i-h3-rtc", (uintptr_t) &h3_conf },
        { NULL, 0 }
 };
 
 struct aw_rtc_softc {
        struct resource         *res;
+       struct aw_rtc_conf      *conf;
        int                     type;
-       bus_size_t              rtc_date;
-       bus_size_t              rtc_time;
 };
 
+static struct clk_fixed_def aw_rtc_osc32k = {
+       .clkdef.id = 0,
+       .freq = 32768,
+};
+
+static struct clk_fixed_def aw_rtc_iosc = {
+       .clkdef.id = 2,
+};
+
+static void    aw_rtc_install_clocks(struct aw_rtc_softc *sc, device_t dev);
+
 static int aw_rtc_probe(device_t dev);
 static int aw_rtc_attach(device_t dev);
 static int aw_rtc_detach(device_t dev);
@@ -140,9 +184,8 @@ static driver_t aw_rtc_driver = {
 static devclass_t aw_rtc_devclass;
 
 EARLY_DRIVER_MODULE(aw_rtc, simplebus, aw_rtc_driver, aw_rtc_devclass, 0, 0,
-    BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+    BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
 
-
 static int
 aw_rtc_probe(device_t dev)
 {
@@ -161,7 +204,6 @@ static int
 aw_rtc_attach(device_t dev)
 {
        struct aw_rtc_softc *sc  = device_get_softc(dev);
-       bus_size_t rtc_losc_sta;
        uint32_t val;
        int rid = 0;
 
@@ -171,20 +213,7 @@ aw_rtc_attach(device_t dev)
                return (ENXIO);
        }
 
-       sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
-       switch (sc->type) {
-       case A10_RTC:
-       case A20_RTC:
-               sc->rtc_date = A10_RTC_DATE_REG;
-               sc->rtc_time = A10_RTC_TIME_REG;
-               rtc_losc_sta = LOSC_CTRL_REG;
-               break;
-       case A31_RTC:
-               sc->rtc_date = A31_RTC_DATE_REG;
-               sc->rtc_time = A31_RTC_TIME_REG;
-               rtc_losc_sta = A31_LOSC_AUTO_SWT_STA;
-               break;
-       }
+       sc->conf = (struct aw_rtc_conf *)ofw_bus_search_compatible(dev, 
compat_data)->ocd_data;
        val = RTC_READ(sc, LOSC_CTRL_REG);
        val |= LOSC_AUTO_SW_EN;
        val |= LOSC_MAGIC | LOSC_GSM | LOSC_OSC_SRC;
@@ -193,13 +222,15 @@ aw_rtc_attach(device_t dev)
        DELAY(100);
 
        if (bootverbose) {
-               val = RTC_READ(sc, rtc_losc_sta);
+               val = RTC_READ(sc, sc->conf->rtc_losc_sta);
                if ((val & LOSC_OSC_SRC) == 0)
                        device_printf(dev, "Using internal oscillator\n");
                else
                        device_printf(dev, "Using external oscillator\n");
        }
 
+       aw_rtc_install_clocks(sc, dev);
+
        clock_register(dev, RTC_RES_US);
        
        return (0);
@@ -212,6 +243,41 @@ aw_rtc_detach(device_t dev)
        return (EBUSY);
 }
 
+static void
+aw_rtc_install_clocks(struct aw_rtc_softc *sc, device_t dev) {
+       struct clkdom *clkdom;
+       const char **clknames;
+       phandle_t node;
+       int nclocks;
+
+       node = ofw_bus_get_node(dev);
+       nclocks = ofw_bus_string_list_to_array(node, "clock-output-names", 
&clknames);
+       /* No clocks to export */
+       if (nclocks <= 0)
+               return;
+
+       if (nclocks != 3) {
+               device_printf(dev, "Having only %d clocks instead of 3, 
aborting\n", nclocks);
+               return;
+       }
+
+       clkdom = clkdom_create(dev);
+
+       aw_rtc_osc32k.clkdef.name = clknames[0];
+       if (clknode_fixed_register(clkdom, &aw_rtc_osc32k) != 0)
+               device_printf(dev, "Cannot register osc32k clock\n");
+
+       aw_rtc_iosc.clkdef.name = clknames[2];
+       aw_rtc_iosc.freq = sc->conf->iosc_freq;
+       if (clknode_fixed_register(clkdom, &aw_rtc_iosc) != 0)
+               device_printf(dev, "Cannot register iosc clock\n");
+
+       clkdom_finit(clkdom);
+
+       if (bootverbose)
+               clkdom_dump(clkdom);
+}
+
 static int
 aw_rtc_gettime(device_t dev, struct timespec *ts)
 {
@@ -219,11 +285,11 @@ aw_rtc_gettime(device_t dev, struct timespec *ts)
        struct clocktime ct;
        uint32_t rdate, rtime;
 
-       rdate = RTC_READ(sc, sc->rtc_date);
-       rtime = RTC_READ(sc, sc->rtc_time);
+       rdate = RTC_READ(sc, sc->conf->rtc_date);
+       rtime = RTC_READ(sc, sc->conf->rtc_time);
        
        if ((rtime & TIME_MASK) == 0)
-               rdate = RTC_READ(sc, sc->rtc_date);
+               rdate = RTC_READ(sc, sc->conf->rtc_date);
 
        ct.sec = GET_SEC_VALUE(rtime);
        ct.min = GET_MIN_VALUE(rtime);
@@ -265,7 +331,7 @@ aw_rtc_settime(device_t dev, struct timespec *ts)
                DELAY(1);
        }
        /* reset time register to avoid unexpected date increment */
-       RTC_WRITE(sc, sc->rtc_time, 0);
+       RTC_WRITE(sc, sc->conf->rtc_time, 0);
 
        rdate = SET_DAY_VALUE(ct.day) | SET_MON_VALUE(ct.mon) |
                SET_YEAR_VALUE(ct.year - YEAR_OFFSET) | 
@@ -281,7 +347,7 @@ aw_rtc_settime(device_t dev, struct timespec *ts)
                }
                DELAY(1);
        }
-       RTC_WRITE(sc, sc->rtc_date, rdate);
+       RTC_WRITE(sc, sc->conf->rtc_date, rdate);
 
        for (clk = 0; RTC_READ(sc, LOSC_CTRL_REG) & LOSC_BUSY_MASK; clk++) {
                if (clk > RTC_TIMEOUT) {
@@ -290,7 +356,7 @@ aw_rtc_settime(device_t dev, struct timespec *ts)
                }
                DELAY(1);
        }
-       RTC_WRITE(sc, sc->rtc_time, rtime);
+       RTC_WRITE(sc, sc->conf->rtc_time, rtime);
 
        DELAY(RTC_TIMEOUT);
 

Modified: head/sys/arm/allwinner/clkng/ccu_a31.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a31.c      Tue Apr 16 12:25:15 2019        
(r346270)
+++ head/sys/arm/allwinner/clkng/ccu_a31.c      Tue Apr 16 12:39:31 2019        
(r346271)
@@ -973,4 +973,4 @@ DEFINE_CLASS_1(ccu_a31ng, ccu_a31ng_driver, ccu_a31ng_
   sizeof(struct aw_ccung_softc), aw_ccung_driver);
 
 EARLY_DRIVER_MODULE(ccu_a31ng, simplebus, ccu_a31ng_driver,
-    ccu_a31ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    ccu_a31ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);

Modified: head/sys/arm/allwinner/clkng/ccu_a64.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a64.c      Tue Apr 16 12:25:15 2019        
(r346270)
+++ head/sys/arm/allwinner/clkng/ccu_a64.c      Tue Apr 16 12:39:31 2019        
(r346271)
@@ -825,4 +825,4 @@ DEFINE_CLASS_1(ccu_a64ng, ccu_a64ng_driver, ccu_a64ng_
   sizeof(struct aw_ccung_softc), aw_ccung_driver);
 
 EARLY_DRIVER_MODULE(ccu_a64ng, simplebus, ccu_a64ng_driver,
-    ccu_a64ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    ccu_a64ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);

Modified: head/sys/arm/allwinner/clkng/ccu_a83t.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a83t.c     Tue Apr 16 12:25:15 2019        
(r346270)
+++ head/sys/arm/allwinner/clkng/ccu_a83t.c     Tue Apr 16 12:39:31 2019        
(r346271)
@@ -786,4 +786,4 @@ DEFINE_CLASS_1(ccu_a83tng, ccu_a83tng_driver, ccu_a83t
   sizeof(struct aw_ccung_softc), aw_ccung_driver);
 
 EARLY_DRIVER_MODULE(ccu_a83tng, simplebus, ccu_a83tng_driver,
-    ccu_a83tng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    ccu_a83tng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);

Modified: head/sys/arm/allwinner/clkng/ccu_h3.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_h3.c       Tue Apr 16 12:25:15 2019        
(r346270)
+++ head/sys/arm/allwinner/clkng/ccu_h3.c       Tue Apr 16 12:39:31 2019        
(r346271)
@@ -787,4 +787,4 @@ DEFINE_CLASS_1(ccu_h3ng, ccu_h3ng_driver, ccu_h3ng_met
   sizeof(struct aw_ccung_softc), aw_ccung_driver);
 
 EARLY_DRIVER_MODULE(ccu_h3ng, simplebus, ccu_h3ng_driver,
-    ccu_h3ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    ccu_h3ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to