drivers/watchdog/at91sam9_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/at91sam9_wdt.c
Extension
.c
Size
10506 bytes
Lines
406
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 at91wdt {
	struct watchdog_device wdd;
	void __iomem *base;
	unsigned long next_heartbeat;	/* the next_heartbeat for the timer */
	struct timer_list timer;	/* The timer that pings the watchdog */
	u32 mr;
	u32 mr_mask;
	unsigned long heartbeat;	/* WDT heartbeat in jiffies */
	bool nowayout;
	unsigned int irq;
	struct clk *sclk;
};

/* ......................................................................... */

static irqreturn_t wdt_interrupt(int irq, void *dev_id)
{
	struct at91wdt *wdt = (struct at91wdt *)dev_id;

	if (wdt_read(wdt, AT91_WDT_SR)) {
		pr_crit("at91sam9 WDT software reset\n");
		emergency_restart();
		pr_crit("Reboot didn't ?????\n");
	}

	return IRQ_HANDLED;
}

/*
 * Reload the watchdog timer.  (ie, pat the watchdog)
 */
static inline void at91_wdt_reset(struct at91wdt *wdt)
{
	wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
}

/*
 * Timer tick
 */
static void at91_ping(struct timer_list *t)
{
	struct at91wdt *wdt = timer_container_of(wdt, t, timer);
	if (time_before(jiffies, wdt->next_heartbeat) ||
	    !watchdog_active(&wdt->wdd)) {
		at91_wdt_reset(wdt);
		mod_timer(&wdt->timer, jiffies + wdt->heartbeat);
	} else {
		pr_crit("I will reset your machine !\n");
	}
}

static int at91_wdt_start(struct watchdog_device *wdd)
{
	struct at91wdt *wdt = to_wdt(wdd);
	/* calculate when the next userspace timeout will be */
	wdt->next_heartbeat = jiffies + wdd->timeout * HZ;
	return 0;
}

static int at91_wdt_stop(struct watchdog_device *wdd)
{
	/* The watchdog timer hardware can not be stopped... */
	return 0;
}

static int at91_wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout)
{
	wdd->timeout = new_timeout;
	return at91_wdt_start(wdd);
}

static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
{
	u32 tmp;
	u32 delta;
	u32 value;
	int err;
	u32 mask = wdt->mr_mask;
	unsigned long min_heartbeat = 1;
	unsigned long max_heartbeat;
	struct device *dev = &pdev->dev;

	tmp = wdt_read(wdt, AT91_WDT_MR);
	if ((tmp & mask) != (wdt->mr & mask)) {
		if (tmp == WDT_MR_RESET) {
			wdt_write(wdt, AT91_WDT_MR, wdt->mr);
			tmp = wdt_read(wdt, AT91_WDT_MR);
		}
	}

Annotation

Implementation Notes