drivers/watchdog/retu_wdt.c

Source file repositories/reference/linux-study-clean/drivers/watchdog/retu_wdt.c

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/retu_wdt.c
Extension
.c
Size
4013 bytes
Lines
161
Domain
Driver Families
Bucket
drivers/watchdog
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

struct retu_wdt_dev {
	struct retu_dev		*rdev;
	struct device		*dev;
	struct delayed_work	ping_work;
};

/*
 * Since Retu watchdog cannot be disabled in hardware, we must kick it
 * with a timer until userspace watchdog software takes over. If
 * CONFIG_WATCHDOG_NOWAYOUT is set, we never start the feeding.
 */
static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
{
	retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
	schedule_delayed_work(&wdev->ping_work,
			round_jiffies_relative(RETU_WDT_MAX_TIMER * HZ / 2));
}

static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
{
	retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
	cancel_delayed_work_sync(&wdev->ping_work);
}

static void retu_wdt_ping_work(struct work_struct *work)
{
	struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
						struct retu_wdt_dev, ping_work);
	retu_wdt_ping_enable(wdev);
}

static int retu_wdt_start(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	retu_wdt_ping_disable(wdev);

	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_stop(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	retu_wdt_ping_enable(wdev);

	return 0;
}

static int retu_wdt_ping(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_set_timeout(struct watchdog_device *wdog,
				unsigned int timeout)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	wdog->timeout = timeout;
	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

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

static const struct watchdog_ops retu_wdt_ops = {
	.owner		= THIS_MODULE,
	.start		= retu_wdt_start,
	.stop		= retu_wdt_stop,
	.ping		= retu_wdt_ping,
	.set_timeout	= retu_wdt_set_timeout,
};

static int retu_wdt_probe(struct platform_device *pdev)
{
	struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
	bool nowayout = WATCHDOG_NOWAYOUT;
	struct watchdog_device *retu_wdt;
	struct retu_wdt_dev *wdev;
	int ret;

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

Annotation

Implementation Notes