drivers/thermal/qoriq_thermal.c

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

File Facts

System
Linux kernel
Corpus path
drivers/thermal/qoriq_thermal.c
Extension
.c
Size
11910 bytes
Lines
462
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 qoriq_sensor {
	int				id;
};

struct tmu_drvdata {
	u32 teumr0;
	u32 tmu_errata;
};

struct qoriq_tmu_data {
	int ver;
	u32 ttrcr[NUM_TTRCR_MAX];
	struct regmap *regmap;
	struct clk *clk;
	struct qoriq_sensor	sensor[SITES_MAX];
	const struct tmu_drvdata *drvdata;
};

static inline bool qoriq_tmu_has_errata(const struct tmu_drvdata *drvdata,
					u32 flag)
{
	return drvdata->tmu_errata & flag;
}

static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
{
	return container_of(s, struct qoriq_tmu_data, sensor[s->id]);
}

static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
{
	struct qoriq_sensor *qsensor = thermal_zone_device_priv(tz);
	struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
	u32 val, tidr;
	/*
	 * REGS_TRITSR(id) has the following layout:
	 *
	 * For TMU Rev1:
	 * 31  ... 7 6 5 4 3 2 1 0
	 *  V          TEMP
	 *
	 * Where V bit signifies if the measurement is ready and is
	 * within sensor range. TEMP is an 8 bit value representing
	 * temperature in Celsius.

	 * For TMU Rev2:
	 * 31  ... 8 7 6 5 4 3 2 1 0
	 *  V          TEMP
	 *
	 * Where V bit signifies if the measurement is ready and is
	 * within sensor range. TEMP is an 9 bit value representing
	 * temperature in KelVin.
	 */

	regmap_read(qdata->regmap, REGS_TMR, &val);
	if (!(val & TMR_ME))
		return -EAGAIN;

	if (regmap_read_poll_timeout(qdata->regmap,
				     REGS_TRITSR(qsensor->id),
				     val,
				     val & TRITSR_V,
				     USEC_PER_MSEC,
				     10 * USEC_PER_MSEC))
		return -ENODATA;

	/*ERR052243: If a raising or falling edge happens, try later */
	if (qoriq_tmu_has_errata(qdata->drvdata, TMU_ERR052243)) {
		regmap_read(qdata->regmap, REGS_TIDR, &tidr);
		if (tidr & TEMP_RATE_IRQ_MASK) {
			regmap_write(qdata->regmap, REGS_TIDR, TEMP_RATE_IRQ_MASK);
			return -EAGAIN;
		}
	}

	if (qdata->ver == TMU_VER1) {
		*temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
	} else {
		if (val & TRITSR_TP5)
			*temp = milli_kelvin_to_millicelsius((val & GENMASK(8, 0)) *
							     MILLIDEGREE_PER_DEGREE + 500);
		else
			*temp = kelvin_to_millicelsius(val & GENMASK(8, 0));
	}

	return 0;
}

static const struct thermal_zone_device_ops tmu_tz_ops = {
	.get_temp = tmu_get_temp,

Annotation

Implementation Notes