xref: /openbsd-src/sys/arch/arm64/dev/apldog.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
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