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 #ifndef _SYS_PCIE_PWR_H 27 #define _SYS_PCIE_PWR_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 /* index of counters for each level */ 34 #define PCIE_D3_INDEX PM_LEVEL_D3 35 #define PCIE_D2_INDEX PM_LEVEL_D2 36 #define PCIE_D1_INDEX PM_LEVEL_D1 37 #define PCIE_D0_INDEX PM_LEVEL_D0 38 #define PCIE_UNKNOWN_INDEX PM_LEVEL_D0 + 1 39 #define PCIE_MAX_PWR_LEVELS 5 40 41 /* 42 * PCIe nexus power management data structure 43 */ 44 typedef struct pcie_pwr { 45 /* 46 * general data structure fields 47 */ 48 kmutex_t pwr_lock; /* to protect the counters and */ 49 /* power level change */ 50 int pwr_pmcaps; /* pm capability */ 51 ddi_acc_handle_t pwr_conf_hdl; /* for config access */ 52 uint8_t pwr_pmcsr_offset; /* PMCSR offset */ 53 int pwr_link_lvl; /* link level. Currently not used */ 54 int pwr_func_lvl; /* function power level */ 55 int pwr_flags; /* flags */ 56 int pwr_hold; /* for temporarily keeping busy */ 57 /* 58 * counters to keep track of child's power level. 59 * D3,D2,D1,D0 and unknown respectively. 60 */ 61 int pwr_counters[PCIE_MAX_PWR_LEVELS]; 62 63 } pcie_pwr_t; 64 65 typedef struct pcie_pwr_child { 66 /* 67 * Per child dip counters decsribing 68 * a child's components 69 */ 70 int pwr_child_counters[PCIE_MAX_PWR_LEVELS]; 71 } pcie_pwr_child_t; 72 73 typedef struct pcie_pm { 74 pcie_pwr_t *pcie_pwr_p; /* nexus PM info */ 75 pcie_pwr_child_t *pcie_par_pminfo; /* PM info created by the parent */ 76 } pcie_pm_t; 77 78 #define PCIE_PMINFO(dip) \ 79 ((pcie_pm_t *)(DEVI(dip)->devi_nex_pm)) 80 81 #define PCIE_NEXUS_PMINFO(dip) \ 82 (PCIE_PMINFO(dip)->pcie_pwr_p) 83 84 #define PCIE_PAR_PMINFO(dip) \ 85 (PCIE_PMINFO(dip)->pcie_par_pminfo) 86 87 #define PCIE_CHILD_COUNTERS(cdip) \ 88 (PCIE_PAR_PMINFO(cdip)->pwr_child_counters) 89 90 #define PCIE_SET_PMINFO(dip, pminfo_p) \ 91 (DEVI(dip)->devi_nex_pm = (pminfo_p)) 92 93 #define PCIE_RESET_PMINFO(dip) \ 94 (DEVI(dip)->devi_nex_pm = NULL) 95 96 #define PCIE_IS_COMPS_COUNTED(cdip) \ 97 (PCIE_PMINFO(cdip) && PCIE_PAR_PMINFO(cdip)) 98 99 /* 100 * pmcap field: device power management capability. 101 * First 4 bits must indicate support for D3, D2, D1 and D0 102 * respectively. Their bit position matches with their index 103 * into the counters array. 104 */ 105 #define PCIE_SUPPORTS_D3 0x01 /* Supports D1 */ 106 #define PCIE_SUPPORTS_D2 0x02 /* Supports D2 */ 107 #define PCIE_SUPPORTS_D1 0x04 /* Supports D2 */ 108 #define PCIE_SUPPORTS_D0 0x08 /* Supports D2 */ 109 #define PCIE_L2_CAP 0x10 /* if with Vaux, optional */ 110 #define PCIE_L0s_L1_CAP 0x20 /* ASPM, L0s must, L1 optional */ 111 112 #define PCIE_DEFAULT_LEVEL_SUPPORTED (PCIE_SUPPORTS_D3 | PCIE_SUPPORTS_D0) 113 114 #define PCIE_LEVEL_SUPPORTED(pmcaps, level) \ 115 ((pmcaps) & (1 << (level))) 116 117 #define PCIE_SUPPORTS_DEVICE_PM(dip) \ 118 (ddi_prop_exists(DDI_DEV_T_ANY, (dip), \ 119 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pm-components") == 1) 120 /* 121 * flags field 122 */ 123 #define PCIE_ASPM_ENABLED 0x01 124 #define PCIE_SLOT_LOADED 0x02 125 #define PCIE_PM_BUSY 0x04 126 #define PCIE_NO_CHILD_PM 0x08 127 128 #define PM_LEVEL_L3 0 129 #define PM_LEVEL_L2 1 130 #define PM_LEVEL_L1 2 131 #define PM_LEVEL_L0 3 132 133 /* ioctl definitions for ppm drivers */ 134 #define PPMREQ (('P' << 24) | ('M' << 16)) 135 #define PPMREQ_MASK 0xffff 136 #define PPMREQ_PRE_PWR_OFF (PPMREQ | 1) 137 #define PPMREQ_PRE_PWR_ON (PPMREQ | 2) 138 #define PPMREQ_POST_PWR_ON (PPMREQ | 3) 139 140 /* settle time in microseconds before PCI operation */ 141 #define PCI_CLK_SETTLE_TIME 10000 142 143 /* 144 * Interface with other parts of the driver(s) code 145 */ 146 147 /* 148 * We link pcie_pwr.o into several drivers (px, pcieb, pcieb_bcm, pcieb_plx), 149 * which causes the symbols below to be duplicated. This isn't an issue in 150 * practice, since they aren't used from outside the module that they're 151 * part of. However, lint does not know this, and when it does global 152 * crosschecks for the kernel, it complains. To prevent this, we rename the 153 * symbols to driver-specific names when we're doing a lint run. 154 */ 155 156 #if defined(lint) 157 #if defined(PX_MOD_NAME) 158 #define pwr_common_setup PX_MOD_NAME##_pwr_common_setup 159 #define pwr_common_teardown PX_MOD_NAME##_pwr_common_teardown 160 #define pcie_bus_power PX_MOD_NAME##_pcie_bus_power 161 #define pcie_power PX_MOD_NAME##_pcie_power 162 #define pcie_pm_add_child PX_MOD_NAME##_pcie_pm_add_child 163 #define pcie_pm_remove_child PX_MOD_NAME##_pcie_pm_remove_child 164 #define pcie_pwr_suspend PX_MOD_NAME##_pcie_pwr_suspend 165 #define pcie_pwr_resume PX_MOD_NAME##_pcie_pwr_resume 166 #define pcie_pm_hold PX_MOD_NAME##_pcie_pm_hold 167 #define pcie_pm_release PX_MOD_NAME##_pcie_pm_release 168 #endif /* PX_MOD_NAME */ 169 170 #if defined(PX_PLX) 171 #define pwr_common_setup PX_PLX##_pwr_common_setup 172 #define pwr_common_teardown PX_PLX##_pwr_common_teardown 173 #define pcie_bus_power PX_PLX##_pcie_bus_power 174 #define pcie_power PX_PLX##_pcie_power 175 #define pcie_pm_add_child PX_PLX##_pcie_pm_add_child 176 #define pcie_pm_remove_child PX_PLX##_pcie_pm_remove_child 177 #define pcie_pwr_suspend PX_PLX##_pcie_pwr_suspend 178 #define pcie_pwr_resume PX_PLX##_pcie_pwr_resume 179 #define pcie_pm_hold PX_PLX##_pcie_pm_hold 180 #define pcie_pm_release PX_PLX##_pcie_pm_release 181 #endif /* PX_PLX */ 182 #endif /* lint */ 183 184 extern int pcie_plat_pwr_setup(dev_info_t *dip); 185 extern void pcie_plat_pwr_teardown(dev_info_t *dip); 186 extern int pwr_common_setup(dev_info_t *dip); 187 extern void pwr_common_teardown(dev_info_t *dip); 188 extern int pcie_bus_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op, 189 void *arg, void *result); 190 extern int pcie_power(dev_info_t *dip, int component, int level); 191 192 extern int pcie_pm_add_child(dev_info_t *dip, dev_info_t *cdip); 193 extern int pcie_pm_remove_child(dev_info_t *dip, dev_info_t *cdip); 194 extern int pcie_pwr_suspend(dev_info_t *dip); 195 extern int pcie_pwr_resume(dev_info_t *dip); 196 extern int pcie_pm_hold(dev_info_t *dip); 197 extern void pcie_pm_release(dev_info_t *dip); 198 199 #ifdef __cplusplus 200 } 201 #endif 202 203 #endif /* _SYS_PCIE_PWR_H */ 204