drivers/watchdog/marvell_gti_wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/marvell_gti_wdt.c
Extension
.c
Size
9852 bytes
Lines
349
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 gti_match_data {
	u32 gti_num_timers;
};

static const struct gti_match_data match_data_octeontx2 = {
	.gti_num_timers = 54,
};

static const struct gti_match_data match_data_cn10k = {
	.gti_num_timers = 64,
};

struct gti_wdt_priv {
	struct watchdog_device wdev;
	void __iomem *base;
	u32 clock_freq;
	struct clk *sclk;
	/* wdt_timer_idx used for timer to be used for system watchdog */
	u32 wdt_timer_idx;
	const struct gti_match_data *data;
};

static irqreturn_t gti_wdt_interrupt(int irq, void *data)
{
	struct watchdog_device *wdev = data;
	struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev);

	/* Clear Interrupt Pending Status */
	writeq(GTI_CWD_INT_PENDING_STATUS(priv->wdt_timer_idx),
	       priv->base + GTI_CWD_INT);

	watchdog_notify_pretimeout(wdev);

	return IRQ_HANDLED;
}

static int gti_wdt_ping(struct watchdog_device *wdev)
{
	struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev);

	writeq(GTI_CWD_POKE_VAL,
	       priv->base + GTI_CWD_POKE(priv->wdt_timer_idx));

	return 0;
}

static int gti_wdt_start(struct watchdog_device *wdev)
{
	struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev);
	u64 regval;

	if (!wdev->pretimeout)
		return -EINVAL;

	set_bit(WDOG_HW_RUNNING, &wdev->status);

	/* Clear any pending interrupt */
	writeq(GTI_CWD_INT_PENDING_STATUS(priv->wdt_timer_idx),
	       priv->base + GTI_CWD_INT);

	/* Enable Interrupt */
	writeq(GTI_CWD_INT_ENA_SET_VAL(priv->wdt_timer_idx),
	       priv->base + GTI_CWD_INT_ENA_SET);

	/* Set (Interrupt + SCP interrupt (DEL3T) + core domain reset) Mode */
	regval = readq(priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx));
	regval |= GTI_CWD_WDOG_MODE_INT_DEL3T_RST;
	writeq(regval, priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx));

	return 0;
}

static int gti_wdt_stop(struct watchdog_device *wdev)
{
	struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev);
	u64 regval;

	/* Disable Interrupt */
	writeq(GTI_CWD_INT_ENA_CLR_VAL(priv->wdt_timer_idx),
	       priv->base + GTI_CWD_INT_ENA_CLR);

	/* Set GTI_CWD_WDOG.Mode = 0 to stop the timer */
	regval = readq(priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx));
	regval &= ~GTI_CWD_WDOG_MODE_MASK;
	writeq(regval, priv->base + GTI_CWD_WDOG(priv->wdt_timer_idx));

	return 0;
}

static int gti_wdt_settimeout(struct watchdog_device *wdev,

Annotation

Implementation Notes