Index: stable/11/share/man/man4/man4.arm/Makefile =================================================================== --- stable/11/share/man/man4/man4.arm/Makefile (revision 346521) +++ stable/11/share/man/man4/man4.arm/Makefile (revision 346522) @@ -1,17 +1,19 @@ # $FreeBSD$ PACKAGE=runtime-manuals MAN= cgem.4 \ devcfg.4 \ + imx_wdog.4 \ mge.4 \ npe.4 \ ti_adc.4 MLINKS= cgem.4 if_cgem.4 +MLINKS+= imx_wdog.4 imxwdt.4 MLINKS+= mge.4 if_mge.4 MLINKS+=npe.4 if_npe.4 MANSUBDIR=/arm .include Index: stable/11/share/man/man4/man4.arm/imx_wdog.4 =================================================================== --- stable/11/share/man/man4/man4.arm/imx_wdog.4 (nonexistent) +++ stable/11/share/man/man4/man4.arm/imx_wdog.4 (revision 346522) @@ -0,0 +1,112 @@ +.\" +.\" Copyright (c) 2018 Ian Lepore +.\" 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 ``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 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 7, 2018 +.Dt IMX_WDOG 4 +.Os +.Sh NAME +.Nm imx_wdog +.Nd device driver for the NXP i.MX5 and i.MX6 watchdog timer +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following line in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device imxwdt" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +imx_wdog_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides +.Xr watchdog 4 +support for the watchdog timer present on NXP i.MX5 and i.MX6 processors. +The i.MX watchdog hardware supports programmable timeouts ranging from +0.5 to 128 seconds, in half-second increments. +Once activated, the watchdog hardware cannot be deactivated, but the +timeout period can be changed to any valid non-zero value. +.Pp +At power-on, a special 16-second +.Sq power-down timer +mode is automatically enabled by the hardware. +It will assert the external WDOG_B signal, which may be connected to +external hardware that causes the system to reset or power-down. +The power-down timer is often reset by the boot loader (typically U-Boot). +If the power-down timer is still active at the time when the normal +watchdog is first enabled, the +.Nm +driver automatically disables it. +.Pp +The +.Nm +driver supports the FDT +.Va fsl,external-reset +property by enabling the assertion of the WDOG_B external timeout signal +when the property is present. +When running this way, the need to reset the system due to watchdog +timeout is signaled by driving the WDOG_B line low; some external +entity is expected to assert the chip's POR pin in response. +The +.Nm +driver attempts to backstop this external reset by scheduling an +interrupt to occur as well. +The interrupt handler waits 1 second for the external reset to occur, +then it triggers a normal software reset. +Note that the WDOG_B signal can be configured to use a variety of +pins on the chip. +For the +.Va fsl,external-reset +property to be effective, the signal must be connected to an appropriate +pin by the system's FDT pinctrl data. +.Pp +The +.Nm +driver supports the FDT +.Va timeout-secs +property by enabling the watchdog as soon as the driver attaches, +using the given timeout value. +This extends watchdog protection to much of the system startup process, +but it still requires that +.Xr watchdogd 4 +be configured to service the watchdog. +.Sh SEE ALSO +.Xr fdt 4 , +.Xr watchdog 4 , +.Xr watchdog 8 , +.Xr watchdogd 8 , +.Xr watchdog 9 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 10.0 . Property changes on: stable/11/share/man/man4/man4.arm/imx_wdog.4 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/freescale/imx/imx_wdog.c =================================================================== --- stable/11/sys/arm/freescale/imx/imx_wdog.c (revision 346521) +++ stable/11/sys/arm/freescale/imx/imx_wdog.c (revision 346522) @@ -1,228 +1,260 @@ /*- * Copyright (c) 2012, 2013 The FreeBSD Foundation * All rights reserved. * * This software was developed by Oleksandr Rybalko under sponsorship * from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct imx_wdog_softc { struct mtx sc_mtx; device_t sc_dev; struct resource *sc_res[2]; void *sc_ih; uint32_t sc_timeout; bool sc_pde_enabled; }; static struct resource_spec imx_wdog_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE }, RESOURCE_SPEC_END }; #define MEMRES 0 #define IRQRES 1 static struct ofw_compat_data compat_data[] = { {"fsl,imx6sx-wdt", 1}, {"fsl,imx6sl-wdt", 1}, {"fsl,imx6q-wdt", 1}, {"fsl,imx53-wdt", 1}, {"fsl,imx51-wdt", 1}, {"fsl,imx50-wdt", 1}, {"fsl,imx35-wdt", 1}, {"fsl,imx27-wdt", 1}, {"fsl,imx25-wdt", 1}, {"fsl,imx21-wdt", 1}, {NULL, 0} }; static inline uint16_t RD2(struct imx_wdog_softc *sc, bus_size_t offs) { return (bus_read_2(sc->sc_res[MEMRES], offs)); } static inline void WR2(struct imx_wdog_softc *sc, bus_size_t offs, uint16_t val) { bus_write_2(sc->sc_res[MEMRES], offs, val); } +static int +imx_wdog_enable(struct imx_wdog_softc *sc, u_int timeout) +{ + uint16_t reg; + + if (timeout < 1 || timeout > 128) + return (EINVAL); + + mtx_lock(&sc->sc_mtx); + if (timeout != sc->sc_timeout) { + sc->sc_timeout = timeout; + reg = RD2(sc, WDOG_CR_REG); + reg &= ~WDOG_CR_WT_MASK; + reg |= ((2 * timeout - 1) << WDOG_CR_WT_SHIFT); + WR2(sc, WDOG_CR_REG, reg | WDOG_CR_WDE); + } + /* Refresh counter */ + WR2(sc, WDOG_SR_REG, WDOG_SR_STEP1); + WR2(sc, WDOG_SR_REG, WDOG_SR_STEP2); + /* Watchdog active, can disable rom-boot watchdog. */ + if (sc->sc_pde_enabled) { + sc->sc_pde_enabled = false; + reg = RD2(sc, WDOG_MCR_REG); + WR2(sc, WDOG_MCR_REG, reg & ~WDOG_MCR_PDE); + } + mtx_unlock(&sc->sc_mtx); + + return (0); +} + static void imx_watchdog(void *arg, u_int cmd, int *error) { struct imx_wdog_softc *sc; - uint16_t reg; u_int timeout; sc = arg; - mtx_lock(&sc->sc_mtx); if (cmd == 0) { if (bootverbose) device_printf(sc->sc_dev, "Can not be disabled.\n"); *error = EOPNOTSUPP; } else { timeout = (u_int)((1ULL << (cmd & WD_INTERVAL)) / 1000000000U); - if (timeout > 1 && timeout < 128) { - if (timeout != sc->sc_timeout) { - sc->sc_timeout = timeout; - reg = RD2(sc, WDOG_CR_REG); - reg &= ~WDOG_CR_WT_MASK; - reg |= (timeout << (WDOG_CR_WT_SHIFT + 1)) & - WDOG_CR_WT_MASK; - WR2(sc, WDOG_CR_REG, reg | WDOG_CR_WDE); - } - /* Refresh counter */ - WR2(sc, WDOG_SR_REG, WDOG_SR_STEP1); - WR2(sc, WDOG_SR_REG, WDOG_SR_STEP2); - /* Watchdog active, can disable rom-boot watchdog. */ - if (sc->sc_pde_enabled) { - sc->sc_pde_enabled = false; - reg = RD2(sc, WDOG_MCR_REG); - WR2(sc, WDOG_MCR_REG, reg & ~WDOG_MCR_PDE); - } + if (imx_wdog_enable(sc, timeout) == 0) *error = 0; - } } - mtx_unlock(&sc->sc_mtx); } static int imx_wdog_intr(void *arg) { struct imx_wdog_softc *sc = arg; /* * When configured for external reset, the actual reset is supposed to * happen when some external device responds to the assertion of the * WDOG_B signal by asserting the POR signal to the chip. This * interrupt handler is a backstop mechanism; it is set up to fire * simultaneously with WDOG_B, and if the external reset happens we'll * never actually make it to here. If we do make it here, just trigger * a software reset. That code will see that external reset is * configured, and it will wait for 1 second for it to take effect, then * it will do a software reset as a fallback. */ imx_wdog_cpu_reset(BUS_SPACE_PHYSADDR(sc->sc_res[MEMRES], WDOG_CR_REG)); return (FILTER_HANDLED); /* unreached */ } static int imx_wdog_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); device_set_desc(dev, "Freescale i.MX Watchdog"); return (0); } static int imx_wdog_attach(device_t dev) { struct imx_wdog_softc *sc; + pcell_t timeout; sc = device_get_softc(dev); sc->sc_dev = dev; if (bus_alloc_resources(dev, imx_wdog_spec, sc->sc_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "imx_wdt", MTX_DEF); /* * If we're configured to assert an external reset signal, set up the * hardware to do so, and install an interrupt handler whose only * purpose is to backstop the external reset. Don't worry if the * interrupt setup fails, since it's only a backstop measure. */ if (ofw_bus_has_prop(sc->sc_dev, "fsl,ext-reset-output")) { WR2(sc, WDOG_CR_REG, WDOG_CR_WDT | RD2(sc, WDOG_CR_REG)); bus_setup_intr(sc->sc_dev, sc->sc_res[IRQRES], INTR_TYPE_MISC | INTR_MPSAFE, imx_wdog_intr, NULL, sc, &sc->sc_ih); WR2(sc, WDOG_ICR_REG, WDOG_ICR_WIE); /* Enable, count is 0. */ } /* * Note whether the rom-boot so-called "power-down" watchdog is active, * so we can disable it when the regular watchdog is first enabled. */ if (RD2(sc, WDOG_MCR_REG) & WDOG_MCR_PDE) sc->sc_pde_enabled = true; EVENTHANDLER_REGISTER(watchdog_list, imx_watchdog, sc, 0); + + /* If there is a timeout-sec property, activate the watchdog. */ + if (OF_getencprop(ofw_bus_get_node(sc->sc_dev), "timeout-sec", + &timeout, sizeof(timeout)) == sizeof(timeout)) { + if (timeout < 1 || timeout > 128) { + device_printf(sc->sc_dev, "ERROR: bad timeout-sec " + "property value %u, using 128\n", timeout); + timeout = 128; + } + imx_wdog_enable(sc, timeout); + device_printf(sc->sc_dev, "watchdog enabled using " + "timeout-sec property value %u\n", timeout); + } + + /* + * The watchdog hardware cannot be disabled, so there's little point in + * coding up a detach() routine to carefully tear everything down, just + * make the device busy so that detach can't happen. + */ + device_busy(sc->sc_dev); return (0); } static device_method_t imx_wdog_methods[] = { DEVMETHOD(device_probe, imx_wdog_probe), DEVMETHOD(device_attach, imx_wdog_attach), DEVMETHOD_END }; static driver_t imx_wdog_driver = { "imx_wdog", imx_wdog_methods, sizeof(struct imx_wdog_softc), }; static devclass_t imx_wdog_devclass; -DRIVER_MODULE(imx_wdog, simplebus, imx_wdog_driver, imx_wdog_devclass, 0, 0); +EARLY_DRIVER_MODULE(imx_wdog, simplebus, imx_wdog_driver, + imx_wdog_devclass, 0, 0, BUS_PASS_TIMER); +SIMPLEBUS_PNP_INFO(compat_data); Index: stable/11/sys/modules/imx/Makefile =================================================================== --- stable/11/sys/modules/imx/Makefile (revision 346521) +++ stable/11/sys/modules/imx/Makefile (revision 346522) @@ -1,9 +1,10 @@ # $FreeBSD$ # Build modules specific to freescale/nxp imx-family SoCs. SUBDIR = \ ../ffec \ imx_i2c \ imx_spi \ + imx_wdog \ .include Index: stable/11/sys/modules/imx/imx_wdog/Makefile =================================================================== --- stable/11/sys/modules/imx/imx_wdog/Makefile (nonexistent) +++ stable/11/sys/modules/imx/imx_wdog/Makefile (revision 346522) @@ -0,0 +1,14 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/arm/freescale/imx + +KMOD= imx_wdog +SRCS= imx_wdog.c + +# Generated files... +SRCS+= \ + bus_if.h \ + device_if.h \ + ofw_bus_if.h \ + +.include Property changes on: stable/11/sys/modules/imx/imx_wdog/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11 =================================================================== --- stable/11 (revision 346521) +++ stable/11 (revision 346522) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r336070,336072-336073,336076