11.2Sjruoho/* $NetBSD: acpi_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $ */ 21.1Sjruoho 31.1Sjruoho/*- 41.1Sjruoho * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi> 51.1Sjruoho * All rights reserved. 61.1Sjruoho * 71.1Sjruoho * Redistribution and use in source and binary forms, with or without 81.1Sjruoho * modification, are permitted provided that the following conditions 91.1Sjruoho * are met: 101.1Sjruoho * 111.1Sjruoho * 1. Redistributions of source code must retain the above copyright 121.1Sjruoho * notice, this list of conditions and the following disclaimer. 131.1Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 141.1Sjruoho * notice, this list of conditions and the following disclaimer in the 151.1Sjruoho * documentation and/or other materials provided with the distribution. 161.1Sjruoho * 171.1Sjruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 181.1Sjruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191.1Sjruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201.1Sjruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 211.1Sjruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221.1Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231.1Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241.1Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251.1Sjruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261.1Sjruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271.1Sjruoho * SUCH DAMAGE. 281.1Sjruoho */ 291.1Sjruoho#include <sys/cdefs.h> 301.2Sjruoho__KERNEL_RCSID(0, "$NetBSD: acpi_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $"); 311.1Sjruoho 321.1Sjruoho#include <sys/param.h> 331.1Sjruoho 341.1Sjruoho#include <x86/cpu.h> 351.1Sjruoho#include <x86/cputypes.h> 361.1Sjruoho#include <x86/cpuvar.h> 371.1Sjruoho 381.1Sjruoho#include <dev/acpi/acpireg.h> 391.1Sjruoho#include <dev/acpi/acpivar.h> 401.1Sjruoho#include <dev/acpi/acpi_cpu.h> 411.1Sjruoho 421.1Sjruoho#include <machine/acpi_machdep.h> 431.1Sjruoho 441.1Sjruoho#define _COMPONENT ACPI_BUS_COMPONENT 451.1SjruohoACPI_MODULE_NAME ("acpi_pdc") 461.1Sjruoho 471.1Sjruohostatic uint32_t flags = 0; 481.1Sjruoho 491.1Sjruohostatic ACPI_STATUS acpi_md_pdc_walk(ACPI_HANDLE, uint32_t,void *,void **); 501.2Sjruohostatic void acpi_md_pdc_set(ACPI_HANDLE, uint32_t); 511.1Sjruoho 521.1Sjruohouint32_t 531.1Sjruohoacpi_md_pdc(void) 541.1Sjruoho{ 551.1Sjruoho struct cpu_info *ci = curcpu(); 561.1Sjruoho uint32_t regs[4]; 571.1Sjruoho 581.1Sjruoho if (flags != 0) 591.1Sjruoho return flags; 601.1Sjruoho 611.1Sjruoho if (cpu_vendor != CPUVENDOR_IDT && 621.1Sjruoho cpu_vendor != CPUVENDOR_INTEL) 631.1Sjruoho return 0; 641.1Sjruoho 651.1Sjruoho /* 661.1Sjruoho * Basic SMP C-states (required for e.g. _CST). 671.1Sjruoho */ 681.1Sjruoho flags |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; 691.1Sjruoho 701.1Sjruoho /* 711.1Sjruoho * Claim to support dependency coordination. 721.1Sjruoho */ 731.1Sjruoho flags |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW; 741.1Sjruoho 751.1Sjruoho /* 761.1Sjruoho * If MONITOR/MWAIT is available, announce 771.1Sjruoho * support for native instructions in all C-states. 781.1Sjruoho */ 791.1Sjruoho if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) 801.1Sjruoho flags |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; 811.1Sjruoho 821.1Sjruoho /* 831.1Sjruoho * Set native P- and T-states, if available. 841.1Sjruoho */ 851.1Sjruoho if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) 861.1Sjruoho flags |= ACPICPU_PDC_P_FFH; 871.1Sjruoho 881.1Sjruoho if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) 891.1Sjruoho flags |= ACPICPU_PDC_T_FFH; 901.1Sjruoho 911.1Sjruoho /* 921.1Sjruoho * Declare support for APERF and MPERF. 931.1Sjruoho */ 941.1Sjruoho if (cpuid_level >= 0x06) { 951.1Sjruoho 961.1Sjruoho x86_cpuid(0x00000006, regs); 971.1Sjruoho 981.1Sjruoho if ((regs[2] & CPUID_DSPM_HWF) != 0) 991.1Sjruoho flags |= ACPICPU_PDC_P_HWF; 1001.1Sjruoho } 1011.1Sjruoho 1021.1Sjruoho /* 1031.1Sjruoho * As the _PDC must be evaluated before the internal namespace 1041.1Sjruoho * is built, we have no option but to walk with the interpreter. 1051.1Sjruoho */ 1061.2Sjruoho (void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 1071.1Sjruoho UINT32_MAX, acpi_md_pdc_walk, NULL, NULL, NULL); 1081.1Sjruoho 1091.1Sjruoho return flags; 1101.1Sjruoho} 1111.1Sjruoho 1121.1Sjruohostatic ACPI_STATUS 1131.2Sjruohoacpi_md_pdc_walk(ACPI_HANDLE hdl, uint32_t level, void *aux, void **sta) 1141.1Sjruoho{ 1151.2Sjruoho struct cpu_info *ci; 1161.2Sjruoho 1171.2Sjruoho ci = acpi_match_cpu_handle(hdl); 1181.2Sjruoho 1191.2Sjruoho if (ci != NULL) 1201.2Sjruoho acpi_md_pdc_set(hdl, flags); 1211.2Sjruoho 1221.2Sjruoho return AE_OK; 1231.1Sjruoho} 1241.1Sjruoho 1251.2Sjruohostatic void 1261.1Sjruohoacpi_md_pdc_set(ACPI_HANDLE hdl, uint32_t val) 1271.1Sjruoho{ 1281.1Sjruoho ACPI_OBJECT_LIST arg; 1291.1Sjruoho ACPI_OBJECT obj; 1301.1Sjruoho uint32_t cap[3]; 1311.1Sjruoho 1321.1Sjruoho arg.Count = 1; 1331.1Sjruoho arg.Pointer = &obj; 1341.1Sjruoho 1351.1Sjruoho cap[0] = ACPICPU_PDC_REVID; 1361.1Sjruoho cap[1] = 1; 1371.1Sjruoho cap[2] = val; 1381.1Sjruoho 1391.1Sjruoho obj.Type = ACPI_TYPE_BUFFER; 1401.1Sjruoho obj.Buffer.Length = sizeof(cap); 1411.1Sjruoho obj.Buffer.Pointer = (void *)cap; 1421.1Sjruoho 1431.1Sjruoho (void)AcpiEvaluateObject(hdl, "_PDC", &arg, NULL); 1441.1Sjruoho} 145