xref: /openbsd-src/sys/arch/armv7/xilinx/zqreset.c (revision 5b874c1196a514aa442de1f3320274d89766b2d8)
1 /*	$OpenBSD: zqreset.c,v 1.1 2021/04/30 13:20:14 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2021 Visa Hankala
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for Xilinx Zynq-7000 reset controller.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/mutex.h>
27 
28 #include <machine/bus.h>
29 #include <machine/fdt.h>
30 
31 #include <dev/ofw/fdt.h>
32 #include <dev/ofw/openfirm.h>
33 #include <dev/ofw/ofw_misc.h>
34 
35 #include <armv7/xilinx/slcreg.h>
36 
37 extern void (*cpuresetfn)(void);
38 
39 struct zqreset_softc {
40 	struct device		sc_dev;
41 	struct regmap		*sc_rm;
42 };
43 
44 int	zqreset_match(struct device *, void *, void *);
45 void	zqreset_attach(struct device *, struct device *, void *);
46 
47 void	zqreset_cpureset(void);
48 
49 const struct cfattach zqreset_ca = {
50 	sizeof(struct zqreset_softc), zqreset_match, zqreset_attach
51 };
52 
53 struct cfdriver zqreset_cd = {
54 	NULL, "zqreset", DV_DULL
55 };
56 
57 struct zqreset_softc	*zqreset_sc;
58 
59 struct mutex	zynq_slcr_lock = MUTEX_INITIALIZER(IPL_HIGH);
60 
61 int
zqreset_match(struct device * parent,void * match,void * aux)62 zqreset_match(struct device *parent, void *match, void *aux)
63 {
64 	struct fdt_attach_args *faa = aux;
65 
66 	return OF_is_compatible(faa->fa_node, "xlnx,zynq-reset");
67 }
68 
69 void
zqreset_attach(struct device * parent,struct device * self,void * aux)70 zqreset_attach(struct device *parent, struct device *self, void *aux)
71 {
72 	struct fdt_attach_args *faa = aux;
73 	struct zqreset_softc *sc = (struct zqreset_softc *)self;
74 
75 	sc->sc_rm = regmap_bynode(OF_parent(faa->fa_node));
76 	if (sc->sc_rm == NULL) {
77 		printf(": can't get regmap\n");
78 		return;
79 	}
80 
81 	printf("\n");
82 
83 	zqreset_sc = sc;
84 	cpuresetfn = zqreset_cpureset;
85 }
86 
87 void
zqreset_cpureset(void)88 zqreset_cpureset(void)
89 {
90 	struct zqreset_softc *sc = zqreset_sc;
91 
92 	mtx_enter(&zynq_slcr_lock);
93 	zynq_slcr_write(sc->sc_rm, SLCR_PSS_RST_CTRL,
94 	    SLCR_PSS_RST_CTRL_SOFT_RST);
95 	mtx_leave(&zynq_slcr_lock);
96 }
97 
98 uint32_t
zynq_slcr_read(struct regmap * rm,uint32_t reg)99 zynq_slcr_read(struct regmap *rm, uint32_t reg)
100 {
101 	return regmap_read_4(rm, reg);
102 }
103 
104 void
zynq_slcr_write(struct regmap * rm,uint32_t reg,uint32_t val)105 zynq_slcr_write(struct regmap *rm, uint32_t reg, uint32_t val)
106 {
107 	MUTEX_ASSERT_LOCKED(&zynq_slcr_lock);
108 
109 	regmap_write_4(rm, SLCR_UNLOCK, SLCR_UNLOCK_KEY);
110 	regmap_write_4(rm, reg, val);
111 	regmap_write_4(rm, SLCR_LOCK, SLCR_LOCK_KEY);
112 }
113