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 54struct 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 61int power_match(struct device *, void *, void *); 62void power_attach(struct device *, struct device *, void *); 63int power_intr(void *); 64 65const struct cfattach power_ca = { 66 sizeof(struct power_softc), power_match, power_attach 67}; 68 69struct cfdriver power_cd = { 70 NULL, "power", DV_DULL 71}; 72 73int 74power_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 83void 84power_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 126int 127power_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