drivers/watchdog/rza_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/rza_wdt.c
Extension
.c
Size
6023 bytes
Lines
243
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 rza_wdt {
	struct watchdog_device wdev;
	void __iomem *base;
	struct clk *clk;
	u8 count;
	u8 cks;
};

static void rza_wdt_calc_timeout(struct rza_wdt *priv, int timeout)
{
	unsigned long rate = clk_get_rate(priv->clk);
	unsigned int ticks;

	if (priv->cks == CKS_4BIT) {
		ticks = DIV_ROUND_UP(timeout * rate, DIVIDER_4BIT);

		/*
		 * Since max_timeout was set in probe, we know that the timeout
		 * value passed will never calculate to a tick value greater
		 * than 256.
		 */
		priv->count = 256 - ticks;

	} else {
		/* Start timer with longest timeout */
		priv->count = 0;
	}

	pr_debug("%s: timeout set to %u (WTCNT=%d)\n", __func__,
		 timeout, priv->count);
}

static int rza_wdt_start(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	/* Stop timer */
	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	/* Must dummy read WRCSR:WOVF at least once before clearing */
	readb(priv->base + WRCSR);
	writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR);

	rza_wdt_calc_timeout(priv, wdev->timeout);

	writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR);
	writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);
	writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME |
	       WTSCR_CKS(priv->cks), priv->base + WTCSR);

	return 0;
}

static int rza_wdt_stop(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	return 0;
}

static int rza_wdt_ping(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);

	pr_debug("%s: timeout = %u\n", __func__, wdev->timeout);

	return 0;
}

static int rza_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
{
	wdev->timeout = timeout;
	rza_wdt_start(wdev);
	return 0;
}

static int rza_wdt_restart(struct watchdog_device *wdev, unsigned long action,
			    void *data)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	/* Stop timer */
	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	/* Must dummy read WRCSR:WOVF at least once before clearing */
	readb(priv->base + WRCSR);

Annotation

Implementation Notes