4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2009, Intel Corporation.
27 * All Rights Reserved.
38 #include <sys/sunddi.h>
39 #include <sys/cpuvar.h>
40 #include <sys/ksynch.h>
41 #include <sys/cpu_pm.h>
46 typedef struct cpupm_state_domains
{
47 struct cpupm_state_domains
*pm_next
;
52 } cpupm_state_domains_t
;
54 extern cpupm_state_domains_t
*cpupm_pstate_domains
;
55 extern cpupm_state_domains_t
*cpupm_tstate_domains
;
56 extern cpupm_state_domains_t
*cpupm_cstate_domains
;
59 * Different processor families have their own technologies for supporting
60 * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its
61 * processors and AMD has PowerNow! for some of its processors). We support
62 * these different technologies via modules that export the interfaces
65 * If a module implements the technology that should be used to manage
66 * the current CPU device, then the cpus_init() module should return
67 * succesfully (i.e., return code of 0) and perform any initialization
68 * such that future power transistions can be performed by calling
69 * the cpus_change() interface. And the cpups_fini() interface can be
70 * used to free any resources allocated by cpus_init().
72 typedef struct cpupm_state_ops
{
74 int (*cpus_init
)(cpu_t
*);
75 void (*cpus_fini
)(cpu_t
*);
76 void (*cpus_change
)(cpuset_t
, uint32_t);
77 void (*cpus_stop
)(cpu_t
*);
81 * Data kept for each C-state power-domain.
83 typedef struct cma_c_state
{
84 uint32_t cs_next_cstate
; /* computed best C-state */
86 uint32_t cs_cnt
; /* times accessed */
87 uint32_t cs_type
; /* current ACPI idle type */
89 hrtime_t cs_idle_enter
; /* entered idle */
90 hrtime_t cs_idle_exit
; /* left idle */
92 hrtime_t cs_smpl_start
; /* accounting sample began */
93 hrtime_t cs_idle
; /* time idle */
94 hrtime_t cs_smpl_len
; /* sample duration */
95 hrtime_t cs_smpl_idle
; /* idle time in last sample */
96 uint64_t cs_smpl_idle_pct
; /* % idle time in last smpl */
99 typedef union cma_state
{
100 cma_c_state_t
*cstate
;
104 typedef struct cpupm_mach_acpi_state
{
105 cpupm_state_ops_t
*cma_ops
;
106 cpupm_state_domains_t
*cma_domain
;
107 cma_state_t cma_state
;
108 } cpupm_mach_acpi_state_t
;
110 typedef struct cpupm_mach_turbo_info
{
111 kstat_t
*turbo_ksp
; /* turbo kstat */
112 int in_turbo
; /* in turbo? */
113 int turbo_supported
; /* turbo flag */
114 uint64_t t_mcnt
; /* turbo mcnt */
115 uint64_t t_acnt
; /* turbo acnt */
116 } cpupm_mach_turbo_info_t
;
118 typedef struct cpupm_mach_state
{
119 void *ms_acpi_handle
;
120 cpupm_mach_acpi_state_t ms_pstate
;
121 cpupm_mach_acpi_state_t ms_cstate
;
122 cpupm_mach_acpi_state_t ms_tstate
;
126 cpupm_mach_turbo_info_t
*ms_turbo
;
127 struct cpupm_notification
*ms_handlers
;
128 } cpupm_mach_state_t
;
131 * Constants used by the Processor Device Notification handler
132 * that identify what kind of change has occurred.
134 #define CPUPM_PPC_CHANGE_NOTIFICATION 0x80
135 #define CPUPM_CST_CHANGE_NOTIFICATION 0x81
136 #define CPUPM_TPC_CHANGE_NOTIFICATION 0x82
138 typedef void (*CPUPM_NOTIFY_HANDLER
)(void *handle
, uint32_t val
,
141 typedef struct cpupm_notification
{
142 struct cpupm_notification
*nq_next
;
143 CPUPM_NOTIFY_HANDLER nq_handler
;
145 } cpupm_notification_t
;
148 * If any states are added, then make sure to add them to
151 #define CPUPM_NO_STATES 0x00
152 #define CPUPM_P_STATES 0x01
153 #define CPUPM_T_STATES 0x02
154 #define CPUPM_C_STATES 0x04
155 #define CPUPM_ALL_STATES (CPUPM_P_STATES \
160 * An error in initializing any of the CPU PM results in disabling
161 * CPU power management.
163 #define CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES)
165 #define CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000)
168 * Callbacks used for CPU power management.
170 extern void (*cpupm_ppm_alloc_pstate_domains
)(cpu_t
*);
171 extern void (*cpupm_ppm_free_pstate_domains
)(cpu_t
*);
172 extern void (*cpupm_redefine_topspeed
)(void *);
173 extern int (*cpupm_get_topspeed_callb
)(void *);
174 extern void (*cpupm_set_topspeed_callb
)(void *, int);
176 extern void cpupm_init(cpu_t
*);
177 extern void cpupm_fini(cpu_t
*);
178 extern void cpupm_start(cpu_t
*);
179 extern void cpupm_stop(cpu_t
*);
180 extern boolean_t
cpupm_is_ready(cpu_t
*);
181 extern boolean_t
cpupm_is_enabled(uint32_t);
182 extern void cpupm_disable(uint32_t);
183 extern void cpupm_alloc_domains(cpu_t
*, int);
184 extern void cpupm_free_domains(cpupm_state_domains_t
**);
185 extern void cpupm_remove_domains(cpu_t
*, int, cpupm_state_domains_t
**);
186 extern void cpupm_alloc_ms_cstate(cpu_t
*cp
);
187 extern void cpupm_free_ms_cstate(cpu_t
*cp
);
188 extern void cpupm_state_change(cpu_t
*, int, int);
189 extern id_t
cpupm_plat_domain_id(cpu_t
*cp
, cpupm_dtype_t type
);
190 extern uint_t
cpupm_plat_state_enumerate(cpu_t
*, cpupm_dtype_t
,
192 extern int cpupm_plat_change_state(cpu_t
*, cpupm_state_t
*);
193 extern uint_t
cpupm_get_speeds(cpu_t
*, int **);
194 extern void cpupm_free_speeds(int *, uint_t
);
195 extern boolean_t
cpupm_power_ready(cpu_t
*);
196 extern boolean_t
cpupm_throttle_ready(cpu_t
*);
197 extern boolean_t
cpupm_cstate_ready(cpu_t
*);
198 extern void cpupm_add_notify_handler(cpu_t
*, CPUPM_NOTIFY_HANDLER
, void *);
199 extern int cpupm_get_top_speed(cpu_t
*);
200 extern void cpupm_idle_cstate_data(cma_c_state_t
*, int);
201 extern void cpupm_wakeup_cstate_data(cma_c_state_t
*, hrtime_t
);
202 extern void cpupm_record_turbo_info(cpupm_mach_turbo_info_t
*, uint32_t,
204 extern cpupm_mach_turbo_info_t
*cpupm_turbo_init(cpu_t
*);
205 extern void cpupm_turbo_fini(cpupm_mach_turbo_info_t
*);
211 #endif /* _CPUPM_MACH_H */