drivers/thermal/st/stm_thermal.c

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

File Facts

System
Linux kernel
Corpus path
drivers/thermal/st/stm_thermal.c
Extension
.c
Size
14316 bytes
Lines
593
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 stm_thermal_sensor {
	struct device *dev;
	struct thermal_zone_device *th_dev;
	enum thermal_device_mode mode;
	struct clk *clk;
	unsigned int low_temp_enabled;
	unsigned int high_temp_enabled;
	int irq;
	void __iomem *base;
	int t0, fmt0, ramp_coeff;
};

static int stm_enable_irq(struct stm_thermal_sensor *sensor)
{
	u32 value;

	dev_dbg(sensor->dev, "low:%d high:%d\n", sensor->low_temp_enabled,
		sensor->high_temp_enabled);

	/* Disable IT generation for low and high thresholds */
	value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
	value &= ~(LOW_THRESHOLD | HIGH_THRESHOLD);

	if (sensor->low_temp_enabled)
		value |= HIGH_THRESHOLD;

	if (sensor->high_temp_enabled)
		value |= LOW_THRESHOLD;

	/* Enable interrupts */
	writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);

	return 0;
}

static irqreturn_t stm_thermal_irq_handler(int irq, void *sdata)
{
	struct stm_thermal_sensor *sensor = sdata;

	dev_dbg(sensor->dev, "sr:%d\n",
		readl_relaxed(sensor->base + DTS_SR_OFFSET));

	thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);

	stm_enable_irq(sensor);

	/* Acknoledge all DTS irqs */
	writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);

	return IRQ_HANDLED;
}

static int stm_sensor_power_on(struct stm_thermal_sensor *sensor)
{
	int ret;
	u32 value;

	/* Enable sensor */
	value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
	value |= TS1_EN;
	writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);

	/*
	 * The DTS block can be enabled by setting TSx_EN bit in
	 * DTS_CFGRx register. It requires a startup time of
	 * 40μs. Use 5 ms as arbitrary timeout.
	 */
	ret = readl_poll_timeout(sensor->base + DTS_SR_OFFSET,
				 value, (value & TS_RDY),
				 STARTUP_TIME, POLL_TIMEOUT);
	if (ret)
		return ret;

	/* Start continuous measuring */
	value = readl_relaxed(sensor->base +
			      DTS_CFGR1_OFFSET);
	value |= TS1_START;
	writel_relaxed(value, sensor->base +
		       DTS_CFGR1_OFFSET);

	sensor->mode = THERMAL_DEVICE_ENABLED;

	return 0;
}

static int stm_sensor_power_off(struct stm_thermal_sensor *sensor)
{
	u32 value;

	sensor->mode = THERMAL_DEVICE_DISABLED;

Annotation

Implementation Notes