drivers/watchdog/cgbc_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/cgbc_wdt.c
Extension
.c
Size
5243 bytes
Lines
212
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 cgbc_wdt_data {
	struct cgbc_device_data	*cgbc;
	struct watchdog_device	wdd;
};

struct cgbc_wdt_cmd_cfg {
	u8 cmd;
	u8 mode;
	u8 action;
	u8 timeout1[3];
	u8 timeout2[3];
	u8 reserved[3];
	u8 delay[3];
} __packed;

static_assert(sizeof(struct cgbc_wdt_cmd_cfg) == 15);

static int cgbc_wdt_start(struct watchdog_device *wdd)
{
	struct cgbc_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
	struct cgbc_device_data *cgbc = wdt_data->cgbc;
	unsigned int timeout1 = (wdd->timeout - wdd->pretimeout) * 1000;
	unsigned int timeout2 = wdd->pretimeout * 1000;
	u8 action;

	struct cgbc_wdt_cmd_cfg cmd_start = {
		.cmd = CGBC_WDT_CMD_INIT,
		.mode = CGBC_WDT_MODE_SINGLE_EVENT,
		.timeout1[0] = (u8)timeout1,
		.timeout1[1] = (u8)(timeout1 >> 8),
		.timeout1[2] = (u8)(timeout1 >> 16),
		.timeout2[0] = (u8)timeout2,
		.timeout2[1] = (u8)(timeout2 >> 8),
		.timeout2[2] = (u8)(timeout2 >> 16),
	};

	if (wdd->pretimeout) {
		action = 2;
		action |= ACTION_SMI << 2;
		action |= ACTION_RESET << 4;
	} else {
		action = 1;
		action |= ACTION_RESET << 2;
	}

	cmd_start.action = action;

	return cgbc_command(cgbc, &cmd_start, sizeof(cmd_start), NULL, 0, NULL);
}

static int cgbc_wdt_stop(struct watchdog_device *wdd)
{
	struct cgbc_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
	struct cgbc_device_data *cgbc = wdt_data->cgbc;
	struct cgbc_wdt_cmd_cfg cmd_stop = {
		.cmd = CGBC_WDT_CMD_INIT,
		.mode = CGBC_WDT_DISABLE,
	};

	return cgbc_command(cgbc, &cmd_stop, sizeof(cmd_stop), NULL, 0, NULL);
}

static int cgbc_wdt_keepalive(struct watchdog_device *wdd)
{
	struct cgbc_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
	struct cgbc_device_data *cgbc = wdt_data->cgbc;
	u8 cmd_ping = CGBC_WDT_CMD_TRIGGER;

	return cgbc_command(cgbc, &cmd_ping, sizeof(cmd_ping), NULL, 0, NULL);
}

static int cgbc_wdt_set_pretimeout(struct watchdog_device *wdd,
				   unsigned int pretimeout)
{
	wdd->pretimeout = pretimeout;

	if (watchdog_active(wdd))
		return cgbc_wdt_start(wdd);

	return 0;
}

static int cgbc_wdt_set_timeout(struct watchdog_device *wdd,
				unsigned int timeout)
{
	if (timeout < wdd->pretimeout)
		wdd->pretimeout = 0;

	wdd->timeout = timeout;

Annotation

Implementation Notes