drivers/watchdog/apple_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/apple_wdt.c
Extension
.c
Size
6545 bytes
Lines
240
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 apple_wdt {
	struct watchdog_device wdd;
	void __iomem *regs;
	unsigned long clk_rate;
};

static struct apple_wdt *to_apple_wdt(struct watchdog_device *wdd)
{
	return container_of(wdd, struct apple_wdt, wdd);
}

static int apple_wdt_start(struct watchdog_device *wdd)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);

	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_CUR_TIME);
	writel_relaxed(APPLE_WDT_CTRL_RESET_EN, wdt->regs + APPLE_WDT_WD1_CTRL);

	return 0;
}

static int apple_wdt_stop(struct watchdog_device *wdd)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);

	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_CTRL);

	return 0;
}

static int apple_wdt_ping(struct watchdog_device *wdd)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);

	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_CUR_TIME);

	return 0;
}

static int apple_wdt_set_timeout(struct watchdog_device *wdd, unsigned int s)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);
	u32 actual;

	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_CUR_TIME);

	actual = min(s, wdd->max_hw_heartbeat_ms / 1000);
	writel_relaxed(wdt->clk_rate * actual, wdt->regs + APPLE_WDT_WD1_BITE_TIME);

	wdd->timeout = s;

	return 0;
}

static unsigned int apple_wdt_get_timeleft(struct watchdog_device *wdd)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);
	u32 cur_time, reset_time;

	cur_time = readl_relaxed(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
	reset_time = readl_relaxed(wdt->regs + APPLE_WDT_WD1_BITE_TIME);

	return (reset_time - cur_time) / wdt->clk_rate;
}

static int apple_wdt_restart(struct watchdog_device *wdd, unsigned long mode,
			     void *cmd)
{
	struct apple_wdt *wdt = to_apple_wdt(wdd);

	writel_relaxed(APPLE_WDT_CTRL_RESET_EN, wdt->regs + APPLE_WDT_WD1_CTRL);
	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_BITE_TIME);
	writel_relaxed(0, wdt->regs + APPLE_WDT_WD1_CUR_TIME);

	/*
	 * Flush writes and then wait for the SoC to reset. Even though the
	 * reset is queued almost immediately experiments have shown that it
	 * can take up to ~120-125ms until the SoC is actually reset. Just
	 * wait 150ms here to be safe.
	 */
	(void)readl(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
	mdelay(150);

	return 0;
}

static struct watchdog_ops apple_wdt_ops = {
	.owner = THIS_MODULE,
	.start = apple_wdt_start,
	.stop = apple_wdt_stop,

Annotation

Implementation Notes