On 14/12/2023 16:04, Elad Nachman wrote: > From: Elad Nachman <enachman@xxxxxxxxxxx> > > Add support for Marvell ac5/x variant of the ARM > sbsa global watchdog. This watchdog deviates from > the standard driver by the following items: > > 1. Registers reside in secure register section. > hence access is only possible via SMC calls to ATF. > > 2. There are couple more registers which reside in > other register areas, which needs to be configured > in order for the watchdog to properly generate > reset through the SOC. > > The new Marvell compatibility string differentiates between > the original sbsa mode of operation and the Marvell mode of > operation. > > Signed-off-by: Elad Nachman <enachman@xxxxxxxxxxx> > --- ... > gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL); > if (!gwdt) > return -ENOMEM; > platform_set_drvdata(pdev, gwdt); > > - cf_base = devm_platform_ioremap_resource(pdev, 0); > - if (IS_ERR(cf_base)) > - return PTR_ERR(cf_base); > - > - rf_base = devm_platform_ioremap_resource(pdev, 1); > - if (IS_ERR(rf_base)) > - return PTR_ERR(rf_base); > + if (of_device_is_compatible(np, "marvell,ac5-wd")) { No, use match data. That's its purpose, don't put comaptibles inside code. > + marvell = true; > + gwdt->soc_reg_ops = &smc_reg_ops; > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (IS_ERR(res)) > + return PTR_ERR(res); > + cf_base = res->start; Why do you use entirely different code? > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (IS_ERR(res)) > + return PTR_ERR(res); > + rf_base = res->start; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); > + if (IS_ERR(res)) > + return PTR_ERR(res); > + cpu_ctrl_base = res->start; > + mng_base = devm_platform_ioremap_resource(pdev, 3); > + if (IS_ERR(mng_base)) > + return PTR_ERR(mng_base); > + rst_ctrl_base = devm_platform_ioremap_resource(pdev, 4); > + if (IS_ERR(rst_ctrl_base)) > + return PTR_ERR(rst_ctrl_base); > + } else { > + gwdt->soc_reg_ops = &direct_reg_ops; > + cf_base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(cf_base)) > + return PTR_ERR(cf_base); Why? This is shared. > + > + rf_base = devm_platform_ioremap_resource(pdev, 1); > + if (IS_ERR(rf_base)) > + return PTR_ERR(rf_base); Ditto > + } > > /* > * Get the frequency of system counter from the cp15 interface of ARM > @@ -299,7 +482,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) > else > wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; > > - status = readl(cf_base + SBSA_GWDT_WCS); > + status = gwdt->soc_reg_ops->reg_read32(cf_base + SBSA_GWDT_WCS); > if (status & SBSA_GWDT_WCS_WS1) { > dev_warn(dev, "System reset by WDT.\n"); > wdd->bootstatus |= WDIOF_CARDRESET; > @@ -317,7 +500,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) > * In case there is a pending ws0 interrupt, just ping > * the watchdog before registering the interrupt routine > */ > - writel(0, rf_base + SBSA_GWDT_WRR); > + gwdt->soc_reg_ops->reg_write32(0, rf_base + SBSA_GWDT_WRR); > if (devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0, > pdev->name, gwdt)) { > action = 0; > @@ -347,7 +530,28 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) > ret = devm_watchdog_register_device(dev, wdd); > if (ret) > return ret; > - > + /* > + * Marvell AC5/X/IM: need to configure the watchdog > + * HW to trigger reset on WS1 (Watchdog Signal 1): > + * > + * 1. Configure the watchdog signal enable (routing) > + * according to configuration > + * 2. Unmask the wd_rst input signal to the reset unit > + */ > + if (marvell) { > + gwdt->soc_reg_ops->reg_write32(reset, cpu_ctrl_base + > + SBSA_GWDT_MARVELL_CPU_WD_RST_EN_REG); > + id = readl(mng_base + SBSA_GWDT_MARVELL_MNG_ID_REG) & > + SBSA_GWDT_MARVELL_ID_MASK; > + > + if (id == SBSA_GWDT_MARVELL_AC5_ID) > + val = SBSA_GWDT_MARVELL_AC5_RST_UNIT_WD_BIT; > + else > + val = SBSA_GWDT_MARVELL_IRONMAN_RST_UNIT_WD_BIT; > + > + writel(readl(rst_ctrl_base + SBSA_GWDT_MARVELL_RST_CTRL_REG) & ~val, > + rst_ctrl_base + SBSA_GWDT_MARVELL_RST_CTRL_REG); > + } > dev_info(dev, "Initialized with %ds timeout @ %u Hz, action=%d.%s\n", > wdd->timeout, gwdt->clk, action, > status & SBSA_GWDT_WCS_EN ? " [enabled]" : ""); > @@ -383,6 +587,7 @@ static const struct dev_pm_ops sbsa_gwdt_pm_ops = { > > static const struct of_device_id sbsa_gwdt_of_match[] = { > { .compatible = "arm,sbsa-gwdt", }, > + { .compatible = "marvell,ac5-wd", }, > {}, > }; > MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match); Best regards, Krzysztof