Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 1 | /* |
| 2 | * inteltool - dump all registers on an Intel CPU + chipset based system. |
| 3 | * |
| 4 | * Copyright (C) 2017 secunet Security Networks AG |
Maxim Polyakov | b89ce2e | 2019-08-17 14:54:02 +0300 | [diff] [blame] | 5 | * Copyright (C) 2019 YADRO |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 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 | |
| 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 Schander | f80c5d9 | 2020-01-29 09:20:23 +0100 | [diff] [blame] | 26 | #include "gpio_names/apollolake.h" |
Johanna Schander | d5a6530 | 2020-01-29 09:16:06 +0100 | [diff] [blame] | 27 | #include "gpio_names/cannonlake.h" |
Matt DeVillier | 3c78445 | 2019-06-11 23:23:46 -0500 | [diff] [blame] | 28 | #include "gpio_names/cannonlake_lp.h" |
Johanna Schander | 7da602f | 2020-01-29 09:51:25 +0100 | [diff] [blame] | 29 | #include "gpio_names/denverton.h" |
Johanna Schander | dca20cd | 2020-01-29 09:14:18 +0100 | [diff] [blame] | 30 | #include "gpio_names/icelake.h" |
Johanna Schander | aff7d1f | 2020-01-29 09:29:39 +0100 | [diff] [blame] | 31 | #include "gpio_names/lewisburg.h" |
Johanna Schander | e98af86 | 2020-01-29 09:25:45 +0100 | [diff] [blame] | 32 | #include "gpio_names/sunrise.h" |
Johanna Schander | dca20cd | 2020-01-29 09:14:18 +0100 | [diff] [blame] | 33 | |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 34 | #define SBBAR_SIZE (16 * MiB) |
| 35 | #define PCR_PORT_SIZE (64 * KiB) |
| 36 | |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 37 | static 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 Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 41 | const char *const pad_name = |
| 42 | group->pad_names[pad * group->func_count + pad_mode]; |
| 43 | |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 44 | if (!pad_mode) |
Nico Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 45 | return pad_name[0] == '*' ? "*GPIO" : "GPIO"; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 46 | 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 | |
| 52 | static void print_gpio_group(const uint8_t pid, size_t pad_cfg, |
Thomas Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 53 | const struct gpio_group *const group, |
| 54 | size_t pad_stepping) |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 55 | { |
| 56 | size_t p; |
| 57 | |
| 58 | printf("%s\n", group->display); |
| 59 | |
Thomas Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 60 | for (p = 0; p < group->pad_count; ++p, pad_cfg += pad_stepping) { |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 61 | const uint32_t dw0 = read_pcr32(pid, pad_cfg); |
| 62 | const uint32_t dw1 = read_pcr32(pid, pad_cfg + 4); |
Nico Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 63 | const char *const pad_name = |
| 64 | group->pad_names[p * group->func_count]; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 65 | |
Nico Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 66 | printf("0x%04zx: 0x%016"PRIx64" %-12s %-20s\n", pad_cfg, |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 67 | (uint64_t)dw1 << 32 | dw0, |
Nico Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 68 | pad_name[0] == '*' ? &pad_name[1] : pad_name, |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 69 | decode_pad_mode(group, p, dw0)); |
| 70 | } |
| 71 | } |
| 72 | |
Thomas Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 73 | static void print_gpio_community(const struct gpio_community *const community, |
| 74 | size_t pad_stepping) |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 75 | { |
| 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 Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 94 | pad_cfg, community->groups[group], |
| 95 | pad_stepping); |
| 96 | pad_cfg += community->groups[group]->pad_count * pad_stepping; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 97 | } |
| 98 | } |
| 99 | |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 100 | const struct gpio_community *const *get_gpio_communities(struct pci_dev *const sb, |
| 101 | size_t* community_count, |
| 102 | size_t* pad_stepping) |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 103 | { |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 104 | *pad_stepping = 8; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 105 | |
| 106 | switch (sb->device_id) { |
Pavel Sayekat | 9429b70 | 2019-07-28 23:09:08 +0600 | [diff] [blame] | 107 | case PCI_DEVICE_ID_INTEL_H110: |
Felix Singer | f98dc48 | 2019-07-29 21:53:14 +0200 | [diff] [blame] | 108 | 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 Huber | 54fe32f | 2017-10-03 16:03:07 +0200 | [diff] [blame] | 112 | case PCI_DEVICE_ID_INTEL_B150: |
Christian Walter | 9a8c5e7 | 2019-05-06 17:50:57 +0200 | [diff] [blame] | 113 | case PCI_DEVICE_ID_INTEL_C236: |
Felix Singer | f98dc48 | 2019-07-29 21:53:14 +0200 | [diff] [blame] | 114 | 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 Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 118 | *community_count = ARRAY_SIZE(sunrise_communities); |
| 119 | return sunrise_communities; |
Felix Singer | 0a7543d | 2019-02-19 23:49:11 +0100 | [diff] [blame] | 120 | 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 Garrett | 2bf28e5 | 2018-07-23 21:09:47 -0700 | [diff] [blame] | 127 | 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 Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 130 | *community_count = ARRAY_SIZE(sunrise_lp_communities); |
| 131 | return sunrise_lp_communities; |
Maxim Polyakov | b89ce2e | 2019-08-17 14:54:02 +0300 | [diff] [blame] | 132 | 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 Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 145 | *community_count = ARRAY_SIZE(lewisburg_communities); |
| 146 | return lewisburg_communities; |
Thomas Heijligen | da02719 | 2019-01-12 19:20:50 +0100 | [diff] [blame] | 147 | case PCI_DEVICE_ID_INTEL_DNV_LPC: |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 148 | *community_count = ARRAY_SIZE(denverton_communities); |
| 149 | return denverton_communities; |
Nico Huber | 8a95c6c | 2018-11-27 12:27:22 +0100 | [diff] [blame] | 150 | case PCI_DEVICE_ID_INTEL_APL_LPC: |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 151 | *community_count = ARRAY_SIZE(apl_communities); |
| 152 | return apl_communities; |
Matt DeVillier | 3c78445 | 2019-06-11 23:23:46 -0500 | [diff] [blame] | 153 | 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 Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 157 | 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 Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 167 | *community_count = ARRAY_SIZE(cannonlake_pch_h_communities); |
| 168 | *pad_stepping = 16; |
| 169 | return cannonlake_pch_h_communities; |
Johanna Schander | 0174ea7 | 2020-01-04 15:14:59 +0100 | [diff] [blame] | 170 | case PCI_DEVICE_ID_INTEL_ICELAKE_LP_U: |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 171 | *community_count = ARRAY_SIZE(icelake_pch_h_communities); |
| 172 | *pad_stepping = 16; |
| 173 | return icelake_pch_h_communities; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 174 | default: |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 175 | return NULL; |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 176 | } |
Johanna Schander | e32ded8 | 2020-01-29 10:08:17 +0100 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | void 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 Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 191 | |
| 192 | printf("\n============= GPIOS =============\n\n"); |
| 193 | |
| 194 | for (; community_count; --community_count) |
Thomas Heijligen | 725369f | 2019-02-19 10:51:34 +0000 | [diff] [blame] | 195 | print_gpio_community(*communities++, pad_stepping); |
Nico Huber | 1898023 | 2017-04-07 12:26:07 +0200 | [diff] [blame] | 196 | } |