[PATCH 0/3] iTCO refactoring and V6 / Elkhart Lake support

92 views
Skip to first unread message

Jan Kiszka

unread,
Jan 12, 2021, 7:10:14 AM1/12/21
to efibootg...@googlegroups.com
Tested only on an EHL platform so far. If you have anything in reach
that used to work fine with our iTCO driver, please check this series!

Jan

Jan Kiszka (3):
watchdog: iTCO: Drop enabling of SMI
watchdog: iTCO: Rework TCOBASE retrieval
watchdog: iTCO: Add support for version 6 as found in Elkhart Lake
SOCs

drivers/watchdog/itco.c | 90 ++++++++++++++++++++++++-----------------
1 file changed, 54 insertions(+), 36 deletions(-)

--
2.26.2

Jan Kiszka

unread,
Jan 12, 2021, 7:10:15 AM1/12/21
to efibootg...@googlegroups.com
From: Jan Kiszka <jan.k...@siemens.com>

Linux does not do that either, rather turns it off for V1 iTCO (which we
do not support), and things seem to work fine. So drop this.

Signed-off-by: Jan Kiszka <jan.k...@siemens.com>
---
drivers/watchdog/itco.c | 23 -----------------------
1 file changed, 23 deletions(-)

diff --git a/drivers/watchdog/itco.c b/drivers/watchdog/itco.c
index 6fe83f7..1c393e2 100644
--- a/drivers/watchdog/itco.c
+++ b/drivers/watchdog/itco.c
@@ -17,8 +17,6 @@
#include <efilib.h>
#include <pci/header.h>

