inteltool: Support dumping IOBP register values
This patch also adds LynxPoint and WildcatPoint-LP IOBP registers,
which is used to get the USB and SATA configuration values for
autoport.
Change-Id: I1f11640fdff59a5317f19057476f7e48c2956ab9
Signed-off-by: Iru Cai <mytbk920423@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41473
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/util/inteltool/Makefile b/util/inteltool/Makefile
index 1ae04d4..3b692fd 100644
--- a/util/inteltool/Makefile
+++ b/util/inteltool/Makefile
@@ -16,7 +16,7 @@
OBJS = inteltool.o pcr.o cpu.o gpio.o gpio_groups.o rootcmplx.o powermgt.o \
- memory.o pcie.o amb.o ivy_memory.o spi.o gfx.o ahci.o lpc.o
+ memory.o pcie.o amb.o ivy_memory.o spi.o gfx.o ahci.o lpc.o iobp.o
OS_ARCH = $(shell uname)
ifeq ($(OS_ARCH), Darwin)
diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h
index 4a6eba4..1ad1224 100644
--- a/util/inteltool/inteltool.h
+++ b/util/inteltool/inteltool.h
@@ -401,6 +401,7 @@
int print_pmbase(struct pci_dev *sb, struct pci_access *pacc);
int print_lpc(struct pci_dev *sb, struct pci_access *pacc);
int print_rcba(struct pci_dev *sb);
+void print_iobp(struct pci_dev *sb, volatile uint8_t *rcba);
int print_gpios(struct pci_dev *sb, int show_all, int show_diffs);
const struct gpio_community *const *get_gpio_communities(struct pci_dev *const sb,
size_t* community_count,
diff --git a/util/inteltool/iobp.c b/util/inteltool/iobp.c
new file mode 100644
index 0000000..e6c4185
--- /dev/null
+++ b/util/inteltool/iobp.c
@@ -0,0 +1,320 @@
+/* inteltool - dump all registers on an Intel CPU + chipset based system */
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "inteltool.h"
+
+#define RCBA16(rcba, x) (*((volatile u16 *)((rcba) + (x))))
+#define RCBA32(rcba, x) (*((volatile u32 *)((rcba) + (x))))
+/* IO Buffer Programming */
+#define IOBPIRI 0x2330
+#define IOBPD 0x2334
+#define IOBPS 0x2338
+#define IOBPS_READY 0x0001
+#define IOBPS_TX_MASK 0x0006
+#define IOBPS_MASK 0xff00
+#define IOBPS_READ 0x0600
+#define IOBPS_WRITE 0x0700
+#define IOBPU 0x233a
+#define IOBPU_MAGIC 0xf000
+
+#define IOBP_RETRY 1000
+static inline int iobp_poll(volatile uint8_t *rcba)
+{
+ for (int try = IOBP_RETRY; try > 0; try--) {
+ u16 status = RCBA16(rcba, IOBPS);
+ if ((status & IOBPS_READY) == 0)
+ return 1;
+ // udelay(10);
+ }
+
+ printf("IOBP: timeout waiting for transaction to complete\n");
+ return 0;
+}
+
+static u32 pch_iobp_read(volatile uint8_t *rcba, u32 address)
+{
+ u16 status;
+
+ if (!iobp_poll(rcba))
+ return 0;
+
+ /* Set the address */
+ RCBA32(rcba, IOBPIRI) = address;
+
+ /* READ OPCODE */
+ status = RCBA16(rcba, IOBPS);
+ status &= ~IOBPS_MASK;
+ status |= IOBPS_READ;
+ RCBA16(rcba, IOBPS) = status;
+
+ /* Undocumented magic */
+ RCBA16(rcba, IOBPU) = IOBPU_MAGIC;
+
+ /* Set ready bit */
+ status = RCBA16(rcba, IOBPS);
+ status |= IOBPS_READY;
+ RCBA16(rcba, IOBPS) = status;
+
+ if (!iobp_poll(rcba))
+ return 0;
+
+ /* Check for successful transaction */
+ status = RCBA16(rcba, IOBPS);
+ if (status & IOBPS_TX_MASK) {
+ printf("IOBP: read 0x%08x failed\n", address);
+ return 0;
+ }
+
+ /* Read IOBP data */
+ return RCBA32(rcba, IOBPD);
+}
+
+struct iobp_register {
+ u32 addr;
+ const char *name;
+};
+
+static const struct iobp_register lynxpoint_iobp_registers[] = {
+ /* SATA Electrical Control Register */
+ {0xea002488, "SECRT88P0"},
+ {0xea00248c, "SECRT8CP0"},
+ {0xea002490, "SECRT90P0"},
+ {0xea002498, "SECRT98P0"},
+ {0xea00251c, "SECRR1CP0"},
+ {0xea002550, "SECRR50P0"},
+ {0xea002554, "SECRR54P0"},
+ {0xea002558, "SECRR58P0"},
+
+ {0xea002688, "SECRT88P1"},
+ {0xea00268c, "SECRT8CP1"},
+ {0xea002690, "SECRT90P1"},
+ {0xea002698, "SECRT98P1"},
+ {0xea00271c, "SECRR1CP1"},
+ {0xea002750, "SECRR50P1"},
+ {0xea002754, "SECRR54P1"},
+ {0xea002758, "SECRR58P1"},
+
+ {0xea000888, "SECRT88P2"},
+ {0xea00088c, "SECRT8CP2"},
+ {0xea000890, "SECRT90P2"},
+ {0xea000898, "SECRT98P2"},
+ {0xea00091c, "SECRR1CP2"},
+ {0xea000950, "SECRR50P2"},
+ {0xea000954, "SECRR54P2"},
+ {0xea000958, "SECRR58P2"},
+
+ {0xea000a88, "SECRT88P3"},
+ {0xea000a8c, "SECRT8CP3"},
+ {0xea000a90, "SECRT90P3"},
+ {0xea000a98, "SECRT98P3"},
+ {0xea000b1c, "SECRR1CP3"},
+ {0xea000b50, "SECRR50P3"},
+ {0xea000b54, "SECRR54P3"},
+ {0xea000b58, "SECRR58P3"},
+
+ {0xea002088, "SECRT88P4"},
+ {0xea00208c, "SECRT8CP4"},
+ {0xea002090, "SECRT90P4"},
+ {0xea002098, "SECRT98P4"},
+ {0xea00211c, "SECRR1CP4"},
+ {0xea002150, "SECRR50P4"},
+ {0xea002154, "SECRR54P4"},
+ {0xea002158, "SECRR58P4"},
+
+ {0xea002288, "SECRT88P5"},
+ {0xea00228c, "SECRT8CP5"},
+ {0xea002290, "SECRT90P5"},
+ {0xea002298, "SECRT98P5"},
+ {0xea00231c, "SECRR1CP5"},
+ {0xea002350, "SECRR50P5"},
+ {0xea002354, "SECRR54P5"},
+ {0xea002358, "SECRR58P5"},
+
+ {0xea008100, "SECRF00"},
+ {0xea008104, "SECRF04"},
+
+ /* USB 2.0 Electrical Control Register */
+ {0xe5004100, "U2ECRP01"},
+ {0xe5004200, "U2ECRP02"},
+ {0xe5004300, "U2ECRP03"},
+ {0xe5004400, "U2ECRP04"},
+ {0xe5004500, "U2ECRP05"},
+ {0xe5004600, "U2ECRP06"},
+ {0xe5004700, "U2ECRP07"},
+ {0xe5004800, "U2ECRP08"},
+ {0xe5004900, "U2ECRP09"},
+ {0xe5004a00, "U2ECRP10"},
+ {0xe5004b00, "U2ECRP11"},
+ {0xe5004c00, "U2ECRP12"},
+ {0xe5004d00, "U2ECRP13"},
+ {0xe5004e00, "U2ECRP14"},
+
+ /* IOBP related to USB 3.0 ports */
+ /* port 1 */
+ {0xe900175c, ""},
+ {0xe9001760, ""},
+ {0xe9001768, ""},
+ {0xe9001770, ""},
+ {0xe90017cc, ""},
+ /* port 2 */
+ {0xe900155c, ""},
+ {0xe9001560, ""},
+ {0xe9001568, ""},
+ {0xe9001570, ""},
+ {0xe90015cc, ""},
+ /* port 3 */
+ {0xe9002f5c, ""},
+ {0xe9002f60, ""},
+ {0xe9002f68, ""},
+ {0xe9002f70, ""},
+ {0xe9002fcc, ""},
+ /* port 4 */
+ {0xe9002d5c, ""},
+ {0xe9002d60, ""},
+ {0xe9002d68, ""},
+ {0xe9002d70, ""},
+ {0xe9002dcc, ""},
+ /* port 5 */
+ {0xe900335c, ""},
+ {0xe9003360, ""},
+ {0xe9003368, ""},
+ {0xe9003370, ""},
+ {0xe90033cc, ""},
+ /* port 6 */
+ {0xe900315c, ""},
+ {0xe9003160, ""},
+ {0xe9003168, ""},
+ {0xe9003170, ""},
+ {0xe90031cc, ""},
+};
+
+static const struct iobp_register lynxpoint_lp_iobp_registers[] = {
+ /* SATA Electrical Control Register */
+ {0xea002688, "SECRT88P0"},
+ {0xea00268c, "SECRT8CP0"},
+ {0xea002690, "SECRT90P0"},
+ {0xea002698, "SECRT98P0"},
+ {0xea00271c, "SECRR1CP0"},
+ {0xea002750, "SECRR50P0"},
+ {0xea002754, "SECRR54P0"},
+ {0xea002758, "SECRR58P0"},
+
+ {0xea002488, "SECRT88P1"},
+ {0xea00248c, "SECRT8CP1"},
+ {0xea002490, "SECRT90P1"},
+ {0xea002498, "SECRT98P1"},
+ {0xea00251c, "SECRR1CP1"},
+ {0xea002550, "SECRR50P1"},
+ {0xea002554, "SECRR54P1"},
+ {0xea002558, "SECRR58P1"},
+
+ {0xea002288, "SECRT88P2"},
+ {0xea00228c, "SECRT8CP2"},
+ {0xea002290, "SECRT90P2"},
+ {0xea002298, "SECRT98P2"},
+ {0xea00231c, "SECRR1CP2"},
+ {0xea002350, "SECRR50P2"},
+ {0xea002354, "SECRR54P2"},
+ {0xea002358, "SECRR58P2"},
+
+ {0xea002088, "SECRT88P3"},
+ {0xea00208c, "SECRT8CP3"},
+ {0xea002090, "SECRT90P3"},
+ {0xea002098, "SECRT98P3"},
+ {0xea00211c, "SECRR1CP3"},
+ {0xea002150, "SECRR50P3"},
+ {0xea002154, "SECRR54P3"},
+ {0xea002158, "SECRR58P3"},
+
+ {0xea008100, "SECRF00"},
+ {0xea008104, "SECRF04"},
+
+ /* USB 2.0 Electrical Control Register, 8 for -U SoC and 10 for Core-M */
+ {0xe5004100, "U2ECRP01"},
+ {0xe5004200, "U2ECRP02"},
+ {0xe5004300, "U2ECRP03"},
+ {0xe5004400, "U2ECRP04"},
+ {0xe5004500, "U2ECRP05"},
+ {0xe5004600, "U2ECRP06"},
+ {0xe5004700, "U2ECRP07"},
+ {0xe5004800, "U2ECRP08"},
+ {0xe5004900, "U2ECRP09"},
+ {0xe5004a00, "U2ECRP10"},
+
+ /* IOBP related to USB 3.0 ports */
+ /* port 1 */
+ {0xe900215c, ""},
+ {0xe9002160, ""},
+ {0xe9002168, ""},
+ {0xe9002170, ""},
+ {0xe90021cc, ""},
+ /* port 2 */
+ {0xe900235c, ""},
+ {0xe9002360, ""},
+ {0xe9002368, ""},
+ {0xe9002370, ""},
+ {0xe90023cc, ""},
+ /* port 3 */
+ {0xe900255c, ""},
+ {0xe9002560, ""},
+ {0xe9002568, ""},
+ {0xe9002570, ""},
+ {0xe90025cc, ""},
+ /* port 4 */
+ {0xe900275c, ""},
+ {0xe9002760, ""},
+ {0xe9002768, ""},
+ {0xe9002770, ""},
+ {0xe90027cc, ""},
+};
+
+void print_iobp(struct pci_dev *sb, volatile uint8_t *rcba)
+{
+ const struct iobp_register *iobp_registers = NULL;
+ size_t iobp_size = 0;
+
+ switch (sb->device_id) {
+ case PCI_DEVICE_ID_INTEL_C8_MOBILE:
+ case PCI_DEVICE_ID_INTEL_C8_DESKTOP:
+ case PCI_DEVICE_ID_INTEL_Z87:
+ case PCI_DEVICE_ID_INTEL_Z85:
+ case PCI_DEVICE_ID_INTEL_HM86:
+ case PCI_DEVICE_ID_INTEL_H87:
+ case PCI_DEVICE_ID_INTEL_HM87:
+ case PCI_DEVICE_ID_INTEL_Q85:
+ case PCI_DEVICE_ID_INTEL_Q87:
+ case PCI_DEVICE_ID_INTEL_QM87:
+ case PCI_DEVICE_ID_INTEL_B85:
+ case PCI_DEVICE_ID_INTEL_C222:
+ case PCI_DEVICE_ID_INTEL_C224:
+ case PCI_DEVICE_ID_INTEL_C226:
+ case PCI_DEVICE_ID_INTEL_H81:
+ iobp_registers = lynxpoint_iobp_registers;
+ iobp_size = ARRAY_SIZE(lynxpoint_iobp_registers);
+ break;
+ case PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_FULL:
+ case PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_PREM:
+ case PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_BASE:
+ case PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_PREM:
+ case PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP:
+ iobp_registers = lynxpoint_lp_iobp_registers;
+ iobp_size = ARRAY_SIZE(lynxpoint_lp_iobp_registers);
+ break;
+ default:
+ break;
+ }
+
+ if (iobp_size == 0)
+ return;
+
+ printf("\n============= IOBP ==============\n\n");
+
+ for (size_t i = 0; i < iobp_size; i++) {
+ u32 address = iobp_registers[i].addr;
+ const char *name = iobp_registers[i].name;
+ u32 v = pch_iobp_read(rcba, address);
+ printf("0x%08x: 0x%08x (%s)\n", address, v, name);
+ }
+}
diff --git a/util/inteltool/rootcmplx.c b/util/inteltool/rootcmplx.c
index b1e4939..da9144a 100644
--- a/util/inteltool/rootcmplx.c
+++ b/util/inteltool/rootcmplx.c
@@ -139,6 +139,8 @@
printf("0x%04x: 0x%08x\n", i, read32(rcba + i));
}
+ print_iobp(sb, rcba);
+
unmap_physical((void *)rcba, size);
return 0;
}