drivers/watchdog/visconti_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/visconti_wdt.c
Extension
.c
Size
4681 bytes
Lines
178
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 visconti_wdt_priv {
	struct watchdog_device wdev;
	void __iomem *base;
	u32 div;
};

static int visconti_wdt_start(struct watchdog_device *wdev)
{
	struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev);
	u32 timeout = wdev->timeout * VISCONTI_WDT_FREQ;

	writel(priv->div, priv->base + WDT_DIV);
	writel(0, priv->base + WDT_MIN);
	writel(timeout, priv->base + WDT_MAX);
	writel(0, priv->base + WDT_CTL);
	writel(WDT_CMD_START_STOP, priv->base + WDT_CMD);

	return 0;
}

static int visconti_wdt_stop(struct watchdog_device *wdev)
{
	struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev);

	writel(1, priv->base + WDT_CTL);
	writel(WDT_CMD_START_STOP, priv->base + WDT_CMD);

	return 0;
}

static int visconti_wdt_ping(struct watchdog_device *wdd)
{
	struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdd);

	writel(WDT_CMD_CLEAR, priv->base + WDT_CMD);

	return 0;
}

static unsigned int visconti_wdt_get_timeleft(struct watchdog_device *wdev)
{
	struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev);
	u32 timeout = wdev->timeout * VISCONTI_WDT_FREQ;
	u32 cnt = readl(priv->base + WDT_CNT);

	if (timeout <= cnt)
		return 0;
	timeout -= cnt;

	return timeout / VISCONTI_WDT_FREQ;
}

static int visconti_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
{
	u32 val;
	struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev);

	wdev->timeout = timeout;
	val = wdev->timeout * VISCONTI_WDT_FREQ;

	/* Clear counter before setting timeout because WDT expires */
	writel(WDT_CMD_CLEAR, priv->base + WDT_CMD);
	writel(val, priv->base + WDT_MAX);

	return 0;
}

static const struct watchdog_info visconti_wdt_info = {
	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
	.identity = "Visconti Watchdog",
};

static const struct watchdog_ops visconti_wdt_ops = {
	.owner		= THIS_MODULE,
	.start		= visconti_wdt_start,
	.stop		= visconti_wdt_stop,
	.ping		= visconti_wdt_ping,
	.get_timeleft	= visconti_wdt_get_timeleft,
	.set_timeout	= visconti_wdt_set_timeout,
};

static int visconti_wdt_probe(struct platform_device *pdev)
{
	struct watchdog_device *wdev;
	struct visconti_wdt_priv *priv;
	struct device *dev = &pdev->dev;
	struct clk *clk;
	unsigned long clk_freq;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

Annotation

Implementation Notes