1 /* $OpenBSD: power.c,v 1.10 2022/10/16 01:22:39 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2006 Jason L. Wright (jason@thought.net)
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
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Driver for power-button device on U5, U10, etc.
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/device.h>
37 #include <sys/conf.h>
38 #include <sys/timeout.h>
39 #include <sys/proc.h>
40 #include <sys/signalvar.h>
41
42 #include <machine/bus.h>
43 #include <machine/autoconf.h>
44 #include <machine/openfirm.h>
45
46 #include <sparc64/dev/ebusreg.h>
47 #include <sparc64/dev/ebusvar.h>
48
49 #define POWER_REG 0
50
51 #define POWER_REG_CPWR_OFF 0x00000002 /* courtesy power off */
52 #define POWER_REG_SPWR_OFF 0x00000001 /* system power off */
53
54 struct power_softc {
55 struct device sc_dev;
56 bus_space_tag_t sc_iot;
57 bus_space_handle_t sc_ioh;
58 struct intrhand *sc_ih;
59 };
60
61 int power_match(struct device *, void *, void *);
62 void power_attach(struct device *, struct device *, void *);
63 int power_intr(void *);
64
65 const struct cfattach power_ca = {
66 sizeof(struct power_softc), power_match, power_attach
67 };
68
69 struct cfdriver power_cd = {
70 NULL, "power", DV_DULL
71 };
72
73 int
power_match(struct device * parent,void * match,void * aux)74 power_match(struct device *parent, void *match, void *aux)
75 {
76 struct ebus_attach_args *ea = aux;
77
78 if (strcmp(ea->ea_name, "power") == 0)
79 return (1);
80 return (0);
81 }
82
83 void
power_attach(struct device * parent,struct device * self,void * aux)84 power_attach(struct device *parent, struct device *self, void *aux)
85 {
86 struct power_softc *sc = (void *)self;
87 struct ebus_attach_args *ea = aux;
88
89 if (ea->ea_nregs < 1) {
90 printf(": no registers\n");
91 return;
92 }
93
94 /* Use prom address if available, otherwise map it. */
95 if (ea->ea_nvaddrs) {
96 if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
97 BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
98 printf(": can't map PROM register space\n");
99 return;
100 }
101 sc->sc_iot = ea->ea_memtag;
102 } else if (ebus_bus_map(ea->ea_iotag, 0,
103 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
104 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
105 sc->sc_iot = ea->ea_iotag;
106 } else if (ebus_bus_map(ea->ea_memtag, 0,
107 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
108 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
109 sc->sc_iot = ea->ea_memtag;
110 } else {
111 printf("%s: can't map register space\n", self->dv_xname);
112 return;
113 }
114
115 if (ea->ea_nintrs > 0 && OF_getproplen(ea->ea_node, "button") >= 0) {
116 sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
117 IPL_BIO, 0, power_intr, sc, self->dv_xname);
118 if (sc->sc_ih == NULL) {
119 printf(": can't establish interrupt\n");
120 return;
121 }
122 }
123 printf("\n");
124 }
125
126 int
power_intr(void * vsc)127 power_intr(void *vsc)
128 {
129 extern int allowpowerdown;
130
131 if (allowpowerdown == 1) {
132 allowpowerdown = 0;
133 prsignal(initprocess, SIGUSR2);
134 }
135 return (1);
136 }
137