drivers/thermal/da9062-thermal.c

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

File Facts

System
Linux kernel
Corpus path
drivers/thermal/da9062-thermal.c
Extension
.c
Size
7228 bytes
Lines
266
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 da9062_thermal_config {
	const char *name;
};

struct da9062_thermal {
	struct da9062 *hw;
	struct delayed_work work;
	struct thermal_zone_device *zone;
	struct mutex lock; /* protection for da9062_thermal temperature */
	int temperature;
	int irq;
	const struct da9062_thermal_config *config;
	struct device *dev;
};

static void da9062_thermal_poll_on(struct work_struct *work)
{
	struct da9062_thermal *thermal = container_of(work,
						struct da9062_thermal,
						work.work);
	unsigned long delay;
	unsigned int val;
	int ret;

	/* clear E_TEMP */
	ret = regmap_write(thermal->hw->regmap,
			   DA9062AA_EVENT_B,
			   DA9062AA_E_TEMP_MASK);
	if (ret < 0) {
		dev_err(thermal->dev,
			"Cannot clear the TJUNC temperature status\n");
		goto err_enable_irq;
	}

	/* Now read E_TEMP again: it is acting like a status bit.
	 * If over-temperature, then this status will be true.
	 * If not over-temperature, this status will be false.
	 */
	ret = regmap_read(thermal->hw->regmap,
			  DA9062AA_EVENT_B,
			  &val);
	if (ret < 0) {
		dev_err(thermal->dev,
			"Cannot check the TJUNC temperature status\n");
		goto err_enable_irq;
	}

	if (val & DA9062AA_E_TEMP_MASK) {
		mutex_lock(&thermal->lock);
		thermal->temperature = DA9062_MILLI_CELSIUS(125);
		mutex_unlock(&thermal->lock);
		thermal_zone_device_update(thermal->zone,
					   THERMAL_EVENT_UNSPECIFIED);

		/*
		 * pp_tmp is between 1s and 10s, so we can round the jiffies
		 */
		delay = round_jiffies(msecs_to_jiffies(pp_tmp));
		queue_delayed_work(system_freezable_wq, &thermal->work, delay);
		return;
	}

	mutex_lock(&thermal->lock);
	thermal->temperature = DA9062_MILLI_CELSIUS(0);
	mutex_unlock(&thermal->lock);
	thermal_zone_device_update(thermal->zone,
				   THERMAL_EVENT_UNSPECIFIED);

err_enable_irq:
	enable_irq(thermal->irq);
}

static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
{
	struct da9062_thermal *thermal = data;

	disable_irq_nosync(thermal->irq);
	queue_delayed_work(system_freezable_wq, &thermal->work, 0);

	return IRQ_HANDLED;
}

static int da9062_thermal_get_temp(struct thermal_zone_device *z,
				   int *temp)
{
	struct da9062_thermal *thermal = thermal_zone_device_priv(z);

	mutex_lock(&thermal->lock);
	*temp = thermal->temperature;
	mutex_unlock(&thermal->lock);

Annotation

Implementation Notes