cpupm_mach.h revision 8935:5bd81ee07936
1214152Sed/*
2214152Sed * CDDL HEADER START
3214152Sed *
4214152Sed * The contents of this file are subject to the terms of the
5222656Sed * Common Development and Distribution License (the "License").
6222656Sed * You may not use this file except in compliance with the License.
7214152Sed *
8214152Sed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9214152Sed * or http://www.opensolaris.org/os/licensing.
10214152Sed * See the License for the specific language governing permissions
11214152Sed * and limitations under the License.
12214152Sed *
13214152Sed * When distributing Covered Code, include this CDDL HEADER in each
14214152Sed * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15214152Sed * If applicable, add the following below this CDDL HEADER, with the
16229135Sed * fields enclosed by brackets "[]" replaced with your own identifying
17214152Sed * information: Portions Copyright [yyyy] [name of copyright owner]
18214152Sed *
19214152Sed * CDDL HEADER END
20214152Sed */
21214152Sed/*
22214152Sed * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23214152Sed * Use is subject to license terms.
24214152Sed */
25214152Sed
26214152Sed#ifndef	_CPUPM_MACH_H
27214152Sed#define	_CPUPM_MACH_H
28214152Sed
29214152Sed#ifdef __cplusplus
30229135Sedextern "C" {
31214152Sed#endif
32214152Sed
33229135Sed#include <sys/ddi.h>
34214152Sed#include <sys/sunddi.h>
35229135Sed#include <sys/cpuvar.h>
36229135Sed#include <sys/ksynch.h>
37229135Sed#include <sys/cpu_pm.h>
38229135Sed
39229135Sed/*
40229135Sed * CPU power domains
41214152Sed */
42214152Sedtypedef struct cpupm_state_domains {
43229135Sed	struct cpupm_state_domains	*pm_next;
44214152Sed	uint32_t			pm_domain;
45229135Sed	uint32_t			pm_type;
46229135Sed	cpuset_t			pm_cpus;
47229135Sed	kmutex_t			pm_lock;
48229135Sed} cpupm_state_domains_t;
49229135Sed
50229135Sedextern cpupm_state_domains_t *cpupm_pstate_domains;
51214152Sedextern cpupm_state_domains_t *cpupm_tstate_domains;
52214152Sedextern cpupm_state_domains_t *cpupm_cstate_domains;
53229135Sed
54229135Sed/*
55214152Sed * Different processor families have their own technologies for supporting
56229135Sed * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its
57229135Sed * processors and AMD has PowerNow! for some of its processors). We support
58229135Sed * these different technologies via modules that export the interfaces
59229135Sed * described below.
60229135Sed *
61229135Sed * If a module implements the technology that should be used to manage
62229135Sed * the current CPU device, then the cpus_init() module should return
63229135Sed * succesfully (i.e., return code of 0) and perform any initialization
64214152Sed * such that future power transistions can be performed by calling
65214152Sed * the cpus_change() interface. And the cpups_fini() interface can be
66214152Sed * used to free any resources allocated by cpus_init().
67214152Sed */
68229135Sedtypedef struct cpupm_state_ops {
69229135Sed	char	*cpups_label;
70214152Sed	int	(*cpus_init)(cpu_t *);
71214152Sed	void	(*cpus_fini)(cpu_t *);
72214152Sed	void	(*cpus_change)(cpuset_t, uint32_t);
73214152Sed} cpupm_state_ops_t;
74
75/*
76 * Data kept for each C-state power-domain.
77 */
78typedef struct cma_c_state {
79	uint32_t	cs_next_cstate;	/* computed best C-state */
80
81	uint32_t	cs_cnt;		/* times accessed */
82	uint32_t	cs_type;	/* current ACPI idle type */
83
84	hrtime_t	cs_idle_enter;	/* entered idle */
85	hrtime_t	cs_idle_exit;	/* left idle */
86
87	hrtime_t	cs_smpl_start;	/* accounting sample began */
88	hrtime_t	cs_idle;	/* time idle */
89	hrtime_t	cs_smpl_len;	/* sample duration */
90	hrtime_t	cs_smpl_idle;	/* idle time in last sample */
91	uint64_t	cs_smpl_idle_pct;	/* % idle time in last smpl */
92
93	hrtime_t	cs_C2_latency;	/* C2 round trip latency */
94	hrtime_t	cs_C3_latency;	/* C3 round trip latency */
95} cma_c_state_t;
96
97typedef union cma_state {
98	cma_c_state_t	*cstate;
99	uint32_t	pstate;
100} cma_state_t;
101
102typedef struct cpupm_mach_acpi_state {
103	cpupm_state_ops_t	*cma_ops;
104	cpupm_state_domains_t   *cma_domain;
105	cma_state_t		cma_state;
106} cpupm_mach_acpi_state_t;
107
108typedef struct cpupm_mach_state {
109	void			*ms_acpi_handle;
110	cpupm_mach_acpi_state_t	ms_pstate;
111	cpupm_mach_acpi_state_t	ms_cstate;
112	cpupm_mach_acpi_state_t	ms_tstate;
113	uint32_t		ms_caps;
114	dev_info_t		*ms_dip;
115	kmutex_t		ms_lock;
116	void			*ms_vendor;
117	struct cpupm_notification *ms_handlers;
118} cpupm_mach_state_t;
119
120/*
121 * Constants used by the Processor Device Notification handler
122 * that identify what kind of change has occurred.
123 */
124#define	CPUPM_PPC_CHANGE_NOTIFICATION 0x80
125#define	CPUPM_CST_CHANGE_NOTIFICATION 0x81
126#define	CPUPM_TPC_CHANGE_NOTIFICATION 0x82
127
128typedef void (*CPUPM_NOTIFY_HANDLER)(void *handle, uint32_t val,
129    void *ctx);
130
131typedef struct cpupm_notification {
132	struct cpupm_notification	*nq_next;
133	CPUPM_NOTIFY_HANDLER		nq_handler;
134	void				*nq_ctx;
135} cpupm_notification_t;
136
137/*
138 * If any states are added, then make sure to add them to
139 * CPUPM_ALL_STATES.
140 */
141#define	CPUPM_NO_STATES		0x00
142#define	CPUPM_P_STATES		0x01
143#define	CPUPM_T_STATES		0x02
144#define	CPUPM_C_STATES		0x04
145#define	CPUPM_ALL_STATES	(CPUPM_P_STATES \
146				| CPUPM_T_STATES \
147				| CPUPM_C_STATES)
148
149#define	CPUPM_XCALL_IS_READY(cpuid) CPU_IN_SET(cpu_ready_set, (cpuid))
150
151/*
152 * An error in initializing any of the CPU PM results in disabling
153 * CPU power management.
154 */
155#define	CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES)
156
157#define	CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000)
158
159/*
160 * Callbacks used for CPU power management.
161 */
162extern void (*cpupm_rebuild_cpu_domains)(void);
163extern void (*cpupm_init_topspeed)(void);
164extern void (*cpupm_redefine_topspeed)(void *);
165extern int (*cpupm_get_topspeed_callb)(void *);
166extern void (*cpupm_set_topspeed_callb)(void *, int);
167
168extern void cpupm_init(cpu_t *);
169extern void cpupm_free(cpu_t *);
170extern boolean_t cpupm_is_ready();
171extern boolean_t cpupm_is_enabled(uint32_t);
172extern void cpupm_disable(uint32_t);
173extern void cpupm_post_startup();
174extern void cpupm_alloc_domains(cpu_t *, int);
175extern void cpupm_free_domains(cpupm_state_domains_t **);
176extern void cpupm_alloc_ms_cstate(cpu_t *cp);
177extern void cpupm_free_ms_cstate(cpu_t *cp);
178extern void cpupm_state_change(cpu_t *, int, int);
179extern id_t cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type);
180extern uint_t cpupm_plat_state_enumerate(cpu_t *, cpupm_dtype_t,
181    cpupm_state_t *);
182extern int cpupm_plat_change_state(cpu_t *, cpupm_state_t *);
183extern uint_t cpupm_get_speeds(cpu_t *, int **);
184extern void cpupm_free_speeds(int *, uint_t);
185extern boolean_t cpupm_power_ready(void);
186extern boolean_t cpupm_throttle_ready(void);
187extern boolean_t cpupm_cstate_ready(void);
188extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *);
189extern int cpupm_get_top_speed(cpu_t *);
190extern uint32_t cpupm_next_cstate(cma_c_state_t *, hrtime_t);
191extern void cpupm_idle_cstate_data(cma_c_state_t *, int);
192extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t);
193
194#ifdef __cplusplus
195}
196#endif
197
198#endif	/* _CPUPM_MACH_H */
199