summaryrefslogtreecommitdiff
path: root/arch/x86/platform/mrst/pmu.h
blob: bfbfe64b167bf09117e6f0a3792514fd310f839f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
 * mrst/pmu.h - private definitions for MRST Power Management Unit mrst/pmu.c
 *
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef _MRST_PMU_H_
#define _MRST_PMU_H_

#define PCI_DEV_ID_MRST_PMU		0x0810
#define MRST_PMU_DRV_NAME		"mrst_pmu"
#define	PCI_SUB_CLASS_MASK		0xFF00

#define	PCI_VENDOR_CAP_LOG_ID_MASK	0x7F
#define PCI_VENDOR_CAP_LOG_SS_MASK	0x80

#define SUB_SYS_ALL_D0I1	0x01155555
#define S0I3_WAKE_SOURCES	0x00001FFF

#define PM_S0I3_COMMAND					\
	((0 << 31) |	/* Reserved */			\
	(0 << 30) |	/* Core must be idle */		\
	(0xc2 << 22) |	/* ACK C6 trigger */		\
	(3 << 19) |	/* Trigger on DMI message */	\
	(3 << 16) |	/* Enter S0i3 */		\
	(0 << 13) |	/* Numeric mode ID (sw) */	\
	(3 << 9) |	/* Trigger mode */		\
	(0 << 8) |	/* Do not interrupt */		\
	(1 << 0))	/* Set configuration */

#define	LSS_DMI		0
#define	LSS_SD_HC0	1
#define	LSS_SD_HC1	2
#define	LSS_NAND	3
#define	LSS_IMAGING	4
#define	LSS_SECURITY	5
#define	LSS_DISPLAY	6
#define	LSS_USB_HC	7
#define	LSS_USB_OTG	8
#define	LSS_AUDIO	9
#define	LSS_AUDIO_LPE	9
#define	LSS_AUDIO_SSP	9
#define	LSS_I2C0	10
#define	LSS_I2C1	10
#define	LSS_I2C2	10
#define	LSS_KBD		10
#define	LSS_SPI0	10
#define	LSS_SPI1	10
#define	LSS_SPI2	10
#define	LSS_GPIO	10
#define	LSS_SRAM	11	/* used by SCU, do not touch */
#define	LSS_SD_HC2	12
/* LSS hardware bits 15,14,13 are hardwired to 0, thus unusable */
#define MRST_NUM_LSS	13

#define MIN(a, b) (((a) < (b)) ? (a) : (b))

#define	SSMSK(mask, lss) ((mask) << ((lss) * 2))
#define	D0	0
#define	D0i1	1
#define	D0i2	2
#define	D0i3	3

#define S0I3_SSS_TARGET	(		\
	SSMSK(D0i1, LSS_DMI) |		\
	SSMSK(D0i3, LSS_SD_HC0) |	\
	SSMSK(D0i3, LSS_SD_HC1) |	\
	SSMSK(D0i3, LSS_NAND) |		\
	SSMSK(D0i3, LSS_SD_HC2) |	\
	SSMSK(D0i3, LSS_IMAGING) |	\
	SSMSK(D0i3, LSS_SECURITY) |	\
	SSMSK(D0i3, LSS_DISPLAY) |	\
	SSMSK(D0i3, LSS_USB_HC) |	\
	SSMSK(D0i3, LSS_USB_OTG) |	\
	SSMSK(D0i3, LSS_AUDIO) |	\
	SSMSK(D0i1, LSS_I2C0))

/*
 * D0i1 on Langwell is Autonomous Clock Gating (ACG).
 * Enable ACG on every LSS except camera and audio
 */
#define D0I1_ACG_SSS_TARGET	 \
	(SUB_SYS_ALL_D0I1 & ~SSMSK(D0i1, LSS_IMAGING) & ~SSMSK(D0i1, LSS_AUDIO))

enum cm_mode {
	CM_NOP,			/* ignore the config mode value */
	CM_IMMEDIATE,
	CM_DELAY,
	CM_TRIGGER,
	CM_INVALID
};

enum sys_state {
	SYS_STATE_S0I0,
	SYS_STATE_S0I1,
	SYS_STATE_S0I2,
	SYS_STATE_S0I3,
	SYS_STATE_S3,
	SYS_STATE_S5
};

#define SET_CFG_CMD	1

enum int_status {
	INT_SPURIOUS = 0,
	INT_CMD_DONE = 1,
	INT_CMD_ERR = 2,
	INT_WAKE_RX = 3,
	INT_SS_ERROR = 4,
	INT_S0IX_MISS = 5,
	INT_NO_ACKC6 = 6,
	INT_INVALID = 7,
};

/* PMU register interface */
static struct mrst_pmu_reg {
	u32 pm_sts;		/* 0x00 */
	u32 pm_cmd;		/* 0x04 */
	u32 pm_ics;		/* 0x08 */
	u32 _resv1;		/* 0x0C */
	u32 pm_wkc[2];		/* 0x10 */
	u32 pm_wks[2];		/* 0x18 */
	u32 pm_ssc[4];		/* 0x20 */
	u32 pm_sss[4];		/* 0x30 */
	u32 pm_wssc[4];		/* 0x40 */
	u32 pm_c3c4;		/* 0x50 */
	u32 pm_c5c6;		/* 0x54 */
	u32 pm_msi_disable;	/* 0x58 */
} *pmu_reg;

static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); }
static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); }
static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); }
static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); }

static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); }
static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); }
static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); }
static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); }
static inline void pmu_write_wssc(u32 arg)
					{ writel(arg, &pmu_reg->pm_wssc[0]); }

static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); }
static inline u32 pmu_msi_is_disabled(void)
				{ return readl(&pmu_reg->pm_msi_disable); }

union pmu_pm_ics {
	struct {
		u32 cause:8;
		u32 enable:1;
		u32 pending:1;
		u32 reserved:22;
	} bits;
	u32 value;
};

static inline void pmu_irq_enable(void)
{
	union pmu_pm_ics pmu_ics;

	pmu_ics.value = pmu_read_ics();
	pmu_ics.bits.enable = 1;
	pmu_write_ics(pmu_ics.value);
}

union pmu_pm_status {
	struct {
		u32 pmu_rev:8;
		u32 pmu_busy:1;
		u32 mode_id:4;
		u32 Reserved:19;
	} pmu_status_parts;
	u32 pmu_status_value;
};

static inline int pmu_read_busy_status(void)
{
	union pmu_pm_status result;

	result.pmu_status_value = pmu_read_sts();

	return result.pmu_status_parts.pmu_busy;
}

/* pmu set config parameters */
struct cfg_delay_param_t {
	u32 cmd:8;
	u32 ioc:1;
	u32 cfg_mode:4;
	u32 mode_id:3;
	u32 sys_state:3;
	u32 cfg_delay:8;
	u32 rsvd:5;
};

struct cfg_trig_param_t {
	u32 cmd:8;
	u32 ioc:1;
	u32 cfg_mode:4;
	u32 mode_id:3;
	u32 sys_state:3;
	u32 cfg_trig_type:3;
	u32 cfg_trig_val:8;
	u32 cmbi:1;
	u32 rsvd1:1;
};

union pmu_pm_set_cfg_cmd_t {
	union {
		struct cfg_delay_param_t d_param;
		struct cfg_trig_param_t t_param;
	} pmu2_params;
	u32 pmu_pm_set_cfg_cmd_value;
};

#ifdef FUTURE_PATCH
extern int mrst_s0i3_entry(u32 regval, u32 *regaddr);
#else
static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; }
#endif
#endif