drivers/hwmon/sfctemp.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/sfctemp.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/sfctemp.c
Extension
.c
Size
7281 bytes
Lines
312
Domain
Driver Families
Bucket
drivers/hwmon
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 sfctemp {
	void __iomem *regs;
	struct clk *clk_sense;
	struct clk *clk_bus;
	struct reset_control *rst_sense;
	struct reset_control *rst_bus;
	bool enabled;
};

static void sfctemp_power_up(struct sfctemp *sfctemp)
{
	/* make sure we're powered down first */
	writel(SFCTEMP_PD, sfctemp->regs);
	udelay(1);

	writel(0, sfctemp->regs);
	/* wait t_pu(50us) + t_rst(100ns) */
	usleep_range(60, 200);

	/* de-assert reset */
	writel(SFCTEMP_RSTN, sfctemp->regs);
	udelay(1); /* wait t_su(500ps) */
}

static void sfctemp_power_down(struct sfctemp *sfctemp)
{
	writel(SFCTEMP_PD, sfctemp->regs);
}

static void sfctemp_run(struct sfctemp *sfctemp)
{
	writel(SFCTEMP_RSTN | SFCTEMP_RUN, sfctemp->regs);
	udelay(1);
}

static void sfctemp_stop(struct sfctemp *sfctemp)
{
	writel(SFCTEMP_RSTN, sfctemp->regs);
}

static int sfctemp_enable(struct sfctemp *sfctemp)
{
	int ret;

	if (sfctemp->enabled)
		return 0;

	ret = clk_prepare_enable(sfctemp->clk_bus);
	if (ret)
		return ret;
	ret = reset_control_deassert(sfctemp->rst_bus);
	if (ret)
		goto err_disable_bus;

	ret = clk_prepare_enable(sfctemp->clk_sense);
	if (ret)
		goto err_assert_bus;
	ret = reset_control_deassert(sfctemp->rst_sense);
	if (ret)
		goto err_disable_sense;

	sfctemp_power_up(sfctemp);
	sfctemp_run(sfctemp);
	sfctemp->enabled = true;
	return 0;

err_disable_sense:
	clk_disable_unprepare(sfctemp->clk_sense);
err_assert_bus:
	reset_control_assert(sfctemp->rst_bus);
err_disable_bus:
	clk_disable_unprepare(sfctemp->clk_bus);
	return ret;
}

static int sfctemp_disable(struct sfctemp *sfctemp)
{
	if (!sfctemp->enabled)
		return 0;

	sfctemp_stop(sfctemp);
	sfctemp_power_down(sfctemp);
	reset_control_assert(sfctemp->rst_sense);
	clk_disable_unprepare(sfctemp->clk_sense);
	reset_control_assert(sfctemp->rst_bus);
	clk_disable_unprepare(sfctemp->clk_bus);
	sfctemp->enabled = false;
	return 0;
}

Annotation

Implementation Notes