1 /* 2 * Copyright (c) 2015 Patrick Wildt <patrick@blueri.se> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/queue.h> 20 #include <sys/malloc.h> 21 #include <sys/device.h> 22 #include <sys/evcount.h> 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/fdt.h> 28 29 extern void (*cpuresetfn)(void); 30 31 /* registers */ 32 #define PM_RSTC 0x1c 33 #define PM_RSTS 0x20 34 #define PM_WDOG 0x24 35 36 /* bits and bytes */ 37 #define PM_PASSWORD 0x5a000000 38 #define PM_RSTC_CONFIGMASK 0x00000030 39 #define PM_RSTC_FULL_RESET 0x00000020 40 #define PM_RSTC_RESET 0x00000102 41 #define PM_WDOG_TIMEMASK 0x000fffff 42 43 #define HREAD4(sc, reg) \ 44 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 45 #define HWRITE4(sc, reg, val) \ 46 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 47 #define HSET4(sc, reg, bits) \ 48 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 49 #define HCLR4(sc, reg, bits) \ 50 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 51 52 struct bcmdog_softc { 53 struct device sc_dev; 54 bus_space_tag_t sc_iot; 55 bus_space_handle_t sc_ioh; 56 }; 57 58 struct bcmdog_softc *bcmdog_sc; 59 60 int bcmdog_match(struct device *, void *, void *); 61 void bcmdog_attach(struct device *, struct device *, void *); 62 int bcmdog_activate(struct device *, int); 63 int bcmdog_wdog_cb(void *, int); 64 void bcmdog_wdog_reset(void); 65 66 struct cfattach bcmdog_ca = { 67 sizeof (struct bcmdog_softc), bcmdog_match, bcmdog_attach, NULL, 68 bcmdog_activate 69 }; 70 71 struct cfdriver bcmdog_cd = { 72 NULL, "bcmdog", DV_DULL 73 }; 74 75 int 76 bcmdog_match(struct device *parent, void *cfdata, void *aux) 77 { 78 struct fdt_attach_args *fa = aux; 79 80 return OF_is_compatible(fa->fa_node, "brcm,bcm2835-pm-wdt"); 81 } 82 83 void 84 bcmdog_attach(struct device *parent, struct device *self, void *aux) 85 { 86 struct bcmdog_softc *sc = (struct bcmdog_softc *)self; 87 struct fdt_attach_args *fa = aux; 88 89 sc->sc_iot = fa->fa_iot; 90 91 if (bus_space_map(sc->sc_iot, fa->fa_reg[0].addr, 92 fa->fa_reg[0].size, 0, &sc->sc_ioh)) 93 panic("%s: bus_space_map failed!", __func__); 94 95 printf("\n"); 96 97 bcmdog_sc = sc; 98 cpuresetfn = bcmdog_wdog_reset; 99 100 #ifndef SMALL_KERNEL 101 wdog_register(bcmdog_wdog_cb, sc); 102 #endif 103 } 104 105 int 106 bcmdog_activate(struct device *self, int act) 107 { 108 switch (act) { 109 case DVACT_POWERDOWN: 110 #ifndef SMALL_KERNEL 111 wdog_shutdown(self); 112 #endif 113 break; 114 } 115 116 return 0; 117 } 118 119 void 120 bcmdog_wdog_set(struct bcmdog_softc *sc, uint32_t period) 121 { 122 uint32_t rstc, wdog; 123 124 if (period == 0) { 125 HWRITE4(sc, PM_RSTC, PM_RSTC_RESET | PM_PASSWORD); 126 return; 127 } 128 129 rstc = HREAD4(sc, PM_RSTC) & PM_RSTC_CONFIGMASK; 130 rstc |= PM_RSTC_FULL_RESET; 131 rstc |= PM_PASSWORD; 132 133 wdog = period & PM_WDOG_TIMEMASK; 134 wdog |= PM_PASSWORD; 135 136 HWRITE4(sc, PM_WDOG, wdog); 137 HWRITE4(sc, PM_RSTC, rstc); 138 } 139 140 int 141 bcmdog_wdog_cb(void *self, int period) 142 { 143 struct bcmdog_softc *sc = self; 144 145 bcmdog_wdog_set(sc, period << 16); 146 return period; 147 } 148 149 void 150 bcmdog_wdog_reset(void) 151 { 152 struct bcmdog_softc *sc = bcmdog_sc; 153 154 bcmdog_wdog_set(sc, 10); 155 delay(100000); 156 } 157