drivers/watchdog/starfive-wdt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/starfive-wdt.c
Extension
.c
Size
16778 bytes
Lines
616
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 starfive_wdt_variant {
	unsigned int control;		/* Watchdog Control Register for reset enable */
	unsigned int load;		/* Watchdog Load register */
	unsigned int reload;		/* Watchdog Reload Control register */
	unsigned int enable;		/* Watchdog Enable Register */
	unsigned int value;		/* Watchdog Counter Value Register */
	unsigned int int_clr;		/* Watchdog Interrupt Clear Register */
	unsigned int unlock;		/* Watchdog Lock Register */
	unsigned int int_status;	/* Watchdog Interrupt Status Register */

	u32 unlock_key;
	char enrst_shift;
	char en_shift;
	bool intclr_check;		/*  whether need to check it before clearing interrupt */
	char intclr_ava_shift;
	bool double_timeout;		/* The watchdog need twice timeout to reboot */
};

struct starfive_wdt {
	struct watchdog_device wdd;
	spinlock_t lock;		/* spinlock for register handling */
	void __iomem *base;
	struct clk *core_clk;
	struct clk *apb_clk;
	const struct starfive_wdt_variant *variant;
	unsigned long freq;
	u32 count;			/* count of timeout */
	u32 reload;			/* restore the count */
};

/* Register layout and configuration for the JH7100 */
static const struct starfive_wdt_variant starfive_wdt_jh7100_variant = {
	.control = STARFIVE_WDT_JH7100_CONTROL,
	.load = STARFIVE_WDT_JH7100_LOAD,
	.reload = STARFIVE_WDT_JH7100_RELOAD,
	.enable = STARFIVE_WDT_JH7100_EN,
	.value = STARFIVE_WDT_JH7100_VALUE,
	.int_clr = STARFIVE_WDT_JH7100_INTCLR,
	.unlock = STARFIVE_WDT_JH7100_LOCK,
	.unlock_key = STARFIVE_WDT_JH7100_UNLOCK_KEY,
	.int_status = STARFIVE_WDT_JH7100_INTSTAUS,
	.enrst_shift = STARFIVE_WDT_JH7100_RST_EN_SHIFT,
	.en_shift = STARFIVE_WDT_EN_SHIFT,
	.intclr_check = true,
	.intclr_ava_shift = STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT,
	.double_timeout = false,
};

/* Register layout and configuration for the JH7110 */
static const struct starfive_wdt_variant starfive_wdt_jh7110_variant = {
	.control = STARFIVE_WDT_JH7110_CONTROL,
	.load = STARFIVE_WDT_JH7110_LOAD,
	.enable = STARFIVE_WDT_JH7110_CONTROL,
	.value = STARFIVE_WDT_JH7110_VALUE,
	.int_clr = STARFIVE_WDT_JH7110_INTCLR,
	.unlock = STARFIVE_WDT_JH7110_LOCK,
	.unlock_key = STARFIVE_WDT_JH7110_UNLOCK_KEY,
	.int_status = STARFIVE_WDT_JH7110_IMS,
	.enrst_shift = STARFIVE_WDT_JH7110_RST_EN_SHIFT,
	.en_shift = STARFIVE_WDT_EN_SHIFT,
	.intclr_check = false,
	.double_timeout = true,
};

static int starfive_wdt_enable_clock(struct starfive_wdt *wdt)
{
	int ret;

	ret = clk_prepare_enable(wdt->apb_clk);
	if (ret)
		return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n");

	ret = clk_prepare_enable(wdt->core_clk);
	if (ret) {
		clk_disable_unprepare(wdt->apb_clk);
		return dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n");
	}

	return 0;
}

static void starfive_wdt_disable_clock(struct starfive_wdt *wdt)
{
	clk_disable_unprepare(wdt->core_clk);
	clk_disable_unprepare(wdt->apb_clk);
}

static inline int starfive_wdt_get_clock(struct starfive_wdt *wdt)
{
	struct device *dev = wdt->wdd.parent;

Annotation

Implementation Notes