Skip to content

Commit 1f182ac

Browse files
ktbowmanWim Van Sebroeck
authored andcommitted
Watchdog: sp5100_tco: Refactor MMIO base address initialization
Combine MMIO base address and alternate base address detection. Combine based on layout type. This will simplify the function by eliminating a switch case. Move existing request/release code into functions. This currently only supports port I/O request/release. The move into a separate function will make it ready for adding MMIO region support. Co-developed-by: Robert Richter <rrichter@amd.com> Signed-off-by: Robert Richter <rrichter@amd.com> Signed-off-by: Terry Bowman <terry.bowman@amd.com> Tested-by: Jean Delvare <jdelvare@suse.de> Reviewed-by: Jean Delvare <jdelvare@suse.de> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20220202153525.1693378-3-terry.bowman@amd.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
1 parent abd71a9 commit 1f182ac

2 files changed

Lines changed: 82 additions & 74 deletions

File tree

drivers/watchdog/sp5100_tco.c

Lines changed: 81 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,55 @@ static u32 sp5100_tco_read_pm_reg32(u8 index)
223223
return val;
224224
}
225225

226+
static u32 sp5100_tco_request_region(struct device *dev,
227+
u32 mmio_addr,
228+
const char *dev_name)
229+
{
230+
if (!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
231+
dev_name)) {
232+
dev_dbg(dev, "MMIO address 0x%08x already in use\n", mmio_addr);
233+
return 0;
234+
}
235+
236+
return mmio_addr;
237+
}
238+
239+
static u32 sp5100_tco_prepare_base(struct sp5100_tco *tco,
240+
u32 mmio_addr,
241+
u32 alt_mmio_addr,
242+
const char *dev_name)
243+
{
244+
struct device *dev = tco->wdd.parent;
245+
246+
dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr);
247+
248+
if (!mmio_addr && !alt_mmio_addr)
249+
return -ENODEV;
250+
251+
/* Check for MMIO address and alternate MMIO address conflicts */
252+
if (mmio_addr)
253+
mmio_addr = sp5100_tco_request_region(dev, mmio_addr, dev_name);
254+
255+
if (!mmio_addr && alt_mmio_addr)
256+
mmio_addr = sp5100_tco_request_region(dev, alt_mmio_addr, dev_name);
257+
258+
if (!mmio_addr) {
259+
dev_err(dev, "Failed to reserve MMIO or alternate MMIO region\n");
260+
return -EBUSY;
261+
}
262+
263+
tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
264+
if (!tco->tcobase) {
265+
dev_err(dev, "MMIO address 0x%08x failed mapping\n", mmio_addr);
266+
devm_release_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
267+
return -ENOMEM;
268+
}
269+
270+
dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
271+
272+
return 0;
273+
}
274+
226275
static int sp5100_tco_timer_init(struct sp5100_tco *tco)
227276
{
228277
struct watchdog_device *wdd = &tco->wdd;
@@ -264,6 +313,7 @@ static int sp5100_tco_setupdevice(struct device *dev,
264313
struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
265314
const char *dev_name;
266315
u32 mmio_addr = 0, val;
316+
u32 alt_mmio_addr = 0;
267317
int ret;
268318

269319
/* Request the IO ports used by this driver */
@@ -282,11 +332,32 @@ static int sp5100_tco_setupdevice(struct device *dev,
282332
dev_name = SP5100_DEVNAME;
283333
mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) &
284334
0xfffffff8;
335+
336+
/*
337+
* Secondly, find the watchdog timer MMIO address
338+
* from SBResource_MMIO register.
339+
*/
340+
341+
/* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
342+
pci_read_config_dword(sp5100_tco_pci,
343+
SP5100_SB_RESOURCE_MMIO_BASE,
344+
&val);
345+
346+
/* Verify MMIO is enabled and using bar0 */
347+
if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
348+
alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
285349
break;
286350
case sb800:
287351
dev_name = SB800_DEVNAME;
288352
mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) &
289353
0xfffffff8;
354+
355+
/* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
356+
val = sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
357+
358+
/* Verify MMIO is enabled and using bar0 */
359+
if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
360+
alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
290361
break;
291362
case efch:
292363
dev_name = SB800_DEVNAME;
@@ -305,87 +376,23 @@ static int sp5100_tco_setupdevice(struct device *dev,
305376
val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
306377
if (val & EFCH_PM_DECODEEN_WDT_TMREN)
307378
mmio_addr = EFCH_PM_WDT_ADDR;
379+
380+
val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
381+
if (val & EFCH_PM_ISACONTROL_MMIOEN)
382+
alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
383+
EFCH_PM_ACPI_MMIO_WDT_OFFSET;
308384
break;
309385
default:
310386
return -ENODEV;
311387
}
312388

313-
/* Check MMIO address conflict */
314-
if (!mmio_addr ||
315-
!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
316-
dev_name)) {
317-
if (mmio_addr)
318-
dev_dbg(dev, "MMIO address 0x%08x already in use\n",
319-
mmio_addr);
320-
switch (tco->tco_reg_layout) {
321-
case sp5100:
322-
/*
323-
* Secondly, Find the watchdog timer MMIO address
324-
* from SBResource_MMIO register.
325-
*/
326-
/* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
327-
pci_read_config_dword(sp5100_tco_pci,
328-
SP5100_SB_RESOURCE_MMIO_BASE,
329-
&mmio_addr);
330-
if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
331-
SB800_ACPI_MMIO_SEL)) !=
332-
SB800_ACPI_MMIO_DECODE_EN) {
333-
ret = -ENODEV;
334-
goto unreg_region;
335-
}
336-
mmio_addr &= ~0xFFF;
337-
mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
338-
break;
339-
case sb800:
340-
/* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
341-
mmio_addr =
342-
sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
343-
if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
344-
SB800_ACPI_MMIO_SEL)) !=
345-
SB800_ACPI_MMIO_DECODE_EN) {
346-
ret = -ENODEV;
347-
goto unreg_region;
348-
}
349-
mmio_addr &= ~0xFFF;
350-
mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
351-
break;
352-
case efch:
353-
val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
354-
if (!(val & EFCH_PM_ISACONTROL_MMIOEN)) {
355-
ret = -ENODEV;
356-
goto unreg_region;
357-
}
358-
mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
359-
EFCH_PM_ACPI_MMIO_WDT_OFFSET;
360-
break;
361-
}
362-
dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n",
363-
mmio_addr);
364-
if (!devm_request_mem_region(dev, mmio_addr,
365-
SP5100_WDT_MEM_MAP_SIZE,
366-
dev_name)) {
367-
dev_dbg(dev, "MMIO address 0x%08x already in use\n",
368-
mmio_addr);
369-
ret = -EBUSY;
370-
goto unreg_region;
371-
}
372-
}
373-
374-
tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
375-
if (!tco->tcobase) {
376-
dev_err(dev, "failed to get tcobase address\n");
377-
ret = -ENOMEM;
378-
goto unreg_region;
389+
ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
390+
if (!ret) {
391+
/* Setup the watchdog timer */
392+
tco_timer_enable(tco);
393+
ret = sp5100_tco_timer_init(tco);
379394
}
380395

381-
dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
382-
383-
/* Setup the watchdog timer */
384-
tco_timer_enable(tco);
385-
386-
ret = sp5100_tco_timer_init(tco);
387-
388-
unreg_region:
389396
release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
390397
return ret;
391398
}

drivers/watchdog/sp5100_tco.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#define SB800_PM_WATCHDOG_SECOND_RES GENMASK(1, 0)
5959
#define SB800_ACPI_MMIO_DECODE_EN BIT(0)
6060
#define SB800_ACPI_MMIO_SEL BIT(1)
61+
#define SB800_ACPI_MMIO_MASK GENMASK(1, 0)
6162

6263
#define SB800_PM_WDT_MMIO_OFFSET 0xB00
6364

0 commit comments

Comments
 (0)