drivers/watchdog/it8712f_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/it8712f_wdt.c
Extension
.c
Size
9977 bytes
Lines
450
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 it8712f_wdt_fops = {
	.owner = THIS_MODULE,
	.write = it8712f_wdt_write,
	.unlocked_ioctl = it8712f_wdt_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.open = it8712f_wdt_open,
	.release = it8712f_wdt_release,
};

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

static int __init it8712f_wdt_find(unsigned short *address)
{
	int err = -ENODEV;
	int chip_type;
	int ret = superio_enter();
	if (ret)
		return ret;

	chip_type = superio_inw(DEVID);
	if (chip_type != IT8712F_DEVID)
		goto exit;

	superio_select(LDN_GAME);
	superio_outb(1, ACT_REG);
	if (!(superio_inb(ACT_REG) & 0x01)) {
		pr_err("Device not activated, skipping\n");
		goto exit;
	}

	*address = superio_inw(BASE_REG);
	if (*address == 0) {
		pr_err("Base address not set, skipping\n");
		goto exit;
	}

	err = 0;
	revision = superio_inb(DEVREV) & 0x0f;

	/* Later revisions have 16-bit values per datasheet 0.9.1 */
	if (revision >= 0x08)
		max_units = 65535;

	if (margin > (max_units * 60))
		margin = (max_units * 60);

	pr_info("Found IT%04xF chip revision %d - using DogFood address 0x%x\n",
		chip_type, revision, *address);

exit:
	superio_exit();
	return err;
}

static int __init it8712f_wdt_init(void)
{
	int err = 0;

	if (it8712f_wdt_find(&address))
		return -ENODEV;

	if (!request_region(address, 1, "IT8712F Watchdog")) {
		pr_warn("watchdog I/O region busy\n");
		return -EBUSY;
	}

	err = it8712f_wdt_disable();
	if (err) {
		pr_err("unable to disable watchdog timer\n");
		goto out;
	}

	err = register_reboot_notifier(&it8712f_wdt_notifier);
	if (err) {
		pr_err("unable to register reboot notifier\n");
		goto out;
	}

	err = misc_register(&it8712f_wdt_miscdev);
	if (err) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       WATCHDOG_MINOR, err);
		goto reboot_out;
	}

	return 0;

Annotation

Implementation Notes