drivers/watchdog/omap_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/omap_wdt.c
Extension
.c
Size
9710 bytes
Lines
376
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 omap_wdt_dev {
	struct watchdog_device wdog;
	void __iomem    *base;          /* physical */
	struct device   *dev;
	bool		omap_wdt_users;
	int		wdt_trgr_pattern;
	struct mutex	lock;		/* to avoid races with PM */
};

static void omap_wdt_reload(struct omap_wdt_dev *wdev)
{
	void __iomem    *base = wdev->base;

	/* wait for posted write to complete */
	while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x08)
		cpu_relax();

	wdev->wdt_trgr_pattern = ~wdev->wdt_trgr_pattern;
	writel_relaxed(wdev->wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR));

	/* wait for posted write to complete */
	while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x08)
		cpu_relax();
	/* reloaded WCRR from WLDR */
}

static void omap_wdt_enable(struct omap_wdt_dev *wdev)
{
	void __iomem *base = wdev->base;

	/* Sequence to enable the watchdog */
	writel_relaxed(0xBBBB, base + OMAP_WATCHDOG_SPR);
	while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x10)
		cpu_relax();

	writel_relaxed(0x4444, base + OMAP_WATCHDOG_SPR);
	while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x10)
		cpu_relax();
}

static void omap_wdt_disable(struct omap_wdt_dev *wdev)
{
	void __iomem *base = wdev->base;

	/* sequence required to disable watchdog */
	writel_relaxed(0xAAAA, base + OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
	while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x10)
		cpu_relax();

	writel_relaxed(0x5555, base + OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
	while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x10)
		cpu_relax();
}

static void omap_wdt_set_timer(struct omap_wdt_dev *wdev,
				   unsigned int timeout)
{
	u32 pre_margin = GET_WLDR_VAL(timeout);
	void __iomem *base = wdev->base;

	/* just count up at 32 KHz */
	while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x04)
		cpu_relax();

	writel_relaxed(pre_margin, base + OMAP_WATCHDOG_LDR);
	while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x04)
		cpu_relax();
}

static int omap_wdt_start(struct watchdog_device *wdog)
{
	struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
	void __iomem *base = wdev->base;

	mutex_lock(&wdev->lock);

	wdev->omap_wdt_users = true;

	pm_runtime_get_sync(wdev->dev);

	/*
	 * Make sure the watchdog is disabled. This is unfortunately required
	 * because writing to various registers with the watchdog running has no
	 * effect.
	 */
	omap_wdt_disable(wdev);

	/* initialize prescaler */
	while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01)
		cpu_relax();

Annotation

Implementation Notes