1 /* $OpenBSD: exdog.c,v 1.8 2021/10/24 17:52:27 mpi Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <machine/bus.h> 23 #include <machine/fdt.h> 24 25 #include <armv7/armv7/armv7_machdep.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/fdt.h> 29 30 /* registers */ 31 #define WTCON 0x00 32 #define WTDAT 0x04 33 #define WTCNT 0x08 34 #define WTCLRINT 0x0C 35 36 /* bits and bytes */ 37 #define WTCON_RESET (1 << 0) 38 #define WTCON_INT (1 << 2) 39 #define WTCON_CLKSEL_16 (0x0 << 3) 40 #define WTCON_CLKSEL_32 (0x1 << 3) 41 #define WTCON_CLKSEL_64 (0x2 << 3) 42 #define WTCON_CLKSEL_128 (0x3 << 3) 43 #define WTCON_EN (1 << 5) 44 #define WTCON_PRESCALER(x) (((x) & 0xff) << 8) 45 46 struct exdog_softc { 47 struct device sc_dev; 48 bus_space_tag_t sc_iot; 49 bus_space_handle_t sc_ioh; 50 }; 51 52 struct exdog_softc *exdog_sc; 53 54 int exdog_match(struct device *parent, void *v, void *aux); 55 void exdog_attach(struct device *parent, struct device *self, void *args); 56 void exdog_stop(void); 57 void exdog_reset(void); 58 59 const struct cfattach exdog_ca = { 60 sizeof (struct exdog_softc), exdog_match, exdog_attach 61 }; 62 63 struct cfdriver exdog_cd = { 64 NULL, "exdog", DV_DULL 65 }; 66 67 int 68 exdog_match(struct device *parent, void *cfdata, void *aux) 69 { 70 struct fdt_attach_args *fa = aux; 71 72 return (OF_is_compatible(fa->fa_node, "samsung,exynos5250-wdt") || 73 OF_is_compatible(fa->fa_node, "samsung,exynos5420-wdt")); 74 } 75 76 void 77 exdog_attach(struct device *parent, struct device *self, void *aux) 78 { 79 struct exdog_softc *sc = (struct exdog_softc *)self; 80 struct fdt_attach_args *fa = aux; 81 82 sc->sc_iot = fa->fa_iot; 83 84 if (bus_space_map(sc->sc_iot, fa->fa_reg[0].addr, 85 fa->fa_reg[0].size, 0, &sc->sc_ioh)) 86 panic("%s: bus_space_map failed!", __func__); 87 88 printf("\n"); 89 90 exdog_sc = sc; 91 if (cpuresetfn == NULL) 92 cpuresetfn = exdog_reset; 93 } 94 95 void 96 exdog_stop(void) 97 { 98 uint32_t wtcon; 99 100 if (exdog_sc == NULL) 101 return; 102 103 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON); 104 105 wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); 106 107 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon); 108 } 109 110 void 111 exdog_reset(void) 112 { 113 uint32_t wtcon; 114 115 if (exdog_sc == NULL) 116 return; 117 118 /* disable watchdog */ 119 exdog_stop(); 120 121 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON); 122 123 wtcon |= WTCON_EN | WTCON_CLKSEL_128; 124 wtcon &= ~WTCON_INT; 125 wtcon |= WTCON_RESET; 126 wtcon |= WTCON_PRESCALER(0xff); 127 128 /* set timeout to 1 */ 129 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTDAT, 1); 130 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCNT, 1); 131 132 /* kick off the watchdog */ 133 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon); 134 135 delay(100000); 136 } 137