drivers/thermal/imx91_thermal.c

Source file repositories/reference/linux-study-clean/drivers/thermal/imx91_thermal.c

File Facts

System
Linux kernel
Corpus path
drivers/thermal/imx91_thermal.c
Extension
.c
Size
10349 bytes
Lines
389
Domain
Driver Families
Bucket
drivers/thermal
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 imx91_tmu {
	void __iomem *base;
	struct clk *clk;
	struct device *dev;
	struct thermal_zone_device *tzd;
};

static void imx91_tmu_start(struct imx91_tmu *tmu, bool start)
{
	u32 val = start ? IMX91_TMU_CTRL1_START : IMX91_TMU_CTRL1_STOP;

	writel_relaxed(val, tmu->base + IMX91_TMU_CTRL1 + REG_SET);
}

static void imx91_tmu_enable(struct imx91_tmu *tmu, bool enable)
{
	u32 reg = IMX91_TMU_CTRL1;

	reg += enable ? REG_SET : REG_CLR;

	writel_relaxed(IMX91_TMU_CTRL1_EN, tmu->base + reg);
}

static int imx91_tmu_to_mcelsius(int x)
{
	return x * MILLIDEGREE_PER_DEGREE / IMX91_TMP_FRAC;
}

static int imx91_tmu_from_mcelsius(int x)
{
	return x * IMX91_TMP_FRAC / MILLIDEGREE_PER_DEGREE;
}

static int imx91_tmu_get_temp(struct thermal_zone_device *tz, int *temp)
{
	struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
	s16 data;

	/* DATA0 is 16bit signed number */
	data = readw_relaxed(tmu->base + IMX91_TMU_DATA0);
	*temp = imx91_tmu_to_mcelsius(data);

	return 0;
}

static int imx91_tmu_set_trips(struct thermal_zone_device *tz, int low, int high)
{
	struct imx91_tmu *tmu = thermal_zone_device_priv(tz);
	int val;

	if (high >= IMX91_TMU_TEMP_HIGH_LIMIT)
		return -EINVAL;

	writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_CLR);

	/* Comparator1 for temperature threshold */
	writel_relaxed(IMX91_TMU_THR_CTRL01_THR1_MASK, tmu->base + IMX91_TMU_THR_CTRL01 + REG_CLR);
	val = FIELD_PREP(IMX91_TMU_THR_CTRL01_THR1_MASK, imx91_tmu_from_mcelsius(high));

	writel_relaxed(val, tmu->base + IMX91_TMU_THR_CTRL01 + REG_SET);

	writel_relaxed(IMX91_TMU_STAT0_THR1_IF, tmu->base + IMX91_TMU_STAT0 + REG_CLR);

	writel_relaxed(IMX91_TMU_CTRL0_THR1_IE, tmu->base + IMX91_TMU_CTRL0 + REG_SET);

	return 0;
}

static int imx91_init_from_nvmem_cells(struct imx91_tmu *tmu)
{
	struct device *dev = tmu->dev;
	u32 trim1, trim2;
	int ret;

	ret = nvmem_cell_read_u32(dev, "trim1", &trim1);
	if (ret)
		return ret;

	ret = nvmem_cell_read_u32(dev, "trim2", &trim2);
	if (ret)
		return ret;

	if (trim1 == 0 || trim2 == 0)
		return -EINVAL;

	writel_relaxed(trim1, tmu->base + IMX91_TMU_TRIM1);
	writel_relaxed(trim2, tmu->base + IMX91_TMU_TRIM2);

	return 0;
}

Annotation

Implementation Notes