xref: /openbsd-src/sys/arch/sparc64/dev/power.c (revision 47c47feae40d23b370daf5f162f0e605e186b16a)
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