drivers/watchdog/dw_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/dw_wdt.c
Extension
.c
Size
19274 bytes
Lines
702
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 dw_wdt_timeout {
	u32 top_val;
	unsigned int sec;
	unsigned int msec;
};

struct dw_wdt {
	void __iomem		*regs;
	struct clk		*clk;
	struct clk		*pclk;
	unsigned long		rate;
	enum dw_wdt_rmod	rmod;
	struct dw_wdt_timeout	timeouts[DW_WDT_NUM_TOPS];
	struct watchdog_device	wdd;
	struct reset_control	*rst;
	/* Save/restore */
	u32			control;
	u32			timeout;

#ifdef CONFIG_DEBUG_FS
	struct dentry		*dbgfs_dir;
#endif
};

#define to_dw_wdt(wdd)	container_of(wdd, struct dw_wdt, wdd)

static inline int dw_wdt_is_enabled(struct dw_wdt *dw_wdt)
{
	return readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET) &
		WDOG_CONTROL_REG_WDT_EN_MASK;
}

static void dw_wdt_update_mode(struct dw_wdt *dw_wdt, enum dw_wdt_rmod rmod)
{
	u32 val;

	val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);
	if (rmod == DW_WDT_RMOD_IRQ)
		val |= WDOG_CONTROL_REG_RESP_MODE_MASK;
	else
		val &= ~WDOG_CONTROL_REG_RESP_MODE_MASK;
	writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);

	dw_wdt->rmod = rmod;
}

static unsigned int dw_wdt_find_best_top(struct dw_wdt *dw_wdt,
					 unsigned int timeout, u32 *top_val)
{
	int idx;

	/*
	 * Find a TOP with timeout greater or equal to the requested number.
	 * Note we'll select a TOP with maximum timeout if the requested
	 * timeout couldn't be reached.
	 */
	for (idx = 0; idx < DW_WDT_NUM_TOPS; ++idx) {
		if (dw_wdt->timeouts[idx].sec >= timeout)
			break;
	}

	if (idx == DW_WDT_NUM_TOPS)
		--idx;

	*top_val = dw_wdt->timeouts[idx].top_val;

	return dw_wdt->timeouts[idx].sec;
}

static unsigned int dw_wdt_get_min_timeout(struct dw_wdt *dw_wdt)
{
	int idx;

	/*
	 * We'll find a timeout greater or equal to one second anyway because
	 * the driver probe would have failed if there was none.
	 */
	for (idx = 0; idx < DW_WDT_NUM_TOPS; ++idx) {
		if (dw_wdt->timeouts[idx].sec)
			break;
	}

	return dw_wdt->timeouts[idx].sec;
}

static unsigned int dw_wdt_get_max_timeout_ms(struct dw_wdt *dw_wdt)
{
	struct dw_wdt_timeout *timeout = &dw_wdt->timeouts[DW_WDT_NUM_TOPS - 1];
	u64 msec;

Annotation

Implementation Notes