drivers/watchdog/sbc8360.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/sbc8360.c
Extension
.c
Size
9794 bytes
Lines
404
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 sbc8360_fops = {
	.owner = THIS_MODULE,
	.write = sbc8360_write,
	.open = sbc8360_open,
	.release = sbc8360_close,
};

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

/*
 *	The SBC8360 needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block sbc8360_notifier = {
	.notifier_call = sbc8360_notify_sys,
};

static int __init sbc8360_init(void)
{
	int res;
	unsigned long int mseconds = 60000;

	if (timeout < 0 || timeout > 63) {
		pr_err("Invalid timeout index (must be 0-63)\n");
		res = -EINVAL;
		goto out;
	}

	if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
		pr_err("ENABLE method I/O %X is not available\n",
		       SBC8360_ENABLE);
		res = -EIO;
		goto out;
	}
	if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
		pr_err("BASETIME method I/O %X is not available\n",
		       SBC8360_BASETIME);
		res = -EIO;
		goto out_nobasetimereg;
	}

	res = register_reboot_notifier(&sbc8360_notifier);
	if (res) {
		pr_err("Failed to register reboot notifier\n");
		goto out_noreboot;
	}

	res = misc_register(&sbc8360_miscdev);
	if (res) {
		pr_err("failed to register misc device\n");
		goto out_nomisc;
	}

	wd_margin = wd_times[timeout][0];
	wd_multiplier = wd_times[timeout][1];

	if (wd_multiplier == 1)
		mseconds = (wd_margin + 1) * 500;
	else if (wd_multiplier == 2)
		mseconds = (wd_margin + 1) * 5000;
	else if (wd_multiplier == 3)
		mseconds = (wd_margin + 1) * 50000;
	else if (wd_multiplier == 4)
		mseconds = (wd_margin + 1) * 100000;

	/* My kingdom for the ability to print "0.5 seconds" in the kernel! */
	pr_info("Timeout set at %ld ms\n", mseconds);

	return 0;

out_nomisc:
	unregister_reboot_notifier(&sbc8360_notifier);
out_noreboot:
	release_region(SBC8360_BASETIME, 1);
out_nobasetimereg:
	release_region(SBC8360_ENABLE, 1);
out:
	return res;
}

static void __exit sbc8360_exit(void)
{
	misc_deregister(&sbc8360_miscdev);
	unregister_reboot_notifier(&sbc8360_notifier);
	release_region(SBC8360_ENABLE, 1);

Annotation

Implementation Notes