a2ac32e1a9d7577097b2bc883f6e2ecc2c05b5a9
[coreboot.git] / util / inteltool / powermgt.c
1 /*
2  * inteltool - dump all registers on an Intel CPU + chipset based system.
3  *
4  * Copyright (C) 2008-2010 by coresystems GmbH
5  *  written by Stefan Reinauer <stepan@coresystems.de>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <stdio.h>
22 #include "inteltool.h"
23
24 static const io_register_t ich10_pm_registers[] = {
25         { 0x00, 2, "PM1_STS" }, // PM1 Status; ACPI pointer: PM1a_EVT_BLK
26         { 0x02, 2, "PM1_EN" },  // PM1 Enables; ACPI pointer: PM1a_EVT_BLK+2
27         { 0x04, 4, "PM1_CNT" }, // PM1 Control; ACPI pointer: PM1a_CNT_BLK
28         { 0x08, 4, "PM1_TMR" }, // PM1 Timer; ACPI pointer: PMTMR_BLK
29         { 0x0c, 4, "RESERVED" },
30         { 0x10, 4, "PROC_CNT" }, // Processor Control; ACPI pointer: P_BLK
31 #if DANGEROUS_REGISTERS
32         /* These registers return 0 on read, but reading them may cause
33          * the system to enter Cx states, which might hang the system.
34          */
35         { 0x14, 1, "LV2 (Mobile)" },
36         { 0x15, 1, "LV3 (Mobile)" },
37         { 0x16, 1, "LV4 (Mobile)" },
38 #endif
39         { 0x17, 2, "RESERVED" },
40         { 0x19, 1, "RESERVED" },
41         { 0x1a, 2, "RESERVED" },
42         { 0x1c, 4, "RESERVED" },
43         { 0x20, 8, "GPE0_STS" }, // General Purpose Event 0 Status; ACPI pointer: GPE0_BLK
44         { 0x2C, 4, "GPE0_EN" },  // General Purpose Event 0 Enables; ACPI pointer: GPE0_BLK+8
45         { 0x30, 4, "SMI_EN" },
46         { 0x34, 4, "SMI_STS" },
47         { 0x38, 2, "ALT_GP_SMI_EN" },
48         { 0x3a, 2, "ALT_GP_SMI_STS" },
49         { 0x3c, 1, "UPRWC" },   // USB Per-Port registers write control;
50         { 0x3d, 2, "RESERVED" },
51         { 0x3f, 1, "RESERVED" },
52         { 0x40, 2, "RESERVED" },
53         { 0x42, 1, "GPE_CNTL" },
54         { 0x43, 1, "RESERVED" },
55         { 0x44, 2, "DEVACT_STS" }, // Device Activity Status
56         { 0x46, 2, "RESERVED" },
57         { 0x48, 4, "RESERVED" },
58         { 0x4c, 4, "RESERVED" },
59         { 0x50, 1, "PM2_CNT (Mobile)" }, // PM2 Control (Mobile only); ACPI pointer: PM2a_CNT_BLK
60         { 0x51, 1, "RESERVED" },
61         { 0x52, 2, "RESERVED" },
62         { 0x54, 4, "C3_RES (Mobile)" },
63         { 0x58, 4, "RESERVED" },
64         { 0x5c, 4, "RESERVED" },
65         /* Here start the TCO registers */
66         { 0x60, 2, "TCO_RLD" },
67         { 0x62, 1, "TCO_DAT_IN" },
68         { 0x63, 1, "TCO_DAT_OUT" },
69         { 0x64, 2, "TCO1_STS" },
70         { 0x66, 2, "TCO2_STS" },
71         { 0x68, 2, "TCO1_CNT" },
72         { 0x6a, 2, "TCO2_CNT" },
73         { 0x6c, 2, "TCO_MESSAGE" },
74         { 0x6e, 1, "TCO_WDCNT" },
75         { 0x6f, 1, "RESERVED" },
76         { 0x70, 1, "SW_IRQ_GEN" },
77         { 0x71, 1, "RESERVED" },
78         { 0x72, 2, "TCO_TMR" },
79         { 0x74, 4, "RESERVED" },
80         { 0x78, 4, "RESERVED" },
81         { 0x7c, 4, "RESERVED" },
82 };
83
84 static const io_register_t ich9_pm_registers[] = {
85         { 0x00, 2, "PM1_STS" }, // PM1 Status; ACPI pointer: PM1a_EVT_BLK
86         { 0x02, 2, "PM1_EN" },  // PM1 Enables; ACPI pointer: PM1a_EVT_BLK+2
87         { 0x04, 4, "PM1_CNT" }, // PM1 Control; ACPI pointer: PM1a_CNT_BLK
88         { 0x08, 4, "PM1_TMR" }, // PM1 Timer; ACPI pointer: PMTMR_BLK
89         { 0x0c, 4, "RESERVED" },
90         { 0x10, 4, "PROC_CNT" }, // Processor Control; ACPI pointer: P_BLK
91 #if DANGEROUS_REGISTERS
92         /* These registers return 0 on read, but reading them may cause
93          * the system to enter Cx states, which might hang the system.
94          */
95         { 0x14, 1, "LV2 (Mobile)" },
96         { 0x15, 1, "LV3 (Mobile)" },
97         { 0x16, 1, "LV4 (Mobile)" },
98         { 0x17, 1, "LV5 (Mobile)" },
99         { 0x18, 1, "LV6 (Mobile)" },
100 #endif
101         { 0x19, 1, "RESERVED" },
102         { 0x1a, 2, "RESERVED" },
103         { 0x1c, 4, "RESERVED" },
104         { 0x20, 8, "GPE0_STS" }, // General Purpose Event 0 Status; ACPI pointer: GPE0_BLK
105         { 0x2C, 4, "GPE0_EN" },  // General Purpose Event 0 Enables; ACPI pointer: GPE0_BLK+8
106         { 0x30, 4, "SMI_EN" },
107         { 0x34, 4, "SMI_STS" },
108         { 0x38, 2, "ALT_GP_SMI_EN" },
109         { 0x3a, 2, "ALT_GP_SMI_STS" },
110         { 0x3c, 1, "UPRWC" },   // USB Per-Port registers write control;
111         { 0x3d, 2, "RESERVED" },
112         { 0x3f, 1, "RESERVED" },
113         { 0x40, 2, "RESERVED" },
114         { 0x42, 1, "GPE_CNTL" },
115         { 0x43, 1, "RESERVED" },
116         { 0x44, 2, "DEVACT_STS" }, // Device Activity Status
117         { 0x46, 2, "RESERVED" },
118         { 0x48, 4, "RESERVED" },
119         { 0x4c, 4, "RESERVED" },
120         { 0x50, 1, "PM2_CNT (Mobile)" }, // PM2 Control (Mobile only); ACPI pointer: PM2a_CNT_BLK
121         { 0x51, 1, "RESERVED" },
122         { 0x52, 2, "RESERVED" },
123         { 0x54, 4, "C3_RES (Mobile)" },
124         { 0x58, 4, "C5_RES (Mobile)" },
125         { 0x5c, 4, "RESERVED" },
126         /* Here start the TCO registers */
127         { 0x60, 2, "TCO_RLD" },
128         { 0x62, 1, "TCO_DAT_IN" },
129         { 0x63, 1, "TCO_DAT_OUT" },
130         { 0x64, 2, "TCO1_STS" },
131         { 0x66, 2, "TCO2_STS" },
132         { 0x68, 2, "TCO1_CNT" },
133         { 0x6a, 2, "TCO2_CNT" },
134         { 0x6c, 2, "TCO_MESSAGE" },
135         { 0x6e, 1, "TCO_WDCNT" },
136         { 0x6f, 1, "RESERVED" },
137         { 0x70, 1, "SW_IRQ_GEN" },
138         { 0x71, 1, "RESERVED" },
139         { 0x72, 2, "TCO_TMR" },
140         { 0x74, 4, "RESERVED" },
141         { 0x78, 4, "RESERVED" },
142         { 0x7c, 4, "RESERVED" },
143 };
144
145 static const io_register_t ich8_pm_registers[] = {
146         { 0x00, 2, "PM1_STS" },
147         { 0x02, 2, "PM1_EN" },
148         { 0x04, 4, "PM1_CNT" },
149         { 0x08, 4, "PM1_TMR" },
150         { 0x0c, 4, "RESERVED" },
151         { 0x10, 4, "PROC_CNT" },
152 #if DANGEROUS_REGISTERS
153         /* These registers return 0 on read, but reading them may cause
154          * the system to enter Cx states, which might hang the system.
155          */
156         { 0x14, 1, "LV2 (Mobile)" },
157         { 0x15, 1, "LV3 (Mobile)" },
158         { 0x16, 1, "LV4 (Mobile)" },
159         { 0x17, 1, "LV5 (Mobile)" },
160         { 0x18, 1, "LV6 (Mobile)" },
161 #endif
162         { 0x19, 1, "RESERVED" },
163         { 0x1a, 2, "RESERVED" },
164         { 0x1c, 4, "RESERVED" },
165         { 0x20, 1, "PM2_CNT (Mobile)" },
166         { 0x21, 1, "RESERVED" },
167         { 0x22, 2, "RESERVED" },
168         { 0x24, 4, "RESERVED" },
169         { 0x28, 4, "GPE0_STS" },
170         { 0x2C, 4, "GPE0_EN" },
171         { 0x30, 4, "SMI_EN" },
172         { 0x34, 4, "SMI_STS" },
173         { 0x38, 2, "ALT_GP_SMI_EN" },
174         { 0x3a, 2, "ALT_GP_SMI_STS" },
175         { 0x3c, 4, "RESERVED" },
176         { 0x40, 2, "RESERVED" },
177         { 0x42, 1, "GPE_CNTL" },
178         { 0x43, 1, "RESERVED" },
179         { 0x44, 2, "DEVACT_STS" },
180         { 0x46, 2, "RESERVED" },
181         { 0x48, 4, "RESERVED" },
182         { 0x4c, 4, "RESERVED" },
183         { 0x50, 1, "SS_CNT (Mobile)" },
184         { 0x51, 1, "RESERVED" },
185         { 0x52, 2, "RESERVED" },
186         { 0x54, 4, "C3_RES (Mobile)" },
187         { 0x58, 4, "C5_RES (Mobile)" },
188         { 0x5c, 4, "RESERVED" },
189         /* Here start the TCO registers */
190         { 0x60, 2, "TCO_RLD" },
191         { 0x62, 1, "TCO_DAT_IN" },
192         { 0x63, 1, "TCO_DAT_OUT" },
193         { 0x64, 2, "TCO1_STS" },
194         { 0x66, 2, "TCO2_STS" },
195         { 0x68, 2, "TCO1_CNT" },
196         { 0x6a, 2, "TCO2_CNT" },
197         { 0x6c, 2, "TCO_MESSAGE" },
198         { 0x6e, 1, "TCO_WDCNT" },
199         { 0x6f, 1, "RESERVED" },
200         { 0x70, 1, "SW_IRQ_GEN" },
201         { 0x71, 1, "RESERVED" },
202         { 0x72, 2, "TCO_TMR" },
203         { 0x74, 4, "RESERVED" },
204         { 0x78, 4, "RESERVED" },
205         { 0x7c, 4, "RESERVED" },
206 };
207
208 static const io_register_t ich7_pm_registers[] = {
209         { 0x00, 2, "PM1_STS" },
210         { 0x02, 2, "PM1_EN" },
211         { 0x04, 4, "PM1_CNT" },
212         { 0x08, 4, "PM1_TMR" },
213         { 0x0c, 4, "RESERVED" },
214         { 0x10, 4, "PROC_CNT" },
215 #if DANGEROUS_REGISTERS
216         /* These registers return 0 on read, but reading them may cause
217          * the system to enter C2/C3/C4 state, which might hang the system.
218          */
219         { 0x14, 1, "LV2 (Mobile/Ultra Mobile)" },
220         { 0x15, 1, "LV3 (Mobile/Ultra Mobile)" },
221         { 0x16, 1, "LV4 (Mobile/Ultra Mobile)" },
222 #endif
223         { 0x17, 1, "RESERVED" },
224         { 0x18, 4, "RESERVED" },
225         { 0x1c, 4, "RESERVED" },
226         { 0x20, 1, "PM2_CNT (Mobile/Ultra Mobile)" },
227         { 0x21, 1, "RESERVED" },
228         { 0x22, 2, "RESERVED" },
229         { 0x24, 4, "RESERVED" },
230         { 0x28, 4, "GPE0_STS" },
231         { 0x2C, 4, "GPE0_EN" },
232         { 0x30, 4, "SMI_EN" },
233         { 0x34, 4, "SMI_STS" },
234         { 0x38, 2, "ALT_GP_SMI_EN" },
235         { 0x3a, 2, "ALT_GP_SMI_STS" },
236         { 0x3c, 4, "RESERVED" },
237         { 0x40, 2, "RESERVED" },
238         { 0x42, 1, "GPE_CNTL" },
239         { 0x43, 1, "RESERVED" },
240         { 0x44, 2, "DEVACT_STS" },
241         { 0x46, 2, "RESERVED" },
242         { 0x48, 4, "RESERVED" },
243         { 0x4c, 4, "RESERVED" },
244         { 0x50, 1, "SS_CNT (Mobile/Ultra Mobile)" },
245         { 0x51, 1, "RESERVED" },
246         { 0x52, 2, "RESERVED" },
247         { 0x54, 4, "C3_RES (Mobile/Ultra Mobile)" },
248         { 0x58, 4, "RESERVED" },
249         { 0x5c, 4, "RESERVED" },
250         /* Here start the TCO registers */
251         { 0x60, 2, "TCO_RLD" },
252         { 0x62, 1, "TCO_DAT_IN" },
253         { 0x63, 1, "TCO_DAT_OUT" },
254         { 0x64, 2, "TCO1_STS" },
255         { 0x66, 2, "TCO2_STS" },
256         { 0x68, 2, "TCO1_CNT" },
257         { 0x6a, 2, "TCO2_CNT" },
258         { 0x6c, 2, "TCO_MESSAGE" },
259         { 0x6e, 1, "TCO_WDCNT" },
260         { 0x6f, 1, "RESERVED" },
261         { 0x70, 1, "SW_IRQ_GEN" },
262         { 0x71, 1, "RESERVED" },
263         { 0x72, 2, "TCO_TMR" },
264         { 0x74, 4, "RESERVED" },
265         { 0x78, 4, "RESERVED" },
266         { 0x7c, 4, "RESERVED" },
267 };
268
269 /*
270  * INTEL I/O Controller Hub 6 Family
271  * http://www.intel.com/assets/pdf/datasheet/301473.pdf
272  */
273 static const io_register_t ich6_pm_registers[] = {
274         /* 10.8.3 */
275         { 0x00, 2, "PM1_STS" },
276         { 0x02, 2, "PM1_EN" },
277         { 0x04, 4, "PM1_CNT" },
278         { 0x08, 4, "PM1_TMR" },
279         { 0x10, 4, "PROC_CNT" },
280 #if DANGEROUS_REGISTERS
281         /* These registers return 0 on read, but reading them may cause
282          * the system to enter C2/C3/C4 state, which might hang the system.
283          */
284         { 0x14, 1, "LV2" },
285         { 0x15, 1, "LV3 (Mobile Only)" },
286         { 0x16, 1, "LV4 (Mobile Only)" },
287 #endif
288         { 0x20, 1, "PM2_CNT (Mobile Only)" },
289         { 0x28, 4, "GPE0_STS" },
290         { 0x2c, 4, "GPE0_EN" },
291         { 0x30, 4, "SMI_EN" },
292         { 0x34, 4, "SMI_STS" },
293         { 0x38, 2, "ALT_GP_SMI_EN" },
294         { 0x3a, 2, "ALT_GP_SMI_STS" },
295         { 0x44, 2, "DEVACT_STS" },
296         { 0x50, 1, "SS_CNT (Mobile Only)" },
297         { 0x54, 4, "C3_RES (Mobile Only)" },
298 };
299
300 static const io_register_t ich5_pm_registers[] = {
301         { 0x00, 2, "PM1_STS" },
302         { 0x02, 2, "PM1_EN" },
303         { 0x04, 4, "PM1_CNT" },
304         { 0x08, 4, "PM1_TMR" },
305         { 0x0c, 4, "RESERVED" },
306         { 0x10, 4, "PROC_CNT" },
307         { 0x14, 3, "RESERVED" },
308         { 0x17, 9, "RESERVED" },
309         { 0x20, 1, "RESERVED" },
310         { 0x28, 4, "GPE0_STS" },
311         { 0x2c, 4, "GPE0_EN" },
312         { 0x30, 4, "SMI_EN" },
313         { 0x34, 4, "SMI_STS" },
314         { 0x38, 2, "ALT_GP_SMI_EN" },
315         { 0x3a, 2, "ALT_GP_SMI_STS" },
316         { 0x3c, 4, "RESERVED" },
317         { 0x40, 1, "MON_SMI" },
318         { 0x42, 2, "RESERVED" },
319         { 0x44, 1, "DEVACT_STS" },
320         { 0x48, 1, "DEVTRAP_EN" },
321         { 0x50, 1, "RESERVED" },
322         { 0x51, 15, "RESERVED" },
323         { 0x60, 16, "RESERVED" },
324 };
325
326 static const io_register_t ich4_pm_registers[] = {
327         { 0x00, 2, "PM1_STS" },
328         { 0x02, 2, "PM1_EN" },
329         { 0x04, 4, "PM1_CNT" },
330         { 0x08, 4, "PM1_TMR" },
331         { 0x0c, 4, "RESERVED" },
332         { 0x10, 4, "PROC_CNT" },
333 #if DANGEROUS_REGISTERS
334         /* These registers return 0 on read, but reading them may cause
335          * the system to enter C2/C3/C4 state, which might hang the system.
336          */
337         { 0x14, 1, "LV2 (Mobile)" },
338         { 0x15, 1, "LV3 (Mobile)" },
339         { 0x16, 1, "LV4 (Mobile)" },
340 #endif
341         { 0x17, 1, "RESERVED" },
342         { 0x18, 4, "RESERVED" },
343         { 0x1c, 4, "RESERVED" },
344         { 0x20, 1, "PM2_CNT (Mobile)" },
345         { 0x21, 1, "RESERVED" },
346         { 0x22, 2, "RESERVED" },
347         { 0x24, 4, "RESERVED" },
348         { 0x28, 4, "GPE0_STS" },
349         { 0x2C, 4, "GPE0_EN" },
350         { 0x30, 4, "SMI_EN" },
351         { 0x34, 4, "SMI_STS" },
352         { 0x38, 2, "ALT_GP_SMI_EN" },
353         { 0x3a, 2, "ALT_GP_SMI_STS" },
354         { 0x3c, 4, "RESERVED" },
355         { 0x40, 2, "MON_SMI" },
356         { 0x42, 2, "RESERVED" },
357         { 0x44, 2, "DEVACT_STS" },
358         { 0x46, 2, "RESERVED" },
359         { 0x48, 4, "DEVTRAP_EN" },
360         { 0x4c, 2, "BUS_ADDR_TRACK" },
361         { 0x4e, 2, "BUS_CYC_TRACK" },
362         { 0x50, 1, "SS_CNT (Mobile/Ultra Mobile)" },
363         { 0x51, 1, "RESERVED" },
364         { 0x52, 2, "RESERVED" },
365         { 0x54, 4, "RESERVED" },
366         { 0x58, 4, "RESERVED" },
367         { 0x5c, 4, "RESERVED" },
368         /* Here start the TCO registers */
369         { 0x60, 1, "TCO_RLD" },
370         { 0x61, 1, "TCO_TMR" },
371         { 0x62, 1, "TCO_DAT_IN" },
372         { 0x63, 1, "TCO_DAT_OUT" },
373         { 0x64, 2, "TCO1_STS" },
374         { 0x66, 2, "TCO2_STS" },
375         { 0x68, 2, "TCO1_CNT" },
376         { 0x6a, 2, "TCO2_CNT" },
377         { 0x6c, 2, "TCO_MESSAGE" },
378         { 0x6e, 1, "TCO_WDSTATUS" },
379         { 0x6f, 1, "RESERVED" },
380         { 0x70, 1, "SW_IRQ_GEN" },
381         { 0x71, 1, "RESERVED" },
382         { 0x72, 2, "RESERVED" },
383         { 0x74, 4, "RESERVED" },
384         { 0x78, 4, "RESERVED" },
385         { 0x7c, 4, "RESERVED" },
386 };
387
388 static const io_register_t ich2_pm_registers[] = {
389         { 0x00, 2, "PM1_STS" },
390         { 0x02, 2, "PM1_EN" },
391         { 0x04, 4, "PM1_CNT" },
392         { 0x08, 4, "PM1_TMR" },
393         { 0x0c, 4, "RESERVED" },
394         { 0x10, 4, "PROC_CNT" },
395 #if DANGEROUS_REGISTERS
396         /* This register returns 0 on read, but reading it may cause
397          * the system to enter C2 state, which might hang the system.
398          */
399         { 0x14, 1, "LV2" },
400         { 0x15, 1, "RESERVED" },
401         { 0x16, 2, "RESERVED" },
402 #endif
403         { 0x18, 4, "RESERVED" },
404         { 0x1c, 4, "RESERVED" },
405         { 0x20, 4, "RESERVED" },
406         { 0x24, 4, "RESERVED" },
407         { 0x28, 2, "GPE0_STS" },
408         { 0x2a, 2, "GPE0_EN" },
409         { 0x2c, 2, "GPE1_STS" },
410         { 0x2e, 2, "GPE1_EN" },
411         { 0x30, 2, "SMI_EN" },
412         { 0x32, 2, "RESERVED" },
413         { 0x34, 2, "SMI_STS" },
414         { 0x36, 2, "RESERVED" },
415         { 0x38, 4, "RESERVED" },
416         { 0x3c, 4, "RESERVED" },
417         { 0x40, 2, "MON_SMI_STS" },
418         { 0x42, 2, "RESERVED" },
419         { 0x44, 2, "DEV_TRP_STS" },
420         { 0x46, 2, "RESERVED" },
421         { 0x48, 2, "TRP_EN" },
422         { 0x4A, 2, "RESERVED" },
423         { 0x4c, 2, "BUS_ADDR_TRACK" },
424         { 0x4e, 1, "BUS_CYC_TRACK" },
425         { 0x4f, 1, "RESERVED" },
426         { 0x50, 4, "RESERVED" },
427         { 0x54, 4, "RESERVED" },
428         { 0x58, 4, "RESERVED" },
429         { 0x5c, 4, "RESERVED" },
430         /* Here start the TCO registers */
431         { 0x60, 1, "TCO_RLD" },
432         { 0x61, 1, "TCO_TMR" },
433         { 0x62, 1, "TCO_DAT_IN" },
434         { 0x63, 1, "TCO_DAT_OUT" },
435         { 0x64, 2, "TCO1_STS" },
436         { 0x66, 2, "TCO2_STS" },
437         { 0x68, 2, "TCO1_CNT" },
438         { 0x6a, 2, "TCO2_CNT" },
439         { 0x6c, 1, "TCO_MESSAGE1" },
440         { 0x6d, 1, "TCO_MESSAGE2" },
441         { 0x6e, 1, "TCO_WDSTATUS" },
442         { 0x6f, 1, "RESERVED" },
443         { 0x70, 1, "SW_IRQ_GEN" },
444         { 0x71, 1, "RESERVED" },
445         { 0x72, 2, "RESERVED" },
446         { 0x74, 4, "RESERVED" },
447         { 0x78, 4, "RESERVED" },
448         { 0x7c, 4, "RESERVED" },
449 };
450
451 static const io_register_t ich0_pm_registers[] = {
452         { 0x00, 2, "PM1_STS" },
453         { 0x02, 2, "PM1_EN" },
454         { 0x04, 4, "PM1_CNT" },
455         { 0x08, 4, "PM1_TMR" },
456         { 0x0c, 4, "RESERVED" },
457         { 0x10, 4, "PROC_CNT" },
458 #if DANGEROUS_REGISTERS
459         /* This register returns 0 on read, but reading it may cause
460          * the system to enter C2 state, which might hang the system.
461          */
462         { 0x14, 1, "LV2" },
463         { 0x15, 1, "RESERVED" },
464         { 0x16, 2, "RESERVED" },
465 #endif
466         { 0x18, 4, "RESERVED" },
467         { 0x1c, 4, "RESERVED" },
468         { 0x20, 4, "RESERVED" },
469         { 0x24, 4, "RESERVED" },
470         { 0x28, 4, "GPE0_STS" },
471         { 0x2C, 4, "GPE0_EN" },
472         { 0x30, 2, "SMI_EN" },
473         { 0x32, 2, "RESERVED" },
474         { 0x34, 2, "SMI_STS" },
475         { 0x36, 2, "RESERVED" },
476         { 0x38, 4, "RESERVED" },
477         { 0x3c, 4, "RESERVED" },
478         { 0x40, 2, "IOMON_STS_EN" },
479         { 0x42, 2, "RESERVED" },
480         { 0x44, 2, "DEVACT_STS" },
481         { 0x46, 2, "RESERVED" },
482         { 0x48, 4, "RESERVED" },
483         { 0x4c, 2, "BUS_ADDR_TRACK" },
484         { 0x4e, 1, "BUS_CYC_TRACK" },
485         { 0x4f, 1, "RESERVED" },
486         { 0x50, 4, "RESERVED" },
487         { 0x54, 4, "RESERVED" },
488         { 0x58, 4, "RESERVED" },
489         { 0x5c, 4, "RESERVED" },
490         /* Here start the TCO registers */
491         { 0x60, 1, "TCO_RLD" },
492         { 0x61, 1, "TCO_TMR" },
493         { 0x62, 1, "TCO_DAT_IN" },
494         { 0x63, 1, "TCO_DAT_OUT" },
495         { 0x64, 2, "TCO1_STS" },
496         { 0x66, 2, "TCO2_STS" },
497         { 0x68, 2, "TCO1_CNT" },
498         { 0x6a, 2, "TCO2_CNT" },
499         { 0x6c, 1, "TCO_MESSAGE1" },
500         { 0x6d, 1, "TCO_MESSAGE2" },
501         { 0x6e, 1, "TCO_WDSTATUS" },
502         { 0x6f, 1, "RESERVED" },
503         { 0x70, 4, "RESERVED" },
504         { 0x74, 4, "RESERVED" },
505         { 0x78, 4, "RESERVED" },
506         { 0x7c, 4, "RESERVED" },
507 };
508
509 static const io_register_t i82371xx_pm_registers[] = {
510         { 0x00, 2, "PMSTS" },
511         { 0x02, 2, "PMEN" },
512         { 0x04, 2, "PMCNTRL" },
513         { 0x06, 2, "RESERVED" },
514         { 0x08, 1, "PMTMR" },
515         { 0x09, 1, "RESERVED" },
516         { 0x0A, 1, "RESERVED" },
517         { 0x0B, 1, "RESERVED" },
518         { 0x0C, 2, "GPSTS" },
519         { 0x0E, 2, "GPEN" },
520         { 0x10, 4, "PCNTRL" },
521 #if DANGEROUS_REGISTERS
522         /*
523          * This register returns 0 on read, but reading it may cause
524          * the system to enter C2 state, which might hang the system.
525          */
526         { 0x14, 1, "PLVL2" },
527         { 0x15, 1, "PLVL3" },
528         { 0x16, 2, "RESERVED" },
529 #endif
530         { 0x18, 2, "GLBSTS" },
531         { 0x1A, 2, "RESERVED" },
532         { 0x1c, 4, "DEVSTS" },
533         { 0x20, 2, "GLBEN" },
534         { 0x22, 1, "RESERVED" },
535         { 0x23, 1, "RESERVED" },
536         { 0x24, 1, "RESERVED" },
537         { 0x25, 1, "RESERVED" },
538         { 0x26, 1, "RESERVED" },
539         { 0x27, 1, "RESERVED" },
540         { 0x28, 4, "GLBCTL" },
541         { 0x2C, 4, "DEVCTL" },
542         /* The registers 0x30-0x33 and 0x34-0x37 allow byte-wise reads only. */
543         { 0x30, 1, "GPIREG 0" },
544         { 0x31, 1, "GPIREG 1" },
545         { 0x32, 1, "GPIREG 2" },
546         { 0x33, 1, "GPIREG 3" },
547         { 0x34, 1, "GPOREG 0" },
548         { 0x35, 1, "GPOREG 1" },
549         { 0x36, 1, "GPOREG 2" },
550         { 0x37, 1, "GPOREG 3" },
551 };
552
553 int print_pmbase(struct pci_dev *sb, struct pci_access *pacc)
554 {
555         int i, size;
556         uint16_t pmbase;
557         const io_register_t *pm_registers;
558         struct pci_dev *acpi;
559
560         printf("\n============= PMBASE ============\n\n");
561
562         switch (sb->device_id) {
563         case PCI_DEVICE_ID_INTEL_ICH10R:
564                 pmbase = pci_read_word(sb, 0x40) & 0xff80;
565                 pm_registers = ich10_pm_registers;
566                 size = ARRAY_SIZE(ich10_pm_registers);
567                 break;
568         case PCI_DEVICE_ID_INTEL_ICH7:
569         case PCI_DEVICE_ID_INTEL_ICH7M:
570         case PCI_DEVICE_ID_INTEL_ICH7DH:
571         case PCI_DEVICE_ID_INTEL_ICH7MDH:
572         case PCI_DEVICE_ID_INTEL_NM10:
573                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
574                 pm_registers = ich7_pm_registers;
575                 size = ARRAY_SIZE(ich7_pm_registers);
576                 break;
577         case PCI_DEVICE_ID_INTEL_ICH9DH:
578         case PCI_DEVICE_ID_INTEL_ICH9DO:
579         case PCI_DEVICE_ID_INTEL_ICH9R:
580         case PCI_DEVICE_ID_INTEL_ICH9:
581         case PCI_DEVICE_ID_INTEL_ICH9M:
582         case PCI_DEVICE_ID_INTEL_ICH9ME:
583                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
584                 pm_registers = ich9_pm_registers;
585                 size = ARRAY_SIZE(ich9_pm_registers);
586                 break;
587         case PCI_DEVICE_ID_INTEL_ICH8:
588         case PCI_DEVICE_ID_INTEL_ICH8M:
589                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
590                 pm_registers = ich8_pm_registers;
591                 size = ARRAY_SIZE(ich8_pm_registers);
592                 break;
593         case PCI_DEVICE_ID_INTEL_ICH6:
594                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
595                 pm_registers = ich6_pm_registers;
596                 size = ARRAY_SIZE(ich6_pm_registers);
597                 break;
598         case PCI_DEVICE_ID_INTEL_ICH5:
599                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
600                 pm_registers = ich5_pm_registers;
601                 size = ARRAY_SIZE(ich5_pm_registers);
602                 break;
603         case PCI_DEVICE_ID_INTEL_ICH4:
604                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
605                 pm_registers = ich4_pm_registers;
606                 size = ARRAY_SIZE(ich4_pm_registers);
607                 break;
608         case PCI_DEVICE_ID_INTEL_ICH2:
609                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
610                 pm_registers = ich2_pm_registers;
611                 size = ARRAY_SIZE(ich2_pm_registers);
612                 break;
613         case PCI_DEVICE_ID_INTEL_ICH0:
614                 pmbase = pci_read_word(sb, 0x40) & 0xfffc;
615                 pm_registers = ich0_pm_registers;
616                 size = ARRAY_SIZE(ich0_pm_registers);
617                 break;
618         case PCI_DEVICE_ID_INTEL_82371XX:
619                 acpi = pci_get_dev(pacc, sb->domain, sb->bus, sb->dev, 3);
620                 if (!acpi) {
621                         printf("Southbridge function 3 not found.\n");
622                         return 1;
623                 }
624                 pmbase = pci_read_word(acpi, 0x40) & 0xfffc;
625                 pm_registers = i82371xx_pm_registers;
626                 size = ARRAY_SIZE(i82371xx_pm_registers);
627                 break;
628         case 0x1234: // Dummy for non-existent functionality
629                 printf("This southbridge does not have PMBASE.\n");
630                 return 1;
631         default:
632                 printf("Error: Dumping PMBASE on this southbridge is not (yet) supported.\n");
633                 return 1;
634         }
635
636         printf("PMBASE = 0x%04x (IO)\n\n", pmbase);
637
638         for (i = 0; i < size; i++) {
639                 switch (pm_registers[i].size) {
640                 case 4:
641                         printf("pmbase+0x%04x: 0x%08x (%s)\n",
642                                 pm_registers[i].addr,
643                                 inl(pmbase+pm_registers[i].addr),
644                                 pm_registers[i].name);
645                         break;
646                 case 2:
647                         printf("pmbase+0x%04x: 0x%04x     (%s)\n",
648                                 pm_registers[i].addr,
649                                 inw(pmbase+pm_registers[i].addr),
650                                 pm_registers[i].name);
651                         break;
652                 case 1:
653                         printf("pmbase+0x%04x: 0x%02x       (%s)\n",
654                                 pm_registers[i].addr,
655                                 inb(pmbase+pm_registers[i].addr),
656                                 pm_registers[i].name);
657                         break;
658                 }
659         }
660
661         return 0;
662 }