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