blob: bb196a914e42475f5bbd1e555f269783745d72f7 [file] [log] [blame]
Nico Huber18980232017-04-07 12:26:07 +02001/*
2 * inteltool - dump all registers on an Intel CPU + chipset based system.
3 *
4 * Copyright (C) 2017 secunet Security Networks AG
Maxim Polyakovb89ce2e2019-08-17 14:54:02 +03005 * Copyright (C) 2019 YADRO
Nico Huber18980232017-04-07 12:26:07 +02006 *
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
17#include <stdio.h>
18#include <stdlib.h>
19#include <stddef.h>
20#include <stdint.h>
21#include <assert.h>
22#include <inttypes.h>
23#include "inteltool.h"
24#include "pcr.h"
25
Johanna Schanderf80c5d92020-01-29 09:20:23 +010026#include "gpio_names/apollolake.h"
Johanna Schanderd5a65302020-01-29 09:16:06 +010027#include "gpio_names/cannonlake.h"
Matt DeVillier3c784452019-06-11 23:23:46 -050028#include "gpio_names/cannonlake_lp.h"
Johanna Schander7da602f2020-01-29 09:51:25 +010029#include "gpio_names/denverton.h"
Johanna Schanderdca20cd2020-01-29 09:14:18 +010030#include "gpio_names/icelake.h"
Johanna Schanderaff7d1f2020-01-29 09:29:39 +010031#include "gpio_names/lewisburg.h"
Johanna Schandere98af862020-01-29 09:25:45 +010032#include "gpio_names/sunrise.h"
Johanna Schanderdca20cd2020-01-29 09:14:18 +010033
Nico Huber18980232017-04-07 12:26:07 +020034#define SBBAR_SIZE (16 * MiB)
35#define PCR_PORT_SIZE (64 * KiB)
36
Nico Huber18980232017-04-07 12:26:07 +020037static const char *decode_pad_mode(const struct gpio_group *const group,
38 const size_t pad, const uint32_t dw0)
39{
40 const size_t pad_mode = dw0 >> 10 & 7;
Nico Huber8a95c6c2018-11-27 12:27:22 +010041 const char *const pad_name =
42 group->pad_names[pad * group->func_count + pad_mode];
43
Nico Huber18980232017-04-07 12:26:07 +020044 if (!pad_mode)
Nico Huber8a95c6c2018-11-27 12:27:22 +010045 return pad_name[0] == '*' ? "*GPIO" : "GPIO";
Nico Huber18980232017-04-07 12:26:07 +020046 else if (pad_mode < group->func_count)
47 return group->pad_names[pad * group->func_count + pad_mode];
48 else
49 return "RESERVED";
50}
51
52static void print_gpio_group(const uint8_t pid, size_t pad_cfg,
Thomas Heijligen725369f2019-02-19 10:51:34 +000053 const struct gpio_group *const group,
54 size_t pad_stepping)
Nico Huber18980232017-04-07 12:26:07 +020055{
56 size_t p;
57
58 printf("%s\n", group->display);
59
Thomas Heijligen725369f2019-02-19 10:51:34 +000060 for (p = 0; p < group->pad_count; ++p, pad_cfg += pad_stepping) {
Nico Huber18980232017-04-07 12:26:07 +020061 const uint32_t dw0 = read_pcr32(pid, pad_cfg);
62 const uint32_t dw1 = read_pcr32(pid, pad_cfg + 4);
Nico Huber8a95c6c2018-11-27 12:27:22 +010063 const char *const pad_name =
64 group->pad_names[p * group->func_count];
Nico Huber18980232017-04-07 12:26:07 +020065
Nico Huber8a95c6c2018-11-27 12:27:22 +010066 printf("0x%04zx: 0x%016"PRIx64" %-12s %-20s\n", pad_cfg,
Nico Huber18980232017-04-07 12:26:07 +020067 (uint64_t)dw1 << 32 | dw0,
Nico Huber8a95c6c2018-11-27 12:27:22 +010068 pad_name[0] == '*' ? &pad_name[1] : pad_name,
Nico Huber18980232017-04-07 12:26:07 +020069 decode_pad_mode(group, p, dw0));
70 }
71}
72
Thomas Heijligen725369f2019-02-19 10:51:34 +000073static void print_gpio_community(const struct gpio_community *const community,
74 size_t pad_stepping)
Nico Huber18980232017-04-07 12:26:07 +020075{
76 size_t group, pad_count;
77 size_t pad_cfg; /* offset in bytes under this communities PCR port */
78
79 printf("%s\n\nPCR Port ID: 0x%06zx\n\n",
80 community->name, (size_t)community->pcr_port_id << 16);
81
82 for (group = 0, pad_count = 0; group < community->group_count; ++group)
83 pad_count += community->groups[group]->pad_count;
84 assert(pad_count * 8 <= PCR_PORT_SIZE - 0x10);
85
86 pad_cfg = read_pcr32(community->pcr_port_id, 0x0c);
87 if (pad_cfg + pad_count * 8 > PCR_PORT_SIZE) {
88 fprintf(stderr, "Bad Pad Base Address: 0x%08zx\n", pad_cfg);
89 return;
90 }
91
92 for (group = 0; group < community->group_count; ++group) {
93 print_gpio_group(community->pcr_port_id,
Thomas Heijligen725369f2019-02-19 10:51:34 +000094 pad_cfg, community->groups[group],
95 pad_stepping);
96 pad_cfg += community->groups[group]->pad_count * pad_stepping;
Nico Huber18980232017-04-07 12:26:07 +020097 }
98}
99
Johanna Schandere32ded82020-01-29 10:08:17 +0100100const struct gpio_community *const *get_gpio_communities(struct pci_dev *const sb,
101 size_t* community_count,
102 size_t* pad_stepping)
Nico Huber18980232017-04-07 12:26:07 +0200103{
Johanna Schandere32ded82020-01-29 10:08:17 +0100104 *pad_stepping = 8;
Nico Huber18980232017-04-07 12:26:07 +0200105
106 switch (sb->device_id) {
Pavel Sayekat9429b702019-07-28 23:09:08 +0600107 case PCI_DEVICE_ID_INTEL_H110:
Felix Singerf98dc482019-07-29 21:53:14 +0200108 case PCI_DEVICE_ID_INTEL_H170:
109 case PCI_DEVICE_ID_INTEL_Z170:
110 case PCI_DEVICE_ID_INTEL_Q170:
111 case PCI_DEVICE_ID_INTEL_Q150:
Nico Huber54fe32f2017-10-03 16:03:07 +0200112 case PCI_DEVICE_ID_INTEL_B150:
Christian Walter9a8c5e72019-05-06 17:50:57 +0200113 case PCI_DEVICE_ID_INTEL_C236:
Felix Singerf98dc482019-07-29 21:53:14 +0200114 case PCI_DEVICE_ID_INTEL_C232:
115 case PCI_DEVICE_ID_INTEL_QM170:
116 case PCI_DEVICE_ID_INTEL_HM170:
117 case PCI_DEVICE_ID_INTEL_CM236:
Johanna Schandere32ded82020-01-29 10:08:17 +0100118 *community_count = ARRAY_SIZE(sunrise_communities);
119 return sunrise_communities;
Felix Singer0a7543d2019-02-19 23:49:11 +0100120 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE:
121 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL:
122 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL:
123 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL:
124 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL:
125 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL:
126 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL:
Matthew Garrett2bf28e52018-07-23 21:09:47 -0700127 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE:
128 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM:
129 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM:
Johanna Schandere32ded82020-01-29 10:08:17 +0100130 *community_count = ARRAY_SIZE(sunrise_lp_communities);
131 return sunrise_lp_communities;
Maxim Polyakovb89ce2e2019-08-17 14:54:02 +0300132 case PCI_DEVICE_ID_INTEL_C621:
133 case PCI_DEVICE_ID_INTEL_C622:
134 case PCI_DEVICE_ID_INTEL_C624:
135 case PCI_DEVICE_ID_INTEL_C625:
136 case PCI_DEVICE_ID_INTEL_C626:
137 case PCI_DEVICE_ID_INTEL_C627:
138 case PCI_DEVICE_ID_INTEL_C628:
139 case PCI_DEVICE_ID_INTEL_C629:
140 case PCI_DEVICE_ID_INTEL_C624_SUPER:
141 case PCI_DEVICE_ID_INTEL_C627_SUPER_1:
142 case PCI_DEVICE_ID_INTEL_C621_SUPER:
143 case PCI_DEVICE_ID_INTEL_C627_SUPER_2:
144 case PCI_DEVICE_ID_INTEL_C628_SUPER:
Johanna Schandere32ded82020-01-29 10:08:17 +0100145 *community_count = ARRAY_SIZE(lewisburg_communities);
146 return lewisburg_communities;
Thomas Heijligenda027192019-01-12 19:20:50 +0100147 case PCI_DEVICE_ID_INTEL_DNV_LPC:
Johanna Schandere32ded82020-01-29 10:08:17 +0100148 *community_count = ARRAY_SIZE(denverton_communities);
149 return denverton_communities;
Nico Huber8a95c6c2018-11-27 12:27:22 +0100150 case PCI_DEVICE_ID_INTEL_APL_LPC:
Johanna Schandere32ded82020-01-29 10:08:17 +0100151 *community_count = ARRAY_SIZE(apl_communities);
152 return apl_communities;
Matt DeVillier3c784452019-06-11 23:23:46 -0500153 case PCI_DEVICE_ID_INTEL_CANNONPOINT_LP_U_PREM:
154 *community_count = ARRAY_SIZE(cannonlake_pch_lp_communities);
155 *pad_stepping = 16;
156 return cannonlake_pch_lp_communities;
Thomas Heijligen725369f2019-02-19 10:51:34 +0000157 case PCI_DEVICE_ID_INTEL_H310:
158 case PCI_DEVICE_ID_INTEL_H370:
159 case PCI_DEVICE_ID_INTEL_Z390:
160 case PCI_DEVICE_ID_INTEL_Q370:
161 case PCI_DEVICE_ID_INTEL_B360:
162 case PCI_DEVICE_ID_INTEL_C246:
163 case PCI_DEVICE_ID_INTEL_C242:
164 case PCI_DEVICE_ID_INTEL_QM370:
165 case PCI_DEVICE_ID_INTEL_HM370:
166 case PCI_DEVICE_ID_INTEL_CM246:
Johanna Schandere32ded82020-01-29 10:08:17 +0100167 *community_count = ARRAY_SIZE(cannonlake_pch_h_communities);
168 *pad_stepping = 16;
169 return cannonlake_pch_h_communities;
Johanna Schander0174ea72020-01-04 15:14:59 +0100170 case PCI_DEVICE_ID_INTEL_ICELAKE_LP_U:
Johanna Schandere32ded82020-01-29 10:08:17 +0100171 *community_count = ARRAY_SIZE(icelake_pch_h_communities);
172 *pad_stepping = 16;
173 return icelake_pch_h_communities;
Nico Huber18980232017-04-07 12:26:07 +0200174 default:
Johanna Schandere32ded82020-01-29 10:08:17 +0100175 return NULL;
Nico Huber18980232017-04-07 12:26:07 +0200176 }
Johanna Schandere32ded82020-01-29 10:08:17 +0100177}
178
179void print_gpio_groups(struct pci_dev *const sb)
180{
181 size_t community_count;
182 const struct gpio_community *const *communities;
183 size_t pad_stepping;
184
185 communities = get_gpio_communities(sb, &community_count, &pad_stepping);
186
187 if (!communities)
188 return;
189
190 pcr_init(sb);
Nico Huber18980232017-04-07 12:26:07 +0200191
192 printf("\n============= GPIOS =============\n\n");
193
194 for (; community_count; --community_count)
Thomas Heijligen725369f2019-02-19 10:51:34 +0000195 print_gpio_community(*communities++, pad_stepping);
Nico Huber18980232017-04-07 12:26:07 +0200196}