1/*
2 * Copyright 2012, Haiku, Inc. All Rights Reserved.
3 *
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		Yongcong Du <ycdu.vmcore@gmail.com>
8 */
9
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include <ACPI.h>
16#include <Drivers.h>
17#include <Errors.h>
18#include <KernelExport.h>
19
20#include <arch_system_info.h>
21#include <cpu.h>
22#include <cpuidle.h>
23#include <smp.h>
24
25#include "x86_cpuidle.h"
26
27
28#define ACPI_PDC_REVID		0x1
29#define ACPI_OSC_QUERY		(1 << 0)
30
31#define ACPI_PDC_P_FFH		(1 << 0)
32#define ACPI_PDC_C_C1_HALT	(1 << 1)
33#define ACPI_PDC_T_FFH		(1 << 2)
34#define ACPI_PDC_SMP_C1PT	(1 << 3)
35#define ACPI_PDC_SMP_C2C3	(1 << 4)
36#define ACPI_PDC_SMP_P_SW	(1 << 5)
37#define ACPI_PDC_SMP_C_SW	(1 << 6)
38#define ACPI_PDC_SMP_T_SW	(1 << 7)
39#define ACPI_PDC_C_C1_FFH	(1 << 8)
40#define ACPI_PDC_C_C2C3_FFH	(1 << 9)
41#define ACPI_PDC_P_HWCOORD	(1 << 11)
42
43// Bus Master check required
44#define ACPI_PDC_GAS_BM		(1 << 1)
45
46#define ACPI_CSTATE_HALT	0x1
47#define ACPI_CSTATE_SYSIO	0x2
48#define ACPI_CSTATE_FFH		0x3
49
50// Bus Master Check
51#define ACPI_FLAG_C_BM		(1 << 0)
52// Bus master arbitration
53#define ACPI_FLAG_C_ARB		(1 << 1)
54
55// Copied from acpica's actypes.h, where's the best place to put?
56#define ACPI_BITREG_BUS_MASTER_STATUS           0x01
57#define ACPI_BITREG_BUS_MASTER_RLD              0x0F
58#define ACPI_BITREG_ARB_DISABLE                 0x13
59
60#define ACPI_STATE_C0                   (uint8) 0
61#define ACPI_STATE_C1                   (uint8) 1
62#define ACPI_STATE_C2                   (uint8) 2
63#define ACPI_STATE_C3                   (uint8) 3
64#define ACPI_C_STATES_MAX               ACPI_STATE_C3
65#define ACPI_C_STATE_COUNT              4
66
67
68#define ACPI_CPUIDLE_MODULE_NAME "drivers/power/x86_cpuidle/acpi/driver_v1"
69
70
71struct acpicpu_reg {
72	uint8	reg_desc;
73	uint16	reg_reslen;
74	uint8	reg_spaceid;
75	uint8	reg_bitwidth;
76	uint8	reg_bitoffset;
77	uint8	reg_accesssize;
78	uint64	reg_addr;
79} __attribute__((packed));
80
81struct acpi_cpuidle_driver_info {
82	device_node *node;
83	acpi_device_module_info *acpi;
84	acpi_device acpi_cookie;
85	uint32 flags;
86	int32 cpuIndex;
87};
88
89struct acpi_cstate_info {
90	uint32 address;
91	uint8 skip_bm_sts;
92	uint8 method;
93	uint8 type;
94};
95
96
97static acpi_cpuidle_driver_info *sAcpiProcessor[SMP_MAX_CPUS];
98static CpuidleDevice sAcpiDevice;
99static device_manager_info *sDeviceManager;
100static acpi_module_info *sAcpi;
101
102CpuidleModuleInfo *gIdle;
103
104
105static status_t
106acpi_eval_pdc(acpi_cpuidle_driver_info *device)
107{
108	acpi_objects arg;
109	acpi_object_type obj;
110	uint32 cap[3];
111
112	arg.count = 1;
113	arg.pointer = &obj;
114	cap[0] = 1;
115	cap[1] = 1;
116	cap[2] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
117	cap[2] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
118	cap[2] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
119	cap[2] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD
120		| ACPI_PDC_T_FFH;
121	obj.object_type = ACPI_TYPE_BUFFER;
122	obj.data.buffer.length = sizeof(cap);
123	obj.data.buffer.buffer = cap;
124	status_t status = device->acpi->evaluate_method(device->acpi_cookie, "_PDC",
125		&arg, NULL);
126	return status;
127}
128
129
130static status_t
131acpi_eval_osc(acpi_cpuidle_driver_info *device)
132{
133	// guid for intel platform
134	dprintf("%s@%p\n", __func__, device->acpi_cookie);
135	static uint8 uuid[] = {
136		0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
137		0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
138	};
139	uint32 cap[2];
140	cap[0] = 0;
141	cap[1] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
142	cap[1] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
143	cap[1] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
144	cap[1] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD
145		| ACPI_PDC_T_FFH;
146
147	acpi_objects arg;
148	acpi_object_type obj[4];
149
150	arg.count = 4;
151	arg.pointer = obj;
152
153	obj[0].object_type = ACPI_TYPE_BUFFER;
154	obj[0].data.buffer.length = sizeof(uuid);
155	obj[0].data.buffer.buffer = uuid;
156	obj[1].object_type = ACPI_TYPE_INTEGER;
157	obj[1].data.integer = ACPI_PDC_REVID;
158	obj[2].object_type = ACPI_TYPE_INTEGER;
159	obj[2].data.integer = sizeof(cap)/sizeof(cap[0]);
160	obj[3].object_type = ACPI_TYPE_BUFFER;
161	obj[3].data.buffer.length = sizeof(cap);
162	obj[3].data.buffer.buffer = (void *)cap;
163
164	acpi_data buf;
165	buf.pointer = NULL;
166	buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
167	status_t status = device->acpi->evaluate_method(device->acpi_cookie, "_OSC",
168		&arg, &buf);
169	if (status != B_OK)
170		return status;
171	acpi_object_type *osc = (acpi_object_type *)buf.pointer;
172	if (osc->object_type != ACPI_TYPE_BUFFER)
173		return B_BAD_TYPE;
174	if (osc->data.buffer.length != sizeof(cap))
175		return B_BUFFER_OVERFLOW;
176	return status;
177}
178
179
180static inline bool
181acpi_cstate_bm_check(void)
182{
183	uint32 val;
184	sAcpi->read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &val);
185	if (!val)
186		return false;
187	sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
188
189	return true;
190}
191
192
193static inline void
194acpi_cstate_ffh_enter(CpuidleCstate *cState)
195{
196	cpu_ent *cpu = get_cpu_struct();
197	if (cpu->invoke_scheduler)
198		return;
199
200	x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
201	if (!cpu->invoke_scheduler)
202		x86_mwait((unsigned long)cState->pData, 1);
203}
204
205
206static inline void
207acpi_cstate_halt(void)
208{
209	cpu_ent *cpu = get_cpu_struct();
210	if (cpu->invoke_scheduler)
211		return;
212	asm("hlt");
213}
214
215
216static void
217acpi_cstate_enter(CpuidleCstate *cState)
218{
219	acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
220	if (ci->method == ACPI_CSTATE_FFH)
221		acpi_cstate_ffh_enter(cState);
222	else if (ci->method == ACPI_CSTATE_SYSIO)
223		in8(ci->address);
224	else
225		acpi_cstate_halt();
226}
227
228
229static int32
230acpi_cstate_idle(int32 state, CpuidleDevice *device)
231{
232	CpuidleCstate *cState = &device->cStates[state];
233	acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
234	if (!ci->skip_bm_sts) {
235		// we fall back to C1 if there's bus master activity
236		if (acpi_cstate_bm_check())
237			state = 1;
238	}
239	if (ci->type != ACPI_STATE_C3)
240		acpi_cstate_enter(cState);
241
242	// set BM_RLD for Bus Master to activity to wake the system from C3
243	// With Newer chipsets BM_RLD is a NOP Since DMA is automatically handled
244	// during C3 State
245	acpi_cpuidle_driver_info *pi = sAcpiProcessor[smp_get_current_cpu()];
246	if (pi->flags & ACPI_FLAG_C_BM)
247		sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
248
249	// disable bus master arbitration during C3
250	if (pi->flags & ACPI_FLAG_C_ARB)
251		sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
252
253	acpi_cstate_enter(cState);
254
255	// clear BM_RLD and re-enable the arbiter
256	if (pi->flags & ACPI_FLAG_C_BM)
257		sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
258
259	if (pi->flags & ACPI_FLAG_C_ARB)
260		sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
261
262	return state;
263}
264
265
266static status_t
267acpi_cstate_add(acpi_object_type *object, CpuidleCstate *cState)
268{
269	acpi_cstate_info *ci = (acpi_cstate_info *)malloc(sizeof(acpi_cstate_info));
270	if (!ci)
271		return B_NO_MEMORY;
272
273	if (object->object_type != ACPI_TYPE_PACKAGE) {
274		dprintf("invalid _CST object\n");
275		goto error;
276	}
277
278	if (object->data.package.count != 4) {
279		dprintf("invalid _CST number\n");
280		goto error;
281	}
282
283	// type
284	acpi_object_type * pointer = &object->data.package.objects[1];
285	if (pointer->object_type != ACPI_TYPE_INTEGER) {
286		dprintf("invalid _CST elem type\n");
287		goto error;
288	}
289	uint32 n = pointer->data.integer;
290	if (n < 1 || n > 3) {
291		dprintf("invalid _CST elem value\n");
292		goto error;
293	}
294	ci->type = n;
295	dprintf("C%" B_PRId32 "\n", n);
296	snprintf(cState->name, sizeof(cState->name), "C%" B_PRId32, n);
297
298	// Latency
299	pointer = &object->data.package.objects[2];
300	if (pointer->object_type != ACPI_TYPE_INTEGER) {
301		dprintf("invalid _CST elem type\n");
302		goto error;
303	}
304	n = pointer->data.integer;
305	cState->latency = n;
306	dprintf("Latency: %" B_PRId32 "\n", n);
307
308	// power
309	pointer = &object->data.package.objects[3];
310	if (pointer->object_type != ACPI_TYPE_INTEGER) {
311		dprintf("invalid _CST elem type\n");
312		goto error;
313	}
314	n = pointer->data.integer;
315	dprintf("power: %" B_PRId32 "\n", n);
316
317	// register
318	pointer = &object->data.package.objects[0];
319	if (pointer->object_type != ACPI_TYPE_BUFFER) {
320		dprintf("invalid _CST elem type\n");
321		goto error;
322	}
323	if (pointer->data.buffer.length < 15) {
324		dprintf("invalid _CST elem length\n");
325		goto error;
326	}
327
328	struct acpicpu_reg *reg = (struct acpicpu_reg *)pointer->data.buffer.buffer;
329	switch (reg->reg_spaceid) {
330		case ACPI_ADR_SPACE_SYSTEM_IO:
331			dprintf("IO method\n");
332			if (reg->reg_addr == 0) {
333				dprintf("illegal address\n");
334				goto error;
335			}
336			if (reg->reg_bitwidth != 8) {
337				dprintf("invalid source length\n");
338				goto error;
339			}
340			ci->address = reg->reg_addr;
341			ci->method = ACPI_CSTATE_SYSIO;
342			break;
343		case ACPI_ADR_SPACE_FIXED_HARDWARE:
344		{
345			dprintf("FFH method\n");
346			ci->method = ACPI_CSTATE_FFH;
347			ci->address = reg->reg_addr;
348
349			// skip checking BM_STS if ACPI_PDC_GAS_BM is cleared
350			cpu_ent *cpu = get_cpu_struct();
351			if ((cpu->arch.vendor == VENDOR_INTEL) &&
352				!(reg->reg_accesssize & ACPI_PDC_GAS_BM))
353				ci->skip_bm_sts = 1;
354			break;
355		}
356		default:
357			dprintf("invalid spaceid %" B_PRId8 "\n", reg->reg_spaceid);
358			break;
359	}
360	cState->pData = ci;
361	cState->EnterIdle = acpi_cstate_idle;
362
363	return B_OK;
364error:
365	free(ci);
366	return B_ERROR;
367}
368
369
370static void
371acpi_cstate_quirks(acpi_cpuidle_driver_info *device)
372{
373	cpu_ent *cpu = get_cpu_struct();
374	// Calculated Model Value: M = (Extended Model << 4) + Model
375	uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model;
376
377	// On all recent Intel platforms, ARB_DIS is not necessary
378	if (cpu->arch.vendor != VENDOR_INTEL)
379		return;
380	if (cpu->arch.family > 0xf || (cpu->arch.family == 6 && model >= 0xf))
381		device->flags &= ~ACPI_FLAG_C_ARB;
382}
383
384
385static status_t
386acpi_cpuidle_setup(acpi_cpuidle_driver_info *device)
387{
388	// _PDC is deprecated in the ACPI 3.0, we will try _OSC firstly
389	// and fall back to _PDC if _OSC fail
390	status_t status = acpi_eval_osc(device);
391	if (status != B_OK)
392		status = acpi_eval_pdc(device);
393	if (status != B_OK) {
394		dprintf("failed to eval _OSC and _PDC\n");
395		return status;
396	}
397
398	acpi_data buffer;
399	buffer.pointer = NULL;
400	buffer.length = ACPI_ALLOCATE_BUFFER;
401
402	dprintf("evaluate _CST @%p\n", device->acpi_cookie);
403	status = device->acpi->evaluate_method(device->acpi_cookie, "_CST", NULL,
404		&buffer);
405	if (status != B_OK) {
406		dprintf("failed to get _CST\n");
407		return B_IO_ERROR;
408	}
409
410	acpi_object_type *object = (acpi_object_type *)buffer.pointer;
411	if (object->object_type != ACPI_TYPE_PACKAGE)
412		dprintf("invalid _CST type\n");
413	if (object->data.package.count < 2)
414		dprintf("invalid _CST count\n");
415
416	acpi_object_type *pointer = object->data.package.objects;
417	if (pointer[0].object_type != ACPI_TYPE_INTEGER)
418		dprintf("invalid _CST type 2\n");
419	uint32 n = pointer[0].data.integer;
420	if (n != object->data.package.count - 1)
421		dprintf("invalid _CST count 2\n");
422	if (n > 8)
423		dprintf("_CST has too many states\n");
424	dprintf("cpuidle found %" B_PRId32 " cstates\n", n);
425	uint32 count = 1;
426	for (uint32 i = 1; i <= n; i++) {
427		pointer = &object->data.package.objects[i];
428		if (acpi_cstate_add(pointer, &sAcpiDevice.cStates[count]) == B_OK)
429			++count;
430	}
431	sAcpiDevice.cStateCount = count;
432	free(buffer.pointer);
433
434	// TODO we assume BM is a must and ARB_DIS is always available
435	device->flags |= ACPI_FLAG_C_ARB | ACPI_FLAG_C_BM;
436
437	acpi_cstate_quirks(device);
438
439	return B_OK;
440}
441
442
443static status_t
444acpi_cpuidle_init(void)
445{
446	dprintf("acpi_cpuidle_init\n");
447
448	for (int32 i = 0; i < smp_get_num_cpus(); i++)
449		if (acpi_cpuidle_setup(sAcpiProcessor[i]) != B_OK)
450			return B_ERROR;
451
452	status_t status = gIdle->AddDevice(&sAcpiDevice);
453	if (status == B_OK)
454		dprintf("using acpi idle\n");
455	return status;
456}
457
458
459static status_t
460acpi_processor_init(acpi_cpuidle_driver_info *device)
461{
462	// get the CPU index
463	dprintf("get acpi processor @%p\n", device->acpi_cookie);
464
465	acpi_data buffer;
466	buffer.pointer = NULL;
467	buffer.length = ACPI_ALLOCATE_BUFFER;
468	status_t status = device->acpi->evaluate_method(device->acpi_cookie, NULL,
469		NULL, &buffer);
470	if (status != B_OK) {
471		dprintf("failed to get processor obj\n");
472		return status;
473	}
474
475	acpi_object_type *object = (acpi_object_type *)buffer.pointer;
476	dprintf("acpi cpu%" B_PRId32 ": P_BLK at %#x/%lu\n",
477		object->data.processor.cpu_id,
478		object->data.processor.pblk_address,
479		object->data.processor.pblk_length);
480
481	int32 cpuIndex = object->data.processor.cpu_id;
482	free(buffer.pointer);
483
484	if (cpuIndex < 0 || cpuIndex >= smp_get_num_cpus())
485		return B_ERROR;
486
487	device->cpuIndex = cpuIndex;
488	sAcpiProcessor[cpuIndex] = device;
489
490	// If nodes for all processors have been registered, init the idle callback.
491	for (int32 i = smp_get_num_cpus() - 1; i >= 0; i--) {
492		if (sAcpiProcessor[i] == NULL)
493			return B_OK;
494	}
495
496	if (intel_cpuidle_init() == B_OK)
497		return B_OK;
498
499	status = acpi_cpuidle_init();
500	if (status != B_OK)
501		sAcpiProcessor[cpuIndex] = NULL;
502
503	return status;
504}
505
506
507static float
508acpi_cpuidle_support(device_node *parent)
509{
510	const char *bus;
511	uint32 device_type;
512
513	dprintf("acpi_cpuidle_support\n");
514	// make sure parent is really the ACPI bus manager
515	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
516		return -1;
517
518	if (strcmp(bus, "acpi") != 0)
519		return 0.0;
520
521	// check whether it's really a cpu Device
522	if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM,
523			&device_type, false) != B_OK
524		|| device_type != ACPI_TYPE_PROCESSOR) {
525		return 0.0;
526	}
527
528	return 0.6;
529}
530
531
532static status_t
533acpi_cpuidle_register_device(device_node *node)
534{
535	device_attr attrs[] = {
536		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "ACPI CPU IDLE" }},
537		{ NULL }
538	};
539
540	dprintf("acpi_cpuidle_register_device\n");
541	return sDeviceManager->register_node(node, ACPI_CPUIDLE_MODULE_NAME, attrs,
542		NULL, NULL);
543}
544
545
546static status_t
547acpi_cpuidle_init_driver(device_node *node, void **driverCookie)
548{
549	dprintf("acpi_cpuidle_init_driver\n");
550	acpi_cpuidle_driver_info *device;
551	device = (acpi_cpuidle_driver_info *)calloc(1, sizeof(*device));
552	if (device == NULL)
553		return B_NO_MEMORY;
554
555	device->node = node;
556
557	device_node *parent;
558	parent = sDeviceManager->get_parent_node(node);
559	sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
560		(void **)&device->acpi_cookie);
561	sDeviceManager->put_node(parent);
562
563	status_t status = acpi_processor_init(device);
564	if (status != B_OK) {
565		free(device);
566		return status;
567	}
568
569	*driverCookie = device;
570	return B_OK;
571}
572
573
574static void
575acpi_cpuidle_uninit_driver(void *driverCookie)
576{
577	dprintf("acpi_cpuidle_uninit_driver");
578	acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info *)driverCookie;
579	// TODO: When the first device to be unregistered, we'd need to balance the
580	// gIdle->AddDevice() call, but ATM isn't any API for that.
581	sAcpiProcessor[device->cpuIndex] = NULL;
582	free(device);
583}
584
585
586module_dependency module_dependencies[] = {
587	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
588	{ B_ACPI_MODULE_NAME, (module_info **)&sAcpi},
589	{ B_CPUIDLE_MODULE_NAME, (module_info **)&gIdle },
590	{}
591};
592
593
594static driver_module_info sAcpiidleModule = {
595	{
596		ACPI_CPUIDLE_MODULE_NAME,
597		0,
598		NULL
599	},
600
601	acpi_cpuidle_support,
602	acpi_cpuidle_register_device,
603	acpi_cpuidle_init_driver,
604	acpi_cpuidle_uninit_driver,
605	NULL,
606	NULL,	// rescan
607	NULL,	// removed
608};
609
610
611module_info *modules[] = {
612	(module_info *)&sAcpiidleModule,
613	NULL
614};
615