Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/watchdog/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  sl28cpld_wdt.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * sl28cpld watchdog driver
 *
 * Copyright 2020 Kontron Europe GmbH
 */


#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/watchdog.h>

/*
 * Watchdog timer block registers.
 */

#define WDT_CTRL   0x00
#define  WDT_CTRL_EN   BIT(0)
#define  WDT_CTRL_LOCK   BIT(2)
#define  WDT_CTRL_ASSERT_SYS_RESET BIT(6)
#define  WDT_CTRL_ASSERT_WDT_TIMEOUT BIT(7)
#define WDT_TIMEOUT   0x01
#define WDT_KICK   0x02
#define  WDT_KICK_VALUE   0x6b
#define WDT_COUNT   0x03

#define WDT_DEFAULT_TIMEOUT  10

static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
    __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

static int timeout;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds");

struct sl28cpld_wdt {
 struct watchdog_device wdd;
 struct regmap *regmap;
 u32 offset;
 bool assert_wdt_timeout;
};

static int sl28cpld_wdt_ping(struct watchdog_device *wdd)
{
 struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd);

 return regmap_write(wdt->regmap, wdt->offset + WDT_KICK,
       WDT_KICK_VALUE);
}

static int sl28cpld_wdt_start(struct watchdog_device *wdd)
{
 struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd);
 unsigned int val;

 val = WDT_CTRL_EN | WDT_CTRL_ASSERT_SYS_RESET;
 if (wdt->assert_wdt_timeout)
  val |= WDT_CTRL_ASSERT_WDT_TIMEOUT;
 if (nowayout)
  val |= WDT_CTRL_LOCK;

 return regmap_update_bits(wdt->regmap, wdt->offset + WDT_CTRL,
      val, val);
}

static int sl28cpld_wdt_stop(struct watchdog_device *wdd)
{
 struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd);

 return regmap_update_bits(wdt->regmap, wdt->offset + WDT_CTRL,
      WDT_CTRL_EN, 0);
}

static unsigned int sl28cpld_wdt_get_timeleft(struct watchdog_device *wdd)
{
 struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd);
 unsigned int val;
 int ret;

 ret = regmap_read(wdt->regmap, wdt->offset + WDT_COUNT, &val);
 if (ret)
  return 0;

 return val;
}

static int sl28cpld_wdt_set_timeout(struct watchdog_device *wdd,
        unsigned int timeout)
{
 struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd);
 int ret;

 ret = regmap_write(wdt->regmap, wdt->offset + WDT_TIMEOUT, timeout);
 if (ret)
  return ret;

 wdd->timeout = timeout;

 return 0;
}

static const struct watchdog_info sl28cpld_wdt_info = {
 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 .identity = "sl28cpld watchdog",
};

static const struct watchdog_ops sl28cpld_wdt_ops = {
 .owner = THIS_MODULE,
 .start = sl28cpld_wdt_start,
 .stop = sl28cpld_wdt_stop,
 .ping = sl28cpld_wdt_ping,
 .set_timeout = sl28cpld_wdt_set_timeout,
 .get_timeleft = sl28cpld_wdt_get_timeleft,
};

static int sl28cpld_wdt_probe(struct platform_device *pdev)
{
 struct watchdog_device *wdd;
 struct sl28cpld_wdt *wdt;
 unsigned int status;
 unsigned int val;
 int ret;

 if (!pdev->dev.parent)
  return -ENODEV;

 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
 if (!wdt)
  return -ENOMEM;

 wdt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
 if (!wdt->regmap)
  return -ENODEV;

 ret = device_property_read_u32(&pdev->dev, "reg", &wdt->offset);
 if (ret)
  return -EINVAL;

 wdt->assert_wdt_timeout = device_property_read_bool(&pdev->dev,
           "kontron,assert-wdt-timeout-pin");

 /* initialize struct watchdog_device */
 wdd = &wdt->wdd;
 wdd->parent = &pdev->dev;
 wdd->info = &sl28cpld_wdt_info;
 wdd->ops = &sl28cpld_wdt_ops;
 wdd->min_timeout = 1;
 wdd->max_timeout = 255;

 watchdog_set_drvdata(wdd, wdt);
 watchdog_stop_on_reboot(wdd);

 /*
 * Read the status early, in case of an error, we haven't modified the
 * hardware.
 */

 ret = regmap_read(wdt->regmap, wdt->offset + WDT_CTRL, &status);
 if (ret)
  return ret;

 /*
 * Initial timeout value, may be overwritten by device tree or module
 * parameter in watchdog_init_timeout().
 *
 * Reading a zero here means that either the hardware has a default
 * value of zero (which is very unlikely and definitely a hardware
 * bug) or the bootloader set it to zero. In any case, we handle
 * this case gracefully and set out own timeout.
 */

 ret = regmap_read(wdt->regmap, wdt->offset + WDT_TIMEOUT, &val);
 if (ret)
  return ret;

 if (val)
  wdd->timeout = val;
 else
  wdd->timeout = WDT_DEFAULT_TIMEOUT;

 watchdog_init_timeout(wdd, timeout, &pdev->dev);
 sl28cpld_wdt_set_timeout(wdd, wdd->timeout);

 /* if the watchdog is locked, we set nowayout */
 if (status & WDT_CTRL_LOCK)
  nowayout = true;
 watchdog_set_nowayout(wdd, nowayout);

 /*
 * If watchdog is already running, keep it enabled, but make
 * sure its mode is set correctly.
 */

 if (status & WDT_CTRL_EN) {
  sl28cpld_wdt_start(wdd);
  set_bit(WDOG_HW_RUNNING, &wdd->status);
 }

 ret = devm_watchdog_register_device(&pdev->dev, wdd);
 if (ret < 0)
  return ret;

 dev_info(&pdev->dev, "initial timeout %d sec%s\n",
   wdd->timeout, nowayout ? ", nowayout" : "");

 return 0;
}

static const struct of_device_id sl28cpld_wdt_of_match[] = {
 { .compatible = "kontron,sl28cpld-wdt" },
 {}
};
MODULE_DEVICE_TABLE(of, sl28cpld_wdt_of_match);

static struct platform_driver sl28cpld_wdt_driver = {
 .probe = sl28cpld_wdt_probe,
 .driver = {
  .name = "sl28cpld-wdt",
  .of_match_table = sl28cpld_wdt_of_match,
 },
};
module_platform_driver(sl28cpld_wdt_driver);

MODULE_DESCRIPTION("sl28cpld Watchdog Driver");
MODULE_AUTHOR("Michael Walle ");
MODULE_LICENSE("GPL");

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.