drivers/thermal/sun8i_thermal.c

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

File Facts

System
Linux kernel
Corpus path
drivers/thermal/sun8i_thermal.c
Extension
.c
Size
19714 bytes
Lines
737
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 tsensor {
	struct ths_device		*tmdev;
	struct thermal_zone_device	*tzd;
	int				id;
};

struct ths_thermal_chip {
	bool            has_mod_clk;
	bool            has_bus_clk_reset;
	bool		needs_sram;
	int		sensor_num;
	int		offset;
	int		scale;
	int		ft_deviation;
	int		temp_data_base;
	int		(*calibrate)(struct ths_device *tmdev,
				     u16 *caldata, int callen);
	int		(*init)(struct ths_device *tmdev);
	unsigned long	(*irq_ack)(struct ths_device *tmdev);
	int		(*calc_temp)(struct ths_device *tmdev,
				     int id, int reg);
};

struct ths_device {
	const struct ths_thermal_chip		*chip;
	struct device				*dev;
	struct regmap				*regmap;
	struct regmap_field			*sram_regmap_field;
	struct reset_control			*reset;
	struct clk				*bus_clk;
	struct clk                              *mod_clk;
	struct tsensor				sensor[MAX_SENSOR_NUM];
};

/* The H616 needs to have a bit 16 in the SRAM control register cleared. */
static const struct reg_field sun8i_ths_sram_reg_field = REG_FIELD(0x0, 16, 16);

/* Temp Unit: millidegree Celsius */
static int sun8i_ths_calc_temp(struct ths_device *tmdev,
			       int id, int reg)
{
	return tmdev->chip->offset - (reg * tmdev->chip->scale / 10);
}

static int sun50i_h5_calc_temp(struct ths_device *tmdev,
			       int id, int reg)
{
	if (reg >= 0x500)
		return -1191 * reg / 10 + 223000;
	else if (!id)
		return -1452 * reg / 10 + 259000;
	else
		return -1590 * reg / 10 + 276000;
}

static int sun8i_ths_get_temp(struct thermal_zone_device *tz, int *temp)
{
	struct tsensor *s = thermal_zone_device_priv(tz);
	struct ths_device *tmdev = s->tmdev;
	int val = 0;

	regmap_read(tmdev->regmap, tmdev->chip->temp_data_base +
		    0x4 * s->id, &val);

	/* ths have no data yet */
	if (!val)
		return -EAGAIN;

	*temp = tmdev->chip->calc_temp(tmdev, s->id, val);
	/*
	 * According to the original sdk, there are some platforms(rarely)
	 * that add a fixed offset value after calculating the temperature
	 * value. We can't simply put it on the formula for calculating the
	 * temperature above, because the formula for calculating the
	 * temperature above is also used when the sensor is calibrated. If
	 * do this, the correct calibration formula is hard to know.
	 */
	*temp += tmdev->chip->ft_deviation;

	return 0;
}

static const struct thermal_zone_device_ops ths_ops = {
	.get_temp = sun8i_ths_get_temp,
};

static const struct regmap_config config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,

Annotation

Implementation Notes