xref: /freebsd/sys/dev/acpica/acpi_cpu.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
1 /*-
2  * Copyright (c) 2001 Michael Smith
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_acpi.h"
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 #include <sys/power.h>
35 
36 #include <machine/bus_pio.h>
37 #include <machine/bus.h>
38 #include <machine/resource.h>
39 #include <sys/rman.h>
40 
41 #include "acpi.h"
42 #include <dev/acpica/acpivar.h>
43 
44 /*
45  * Support for ACPI Processor devices.
46  *
47  * Note that this only provides ACPI 1.0 support (with the exception of the
48  * PSTATE_CNT field).  2.0 support will involve implementing _PTC, _PCT,
49  * _PSS and _PPC.
50  */
51 
52 /* Hooks for the ACPI CA debugging infrastructure */
53 #define _COMPONENT	ACPI_PROCESSOR
54 ACPI_MODULE_NAME("PROCESSOR")
55 
56 struct acpi_cpu_softc {
57     device_t		cpu_dev;
58     ACPI_HANDLE		cpu_handle;
59 
60     u_int32_t		cpu_id;
61 
62     /* CPU throttling control register */
63     struct resource	*cpu_p_blk;
64 #define CPU_P_CNT_THT_EN (1<<4)
65 };
66 
67 #define CPU_GET_P_CNT(sc) 					\
68     (bus_space_read_4(rman_get_bustag((sc)->cpu_p_blk), 	\
69 		      rman_get_bushandle((sc)->cpu_p_blk), 0))
70 #define CPU_SET_P_CNT(sc, val)					\
71     (bus_space_write_4(rman_get_bustag((sc)->cpu_p_blk), 	\
72 		       rman_get_bushandle((sc)->cpu_p_blk), 0, (val)))
73 
74 /*
75  * Speeds are stored in counts, from 1 - CPU_MAX_SPEED, and
76  * reported to the user in tenths of a percent.
77  */
78 static u_int32_t	cpu_duty_offset;
79 static u_int32_t	cpu_duty_width;
80 #define CPU_MAX_SPEED		(1 << cpu_duty_width)
81 #define CPU_SPEED_PERCENT(x)	((1000 * (x)) / CPU_MAX_SPEED)
82 #define CPU_SPEED_PRINTABLE(x)	(CPU_SPEED_PERCENT(x) / 10),(CPU_SPEED_PERCENT(x) % 10)
83 
84 /* XXX Should be a generic way to do this */
85 static u_int32_t	cpu_smi_cmd;
86 static u_int8_t		cpu_pstate_cnt;
87 
88 static u_int32_t	cpu_current_state;
89 static u_int32_t	cpu_performance_state;
90 static u_int32_t	cpu_economy_state;
91 static u_int32_t	cpu_max_state;
92 
93 static device_t		*cpu_devices;
94 static int		cpu_ndevices;
95 
96 static struct sysctl_ctx_list	acpi_cpu_sysctl_ctx;
97 static struct sysctl_oid	*acpi_cpu_sysctl_tree;
98 
99 static int	acpi_cpu_probe(device_t dev);
100 static int	acpi_cpu_attach(device_t dev);
101 static void	acpi_cpu_init_throttling(void *arg);
102 static void	acpi_cpu_set_speed(u_int32_t speed);
103 static void	acpi_cpu_power_profile(void *arg);
104 static int	acpi_cpu_speed_sysctl(SYSCTL_HANDLER_ARGS);
105 
106 static device_method_t acpi_cpu_methods[] = {
107     /* Device interface */
108     DEVMETHOD(device_probe,	acpi_cpu_probe),
109     DEVMETHOD(device_attach,	acpi_cpu_attach),
110 
111     {0, 0}
112 };
113 
114 static driver_t acpi_cpu_driver = {
115     "acpi_cpu",
116     acpi_cpu_methods,
117     sizeof(struct acpi_cpu_softc),
118 };
119 
120 static devclass_t acpi_cpu_devclass;
121 DRIVER_MODULE(acpi_cpu, acpi, acpi_cpu_driver, acpi_cpu_devclass, 0, 0);
122 
123 static int
124 acpi_cpu_probe(device_t dev)
125 {
126     if (!acpi_disabled("cpu") && acpi_get_type(dev) == ACPI_TYPE_PROCESSOR) {
127 	/* XXX get more verbose description? */
128 	device_set_desc(dev, "CPU");
129 	return (0);
130     }
131 
132     return (ENXIO);
133 }
134 
135 static int
136 acpi_cpu_attach(device_t dev)
137 {
138     struct acpi_cpu_softc	*sc;
139     struct acpi_softc		*acpi_sc;
140     ACPI_OBJECT			processor;
141     ACPI_BUFFER			buf;
142     ACPI_STATUS			status;
143     u_int32_t			p_blk;
144     u_int32_t			p_blk_length;
145     u_int32_t			duty_end;
146     int				rid;
147 
148     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
149 
150     ACPI_ASSERTLOCK;
151 
152     sc = device_get_softc(dev);
153     sc->cpu_dev = dev;
154     sc->cpu_handle = acpi_get_handle(dev);
155 
156     /* Get global parameters from the FADT. */
157     if (device_get_unit(sc->cpu_dev) == 0) {
158 	cpu_duty_offset = AcpiGbl_FADT->DutyOffset;
159 	cpu_duty_width = AcpiGbl_FADT->DutyWidth;
160 	cpu_smi_cmd = AcpiGbl_FADT->SmiCmd;
161 	cpu_pstate_cnt = AcpiGbl_FADT->PstateCnt;
162 
163 	/* Validate the offset/width */
164 	if (cpu_duty_width > 0) {
165 	    duty_end = cpu_duty_offset + cpu_duty_width - 1;
166 
167 	    /* Check that it fits */
168 	    if (duty_end > 31) {
169 		printf("acpi_cpu: CLK_VAL field overflows P_CNT register\n");
170 		cpu_duty_width = 0;
171 	    }
172 
173 	    /* Check for overlap with the THT_EN bit */
174 	    if (cpu_duty_offset <= 4 && duty_end >= 4) {
175 		printf("acpi_cpu: CLK_VAL field overlaps THT_EN bit\n");
176 		cpu_duty_width = 0;
177 	    }
178 	}
179 
180 	/*
181 	 * Start the throttling process once the probe phase completes, if we
182 	 * think that it's going to be useful.  If the duty width value is
183 	 * zero, there are no significant bits in the register and thus no
184 	 * throttled states.
185 	 */
186 	if (cpu_duty_width > 0) {
187 	    AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cpu_init_throttling,
188 				    NULL);
189 	    acpi_sc = acpi_device_get_parent_softc(dev);
190 	    sysctl_ctx_init(&acpi_cpu_sysctl_ctx);
191 	    acpi_cpu_sysctl_tree = SYSCTL_ADD_NODE(&acpi_cpu_sysctl_ctx,
192 				   SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
193 				   OID_AUTO, "cpu", CTLFLAG_RD, 0, "");
194 
195 	    SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
196 			   SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
197 			   OID_AUTO, "max_speed", CTLFLAG_RD,
198 			   &cpu_max_state, 0, "maximum CPU speed");
199 	    SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
200 			   SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
201 			   OID_AUTO, "current_speed", CTLFLAG_RD,
202 			   &cpu_current_state, 0, "current CPU speed");
203 	    SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
204 			    SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
205 			    OID_AUTO, "performance_speed",
206 			    CTLTYPE_INT | CTLFLAG_RW, &cpu_performance_state,
207 			    0, acpi_cpu_speed_sysctl, "I", "");
208 	    SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
209 			    SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
210 			    OID_AUTO, "economy_speed",
211 			    CTLTYPE_INT | CTLFLAG_RW, &cpu_economy_state,
212 			    0, acpi_cpu_speed_sysctl, "I", "");
213 	}
214     }
215 
216     /* Get the processor object. */
217     buf.Pointer = &processor;
218     buf.Length = sizeof(processor);
219     status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
220     if (ACPI_FAILURE(status)) {
221 	device_printf(sc->cpu_dev, "couldn't get Processor object - %s\n",
222 		      AcpiFormatException(status));
223 	return_VALUE (ENXIO);
224     }
225     if (processor.Type != ACPI_TYPE_PROCESSOR) {
226 	device_printf(sc->cpu_dev, "Processor object has bad type %d\n",
227 		      processor.Type);
228 	return_VALUE (ENXIO);
229     }
230     sc->cpu_id = processor.Processor.ProcId;
231 
232     /*
233      * If it looks like we support throttling, find this CPU's P_BLK.
234      *
235      * Note that some systems seem to duplicate the P_BLK pointer across
236      * multiple CPUs, so not getting the resource is not fatal.
237      *
238      * XXX should support _PTC here as well, once we work out how to parse it.
239      *
240      * XXX is it valid to assume that the P_BLK must be 6 bytes long?
241      */
242     if (cpu_duty_width > 0) {
243 	p_blk = processor.Processor.PblkAddress;
244 	p_blk_length = processor.Processor.PblkLength;
245 
246 	/* allocate bus space if possible */
247 	if (p_blk > 0 && p_blk_length == 6) {
248 	    rid = 0;
249 	    bus_set_resource(sc->cpu_dev, SYS_RES_IOPORT, rid, p_blk,
250 			     p_blk_length);
251 	    sc->cpu_p_blk = bus_alloc_resource(sc->cpu_dev, SYS_RES_IOPORT,
252 					       &rid, 0, ~0, 1, RF_ACTIVE);
253 
254 	    ACPI_DEBUG_PRINT((ACPI_DB_IO, "acpi_cpu%d: throttling with P_BLK "
255 			     "at 0x%x/%d%s\n", device_get_unit(sc->cpu_dev),
256 			     p_blk, p_blk_length,
257 			     sc->cpu_p_blk ? "" : " (shadowed)"));
258 	}
259     }
260 
261     return_VALUE (0);
262 }
263 
264 /*
265  * Call this *after* all CPUs have been attached.
266  *
267  * Takes the ACPI lock to avoid fighting anyone over the SMI command
268  * port.  Could probably lock less code.
269  */
270 static void
271 acpi_cpu_init_throttling(void *arg)
272 {
273     int cpu_temp_speed;
274     ACPI_LOCK_DECL;
275 
276     ACPI_LOCK;
277 
278     /* Get set of CPU devices */
279     devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);
280 
281     /* Initialise throttling states */
282     cpu_max_state = CPU_MAX_SPEED;
283     cpu_performance_state = cpu_max_state;
284     cpu_economy_state = cpu_performance_state / 2;
285 
286     /* 0 is 'reserved' */
287     if (cpu_economy_state == 0)
288 	cpu_economy_state++;
289     if (TUNABLE_INT_FETCH("hw.acpi.cpu.performance_speed", &cpu_temp_speed) &&
290 	cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
291 
292 	cpu_performance_state = cpu_temp_speed;
293     }
294     if (TUNABLE_INT_FETCH("hw.acpi.cpu.economy_speed", &cpu_temp_speed) &&
295 	cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
296 
297 	cpu_economy_state = cpu_temp_speed;
298     }
299 
300     /* Register performance profile change handler */
301     EVENTHANDLER_REGISTER(power_profile_change, acpi_cpu_power_profile, NULL,
302 			  0);
303 
304     /*
305      * If ACPI 2.0+, signal platform that we are taking over throttling
306      * XXX should be a generic interface for this
307      */
308     if (cpu_pstate_cnt != 0)
309 	AcpiOsWritePort(cpu_smi_cmd, cpu_pstate_cnt, 8);
310 
311     ACPI_UNLOCK;
312 
313     /* Set initial speed */
314     acpi_cpu_power_profile(NULL);
315 
316     printf("acpi_cpu: throttling enabled, %d steps (100%% to %d.%d%%), "
317 	   "currently %d.%d%%\n", CPU_MAX_SPEED, CPU_SPEED_PRINTABLE(1),
318 	   CPU_SPEED_PRINTABLE(cpu_current_state));
319 }
320 
321 /*
322  * Set CPUs to the new state.
323  *
324  * Must be called with the ACPI lock held.
325  */
326 static void
327 acpi_cpu_set_speed(u_int32_t speed)
328 {
329     struct acpi_cpu_softc	*sc;
330     int				i;
331     u_int32_t			p_cnt, clk_val;
332 
333     ACPI_ASSERTLOCK;
334 
335     /* Iterate over processors */
336     for (i = 0; i < cpu_ndevices; i++) {
337 	sc = device_get_softc(cpu_devices[i]);
338 	if (sc->cpu_p_blk == NULL)
339 	    continue;
340 
341 	/* Get the current P_CNT value and disable throttling */
342 	p_cnt = CPU_GET_P_CNT(sc);
343 	p_cnt &= ~CPU_P_CNT_THT_EN;
344 	CPU_SET_P_CNT(sc, p_cnt);
345 
346 	/* If we're at maximum speed, that's all */
347 	if (speed < CPU_MAX_SPEED) {
348 	    /* Mask the old CLK_VAL off and or-in the new value */
349 	    clk_val = CPU_MAX_SPEED << cpu_duty_offset;
350 	    p_cnt &= ~clk_val;
351 	    p_cnt |= (speed << cpu_duty_offset);
352 
353 	    /* Write the new P_CNT value and then enable throttling */
354 	    CPU_SET_P_CNT(sc, p_cnt);
355 	    p_cnt |= CPU_P_CNT_THT_EN;
356 	    CPU_SET_P_CNT(sc, p_cnt);
357 	}
358 	ACPI_VPRINT(sc->cpu_dev, acpi_device_get_parent_softc(sc->cpu_dev),
359 		    "set speed to %d.%d%%\n", CPU_SPEED_PRINTABLE(speed));
360     }
361     cpu_current_state = speed;
362 }
363 
364 /*
365  * Power profile change hook.
366  *
367  * Uses the ACPI lock to avoid reentrancy.
368  */
369 static void
370 acpi_cpu_power_profile(void *arg)
371 {
372     int		state;
373     u_int32_t	new;
374     ACPI_LOCK_DECL;
375 
376     state = power_profile_get_state();
377     if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
378 	return;
379 
380     ACPI_LOCK;
381 
382     switch (state) {
383     case POWER_PROFILE_PERFORMANCE:
384 	new = cpu_performance_state;
385 	break;
386     case POWER_PROFILE_ECONOMY:
387 	new = cpu_economy_state;
388 	break;
389     default:
390 	new = cpu_current_state;
391 	break;
392     }
393 
394     if (cpu_current_state != new)
395 	acpi_cpu_set_speed(new);
396 
397     ACPI_UNLOCK;
398 }
399 
400 /*
401  * Handle changes in the performance/ecomony CPU settings.
402  *
403  * Does not need the ACPI lock (although setting *argp should
404  * probably be atomic).
405  */
406 static int
407 acpi_cpu_speed_sysctl(SYSCTL_HANDLER_ARGS)
408 {
409     u_int32_t	*argp;
410     u_int32_t	arg;
411     int		error;
412 
413     argp = (u_int32_t *)oidp->oid_arg1;
414     arg = *argp;
415     error = sysctl_handle_int(oidp, &arg, 0, req);
416 
417     /* Error or no new value */
418     if (error != 0 || req->newptr == NULL)
419 	return (error);
420     if (arg < 1 || arg > cpu_max_state)
421 	return (EINVAL);
422 
423     /* Set new value and possibly switch */
424     *argp = arg;
425     acpi_cpu_power_profile(NULL);
426 
427     return (0);
428 }
429