diff options
| author | jmcneill <jmcneill@NetBSD.org> | 2023-04-16 16:51:38 +0000 |
|---|---|---|
| committer | jmcneill <jmcneill@NetBSD.org> | 2023-04-16 16:51:38 +0000 |
| commit | 530bf2e744db14bc5e51dfe0accbf98173a44ed0 (patch) | |
| tree | 7df47f8fff17245b472789960accc41844c3bf5e /sys/dev | |
| parent | fa24d106cb14c6e8e5903e1f60e0e3b971f41c35 (diff) | |
Separate DesignWare watchdog driver and FDT glue.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/fdt/dwcwdt_fdt.c | 143 | ||||
| -rw-r--r-- | sys/dev/fdt/files.fdt | 3 | ||||
| -rw-r--r-- | sys/dev/ic/dwc_wdt.c | 173 | ||||
| -rw-r--r-- | sys/dev/ic/dwc_wdt_var.h | 42 |
4 files changed, 224 insertions, 137 deletions
diff --git a/sys/dev/fdt/dwcwdt_fdt.c b/sys/dev/fdt/dwcwdt_fdt.c index c993e5d9527..658e78b2c9a 100644 --- a/sys/dev/fdt/dwcwdt_fdt.c +++ b/sys/dev/fdt/dwcwdt_fdt.c @@ -1,7 +1,7 @@ -/* $NetBSD: dwcwdt_fdt.c,v 1.5 2021/01/27 03:10:21 thorpej Exp $ */ +/* $NetBSD: dwcwdt_fdt.c,v 1.6 2023/04/16 16:51:38 jmcneill Exp $ */ /*- - * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> + * Copyright (c) 2018, 2023 Jared McNeill <jmcneill@invisible.ca> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dwcwdt_fdt.c,v 1.5 2021/01/27 03:10:21 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwcwdt_fdt.c,v 1.6 2023/04/16 16:51:38 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -38,133 +38,17 @@ __KERNEL_RCSID(0, "$NetBSD: dwcwdt_fdt.c,v 1.5 2021/01/27 03:10:21 thorpej Exp $ #include <sys/wdog.h> #include <dev/sysmon/sysmonvar.h> +#include <dev/ic/dwc_wdt_var.h> #include <dev/fdt/fdtvar.h> -#define WDT_CR 0x00 -#define WDT_CR_RST_PULSE_LENGTH __BITS(4,2) -#define WDT_CR_RESP_MODE __BIT(1) -#define WDT_CR_WDT_EN __BIT(0) - -#define WDT_TORR 0x04 -#define WDT_TORR_TIMEOUT_PERIOD __BITS(3,0) - -#define WDT_CCVR 0x08 - -#define WDT_CRR 0x0c -#define WDT_CRR_CNT_RESTART __BITS(7,0) -#define WDT_CRR_CNT_RESTART_MAGIC 0x76 - -#define WDT_STAT 0x10 -#define WDT_STAT_WDT_STATUS __BIT(0) - -#define WDT_EOI 0x14 -#define WDT_EOI_WDT_INT_CLR __BIT(0) - -static const uint32_t wdt_torr[] = { - 0x0000ffff, - 0x0001ffff, - 0x0003ffff, - 0x0007ffff, - 0x000fffff, - 0x001fffff, - 0x003fffff, - 0x007fffff, - 0x00ffffff, - 0x01ffffff, - 0x03ffffff, - 0x07ffffff, - 0x0fffffff, - 0x1fffffff, - 0x3fffffff, - 0x7fffffff, -}; - -#define DWCWDT_PERIOD_DEFAULT 15 - static const struct device_compatible_entry compat_data[] = { { .compat = "snps,dw-wdt" }, DEVICE_COMPAT_EOL }; -struct dwcwdt_softc { - device_t sc_dev; - bus_space_tag_t sc_bst; - bus_space_handle_t sc_bsh; - struct sysmon_wdog sc_smw; - u_int sc_clkrate; -}; - -#define RD4(sc, reg) \ - bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) -#define WR4(sc, reg, val) \ - bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) - -static int -dwcwdt_map_period(struct dwcwdt_softc *sc, u_int period, - u_int *aperiod) -{ - int i; - - if (period == 0) - return -1; - - for (i = 0; i < __arraycount(wdt_torr); i++) { - const u_int ms = (u_int)((((uint64_t)wdt_torr[i] + 1) * 1000) / sc->sc_clkrate); - if (ms >= period * 1000) { - *aperiod = ms / 1000; - return i; - } - } - - return -1; -} - -static int -dwcwdt_tickle(struct sysmon_wdog *smw) -{ - struct dwcwdt_softc * const sc = smw->smw_cookie; - const uint32_t crr = - __SHIFTIN(WDT_CRR_CNT_RESTART_MAGIC, WDT_CRR_CNT_RESTART); - - WR4(sc, WDT_CRR, crr); - - return 0; -} - static int -dwcwdt_setmode(struct sysmon_wdog *smw) -{ - struct dwcwdt_softc * const sc = smw->smw_cookie; - uint32_t cr, torr; - int intv; - - if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { - /* Watchdog can only be disarmed by a reset */ - return EIO; - } - - if (smw->smw_period == WDOG_PERIOD_DEFAULT) - smw->smw_period = DWCWDT_PERIOD_DEFAULT; - - intv = dwcwdt_map_period(sc, smw->smw_period, - &sc->sc_smw.smw_period); - if (intv == -1) - return EINVAL; - - torr = __SHIFTIN(intv, WDT_TORR_TIMEOUT_PERIOD); - WR4(sc, WDT_TORR, torr); - dwcwdt_tickle(smw); - cr = RD4(sc, WDT_CR); - cr &= ~WDT_CR_RESP_MODE; - cr |= WDT_CR_WDT_EN; - WR4(sc, WDT_CR, cr); - - return 0; -} - -static int -dwcwdt_match(device_t parent, cfdata_t cf, void *aux) +dwcwdt_fdt_match(device_t parent, cfdata_t cf, void *aux) { struct fdt_attach_args * const faa = aux; @@ -172,7 +56,7 @@ dwcwdt_match(device_t parent, cfdata_t cf, void *aux) } static void -dwcwdt_attach(device_t parent, device_t self, void *aux) +dwcwdt_fdt_attach(device_t parent, device_t self, void *aux) { struct dwcwdt_softc * const sc = device_private(self); struct fdt_attach_args * const faa = aux; @@ -213,19 +97,8 @@ dwcwdt_attach(device_t parent, device_t self, void *aux) aprint_naive("\n"); aprint_normal(": DesignWare Watchdog Timer\n"); - sc->sc_smw.smw_name = device_xname(self); - sc->sc_smw.smw_cookie = sc; - sc->sc_smw.smw_period = DWCWDT_PERIOD_DEFAULT; - sc->sc_smw.smw_setmode = dwcwdt_setmode; - sc->sc_smw.smw_tickle = dwcwdt_tickle; - - aprint_normal_dev(self, - "default watchdog period is %u seconds\n", - sc->sc_smw.smw_period); - - if (sysmon_wdog_register(&sc->sc_smw) != 0) - aprint_error_dev(self, "couldn't register with sysmon\n"); + dwcwdt_init(sc); } CFATTACH_DECL_NEW(dwcwdt_fdt, sizeof(struct dwcwdt_softc), - dwcwdt_match, dwcwdt_attach, NULL, NULL); + dwcwdt_fdt_match, dwcwdt_fdt_attach, NULL, NULL); diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index 038e6880f2b..0784e22903e 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,4 +1,4 @@ -# $NetBSD: files.fdt,v 1.67 2023/04/07 08:55:31 skrll Exp $ +# $NetBSD: files.fdt,v 1.68 2023/04/16 16:51:38 jmcneill Exp $ include "external/bsd/libfdt/conf/files.libfdt" @@ -162,7 +162,6 @@ attach dwcmmc at fdt with dwcmmc_fdt file dev/fdt/dwcmmc_fdt.c dwcmmc_fdt # Designware Watchdog Timer -device dwcwdt: sysmon_wdog attach dwcwdt at fdt with dwcwdt_fdt file dev/fdt/dwcwdt_fdt.c dwcwdt_fdt diff --git a/sys/dev/ic/dwc_wdt.c b/sys/dev/ic/dwc_wdt.c new file mode 100644 index 00000000000..89d3632e273 --- /dev/null +++ b/sys/dev/ic/dwc_wdt.c @@ -0,0 +1,173 @@ +/* $NetBSD: dwc_wdt.c,v 1.1 2023/04/16 16:51:38 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018, 2023 Jared McNeill <jmcneill@invisible.ca> + * 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: dwc_wdt.c,v 1.1 2023/04/16 16:51:38 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/mutex.h> +#include <sys/wdog.h> + +#include <dev/sysmon/sysmonvar.h> +#include <dev/ic/dwc_wdt_var.h> + +#define WDT_CR 0x00 +#define WDT_CR_RST_PULSE_LENGTH __BITS(4,2) +#define WDT_CR_RESP_MODE __BIT(1) +#define WDT_CR_WDT_EN __BIT(0) + +#define WDT_TORR 0x04 +#define WDT_TORR_TIMEOUT_PERIOD __BITS(3,0) + +#define WDT_CCVR 0x08 + +#define WDT_CRR 0x0c +#define WDT_CRR_CNT_RESTART __BITS(7,0) +#define WDT_CRR_CNT_RESTART_MAGIC 0x76 + +#define WDT_STAT 0x10 +#define WDT_STAT_WDT_STATUS __BIT(0) + +#define WDT_EOI 0x14 +#define WDT_EOI_WDT_INT_CLR __BIT(0) + +static const uint32_t wdt_torr[] = { + 0x0000ffff, + 0x0001ffff, + 0x0003ffff, + 0x0007ffff, + 0x000fffff, + 0x001fffff, + 0x003fffff, + 0x007fffff, + 0x00ffffff, + 0x01ffffff, + 0x03ffffff, + 0x07ffffff, + 0x0fffffff, + 0x1fffffff, + 0x3fffffff, + 0x7fffffff, +}; + +#define DWCWDT_PERIOD_DEFAULT 15 + +#define RD4(sc, reg) \ + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) +#define WR4(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) + +static int +dwcwdt_map_period(struct dwcwdt_softc *sc, u_int period, + u_int *aperiod) +{ + int i; + + if (period == 0) + return -1; + + for (i = 0; i < __arraycount(wdt_torr); i++) { + const u_int ms = (u_int)((((uint64_t)wdt_torr[i] + 1) * 1000) / sc->sc_clkrate); + if (ms >= period * 1000) { + *aperiod = ms / 1000; + return i; + } + } + + return -1; +} + +static int +dwcwdt_tickle(struct sysmon_wdog *smw) +{ + struct dwcwdt_softc * const sc = smw->smw_cookie; + const uint32_t crr = + __SHIFTIN(WDT_CRR_CNT_RESTART_MAGIC, WDT_CRR_CNT_RESTART); + + WR4(sc, WDT_CRR, crr); + + return 0; +} + +static int +dwcwdt_setmode(struct sysmon_wdog *smw) +{ + struct dwcwdt_softc * const sc = smw->smw_cookie; + uint32_t cr, torr; + int intv; + + if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { + /* Watchdog can only be disarmed by a reset */ + return EIO; + } + + if (smw->smw_period == WDOG_PERIOD_DEFAULT) + smw->smw_period = DWCWDT_PERIOD_DEFAULT; + + intv = dwcwdt_map_period(sc, smw->smw_period, + &sc->sc_smw.smw_period); + if (intv == -1) + return EINVAL; + + torr = __SHIFTIN(intv, WDT_TORR_TIMEOUT_PERIOD); + WR4(sc, WDT_TORR, torr); + dwcwdt_tickle(smw); + cr = RD4(sc, WDT_CR); + cr &= ~WDT_CR_RESP_MODE; + cr |= WDT_CR_WDT_EN; + WR4(sc, WDT_CR, cr); + + return 0; +} + +void +dwcwdt_init(struct dwcwdt_softc *sc) +{ + if (sc->sc_clkrate == 0) { + aprint_error_dev(sc->sc_dev, "clock rate not specified\n"); + return; + } + + sc->sc_smw.smw_name = device_xname(sc->sc_dev); + sc->sc_smw.smw_cookie = sc; + sc->sc_smw.smw_period = DWCWDT_PERIOD_DEFAULT; + sc->sc_smw.smw_setmode = dwcwdt_setmode; + sc->sc_smw.smw_tickle = dwcwdt_tickle; + + aprint_normal_dev(sc->sc_dev, + "default watchdog period is %u seconds\n", + sc->sc_smw.smw_period); + + if (sysmon_wdog_register(&sc->sc_smw) != 0) { + aprint_error_dev(sc->sc_dev, "couldn't register with sysmon\n"); + } +} diff --git a/sys/dev/ic/dwc_wdt_var.h b/sys/dev/ic/dwc_wdt_var.h new file mode 100644 index 00000000000..d0345350c81 --- /dev/null +++ b/sys/dev/ic/dwc_wdt_var.h @@ -0,0 +1,42 @@ +/* $NetBSD: dwc_wdt_var.h,v 1.1 2023/04/16 16:51:38 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018, 2023 Jared McNeill <jmcneill@invisible.ca> + * 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. + */ + +#ifndef _DWC_WDT_VAR_H +#define _DWC_WDT_VAR_H + +struct dwcwdt_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + struct sysmon_wdog sc_smw; + u_int sc_clkrate; +}; + +void dwcwdt_init(struct dwcwdt_softc *); + +#endif /* !_DWC_WDT_VAR_H */ |
