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 
pmu_read_sts(void)144 static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); }
pmu_read_ics(void)145 static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); }
pmu_read_wks(void)146 static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); }
pmu_read_sss(void)147 static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); }
148 
pmu_write_cmd(u32 arg)149 static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); }
pmu_write_ics(u32 arg)150 static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); }
pmu_write_wkc(u32 arg)151 static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); }
pmu_write_ssc(u32 arg)152 static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); }
pmu_write_wssc(u32 arg)153 static inline void pmu_write_wssc(u32 arg)
154 					{ writel(arg, &pmu_reg->pm_wssc[0]); }
155 
pmu_msi_enable(void)156 static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); }
pmu_msi_is_disabled(void)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 
pmu_irq_enable(void)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 
pmu_read_busy_status(void)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
mrst_s0i3_entry(u32 regval,u32 * regaddr)232 static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; }
233 #endif
234 #endif
235