xref: /openbsd-src/sys/dev/acpi/acpi_x86.c (revision 8550894424f8a4aa4aafb6cd57229dd6ed7cd9dd)
1 /* $OpenBSD: acpi_x86.c,v 1.15 2022/03/06 15:12:00 deraadt Exp $ */
2 /*
3  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
4  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
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/device.h>
22 
23 #include <dev/acpi/acpireg.h>
24 #include <dev/acpi/acpivar.h>
25 #include <dev/acpi/acpidev.h>
26 #include <dev/acpi/dsdt.h>
27 
28 #include <machine/apmvar.h>
29 
30 int
31 sleep_showstate(void *v, int sleepmode)
32 {
33 	struct acpi_softc *sc = v;
34 
35 	switch (sleepmode) {
36 	case SLEEP_SUSPEND:
37 		sc->sc_state = ACPI_STATE_S3;
38 		break;
39 	case SLEEP_HIBERNATE:
40 		sc->sc_state = ACPI_STATE_S4;
41 		break;
42 	default:
43 		return (EOPNOTSUPP);
44 	}
45 
46 	if (sc->sc_sleeptype[sc->sc_state].slp_typa == -1 ||
47 	    sc->sc_sleeptype[sc->sc_state].slp_typb == -1) {
48 		if (sc->sc_state == ACPI_STATE_S4) {
49 			sc->sc_state = ACPI_STATE_S5;	/* No S4, use S5 */
50 			printf("%s: S4 unavailable, using S5\n",
51 			    sc->sc_dev.dv_xname);
52 		} else {
53 			printf("%s: state S%d unavailable\n",
54 			    sc->sc_dev.dv_xname, sc->sc_state);
55 			return (EOPNOTSUPP);
56 		}
57 	}
58 
59 	/* 1st suspend AML step: _TTS(tostate) */
60 	if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
61 		return (EINVAL);
62 	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
63 	return 0;
64 }
65 
66 int
67 sleep_setstate(void *v)
68 {
69 	struct acpi_softc *sc = v;
70 
71 	/* 2nd suspend AML step: _PTS(tostate) */
72 	if (aml_node_setval(sc, sc->sc_pts, sc->sc_state) != 0)
73 		return (EINVAL);
74 	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
75 	return 0;
76 }
77 
78 int
79 gosleep(void *v)
80 {
81 	struct acpi_softc *sc = v;
82 	int ret;
83 
84 	acpibtn_enable_psw();   /* enable _LID for wakeup */
85 	acpi_indicator(sc, ACPI_SST_SLEEPING);
86 
87 	/* 3rd suspend AML step: _GTS(tostate) */
88 	aml_node_setval(sc, sc->sc_gts, sc->sc_state);
89 
90 	/* Clear fixed event status */
91 	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
92 
93 	/* Enable wake GPEs */
94 	acpi_disable_allgpes(sc);
95 	acpi_enable_wakegpes(sc, sc->sc_state);
96 
97 	ret = acpi_sleep_cpu(sc, sc->sc_state);
98 	acpi_resume_cpu(sc, sc->sc_state);
99 	sc->sc_state = ACPI_STATE_S0;
100 
101 	return ret;
102 }
103 
104 void
105 sleep_abort(void *v)
106 {
107 	struct acpi_softc *sc = v;
108 
109 	sc->sc_state = ACPI_STATE_S0;
110 }
111 
112 int
113 sleep_resume(void *v)
114 {
115 	struct acpi_softc *sc = v;
116 
117 	acpibtn_disable_psw();		/* disable _LID for wakeup */
118 
119 	/* 3rd resume AML step: _TTS(runstate) */
120 	if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
121 		return (EINVAL);
122 	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
123 	return 0;
124 }
125 
126 
127 static int
128 checklids(struct acpi_softc *sc)
129 {
130 	extern int lid_action;
131 	int lids;
132 
133 	lids = acpibtn_numopenlids();
134 	if (lids == 0 && lid_action != 0)
135 		return EAGAIN;
136 	return 0;
137 }
138 
139 
140 int
141 suspend_finish(void *v)
142 {
143 	struct acpi_softc *sc = v;
144 
145 	acpi_record_event(sc, APM_NORMAL_RESUME);
146 	acpi_indicator(sc, ACPI_SST_WORKING);
147 
148 	/* If we woke up but all the lids are closed, go back to sleep */
149 	return checklids(sc);
150 }
151