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