[PATCH v2 2/4] Watchdog: sp5100_tco: Refactor MMIO base address initialization

From: Terry Bowman
Date: Wed Nov 03 2021 - 12:16:07 EST


Move existing MMIO reservation and mapping code into helper functions. The
move locates related MMIO code together.

Also, combine MMIO base address and alternate base address discovery.
Combine based on layout type.

Co-developed-by: Robert Richter <rrichter@xxxxxxx>
Signed-off-by: Robert Richter <rrichter@xxxxxxx>
Signed-off-by: Terry Bowman <terry.bowman@xxxxxxx>
To: linux-watchdog@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Cc: Wim Van Sebroeck <wim@xxxxxxxxxxxxxxxxxx>
Cc: Guenter Roeck <linux@xxxxxxxxxxxx>
Cc: Robert Richter <rrichter@xxxxxxx>
---
drivers/watchdog/sp5100_tco.c | 167 +++++++++++++++++++---------------
1 file changed, 95 insertions(+), 72 deletions(-)

diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index f5e845c3ecea..80ae42ae7aaa 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -215,6 +215,66 @@ static u32 sp5100_tco_read_pm_reg32(u8 index)
return val;
}

+static int __sp5100_tco_prepare_base(struct sp5100_tco *tco,
+ u32 mmio_addr,
+ const char *dev_name)
+{
+ struct device *dev = tco->wdd.parent;
+ int ret = 0;
+
+ if (!mmio_addr)
+ return -ENOMEM;
+
+ if (!devm_request_mem_region(dev, mmio_addr,
+ SP5100_WDT_MEM_MAP_SIZE,
+ dev_name)) {
+ dev_dbg(dev, "MMIO address 0x%08x already in use\n",
+ mmio_addr);
+ return -EBUSY;
+ }
+
+ tco->tcobase = devm_ioremap(dev, mmio_addr,
+ SP5100_WDT_MEM_MAP_SIZE);
+ if (!tco->tcobase) {
+ dev_dbg(dev, "MMIO address 0x%08x failed mapping.\n",
+ mmio_addr);
+ devm_release_mem_region(dev, mmio_addr,
+ SP5100_WDT_MEM_MAP_SIZE);
+ return -ENOMEM;
+ }
+
+ dev_info(dev, "Using 0x%08x for watchdog MMIO address\n",
+ mmio_addr);
+
+ return ret;
+}
+
+static int sp5100_tco_prepare_base(struct sp5100_tco *tco,
+ u32 mmio_addr,
+ u32 alt_mmio_addr,
+ const char *dev_name)
+{
+ struct device *dev = tco->wdd.parent;
+ int ret = 0;
+
+ dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n",
+ mmio_addr);
+
+ /* Check MMIO address conflict */
+ ret = __sp5100_tco_prepare_base(tco, mmio_addr, dev_name);
+
+ /* Check alternate MMIO address conflict */
+ if (ret)
+ ret = __sp5100_tco_prepare_base(tco, alt_mmio_addr,
+ dev_name);
+
+ if (ret)
+ dev_err(dev, "Failed to reserve-map MMIO (%X) and alternate MMIO (%X) regions. ret=%X",
+ mmio_addr, alt_mmio_addr, ret);
+
+ return ret;
+}
+
static int sp5100_tco_timer_init(struct sp5100_tco *tco)
{
struct watchdog_device *wdd = &tco->wdd;
@@ -259,6 +319,7 @@ static int sp5100_tco_setupdevice(struct device *dev,
struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
const char *dev_name;
u32 mmio_addr = 0, val;
+ u32 alt_mmio_addr = 0;
int ret;

/* Request the IO ports used by this driver */
@@ -277,11 +338,35 @@ static int sp5100_tco_setupdevice(struct device *dev,
dev_name = SP5100_DEVNAME;
mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) &
0xfffffff8;
+
+ /*
+ * Secondly, Find the watchdog timer MMIO address
+ * from SBResource_MMIO register.
+ */
+ /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
+ pci_read_config_dword(sp5100_tco_pci,
+ SP5100_SB_RESOURCE_MMIO_BASE,
+ &alt_mmio_addr);
+ if (alt_mmio_addr & ((SB800_ACPI_MMIO_DECODE_EN |
+ SB800_ACPI_MMIO_SEL) !=
+ SB800_ACPI_MMIO_DECODE_EN)) {
+ alt_mmio_addr &= ~0xFFF;
+ alt_mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+ }
break;
case sb800:
dev_name = SB800_DEVNAME;
mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) &
0xfffffff8;
+ /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
+ alt_mmio_addr =
+ sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
+ if (!(alt_mmio_addr & (((SB800_ACPI_MMIO_DECODE_EN |
+ SB800_ACPI_MMIO_SEL)) !=
+ SB800_ACPI_MMIO_DECODE_EN))) {
+ alt_mmio_addr &= ~0xFFF;
+ alt_mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+ }
break;
case efch:
dev_name = SB800_DEVNAME;
@@ -300,84 +385,22 @@ static int sp5100_tco_setupdevice(struct device *dev,
val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
if (val & EFCH_PM_DECODEEN_WDT_TMREN)
mmio_addr = EFCH_PM_WDT_ADDR;
- break;
- default:
- return -ENODEV;
- }

- /* Check MMIO address conflict */
- if (!mmio_addr ||
- !devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
- dev_name)) {
- if (mmio_addr)
- dev_dbg(dev, "MMIO address 0x%08x already in use\n",
- mmio_addr);
- switch (tco->tco_reg_layout) {
- case sp5100:
- /*
- * Secondly, Find the watchdog timer MMIO address
- * from SBResource_MMIO register.
- */
- /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
- pci_read_config_dword(sp5100_tco_pci,
- SP5100_SB_RESOURCE_MMIO_BASE,
- &mmio_addr);
- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
- SB800_ACPI_MMIO_SEL)) !=
- SB800_ACPI_MMIO_DECODE_EN) {
- ret = -ENODEV;
- goto unreg_region;
- }
- mmio_addr &= ~0xFFF;
- mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
- break;
- case sb800:
- /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
- mmio_addr =
- sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
- if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
- SB800_ACPI_MMIO_SEL)) !=
- SB800_ACPI_MMIO_DECODE_EN) {
- ret = -ENODEV;
- goto unreg_region;
- }
- mmio_addr &= ~0xFFF;
- mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
- break;
- case efch:
- val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
- if (!(val & EFCH_PM_ISACONTROL_MMIOEN)) {
- ret = -ENODEV;
- goto unreg_region;
- }
- mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
- EFCH_PM_ACPI_MMIO_WDT_OFFSET;
- break;
- }
- dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n",
- mmio_addr);
- if (!devm_request_mem_region(dev, mmio_addr,
- SP5100_WDT_MEM_MAP_SIZE,
- dev_name)) {
- dev_dbg(dev, "MMIO address 0x%08x already in use\n",
- mmio_addr);
- ret = -EBUSY;
- goto unreg_region;
+ val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
+ if (val & EFCH_PM_ISACONTROL_MMIOEN) {
+ alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
+ EFCH_PM_ACPI_MMIO_WDT_OFFSET;
}
- }

- tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
- if (!tco->tcobase) {
- dev_err(dev, "failed to get tcobase address\n");
- ret = -ENOMEM;
- goto unreg_region;
+ break;
+ default:
+ return -ENODEV;
}

- dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
-
- ret = sp5100_tco_timer_init(tco);
+ ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
+ if (!ret)
+ ret = sp5100_tco_timer_init(tco);

-unreg_region:
release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
return ret;
}
--
2.25.1