1 /* $OpenBSD: power.c,v 1.9 2022/04/06 18:59:26 naddy Exp $ */
2
3 /*
4 * Copyright (c) 2007 Martin Reindl.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/kernel.h>
22 #include <sys/device.h>
23 #include <sys/conf.h>
24 #include <sys/proc.h>
25 #include <sys/signalvar.h>
26
27 #include <machine/bus.h>
28 #include <machine/autoconf.h>
29
30 #include <sh/include/devreg.h>
31
32 #include <landisk/landisk/landiskreg.h>
33 #include <landisk/dev/obiovar.h>
34
35 struct power_softc {
36 struct device sc_dev;
37 void *sc_ih;
38 };
39
40 int power_match(struct device *, void *, void *);
41 void power_attach(struct device *, struct device *, void *);
42 int power_intr(void *aux);
43
44 const struct cfattach power_ca = {
45 sizeof(struct power_softc),
46 power_match,
47 power_attach
48 };
49
50 struct cfdriver power_cd = {
51 NULL, "power", DV_DULL
52 };
53
54 struct power_softc *power_softc;
55
56 int
power_match(struct device * parent,void * match,void * aux)57 power_match(struct device *parent, void *match, void *aux)
58 {
59 struct obio_attach_args *oa = aux;
60 static struct obio_irq power_match_irq;
61
62 oa->oa_nio = 0;
63 oa->oa_niomem = 0;
64 if (oa->oa_nirq == 0)
65 oa->oa_irq = &power_match_irq;
66 oa->oa_nirq = 1;
67 oa->oa_irq[0].or_irq = LANDISK_INTR_PWRSW;
68
69 return (1);
70 }
71
72 void
power_attach(struct device * parent,struct device * self,void * aux)73 power_attach(struct device *parent, struct device *self, void *aux)
74 {
75 struct power_softc *sc = (void *)self;
76
77 power_softc = sc;
78
79 sc->sc_ih = extintr_establish(LANDISK_INTR_PWRSW, IPL_TTY,
80 power_intr, sc, sc->sc_dev.dv_xname);
81 if (sc->sc_ih == NULL) {
82 printf(": couldn't map interrupt\n");
83 return;
84 }
85
86 printf("\n");
87 }
88
89 int
power_intr(void * arg)90 power_intr(void *arg)
91 {
92 extern int allowpowerdown;
93 int status;
94
95 status = (int8_t)_reg_read_1(LANDISK_BTNSTAT);
96 if (status == -1) {
97 return (0);
98 }
99
100 status = ~status;
101 if (status & BTN_POWER_BIT) {
102 #ifdef DEBUG
103 printf("%s switched\n", sc->sc_dev.dv_xname);
104 db_enter();
105 #endif
106 _reg_write_1(LANDISK_PWRSW_INTCLR, 1);
107 if (allowpowerdown == 1) {
108 allowpowerdown = 0;
109 prsignal(initprocess, SIGUSR1);
110 }
111 return (1);
112 }
113 return (0);
114 }
115