summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc/io/cpu_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/i86pc/io/cpu_acpi.c')
-rw-r--r--usr/src/uts/i86pc/io/cpu_acpi.c519
1 files changed, 0 insertions, 519 deletions
diff --git a/usr/src/uts/i86pc/io/cpu_acpi.c b/usr/src/uts/i86pc/io/cpu_acpi.c
deleted file mode 100644
index 11fe37561f..0000000000
--- a/usr/src/uts/i86pc/io/cpu_acpi.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/cpu_acpi.h>
-
-#define CPU_ACPI_PSTATES_SIZE(cnt) (cnt * sizeof (cpu_acpi_pstate_t))
-#define CPU_ACPI_PSS_SIZE (sizeof (cpu_acpi_pstate_t) / sizeof (uint32_t))
-
-/*
- * Map the dip to an ACPI handle for the device.
- */
-cpu_acpi_handle_t
-cpu_acpi_init(dev_info_t *dip)
-{
- cpu_acpi_handle_t handle;
-
- handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP);
-
- if (ACPI_FAILURE(acpica_get_handle(dip, &handle->cs_handle))) {
- kmem_free(handle, sizeof (cpu_acpi_state_t));
- return (NULL);
- }
- handle->cs_dip = dip;
- return (handle);
-}
-
-/*
- * Free any resources.
- */
-void
-cpu_acpi_fini(cpu_acpi_handle_t handle)
-{
- if (handle->cs_pstates != NULL) {
- if (CPU_ACPI_PSTATES(handle) != NULL)
- kmem_free(CPU_ACPI_PSTATES(handle),
- CPU_ACPI_PSTATES_SIZE(
- CPU_ACPI_PSTATES_COUNT(handle)));
- kmem_free(handle->cs_pstates, sizeof (cpu_acpi_pstates_t));
- }
- kmem_free(handle, sizeof (cpu_acpi_state_t));
-}
-
-/*
- * Cache the ACPI _PCT data. The _PCT data defines the interface to use
- * when making power level transitions (i.e., system IO ports, fixed
- * hardware port, etc).
- */
-int
-cpu_acpi_cache_pct(cpu_acpi_handle_t handle)
-{
- ACPI_BUFFER abuf;
- ACPI_OBJECT *obj;
- AML_RESOURCE_GENERIC_REGISTER *greg;
- cpu_acpi_pct_t *pct;
- int ret = -1;
- int i;
-
- /*
- * Fetch the _PCT (if present) for the CPU node. Since the PCT is
- * optional, non-existence is not a failure (we just consider
- * it a fixed hardware case).
- */
- CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PCT_CACHED);
- abuf.Length = ACPI_ALLOCATE_BUFFER;
- abuf.Pointer = NULL;
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle, "_PCT",
- NULL, &abuf, ACPI_TYPE_PACKAGE))) {
- CPU_ACPI_PCT(handle)[0].pc_addrspace_id =
- ACPI_ADR_SPACE_FIXED_HARDWARE;
- CPU_ACPI_PCT(handle)[1].pc_addrspace_id =
- ACPI_ADR_SPACE_FIXED_HARDWARE;
- return (1);
- }
-
- obj = abuf.Pointer;
- if (obj->Package.Count != 2) {
- cmn_err(CE_NOTE, "!cpu_acpi: _PCT package bad count %d.",
- obj->Package.Count);
- goto out;
- }
-
- /*
- * Does the package look coherent?
- */
- for (i = 0; i < obj->Package.Count; i++) {
- if (obj->Package.Elements[i].Type != ACPI_TYPE_BUFFER) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "Unexpected data in _PCT package.");
- goto out;
- }
-
- greg = (AML_RESOURCE_GENERIC_REGISTER *)
- obj->Package.Elements[i].Buffer.Pointer;
- if (greg->DescriptorType !=
- ACPI_RESOURCE_NAME_GENERIC_REGISTER) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "_PCT package has format error.");
- goto out;
- }
- if (greg->ResourceLength !=
- ACPI_AML_SIZE_LARGE(AML_RESOURCE_GENERIC_REGISTER)) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "_PCT package not right size.");
- goto out;
- }
- if (greg->AddressSpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE &&
- greg->AddressSpaceId != ACPI_ADR_SPACE_SYSTEM_IO) {
- cmn_err(CE_NOTE, "!cpu_apci: _PCT contains unsupported "
- "address space type %x", greg->AddressSpaceId);
- goto out;
- }
- }
-
- /*
- * Looks good!
- */
- for (i = 0; i < obj->Package.Count; i++) {
- greg = (AML_RESOURCE_GENERIC_REGISTER *)
- obj->Package.Elements[i].Buffer.Pointer;
- pct = &CPU_ACPI_PCT(handle)[i];
- pct->pc_addrspace_id = greg->AddressSpaceId;
- pct->pc_width = greg->BitWidth;
- pct->pc_offset = greg->BitOffset;
- pct->pc_asize = greg->AccessSize;
- pct->pc_address = greg->Address;
- }
- CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PCT_CACHED);
- ret = 0;
-out:
- AcpiOsFree(abuf.Pointer);
- return (ret);
-}
-
-/*
- * Cache the ACPI _PSD data. The _PSD data defines CPU dependencies
- * (think CPU domains).
- */
-int
-cpu_acpi_cache_psd(cpu_acpi_handle_t handle)
-{
- ACPI_BUFFER abuf;
- ACPI_OBJECT *pkg, *elements;
- cpu_acpi_psd_t *psd;
- int ret = -1;
-
- /*
- * Fetch the _PSD (if present) for the CPU node. Since the PSD is
- * optional, non-existence is not a failure (it's up to the caller
- * to determine how to handle non-existence).
- */
- CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSD_CACHED);
- abuf.Length = ACPI_ALLOCATE_BUFFER;
- abuf.Pointer = NULL;
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle, "_PSD",
- NULL, &abuf, ACPI_TYPE_PACKAGE))) {
- return (1);
- }
-
- pkg = abuf.Pointer;
- if (pkg->Package.Count != 1) {
- cmn_err(CE_NOTE, "!cpu_acpi: _PSD unsupported package "
- "count %d.", pkg->Package.Count);
- goto out;
- }
-
- if (pkg->Package.Elements[0].Type != ACPI_TYPE_PACKAGE ||
- pkg->Package.Elements[0].Package.Count != 5) {
- cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in _PSD package.");
- goto out;
- }
- elements = pkg->Package.Elements[0].Package.Elements;
- if (elements[0].Integer.Value != 5 || elements[1].Integer.Value != 0) {
- cmn_err(CE_NOTE, "!cpu_acpi: Unexpected _PSD revision.");
- goto out;
- }
- psd = &CPU_ACPI_PSD(handle);
-
- psd->pd_entries = elements[0].Integer.Value;
- psd->pd_revision = elements[1].Integer.Value;
- psd->pd_domain = elements[2].Integer.Value;
- psd->pd_type = elements[3].Integer.Value;
- psd->pd_num = elements[4].Integer.Value;
- CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSD_CACHED);
- ret = 0;
-out:
- AcpiOsFree(abuf.Pointer);
- return (ret);
-}
-
-/*
- * Cache the _PSS data. The _PSS data defines the different power levels
- * supported by the CPU and the attributes associated with each power level
- * (i.e., frequency, voltage, etc.). The power levels are number from
- * highest to lowest. That is, the highest power level is _PSS entry 0
- * and the lowest power level is the last _PSS entry.
- */
-int
-cpu_acpi_cache_pstates(cpu_acpi_handle_t handle)
-{
- ACPI_BUFFER abuf;
- ACPI_OBJECT *obj, *q, *l;
- cpu_acpi_pstate_t *pstate;
- boolean_t eot = B_FALSE;
- int ret = -1;
- int cnt;
- int i, j;
-
- /*
- * Fetch the _PSS (if present) for the CPU node. If there isn't
- * one, then CPU power management will not be possible.
- */
- CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSS_CACHED);
- abuf.Length = ACPI_ALLOCATE_BUFFER;
- abuf.Pointer = NULL;
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle, "_PSS",
- NULL, &abuf, ACPI_TYPE_PACKAGE))) {
- cmn_err(CE_NOTE, "!cpu_acpi: _PSS package not found.");
- return (1);
- }
- obj = abuf.Pointer;
- if (obj->Package.Count < 2) {
- cmn_err(CE_NOTE, "!cpu_acpi: _PSS package bad count %d.",
- obj->Package.Count);
- goto out;
- }
-
- /*
- * Does the package look coherent?
- */
- cnt = 0;
- for (i = 0, l = NULL; i < obj->Package.Count; i++, l = q) {
- if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE ||
- obj->Package.Elements[i].Package.Count !=
- CPU_ACPI_PSS_SIZE) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "Unexpected data in _PSS package.");
- goto out;
- }
-
- q = obj->Package.Elements[i].Package.Elements;
- for (j = 0; j < CPU_ACPI_PSS_SIZE; j++) {
- if (q[j].Type != ACPI_TYPE_INTEGER) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "_PSS element invalid (type)");
- goto out;
- }
- }
-
- /*
- * Ignore duplicate entries.
- */
- if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
- continue;
-
- /*
- * Some _PSS tables are larger than required
- * and unused elements are filled with patterns
- * of 0xff. Simply check here for frequency = 0xffff
- * and stop counting if found.
- */
- if (q[0].Integer.Value == 0xffff) {
- eot = B_TRUE;
- continue;
- }
-
- /*
- * We should never find a valid entry after we've hit
- * an end-of-table entry.
- */
- if (eot) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "Unexpected data in _PSS package after eot.");
- goto out;
- }
-
- /*
- * pstates must be defined in order from highest to lowest.
- */
- if (l != NULL && l[0].Integer.Value < q[0].Integer.Value) {
- cmn_err(CE_NOTE, "!cpu_acpi: "
- "_PSS package pstate definitions out of order.");
- goto out;
- }
-
- /*
- * This entry passes.
- */
- cnt++;
- }
- if (cnt == 0)
- goto out;
-
- /*
- * Yes, fill in pstate structure.
- */
- handle->cs_pstates = kmem_zalloc(sizeof (cpu_acpi_pstates_t), KM_SLEEP);
- CPU_ACPI_PSTATES_COUNT(handle) = cnt;
- CPU_ACPI_PSTATES(handle) = kmem_zalloc(CPU_ACPI_PSTATES_SIZE(cnt),
- KM_SLEEP);
- pstate = CPU_ACPI_PSTATES(handle);
- for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
- uint32_t *up;
-
- q = obj->Package.Elements[i].Package.Elements;
-
- /*
- * Skip duplicate entries.
- */
- if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
- continue;
-
- up = (uint32_t *)pstate;
- for (j = 0; j < CPU_ACPI_PSS_SIZE; j++)
- up[j] = q[j].Integer.Value;
- pstate++;
- cnt--;
- }
- CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSS_CACHED);
- ret = 0;
-out:
- AcpiOsFree(abuf.Pointer);
- return (ret);
-}
-
-/*
- * Cache the _PPC data. The _PPC simply contains an integer value which
- * represents the highest power level that a CPU should transition to.
- * That is, it's an index into the array of _PSS entries and will be
- * greater than or equal to zero.
- */
-void
-cpu_acpi_cache_ppc(cpu_acpi_handle_t handle)
-{
- ACPI_BUFFER abuf;
- ACPI_OBJECT *obj;
-
- /*
- * Fetch the _PPC (if present) for the CPU node. Since the PPC is
- * optional (I think), non-existence is not a failure.
- */
- CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PPC_CACHED);
- abuf.Length = ACPI_ALLOCATE_BUFFER;
- abuf.Pointer = NULL;
- if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle, "_PPC",
- NULL, &abuf))) {
- CPU_ACPI_PPC(handle) = 0;
- return;
- }
-
- obj = (ACPI_OBJECT *)abuf.Pointer;
- CPU_ACPI_PPC(handle) = obj->Integer.Value;
- CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PPC_CACHED);
- AcpiOsFree(abuf.Pointer);
-}
-
-/*
- * Cache the _PCT, _PSS, _PSD and _PPC data.
- */
-int
-cpu_acpi_cache_data(cpu_acpi_handle_t handle)
-{
- if (cpu_acpi_cache_pct(handle) < 0) {
- cmn_err(CE_WARN, "!cpu_acpi: error parsing _PCT for "
- "CPU instance %d", ddi_get_instance(handle->cs_dip));
- return (-1);
- }
-
- if (cpu_acpi_cache_pstates(handle) != 0) {
- cmn_err(CE_WARN, "!cpu_acpi: error parsing _PSS for "
- "CPU instance %d", ddi_get_instance(handle->cs_dip));
- return (-1);
- }
-
- if (cpu_acpi_cache_psd(handle) < 0) {
- cmn_err(CE_WARN, "!cpu_acpi: error parsing _PSD for "
- "CPU instance %d", ddi_get_instance(handle->cs_dip));
- return (-1);
- }
-
- cpu_acpi_cache_ppc(handle);
-
- return (0);
-}
-
-/*
- * Register a handler for _PPC change notifications. The _PPC
- * change notification is the means by which _P
- */
-void
-cpu_acpi_install_ppc_handler(cpu_acpi_handle_t handle,
- ACPI_NOTIFY_HANDLER handler, dev_info_t *dip)
-{
- char path[MAXNAMELEN];
- if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle,
- ACPI_DEVICE_NOTIFY, handler, dip)))
- cmn_err(CE_NOTE, "!cpu_acpi: Unable to register _PPC "
- "notify handler for %s", ddi_pathname(dip, path));
-}
-
-/*
- * Write _PDC.
- */
-int
-cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count,
- uint32_t *capabilities)
-{
- ACPI_OBJECT obj;
- ACPI_OBJECT_LIST list = { 1, &obj};
- uint32_t *buffer;
- uint32_t *bufptr;
- uint32_t bufsize;
- int i;
-
- bufsize = (count + 2) * sizeof (uint32_t);
- buffer = kmem_zalloc(bufsize, KM_SLEEP);
- buffer[0] = revision;
- buffer[1] = count;
- bufptr = &buffer[2];
- for (i = 0; i < count; i++)
- *bufptr++ = *capabilities++;
-
- obj.Type = ACPI_TYPE_BUFFER;
- obj.Buffer.Length = bufsize;
- obj.Buffer.Pointer = (void *)buffer;
-
- /*
- * _PDC is optional, so don't log failure.
- */
- if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle, "_PDC",
- &list, NULL))) {
- kmem_free(buffer, bufsize);
- return (-1);
- }
-
- kmem_free(buffer, bufsize);
- return (0);
-}
-
-/*
- * Write to system IO port.
- */
-int
-cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width)
-{
- if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) {
- cmn_err(CE_NOTE, "cpu_acpi: error writing system IO port "
- "%lx.", (long)address);
- return (-1);
- }
- return (0);
-}
-
-/*
- * Read from a system IO port.
- */
-int
-cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width)
-{
- if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) {
- cmn_err(CE_NOTE, "cpu_acpi: error reading system IO port "
- "%lx.", (long)address);
- return (-1);
- }
- return (0);
-}
-
-/*
- * Return supported frequencies.
- */
-uint_t
-cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds)
-{
- cpu_acpi_pstate_t *pstate;
- int *hspeeds;
- uint_t nspeeds;
- int i;
-
- nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
- hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP);
- for (i = 0; i < nspeeds; i++) {
- pstate = CPU_ACPI_PSTATE(handle, i);
- hspeeds[i] = CPU_ACPI_FREQ(pstate);
- }
- *speeds = hspeeds;
- return (nspeeds);
-}
-
-/*
- * Free resources allocated by cpu_acpi_get_speeds().
- */
-void
-cpu_acpi_free_speeds(int *speeds, uint_t nspeeds)
-{
- kmem_free(speeds, nspeeds * sizeof (int));
-}