diff options
Diffstat (limited to 'usr/src/uts/i86pc/io/cpudrv_plat.c')
-rw-r--r-- | usr/src/uts/i86pc/io/cpudrv_plat.c | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/usr/src/uts/i86pc/io/cpudrv_plat.c b/usr/src/uts/i86pc/io/cpudrv_plat.c deleted file mode 100644 index a9eced0141..0000000000 --- a/usr/src/uts/i86pc/io/cpudrv_plat.c +++ /dev/null @@ -1,312 +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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * CPU power management driver platform support. - */ - -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/cpupm.h> -#include <sys/cpudrv_plat.h> -#include <sys/cpudrv.h> -#include <sys/speedstep.h> -#include <sys/pwrnow.h> -#include <sys/machsystm.h> - -/* - * Different processor families have their own technologies for supporting - * CPU power management (i.e., Intel has Enhanced SpeedStep for some of it's - * processors and AMD has PowerNow! for some of it's processors). We support - * these different technologies via modules that export the interfaces - * described below. - * - * If a module implements the technology that should be used to manage - * the current CPU device, then the cpum_init() module should return - * succesfully (i.e., return code of 0) and perform any initialization - * such that future power transistions can be performed by calling - * the cpum_power() interface(). And the cpum_fini() interface can be - * used to free any resources allocated by cpum_init(). - */ -struct cpudrv_module_ops { - char *cm_label; - int (*cpum_init)(cpudrv_devstate_t *); - void (*cpum_fini)(cpudrv_devstate_t *); - int (*cpum_power)(cpudrv_devstate_t *, uint32_t); -}; - -/* - * Interfaces for modules implementing Intel's Enhanced SpeedStep. - */ -static struct cpudrv_module_ops speedstep_ops = { - "Enhanced SpeedStep Technology", - speedstep_init, - speedstep_fini, - speedstep_power, -}; - -/* - * Interfaces for modules implementing AMD's PowerNow!. - */ -static struct cpudrv_module_ops pwrnow_ops = { - "PowerNow! Technology", - pwrnow_init, - pwrnow_fini, - pwrnow_power -}; - -/* - * Table of supported modules. - */ -static struct cpudrv_module_ops *cpudrv_module_ops_table[] = { - &speedstep_ops, - &pwrnow_ops, - NULL -}; -static struct cpudrv_module_ops **cpumops; - -/* - * Constants used by the Processor Device Notification handler - * that identify what kind of change has occurred. We currently - * only handle PPC_CHANGE_NOTIFICATION. The other two are - * ignored. - */ -#define PPC_CHANGE_NOTIFICATION 0x80 -#define CST_CHANGE_NOTIFICATION 0x81 -#define TPC_CHANGE_NOTIFICATION 0x82 - -/* - * Note that our driver numbers the power levels from lowest to - * highest starting at 1 (i.e., the lowest power level is 1 and - * the highest power level is cpupm->num_spd). The x86 modules get - * their power levels from ACPI which numbers power levels from - * highest to lowest starting at 0 (i.e., the lowest power level - * is (cpupm->num_spd - 1) and the highest power level is 0). So to - * map one of our driver power levels to one understood by ACPI we - * simply subtract our driver power level from cpupm->num_spd. Likewise, - * to map an ACPI power level to the proper driver power level, we - * subtract the ACPI power level from cpupm->num_spd. - */ -#define PM_2_PLAT_LEVEL(cpupm, pm_level) (cpupm->num_spd - pm_level) -#define PLAT_2_PM_LEVEL(cpupm, plat_level) (cpupm->num_spd - plat_level) - -/* - * Change CPU speed using interface provided by module. - */ -int -cpudrv_pm_change_speed(cpudrv_devstate_t *cpudsp, cpudrv_pm_spd_t *new_spd) -{ - cpudrv_pm_t *cpupm; - uint32_t plat_level; - int ret; - - cpupm = &(cpudsp->cpudrv_pm); - plat_level = PM_2_PLAT_LEVEL(cpupm, new_spd->pm_level); - ret = (*cpumops)->cpum_power(cpudsp, plat_level); - if (ret != 0) - return (DDI_FAILURE); - return (DDI_SUCCESS); -} - -/* - * Determine the cpu_id for the CPU device. - */ -boolean_t -cpudrv_pm_get_cpu_id(dev_info_t *dip, processorid_t *cpu_id) -{ - return ((*cpu_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "reg", -1)) != -1); - -} - -/* - * All CPU instances have been initialized successfully. - */ -boolean_t -cpudrv_pm_all_instances_ready(void) -{ - return (cpupm_is_ready()); -} - -/* - * Is the current thread the thread that is handling the - * PPC change notification? - */ -boolean_t -cpudrv_pm_is_throttle_thread(cpudrv_pm_t *cpupm) -{ - return (curthread == cpupm->pm_throttle_thread); -} - -/* - * See if a module exists for managing power for this CPU. - */ -boolean_t -cpudrv_pm_init_module(cpudrv_devstate_t *cpudsp) -{ - /* - * Loop through the CPU management module table and see if - * any of the modules implement CPU power management - * for this CPU. - */ - for (cpumops = cpudrv_module_ops_table; *cpumops != NULL; cpumops++) { - if ((*cpumops)->cpum_init(cpudsp) == 0) - break; - } - - /* - * Nope, we can't power manage this CPU. - */ - if (*cpumops == NULL) { - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * Free any resources associated with the power management module. - */ -void -cpudrv_pm_free_module(cpudrv_devstate_t *cpudsp) -{ - (*cpumops)->cpum_fini(cpudsp); -} - -/* - * This routine changes the top speed to which the CPUs can transition by: - * - * - Resetting the up_spd for all speeds lower than the new top speed - * to point to the new top speed. - * - Updating the framework with a new "normal" (maximum power) for this - * device. - */ -void -cpudrv_pm_set_topspeed(void *ctx, int plat_level) -{ - cpudrv_devstate_t *cpudsp; - cpudrv_pm_t *cpupm; - cpudrv_pm_spd_t *spd; - cpudrv_pm_spd_t *top_spd; - dev_info_t *dip; - int pm_level; - int instance; - int i; - - dip = ctx; - instance = ddi_get_instance(dip); - cpudsp = ddi_get_soft_state(cpudrv_state, instance); - ASSERT(cpudsp != NULL); - - mutex_enter(&cpudsp->lock); - cpupm = &(cpudsp->cpudrv_pm); - pm_level = PLAT_2_PM_LEVEL(cpupm, plat_level); - for (i = 0, spd = cpupm->head_spd; spd; i++, spd = spd->down_spd) { - /* - * Don't mess with speeds that are higher than the new - * top speed. They should be out of range anyway. - */ - if (spd->pm_level > pm_level) - continue; - /* - * This is the new top speed. - */ - if (spd->pm_level == pm_level) - top_spd = spd; - - spd->up_spd = top_spd; - } - cpupm->targ_spd = top_spd; - - cpupm->pm_throttle_thread = curthread; - - mutex_exit(&cpudsp->lock); - - (void) pm_update_maxpower(dip, 0, top_spd->pm_level); -} - -/* - * This routine reads the ACPI _PPC object. It's accessed as a callback - * by the ppm driver whenever a _PPC change notification is received. - */ -int -cpudrv_pm_get_topspeed(void *ctx) -{ - cpu_acpi_handle_t handle; - cpudrv_devstate_t *cpudsp; - dev_info_t *dip; - int instance; - int plat_level; - - dip = ctx; - instance = ddi_get_instance(dip); - cpudsp = ddi_get_soft_state(cpudrv_state, instance); - ASSERT(cpudsp != NULL); - handle = cpudsp->acpi_handle; - - cpu_acpi_cache_ppc(handle); - plat_level = CPU_ACPI_PPC(handle); - return (plat_level); -} - -/* - * This notification handler is called whenever the ACPI _PPC - * object changes. The _PPC is a sort of governor on power levels. - * It sets an upper threshold on which, _PSS defined, power levels - * are usuable. The _PPC value is dynamic and may change as properties - * (i.e., thermal or AC source) of the system change. - */ -/* ARGSUSED */ -void -cpudrv_pm_ppc_notify_handler(ACPI_HANDLE obj, UINT32 val, void *ctx) -{ - /* - * We only handle _PPC change notifications. - */ - if (val == PPC_CHANGE_NOTIFICATION) - cpudrv_pm_redefine_topspeed(ctx); -} - -void -cpudrv_pm_redefine_topspeed(void *ctx) -{ - /* - * This should never happen, unless ppm does not get loaded. - */ - if (cpupm_redefine_topspeed == NULL) { - cmn_err(CE_WARN, "cpudrv_pm_redefine_topspeed: " - "cpupm_redefine_topspeed has not been initialized - " - "ignoring notification"); - return; - } - - /* - * ppm callback needs to handle redefinition for all CPUs in - * the domain. - */ - (*cpupm_redefine_topspeed)(ctx); -} |