xref: /openbsd/sys/arch/sparc64/dev/power.c (revision 898184e3)
1 /*	$OpenBSD: power.c,v 1.6 2011/06/24 19:47:49 naddy 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/types.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/device.h>
38 #include <sys/conf.h>
39 #include <sys/timeout.h>
40 #include <sys/proc.h>
41 #include <sys/signalvar.h>
42 
43 #include <machine/bus.h>
44 #include <machine/autoconf.h>
45 #include <machine/openfirm.h>
46 
47 #include <sparc64/dev/ebusreg.h>
48 #include <sparc64/dev/ebusvar.h>
49 
50 #define	POWER_REG		0
51 
52 #define	POWER_REG_CPWR_OFF	0x00000002	/* courtesy power off */
53 #define	POWER_REG_SPWR_OFF	0x00000001	/* system power off */
54 
55 struct power_softc {
56 	struct device		sc_dev;
57 	bus_space_tag_t		sc_iot;
58 	bus_space_handle_t	sc_ioh;
59 	struct intrhand		*sc_ih;
60 };
61 
62 int	power_match(struct device *, void *, void *);
63 void	power_attach(struct device *, struct device *, void *);
64 int	power_intr(void *);
65 
66 struct cfattach power_ca = {
67 	sizeof(struct power_softc), power_match, power_attach
68 };
69 
70 struct cfdriver power_cd = {
71 	NULL, "power", DV_DULL
72 };
73 
74 int
75 power_match(parent, match, aux)
76 	struct device *parent;
77 	void *match;
78 	void *aux;
79 {
80 	struct ebus_attach_args *ea = aux;
81 
82 	if (strcmp(ea->ea_name, "power") == 0)
83 		return (1);
84 	return (0);
85 }
86 
87 void
88 power_attach(parent, self, aux)
89 	struct device *parent, *self;
90 	void *aux;
91 {
92 	struct power_softc *sc = (void *)self;
93 	struct ebus_attach_args *ea = aux;
94 
95 	if (ea->ea_nregs < 1) {
96 		printf(": no registers\n");
97 		return;
98 	}
99 
100 	/* Use prom address if available, otherwise map it. */
101 	if (ea->ea_nvaddrs) {
102 		if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
103 		    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
104 			printf(": can't map PROM register space\n");
105 			return;
106 		}
107 		sc->sc_iot = ea->ea_memtag;
108 	} else if (ebus_bus_map(ea->ea_iotag, 0,
109 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
110 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
111 		sc->sc_iot = ea->ea_iotag;
112 	} else if (ebus_bus_map(ea->ea_memtag, 0,
113 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
114 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
115 		sc->sc_iot = ea->ea_memtag;
116 	} else {
117 		printf("%s: can't map register space\n", self->dv_xname);
118 		return;
119 	}
120 
121 	if (ea->ea_nintrs > 0 && OF_getproplen(ea->ea_node, "button") >= 0) {
122 	        sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
123 		    IPL_BIO, 0, power_intr, sc, self->dv_xname);
124 		if (sc->sc_ih == NULL) {
125 			printf(": can't establish interrupt\n");
126 			return;
127 		}
128 	}
129 	printf("\n");
130 }
131 
132 int
133 power_intr(void *vsc)
134 {
135 	extern int allowpowerdown;
136 
137 	if (allowpowerdown == 1) {
138 		allowpowerdown = 0;
139 		psignal(initproc, SIGUSR2);
140 	}
141 	return (1);
142 }
143