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