xref: /illumos-gate/usr/src/uts/common/sys/ppmvar.h (revision 160abee025ef30c34521b981edd40ffcaab560aa)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SYS_PPMVAR_H
27 #define	_SYS_PPMVAR_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include <sys/epm.h>
32 #include <sys/sunldi.h>
33 
34 #ifdef	__cplusplus
35 extern "C" {
36 #endif
37 
38 
39 typedef struct ppm_unit {
40 	dev_info_t	*dip;		/* node dev info */
41 	kmutex_t	lock;		/* global driver lock */
42 	uint_t		states;		/* driver states */
43 	timeout_id_t	led_tid;	/* timeout id for LED */
44 } ppm_unit_t;
45 
46 /*
47  * driver states
48  */
49 #define	PPM_STATE_SUSPENDED	0x1	/* driver is suspended */
50 
51 /*
52  * Check for domain operational
53  */
54 #define	PPM_DOMAIN_UP(domp)	(!(domp->dflags & PPMD_OFFLINE))
55 
56 /*
57  * LED constants
58  */
59 #define	PPM_LED_PULSE		(drv_usectohz(250000))	/* 0.25 seconds */
60 #define	PPM_LEDON_INTERVAL	(1 * PPM_LED_PULSE)
61 #define	PPM_LEDOFF_INTERVAL	(8 * PPM_LED_PULSE)
62 #define	PPM_LEDON		1	/* (s10) */
63 #define	PPM_LEDOFF		0	/* (s10) */
64 
65 /*
66  * internal form of "ppm.conf" data
67  */
68 struct ppm_db {
69 	struct ppm_db	*next;
70 	char		*name;		/* device name */
71 	int		plen;		/* strlen before wildcard(s10) */
72 	int		wccnt;		/* upto 2 '*' allowed */
73 	int		wcpos[2];	/* '*' location in pathname */
74 };
75 typedef struct ppm_db ppm_db_t;
76 
77 struct ppm_cdata {
78 	char *name;			/* property name */
79 	char **strings;			/* string array */
80 	uint_t cnt;			/* property count */
81 };
82 
83 /*
84  * ppm device info
85  */
86 struct ppm_dev {
87 	struct ppm_dev	*next;
88 	struct ppm_domain *domp;
89 	dev_info_t	*dip;
90 	char		*path;		/* OBP device pathname */
91 	int		cmpt;		/* component number */
92 	int		rplvl;		/* last requested power level */
93 	int		level;		/* actual current power level */
94 	int		lowest;		/* lowest power level for device */
95 	int		highest;	/* highest power level for device */
96 	uint_t		flags;
97 };
98 typedef struct ppm_dev ppm_dev_t;
99 
100 /*
101  * ppm_dev.flags field
102  */
103 #define	PPMDEV_PCI66_D2		0x1	/* device support D2 at pci 66mhz */
104 #define	PPMDEV_PCI_PROP_CLKPM	0x2	/* clock can be power managed */
105 #define	PPM_PM_POWEROP		0x10	/* power level change, initiated  */
106 					/* from PM is in progress.	  */
107 #define	PPM_PHC_WHILE_SET_POWER 0x20	/* power level of a device is	  */
108 					/* changed through		  */
109 					/* pm_power_has_changed path	  */
110 					/* while power level change,	  */
111 					/* initiated from PM is in	  */
112 					/* progress.			  */
113 
114 
115 /*
116  * per domain record of device _ever_ managed by ppm
117  */
118 struct ppm_owned {
119 	struct ppm_owned *next;
120 	char	*path;		/* device pathname */
121 	int	initializing;	/* initializing  flag */
122 };
123 typedef struct ppm_owned ppm_owned_t;
124 
125 
126 /*
127  * domain control data structure -
128  *   when you need to do an op for a domain, look up the op in the
129  *   cmd member of the struct, and then perform the method on the
130  *   path using iowr cmd with the args specified in val or val and
131  *   mask or the speed index.
132  */
133 struct ppm_dc {
134 	struct ppm_dc	*next;
135 	ldi_handle_t	lh;	/* layered (ldi) handle			*/
136 	char	*path;		/* control device prom pathname		*/
137 	uint_t	cmd;		/* search key: op to be performed	*/
138 				/* one of: PPMDC_CPU_NEXT		*/
139 				/* PPMDC_CPU_GO, PPMDC_FET_ON,		*/
140 				/* PPMDC_FET_OFF, PPMDC_LED_ON,		*/
141 				/* PPMDC_LED_OFF, PPMDC_PCI_ON,		*/
142 				/* PPMDC_ENTER_S3, PPMDC_PCI_OFF	*/
143 				/* PPMDC_EXIT_S3 commands		*/
144 	uint_t	method;		/* control method / union selector	*/
145 				/* one of PPMDC_KIO, PPMDC_I2CKIO,	*/
146 				/* PPMDC_CPUSPEEDKIO			*/
147 
148 	union {
149 		/* In each sub struct in union, the first three fields	*/
150 		/* must be .iord, .iowr and .val and in such order.	*/
151 		/* The .method field above selects a union sub struct	*/
152 		/* for a particular .cmd operation.			*/
153 		/* The association between .method and .cmd is platform	*/
154 		/* specific, therefore described in ppm.conf file.	*/
155 
156 		/* PPMDC_KIO: simple KIO 				*/
157 		struct m_kio {
158 			uint_t	iord;	/* IOCTL read cmd		*/
159 			uint_t	iowr;	/* IOCTL write cmd		*/
160 			uint_t	val;	/* ioctl arg			*/
161 			uint_t	delay;	/* total delay before this 	*/
162 					/* operation can be carried out	*/
163 			uint_t	post_delay; /* post delay, if any	*/
164 		} kio;
165 
166 #ifdef sun4u
167 		/* PPMDC_I2CKIO: KIO requires 'arg' as struct i2c_gpio	*/
168 		/*    (defined in i2c_client.h)				*/
169 		struct m_i2ckio {
170 			uint_t	iord;	/* IOCTL read cmd		*/
171 			uint_t	iowr;	/* IOCTL write cmd 		*/
172 			uint_t	val;	/* register content		*/
173 			uint_t	mask;	/* mask to select relevant bits	*/
174 					/* of register content		*/
175 			uint_t	delay;	/* total delay before this 	*/
176 					/* operation can be carried out	*/
177 			uint_t	post_delay; /* post delay, if any	*/
178 		} i2c;
179 #endif
180 
181 		/* PPMDC_CPUSPEEDKIO, PPMDC_VCORE: cpu estar related	*/
182 		/* simple KIO						*/
183 		struct m_cpu {
184 			uint_t	iord;	/* IOCTL read cmd 		*/
185 			uint_t	iowr;	/* IOCTL write cmd 		*/
186 			int	val;	/* new register value		*/
187 			uint_t	speeds;	/* number of speeds cpu supports */
188 			uint_t	delay;	/* microseconds post op delay	*/
189 		} cpu;
190 	} m_un;
191 };
192 typedef struct ppm_dc ppm_dc_t;
193 
194 /*
195  * ppm_dc.cmd field -
196  */
197 #define	PPMDC_CPU_NEXT		2
198 #define	PPMDC_PRE_CHNG		3
199 #define	PPMDC_CPU_GO		4
200 #define	PPMDC_POST_CHNG		5
201 #define	PPMDC_FET_ON		6
202 #define	PPMDC_FET_OFF		7
203 #define	PPMDC_LED_ON		8
204 #define	PPMDC_LED_OFF		9
205 #define	PPMDC_CLK_ON		10
206 #define	PPMDC_CLK_OFF		11
207 #define	PPMDC_PRE_PWR_OFF	12
208 #define	PPMDC_PRE_PWR_ON	13
209 #define	PPMDC_POST_PWR_ON	14
210 #define	PPMDC_PWR_OFF		15
211 #define	PPMDC_PWR_ON		16
212 #define	PPMDC_RESET_OFF		17
213 #define	PPMDC_RESET_ON		18
214 #define	PPMDC_ENTER_S3		19
215 #define	PPMDC_EXIT_S3		20
216 
217 /*
218  * ppm_dc.method field - select union element
219  */
220 #define	PPMDC_KIO  		1	/* simple ioctl with val as arg	*/
221 #define	PPMDC_CPUSPEEDKIO	2	/* ioctl with speed index arg	*/
222 #define	PPMDC_VCORE		3	/* CPU Vcore change operation */
223 #ifdef sun4u
224 #define	PPMDC_I2CKIO		4	/* ioctl with i2c_gpio_t as arg	*/
225 #endif
226 
227 /*
228  * devices that are powered by the same source
229  * are grouped by this struct as a "power domain"
230  */
231 struct ppm_domain {
232 	char		*name;		/* domain name */
233 	int		dflags;		/* domain flags */
234 	int		pwr_cnt;	/* number of powered up devices */
235 	ppm_db_t	*conflist;	/* all devices from ppm.conf file */
236 	ppm_dev_t	*devlist;	/* current attached devices */
237 	char		*propname;	/* domain property name */
238 	kmutex_t	lock;		/* domain lock */
239 	int		refcnt;		/* domain lock ref count */
240 	int		model;		/* pm model, CPU, FET or LED	*/
241 	int		status;		/* domain specific status */
242 	ppm_dc_t	*dc;		/* domain control method */
243 	ppm_owned_t	*owned;		/* list of ever owned devices */
244 	struct ppm_domain	*next;	/* a linked list */
245 	clock_t		last_off_time;	/* last time domain was off	*/
246 
247 };
248 typedef struct ppm_domain ppm_domain_t;
249 
250 
251 /*
252  * ppm_domain.model field -
253  */
254 #define	PPMD_CPU		1	/* cpu PM model */
255 #define	PPMD_FET		2	/* power FET pm model */
256 #define	PPMD_LED		3	/* LED pm model */
257 #define	PPMD_PCI		4	/* PCI pm model */
258 #define	PPMD_PCI_PROP		5	/* PCI_PROP pm model */
259 #define	PPMD_PCIE		6	/* PCI Express pm model */
260 #define	PPMD_SX			7	/* ACPI Sx pm model */
261 
262 #define	PPMD_IS_PCI(model) \
263 	((model) == PPMD_PCI || (model) == PPMD_PCI_PROP)
264 
265 /*
266  * ppm_domain.status field -
267  */
268 #define	PPMD_OFF		0x0	/* FET/LED/PCI clock: off */
269 #define	PPMD_ON			0x1	/* FET/LED/PCI clock: on */
270 
271 /*
272  * ppm_domain.dflags field -
273  */
274 #define	PPMD_LOCK_ONE		0x1
275 #define	PPMD_LOCK_ALL		0x4
276 #define	PPMD_PCI33MHZ		0x1000	/* 33mhz PCI slot */
277 #define	PPMD_PCI66MHZ		0x2000	/* 66mhz PCI slot */
278 #define	PPMD_INITCHILD_CLKON	0x4000	/* clk turned on in init_child */
279 #define	PPMD_OFFLINE		0x10000	/* domain is not functional */
280 #define	PPMD_CPU_READY		0x20000	/* CPU domain can process power call */
281 
282 struct ppm_domit {
283 	char	*name;
284 	int	model;
285 	int	dflags;
286 	int	status;
287 };
288 extern struct ppm_domit ppm_domit_data[];
289 
290 /*
291  * XXppm driver-specific routines called from common code (s10)
292  */
293 struct ppm_funcs {
294 	void	(*dev_init)(ppm_dev_t *);
295 	void	(*dev_fini)(ppm_dev_t *);
296 	void	(*iocset)(uint8_t);
297 	uint8_t	(*iocget)(void);
298 };
299 
300 extern ppm_domain_t	*ppm_domain_p;
301 extern void		*ppm_statep;
302 extern int		ppm_inst;
303 extern ppm_domain_t *ppm_domains[];	/* (s10) */
304 extern struct ppm_funcs ppmf;		/* (s10) */
305 
306 extern void		ppm_dev_init(ppm_dev_t *);
307 extern void		ppm_dev_fini(ppm_dev_t *);
308 extern int		ppm_create_db(dev_info_t *);
309 extern int		ppm_claim_dev(dev_info_t *);
310 extern void		ppm_rem_dev(dev_info_t *);
311 extern ppm_dev_t	*ppm_get_dev(dev_info_t *, ppm_domain_t *);
312 extern void		ppm_init_cb(dev_info_t *);
313 extern int		ppm_init_lyr(ppm_dc_t *, dev_info_t *);
314 extern ppm_domain_t	*ppm_lookup_dev(dev_info_t *);
315 extern ppm_domain_t	*ppm_lookup_domain(char *);
316 extern ppm_dc_t		*ppm_lookup_dc(ppm_domain_t *, int);
317 extern ppm_dc_t		*ppm_lookup_hndl(int, ppm_dc_t *);
318 extern ppm_domain_t	*ppm_get_domain_by_dev(const char *);
319 extern boolean_t	ppm_none_else_holds_power(ppm_domain_t *);
320 extern ppm_owned_t	*ppm_add_owned(dev_info_t *, ppm_domain_t *);
321 extern void		ppm_lock_one(ppm_dev_t *, power_req_t *, int *);
322 extern void		ppm_lock_all(ppm_domain_t *, power_req_t *, int *);
323 extern boolean_t	ppm_manage_early_cpus(dev_info_t *, int, int *);
324 extern int		ppm_change_cpu_power(ppm_dev_t *, int);
325 extern int		ppm_revert_cpu_power(ppm_dev_t *, int);
326 extern ppm_dev_t	*ppm_add_dev(dev_info_t *, ppm_domain_t *);
327 
328 #define	PPM_GET_PRIVATE(dip) \
329     DEVI(dip)->devi_pm_ppm_private
330 #define	PPM_SET_PRIVATE(dip, datap) \
331     DEVI(dip)->devi_pm_ppm_private = datap
332 
333 #define	PPM_LOCK_DOMAIN(domp) {			\
334 	if (!MUTEX_HELD(&(domp)->lock))		\
335 		mutex_enter(&(domp)->lock);	\
336 	(domp)->refcnt++;			\
337 }
338 
339 #define	PPM_UNLOCK_DOMAIN(domp) {		\
340 	ASSERT(MUTEX_HELD(&(domp)->lock) &&	\
341 		(domp)->refcnt > 0);		\
342 	if (--(domp)->refcnt == 0)		\
343 		mutex_exit(&(domp)->lock);	\
344 }
345 
346 /*
347  * debug support
348  */
349 #ifdef DEBUG
350 #include <sys/promif.h>
351 
352 extern char	*ppm_get_ctlstr(int, uint_t);
353 extern void	ppm_print_dc(struct ppm_dc *);
354 
355 extern uint_t ppm_debug;
356 
357 #define	D_CREATEDB	0x00000001
358 #define	D_CLAIMDEV	0x00000002
359 #define	D_ADDDEV	0x00000004
360 #define	D_REMDEV	0x00000008
361 #define	D_LOWEST	0x00000010
362 #define	D_SETLVL	0x00000020
363 #define	D_GPIO		0x00000040
364 #define	D_CPU		0x00000080
365 #define	D_FET		0x00000100
366 #define	D_PCIUPA	0x00000200
367 #define	D_1394		0x00000400
368 #define	D_CTLOPS1	0x00000800
369 #define	D_CTLOPS2	0x00001000
370 #define	D_SOME		0x00002000
371 #define	D_LOCKS		0x00004000
372 #define	D_IOCTL		0x00008000
373 #define	D_ATTACH	0x00010000
374 #define	D_DETACH	0x00020000
375 #define	D_OPEN		0x00040000
376 #define	D_CLOSE		0x00080000
377 #define	D_INIT		0x00100000
378 #define	D_FINI		0x00200000
379 #define	D_ERROR		0x00400000
380 #define	D_SETPWR	0x00800000
381 #define	D_LED		0x01000000
382 #define	D_PCI		0x02000000
383 #define	D_PPMDC		0x04000000
384 #define	D_CPR		0x08000000
385 
386 #define	PPMD(level, arglist) {			\
387 	if (ppm_debug & (level)) {		\
388 		pm_log arglist;			\
389 	}					\
390 }
391 /* (s10) */
392 #define	DPRINTF		PPMD
393 
394 #else	/* DEBUG */
395 #define	PPMD(level, arglist)
396 #define	DPRINTF(flag, args)	/* (s10) */
397 #endif	/* DEBUG */
398 
399 #ifdef	__cplusplus
400 }
401 #endif
402 
403 #endif	/* _SYS_PPMVAR_H */
404