drivers/watchdog/mlx_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/mlx_wdt.c
Extension
.c
Size
9162 bytes
Lines
340
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 mlxreg_wdt {
	struct watchdog_device wdd;
	struct mlxreg_core_platform_data *pdata;
	void *regmap;
	int action_idx;
	int timeout_idx;
	int tleft_idx;
	int ping_idx;
	int reset_idx;
	int regmap_val_sz;
	enum mlxreg_wdt_type wdt_type;
};

static void mlxreg_wdt_check_card_reset(struct mlxreg_wdt *wdt)
{
	struct mlxreg_core_data *reg_data;
	u32 regval;
	int rc;

	if (wdt->reset_idx == -EINVAL)
		return;

	if (!(wdt->wdd.info->options & WDIOF_CARDRESET))
		return;

	reg_data = &wdt->pdata->data[wdt->reset_idx];
	rc = regmap_read(wdt->regmap, reg_data->reg, &regval);
	if (!rc) {
		if (regval & ~reg_data->mask) {
			wdt->wdd.bootstatus = WDIOF_CARDRESET;
			dev_info(wdt->wdd.parent,
				 "watchdog previously reset the CPU\n");
		}
	}
}

static int mlxreg_wdt_start(struct watchdog_device *wdd)
{
	struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
	struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];

	return regmap_update_bits(wdt->regmap, reg_data->reg, ~reg_data->mask,
				  BIT(reg_data->bit));
}

static int mlxreg_wdt_stop(struct watchdog_device *wdd)
{
	struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
	struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];

	return regmap_update_bits(wdt->regmap, reg_data->reg, ~reg_data->mask,
				  ~BIT(reg_data->bit));
}

static int mlxreg_wdt_ping(struct watchdog_device *wdd)
{
	struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
	struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->ping_idx];

	return regmap_write_bits(wdt->regmap, reg_data->reg, ~reg_data->mask,
				 BIT(reg_data->bit));
}

static int mlxreg_wdt_set_timeout(struct watchdog_device *wdd,
				  unsigned int timeout)
{
	struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
	struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
	u32 regval, set_time, hw_timeout;
	int rc;

	switch (wdt->wdt_type) {
	case MLX_WDT_TYPE1:
		rc = regmap_read(wdt->regmap, reg_data->reg, &regval);
		if (rc)
			return rc;

		hw_timeout = order_base_2(timeout * MLXREG_WDT_CLOCK_SCALE);
		regval = (regval & reg_data->mask) | hw_timeout;
		/* Rowndown to actual closest number of sec. */
		set_time = BIT(hw_timeout) / MLXREG_WDT_CLOCK_SCALE;
		rc = regmap_write(wdt->regmap, reg_data->reg, regval);
		break;
	case MLX_WDT_TYPE2:
		set_time = timeout;
		rc = regmap_write(wdt->regmap, reg_data->reg, timeout);
		break;
	case MLX_WDT_TYPE3:
		/* WD_TYPE3 has 2B set time register */
		set_time = timeout;

Annotation

Implementation Notes