drivers/thermal/armada_thermal.c

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

File Facts

System
Linux kernel
Corpus path
drivers/thermal/armada_thermal.c
Extension
.c
Size
26502 bytes
Lines
985
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 armada_thermal_priv {
	struct device *dev;
	struct regmap *syscon;
	char zone_name[THERMAL_NAME_LENGTH];
	/* serialize temperature reads/updates */
	struct mutex update_lock;
	struct armada_thermal_data *data;
	struct thermal_zone_device *overheat_sensor;
	int interrupt_source;
	int current_channel;
	long current_threshold;
	long current_hysteresis;
};

struct armada_thermal_data {
	/* Initialize the thermal IC */
	void (*init)(struct platform_device *pdev,
		     struct armada_thermal_priv *priv);

	/* Formula coeficients: temp = (b - m * reg) / div */
	s64 coef_b;
	s64 coef_m;
	u32 coef_div;
	bool inverted;
	bool signed_sample;

	/* Register shift and mask to access the sensor temperature */
	unsigned int temp_shift;
	unsigned int temp_mask;
	unsigned int thresh_shift;
	unsigned int hyst_shift;
	unsigned int hyst_mask;
	u32 is_valid_bit;

	/* Syscon access */
	unsigned int syscon_control0_off;
	unsigned int syscon_control1_off;
	unsigned int syscon_status_off;
	unsigned int dfx_irq_cause_off;
	unsigned int dfx_irq_mask_off;
	unsigned int dfx_overheat_irq;
	unsigned int dfx_server_irq_mask_off;
	unsigned int dfx_server_irq_en;

	/* One sensor is in the thermal IC, the others are in the CPUs if any */
	unsigned int cpu_nr;
};

struct armada_drvdata {
	enum drvtype {
		LEGACY,
		SYSCON
	} type;
	union {
		struct armada_thermal_priv *priv;
		struct thermal_zone_device *tz;
	} data;
};

/*
 * struct armada_thermal_sensor - hold the information of one thermal sensor
 * @thermal: pointer to the local private structure
 * @tzd: pointer to the thermal zone device
 * @id: identifier of the thermal sensor
 */
struct armada_thermal_sensor {
	struct armada_thermal_priv *priv;
	int id;
};

static void armadaxp_init(struct platform_device *pdev,
			  struct armada_thermal_priv *priv)
{
	struct armada_thermal_data *data = priv->data;
	u32 reg;

	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
	reg |= PMU_TDC0_OTF_CAL_MASK;

	/* Reference calibration value */
	reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
	reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);

	/* Reset the sensor */
	reg |= PMU_TDC0_SW_RST_MASK;

	regmap_write(priv->syscon, data->syscon_control1_off, reg);

	reg &= ~PMU_TDC0_SW_RST_MASK;
	regmap_write(priv->syscon, data->syscon_control1_off, reg);

Annotation

Implementation Notes