svn commit: r323420 - stable/11/sys/arm/freescale/imx
Ian Lepore
ian at FreeBSD.org
Mon Sep 11 02:52:42 UTC 2017
Author: ian
Date: Mon Sep 11 02:52:41 2017
New Revision: 323420
URL: https://svnweb.freebsd.org/changeset/base/323420
Log:
MFC r320655, r321933:
Add a driver for the imx6 on-chip realtime clock (snvs).
The imx6_snvs driver is not strictly required for the system to run, so
change it from standard to optional and add a device statement for it so
that it's included unless someone uses nodevice to eliminate it.
Added:
stable/11/sys/arm/freescale/imx/imx6_snvs.c
- copied unchanged from r320655, head/sys/arm/freescale/imx/imx6_snvs.c
Modified:
stable/11/sys/arm/freescale/imx/files.imx6
stable/11/sys/arm/freescale/imx/std.imx6
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/arm/freescale/imx/files.imx6
==============================================================================
--- stable/11/sys/arm/freescale/imx/files.imx6 Mon Sep 11 02:50:24 2017 (r323419)
+++ stable/11/sys/arm/freescale/imx/files.imx6 Mon Sep 11 02:52:41 2017 (r323420)
@@ -14,6 +14,7 @@ arm/freescale/imx/imx6_ccm.c standard
arm/freescale/imx/imx6_machdep.c standard
arm/freescale/imx/imx6_mp.c optional smp
arm/freescale/imx/imx6_pl310.c standard
+arm/freescale/imx/imx6_snvs.c optional imx6_snvs
arm/freescale/imx/imx6_src.c standard
arm/freescale/imx/imx_epit.c standard
arm/freescale/imx/imx_iomux.c standard
Copied: stable/11/sys/arm/freescale/imx/imx6_snvs.c (from r320655, head/sys/arm/freescale/imx/imx6_snvs.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/11/sys/arm/freescale/imx/imx6_snvs.c Mon Sep 11 02:52:41 2017 (r323420, copy of r320655, head/sys/arm/freescale/imx/imx6_snvs.c)
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2017 Ian Lepore <ian at freebsd.org>
+ * 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$");
+
+/*
+ * Driver for imx6 Secure Non-Volatile Storage system, which really means "all
+ * the stuff that's powered by a battery when main power is off". This includes
+ * realtime clock, tamper monitor, and power-management functions. Currently
+ * this driver provides only realtime clock support.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_if.h"
+
+#define SNVS_LPCR 0x38 /* Control register */
+#define LPCR_LPCALB_VAL_SHIFT 10 /* Calibration shift */
+#define LPCR_LPCALB_VAL_MASK 0x1f /* Calibration mask */
+#define LPCR_LPCALB_EN (1u << 8) /* Calibration enable */
+#define LPCR_SRTC_ENV (1u << 0) /* RTC enabled/valid */
+
+#define SNVS_LPSRTCMR 0x50 /* Counter MSB */
+#define SNVS_LPSRTCLR 0x54 /* Counter LSB */
+
+#define RTC_RESOLUTION_US (1000000 / 32768) /* 32khz clock */
+
+/*
+ * The RTC is a 47-bit counter clocked at 32KHz and organized as a 32.15
+ * fixed-point binary value. Shifting by SBT_LSB bits translates between
+ * counter and sbintime values.
+ */
+#define RTC_BITS 47
+#define SBT_BITS 64
+#define SBT_LSB (SBT_BITS - RTC_BITS)
+
+struct snvs_softc {
+ device_t dev;
+ struct resource * memres;
+ uint32_t lpcr;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,sec-v4.0-mon", true},
+ {NULL, false}
+};
+
+static inline uint32_t
+RD4(struct snvs_softc *sc, bus_size_t offset)
+{
+
+ return (bus_read_4(sc->memres, offset));
+}
+
+static inline void
+WR4(struct snvs_softc *sc, bus_size_t offset, uint32_t value)
+{
+
+ bus_write_4(sc->memres, offset, value);
+}
+
+static void
+snvs_rtc_enable(struct snvs_softc *sc, bool enable)
+{
+ uint32_t enbit;
+
+ if (enable)
+ sc->lpcr |= LPCR_SRTC_ENV;
+ else
+ sc->lpcr &= ~LPCR_SRTC_ENV;
+ WR4(sc, SNVS_LPCR, sc->lpcr);
+
+ /* Wait for the hardware to achieve the requested state. */
+ enbit = sc->lpcr & LPCR_SRTC_ENV;
+ while ((RD4(sc, SNVS_LPCR) & LPCR_SRTC_ENV) != enbit)
+ continue;
+}
+
+static int
+snvs_gettime(device_t dev, struct timespec *ts)
+{
+ struct snvs_softc *sc;
+ sbintime_t counter1, counter2;
+
+ sc = device_get_softc(dev);
+
+ /* If the clock is not enabled and valid, we can't help. */
+ if (!(RD4(sc, SNVS_LPCR) & LPCR_SRTC_ENV)) {
+ return (EINVAL);
+ }
+
+ /*
+ * The counter is clocked asynchronously to cpu accesses; read and
+ * assemble the pieces of the counter until we get the same value twice.
+ * The counter is 47 bits, organized as a 32.15 binary fixed-point
+ * value. If we shift it up to the high order part of a 64-bit word it
+ * turns into an sbintime.
+ */
+ do {
+ counter1 = (uint64_t)RD4(sc, SNVS_LPSRTCMR) << (SBT_LSB + 32);
+ counter1 |= (uint64_t)RD4(sc, SNVS_LPSRTCLR) << (SBT_LSB);
+ counter2 = (uint64_t)RD4(sc, SNVS_LPSRTCMR) << (SBT_LSB + 32);
+ counter2 |= (uint64_t)RD4(sc, SNVS_LPSRTCLR) << (SBT_LSB);
+ } while (counter1 != counter2);
+
+ *ts = sbttots(counter1);
+
+ return (0);
+}
+
+static int
+snvs_settime(device_t dev, struct timespec *unused)
+{
+ struct snvs_softc *sc;
+ struct bintime bt;
+ sbintime_t sbt;
+
+ sc = device_get_softc(dev);
+
+ /*
+ * Ignore the inaccurate time passed in from the common clock code and
+ * obtain a time worthy of our 30us accuracy.
+ */
+ bintime(&bt);
+ bt.sec -= utc_offset();
+ sbt = bttosbt(bt);
+
+ /*
+ * It takes two clock cycles for the counter to start after setting the
+ * enable bit, so add two SBT_LSBs to what we're about to set.
+ */
+ sbt += 2 << SBT_LSB;
+ snvs_rtc_enable(sc, false);
+ WR4(sc, SNVS_LPSRTCMR, (uint32_t)(sbt >> (SBT_LSB + 32)));
+ WR4(sc, SNVS_LPSRTCLR, (uint32_t)(sbt >> (SBT_LSB)));
+ snvs_rtc_enable(sc, true);
+
+ return (0);
+}
+
+static int
+snvs_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "i.MX6 SNVS RTC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+snvs_attach(device_t dev)
+{
+ struct snvs_softc *sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->memres == NULL) {
+ device_printf(sc->dev, "could not allocate registers\n");
+ return (ENXIO);
+ }
+
+ clock_register(sc->dev, RTC_RESOLUTION_US);
+
+ return (0);
+}
+
+static device_method_t snvs_methods[] = {
+ DEVMETHOD(device_probe, snvs_probe),
+ DEVMETHOD(device_attach, snvs_attach),
+
+ /* clock_if methods */
+ DEVMETHOD(clock_gettime, snvs_gettime),
+ DEVMETHOD(clock_settime, snvs_settime),
+
+ DEVMETHOD_END
+};
+
+static driver_t snvs_driver = {
+ "snvs",
+ snvs_methods,
+ sizeof(struct snvs_softc),
+};
+
+static devclass_t snvs_devclass;
+
+DRIVER_MODULE(snvs, simplebus, snvs_driver, snvs_devclass, 0, 0);
Modified: stable/11/sys/arm/freescale/imx/std.imx6
==============================================================================
--- stable/11/sys/arm/freescale/imx/std.imx6 Mon Sep 11 02:50:24 2017 (r323419)
+++ stable/11/sys/arm/freescale/imx/std.imx6 Mon Sep 11 02:52:41 2017 (r323420)
@@ -9,7 +9,8 @@ makeoptions KERNVIRTADDR = 0xc2000000
options IPI_IRQ_START=0
options IPI_IRQ_END=15
-device fdt_pinctrl
+device fdt_pinctrl
+device imx6_snvs
files "../freescale/imx/files.imx6"
More information about the svn-src-stable-11
mailing list