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