1 /* $OpenBSD: exdog.c,v 1.6 2017/03/09 20:07:35 kettenis 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/queue.h> 21 #include <sys/malloc.h> 22 #include <sys/device.h> 23 #include <sys/evcount.h> 24 #include <sys/socket.h> 25 #include <sys/timeout.h> 26 27 #include <machine/intr.h> 28 #include <machine/bus.h> 29 #include <machine/fdt.h> 30 31 #include <armv7/armv7/armv7_machdep.h> 32 33 #include <dev/ofw/openfirm.h> 34 #include <dev/ofw/fdt.h> 35 36 /* registers */ 37 #define WTCON 0x00 38 #define WTDAT 0x04 39 #define WTCNT 0x08 40 #define WTCLRINT 0x0C 41 42 /* bits and bytes */ 43 #define WTCON_RESET (1 << 0) 44 #define WTCON_INT (1 << 2) 45 #define WTCON_CLKSEL_16 (0x0 << 3) 46 #define WTCON_CLKSEL_32 (0x1 << 3) 47 #define WTCON_CLKSEL_64 (0x2 << 3) 48 #define WTCON_CLKSEL_128 (0x3 << 3) 49 #define WTCON_EN (1 << 5) 50 #define WTCON_PRESCALER(x) (((x) & 0xff) << 8) 51 52 struct exdog_softc { 53 struct device sc_dev; 54 bus_space_tag_t sc_iot; 55 bus_space_handle_t sc_ioh; 56 }; 57 58 struct exdog_softc *exdog_sc; 59 60 int exdog_match(struct device *parent, void *v, void *aux); 61 void exdog_attach(struct device *parent, struct device *self, void *args); 62 void exdog_stop(void); 63 void exdog_reset(void); 64 65 struct cfattach exdog_ca = { 66 sizeof (struct exdog_softc), exdog_match, exdog_attach 67 }; 68 69 struct cfdriver exdog_cd = { 70 NULL, "exdog", DV_DULL 71 }; 72 73 int 74 exdog_match(struct device *parent, void *cfdata, void *aux) 75 { 76 struct fdt_attach_args *fa = aux; 77 78 return (OF_is_compatible(fa->fa_node, "samsung,exynos5250-wdt") || 79 OF_is_compatible(fa->fa_node, "samsung,exynos5420-wdt")); 80 } 81 82 void 83 exdog_attach(struct device *parent, struct device *self, void *aux) 84 { 85 struct exdog_softc *sc = (struct exdog_softc *)self; 86 struct fdt_attach_args *fa = aux; 87 88 sc->sc_iot = fa->fa_iot; 89 90 if (bus_space_map(sc->sc_iot, fa->fa_reg[0].addr, 91 fa->fa_reg[0].size, 0, &sc->sc_ioh)) 92 panic("%s: bus_space_map failed!", __func__); 93 94 printf("\n"); 95 96 exdog_sc = sc; 97 if (cpuresetfn == NULL) 98 cpuresetfn = exdog_reset; 99 } 100 101 void 102 exdog_stop(void) 103 { 104 uint32_t wtcon; 105 106 if (exdog_sc == NULL) 107 return; 108 109 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON); 110 111 wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); 112 113 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon); 114 } 115 116 void 117 exdog_reset(void) 118 { 119 uint32_t wtcon; 120 121 if (exdog_sc == NULL) 122 return; 123 124 /* disable watchdog */ 125 exdog_stop(); 126 127 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON); 128 129 wtcon |= WTCON_EN | WTCON_CLKSEL_128; 130 wtcon &= ~WTCON_INT; 131 wtcon |= WTCON_RESET; 132 wtcon |= WTCON_PRESCALER(0xff); 133 134 /* set timeout to 1 */ 135 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTDAT, 1); 136 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCNT, 1); 137 138 /* kick off the watchdog */ 139 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon); 140 141 delay(100000); 142 } 143