Hi Terry, Sorry for the late review, I hope you did not send an updated series already. On Tue, 18 Jan 2022 14:22:32 -0600, Terry Bowman wrote: > 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. > > (...) > +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; Can this actually happen? If it does, is -ENOMEM really the best error value? And if it can happen, I think I would prefer if you would simply not call this function, knowing it can only fail. In other words, I'd go for something like the following in the function below: /* Check MMIO address conflict */ if (mmio_addr) ret = __sp5100_tco_prepare_base(tco, mmio_addr, dev_name); The intention is clearer and execution is faster too. > + > + 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); Remove trailing dot for consistency with the other messages. > + 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); Format for the addresses is inconsistent with the other messages above, please use 0x%08x for consistency. As for the return value (which should be preceded by a comma rather than a dot), it should be printed as a decimal, not hexadecimal, value. (And nitpicking: I'd split after "dev," so as to not make the line longer than needed. > + > + return ret; > +} > + > static int sp5100_tco_timer_init(struct sp5100_tco *tco) > { > struct watchdog_device *wdd = &tco->wdd; > @@ -264,6 +324,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 */ > @@ -282,11 +343,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))) { The condition is the opposite of the sp5100 case above, which looks quite suspicious. As far as I can see, that wasn't the case in the original code. Please double check. In any case, please avoid double negations, they are too easy to get wrong. > + alt_mmio_addr &= ~0xFFF; > + alt_mmio_addr += SB800_PM_WDT_MMIO_OFFSET; > + } > break; > case efch: > dev_name = SB800_DEVNAME; > @@ -305,87 +390,24 @@ 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; > + > + 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; > break; > default: > return -ENODEV; > } > (...) Rest looks OK to me. -- Jean Delvare SUSE L3 Support