From ab5cac2c79f2240595fb923a37a4cbdb6ed3f231 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Sun, 14 Jul 2019 23:04:05 +0800 Subject: [PATCH] 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/41473 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- util/inteltool/Makefile | 2 +- util/inteltool/inteltool.h | 1 + util/inteltool/iobp.c | 320 +++++++++++++++++++++++++++++++++++++ util/inteltool/rootcmplx.c | 2 + 4 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 util/inteltool/iobp.c diff --git a/util/inteltool/Makefile b/util/inteltool/Makefile index 1ae04d4fc7..3b692fd332 100644 --- a/util/inteltool/Makefile +++ b/util/inteltool/Makefile @@ -16,7 +16,7 @@ CPPFLAGS += -I$(top)/src/arch/x86/include 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 4a6eba4968..1ad1224451 100644 --- a/util/inteltool/inteltool.h +++ b/util/inteltool/inteltool.h @@ -401,6 +401,7 @@ int print_mchbar(struct pci_dev *nb, struct pci_access *pacc, const char *dump_s 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 0000000000..e6c41858c3 --- /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 +#include +#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 b1e4939def..da9144a8d3 100644 --- a/util/inteltool/rootcmplx.c +++ b/util/inteltool/rootcmplx.c @@ -139,6 +139,8 @@ int print_rcba(struct pci_dev *sb) printf("0x%04x: 0x%08x\n", i, read32(rcba + i)); } + print_iobp(sb, rcba); + unmap_physical((void *)rcba, size); return 0; }