-#define SMI_TCO_MASK (1 << 13)
-
#define TCO_RLD_REG 0x00
#define TCO1_CNT_REG 0x08
#define TCO_TMR_HLT_MASK (1 << 11)
@@ -46,7 +44,6 @@ typedef struct {
UINT32 pm_base_addr_mask;
UINT32 pmc_base_reg;
UINT32 pmc_reg;
- UINT32 smi_reg;
UINT32 pmc_no_reboot_mask;
UINT32 pmc_base_addr_mask;
} iTCO_regs;
@@ -67,7 +64,6 @@ static iTCO_regs iTCO_version_regs[] = {
{
.pmc_base_reg = 0xf0, /* RCBABASE_REG */
.pmc_reg = 0x3410, /* GCS_REG */
- .smi_reg = 0x30,
.pmc_no_reboot_mask = (1 << 5), /* GCS_NO_REBOOT */
.pmc_base_addr_mask = 0xffffc000, /* RCBABASE_ADDRMASK */
.pm_base_addr_mask = 0x0000ff80,
@@ -76,7 +72,6 @@ static iTCO_regs iTCO_version_regs[] = {
{
.pmc_base_reg = 0x44,
.pmc_reg = 0x08,
- .smi_reg = 0x30,
.pmc_no_reboot_mask = (1 << 4),
.pmc_base_addr_mask = 0xfffffe00,
.pm_base_addr_mask = 0x0000ff80,
@@ -89,7 +84,6 @@ static iTCO_regs iTCO_version_regs[] = {
{
.pmc_base_reg = 0x10,
.pmc_reg = 0x1008,
- .smi_reg = 0x40,
.pm_base = 0x400,
.pmc_no_reboot_mask = (1 << 4),
.pmc_base_addr_mask = 0xfffffe00,
@@ -265,23 +259,6 @@ init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
}
tco_base = pm_base + 0x60;

- /* Enable TCO SMIs */
- status = uefi_call_wrapper(pci_io->Io.Read, 6, pci_io,
- EfiPciIoWidthUint32,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- pm_base + itco->regs->smi_reg, 1, &value);
- if (EFI_ERROR(status)) {
- return status;
- }
- value |= SMI_TCO_MASK;
- status = uefi_call_wrapper(pci_io->Io.Write, 6, pci_io,
- EfiPciIoWidthUint32,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- pm_base + itco->regs->smi_reg, 1, &value);
- if (EFI_ERROR(status)) {
- return status;
- }
-
/* Set timer value */
status = uefi_call_wrapper(pci_io->Io.Read, 6, pci_io,
EfiPciIoWidthUint16,
--
2.26.2

Jan Kiszka

unread,
Jan 12, 2021, 7:10:15 AM1/12/21
to efibootg...@googlegroups.com
From: Jan Kiszka <jan.k...@siemens.com>

V6 comes with a different, simpler no-reboot flag setting.

Use hard-coded TCOBASE for these chips as well. This may be reworked in
the future in order to be closer to Linux and to be more generic.

Signed-off-by: Jan Kiszka <jan.k...@siemens.com>
---
drivers/watchdog/itco.c | 46 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/itco.c b/drivers/watchdog/itco.c
index 806b17a..1fdeb0f 100644
--- a/drivers/watchdog/itco.c
+++ b/drivers/watchdog/itco.c
@@ -18,6 +18,7 @@
#include <pci/header.h>

#define TCO_RLD_REG 0x00
+#define TCO1_CNT_NO_REBOOT (1 << 0)
#define TCO1_CNT_REG 0x08
#define TCO_TMR_HLT_MASK (1 << 11)
#define TCO_TMR_REG 0x12
@@ -29,6 +30,7 @@ enum iTCO_chipsets {
ITCO_INTEL_ICH9,
ITCO_INTEL_LPC_LP,
ITCO_INTEL_WBG,
+ ITCO_INTEL_EHL,
};

enum iTCO_versions {
@@ -37,6 +39,7 @@ enum iTCO_versions {
ITCO_V3,
ITCO_V4,
ITCO_V5,
+ ITCO_V6,
};

typedef struct {
@@ -88,6 +91,10 @@ static iTCO_regs iTCO_version_regs[] = {
.pmc_no_reboot_mask = (1 << 4),
.pmc_base_addr_mask = 0xfffffe00,
},
+ [ITCO_V6] =
+ {
+ .tco_base = 0x400,
+ },
};

static iTCO_info iTCO_chipset_info[] = {
@@ -133,6 +140,13 @@ static iTCO_info iTCO_chipset_info[] = {
.regs = &iTCO_version_regs[ITCO_V2],
.itco_version = ITCO_V2,
},
+ [ITCO_INTEL_EHL] =
+ {
+ .name = L"Elkhart Lake",
+ .pci_id = 0x4b23,
+ .regs = &iTCO_version_regs[ITCO_V6],
+ .itco_version = ITCO_V6,
+ },
};

static BOOLEAN itco_supported(UINT16 pci_device_id, UINT8 *index)
@@ -170,7 +184,32 @@ static UINT32 get_tco_base(EFI_PCI_IO *pci_io, iTCO_info *itco)
return (pm_base & itco->regs->pm_base_addr_mask) + 0x60;
}

-static EFI_STATUS update_no_reboot_flag(EFI_PCI_IO *pci_io, iTCO_info *itco)
+static EFI_STATUS update_no_reboot_flag_cnt(EFI_PCI_IO *pci_io,
+ UINT32 tco_base)
+{
+ EFI_STATUS status;
+ UINT32 value;
+
+ status = uefi_call_wrapper(pci_io->Io.Read, 6, pci_io,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ tco_base + TCO1_CNT_REG, 1, &value);
+ if (EFI_ERROR(status)) {
+ return status;
+ }
+ value &= ~TCO1_CNT_NO_REBOOT;
+ status = uefi_call_wrapper(pci_io->Io.Write, 6, pci_io,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ tco_base + TCO1_CNT_REG, 1, &value);
+ if (EFI_ERROR(status)) {
+ return status;
+ }
+ return status;
+}
+
+static EFI_STATUS update_no_reboot_flag_mem(EFI_PCI_IO *pci_io,
+ iTCO_info *itco)
{
EFI_STATUS status;
UINT32 pmc_base, value;
@@ -288,12 +327,15 @@ init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,

/* Clear NO_REBOOT flag */
switch (itco->itco_version) {
+ case ITCO_V6:
+ status = update_no_reboot_flag_cnt(pci_io, tco_base);
+ break;
case ITCO_V5:
status = update_no_reboot_flag_apl(pci_io, itco);
break;
case ITCO_V3:
case ITCO_V2:
- status = update_no_reboot_flag(pci_io, itco);
+ status = update_no_reboot_flag_mem(pci_io, itco);
break;
}
if (EFI_ERROR(status)) {
--
2.26.2

Jan Kiszka

unread,
Jan 12, 2021, 7:10:15 AM1/12/21
to efibootg...@googlegroups.com
From: Jan Kiszka <jan.k...@siemens.com>

Now that SMI control is gone, we no longer need PM base. Store TCOBASE
directly where we would like to do that. And also drop the pointless
application of a mask on that known value.

Signed-off-by: Jan Kiszka <jan.k...@siemens.com>
---
drivers/watchdog/itco.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/watchdog/itco.c b/drivers/watchdog/itco.c
index 1c393e2..806b17a 100644
--- a/drivers/watchdog/itco.c
+++ b/drivers/watchdog/itco.c
@@ -40,7 +40,7 @@ enum iTCO_versions {
};

typedef struct {
- UINT32 pm_base;
+ UINT32 tco_base;
UINT32 pm_base_addr_mask;
UINT32 pmc_base_reg;
UINT32 pmc_reg;
@@ -84,10 +84,9 @@ static iTCO_regs iTCO_version_regs[] = {
{
.pmc_base_reg = 0x10,
.pmc_reg = 0x1008,
- .pm_base = 0x400,
+ .tco_base = 0x460,
.pmc_no_reboot_mask = (1 << 4),
.pmc_base_addr_mask = 0xfffffe00,
- .pm_base_addr_mask = 0x0000ff80,
},
};

@@ -153,13 +152,13 @@ static UINTN get_timeout_value(UINT32 iTCO_version, UINTN seconds){
return iTCO_version == ITCO_V3 ? seconds : ((seconds * 10 ) / 6);
}

-static UINT32 get_pm_base(EFI_PCI_IO *pci_io, iTCO_info *itco)
+static UINT32 get_tco_base(EFI_PCI_IO *pci_io, iTCO_info *itco)
{
UINT32 pm_base;
EFI_STATUS status;

- if (itco->regs->pm_base) {
- return itco->regs->pm_base & itco->regs->pm_base_addr_mask;
+ if (itco->regs->tco_base) {
+ return itco->regs->tco_base;
}

status = uefi_call_wrapper(pci_io->Pci.Read, 5, pci_io,
@@ -168,7 +167,7 @@ static UINT32 get_pm_base(EFI_PCI_IO *pci_io, iTCO_info *itco)
Print(L"Error reading PM_BASE: %r\n", status);
return 0;
}
- return pm_base & itco->regs->pm_base_addr_mask;
+ return (pm_base & itco->regs->pm_base_addr_mask) + 0x60;
}

static EFI_STATUS update_no_reboot_flag(EFI_PCI_IO *pci_io, iTCO_info *itco)
@@ -242,7 +241,7 @@ init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
{
UINT8 itco_chip;
iTCO_info *itco;
- UINT32 pm_base, tco_base, value;
+ UINT32 tco_base, value;
EFI_STATUS status;

if (!pci_io || pci_vendor_id != PCI_VENDOR_ID_INTEL ||
@@ -253,11 +252,11 @@ init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,

Print(L"Detected Intel TCO %s watchdog\n", itco->name);

- /* Get PMBASE and TCOBASE */
- if ((pm_base = get_pm_base(pci_io, itco)) == 0) {
+ /* Get TCOBASE */
+ tco_base = get_tco_base(pci_io, itco);
+ if (!tco_base) {
return EFI_UNSUPPORTED;
}
- tco_base = pm_base + 0x60;

/* Set timer value */
status = uefi_call_wrapper(pci_io->Io.Read, 6, pci_io,
--
2.26.2

Reply all
Reply to author
Forward
0 new messages