1*47c47feaSjsg /* $OpenBSD: power.c,v 1.10 2022/10/16 01:22:39 jsg Exp $ */
2b31099a6Sjason
3b31099a6Sjason /*
4b31099a6Sjason * Copyright (c) 2006 Jason L. Wright (jason@thought.net)
5b31099a6Sjason * All rights reserved.
6b31099a6Sjason *
7b31099a6Sjason * Redistribution and use in source and binary forms, with or without
8b31099a6Sjason * modification, are permitted provided that the following conditions
9b31099a6Sjason * are met:
10b31099a6Sjason * 1. Redistributions of source code must retain the above copyright
11b31099a6Sjason * notice, this list of conditions and the following disclaimer.
12b31099a6Sjason * 2. Redistributions in binary form must reproduce the above copyright
13b31099a6Sjason * notice, this list of conditions and the following disclaimer in the
14b31099a6Sjason * documentation and/or other materials provided with the distribution.
15b31099a6Sjason *
16b31099a6Sjason * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b31099a6Sjason * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b31099a6Sjason * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b31099a6Sjason * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20b31099a6Sjason * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21b31099a6Sjason * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22b31099a6Sjason * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23b31099a6Sjason * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24b31099a6Sjason * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25b31099a6Sjason * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b31099a6Sjason * POSSIBILITY OF SUCH DAMAGE.
27b31099a6Sjason */
28b31099a6Sjason
29b31099a6Sjason /*
30b31099a6Sjason * Driver for power-button device on U5, U10, etc.
31b31099a6Sjason */
32b31099a6Sjason
33b31099a6Sjason #include <sys/param.h>
34b31099a6Sjason #include <sys/systm.h>
35b31099a6Sjason #include <sys/kernel.h>
36b31099a6Sjason #include <sys/device.h>
37b31099a6Sjason #include <sys/conf.h>
38b31099a6Sjason #include <sys/timeout.h>
3967de6befSjason #include <sys/proc.h>
4067de6befSjason #include <sys/signalvar.h>
41b31099a6Sjason
42b31099a6Sjason #include <machine/bus.h>
43b31099a6Sjason #include <machine/autoconf.h>
44b31099a6Sjason #include <machine/openfirm.h>
45b31099a6Sjason
46b31099a6Sjason #include <sparc64/dev/ebusreg.h>
47b31099a6Sjason #include <sparc64/dev/ebusvar.h>
48b31099a6Sjason
4936a573d6Sjason #define POWER_REG 0
5036a573d6Sjason
5136a573d6Sjason #define POWER_REG_CPWR_OFF 0x00000002 /* courtesy power off */
5236a573d6Sjason #define POWER_REG_SPWR_OFF 0x00000001 /* system power off */
5336a573d6Sjason
54b31099a6Sjason struct power_softc {
55b31099a6Sjason struct device sc_dev;
56e6dbd892Skettenis bus_space_tag_t sc_iot;
57e6dbd892Skettenis bus_space_handle_t sc_ioh;
58b31099a6Sjason struct intrhand *sc_ih;
59b31099a6Sjason };
60b31099a6Sjason
61b31099a6Sjason int power_match(struct device *, void *, void *);
62b31099a6Sjason void power_attach(struct device *, struct device *, void *);
63b31099a6Sjason int power_intr(void *);
64b31099a6Sjason
65eb7eaf8dSmpi const struct cfattach power_ca = {
66b31099a6Sjason sizeof(struct power_softc), power_match, power_attach
67b31099a6Sjason };
68b31099a6Sjason
69b31099a6Sjason struct cfdriver power_cd = {
70b31099a6Sjason NULL, "power", DV_DULL
71b31099a6Sjason };
72b31099a6Sjason
73b31099a6Sjason int
power_match(struct device * parent,void * match,void * aux)74*47c47feaSjsg power_match(struct device *parent, void *match, void *aux)
75b31099a6Sjason {
76b31099a6Sjason struct ebus_attach_args *ea = aux;
77b31099a6Sjason
78b31099a6Sjason if (strcmp(ea->ea_name, "power") == 0)
79b31099a6Sjason return (1);
80b31099a6Sjason return (0);
81b31099a6Sjason }
82b31099a6Sjason
83b31099a6Sjason void
power_attach(struct device * parent,struct device * self,void * aux)84*47c47feaSjsg power_attach(struct device *parent, struct device *self, void *aux)
85b31099a6Sjason {
86b31099a6Sjason struct power_softc *sc = (void *)self;
87b31099a6Sjason struct ebus_attach_args *ea = aux;
88b31099a6Sjason
8936a573d6Sjason if (ea->ea_nregs < 1) {
9036a573d6Sjason printf(": no registers\n");
9136a573d6Sjason return;
9236a573d6Sjason }
9336a573d6Sjason
94b31099a6Sjason /* Use prom address if available, otherwise map it. */
95b31099a6Sjason if (ea->ea_nvaddrs) {
96e6dbd892Skettenis if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
97e6dbd892Skettenis BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
98b31099a6Sjason printf(": can't map PROM register space\n");
99b31099a6Sjason return;
100b31099a6Sjason }
101e6dbd892Skettenis sc->sc_iot = ea->ea_memtag;
102e6dbd892Skettenis } else if (ebus_bus_map(ea->ea_iotag, 0,
103e6dbd892Skettenis EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
104e6dbd892Skettenis ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
105e6dbd892Skettenis sc->sc_iot = ea->ea_iotag;
106e6dbd892Skettenis } else if (ebus_bus_map(ea->ea_memtag, 0,
107e6dbd892Skettenis EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
108e6dbd892Skettenis ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
109e6dbd892Skettenis sc->sc_iot = ea->ea_memtag;
110e6dbd892Skettenis } else {
111e6dbd892Skettenis printf("%s: can't map register space\n", self->dv_xname);
112b31099a6Sjason return;
113b31099a6Sjason }
114b31099a6Sjason
115b31099a6Sjason if (ea->ea_nintrs > 0 && OF_getproplen(ea->ea_node, "button") >= 0) {
116e6dbd892Skettenis sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
11767de6befSjason IPL_BIO, 0, power_intr, sc, self->dv_xname);
118b31099a6Sjason if (sc->sc_ih == NULL) {
119b31099a6Sjason printf(": can't establish interrupt\n");
120b31099a6Sjason return;
121b31099a6Sjason }
122b31099a6Sjason }
123b31099a6Sjason printf("\n");
124b31099a6Sjason }
125b31099a6Sjason
126b31099a6Sjason int
power_intr(void * vsc)127b31099a6Sjason power_intr(void *vsc)
128b31099a6Sjason {
129b2e0f490Snaddy extern int allowpowerdown;
13067de6befSjason
131b2e0f490Snaddy if (allowpowerdown == 1) {
132b2e0f490Snaddy allowpowerdown = 0;
133de4108eaSguenther prsignal(initprocess, SIGUSR2);
13467de6befSjason }
13536a573d6Sjason return (1);
136b31099a6Sjason }
137