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