Len Brown | 6dccf9c | 2011-07-12 22:29:32 -0400 | [diff] [blame] | 1 | /* |
| 2 | * mrst/pmu.h - private definitions for MRST Power Management Unit mrst/pmu.c |
| 3 | * |
| 4 | * Copyright (c) 2011, Intel Corporation. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, |
| 8 | * version 2, as published by the Free Software Foundation. |
| 9 | * |
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT |
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with |
| 16 | * this program; if not, write to the Free Software Foundation, Inc., |
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | */ |
| 19 | |
| 20 | #ifndef _MRST_PMU_H_ |
| 21 | #define _MRST_PMU_H_ |
| 22 | |
| 23 | #define PCI_DEV_ID_MRST_PMU 0x0810 |
| 24 | #define MRST_PMU_DRV_NAME "mrst_pmu" |
| 25 | #define PCI_SUB_CLASS_MASK 0xFF00 |
| 26 | |
| 27 | #define PCI_VENDOR_CAP_LOG_ID_MASK 0x7F |
| 28 | #define PCI_VENDOR_CAP_LOG_SS_MASK 0x80 |
| 29 | |
| 30 | #define SUB_SYS_ALL_D0I1 0x01155555 |
| 31 | #define S0I3_WAKE_SOURCES 0x00001FFF |
| 32 | |
| 33 | #define PM_S0I3_COMMAND \ |
| 34 | ((0 << 31) | /* Reserved */ \ |
| 35 | (0 << 30) | /* Core must be idle */ \ |
| 36 | (0xc2 << 22) | /* ACK C6 trigger */ \ |
| 37 | (3 << 19) | /* Trigger on DMI message */ \ |
| 38 | (3 << 16) | /* Enter S0i3 */ \ |
| 39 | (0 << 13) | /* Numeric mode ID (sw) */ \ |
| 40 | (3 << 9) | /* Trigger mode */ \ |
| 41 | (0 << 8) | /* Do not interrupt */ \ |
| 42 | (1 << 0)) /* Set configuration */ |
| 43 | |
| 44 | #define LSS_DMI 0 |
| 45 | #define LSS_SD_HC0 1 |
| 46 | #define LSS_SD_HC1 2 |
| 47 | #define LSS_NAND 3 |
| 48 | #define LSS_IMAGING 4 |
| 49 | #define LSS_SECURITY 5 |
| 50 | #define LSS_DISPLAY 6 |
| 51 | #define LSS_USB_HC 7 |
| 52 | #define LSS_USB_OTG 8 |
| 53 | #define LSS_AUDIO 9 |
| 54 | #define LSS_AUDIO_LPE 9 |
| 55 | #define LSS_AUDIO_SSP 9 |
| 56 | #define LSS_I2C0 10 |
| 57 | #define LSS_I2C1 10 |
| 58 | #define LSS_I2C2 10 |
| 59 | #define LSS_KBD 10 |
| 60 | #define LSS_SPI0 10 |
| 61 | #define LSS_SPI1 10 |
| 62 | #define LSS_SPI2 10 |
| 63 | #define LSS_GPIO 10 |
| 64 | #define LSS_SRAM 11 /* used by SCU, do not touch */ |
| 65 | #define LSS_SD_HC2 12 |
| 66 | /* LSS hardware bits 15,14,13 are hardwired to 0, thus unusable */ |
| 67 | #define MRST_NUM_LSS 13 |
| 68 | |
| 69 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
| 70 | |
| 71 | #define SSMSK(mask, lss) ((mask) << ((lss) * 2)) |
| 72 | #define D0 0 |
| 73 | #define D0i1 1 |
| 74 | #define D0i2 2 |
| 75 | #define D0i3 3 |
| 76 | |
| 77 | #define S0I3_SSS_TARGET ( \ |
| 78 | SSMSK(D0i1, LSS_DMI) | \ |
| 79 | SSMSK(D0i3, LSS_SD_HC0) | \ |
| 80 | SSMSK(D0i3, LSS_SD_HC1) | \ |
| 81 | SSMSK(D0i3, LSS_NAND) | \ |
| 82 | SSMSK(D0i3, LSS_SD_HC2) | \ |
| 83 | SSMSK(D0i3, LSS_IMAGING) | \ |
| 84 | SSMSK(D0i3, LSS_SECURITY) | \ |
| 85 | SSMSK(D0i3, LSS_DISPLAY) | \ |
| 86 | SSMSK(D0i3, LSS_USB_HC) | \ |
| 87 | SSMSK(D0i3, LSS_USB_OTG) | \ |
| 88 | SSMSK(D0i3, LSS_AUDIO) | \ |
| 89 | SSMSK(D0i1, LSS_I2C0)) |
| 90 | |
| 91 | /* |
| 92 | * D0i1 on Langwell is Autonomous Clock Gating (ACG). |
| 93 | * Enable ACG on every LSS except camera and audio |
| 94 | */ |
| 95 | #define D0I1_ACG_SSS_TARGET \ |
| 96 | (SUB_SYS_ALL_D0I1 & ~SSMSK(D0i1, LSS_IMAGING) & ~SSMSK(D0i1, LSS_AUDIO)) |
| 97 | |
| 98 | enum cm_mode { |
| 99 | CM_NOP, /* ignore the config mode value */ |
| 100 | CM_IMMEDIATE, |
| 101 | CM_DELAY, |
| 102 | CM_TRIGGER, |
| 103 | CM_INVALID |
| 104 | }; |
| 105 | |
| 106 | enum sys_state { |
| 107 | SYS_STATE_S0I0, |
| 108 | SYS_STATE_S0I1, |
| 109 | SYS_STATE_S0I2, |
| 110 | SYS_STATE_S0I3, |
| 111 | SYS_STATE_S3, |
| 112 | SYS_STATE_S5 |
| 113 | }; |
| 114 | |
| 115 | #define SET_CFG_CMD 1 |
| 116 | |
| 117 | enum int_status { |
| 118 | INT_SPURIOUS = 0, |
| 119 | INT_CMD_DONE = 1, |
| 120 | INT_CMD_ERR = 2, |
| 121 | INT_WAKE_RX = 3, |
| 122 | INT_SS_ERROR = 4, |
| 123 | INT_S0IX_MISS = 5, |
| 124 | INT_NO_ACKC6 = 6, |
| 125 | INT_INVALID = 7, |
| 126 | }; |
| 127 | |
| 128 | /* PMU register interface */ |
| 129 | static struct mrst_pmu_reg { |
| 130 | u32 pm_sts; /* 0x00 */ |
| 131 | u32 pm_cmd; /* 0x04 */ |
| 132 | u32 pm_ics; /* 0x08 */ |
| 133 | u32 _resv1; /* 0x0C */ |
| 134 | u32 pm_wkc[2]; /* 0x10 */ |
| 135 | u32 pm_wks[2]; /* 0x18 */ |
| 136 | u32 pm_ssc[4]; /* 0x20 */ |
| 137 | u32 pm_sss[4]; /* 0x30 */ |
| 138 | u32 pm_wssc[4]; /* 0x40 */ |
| 139 | u32 pm_c3c4; /* 0x50 */ |
| 140 | u32 pm_c5c6; /* 0x54 */ |
| 141 | u32 pm_msi_disable; /* 0x58 */ |
| 142 | } *pmu_reg; |
| 143 | |
| 144 | static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); } |
| 145 | static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); } |
| 146 | static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); } |
| 147 | static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); } |
| 148 | |
| 149 | static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); } |
| 150 | static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); } |
| 151 | static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); } |
| 152 | static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); } |
| 153 | static inline void pmu_write_wssc(u32 arg) |
| 154 | { writel(arg, &pmu_reg->pm_wssc[0]); } |
| 155 | |
| 156 | static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); } |
| 157 | static inline u32 pmu_msi_is_disabled(void) |
| 158 | { return readl(&pmu_reg->pm_msi_disable); } |
| 159 | |
| 160 | union pmu_pm_ics { |
| 161 | struct { |
| 162 | u32 cause:8; |
| 163 | u32 enable:1; |
| 164 | u32 pending:1; |
| 165 | u32 reserved:22; |
| 166 | } bits; |
| 167 | u32 value; |
| 168 | }; |
| 169 | |
| 170 | static inline void pmu_irq_enable(void) |
| 171 | { |
| 172 | union pmu_pm_ics pmu_ics; |
| 173 | |
| 174 | pmu_ics.value = pmu_read_ics(); |
| 175 | pmu_ics.bits.enable = 1; |
| 176 | pmu_write_ics(pmu_ics.value); |
| 177 | } |
| 178 | |
| 179 | union pmu_pm_status { |
| 180 | struct { |
| 181 | u32 pmu_rev:8; |
| 182 | u32 pmu_busy:1; |
| 183 | u32 mode_id:4; |
| 184 | u32 Reserved:19; |
| 185 | } pmu_status_parts; |
| 186 | u32 pmu_status_value; |
| 187 | }; |
| 188 | |
| 189 | static inline int pmu_read_busy_status(void) |
| 190 | { |
| 191 | union pmu_pm_status result; |
| 192 | |
| 193 | result.pmu_status_value = pmu_read_sts(); |
| 194 | |
| 195 | return result.pmu_status_parts.pmu_busy; |
| 196 | } |
| 197 | |
| 198 | /* pmu set config parameters */ |
| 199 | struct cfg_delay_param_t { |
| 200 | u32 cmd:8; |
| 201 | u32 ioc:1; |
| 202 | u32 cfg_mode:4; |
| 203 | u32 mode_id:3; |
| 204 | u32 sys_state:3; |
| 205 | u32 cfg_delay:8; |
| 206 | u32 rsvd:5; |
| 207 | }; |
| 208 | |
| 209 | struct cfg_trig_param_t { |
| 210 | u32 cmd:8; |
| 211 | u32 ioc:1; |
| 212 | u32 cfg_mode:4; |
| 213 | u32 mode_id:3; |
| 214 | u32 sys_state:3; |
| 215 | u32 cfg_trig_type:3; |
| 216 | u32 cfg_trig_val:8; |
| 217 | u32 cmbi:1; |
| 218 | u32 rsvd1:1; |
| 219 | }; |
| 220 | |
| 221 | union pmu_pm_set_cfg_cmd_t { |
| 222 | union { |
| 223 | struct cfg_delay_param_t d_param; |
| 224 | struct cfg_trig_param_t t_param; |
| 225 | } pmu2_params; |
| 226 | u32 pmu_pm_set_cfg_cmd_value; |
| 227 | }; |
| 228 | |
| 229 | #ifdef FUTURE_PATCH |
| 230 | extern int mrst_s0i3_entry(u32 regval, u32 *regaddr); |
| 231 | #else |
| 232 | static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; } |
| 233 | #endif |
| 234 | #endif |