1 /* $NetBSD: acpi_cpu.h,v 1.45 2020/12/07 10:57:41 jmcneill Exp $ */
2 
3 /*-
4  * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi>
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  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #ifndef _SYS_DEV_ACPI_ACPI_CPU_H
31 #define _SYS_DEV_ACPI_ACPI_CPU_H
32 
33 /*
34  * The following _PDC values are based on:
35  *
36  *        Intel Corporation: Intel Processor-Specific ACPI
37  *        Interface Specification, September 2006, Revision 005.
38  */
39 #define ACPICPU_PDC_REVID         0x1
40 #define ACPICPU_PDC_SMP           0xA
41 #define ACPICPU_PDC_MSR           0x1
42 
43 #define ACPICPU_PDC_P_FFH         __BIT(0)        /* SpeedStep MSRs            */
44 #define ACPICPU_PDC_C_C1_HALT     __BIT(1)        /* C1 "I/O then halt"        */
45 #define ACPICPU_PDC_T_FFH         __BIT(2)        /* OnDemand throttling MSRs  */
46 #define ACPICPU_PDC_C_C1PT        __BIT(3)        /* SMP C1, Px, and Tx (same) */
47 #define ACPICPU_PDC_C_C2C3        __BIT(4)        /* SMP C2 and C3 (same)      */
48 #define ACPICPU_PDC_P_SW          __BIT(5)        /* SMP Px (different)        */
49 #define ACPICPU_PDC_C_SW          __BIT(6)        /* SMP Cx (different)        */
50 #define ACPICPU_PDC_T_SW          __BIT(7)        /* SMP Tx (different)        */
51 #define ACPICPU_PDC_C_C1_FFH      __BIT(8)        /* SMP C1 native beyond halt */
52 #define ACPICPU_PDC_C_C2C3_FFH    __BIT(9)        /* SMP C2 and C2 native      */
53 #define ACPICPU_PDC_P_HWF         __BIT(11)       /* Px hardware feedback      */
54 
55 #define ACPICPU_PDC_GAS_HW      __BIT(0)          /* HW-coordinated state      */
56 #define ACPICPU_PDC_GAS_BM      __BIT(1)          /* Bus master check required */
57 
58 /*
59  * Notify values.
60  */
61 #define ACPICPU_P_NOTIFY       0x80               /* _PPC */
62 #define ACPICPU_C_NOTIFY       0x81               /* _CST */
63 #define ACPICPU_T_NOTIFY       0x82               /* _TPC */
64 
65 /*
66  * Dependency coordination.
67  */
68 #define ACPICPU_DEP_SW_ALL     0xFC               /* All CPUs must set a state */
69 #define ACPICPU_DEP_SW_ANY     0xFD               /* Any CPU can set a state   */
70 #define ACPICPU_DEP_HW_ALL     0xFE               /* HW does the coordination  */
71 
72 /*
73  * C-states.
74  */
75 #define ACPICPU_C_C2_LATENCY_MAX 100              /* us */
76 #define ACPICPU_C_C3_LATENCY_MAX 1000             /* us */
77 
78 #define ACPICPU_C_STATE_HALT   0x01
79 #define ACPICPU_C_STATE_FFH    0x02
80 #define ACPICPU_C_STATE_SYSIO  0x03
81 
82 /*
83  * P-states.
84  */
85 #define ACPICPU_P_STATE_MAX    255                /* Arbitrary upper limit     */
86 #define ACPICPU_P_STATE_RETRY  100
87 
88 /*
89  * T-states.
90  */
91 #define ACPICPU_T_STATE_RETRY  0xA
92 #define ACPICPU_T_STATE_UNKNOWN          255
93 
94 /*
95  * Flags.
96  */
97 #define ACPICPU_FLAG_C                   __BIT(0) /* C-states supported        */
98 #define ACPICPU_FLAG_P                   __BIT(1) /* P-states supported        */
99 #define ACPICPU_FLAG_T                   __BIT(2) /* T-states supported        */
100 
101 #define ACPICPU_FLAG_PIIX4     __BIT(3) /* Broken (quirk)        */
102 
103 #define ACPICPU_FLAG_C_FFH     __BIT(4) /* Native C-states           */
104 #define ACPICPU_FLAG_C_FADT    __BIT(5) /* C-states with FADT        */
105 #define ACPICPU_FLAG_C_DEP     __BIT(6) /* C-state CPU coordination  */
106 #define ACPICPU_FLAG_C_BM      __BIT(7) /* Bus master control        */
107 #define ACPICPU_FLAG_C_BM_STS  __BIT(8) /* Bus master check required */
108 #define ACPICPU_FLAG_C_ARB     __BIT(9) /* Bus master arbitration    */
109 #define ACPICPU_FLAG_C_TSC     __BIT(10)          /* TSC broken, > C1, Px, Tx  */
110 #define ACPICPU_FLAG_C_APIC    __BIT(11)          /* APIC timer broken, > C1   */
111 #define ACPICPU_FLAG_C_C1E     __BIT(12)          /* AMD C1E detected      */
112 
113 #define ACPICPU_FLAG_P_FFH     __BIT(13)          /* Native P-states           */
114 #define ACPICPU_FLAG_P_DEP     __BIT(14)          /* P-state CPU coordination  */
115 #define ACPICPU_FLAG_P_HWF     __BIT(15)          /* HW feedback supported     */
116 #define ACPICPU_FLAG_P_XPSS    __BIT(16)          /* Microsoft XPSS in use     */
117 #define ACPICPU_FLAG_P_TURBO   __BIT(17)          /* Turbo Boost / Turbo Core  */
118 #define ACPICPU_FLAG_P_FIDVID  __BIT(18)          /* AMD "FID/VID algorithm"   */
119 
120 #define ACPICPU_FLAG_T_FFH     __BIT(19)          /* Native throttling         */
121 #define ACPICPU_FLAG_T_FADT    __BIT(20)          /* Throttling with FADT      */
122 #define ACPICPU_FLAG_T_DEP     __BIT(21)          /* T-state CPU coordination  */
123 
124 /*
125  * This is AML_RESOURCE_GENERIC_REGISTER,
126  * included here separately for convenience.
127  */
128 struct acpicpu_reg {
129           uint8_t                        reg_desc;
130           uint16_t             reg_reslen;
131           uint8_t                        reg_spaceid;
132           uint8_t                        reg_bitwidth;
133           uint8_t                        reg_bitoffset;
134           uint8_t                        reg_accesssize;
135           uint64_t             reg_addr;
136 } __packed;
137 
138 struct acpicpu_dep {
139           uint32_t             dep_domain;
140           uint32_t             dep_type;
141           uint32_t             dep_ncpus;
142           uint32_t             dep_index;
143 };
144 
145 struct acpicpu_cstate {
146           struct evcnt                   cs_evcnt;
147           char                           cs_name[EVCNT_STRING_MAX];
148           uint64_t             cs_addr;
149           uint32_t             cs_power;
150           uint32_t             cs_latency;
151           int                            cs_method;
152           int                            cs_flags;
153 };
154 
155 /*
156  * This structure supports both the conventional _PSS and the
157  * so-called extended _PSS (XPSS). For the latter, refer to:
158  *
159  *        Microsoft Corporation: Extended PSS ACPI
160  *        Method Specification, April 2, 2007.
161  */
162 struct acpicpu_pstate {
163           struct evcnt                   ps_evcnt;
164           char                           ps_name[EVCNT_STRING_MAX];
165           uint32_t             ps_freq;
166           uint32_t             ps_power;
167           uint32_t             ps_latency;
168           uint32_t             ps_latency_bm;
169           uint64_t             ps_control;
170           uint64_t             ps_control_addr;
171           uint64_t             ps_control_mask;
172           uint64_t             ps_status;
173           uint64_t             ps_status_addr;
174           uint64_t             ps_status_mask;
175           int                            ps_flags;
176 };
177 
178 struct acpicpu_tstate {
179           struct evcnt                   ts_evcnt;
180           char                           ts_name[EVCNT_STRING_MAX];
181           uint32_t             ts_percent;
182           uint32_t             ts_power;
183           uint32_t             ts_latency;
184           uint32_t             ts_control;
185           uint32_t             ts_status;
186 };
187 
188 struct acpicpu_object {
189           uint32_t             ao_procid;
190           uint32_t             ao_pblklen;
191           uint32_t             ao_pblkaddr;
192 };
193 
194 struct acpicpu_softc {
195           device_t             sc_dev;
196           struct cpu_info               *sc_ci;
197           struct acpi_devnode *sc_node;
198           struct acpicpu_object          sc_object;
199 
200           struct acpicpu_cstate          sc_cstate[ACPI_C_STATE_COUNT];
201           struct acpicpu_dep   sc_cstate_dep;
202           uint32_t             sc_cstate_sleep;
203 
204           struct acpicpu_pstate         *sc_pstate;
205           struct acpicpu_dep   sc_pstate_dep;
206           struct acpicpu_reg   sc_pstate_control;
207           struct acpicpu_reg   sc_pstate_status;
208           uint64_t             sc_pstate_aperf;   /* ACPICPU_FLAG_P_HW */
209           uint64_t             sc_pstate_mperf;   /* ACPICPU_FLAG_P_HW*/
210           uint32_t             sc_pstate_current;
211           uint32_t             sc_pstate_saved;
212           uint32_t             sc_pstate_count;
213           uint32_t             sc_pstate_max;
214           uint32_t             sc_pstate_min;
215 
216           struct acpicpu_tstate         *sc_tstate;
217           struct acpicpu_dep   sc_tstate_dep;
218           struct acpicpu_reg   sc_tstate_control;
219           struct acpicpu_reg   sc_tstate_status;
220           uint32_t             sc_tstate_current;
221           uint32_t             sc_tstate_count;
222           uint32_t             sc_tstate_max;
223           uint32_t             sc_tstate_min;
224 
225           kmutex_t             sc_mtx;
226           uint32_t             sc_cap;
227           uint32_t             sc_ncpus;
228           uint32_t             sc_flags;
229           bool                           sc_cold;
230 };
231 
232 void                 acpicpu_cstate_attach(device_t);
233 void                 acpicpu_cstate_detach(device_t);
234 void                 acpicpu_cstate_start(device_t);
235 void                 acpicpu_cstate_suspend(void *);
236 void                 acpicpu_cstate_resume(void *);
237 void                 acpicpu_cstate_callback(void *);
238 void                 acpicpu_cstate_idle(void);
239 
240 void                 acpicpu_pstate_attach(device_t);
241 void                 acpicpu_pstate_detach(device_t);
242 void                 acpicpu_pstate_start(device_t);
243 void                 acpicpu_pstate_suspend(void *);
244 void                 acpicpu_pstate_resume(void *);
245 void                 acpicpu_pstate_callback(void *);
246 void                 acpicpu_pstate_get(void *, void *);
247 void                 acpicpu_pstate_set(void *, void *);
248 
249 void                 acpicpu_tstate_attach(device_t);
250 void                 acpicpu_tstate_detach(device_t);
251 void                 acpicpu_tstate_start(device_t);
252 void                 acpicpu_tstate_suspend(void *);
253 void                 acpicpu_tstate_resume(void *);
254 void                 acpicpu_tstate_callback(void *);
255 int                  acpicpu_tstate_get(struct cpu_info *, uint32_t *);
256 void                 acpicpu_tstate_set(struct cpu_info *, uint32_t);
257 
258 struct cpu_info *acpicpu_md_match(device_t, cfdata_t, void *);
259 struct cpu_info *acpicpu_md_attach(device_t, device_t, void *);
260 
261 uint32_t   acpicpu_md_flags(void);
262 int                  acpicpu_md_cstate_start(struct acpicpu_softc *);
263 int                  acpicpu_md_cstate_stop(void);
264 void                 acpicpu_md_cstate_enter(int, int);
265 int                  acpicpu_md_pstate_start(struct acpicpu_softc *);
266 int                  acpicpu_md_pstate_stop(void);
267 int                  acpicpu_md_pstate_init(struct acpicpu_softc *);
268 int                  acpicpu_md_pstate_get(struct acpicpu_softc *, uint32_t *);
269 int                  acpicpu_md_pstate_set(struct acpicpu_pstate *);
270 int                  acpicpu_md_tstate_get(struct acpicpu_softc *, uint32_t *);
271 int                  acpicpu_md_tstate_set(struct acpicpu_tstate *);
272 
273 #if defined(__i386__) || defined(__x86_64__)
274 void                 acpicpu_md_quirk_c1e(void);
275 uint8_t              acpicpu_md_pstate_hwf(struct cpu_info *);
276 #endif
277 
278 /*
279  * acpicpu_readreg --
280  *
281  *        Read data from an I/O or memory address defined by 'reg'. The data
282  *        returned is shifted out and masked based on the bit offset and
283  *        width defined by the 'reg' parameter.
284  *
285  */
286 static inline uint32_t
acpicpu_readreg(struct acpicpu_reg * reg)287 acpicpu_readreg(struct acpicpu_reg *reg)
288 {
289           union {
290                     uint64_t u64;
291                     uint32_t u32;
292           } val;
293 
294           KASSERT(reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_IO ||
295                     reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_MEMORY);
296 
297           const uint64_t reg_mask =
298               __BITS(reg->reg_bitoffset + reg->reg_bitwidth - 1,
299                        reg->reg_bitoffset);
300 
301           val.u64 = 0;
302           if (reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_IO) {
303                     AcpiOsReadPort(reg->reg_addr, &val.u32,
304                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
305           } else {
306                     AcpiOsReadMemory(reg->reg_addr, &val.u64,
307                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
308           }
309 
310           return (uint32_t)__SHIFTOUT(val.u64, reg_mask);
311 }
312 
313 /*
314  * acpicpu_writereg --
315  *
316  *        Write data to an I/O or memory address defined by 'reg'. The register
317  *        is updated using a read-modify-write cycle and is shifted in based on
318  *        the bit offset and width defined by the 'reg' parameter.
319  *
320  */
321 static inline void
acpicpu_writereg(struct acpicpu_reg * reg,uint32_t newval)322 acpicpu_writereg(struct acpicpu_reg *reg, uint32_t newval)
323 {
324           union {
325                     uint64_t u64;
326                     uint32_t u32;
327           } val;
328 
329           KASSERT(reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_IO ||
330                     reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_MEMORY);
331 
332           const uint64_t reg_mask =
333               __BITS(reg->reg_bitoffset + reg->reg_bitwidth - 1,
334                        reg->reg_bitoffset);
335 
336           val.u64 = 0;
337           if (reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_IO) {
338                     AcpiOsReadPort(reg->reg_addr, &val.u32,
339                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
340           } else {
341                     AcpiOsReadMemory(reg->reg_addr, &val.u64,
342                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
343           }
344           val.u64 &= ~reg_mask;
345           val.u64 |= __SHIFTIN(newval, reg_mask);
346           if (reg->reg_spaceid == ACPI_ADR_SPACE_SYSTEM_IO) {
347                     AcpiOsWritePort(reg->reg_addr, val.u32,
348                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
349           } else {
350                     AcpiOsWriteMemory(reg->reg_addr, val.u64,
351                         ACPI_ACCESS_BIT_WIDTH(reg->reg_accesssize));
352           }
353 }
354 
355 #endif    /* !_SYS_DEV_ACPI_ACPI_CPU_H */
356