1/*
2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifdef KERNEL_PRIVATE
30
31#ifndef _KERN_PMS_H_
32#define _KERN_PMS_H_
33
34#define pmsMaxStates 64
35#define HalfwayToForever 0x7FFFFFFFFFFFFFFFULL
36#define century 790560000000000ULL
37
38typedef void (*pmsSetFunc_t)(uint32_t, uint32_t, uint32_t);	/* Function used to set hardware power state */
39typedef uint32_t (*pmsQueryFunc_t)(uint32_t, uint32_t);	/* Function used to query hardware power state */
40
41typedef struct pmsStat {
42	uint64_t	stTime[2];			/* Total time until switch to next step */
43	uint32_t	stCnt[2];			/* Number of times switched to next step */
44} pmsStat;
45
46typedef struct pmsDef {
47	uint64_t	pmsLimit;			/* Max time in this state in microseconds */
48	uint32_t	pmsStepID;			/* Unique ID for this step */
49	uint32_t	pmsSetCmd;			/* Command to select power state */
50#define pmsCngXClk  0x80000000		/* Change external clock */
51#define pmsXUnk   	0x7F			/* External clock unknown  */
52#define pmsXClk     0x7F000000		/* External clock frequency */
53#define pmsCngCPU   0x00800000		/* Change CPU parameters */
54#define pmsSync     0x00400000		/* Make changes synchronously, i.e., spin until delay finished */
55#define pmsMustCmp  0x00200000		/* Delay must complete before next change */
56#define pmsCPU      0x001F0000		/* CPU frequency */
57#define pmsCPUUnk	0x1F			/* CPU frequency unknown */
58#define pmsCngVolt  0x00008000		/* Change voltage */
59#define pmsVoltage  0x00007F00		/* Voltage */
60#define pmsVoltUnk	0x7F			/* Voltage unknown */
61#define pmsPowerID  0x000000FF		/* Identify power state to HW */
62
63/*	Special commands - various things */
64#define pmsDelay    0xFFFFFFFD		/* Delayed step, no processor or platform changes.  Timer expiration causes transition to pmsTDelay */
65#define pmsParkIt	0xFFFFFFFF		/* Enters the parked state.  No processor or platform changes.  Timers cancelled */
66#define pmsCInit	((pmsXUnk << 24) | (pmsCPUUnk << 16) | (pmsVoltUnk << 8))	/* Initial current set command value */
67/*	Note:  pmsSetFuncInd is an index into a table of function pointers and pmsSetFunc is the address
68 *	of a function.  Initially, when you create a step table, this field is set as an index into
69 *	a table of function addresses that gets passed as a parameter to pmsBuild.  When pmsBuild
70 *	internalizes the step and function tables, it converts the index to the function address.
71 */
72	union sf {
73		pmsSetFunc_t	pmsSetFunc;	/* Function used to set platform power state */
74		uint32_t	pmsSetFuncInd;	/* Index to function in function table */
75	} sf;
76
77	uint32_t	pmsDown;			/* Next state if going lower */
78	uint32_t	pmsNext;			/* Normal next state */
79	uint32_t	pmsTDelay;			/* State if command was pmsDelay and timer expired */
80} pmsDef;
81
82typedef struct pmsCtl {
83	pmsStat		(*pmsStats)[pmsMaxStates];	/* Pointer to statistics information, 0 if not enabled */
84	pmsDef		*pmsDefs[pmsMaxStates];	/* Indexed pointers to steps */
85} pmsCtl;
86
87/*
88 *	Note that this block is in the middle of the per_proc and the size (32 bytes)
89 *	can't be changed without moving it.
90 */
91
92typedef struct pmsd {
93	uint32_t	pmsState;			/* Current power management state */
94	uint32_t	pmsCSetCmd;			/* Current select command */
95	uint64_t	pmsPop;				/* Time of next step */
96	uint64_t	pmsStamp;			/* Time of transition to current state */
97	uint64_t	pmsTime;			/* Total time in this state */
98} pmsd;
99
100/*
101 *	Required power management step programs
102 */
103
104enum {
105	pmsIdle      = 0,				/* Power state in idle loop */
106	pmsNorm      = 1,				/* Normal step - usually low power */
107	pmsNormHigh  = 2,				/* Highest power in normal step */
108	pmsBoost     = 3,				/* Boost/overdrive step */
109	pmsLow       = 4,				/* Lowest non-idle power state, no transitions */
110	pmsHigh      = 5,				/* Power step for full on, no transitions */
111	pmsPrepCng   = 6,				/* Prepare for step table change */
112	pmsPrepSleep = 7,				/* Prepare for sleep */
113	pmsOverTemp  = 8,				/* Machine is too hot */
114	pmsEnterNorm = 9,				/* Enter into the normal step program */
115	pmsFree      = 10,				/* First available empty step */
116	pmsStartUp   = 0xFFFFFFFE,		/* Start stepping */
117	pmsParked    = 0xFFFFFFFF		/* Power parked - used when changing stepping table */
118};
119
120/*
121 *	Power Management Stepper Control requests
122 */
123
124enum {
125	pmsCPark = 0,					/* Parks the stepper */
126	pmsCStart = 1,					/* Starts normal steppping */
127	pmsCFLow = 2,					/* Forces low power */
128	pmsCFHigh = 3,					/* Forces high power */
129	pmsCCnfg = 4,					/* Loads new stepper program */
130	pmsCQuery = 5,					/* Query current step and state */
131	pmsCExperimental = 6,			/* Enter experimental mode */
132	pmsGCtls = 7,
133	pmsGStats = 8,
134	pmsCVID = 9,
135	pmsCFree = 10					/* Next control command to be assigned */
136};
137
138/*
139 *	User request control structure passed to sysctl
140 */
141typedef struct {
142	uint32_t	request;			/* stepper control request */
143	uint32_t	reqsize;			/* size of data */
144	void		*reqaddr;			/* read/write data buffer */
145} pmsctl_t;
146
147extern pmsCtl pmsCtls;				/* Power Management Stepper control */
148extern uint32_t pmsBroadcastWait;	/* Number of outstanding broadcasts */
149extern int pmsInstalled;
150extern int pmsExperimental;
151
152#define pmsSetFuncMax 32
153extern pmsSetFunc_t pmsFuncTab[pmsSetFuncMax];
154extern pmsQueryFunc_t pmsQueryFunc;
155extern uint32_t pmsPlatformData;
156
157extern kern_return_t pmsControl(uint32_t request, user_addr_t reqaddr, uint32_t reqsize);
158extern void pmsInit(void);
159extern void pmsStep(int timer);
160extern void pmsDown(void);
161extern void pmsSetStep(uint32_t nstep, int dir);
162extern void pmsRunLocal(uint32_t nstep);
163extern void pmsCPUSet(uint32_t sel);
164extern uint32_t pmsCPUQuery(void);
165extern uint32_t pmsCPUPackageQuery(void);
166extern void pmsCPUConf(void);
167extern void pmsCPUMachineInit(void);
168extern void pmsCPUInit(void);
169extern void pmsCPURun(uint32_t nstep);
170
171extern void pmsCPUYellowFlag(void);
172extern void pmsCPUGreenFlag(void);
173
174#ifdef __cplusplus
175extern "C" {
176#endif
177
178extern kern_return_t pmsBuild(pmsDef *pd, uint32_t pdsize, pmsSetFunc_t *functab, uint32_t platformData, pmsQueryFunc_t queryFunc);
179extern void pmsRun(uint32_t nstep);
180extern void pmsPark(void);
181extern void pmsStart(void);
182extern kern_return_t pmsCPULoadVIDTable(uint16_t *tablep, int nstates);	/* i386 only */
183extern kern_return_t pmsCPUSetPStateLimit(uint32_t limit);
184#ifdef __cplusplus
185}
186#endif
187
188#endif /* _KERN_PMS_H_ */
189#endif /* KERNEL_PRIVATE */
190