vexpress_sysreg.c revision 1.2 1 /* $NetBSD: vexpress_sysreg.c,v 1.2 2017/06/02 21:26:20 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: vexpress_sysreg.c,v 1.2 2017/06/02 21:26:20 jmcneill Exp $");
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37
38 #include <dev/fdt/fdtvar.h>
39
40 #define SYS_CFGDATA 0x00a0
41 #define SYS_CFGCTRL 0x00a4
42 #define SYS_CFGCTRL_START __BIT(31)
43 #define SYS_CFGCTRL_WRITE __BIT(30)
44 #define SYS_CFGCTRL_FUNCTION __BITS(25,20)
45 #define SYS_CFGCTRL_FUNCTION_SHUTDOWN 8
46 #define SYS_CFGCTRL_FUNCTION_REBOOT 9
47 #define SYS_CFGCTRL_SITE __BITS(17,16)
48 #define SYS_CFGCTRL_SITE_MB 0
49 #define SYS_CFGSTAT 0x00a8
50
51 static int vexpress_sysreg_match(device_t, cfdata_t, void *);
52 static void vexpress_sysreg_attach(device_t, device_t, void *);
53
54 static const char * const compatible[] = { "arm,vexpress-sysreg", NULL };
55
56 struct vexpress_sysreg_softc {
57 device_t sc_dev;
58 bus_space_tag_t sc_bst;
59 bus_space_handle_t sc_bsh;
60 };
61
62 CFATTACH_DECL_NEW(vexpress_sysreg, sizeof(struct vexpress_sysreg_softc),
63 vexpress_sysreg_match, vexpress_sysreg_attach, NULL, NULL);
64
65 static void
66 vexpress_sysreg_write(device_t dev, u_int func, u_int site)
67 {
68 struct vexpress_sysreg_softc * const sc = device_private(dev);
69
70 const uint32_t cfgctrl = SYS_CFGCTRL_START | SYS_CFGCTRL_WRITE |
71 __SHIFTIN(func, SYS_CFGCTRL_FUNCTION) |
72 __SHIFTIN(site, SYS_CFGCTRL_SITE);
73
74 bus_space_write_4(sc->sc_bst, sc->sc_bsh, SYS_CFGSTAT, 0);
75 bus_space_write_4(sc->sc_bst, sc->sc_bsh, SYS_CFGDATA, 0);
76 bus_space_write_4(sc->sc_bst, sc->sc_bsh, SYS_CFGCTRL, cfgctrl);
77 }
78
79 static void
80 vexpress_sysreg_reset(device_t dev)
81 {
82 delay(1000000);
83 vexpress_sysreg_write(dev, SYS_CFGCTRL_FUNCTION_REBOOT, SYS_CFGCTRL_SITE_MB);
84 }
85
86 static void
87 vexpress_sysreg_poweroff(device_t dev)
88 {
89 delay(1000000);
90 vexpress_sysreg_write(dev, SYS_CFGCTRL_FUNCTION_SHUTDOWN, SYS_CFGCTRL_SITE_MB);
91 }
92
93 static struct fdtbus_power_controller_func vexpress_sysreg_power_funcs = {
94 .reset = vexpress_sysreg_reset,
95 .poweroff = vexpress_sysreg_poweroff,
96 };
97
98 static int
99 vexpress_sysreg_match(device_t parent, cfdata_t cf, void *aux)
100 {
101 struct fdt_attach_args * const faa = aux;
102
103 return of_compatible(faa->faa_phandle, compatible) >= 0;
104 }
105
106 static void
107 vexpress_sysreg_attach(device_t parent, device_t self, void *aux)
108 {
109 struct vexpress_sysreg_softc * const sc = device_private(self);
110 struct fdt_attach_args * const faa = aux;
111 const int phandle = faa->faa_phandle;
112 bus_addr_t addr;
113 bus_size_t size;
114
115 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
116 aprint_error(": missing 'reg' property\n");
117 return;
118 }
119
120 sc->sc_dev = self;
121 sc->sc_bst = faa->faa_bst;
122 if (bus_space_map(faa->faa_bst, addr, size, 0, &sc->sc_bsh)) {
123 aprint_error(": couldn't map device\n");
124 return;
125 }
126
127 aprint_naive("\n");
128 aprint_normal("\n");
129
130 fdtbus_register_power_controller(self, phandle,
131 &vexpress_sysreg_power_funcs);
132 }
133