Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Jun 2017 16:48:09 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r319704 - head/sys/arm/mv/armada38x
Message-ID:  <201706081648.v58Gm9c5078139@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <der@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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706081648.v58Gm9c5078139>