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