xref: /openbsd/sys/arch/armv7/vexpress/sysreg.c (revision 73471bf0)
1 /*	$OpenBSD: sysreg.c,v 1.6 2021/10/24 17:52:28 mpi Exp $	*/
2 
3 /*
4  * Copyright (c) 2015 Jonathan Gray <jsg@openbsd.org>
5  *
6  * Permission to use, copy, modify, and 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 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24 
25 #include <armv7/armv7/armv7_machdep.h>
26 
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/fdt.h>
29 
30 #define SYS_ID			0x00
31 #define SYS_PROCID0		0x84
32 #define SYS_PROCID1		0x88
33 #define SYS_CFGDATA		0xa0
34 #define SYS_CFGCTRL		0xa4
35 #define SYS_CFGSTAT		0xa8
36 
37 #define SYS_CFG_WRITE		(1 << 30)
38 #define SYS_CFG_START		(1U << 31)
39 
40 #define SYS_CFG_RESET		5
41 #define SYS_CFG_SHUTDOWN	8
42 #define SYS_CFG_REBOOT		9
43 
44 #define SYS_CFGSTAT_COMPLETE	(1 << 0)
45 #define SYS_CFGSTAT_ERROR	(1 << 1)
46 
47 struct sysreg_softc {
48 	struct device		sc_dev;
49 	bus_space_tag_t		sc_iot;
50 	bus_space_handle_t	sc_ioh;
51 };
52 
53 struct sysreg_softc *sysreg_sc;
54 
55 int sysreg_match(struct device *, void *, void *);
56 void sysreg_attach(struct device *, struct device *, void *);
57 void sysconf_function(struct sysreg_softc *, int);
58 void sysconf_reboot(void);
59 void sysconf_shutdown(void);
60 
61 const struct cfattach sysreg_ca = {
62 	sizeof (struct sysreg_softc), sysreg_match, sysreg_attach
63 };
64 
65 struct cfdriver sysreg_cd = {
66 	NULL, "sysreg", DV_DULL
67 };
68 
69 int
70 sysreg_match(struct device *parent, void *match, void *aux)
71 {
72 	struct fdt_attach_args *faa = aux;
73 
74 	return OF_is_compatible(faa->fa_node, "arm,vexpress-sysreg");
75 }
76 
77 void
78 sysreg_attach(struct device *parent, struct device *self, void *aux)
79 {
80 	struct fdt_attach_args *faa = aux;
81 	struct sysreg_softc *sc = (struct sysreg_softc *)self;
82 	uint32_t id;
83 
84 	sc->sc_iot = faa->fa_iot;
85 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
86 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
87 		panic(": bus_space_map failed!");
88 	sysreg_sc = sc;
89 
90 	id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SYS_ID);
91 	printf(": ID 0x%x", id);
92 
93 	id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SYS_PROCID0);
94 	printf(" PROCID0 0x%x\n", id);
95 
96 	cpuresetfn = sysconf_reboot;
97 	powerdownfn = sysconf_shutdown;
98 }
99 
100 void
101 sysconf_function(struct sysreg_softc *sc, int function)
102 {
103 	int dcc, site, position, device;
104 
105 	dcc = 0;
106 	site = 0;
107 	position = 0;
108 	device = 0;
109 
110 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SYS_CFGSTAT, 0);
111 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SYS_CFGCTRL,
112 	    SYS_CFG_START | SYS_CFG_WRITE |
113 	    (dcc << 26) | (function << 20) | (site << 16) |
114 	    (position << 12) | device);
115 
116 	while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SYS_CFGSTAT) &
117 	    SYS_CFGSTAT_COMPLETE) == 0);
118 
119 	if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SYS_CFGSTAT) &
120 	    SYS_CFGSTAT_ERROR)
121 		printf("SYS_CFGSTAT error\n");
122 }
123 
124 void
125 sysconf_reboot(void)
126 {
127 	struct sysreg_softc *sc = sysreg_sc;
128 
129 	if (sc == NULL)
130 		return;
131 
132 	sysconf_function(sc, SYS_CFG_REBOOT);
133 }
134 
135 void
136 sysconf_shutdown(void)
137 {
138 	struct sysreg_softc *sc = sysreg_sc;
139 
140 	if (sc == NULL)
141 		return;
142 
143 	sysconf_function(sc, SYS_CFG_SHUTDOWN);
144 }
145