From bedbef8ad3e75a304af6361af235302bcc61d06b Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 14 May 2024 06:39:01 +0000 Subject: [PATCH] 修改内核路径 --- kernel/drivers/watchdog/renesas_wdt.c | 74 +++++++++++++++++++++--------------- 1 files changed, 43 insertions(+), 31 deletions(-) diff --git a/kernel/drivers/watchdog/renesas_wdt.c b/kernel/drivers/watchdog/renesas_wdt.c index 62d9d3e..47fce4d 100644 --- a/kernel/drivers/watchdog/renesas_wdt.c +++ b/kernel/drivers/watchdog/renesas_wdt.c @@ -1,15 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Watchdog driver for Renesas WDT watchdog * * Copyright (C) 2015-17 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> * Copyright (C) 2015-17 Renesas Electronics Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. */ #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> @@ -51,7 +49,6 @@ void __iomem *base; struct watchdog_device wdev; unsigned long clk_rate; - u16 time_left; u8 cks; }; @@ -74,6 +71,15 @@ return 0; } +static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles) +{ + unsigned int delay; + + delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate); + + usleep_range(delay, 2 * delay); +} + static int rwdt_start(struct watchdog_device *wdev) { struct rwdt_priv *priv = watchdog_get_drvdata(wdev); @@ -84,6 +90,8 @@ /* Stop the timer before we modify any register */ val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME; rwdt_write(priv, val, RWTCSRA); + /* Delay 2 cycles before setting watchdog counter */ + rwdt_wait_cycles(priv, 2); rwdt_init_timeout(wdev); rwdt_write(priv, priv->cks, RWTCSRA); @@ -102,6 +110,8 @@ struct rwdt_priv *priv = watchdog_get_drvdata(wdev); rwdt_write(priv, priv->cks, RWTCSRA); + /* Delay 3 cycles before disabling module clock */ + rwdt_wait_cycles(priv, 3); pm_runtime_put(wdev->parent); return 0; @@ -155,7 +165,6 @@ .data = (void *)1, /* needs single CPU */ }, { .soc_id = "r8a7792", - .revision = "*", .data = (void *)0, /* needs SMP disabled */ }, { /* sentinel */ } @@ -180,34 +189,34 @@ static int rwdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rwdt_priv *priv; - struct resource *res; struct clk *clk; unsigned long clks_per_sec; int ret, i; + u8 csra; - if (rwdt_blacklisted(&pdev->dev)) + if (rwdt_blacklisted(dev)) return -ENODEV; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); priv->clk_rate = clk_get_rate(clk); - priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) & - RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0; - pm_runtime_put(&pdev->dev); + csra = readb_relaxed(priv->base + RWTCSRA); + priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0; + pm_runtime_put(dev); if (!priv->clk_rate) { ret = -ENOENT; @@ -223,14 +232,14 @@ } if (i < 0) { - dev_err(&pdev->dev, "Can't find suitable clock divider\n"); + dev_err(dev, "Can't find suitable clock divider\n"); ret = -ERANGE; goto out_pm_disable; } - priv->wdev.info = &rwdt_ident, - priv->wdev.ops = &rwdt_ops, - priv->wdev.parent = &pdev->dev; + priv->wdev.info = &rwdt_ident; + priv->wdev.ops = &rwdt_ops; + priv->wdev.parent = dev; priv->wdev.min_timeout = 1; priv->wdev.max_timeout = DIV_BY_CLKS_PER_SEC(priv, 65536); priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT); @@ -242,9 +251,14 @@ watchdog_stop_on_unregister(&priv->wdev); /* This overrides the default timeout only if DT configuration was found */ - ret = watchdog_init_timeout(&priv->wdev, 0, &pdev->dev); - if (ret) - dev_warn(&pdev->dev, "Specified timeout value invalid, using default\n"); + watchdog_init_timeout(&priv->wdev, 0, dev); + + /* Check if FW enabled the watchdog */ + if (csra & RWTCSRA_TME) { + /* Ensure properly initialized dividers */ + rwdt_start(&priv->wdev); + set_bit(WDOG_HW_RUNNING, &priv->wdev.status); + } ret = watchdog_register_device(&priv->wdev); if (ret < 0) @@ -253,7 +267,7 @@ return 0; out_pm_disable: - pm_runtime_disable(&pdev->dev); + pm_runtime_disable(dev); return ret; } @@ -271,10 +285,9 @@ { struct rwdt_priv *priv = dev_get_drvdata(dev); - if (watchdog_active(&priv->wdev)) { - priv->time_left = readw(priv->base + RWTCNT); + if (watchdog_active(&priv->wdev)) rwdt_stop(&priv->wdev); - } + return 0; } @@ -282,10 +295,9 @@ { struct rwdt_priv *priv = dev_get_drvdata(dev); - if (watchdog_active(&priv->wdev)) { + if (watchdog_active(&priv->wdev)) rwdt_start(&priv->wdev); - rwdt_write(priv, priv->time_left, RWTCNT); - } + return 0; } -- Gitblit v1.6.2