xref: /netbsd-src/sys/dev/hpc/pwctl.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$NetBSD: pwctl.c,v 1.20 2012/10/27 17:18:17 chs Exp $	*/
2c732b455Stakemura 
3c732b455Stakemura /*-
426b0905dStakemura  * Copyright (c) 1999-2001
526b0905dStakemura  *         TAKEMURA Shin and PocketBSD Project. All rights reserved.
6c732b455Stakemura  * Copyright (c) 2000,2001
7c732b455Stakemura  *         SATO Kazumi. All rights reserved.
8c732b455Stakemura  *
9c732b455Stakemura  * Redistribution and use in source and binary forms, with or without
10c732b455Stakemura  * modification, are permitted provided that the following conditions
11c732b455Stakemura  * are met:
12c732b455Stakemura  * 1. Redistributions of source code must retain the above copyright
13c732b455Stakemura  *    notice, this list of conditions and the following disclaimer.
14c732b455Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
15c732b455Stakemura  *    notice, this list of conditions and the following disclaimer in the
16c732b455Stakemura  *    documentation and/or other materials provided with the distribution.
17c732b455Stakemura  * 3. All advertising materials mentioning features or use of this software
18c732b455Stakemura  *    must display the following acknowledgement:
19c732b455Stakemura  *	This product includes software developed by the PocketBSD project
20c732b455Stakemura  *	and its contributors.
21c732b455Stakemura  * 4. Neither the name of the project nor the names of its contributors
22c732b455Stakemura  *    may be used to endorse or promote products derived from this software
23c732b455Stakemura  *    without specific prior written permission.
24c732b455Stakemura  *
25c732b455Stakemura  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26c732b455Stakemura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27c732b455Stakemura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28c732b455Stakemura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29c732b455Stakemura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30c732b455Stakemura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31c732b455Stakemura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32c732b455Stakemura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33c732b455Stakemura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34c732b455Stakemura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35c732b455Stakemura  * SUCH DAMAGE.
36c732b455Stakemura  *
37c732b455Stakemura  */
38c732b455Stakemura 
39b84f53efSlukem #include <sys/cdefs.h>
40*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: pwctl.c,v 1.20 2012/10/27 17:18:17 chs Exp $");
419eddf385Speter 
429eddf385Speter #ifdef _KERNEL_OPT
439eddf385Speter #include "opt_pwctl.h"
449eddf385Speter #endif
45b84f53efSlukem 
46c732b455Stakemura #include <sys/param.h>
47c732b455Stakemura #include <sys/systm.h>
48c732b455Stakemura #include <sys/device.h>
49387ddeb6Ssato #include <sys/reboot.h>
50c732b455Stakemura 
51a2a38285Sad #include <sys/bus.h>
52c732b455Stakemura #include <machine/config_hook.h>
53c732b455Stakemura #include <machine/platid.h>
54c732b455Stakemura #include <machine/platid_mask.h>
55c732b455Stakemura 
56c732b455Stakemura #include <dev/hpc/hpciovar.h>
57c732b455Stakemura 
58c732b455Stakemura #include "locators.h"
59c732b455Stakemura 
609eddf385Speter #ifdef PWCTLDEBUG
612746e887Ssato #ifndef PWCTLDEBUG_CONF
622746e887Ssato #define PWCTLDEBUG_CONF	0
632746e887Ssato #endif
642746e887Ssato int	pwctl_debug = PWCTLDEBUG_CONF;
6526b0905dStakemura #define	DPRINTF(arg) if (pwctl_debug) printf arg;
66387ddeb6Ssato #define	VPRINTF(arg) if (bootverbose) printf arg;
67c732b455Stakemura #else
68c732b455Stakemura #define	DPRINTF(arg)
69387ddeb6Ssato #define	VPRINTF(arg) if (bootverbose) printf arg;
70c732b455Stakemura #endif
71c732b455Stakemura 
7226b0905dStakemura struct pwctl_softc {
73c732b455Stakemura 	hpcio_chip_t sc_hc;
74c732b455Stakemura 	int sc_port;
75c732b455Stakemura 	long sc_id;
76c732b455Stakemura 	int sc_on, sc_off;
77c732b455Stakemura 	config_hook_tag sc_hook_tag;
78c732b455Stakemura 	config_hook_tag sc_hook_hardpower;
79c732b455Stakemura 	config_hook_tag sc_ghook_tag;
80c732b455Stakemura 	int sc_save;
81c732b455Stakemura 	int sc_initvalue;
82c732b455Stakemura };
83c732b455Stakemura 
84529e91fcScegger static int	pwctl_match(device_t, cfdata_t, void *);
85529e91fcScegger static void	pwctl_attach(device_t, device_t, void *);
86859a6a49Such static int	pwctl_hook(void *, int, long, void *);
87859a6a49Such static int	pwctl_ghook(void *, int, long, void *);
88859a6a49Such int	pwctl_hardpower(void *, int, long, void *);
89c732b455Stakemura 
90*cbab9cadSchs CFATTACH_DECL_NEW(pwctl, sizeof(struct pwctl_softc),
91c9b3657cSthorpej     pwctl_match, pwctl_attach, NULL, NULL);
92c732b455Stakemura 
93c732b455Stakemura int
pwctl_match(device_t parent,cfdata_t match,void * aux)94529e91fcScegger pwctl_match(device_t parent, cfdata_t match, void *aux)
95c732b455Stakemura {
96a8304325Stakemura 	struct hpcio_attach_args *haa = aux;
97c732b455Stakemura 	platid_mask_t mask;
98c732b455Stakemura 
99a8304325Stakemura 	if (strcmp(haa->haa_busname, HPCIO_BUSNAME))
100859a6a49Such 		return (0);
101c732b455Stakemura 	if (match->cf_loc[HPCIOIFCF_PLATFORM] == 0)
102859a6a49Such 		return (0);
103c732b455Stakemura 	mask = PLATID_DEREF(match->cf_loc[HPCIOIFCF_PLATFORM]);
104c732b455Stakemura 	if (!platid_match(&platid, &mask))
105859a6a49Such 		return (0);
106859a6a49Such 	return (1);
107c732b455Stakemura }
108c732b455Stakemura 
109c732b455Stakemura void
pwctl_attach(device_t parent,device_t self,void * aux)110529e91fcScegger pwctl_attach(device_t parent, device_t self, void *aux)
111c732b455Stakemura {
112c732b455Stakemura 	struct hpcio_attach_args *haa = aux;
113c732b455Stakemura 	int *loc;
11492c7bba3Sthorpej 	struct pwctl_softc *sc = device_private(self);
115c732b455Stakemura 
116*cbab9cadSchs 	loc = device_cfdata(self)->cf_loc;
11726b0905dStakemura 	sc->sc_hc = (*haa->haa_getchip)(haa->haa_sc, loc[HPCIOIFCF_IOCHIP]);
118c732b455Stakemura 	sc->sc_port = loc[HPCIOIFCF_PORT];
119c732b455Stakemura 	sc->sc_id = loc[HPCIOIFCF_ID];
120c732b455Stakemura 	sc->sc_on = loc[HPCIOIFCF_ACTIVE] ? 1 : 0;
121c732b455Stakemura 	sc->sc_off = loc[HPCIOIFCF_ACTIVE] ? 0 : 1;
122c732b455Stakemura 	sc->sc_initvalue = loc[HPCIOIFCF_INITVALUE];
123859a6a49Such 
124c732b455Stakemura 	printf(" port=%d id=%ld on=%d%s",
125c732b455Stakemura 	    sc->sc_port, sc->sc_id, sc->sc_on,
126c732b455Stakemura 	    sc->sc_initvalue == -1 ? "" :
127c732b455Stakemura 	    sc->sc_initvalue ? " init=on" : " init=off");
128c732b455Stakemura 
129c732b455Stakemura 	if (sc->sc_port == HPCIOIFCF_PORT_DEFAULT ||
130c732b455Stakemura 	    sc->sc_id == HPCIOIFCF_ID_DEFAULT) {
131c732b455Stakemura 		printf(" (ignored)");
132c732b455Stakemura 	} else {
133c732b455Stakemura 		sc->sc_hook_tag = config_hook(CONFIG_HOOK_POWERCONTROL,
134859a6a49Such 		    sc->sc_id, CONFIG_HOOK_SHARE, pwctl_hook, sc);
135c732b455Stakemura 		sc->sc_ghook_tag = config_hook(CONFIG_HOOK_GET,
136859a6a49Such 		    sc->sc_id, CONFIG_HOOK_SHARE, pwctl_ghook, sc);
137c732b455Stakemura 		sc->sc_hook_hardpower = config_hook(CONFIG_HOOK_PMEVENT,
138859a6a49Such 		    CONFIG_HOOK_PMEVENT_HARDPOWER, CONFIG_HOOK_SHARE,
13926b0905dStakemura 		    pwctl_hardpower, sc);
140c732b455Stakemura 	}
141859a6a49Such 
142c732b455Stakemura 	if (sc->sc_initvalue != -1)
143c732b455Stakemura 		hpcio_portwrite(sc->sc_hc, sc->sc_port,
144c732b455Stakemura 		    sc->sc_initvalue ? sc->sc_on : sc->sc_off);
145c732b455Stakemura 	printf("\n");
146c732b455Stakemura }
147c732b455Stakemura 
148c732b455Stakemura int
pwctl_hook(void * ctx,int type,long id,void * msg)149859a6a49Such pwctl_hook(void *ctx, int type, long id, void *msg)
150c732b455Stakemura {
15126b0905dStakemura 	struct pwctl_softc *sc = ctx;
152c732b455Stakemura 
153c732b455Stakemura 	DPRINTF(("pwctl hook: port %d %s(%d)", sc->sc_port,
154c732b455Stakemura 	    msg ? "ON" : "OFF", msg ? sc->sc_on : sc->sc_off));
155c732b455Stakemura 	hpcio_portwrite(sc->sc_hc, sc->sc_port,
156c732b455Stakemura 	    msg ? sc->sc_on : sc->sc_off);
157859a6a49Such 
158c732b455Stakemura 	return (0);
159c732b455Stakemura }
160c732b455Stakemura 
161c732b455Stakemura int
pwctl_ghook(void * ctx,int type,long id,void * msg)162859a6a49Such pwctl_ghook(void *ctx, int type, long id, void *msg)
163c732b455Stakemura {
16426b0905dStakemura 	struct pwctl_softc *sc = ctx;
165c732b455Stakemura 
166c732b455Stakemura 	if (CONFIG_HOOK_VALUEP(msg))
167859a6a49Such 		return (1);
168c732b455Stakemura 
169c732b455Stakemura 	*(int*)msg = hpcio_portread(sc->sc_hc, sc->sc_port) == sc->sc_on;
170c732b455Stakemura 	DPRINTF(("pwctl ghook: port %d %s(%d)", sc->sc_port,
171c732b455Stakemura 	    *(int*)msg? "ON" : "OFF", *(int*)msg ? sc->sc_on : sc->sc_off));
172859a6a49Such 
173859a6a49Such 	return (0);
174c732b455Stakemura }
175c732b455Stakemura 
176c732b455Stakemura int
pwctl_hardpower(void * ctx,int type,long id,void * msg)177859a6a49Such pwctl_hardpower(void *ctx, int type, long id, void *msg)
178c732b455Stakemura {
17926b0905dStakemura 	struct pwctl_softc *sc = ctx;
180c732b455Stakemura 	int why =(int)msg;
181c732b455Stakemura 
182387ddeb6Ssato 	VPRINTF(("pwctl hardpower: port %d %s: %s(%d)\n", sc->sc_port,
183c732b455Stakemura 	    why == PWR_RESUME? "resume"
184c732b455Stakemura 	    : why == PWR_SUSPEND? "suspend" : "standby",
185c732b455Stakemura 	    sc->sc_save == sc->sc_on ? "on": "off", sc->sc_save));
186387ddeb6Ssato 
187c732b455Stakemura 	switch (why) {
188c732b455Stakemura 	case PWR_STANDBY:
189c732b455Stakemura 		break;
190c732b455Stakemura 	case PWR_SUSPEND:
191c732b455Stakemura 		sc->sc_save = hpcio_portread(sc->sc_hc, sc->sc_port);
192c732b455Stakemura 		hpcio_portwrite(sc->sc_hc, sc->sc_port, sc->sc_off);
193c732b455Stakemura 		break;
194c732b455Stakemura 	case PWR_RESUME:
195c732b455Stakemura 		hpcio_portwrite(sc->sc_hc, sc->sc_port, sc->sc_save);
196c732b455Stakemura 		break;
197c732b455Stakemura 	}
198859a6a49Such 
199c732b455Stakemura 	return (0);
200c732b455Stakemura }
201