1 1.20 chs /* $NetBSD: pwctl.c,v 1.20 2012/10/27 17:18:17 chs Exp $ */ 2 1.1 takemura 3 1.1 takemura /*- 4 1.2 takemura * Copyright (c) 1999-2001 5 1.2 takemura * TAKEMURA Shin and PocketBSD Project. All rights reserved. 6 1.1 takemura * Copyright (c) 2000,2001 7 1.1 takemura * SATO Kazumi. All rights reserved. 8 1.1 takemura * 9 1.1 takemura * Redistribution and use in source and binary forms, with or without 10 1.1 takemura * modification, are permitted provided that the following conditions 11 1.1 takemura * are met: 12 1.1 takemura * 1. Redistributions of source code must retain the above copyright 13 1.1 takemura * notice, this list of conditions and the following disclaimer. 14 1.1 takemura * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 takemura * notice, this list of conditions and the following disclaimer in the 16 1.1 takemura * documentation and/or other materials provided with the distribution. 17 1.1 takemura * 3. All advertising materials mentioning features or use of this software 18 1.1 takemura * must display the following acknowledgement: 19 1.1 takemura * This product includes software developed by the PocketBSD project 20 1.1 takemura * and its contributors. 21 1.1 takemura * 4. Neither the name of the project nor the names of its contributors 22 1.1 takemura * may be used to endorse or promote products derived from this software 23 1.1 takemura * without specific prior written permission. 24 1.1 takemura * 25 1.1 takemura * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 1.1 takemura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 1.1 takemura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 1.1 takemura * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 1.1 takemura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 1.1 takemura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 1.1 takemura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 1.1 takemura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 1.1 takemura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 1.1 takemura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 1.1 takemura * SUCH DAMAGE. 36 1.1 takemura * 37 1.1 takemura */ 38 1.8 lukem 39 1.8 lukem #include <sys/cdefs.h> 40 1.20 chs __KERNEL_RCSID(0, "$NetBSD: pwctl.c,v 1.20 2012/10/27 17:18:17 chs Exp $"); 41 1.16 peter 42 1.16 peter #ifdef _KERNEL_OPT 43 1.16 peter #include "opt_pwctl.h" 44 1.16 peter #endif 45 1.1 takemura 46 1.1 takemura #include <sys/param.h> 47 1.1 takemura #include <sys/systm.h> 48 1.1 takemura #include <sys/device.h> 49 1.6 sato #include <sys/reboot.h> 50 1.1 takemura 51 1.17 ad #include <sys/bus.h> 52 1.1 takemura #include <machine/config_hook.h> 53 1.1 takemura #include <machine/platid.h> 54 1.1 takemura #include <machine/platid_mask.h> 55 1.1 takemura 56 1.1 takemura #include <dev/hpc/hpciovar.h> 57 1.1 takemura 58 1.1 takemura #include "locators.h" 59 1.1 takemura 60 1.16 peter #ifdef PWCTLDEBUG 61 1.7 sato #ifndef PWCTLDEBUG_CONF 62 1.7 sato #define PWCTLDEBUG_CONF 0 63 1.7 sato #endif 64 1.7 sato int pwctl_debug = PWCTLDEBUG_CONF; 65 1.2 takemura #define DPRINTF(arg) if (pwctl_debug) printf arg; 66 1.6 sato #define VPRINTF(arg) if (bootverbose) printf arg; 67 1.1 takemura #else 68 1.1 takemura #define DPRINTF(arg) 69 1.6 sato #define VPRINTF(arg) if (bootverbose) printf arg; 70 1.1 takemura #endif 71 1.1 takemura 72 1.2 takemura struct pwctl_softc { 73 1.1 takemura hpcio_chip_t sc_hc; 74 1.1 takemura int sc_port; 75 1.1 takemura long sc_id; 76 1.1 takemura int sc_on, sc_off; 77 1.1 takemura config_hook_tag sc_hook_tag; 78 1.1 takemura config_hook_tag sc_hook_hardpower; 79 1.1 takemura config_hook_tag sc_ghook_tag; 80 1.1 takemura int sc_save; 81 1.1 takemura int sc_initvalue; 82 1.1 takemura }; 83 1.1 takemura 84 1.19 cegger static int pwctl_match(device_t, cfdata_t, void *); 85 1.19 cegger static void pwctl_attach(device_t, device_t, void *); 86 1.5 uch static int pwctl_hook(void *, int, long, void *); 87 1.5 uch static int pwctl_ghook(void *, int, long, void *); 88 1.5 uch int pwctl_hardpower(void *, int, long, void *); 89 1.1 takemura 90 1.20 chs CFATTACH_DECL_NEW(pwctl, sizeof(struct pwctl_softc), 91 1.11 thorpej pwctl_match, pwctl_attach, NULL, NULL); 92 1.1 takemura 93 1.1 takemura int 94 1.19 cegger pwctl_match(device_t parent, cfdata_t match, void *aux) 95 1.1 takemura { 96 1.3 takemura struct hpcio_attach_args *haa = aux; 97 1.1 takemura platid_mask_t mask; 98 1.1 takemura 99 1.3 takemura if (strcmp(haa->haa_busname, HPCIO_BUSNAME)) 100 1.5 uch return (0); 101 1.1 takemura if (match->cf_loc[HPCIOIFCF_PLATFORM] == 0) 102 1.5 uch return (0); 103 1.1 takemura mask = PLATID_DEREF(match->cf_loc[HPCIOIFCF_PLATFORM]); 104 1.1 takemura if (!platid_match(&platid, &mask)) 105 1.5 uch return (0); 106 1.5 uch return (1); 107 1.1 takemura } 108 1.1 takemura 109 1.1 takemura void 110 1.19 cegger pwctl_attach(device_t parent, device_t self, void *aux) 111 1.1 takemura { 112 1.1 takemura struct hpcio_attach_args *haa = aux; 113 1.1 takemura int *loc; 114 1.15 thorpej struct pwctl_softc *sc = device_private(self); 115 1.12 perry 116 1.20 chs loc = device_cfdata(self)->cf_loc; 117 1.2 takemura sc->sc_hc = (*haa->haa_getchip)(haa->haa_sc, loc[HPCIOIFCF_IOCHIP]); 118 1.1 takemura sc->sc_port = loc[HPCIOIFCF_PORT]; 119 1.1 takemura sc->sc_id = loc[HPCIOIFCF_ID]; 120 1.1 takemura sc->sc_on = loc[HPCIOIFCF_ACTIVE] ? 1 : 0; 121 1.1 takemura sc->sc_off = loc[HPCIOIFCF_ACTIVE] ? 0 : 1; 122 1.1 takemura sc->sc_initvalue = loc[HPCIOIFCF_INITVALUE]; 123 1.5 uch 124 1.1 takemura printf(" port=%d id=%ld on=%d%s", 125 1.5 uch sc->sc_port, sc->sc_id, sc->sc_on, 126 1.5 uch sc->sc_initvalue == -1 ? "" : 127 1.5 uch sc->sc_initvalue ? " init=on" : " init=off"); 128 1.1 takemura 129 1.1 takemura if (sc->sc_port == HPCIOIFCF_PORT_DEFAULT || 130 1.1 takemura sc->sc_id == HPCIOIFCF_ID_DEFAULT) { 131 1.1 takemura printf(" (ignored)"); 132 1.1 takemura } else { 133 1.1 takemura sc->sc_hook_tag = config_hook(CONFIG_HOOK_POWERCONTROL, 134 1.5 uch sc->sc_id, CONFIG_HOOK_SHARE, pwctl_hook, sc); 135 1.1 takemura sc->sc_ghook_tag = config_hook(CONFIG_HOOK_GET, 136 1.5 uch sc->sc_id, CONFIG_HOOK_SHARE, pwctl_ghook, sc); 137 1.1 takemura sc->sc_hook_hardpower = config_hook(CONFIG_HOOK_PMEVENT, 138 1.5 uch CONFIG_HOOK_PMEVENT_HARDPOWER, CONFIG_HOOK_SHARE, 139 1.5 uch pwctl_hardpower, sc); 140 1.5 uch } 141 1.1 takemura 142 1.1 takemura if (sc->sc_initvalue != -1) 143 1.1 takemura hpcio_portwrite(sc->sc_hc, sc->sc_port, 144 1.5 uch sc->sc_initvalue ? sc->sc_on : sc->sc_off); 145 1.1 takemura printf("\n"); 146 1.1 takemura } 147 1.1 takemura 148 1.1 takemura int 149 1.5 uch pwctl_hook(void *ctx, int type, long id, void *msg) 150 1.1 takemura { 151 1.2 takemura struct pwctl_softc *sc = ctx; 152 1.1 takemura 153 1.1 takemura DPRINTF(("pwctl hook: port %d %s(%d)", sc->sc_port, 154 1.5 uch msg ? "ON" : "OFF", msg ? sc->sc_on : sc->sc_off)); 155 1.1 takemura hpcio_portwrite(sc->sc_hc, sc->sc_port, 156 1.5 uch msg ? sc->sc_on : sc->sc_off); 157 1.5 uch 158 1.1 takemura return (0); 159 1.1 takemura } 160 1.1 takemura 161 1.1 takemura int 162 1.5 uch pwctl_ghook(void *ctx, int type, long id, void *msg) 163 1.1 takemura { 164 1.2 takemura struct pwctl_softc *sc = ctx; 165 1.1 takemura 166 1.1 takemura if (CONFIG_HOOK_VALUEP(msg)) 167 1.5 uch return (1); 168 1.1 takemura 169 1.1 takemura *(int*)msg = hpcio_portread(sc->sc_hc, sc->sc_port) == sc->sc_on; 170 1.1 takemura DPRINTF(("pwctl ghook: port %d %s(%d)", sc->sc_port, 171 1.5 uch *(int*)msg? "ON" : "OFF", *(int*)msg ? sc->sc_on : sc->sc_off)); 172 1.5 uch 173 1.5 uch return (0); 174 1.1 takemura } 175 1.1 takemura 176 1.1 takemura int 177 1.5 uch pwctl_hardpower(void *ctx, int type, long id, void *msg) 178 1.1 takemura { 179 1.2 takemura struct pwctl_softc *sc = ctx; 180 1.1 takemura int why =(int)msg; 181 1.1 takemura 182 1.6 sato VPRINTF(("pwctl hardpower: port %d %s: %s(%d)\n", sc->sc_port, 183 1.12 perry why == PWR_RESUME? "resume" 184 1.5 uch : why == PWR_SUSPEND? "suspend" : "standby", 185 1.5 uch sc->sc_save == sc->sc_on ? "on": "off", sc->sc_save)); 186 1.6 sato 187 1.1 takemura switch (why) { 188 1.1 takemura case PWR_STANDBY: 189 1.1 takemura break; 190 1.1 takemura case PWR_SUSPEND: 191 1.1 takemura sc->sc_save = hpcio_portread(sc->sc_hc, sc->sc_port); 192 1.1 takemura hpcio_portwrite(sc->sc_hc, sc->sc_port, sc->sc_off); 193 1.1 takemura break; 194 1.1 takemura case PWR_RESUME: 195 1.1 takemura hpcio_portwrite(sc->sc_hc, sc->sc_port, sc->sc_save); 196 1.1 takemura break; 197 1.1 takemura } 198 1.5 uch 199 1.1 takemura return (0); 200 1.1 takemura } 201