staticvoid rzg2l_wdt_write(struct rzg2l_wdt_priv *priv, u32 val, unsignedint reg)
{ if (reg == WDTSET)
val &= WDTSET_COUNTER_MASK;
writel_relaxed(val, priv->base + reg); /* Registers other than the WDTINT is always synchronized with WDT_CLK */ if (reg != WDTINT)
rzg2l_wdt_wait_delay(priv);
}
ret = reset_control_assert(priv->rstc); if (ret) return ret;
ret = pm_runtime_put(wdev->parent); if (ret < 0) return ret;
return 0;
}
staticint rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsignedint timeout)
{ int ret = 0;
wdev->timeout = timeout;
/* * If the watchdog is active, reset the module for updating the WDTSET * register by calling rzg2l_wdt_stop() (which internally calls reset_control_reset() * to reset the module) so that it is updated with new timeout values.
*/ if (watchdog_active(wdev)) {
ret = rzg2l_wdt_stop(wdev); if (ret) return ret;
/* * In case of RZ/G3S the watchdog device may be part of an IRQ safe power * domain that is currently powered off. In this case we need to power * it on before accessing registers. Along with this the clocks will be * enabled. We don't undo the pm_runtime_resume_and_get() as the device * need to be on for the reboot to happen. * * For the rest of SoCs not registering a watchdog IRQ safe power * domain it is safe to call pm_runtime_resume_and_get() as the * irq_safe_dev_in_sleep_domain() call in genpd_runtime_resume() * returns non zero value and the genpd_lock() is avoided, thus, there * will be no invalid wait context reported by lockdep.
*/
ret = pm_runtime_resume_and_get(wdev->parent); if (ret) return ret;
if (priv->devtype == WDT_RZG2L) {
ret = reset_control_deassert(priv->rstc); if (ret) return ret;
/* Generate Reset (WDTRSTB) Signal on parity error */
rzg2l_wdt_write(priv, 0, PECR);
/* Force parity error */
rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
} else { /* RZ/V2M doesn't have parity error registers */
ret = reset_control_reset(priv->rstc); if (ret) return ret;
wdev->timeout = 0;
/* Initialize time out */
rzg2l_wdt_init_timeout(wdev);
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base);
/* Get watchdog main clock */
priv->osc_clk = devm_clk_get(&pdev->dev, "oscclk"); if (IS_ERR(priv->osc_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(priv->osc_clk), "no oscclk");
priv->osc_clk_rate = clk_get_rate(priv->osc_clk); if (!priv->osc_clk_rate) return dev_err_probe(&pdev->dev, -EINVAL, "oscclk rate is 0");
/* Get Peripheral clock */
priv->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(priv->pclk)) return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk), "no pclk");
pclk_rate = clk_get_rate(priv->pclk); if (!pclk_rate) return dev_err_probe(&pdev->dev, -EINVAL, "pclk rate is 0");
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(priv->rstc)) return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc), "failed to get cpg reset");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.