1*471aeecfSnaddy /* $OpenBSD: apldog.c,v 1.4 2022/04/06 18:59:26 naddy Exp $ */
280e00d86Skettenis /*
380e00d86Skettenis * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
480e00d86Skettenis *
580e00d86Skettenis * Permission to use, copy, modify, and distribute this software for any
680e00d86Skettenis * purpose with or without fee is hereby granted, provided that the above
780e00d86Skettenis * copyright notice and this permission notice appear in all copies.
880e00d86Skettenis *
980e00d86Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1080e00d86Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1180e00d86Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1280e00d86Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1380e00d86Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1480e00d86Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1580e00d86Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1680e00d86Skettenis */
1780e00d86Skettenis
1880e00d86Skettenis #include <sys/param.h>
1980e00d86Skettenis #include <sys/systm.h>
2080e00d86Skettenis #include <sys/device.h>
2180e00d86Skettenis
2280e00d86Skettenis #include <machine/bus.h>
2380e00d86Skettenis #include <machine/fdt.h>
2480e00d86Skettenis
2580e00d86Skettenis #include <dev/ofw/openfirm.h>
2680e00d86Skettenis #include <dev/ofw/fdt.h>
2780e00d86Skettenis
2880e00d86Skettenis extern void (*cpuresetfn)(void);
2980e00d86Skettenis
3080e00d86Skettenis /*
3180e00d86Skettenis * This driver is based on preliminary device tree bindings and will
3280e00d86Skettenis * almost certainly need changes once the official bindings land in
3380e00d86Skettenis * mainline Linux. Support for these preliminary bindings will be
3480e00d86Skettenis * dropped as soon as official bindings are available.
3580e00d86Skettenis */
3680e00d86Skettenis
3780e00d86Skettenis #define WDT_CHIP_CTL 0x000c
3880e00d86Skettenis #define WDT_SYS_TMR 0x0010
3980e00d86Skettenis #define WDT_SYS_RST 0x0014
4080e00d86Skettenis #define WDT_SYS_RST_IMMEDIATE (1 << 0)
4180e00d86Skettenis #define WDT_SYS_CTL 0x001c
4280e00d86Skettenis #define WDT_SYS_CTL_ENABLE (1 << 2)
4380e00d86Skettenis
4480e00d86Skettenis #define HREAD4(sc, reg) \
4580e00d86Skettenis (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
4680e00d86Skettenis #define HWRITE4(sc, reg, val) \
4780e00d86Skettenis bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
4880e00d86Skettenis
4980e00d86Skettenis struct apldog_softc {
5080e00d86Skettenis struct device sc_dev;
5180e00d86Skettenis bus_space_tag_t sc_iot;
5280e00d86Skettenis bus_space_handle_t sc_ioh;
5380e00d86Skettenis };
5480e00d86Skettenis
5580e00d86Skettenis struct apldog_softc *apldog_sc;
5680e00d86Skettenis
5780e00d86Skettenis int apldog_match(struct device *, void *, void *);
5880e00d86Skettenis void apldog_attach(struct device *, struct device *, void *);
5980e00d86Skettenis
60*471aeecfSnaddy const struct cfattach apldog_ca = {
6180e00d86Skettenis sizeof (struct apldog_softc), apldog_match, apldog_attach
6280e00d86Skettenis };
6380e00d86Skettenis
6480e00d86Skettenis struct cfdriver apldog_cd = {
6580e00d86Skettenis NULL, "apldog", DV_DULL
6680e00d86Skettenis };
6780e00d86Skettenis
6880e00d86Skettenis void apldog_reset(void);
6980e00d86Skettenis
7080e00d86Skettenis int
apldog_match(struct device * parent,void * match,void * aux)7180e00d86Skettenis apldog_match(struct device *parent, void *match, void *aux)
7280e00d86Skettenis {
7380e00d86Skettenis struct fdt_attach_args *faa = aux;
7480e00d86Skettenis
75275f8d8dSkettenis return OF_is_compatible(faa->fa_node, "apple,wdt");
7680e00d86Skettenis }
7780e00d86Skettenis
7880e00d86Skettenis void
apldog_attach(struct device * parent,struct device * self,void * aux)7980e00d86Skettenis apldog_attach(struct device *parent, struct device *self, void *aux)
8080e00d86Skettenis {
8180e00d86Skettenis struct apldog_softc *sc = (struct apldog_softc *)self;
8280e00d86Skettenis struct fdt_attach_args *faa = aux;
8380e00d86Skettenis
8480e00d86Skettenis if (faa->fa_nreg < 1) {
8580e00d86Skettenis printf(": no registers\n");
8680e00d86Skettenis return;
8780e00d86Skettenis }
8880e00d86Skettenis
8980e00d86Skettenis sc->sc_iot = faa->fa_iot;
9080e00d86Skettenis if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
9180e00d86Skettenis faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
9280e00d86Skettenis printf(": can't map registers\n");
9380e00d86Skettenis return;
9480e00d86Skettenis }
9580e00d86Skettenis
9680e00d86Skettenis printf("\n");
9780e00d86Skettenis
9880e00d86Skettenis /* Reset the watchdog timers. */
9980e00d86Skettenis HWRITE4(sc, WDT_CHIP_CTL, 0);
10080e00d86Skettenis HWRITE4(sc, WDT_SYS_CTL, 0);
10180e00d86Skettenis
10280e00d86Skettenis apldog_sc = sc;
103a5505455Skettenis if (cpuresetfn == NULL)
10480e00d86Skettenis cpuresetfn = apldog_reset;
10580e00d86Skettenis }
10680e00d86Skettenis
10780e00d86Skettenis void
apldog_reset(void)10880e00d86Skettenis apldog_reset(void)
10980e00d86Skettenis {
11080e00d86Skettenis struct apldog_softc *sc = apldog_sc;
11180e00d86Skettenis
11280e00d86Skettenis /* Trigger a system reset. */
11380e00d86Skettenis HWRITE4(sc, WDT_SYS_RST, WDT_SYS_RST_IMMEDIATE);
11480e00d86Skettenis HWRITE4(sc, WDT_SYS_CTL, WDT_SYS_CTL_ENABLE);
11580e00d86Skettenis HWRITE4(sc, WDT_SYS_TMR, 0);
11680e00d86Skettenis
11780e00d86Skettenis delay(1000000);
11880e00d86Skettenis }
119