10e751525SEric Saxe /* 20e751525SEric Saxe * CDDL HEADER START 30e751525SEric Saxe * 40e751525SEric Saxe * The contents of this file are subject to the terms of the 50e751525SEric Saxe * Common Development and Distribution License (the "License"). 60e751525SEric Saxe * You may not use this file except in compliance with the License. 70e751525SEric Saxe * 80e751525SEric Saxe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90e751525SEric Saxe * or http://www.opensolaris.org/os/licensing. 100e751525SEric Saxe * See the License for the specific language governing permissions 110e751525SEric Saxe * and limitations under the License. 120e751525SEric Saxe * 130e751525SEric Saxe * When distributing Covered Code, include this CDDL HEADER in each 140e751525SEric Saxe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150e751525SEric Saxe * If applicable, add the following below this CDDL HEADER, with the 160e751525SEric Saxe * fields enclosed by brackets "[]" replaced with your own identifying 170e751525SEric Saxe * information: Portions Copyright [yyyy] [name of copyright owner] 180e751525SEric Saxe * 190e751525SEric Saxe * CDDL HEADER END 200e751525SEric Saxe */ 210e751525SEric Saxe /* 220e751525SEric Saxe * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230e751525SEric Saxe * Use is subject to license terms. 240e751525SEric Saxe */ 25*444f66e7SMark Haywood /* 26*444f66e7SMark Haywood * Copyright (c) 2009, Intel Corporation. 27*444f66e7SMark Haywood * All Rights Reserved. 28*444f66e7SMark Haywood */ 290e751525SEric Saxe 300e751525SEric Saxe #ifndef _CPUPM_MACH_H 310e751525SEric Saxe #define _CPUPM_MACH_H 320e751525SEric Saxe 330e751525SEric Saxe #ifdef __cplusplus 340e751525SEric Saxe extern "C" { 350e751525SEric Saxe #endif 360e751525SEric Saxe 370e751525SEric Saxe #include <sys/ddi.h> 380e751525SEric Saxe #include <sys/sunddi.h> 390e751525SEric Saxe #include <sys/cpuvar.h> 400e751525SEric Saxe #include <sys/ksynch.h> 410e751525SEric Saxe #include <sys/cpu_pm.h> 420e751525SEric Saxe 430e751525SEric Saxe /* 440e751525SEric Saxe * CPU power domains 450e751525SEric Saxe */ 460e751525SEric Saxe typedef struct cpupm_state_domains { 470e751525SEric Saxe struct cpupm_state_domains *pm_next; 480e751525SEric Saxe uint32_t pm_domain; 490e751525SEric Saxe uint32_t pm_type; 500e751525SEric Saxe cpuset_t pm_cpus; 510e751525SEric Saxe kmutex_t pm_lock; 520e751525SEric Saxe } cpupm_state_domains_t; 530e751525SEric Saxe 540e751525SEric Saxe extern cpupm_state_domains_t *cpupm_pstate_domains; 550e751525SEric Saxe extern cpupm_state_domains_t *cpupm_tstate_domains; 560e751525SEric Saxe extern cpupm_state_domains_t *cpupm_cstate_domains; 570e751525SEric Saxe 580e751525SEric Saxe /* 590e751525SEric Saxe * Different processor families have their own technologies for supporting 600e751525SEric Saxe * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its 610e751525SEric Saxe * processors and AMD has PowerNow! for some of its processors). We support 620e751525SEric Saxe * these different technologies via modules that export the interfaces 630e751525SEric Saxe * described below. 640e751525SEric Saxe * 650e751525SEric Saxe * If a module implements the technology that should be used to manage 660e751525SEric Saxe * the current CPU device, then the cpus_init() module should return 670e751525SEric Saxe * succesfully (i.e., return code of 0) and perform any initialization 680e751525SEric Saxe * such that future power transistions can be performed by calling 690e751525SEric Saxe * the cpus_change() interface. And the cpups_fini() interface can be 700e751525SEric Saxe * used to free any resources allocated by cpus_init(). 710e751525SEric Saxe */ 720e751525SEric Saxe typedef struct cpupm_state_ops { 730e751525SEric Saxe char *cpups_label; 740e751525SEric Saxe int (*cpus_init)(cpu_t *); 750e751525SEric Saxe void (*cpus_fini)(cpu_t *); 760e751525SEric Saxe void (*cpus_change)(cpuset_t, uint32_t); 77*444f66e7SMark Haywood void (*cpus_stop)(cpu_t *); 780e751525SEric Saxe } cpupm_state_ops_t; 790e751525SEric Saxe 800e751525SEric Saxe /* 810e751525SEric Saxe * Data kept for each C-state power-domain. 820e751525SEric Saxe */ 830e751525SEric Saxe typedef struct cma_c_state { 840e751525SEric Saxe uint32_t cs_next_cstate; /* computed best C-state */ 850e751525SEric Saxe 860e751525SEric Saxe uint32_t cs_cnt; /* times accessed */ 870e751525SEric Saxe uint32_t cs_type; /* current ACPI idle type */ 880e751525SEric Saxe 890e751525SEric Saxe hrtime_t cs_idle_enter; /* entered idle */ 900e751525SEric Saxe hrtime_t cs_idle_exit; /* left idle */ 910e751525SEric Saxe 920e751525SEric Saxe hrtime_t cs_smpl_start; /* accounting sample began */ 930e751525SEric Saxe hrtime_t cs_idle; /* time idle */ 940e751525SEric Saxe hrtime_t cs_smpl_len; /* sample duration */ 950e751525SEric Saxe hrtime_t cs_smpl_idle; /* idle time in last sample */ 960e751525SEric Saxe uint64_t cs_smpl_idle_pct; /* % idle time in last smpl */ 970e751525SEric Saxe } cma_c_state_t; 980e751525SEric Saxe 990e751525SEric Saxe typedef union cma_state { 1000e751525SEric Saxe cma_c_state_t *cstate; 1010e751525SEric Saxe uint32_t pstate; 1020e751525SEric Saxe } cma_state_t; 1030e751525SEric Saxe 1040e751525SEric Saxe typedef struct cpupm_mach_acpi_state { 1050e751525SEric Saxe cpupm_state_ops_t *cma_ops; 1060e751525SEric Saxe cpupm_state_domains_t *cma_domain; 1070e751525SEric Saxe cma_state_t cma_state; 1080e751525SEric Saxe } cpupm_mach_acpi_state_t; 1090e751525SEric Saxe 1100e751525SEric Saxe typedef struct cpupm_mach_state { 1110e751525SEric Saxe void *ms_acpi_handle; 1120e751525SEric Saxe cpupm_mach_acpi_state_t ms_pstate; 1130e751525SEric Saxe cpupm_mach_acpi_state_t ms_cstate; 1140e751525SEric Saxe cpupm_mach_acpi_state_t ms_tstate; 1150e751525SEric Saxe uint32_t ms_caps; 1160e751525SEric Saxe dev_info_t *ms_dip; 1170e751525SEric Saxe kmutex_t ms_lock; 118e5bbdc06SRafael Vanoni void *ms_vendor; 1190e751525SEric Saxe struct cpupm_notification *ms_handlers; 1200e751525SEric Saxe } cpupm_mach_state_t; 1210e751525SEric Saxe 1220e751525SEric Saxe /* 1230e751525SEric Saxe * Constants used by the Processor Device Notification handler 1240e751525SEric Saxe * that identify what kind of change has occurred. 1250e751525SEric Saxe */ 1260e751525SEric Saxe #define CPUPM_PPC_CHANGE_NOTIFICATION 0x80 1270e751525SEric Saxe #define CPUPM_CST_CHANGE_NOTIFICATION 0x81 1280e751525SEric Saxe #define CPUPM_TPC_CHANGE_NOTIFICATION 0x82 1290e751525SEric Saxe 1300e751525SEric Saxe typedef void (*CPUPM_NOTIFY_HANDLER)(void *handle, uint32_t val, 1310e751525SEric Saxe void *ctx); 1320e751525SEric Saxe 1330e751525SEric Saxe typedef struct cpupm_notification { 1340e751525SEric Saxe struct cpupm_notification *nq_next; 1350e751525SEric Saxe CPUPM_NOTIFY_HANDLER nq_handler; 1360e751525SEric Saxe void *nq_ctx; 1370e751525SEric Saxe } cpupm_notification_t; 1380e751525SEric Saxe 1390e751525SEric Saxe /* 1400e751525SEric Saxe * If any states are added, then make sure to add them to 1410e751525SEric Saxe * CPUPM_ALL_STATES. 1420e751525SEric Saxe */ 1430e751525SEric Saxe #define CPUPM_NO_STATES 0x00 1440e751525SEric Saxe #define CPUPM_P_STATES 0x01 1450e751525SEric Saxe #define CPUPM_T_STATES 0x02 1460e751525SEric Saxe #define CPUPM_C_STATES 0x04 1470e751525SEric Saxe #define CPUPM_ALL_STATES (CPUPM_P_STATES \ 1480e751525SEric Saxe | CPUPM_T_STATES \ 1490e751525SEric Saxe | CPUPM_C_STATES) 1500e751525SEric Saxe 1510e751525SEric Saxe /* 1520e751525SEric Saxe * An error in initializing any of the CPU PM results in disabling 1530e751525SEric Saxe * CPU power management. 1540e751525SEric Saxe */ 1550e751525SEric Saxe #define CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES) 1560e751525SEric Saxe 1570e751525SEric Saxe #define CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000) 1580e751525SEric Saxe 1590e751525SEric Saxe /* 1600e751525SEric Saxe * Callbacks used for CPU power management. 1610e751525SEric Saxe */ 162*444f66e7SMark Haywood extern void (*cpupm_ppm_alloc_pstate_domains)(cpu_t *); 163*444f66e7SMark Haywood extern void (*cpupm_ppm_free_pstate_domains)(cpu_t *); 1640e751525SEric Saxe extern void (*cpupm_redefine_topspeed)(void *); 1650e751525SEric Saxe extern int (*cpupm_get_topspeed_callb)(void *); 1660e751525SEric Saxe extern void (*cpupm_set_topspeed_callb)(void *, int); 1670e751525SEric Saxe 1680e751525SEric Saxe extern void cpupm_init(cpu_t *); 169*444f66e7SMark Haywood extern void cpupm_fini(cpu_t *); 170*444f66e7SMark Haywood extern void cpupm_start(cpu_t *); 171*444f66e7SMark Haywood extern void cpupm_stop(cpu_t *); 172*444f66e7SMark Haywood extern boolean_t cpupm_is_ready(cpu_t *); 1730e751525SEric Saxe extern boolean_t cpupm_is_enabled(uint32_t); 1740e751525SEric Saxe extern void cpupm_disable(uint32_t); 1750e751525SEric Saxe extern void cpupm_alloc_domains(cpu_t *, int); 1760e751525SEric Saxe extern void cpupm_free_domains(cpupm_state_domains_t **); 177*444f66e7SMark Haywood extern void cpupm_remove_domains(cpu_t *, int, cpupm_state_domains_t **); 1780e751525SEric Saxe extern void cpupm_alloc_ms_cstate(cpu_t *cp); 1790e751525SEric Saxe extern void cpupm_free_ms_cstate(cpu_t *cp); 1800e751525SEric Saxe extern void cpupm_state_change(cpu_t *, int, int); 1810e751525SEric Saxe extern id_t cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type); 1820e751525SEric Saxe extern uint_t cpupm_plat_state_enumerate(cpu_t *, cpupm_dtype_t, 1830e751525SEric Saxe cpupm_state_t *); 1840e751525SEric Saxe extern int cpupm_plat_change_state(cpu_t *, cpupm_state_t *); 1850e751525SEric Saxe extern uint_t cpupm_get_speeds(cpu_t *, int **); 1860e751525SEric Saxe extern void cpupm_free_speeds(int *, uint_t); 187*444f66e7SMark Haywood extern boolean_t cpupm_power_ready(cpu_t *); 188*444f66e7SMark Haywood extern boolean_t cpupm_throttle_ready(cpu_t *); 189*444f66e7SMark Haywood extern boolean_t cpupm_cstate_ready(cpu_t *); 1900e751525SEric Saxe extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *); 1910e751525SEric Saxe extern int cpupm_get_top_speed(cpu_t *); 1920e751525SEric Saxe extern void cpupm_idle_cstate_data(cma_c_state_t *, int); 1930e751525SEric Saxe extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t); 1940e751525SEric Saxe 1950e751525SEric Saxe #ifdef __cplusplus 1960e751525SEric Saxe } 1970e751525SEric Saxe #endif 1980e751525SEric Saxe 1990e751525SEric Saxe #endif /* _CPUPM_MACH_H */ 200