drivers/watchdog/da9063_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/da9063_wdt.c
Extension
.c
Size
8074 bytes
Lines
310
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

// SPDX-License-Identifier: GPL-2.0+
/*
 * Watchdog driver for DA9063 PMICs.
 *
 * Copyright(c) 2012 Dialog Semiconductor Ltd.
 *
 * Author: Mariusz Wojtasik <mariusz.wojtasik@diasemi.com>
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/watchdog.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9063/core.h>
#include <linux/property.h>
#include <linux/regmap.h>

/*
 * Watchdog selector to timeout in seconds.
 *   0: WDT disabled;
 *   others: timeout = 2048 ms * 2^(TWDSCALE-1).
 */
static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };

#define DA9063_TWDSCALE_DISABLE		0
#define DA9063_TWDSCALE_MIN		1
#define DA9063_TWDSCALE_MAX		(ARRAY_SIZE(wdt_timeout) - 1)
#define DA9063_WDT_MIN_TIMEOUT		wdt_timeout[DA9063_TWDSCALE_MIN]
#define DA9063_WDT_MAX_TIMEOUT		wdt_timeout[DA9063_TWDSCALE_MAX]
#define DA9063_WDG_TIMEOUT		wdt_timeout[3]
#define DA9063_RESET_PROTECTION_MS	256

static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
{
	unsigned int i;

	for (i = DA9063_TWDSCALE_MIN; i <= DA9063_TWDSCALE_MAX; i++) {
		if (wdt_timeout[i] >= secs)
			return i;
	}

	return DA9063_TWDSCALE_MAX;
}

/*
 * Read the currently active timeout.
 * Zero means the watchdog is disabled.
 */
static unsigned int da9063_wdt_read_timeout(struct da9063 *da9063)
{
	unsigned int val;

	regmap_read(da9063->regmap, DA9063_REG_CONTROL_D, &val);

	return wdt_timeout[val & DA9063_TWDSCALE_MASK];
}

static int da9063_wdt_disable_timer(struct da9063 *da9063)
{
	return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
				  DA9063_TWDSCALE_MASK,
				  DA9063_TWDSCALE_DISABLE);
}

static int
da9063_wdt_update_timeout(struct da9063 *da9063, unsigned int timeout)
{
	unsigned int regval;
	int ret;

	/*
	 * The watchdog triggers a reboot if a timeout value is already
	 * programmed because the timeout value combines two functions
	 * in one: indicating the counter limit and starting the watchdog.
	 * The watchdog must be disabled to be able to change the timeout
	 * value if the watchdog is already running. Then we can set the
	 * new timeout value which enables the watchdog again.
	 */
	ret = da9063_wdt_disable_timer(da9063);
	if (ret)
		return ret;

	usleep_range(150, 300);
	regval = da9063_wdt_timeout_to_sel(timeout);

Annotation

Implementation Notes