1*10f5d857Sjmcneill /* $NetBSD: dwc_wdt.c,v 1.1 2023/04/16 16:51:38 jmcneill Exp $ */
2*10f5d857Sjmcneill
3*10f5d857Sjmcneill /*-
4*10f5d857Sjmcneill * Copyright (c) 2018, 2023 Jared McNeill <jmcneill@invisible.ca>
5*10f5d857Sjmcneill * All rights reserved.
6*10f5d857Sjmcneill *
7*10f5d857Sjmcneill * Redistribution and use in source and binary forms, with or without
8*10f5d857Sjmcneill * modification, are permitted provided that the following conditions
9*10f5d857Sjmcneill * are met:
10*10f5d857Sjmcneill * 1. Redistributions of source code must retain the above copyright
11*10f5d857Sjmcneill * notice, this list of conditions and the following disclaimer.
12*10f5d857Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
13*10f5d857Sjmcneill * notice, this list of conditions and the following disclaimer in the
14*10f5d857Sjmcneill * documentation and/or other materials provided with the distribution.
15*10f5d857Sjmcneill *
16*10f5d857Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*10f5d857Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*10f5d857Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*10f5d857Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*10f5d857Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*10f5d857Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*10f5d857Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*10f5d857Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*10f5d857Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*10f5d857Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*10f5d857Sjmcneill * SUCH DAMAGE.
27*10f5d857Sjmcneill */
28*10f5d857Sjmcneill
29*10f5d857Sjmcneill #include <sys/cdefs.h>
30*10f5d857Sjmcneill __KERNEL_RCSID(0, "$NetBSD: dwc_wdt.c,v 1.1 2023/04/16 16:51:38 jmcneill Exp $");
31*10f5d857Sjmcneill
32*10f5d857Sjmcneill #include <sys/param.h>
33*10f5d857Sjmcneill #include <sys/bus.h>
34*10f5d857Sjmcneill #include <sys/device.h>
35*10f5d857Sjmcneill #include <sys/intr.h>
36*10f5d857Sjmcneill #include <sys/systm.h>
37*10f5d857Sjmcneill #include <sys/mutex.h>
38*10f5d857Sjmcneill #include <sys/wdog.h>
39*10f5d857Sjmcneill
40*10f5d857Sjmcneill #include <dev/sysmon/sysmonvar.h>
41*10f5d857Sjmcneill #include <dev/ic/dwc_wdt_var.h>
42*10f5d857Sjmcneill
43*10f5d857Sjmcneill #define WDT_CR 0x00
44*10f5d857Sjmcneill #define WDT_CR_RST_PULSE_LENGTH __BITS(4,2)
45*10f5d857Sjmcneill #define WDT_CR_RESP_MODE __BIT(1)
46*10f5d857Sjmcneill #define WDT_CR_WDT_EN __BIT(0)
47*10f5d857Sjmcneill
48*10f5d857Sjmcneill #define WDT_TORR 0x04
49*10f5d857Sjmcneill #define WDT_TORR_TIMEOUT_PERIOD __BITS(3,0)
50*10f5d857Sjmcneill
51*10f5d857Sjmcneill #define WDT_CCVR 0x08
52*10f5d857Sjmcneill
53*10f5d857Sjmcneill #define WDT_CRR 0x0c
54*10f5d857Sjmcneill #define WDT_CRR_CNT_RESTART __BITS(7,0)
55*10f5d857Sjmcneill #define WDT_CRR_CNT_RESTART_MAGIC 0x76
56*10f5d857Sjmcneill
57*10f5d857Sjmcneill #define WDT_STAT 0x10
58*10f5d857Sjmcneill #define WDT_STAT_WDT_STATUS __BIT(0)
59*10f5d857Sjmcneill
60*10f5d857Sjmcneill #define WDT_EOI 0x14
61*10f5d857Sjmcneill #define WDT_EOI_WDT_INT_CLR __BIT(0)
62*10f5d857Sjmcneill
63*10f5d857Sjmcneill static const uint32_t wdt_torr[] = {
64*10f5d857Sjmcneill 0x0000ffff,
65*10f5d857Sjmcneill 0x0001ffff,
66*10f5d857Sjmcneill 0x0003ffff,
67*10f5d857Sjmcneill 0x0007ffff,
68*10f5d857Sjmcneill 0x000fffff,
69*10f5d857Sjmcneill 0x001fffff,
70*10f5d857Sjmcneill 0x003fffff,
71*10f5d857Sjmcneill 0x007fffff,
72*10f5d857Sjmcneill 0x00ffffff,
73*10f5d857Sjmcneill 0x01ffffff,
74*10f5d857Sjmcneill 0x03ffffff,
75*10f5d857Sjmcneill 0x07ffffff,
76*10f5d857Sjmcneill 0x0fffffff,
77*10f5d857Sjmcneill 0x1fffffff,
78*10f5d857Sjmcneill 0x3fffffff,
79*10f5d857Sjmcneill 0x7fffffff,
80*10f5d857Sjmcneill };
81*10f5d857Sjmcneill
82*10f5d857Sjmcneill #define DWCWDT_PERIOD_DEFAULT 15
83*10f5d857Sjmcneill
84*10f5d857Sjmcneill #define RD4(sc, reg) \
85*10f5d857Sjmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
86*10f5d857Sjmcneill #define WR4(sc, reg, val) \
87*10f5d857Sjmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
88*10f5d857Sjmcneill
89*10f5d857Sjmcneill static int
dwcwdt_map_period(struct dwcwdt_softc * sc,u_int period,u_int * aperiod)90*10f5d857Sjmcneill dwcwdt_map_period(struct dwcwdt_softc *sc, u_int period,
91*10f5d857Sjmcneill u_int *aperiod)
92*10f5d857Sjmcneill {
93*10f5d857Sjmcneill int i;
94*10f5d857Sjmcneill
95*10f5d857Sjmcneill if (period == 0)
96*10f5d857Sjmcneill return -1;
97*10f5d857Sjmcneill
98*10f5d857Sjmcneill for (i = 0; i < __arraycount(wdt_torr); i++) {
99*10f5d857Sjmcneill const u_int ms = (u_int)((((uint64_t)wdt_torr[i] + 1) * 1000) / sc->sc_clkrate);
100*10f5d857Sjmcneill if (ms >= period * 1000) {
101*10f5d857Sjmcneill *aperiod = ms / 1000;
102*10f5d857Sjmcneill return i;
103*10f5d857Sjmcneill }
104*10f5d857Sjmcneill }
105*10f5d857Sjmcneill
106*10f5d857Sjmcneill return -1;
107*10f5d857Sjmcneill }
108*10f5d857Sjmcneill
109*10f5d857Sjmcneill static int
dwcwdt_tickle(struct sysmon_wdog * smw)110*10f5d857Sjmcneill dwcwdt_tickle(struct sysmon_wdog *smw)
111*10f5d857Sjmcneill {
112*10f5d857Sjmcneill struct dwcwdt_softc * const sc = smw->smw_cookie;
113*10f5d857Sjmcneill const uint32_t crr =
114*10f5d857Sjmcneill __SHIFTIN(WDT_CRR_CNT_RESTART_MAGIC, WDT_CRR_CNT_RESTART);
115*10f5d857Sjmcneill
116*10f5d857Sjmcneill WR4(sc, WDT_CRR, crr);
117*10f5d857Sjmcneill
118*10f5d857Sjmcneill return 0;
119*10f5d857Sjmcneill }
120*10f5d857Sjmcneill
121*10f5d857Sjmcneill static int
dwcwdt_setmode(struct sysmon_wdog * smw)122*10f5d857Sjmcneill dwcwdt_setmode(struct sysmon_wdog *smw)
123*10f5d857Sjmcneill {
124*10f5d857Sjmcneill struct dwcwdt_softc * const sc = smw->smw_cookie;
125*10f5d857Sjmcneill uint32_t cr, torr;
126*10f5d857Sjmcneill int intv;
127*10f5d857Sjmcneill
128*10f5d857Sjmcneill if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
129*10f5d857Sjmcneill /* Watchdog can only be disarmed by a reset */
130*10f5d857Sjmcneill return EIO;
131*10f5d857Sjmcneill }
132*10f5d857Sjmcneill
133*10f5d857Sjmcneill if (smw->smw_period == WDOG_PERIOD_DEFAULT)
134*10f5d857Sjmcneill smw->smw_period = DWCWDT_PERIOD_DEFAULT;
135*10f5d857Sjmcneill
136*10f5d857Sjmcneill intv = dwcwdt_map_period(sc, smw->smw_period,
137*10f5d857Sjmcneill &sc->sc_smw.smw_period);
138*10f5d857Sjmcneill if (intv == -1)
139*10f5d857Sjmcneill return EINVAL;
140*10f5d857Sjmcneill
141*10f5d857Sjmcneill torr = __SHIFTIN(intv, WDT_TORR_TIMEOUT_PERIOD);
142*10f5d857Sjmcneill WR4(sc, WDT_TORR, torr);
143*10f5d857Sjmcneill dwcwdt_tickle(smw);
144*10f5d857Sjmcneill cr = RD4(sc, WDT_CR);
145*10f5d857Sjmcneill cr &= ~WDT_CR_RESP_MODE;
146*10f5d857Sjmcneill cr |= WDT_CR_WDT_EN;
147*10f5d857Sjmcneill WR4(sc, WDT_CR, cr);
148*10f5d857Sjmcneill
149*10f5d857Sjmcneill return 0;
150*10f5d857Sjmcneill }
151*10f5d857Sjmcneill
152*10f5d857Sjmcneill void
dwcwdt_init(struct dwcwdt_softc * sc)153*10f5d857Sjmcneill dwcwdt_init(struct dwcwdt_softc *sc)
154*10f5d857Sjmcneill {
155*10f5d857Sjmcneill if (sc->sc_clkrate == 0) {
156*10f5d857Sjmcneill aprint_error_dev(sc->sc_dev, "clock rate not specified\n");
157*10f5d857Sjmcneill return;
158*10f5d857Sjmcneill }
159*10f5d857Sjmcneill
160*10f5d857Sjmcneill sc->sc_smw.smw_name = device_xname(sc->sc_dev);
161*10f5d857Sjmcneill sc->sc_smw.smw_cookie = sc;
162*10f5d857Sjmcneill sc->sc_smw.smw_period = DWCWDT_PERIOD_DEFAULT;
163*10f5d857Sjmcneill sc->sc_smw.smw_setmode = dwcwdt_setmode;
164*10f5d857Sjmcneill sc->sc_smw.smw_tickle = dwcwdt_tickle;
165*10f5d857Sjmcneill
166*10f5d857Sjmcneill aprint_normal_dev(sc->sc_dev,
167*10f5d857Sjmcneill "default watchdog period is %u seconds\n",
168*10f5d857Sjmcneill sc->sc_smw.smw_period);
169*10f5d857Sjmcneill
170*10f5d857Sjmcneill if (sysmon_wdog_register(&sc->sc_smw) != 0) {
171*10f5d857Sjmcneill aprint_error_dev(sc->sc_dev, "couldn't register with sysmon\n");
172*10f5d857Sjmcneill }
173*10f5d857Sjmcneill }
174