drivers/platform/cznic/turris-omnia-mcu-watchdog.c

Source file repositories/reference/linux-study-clean/drivers/platform/cznic/turris-omnia-mcu-watchdog.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/cznic/turris-omnia-mcu-watchdog.c
Extension
.c
Size
3309 bytes
Lines
131
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * CZ.NIC's Turris Omnia MCU watchdog driver
 *
 * 2024 by Marek BehĂșn <kabel@kernel.org>
 */

#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/units.h>
#include <linux/watchdog.h>

#include <linux/turris-omnia-mcu-interface.h>
#include "turris-omnia-mcu.h"

#define WATCHDOG_TIMEOUT		120

static unsigned int timeout;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");

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 omnia_wdt_start(struct watchdog_device *wdt)
{
	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);

	return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1);
}

static int omnia_wdt_stop(struct watchdog_device *wdt)
{
	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);

	return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 0);
}

static int omnia_wdt_ping(struct watchdog_device *wdt)
{
	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);

	return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1);
}

static int omnia_wdt_set_timeout(struct watchdog_device *wdt,
				 unsigned int timeout)
{
	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);

	return omnia_cmd_write_u16(mcu->client, OMNIA_CMD_SET_WDT_TIMEOUT,
				   timeout * DECI);
}

static unsigned int omnia_wdt_get_timeleft(struct watchdog_device *wdt)
{
	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
	u16 timeleft;
	int err;

	err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_WDT_TIMELEFT,
				 &timeleft);
	if (err) {
		dev_err(&mcu->client->dev, "Cannot get watchdog timeleft: %d\n",
			err);
		return 0;
	}

	return timeleft / DECI;
}

static const struct watchdog_info omnia_wdt_info = {
	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
	.identity = "Turris Omnia MCU Watchdog",
};

static const struct watchdog_ops omnia_wdt_ops = {
	.owner		= THIS_MODULE,
	.start		= omnia_wdt_start,
	.stop		= omnia_wdt_stop,
	.ping		= omnia_wdt_ping,
	.set_timeout	= omnia_wdt_set_timeout,
	.get_timeleft	= omnia_wdt_get_timeleft,
};

Annotation

Implementation Notes