drivers/watchdog/sa1100_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/sa1100_wdt.c
Extension
.c
Size
6398 bytes
Lines
251
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 sa1100dog_fops = {
	.owner		= THIS_MODULE,
	.write		= sa1100dog_write,
	.unlocked_ioctl	= sa1100dog_ioctl,
	.compat_ioctl	= compat_ptr_ioctl,
	.open		= sa1100dog_open,
	.release	= sa1100dog_release,
};

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

static int margin = 60;		/* (secs) Default is 1 minute */
static struct clk *clk;

static int sa1100dog_probe(struct platform_device *pdev)
{
	int ret;
	int *platform_data;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENXIO;
	reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
	if (!reg_base)
		return -ENOMEM;

	clk = clk_get(NULL, "OSTIMER0");
	if (IS_ERR(clk)) {
		pr_err("SA1100/PXA2xx Watchdog Timer: clock not found: %d\n",
		       (int) PTR_ERR(clk));
		return PTR_ERR(clk);
	}

	ret = clk_prepare_enable(clk);
	if (ret) {
		pr_err("SA1100/PXA2xx Watchdog Timer: clock failed to prepare+enable: %d\n",
		       ret);
		goto err;
	}

	oscr_freq = clk_get_rate(clk);

	platform_data = pdev->dev.platform_data;
	if (platform_data && *platform_data)
		boot_status = WDIOF_CARDRESET;
	pre_margin = oscr_freq * margin;

	ret = misc_register(&sa1100dog_miscdev);
	if (ret == 0) {
		pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
			margin);
		return 0;
	}

	clk_disable_unprepare(clk);
err:
	clk_put(clk);
	return ret;
}

static void sa1100dog_remove(struct platform_device *pdev)
{
	misc_deregister(&sa1100dog_miscdev);
	clk_disable_unprepare(clk);
	clk_put(clk);
}

static struct platform_driver sa1100dog_driver = {
	.driver.name = "sa1100_wdt",
	.probe = sa1100dog_probe,
	.remove = sa1100dog_remove,
};
module_platform_driver(sa1100dog_driver);

MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");

module_param(margin, int, 0);
MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");

MODULE_LICENSE("GPL");

Annotation

Implementation Notes