Matt DeVillier has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/39394 )
Change subject: WIP: inteltool: Add option to output GPIOs as coreboot macros ......................................................................
WIP: inteltool: Add option to output GPIOs as coreboot macros
based on Nico's work in CB:25145, but updated to use current macros found in gpio_defs.h in soc/intel/common. Avoids use of "legacy" macros which are only applicable to Skylake/Kabylake.
Test: Generate reasonably sane list of macros for out-of-tree Whiskeylake-based device.
Signed-off-by: Matt DeVillier matt.devillier@puri.sm Change-Id: Ide0f0f529d62b312a719e78b0e2f747f41067a36 --- M util/inteltool/gpio.c M util/inteltool/gpio_groups.c M util/inteltool/inteltool.c M util/inteltool/inteltool.h 4 files changed, 212 insertions(+), 19 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/94/39394/1
diff --git a/util/inteltool/gpio.c b/util/inteltool/gpio.c index e4e3570..05b5181 100644 --- a/util/inteltool/gpio.c +++ b/util/inteltool/gpio.c @@ -1072,7 +1072,7 @@ case PCI_DEVICE_ID_INTEL_HM370: case PCI_DEVICE_ID_INTEL_CM246: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_U: - print_gpio_groups(sb); + print_gpio_groups(sb, false); return 0; case PCI_DEVICE_ID_INTEL_82371XX: printf("This southbridge has GPIOs in the PM unit.\n"); diff --git a/util/inteltool/gpio_groups.c b/util/inteltool/gpio_groups.c index 5457109..d034860 100644 --- a/util/inteltool/gpio_groups.c +++ b/util/inteltool/gpio_groups.c @@ -49,13 +49,185 @@ return "RESERVED"; }
+static const char *decode_table_gpio_term(const size_t term) +{ + switch (term) { + case 0: return "NONE"; + case 2: return "DN_5K"; + case 4: return "DN_20K"; + case 9: return "UP_1K"; + case 10: return "UP_5K"; + case 11: return "UP_2K"; + case 12: return "UP_20K"; + case 13: return "UP_667"; + case 15: return "NATIVE"; + default: return "UNSUPPORTED"; + } +} + +static const char *decode_table_gpio_reset(const size_t reset) +{ + switch (reset) { + case 0: return "PWROK"; + case 1: return "DEEP"; + case 2: return "PLTRST"; + case 3: return "RSMRST"; + default: return "UNSUPPORTED"; + } +} + +static const char *decode_table_gpio_nf(const size_t pad_mode) +{ + switch (pad_mode) { + case 0: return "GPIO"; + case 1: return "NF1"; + case 2: return "NF2"; + case 3: return "NF3"; + default: return "UNSUPPORTED"; + } +} + +static const char *decode_table_gpio_trig(const size_t trig_mode) +{ + switch (trig_mode) { + case 0: return "LEVEL"; + case 1: return "EDGE_SINGLE"; + case 2: return "OFF"; + case 3: return "EDGE_BOTH"; + default: return "UNSUPPORTED"; + } +} + +static int print_table_gpio(const struct gpio_group *const group, + const size_t pad, + const uint32_t dw0, const uint32_t dw1) +{ + const size_t tx_state = dw0 >> 0 & 1; + const size_t tx_disable = dw0 >> 8 & 1; + const size_t rx_disable = dw0 >> 9 & 1; + const size_t pad_mode = dw0 >> 10 & 3; + const size_t int_route = dw0 >> 17 & 0x0f; + const size_t rx_invert = dw0 >> 23 & 1; + const size_t rx_evcfg = dw0 >> 25 & 3; + const size_t rx_raw1 = dw0 >> 28 & 1; + const size_t rx_padsel = dw0 >> 29 & 1; + const size_t pad_reset = dw0 >> 30 & 3; + const size_t term = dw1 >> 10 & 0x0f; + const size_t pad_tol = dw1 >> 25 & 0x01; + const size_t driver = dw1 >> 4 & 1; + + const char *const pad_name = group->pad_names[pad * group->func_count]; + + if (rx_padsel || rx_raw1) + return -1; + + if (pad_mode) { + printf("PAD_CFG_NF%s(%s, %s, %s, %s),\n", + pad_tol ? "_1V8" : "", pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset), + decode_table_gpio_nf(pad_mode)); + } else if (!tx_disable) { + if (!rx_disable) { + fprintf(stderr, "WARNING: %s has both TX and RX enabled" + ", disabling RX!\n", pad_name); + } + if (term) { + printf("PAD_CFG_TERM_GPO(%s, %zu, %s, %s),\n", + pad_name, tx_state, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset)); + } else { + printf("PAD_CFG_GPO(%s, %zu, %s),\n", + pad_name, tx_state, + decode_table_gpio_reset(pad_reset)); + } + } else if (!rx_disable && tx_disable) { + switch (int_route) { + case 0x0: + if (rx_invert || rx_evcfg > 1) + return -1; + if (driver) { + printf("PAD_CFG_GPI_GPIO_DRIVER(%s, %s, %s),\n", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset)); + } else if (rx_evcfg & ~0x04) { + printf("PAD_CFG_GPI(%s, %s, %s),\n", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset)); + } else { + printf("PAD_CFG_GPI_INT(%s, %s, %s, %s),\n", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset), + decode_table_gpio_trig(rx_evcfg)); + } + break; + case 0x1: + return -1; + case 0x2: + if (rx_evcfg == 1) { + printf("PAD_CFG_GPI_SMI_" + "%s(%s, %s, %s, %s),\n", + rx_invert ? "LOW" : "HIGH", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset), + decode_table_gpio_trig(rx_evcfg)); + } else { + return -1; + } + break; + case 0x4: + if (rx_evcfg > 1) + return -1; + printf("PAD_CFG_GPI_SCI_%s(%s, %s, %s, %s),\n", + rx_invert ? "LOW" : "HIGH", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset), + decode_table_gpio_trig(rx_evcfg)); + break; + case 0x8: + if (rx_evcfg > 1) + return -1; + if (rx_evcfg && !rx_invert) { + printf("PAD_CFG_GPI_APIC(%s, %s, %s, %s, %s),\n", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset), + decode_table_gpio_trig(rx_evcfg), + rx_invert ? "INVERT" : "NONE"); + } else { + printf("PAD_CFG_GPI_APIC%s%s(%s, %s, %s),\n", + rx_evcfg ? "_EDGE" : "", + rx_invert ? "_LOW" : "_HIGH", + pad_name, + decode_table_gpio_term(term), + decode_table_gpio_reset(pad_reset)); + } + break; + default: + return -1; + } + } else { + printf("PAD_NC(%s, %s),\n", pad_name, decode_table_gpio_term(term)); + } + return 0; +} + static void print_gpio_group(const uint8_t pid, size_t pad_cfg, const struct gpio_group *const group, - size_t pad_stepping) + size_t pad_stepping, const bool use_macros) { size_t p;
- printf("%s\n", group->display); + if (use_macros) + printf("\n/* %s */\n\n", group->display); + else + printf("%s\n", group->display);
for (p = 0; p < group->pad_count; ++p, pad_cfg += pad_stepping) { const uint32_t dw0 = read_pcr32(pid, pad_cfg); @@ -63,21 +235,31 @@ const char *const pad_name = group->pad_names[p * group->func_count];
- printf("0x%04zx: 0x%016"PRIx64" %-12s %-20s\n", pad_cfg, - (uint64_t)dw1 << 32 | dw0, - pad_name[0] == '*' ? &pad_name[1] : pad_name, - decode_pad_mode(group, p, dw0)); + if (use_macros) { + printf("/* %-8s %-20s */\t", + group->pad_names[p * group->func_count], + decode_pad_mode(group, p, dw0)); + + if (print_table_gpio(group, p, dw0, dw1)) + printf("PAD_CFG_UNSUPPORTED,\n"); + } else { + printf("0x%04zx: 0x%016"PRIx64" %-12s %-20s\n", pad_cfg, + (uint64_t)dw1 << 32 | dw0, + pad_name[0] == '*' ? &pad_name[1] : pad_name, + decode_pad_mode(group, p, dw0)); + } } }
static void print_gpio_community(const struct gpio_community *const community, - size_t pad_stepping) + size_t pad_stepping, const bool use_macros) { size_t group, pad_count; size_t pad_cfg; /* offset in bytes under this communities PCR port */
- printf("%s\n\nPCR Port ID: 0x%06zx\n\n", - community->name, (size_t)community->pcr_port_id << 16); + if (!use_macros) + printf("%s\n\nPCR Port ID: 0x%06zx\n\n", + community->name, (size_t)community->pcr_port_id << 16);
for (group = 0, pad_count = 0; group < community->group_count; ++group) pad_count += community->groups[group]->pad_count; @@ -92,7 +274,7 @@ for (group = 0; group < community->group_count; ++group) { print_gpio_group(community->pcr_port_id, pad_cfg, community->groups[group], - pad_stepping); + pad_stepping, use_macros); pad_cfg += community->groups[group]->pad_count * pad_stepping; } } @@ -176,7 +358,7 @@ } }
-void print_gpio_groups(struct pci_dev *const sb) +void print_gpio_groups(struct pci_dev *const sb, const bool use_macros) { size_t community_count; const struct gpio_community *const *communities; @@ -192,5 +374,5 @@ printf("\n============= GPIOS =============\n\n");
for (; community_count; --community_count) - print_gpio_community(*communities++, pad_stepping); + print_gpio_community(*communities++, pad_stepping, use_macros); } diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c index 555aa2f..bd0e5e9 100644 --- a/util/inteltool/inteltool.c +++ b/util/inteltool/inteltool.c @@ -490,7 +490,7 @@
static void print_usage(const char *name) { - printf("usage: %s [-vh?gGrpmedPMaAsfSRx]\n", name); + printf("usage: %s [-vh?gGrpmedPMaAsfSRxC]\n", name); printf("\n" " -v | --version: print the version\n" " -h | --help: print this help\n\n" @@ -510,6 +510,7 @@ " -A | --ambs: dump AMB registers\n" " -x | --sgx: dump SGX status\n" " -a | --all: dump all known (safe) registers\n" + " -C | --macros: dump GPIOs in coreboot macro format\n" " --pcr=PORT_ID: dump all registers of a PCR port\n" " (may be specified max %d times)\n" "\n", MAX_PCR_PORTS); @@ -570,7 +571,7 @@ int dump_pmbase = 0, dump_epbar = 0, dump_dmibar = 0; int dump_pciexbar = 0, dump_coremsrs = 0, dump_ambs = 0; int dump_spi = 0, dump_gfx = 0, dump_ahci = 0, dump_sgx = 0; - int show_gpio_diffs = 0; + int show_gpio_diffs = 0, use_gpio_macros = 0; size_t pcr_count = 0; uint8_t dump_pcr[MAX_PCR_PORTS];
@@ -593,11 +594,12 @@ {"gfx", 0, 0, 'f'}, {"ahci", 0, 0, 'R'}, {"sgx", 0, 0, 'x'}, + {"macros", 0, 0, 'C'}, {"pcr", required_argument, 0, LONG_OPT_PCR}, {0, 0, 0, 0} };
- while ((opt = getopt_long(argc, argv, "vh?gGrpmedPMaAsfRS:x", + while ((opt = getopt_long(argc, argv, "vh?gGrpmedPMaAsfRCS:x", long_options, &option_index)) != EOF) { switch (opt) { case 'v': @@ -665,6 +667,10 @@ case 'x': dump_sgx = 1; break; + case 'C': + dump_gpios = 1; + use_gpio_macros = 1; + break; case LONG_OPT_PCR: if (pcr_count < MAX_PCR_PORTS) { errno = 0; @@ -795,8 +801,12 @@
/* Now do the deed */ if (dump_gpios) { - print_gpios(sb, 1, show_gpio_diffs); - printf("\n\n"); + if (use_gpio_macros) { + print_gpio_groups(sb, use_gpio_macros); + } else { + print_gpios(sb, 1, show_gpio_diffs); + printf("\n\n"); + } } else if (show_gpio_diffs) { print_gpios(sb, 0, show_gpio_diffs); printf("\n\n"); diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h index dc55246..5468c21 100644 --- a/util/inteltool/inteltool.h +++ b/util/inteltool/inteltool.h @@ -19,6 +19,7 @@
#include <commonlib/helpers.h>
+#include <stdbool.h> #include <stdint.h>
#if defined(__GLIBC__) @@ -399,7 +400,7 @@ const struct gpio_community *const *get_gpio_communitys(struct pci_dev *const sb, size_t* community_count, size_t* pad_stepping); -void print_gpio_groups(struct pci_dev *sb); +void print_gpio_groups(struct pci_dev *sb, bool use_macros); int print_epbar(struct pci_dev *nb); int print_dmibar(struct pci_dev *nb); int print_pciexbar(struct pci_dev *nb);