drivers/watchdog/sch311x_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/sch311x_wdt.c
Extension
.c
Size
13582 bytes
Lines
541
Domain
Driver Families
Bucket
drivers/watchdog
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations sch311x_wdt_fops = {
	.owner		= THIS_MODULE,
	.write		= sch311x_wdt_write,
	.unlocked_ioctl	= sch311x_wdt_ioctl,
	.compat_ioctl	= compat_ptr_ioctl,
	.open		= sch311x_wdt_open,
	.release	= sch311x_wdt_close,
};

static struct miscdevice sch311x_wdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &sch311x_wdt_fops,
};

/*
 *	Init & exit routines
 */

static int sch311x_wdt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	int err;

	spin_lock_init(&sch311x_wdt_data.io_lock);

	if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) {
		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
			sch311x_wdt_data.runtime_reg + GP60,
			sch311x_wdt_data.runtime_reg + GP60);
		err = -EBUSY;
		goto exit;
	}

	if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4,
								DRV_NAME)) {
		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
			sch311x_wdt_data.runtime_reg + WDT_TIME_OUT,
			sch311x_wdt_data.runtime_reg + WDT_CTRL);
		err = -EBUSY;
		goto exit_release_region;
	}

	/* Make sure that the watchdog is not running */
	sch311x_wdt_stop();

	/* Disable keyboard and mouse interaction and interrupt */
	/* -- Watchdog timer configuration --
	 * Bit 0   Reserved
	 * Bit 1   Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
	 * Bit 2   Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr
	 * Bit 3   Reserved
	 * Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
	 *            0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
	 */
	outb(0, sch311x_wdt_data.runtime_reg + WDT_CFG);

	/* Check that the heartbeat value is within it's range ;
	 * if not reset to the default */
	if (sch311x_wdt_set_heartbeat(timeout)) {
		sch311x_wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		dev_info(dev, "timeout value must be 1<=x<=15300, using %d\n",
			timeout);
	}

	/* Get status at boot */
	sch311x_wdt_get_status(&sch311x_wdt_data.boot_status);

	sch311x_wdt_miscdev.parent = dev;

	err = misc_register(&sch311x_wdt_miscdev);
	if (err != 0) {
		dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n",
							WATCHDOG_MINOR, err);
		goto exit_release_region2;
	}

	dev_info(dev,
		"SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

exit_release_region2:
	release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
exit_release_region:
	release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
	sch311x_wdt_data.runtime_reg = 0;
exit:
	return err;

Annotation

Implementation Notes