svn commit: r294434 - head/sys/arm/mv/armada38x
Zbigniew Bodek
zbb at FreeBSD.org
Wed Jan 20 14:18:50 UTC 2016
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 <jsd at 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);
+}
More information about the svn-src-head
mailing list