Author: zbb
Date: Wed Jan 20 14:18:49 2016
New Revision: 294434
URL: https://svnweb.freebsd.org/changeset/base/294434

Log:
  Add a new RTC driver for Armada38x
  
  New driver registers RTC as system clock. New RTC resolution is 1 sec.
  Settime and gettime functions were implemented.
  
  Reviewed by:    andrew, ian
  Obtained from:  Semihalf
  Sponsored by:   Stormshield
  Submitted by:   Jan Dabros <j...@semihalf.com>
  Differential revision:  https://reviews.freebsd.org/D4421

Added:
  head/sys/arm/mv/armada38x/rtc.c   (contents, props changed)
Modified:
  head/sys/arm/mv/armada38x/files.armada38x

Modified: head/sys/arm/mv/armada38x/files.armada38x
==============================================================================
--- head/sys/arm/mv/armada38x/files.armada38x   Wed Jan 20 14:16:13 2016        
(r294433)
+++ head/sys/arm/mv/armada38x/files.armada38x   Wed Jan 20 14:18:49 2016        
(r294434)
@@ -1,4 +1,4 @@
 # $FreeBSD$
 
 arm/mv/armada38x/armada38x.c   standard
-arm/mv/rtc.c                   standard
+arm/mv/armada38x/rtc.c         standard

Added: head/sys/arm/mv/armada38x/rtc.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm/mv/armada38x/rtc.c     Wed Jan 20 14:18:49 2016        
(r294434)
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 2015 Semihalf.
+ * Copyright (c) 2015 Stormshield.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/rman.h>
+#include <sys/clock.h>
+#include <sys/systm.h>
+#include <sys/mutex.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_if.h"
+
+#define        RTC_RES_US              1000000
+#define        HALF_OF_SEC_NS          500000000
+
+#define        RTC_STATUS              0x0
+#define        RTC_TIME                0xC
+
+#define        MV_RTC_LOCK(sc)         mtx_lock(&(sc)->mutex)
+#define        MV_RTC_UNLOCK(sc)       mtx_unlock(&(sc)->mutex)
+
+static struct resource_spec res_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE },
+       { -1, 0 }
+};
+
+struct mv_rtc_softc {
+       device_t        dev;
+       struct resource *res;
+       struct mtx      mutex;
+};
+
+static int mv_rtc_probe(device_t dev);
+static int mv_rtc_attach(device_t dev);
+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,
+    uint32_t val);
+
+static device_method_t mv_rtc_methods[] = {
+       DEVMETHOD(device_probe,         mv_rtc_probe),
+       DEVMETHOD(device_attach,        mv_rtc_attach),
+       DEVMETHOD(device_detach,        mv_rtc_detach),
+
+       DEVMETHOD(clock_gettime,        mv_rtc_gettime),
+       DEVMETHOD(clock_settime,        mv_rtc_settime),
+
+       { 0, 0 },
+};
+
+static driver_t mv_rtc_driver = {
+       "rtc",
+       mv_rtc_methods,
+       sizeof(struct mv_rtc_softc),
+};
+
+static devclass_t mv_rtc_devclass;
+
+DRIVER_MODULE(mv_rtc, simplebus, mv_rtc_driver, mv_rtc_devclass, 0, 0);
+
+static int
+mv_rtc_probe(device_t dev)
+{
+
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       if (!ofw_bus_is_compatible(dev, "marvell,armada-380-rtc"))
+               return (ENXIO);
+
+       device_set_desc(dev, "Marvell Integrated RTC");
+
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mv_rtc_attach(device_t dev)
+{
+       struct mv_rtc_softc *sc;
+       int unit, ret;
+
+       unit = device_get_unit(dev);
+
+       sc = device_get_softc(dev);
+       sc->dev = dev;
+
+       clock_register(dev, RTC_RES_US);
+
+       mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_DEF);
+
+       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);
+       }
+
+       return (0);
+}
+
+static int
+mv_rtc_detach(device_t dev)
+{
+       struct mv_rtc_softc *sc;
+
+       sc = device_get_softc(dev);
+
+       mtx_destroy(&sc->mutex);
+
+       bus_release_resources(dev, res_spec, &sc->res);
+
+       return (0);
+}
+
+static int
+mv_rtc_gettime(device_t dev, struct timespec *ts)
+{
+       struct mv_rtc_softc *sc;
+       uint32_t val, val_check;
+
+       sc = device_get_softc(dev);
+
+       MV_RTC_LOCK(sc);
+       /*
+        * According to HW Errata if more than one second between
+        * two time reads is detected, then read once again
+        */
+       val = mv_rtc_reg_read(sc, RTC_TIME);
+       val_check = mv_rtc_reg_read(sc, RTC_TIME);
+       if (val_check - val > 1)
+               val_check = mv_rtc_reg_read(sc, RTC_TIME);
+
+       MV_RTC_UNLOCK(sc);
+
+       ts->tv_sec = val_check;
+       /* RTC resolution is 1 sec */
+       ts->tv_nsec = 0;
+
+       return (0);
+}
+
+static int
+mv_rtc_settime(device_t dev, struct timespec *ts)
+{
+       struct mv_rtc_softc *sc;
+
+       sc = device_get_softc(dev);
+
+       /* RTC resolution is 1 sec */
+       if (ts->tv_nsec >= HALF_OF_SEC_NS)
+               ts->tv_sec++;
+       ts->tv_nsec = 0;
+
+       MV_RTC_LOCK(sc);
+
+       /*
+        * According to errata FE-3124064, Write to RTC TIME register
+        * may fail. As a workaround, before writing to RTC TIME register,
+        * issue a dummy write of 0x0 twice to RTC Status register.
+        */
+       mv_rtc_reg_write(sc, RTC_STATUS, 0x0);
+       mv_rtc_reg_write(sc, RTC_STATUS, 0x0);
+       mv_rtc_reg_write(sc, RTC_TIME, ts->tv_sec);
+
+       MV_RTC_UNLOCK(sc);
+
+       return (0);
+}
+
+static uint32_t
+mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off)
+{
+
+       return (bus_read_4(sc->res, off));
+}
+
+/*
+ * According to the datasheet, the OS should wait 5us after every
+ * register write to the RTC hard macro so that the required update
+ * can occur without holding off the system bus
+ */
+static int
+mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val)
+{
+
+       bus_write_4(sc->res, off, val);
+       DELAY(5);
+
+       return (0);
+}
_______________________________________________
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