drivers/watchdog/asm9260_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/asm9260_wdt.c
Extension
.c
Size
8636 bytes
Lines
377
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 asm9260_wdt_priv {
	struct device		*dev;
	struct watchdog_device	wdd;
	struct clk		*clk;
	struct clk		*clk_ahb;
	struct reset_control	*rst;

	void __iomem		*iobase;
	int			irq;
	unsigned long		wdt_freq;
	enum asm9260_wdt_mode	mode;
};

static int asm9260_wdt_feed(struct watchdog_device *wdd)
{
	struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd);

	iowrite32(0xaa, priv->iobase + HW_WDFEED);
	iowrite32(0x55, priv->iobase + HW_WDFEED);

	return 0;
}

static unsigned int asm9260_wdt_gettimeleft(struct watchdog_device *wdd)
{
	struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd);
	u32 counter;

	counter = ioread32(priv->iobase + HW_WDTV);

	return counter / priv->wdt_freq;
}

static int asm9260_wdt_updatetimeout(struct watchdog_device *wdd)
{
	struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd);
	u32 counter;

	counter = wdd->timeout * priv->wdt_freq;

	iowrite32(counter, priv->iobase + HW_WDTC);

	return 0;
}

static int asm9260_wdt_enable(struct watchdog_device *wdd)
{
	struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd);
	u32 mode = 0;

	if (priv->mode == HW_RESET)
		mode = BM_MOD_WDRESET;

	iowrite32(BM_MOD_WDEN | mode, priv->iobase + HW_WDMOD);

	asm9260_wdt_updatetimeout(wdd);

	asm9260_wdt_feed(wdd);

	return 0;
}

static int asm9260_wdt_disable(struct watchdog_device *wdd)
{
	struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd);

	/* The only way to disable WD is to reset it. */
	reset_control_assert(priv->rst);
	reset_control_deassert(priv->rst);

	return 0;
}

static int asm9260_wdt_settimeout(struct watchdog_device *wdd, unsigned int to)
{
	wdd->timeout = to;
	asm9260_wdt_updatetimeout(wdd);

	return 0;
}

static void asm9260_wdt_sys_reset(struct asm9260_wdt_priv *priv)
{
	/* init WD if it was not started */

	iowrite32(BM_MOD_WDEN | BM_MOD_WDRESET, priv->iobase + HW_WDMOD);

	iowrite32(0xff, priv->iobase + HW_WDTC);
	/* first pass correct sequence */
	asm9260_wdt_feed(&priv->wdd);

Annotation

Implementation Notes