Author: zbb
Date: Thu Jun  8 16:48:09 2017
New Revision: 319704
URL: https://svnweb.freebsd.org/changeset/base/319704

Log:
  Enable MBUS bridge configuration in mv_rtc driver
  
  This patch fixes sporadic problems with updating time
  with mv_rtc driver by configuring access to it via MBUS.
  For this purpose already existing second set of resources
  in rtc@3800 node of Armada 38x DT is used.
  
  Submitted by: Dominik Ermel <d...@semihalf.com>
  Obtained from: Semihalf
  Sponsored by: Stormshield
  Differential revision: https://reviews.freebsd.org/D10901

Modified:
  head/sys/arm/mv/armada38x/rtc.c

Modified: head/sys/arm/mv/armada38x/rtc.c
==============================================================================
--- head/sys/arm/mv/armada38x/rtc.c     Thu Jun  8 16:46:38 2017        
(r319703)
+++ head/sys/arm/mv/armada38x/rtc.c     Thu Jun  8 16:48:09 2017        
(r319704)
@@ -69,17 +69,30 @@ __FBSDID("$FreeBSD$");
 #define        RTC_STATUS_ALARM1_MASK  0x1
 #define        RTC_STATUS_ALARM2_MASK  0x2
 
-#define        MV_RTC_LOCK(sc)         mtx_lock(&(sc)->mutex)
-#define        MV_RTC_UNLOCK(sc)       mtx_unlock(&(sc)->mutex)
+#define        MV_RTC_LOCK(sc)         mtx_lock_spin(&(sc)->mutex)
+#define        MV_RTC_UNLOCK(sc)       mtx_unlock_spin(&(sc)->mutex)
 
+#define        RTC_BRIDGE_TIMING_CTRL          0x0
+#define        RTC_WRCLK_PERIOD_SHIFT                  0
+#define        RTC_WRCLK_PERIOD_MASK                   0x00000003FF
+#define        RTC_WRCLK_PERIOD_MAX                    0x3FF
+#define        RTC_READ_OUTPUT_DELAY_SHIFT             26
+#define        RTC_READ_OUTPUT_DELAY_MASK              0x007C000000
+#define        RTC_READ_OUTPUT_DELAY_MAX               0x1F
+
+#define        RTC_RES         0
+#define        RTC_SOC_RES     1
+
+
 static struct resource_spec res_spec[] = {
        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
+       { SYS_RES_MEMORY,       1,      RF_ACTIVE },
        { -1, 0 }
 };
 
 struct mv_rtc_softc {
        device_t        dev;
-       struct resource *res;
+       struct resource *res[2];
        struct mtx      mutex;
 };
 
@@ -90,9 +103,11 @@ static int mv_rtc_detach(device_t dev);
 static int mv_rtc_gettime(device_t dev, struct timespec *ts);
 static int mv_rtc_settime(device_t dev, struct timespec *ts);
 
-static uint32_t mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off);
-static int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off,
+static inline uint32_t mv_rtc_reg_read(struct mv_rtc_softc *sc,
+    bus_size_t off);
+static inline int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off,
     uint32_t val);
+static inline void mv_rtc_configure_bus(struct mv_rtc_softc *sc);
 
 static device_method_t mv_rtc_methods[] = {
        DEVMETHOD(device_probe,         mv_rtc_probe),
@@ -180,14 +195,16 @@ mv_rtc_attach(device_t dev)
 
        clock_register(dev, RTC_RES_US);
 
-       mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_DEF);
+       mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);
 
-       ret = bus_alloc_resources(dev, res_spec, &sc->res);
+       ret = bus_alloc_resources(dev, res_spec, sc->res);
+
        if (ret != 0) {
                device_printf(dev, "could not allocate resources\n");
                mtx_destroy(&sc->mutex);
                return (ENXIO);
        }
+       mv_rtc_configure_bus(sc);
 
        return (0);
 }
@@ -201,7 +218,7 @@ mv_rtc_detach(device_t dev)
 
        mtx_destroy(&sc->mutex);
 
-       bus_release_resources(dev, res_spec, &sc->res);
+       bus_release_resources(dev, res_spec, sc->res);
 
        return (0);
 }
@@ -267,11 +284,11 @@ mv_rtc_settime(device_t dev, struct timespec *ts)
        return (0);
 }
 
-static uint32_t
+static inline uint32_t
 mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off)
 {
 
-       return (bus_read_4(sc->res, off));
+       return (bus_read_4(sc->res[RTC_RES], off));
 }
 
 /*
@@ -279,12 +296,24 @@ mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t of
  * register write to the RTC hard macro so that the required update
  * can occur without holding off the system bus
  */
-static int
+static inline int
 mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val)
 {
 
-       bus_write_4(sc->res, off, val);
+       bus_write_4(sc->res[RTC_RES], off, val);
        DELAY(5);
 
        return (0);
+}
+
+static inline void
+mv_rtc_configure_bus(struct mv_rtc_softc *sc)
+{
+       int val;
+
+       val = bus_read_4(sc->res[RTC_SOC_RES], RTC_BRIDGE_TIMING_CTRL);
+       val &= ~(RTC_WRCLK_PERIOD_MASK | RTC_READ_OUTPUT_DELAY_MASK);
+       val |= RTC_WRCLK_PERIOD_MAX << RTC_WRCLK_PERIOD_SHIFT;
+       val |= RTC_READ_OUTPUT_DELAY_MAX << RTC_READ_OUTPUT_DELAY_SHIFT;
+       bus_write_4(sc->res[RTC_SOC_RES], RTC_BRIDGE_TIMING_CTRL, val);
 }
_______________________________________________
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