1*0e751525SEric Saxe /* 2*0e751525SEric Saxe * CDDL HEADER START 3*0e751525SEric Saxe * 4*0e751525SEric Saxe * The contents of this file are subject to the terms of the 5*0e751525SEric Saxe * Common Development and Distribution License (the "License"). 6*0e751525SEric Saxe * You may not use this file except in compliance with the License. 7*0e751525SEric Saxe * 8*0e751525SEric Saxe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*0e751525SEric Saxe * or http://www.opensolaris.org/os/licensing. 10*0e751525SEric Saxe * See the License for the specific language governing permissions 11*0e751525SEric Saxe * and limitations under the License. 12*0e751525SEric Saxe * 13*0e751525SEric Saxe * When distributing Covered Code, include this CDDL HEADER in each 14*0e751525SEric Saxe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*0e751525SEric Saxe * If applicable, add the following below this CDDL HEADER, with the 16*0e751525SEric Saxe * fields enclosed by brackets "[]" replaced with your own identifying 17*0e751525SEric Saxe * information: Portions Copyright [yyyy] [name of copyright owner] 18*0e751525SEric Saxe * 19*0e751525SEric Saxe * CDDL HEADER END 20*0e751525SEric Saxe */ 21*0e751525SEric Saxe /* 22*0e751525SEric Saxe * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*0e751525SEric Saxe * Use is subject to license terms. 24*0e751525SEric Saxe */ 25*0e751525SEric Saxe 26*0e751525SEric Saxe #ifndef _CPUPM_MACH_H 27*0e751525SEric Saxe #define _CPUPM_MACH_H 28*0e751525SEric Saxe 29*0e751525SEric Saxe #ifdef __cplusplus 30*0e751525SEric Saxe extern "C" { 31*0e751525SEric Saxe #endif 32*0e751525SEric Saxe 33*0e751525SEric Saxe #include <sys/ddi.h> 34*0e751525SEric Saxe #include <sys/sunddi.h> 35*0e751525SEric Saxe #include <sys/cpuvar.h> 36*0e751525SEric Saxe #include <sys/ksynch.h> 37*0e751525SEric Saxe #include <sys/cpu_pm.h> 38*0e751525SEric Saxe 39*0e751525SEric Saxe /* 40*0e751525SEric Saxe * CPU power domains 41*0e751525SEric Saxe */ 42*0e751525SEric Saxe typedef struct cpupm_state_domains { 43*0e751525SEric Saxe struct cpupm_state_domains *pm_next; 44*0e751525SEric Saxe uint32_t pm_domain; 45*0e751525SEric Saxe uint32_t pm_type; 46*0e751525SEric Saxe cpuset_t pm_cpus; 47*0e751525SEric Saxe kmutex_t pm_lock; 48*0e751525SEric Saxe } cpupm_state_domains_t; 49*0e751525SEric Saxe 50*0e751525SEric Saxe extern cpupm_state_domains_t *cpupm_pstate_domains; 51*0e751525SEric Saxe extern cpupm_state_domains_t *cpupm_tstate_domains; 52*0e751525SEric Saxe extern cpupm_state_domains_t *cpupm_cstate_domains; 53*0e751525SEric Saxe 54*0e751525SEric Saxe /* 55*0e751525SEric Saxe * Different processor families have their own technologies for supporting 56*0e751525SEric Saxe * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its 57*0e751525SEric Saxe * processors and AMD has PowerNow! for some of its processors). We support 58*0e751525SEric Saxe * these different technologies via modules that export the interfaces 59*0e751525SEric Saxe * described below. 60*0e751525SEric Saxe * 61*0e751525SEric Saxe * If a module implements the technology that should be used to manage 62*0e751525SEric Saxe * the current CPU device, then the cpus_init() module should return 63*0e751525SEric Saxe * succesfully (i.e., return code of 0) and perform any initialization 64*0e751525SEric Saxe * such that future power transistions can be performed by calling 65*0e751525SEric Saxe * the cpus_change() interface. And the cpups_fini() interface can be 66*0e751525SEric Saxe * used to free any resources allocated by cpus_init(). 67*0e751525SEric Saxe */ 68*0e751525SEric Saxe typedef struct cpupm_state_ops { 69*0e751525SEric Saxe char *cpups_label; 70*0e751525SEric Saxe int (*cpus_init)(cpu_t *); 71*0e751525SEric Saxe void (*cpus_fini)(cpu_t *); 72*0e751525SEric Saxe void (*cpus_change)(cpuset_t, uint32_t); 73*0e751525SEric Saxe } cpupm_state_ops_t; 74*0e751525SEric Saxe 75*0e751525SEric Saxe /* 76*0e751525SEric Saxe * Data kept for each C-state power-domain. 77*0e751525SEric Saxe */ 78*0e751525SEric Saxe typedef struct cma_c_state { 79*0e751525SEric Saxe uint32_t cs_next_cstate; /* computed best C-state */ 80*0e751525SEric Saxe 81*0e751525SEric Saxe uint32_t cs_cnt; /* times accessed */ 82*0e751525SEric Saxe uint32_t cs_type; /* current ACPI idle type */ 83*0e751525SEric Saxe 84*0e751525SEric Saxe hrtime_t cs_idle_enter; /* entered idle */ 85*0e751525SEric Saxe hrtime_t cs_idle_exit; /* left idle */ 86*0e751525SEric Saxe 87*0e751525SEric Saxe hrtime_t cs_smpl_start; /* accounting sample began */ 88*0e751525SEric Saxe hrtime_t cs_idle; /* time idle */ 89*0e751525SEric Saxe hrtime_t cs_smpl_len; /* sample duration */ 90*0e751525SEric Saxe hrtime_t cs_smpl_idle; /* idle time in last sample */ 91*0e751525SEric Saxe uint64_t cs_smpl_idle_pct; /* % idle time in last smpl */ 92*0e751525SEric Saxe 93*0e751525SEric Saxe hrtime_t cs_C2_latency; /* C2 round trip latency */ 94*0e751525SEric Saxe hrtime_t cs_C3_latency; /* C3 round trip latency */ 95*0e751525SEric Saxe } cma_c_state_t; 96*0e751525SEric Saxe 97*0e751525SEric Saxe typedef union cma_state { 98*0e751525SEric Saxe cma_c_state_t *cstate; 99*0e751525SEric Saxe uint32_t pstate; 100*0e751525SEric Saxe } cma_state_t; 101*0e751525SEric Saxe 102*0e751525SEric Saxe typedef struct cpupm_mach_acpi_state { 103*0e751525SEric Saxe cpupm_state_ops_t *cma_ops; 104*0e751525SEric Saxe cpupm_state_domains_t *cma_domain; 105*0e751525SEric Saxe cma_state_t cma_state; 106*0e751525SEric Saxe } cpupm_mach_acpi_state_t; 107*0e751525SEric Saxe 108*0e751525SEric Saxe typedef struct cpupm_mach_state { 109*0e751525SEric Saxe void *ms_acpi_handle; 110*0e751525SEric Saxe cpupm_mach_acpi_state_t ms_pstate; 111*0e751525SEric Saxe cpupm_mach_acpi_state_t ms_cstate; 112*0e751525SEric Saxe cpupm_mach_acpi_state_t ms_tstate; 113*0e751525SEric Saxe uint32_t ms_caps; 114*0e751525SEric Saxe dev_info_t *ms_dip; 115*0e751525SEric Saxe kmutex_t ms_lock; 116*0e751525SEric Saxe struct cpupm_notification *ms_handlers; 117*0e751525SEric Saxe } cpupm_mach_state_t; 118*0e751525SEric Saxe 119*0e751525SEric Saxe /* 120*0e751525SEric Saxe * Constants used by the Processor Device Notification handler 121*0e751525SEric Saxe * that identify what kind of change has occurred. 122*0e751525SEric Saxe */ 123*0e751525SEric Saxe #define CPUPM_PPC_CHANGE_NOTIFICATION 0x80 124*0e751525SEric Saxe #define CPUPM_CST_CHANGE_NOTIFICATION 0x81 125*0e751525SEric Saxe #define CPUPM_TPC_CHANGE_NOTIFICATION 0x82 126*0e751525SEric Saxe 127*0e751525SEric Saxe typedef void (*CPUPM_NOTIFY_HANDLER)(void *handle, uint32_t val, 128*0e751525SEric Saxe void *ctx); 129*0e751525SEric Saxe 130*0e751525SEric Saxe typedef struct cpupm_notification { 131*0e751525SEric Saxe struct cpupm_notification *nq_next; 132*0e751525SEric Saxe CPUPM_NOTIFY_HANDLER nq_handler; 133*0e751525SEric Saxe void *nq_ctx; 134*0e751525SEric Saxe } cpupm_notification_t; 135*0e751525SEric Saxe 136*0e751525SEric Saxe /* 137*0e751525SEric Saxe * If any states are added, then make sure to add them to 138*0e751525SEric Saxe * CPUPM_ALL_STATES. 139*0e751525SEric Saxe */ 140*0e751525SEric Saxe #define CPUPM_NO_STATES 0x00 141*0e751525SEric Saxe #define CPUPM_P_STATES 0x01 142*0e751525SEric Saxe #define CPUPM_T_STATES 0x02 143*0e751525SEric Saxe #define CPUPM_C_STATES 0x04 144*0e751525SEric Saxe #define CPUPM_ALL_STATES (CPUPM_P_STATES \ 145*0e751525SEric Saxe | CPUPM_T_STATES \ 146*0e751525SEric Saxe | CPUPM_C_STATES) 147*0e751525SEric Saxe 148*0e751525SEric Saxe #define CPUPM_XCALL_IS_READY(cpuid) CPU_IN_SET(cpu_ready_set, (cpuid)) 149*0e751525SEric Saxe 150*0e751525SEric Saxe /* 151*0e751525SEric Saxe * An error in initializing any of the CPU PM results in disabling 152*0e751525SEric Saxe * CPU power management. 153*0e751525SEric Saxe */ 154*0e751525SEric Saxe #define CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES) 155*0e751525SEric Saxe 156*0e751525SEric Saxe #define CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000) 157*0e751525SEric Saxe 158*0e751525SEric Saxe /* 159*0e751525SEric Saxe * Callbacks used for CPU power management. 160*0e751525SEric Saxe */ 161*0e751525SEric Saxe extern void (*cpupm_rebuild_cpu_domains)(void); 162*0e751525SEric Saxe extern void (*cpupm_init_topspeed)(void); 163*0e751525SEric Saxe extern void (*cpupm_redefine_topspeed)(void *); 164*0e751525SEric Saxe extern int (*cpupm_get_topspeed_callb)(void *); 165*0e751525SEric Saxe extern void (*cpupm_set_topspeed_callb)(void *, int); 166*0e751525SEric Saxe 167*0e751525SEric Saxe extern void cpupm_init(cpu_t *); 168*0e751525SEric Saxe extern void cpupm_free(cpu_t *); 169*0e751525SEric Saxe extern boolean_t cpupm_is_ready(); 170*0e751525SEric Saxe extern boolean_t cpupm_is_enabled(uint32_t); 171*0e751525SEric Saxe extern void cpupm_disable(uint32_t); 172*0e751525SEric Saxe extern void cpupm_post_startup(); 173*0e751525SEric Saxe extern void cpupm_alloc_domains(cpu_t *, int); 174*0e751525SEric Saxe extern void cpupm_free_domains(cpupm_state_domains_t **); 175*0e751525SEric Saxe extern void cpupm_alloc_ms_cstate(cpu_t *cp); 176*0e751525SEric Saxe extern void cpupm_free_ms_cstate(cpu_t *cp); 177*0e751525SEric Saxe extern void cpupm_state_change(cpu_t *, int, int); 178*0e751525SEric Saxe extern id_t cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type); 179*0e751525SEric Saxe extern uint_t cpupm_plat_state_enumerate(cpu_t *, cpupm_dtype_t, 180*0e751525SEric Saxe cpupm_state_t *); 181*0e751525SEric Saxe extern int cpupm_plat_change_state(cpu_t *, cpupm_state_t *); 182*0e751525SEric Saxe extern uint_t cpupm_get_speeds(cpu_t *, int **); 183*0e751525SEric Saxe extern void cpupm_free_speeds(int *, uint_t); 184*0e751525SEric Saxe extern boolean_t cpupm_power_ready(void); 185*0e751525SEric Saxe extern boolean_t cpupm_throttle_ready(void); 186*0e751525SEric Saxe extern boolean_t cpupm_cstate_ready(void); 187*0e751525SEric Saxe extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *); 188*0e751525SEric Saxe extern int cpupm_get_top_speed(cpu_t *); 189*0e751525SEric Saxe extern uint32_t cpupm_next_cstate(cma_c_state_t *, hrtime_t); 190*0e751525SEric Saxe extern void cpupm_idle_cstate_data(cma_c_state_t *, int); 191*0e751525SEric Saxe extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t); 192*0e751525SEric Saxe 193*0e751525SEric Saxe #ifdef __cplusplus 194*0e751525SEric Saxe } 195*0e751525SEric Saxe #endif 196*0e751525SEric Saxe 197*0e751525SEric Saxe #endif /* _CPUPM_MACH_H */ 198