drivers/hwmon/mr75203.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/mr75203.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/mr75203.c
Extension
.c
Size
22673 bytes
Lines
929
Domain
Driver Families
Bucket
drivers/hwmon
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations pvt_ts_coeff_j_fops = {
	.read = pvt_ts_coeff_j_read,
	.write = pvt_ts_coeff_j_write,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

static void devm_pvt_ts_dbgfs_remove(void *data)
{
	struct pvt_device *pvt = (struct pvt_device *)data;

	debugfs_remove_recursive(pvt->dbgfs_dir);
	pvt->dbgfs_dir = NULL;
}

static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev)
{
	pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL);

	debugfs_create_u32("ts_coeff_h", 0644, pvt->dbgfs_dir,
			   &pvt->ts_coeff.h);
	debugfs_create_u32("ts_coeff_g", 0644, pvt->dbgfs_dir,
			   &pvt->ts_coeff.g);
	debugfs_create_u32("ts_coeff_cal5", 0644, pvt->dbgfs_dir,
			   &pvt->ts_coeff.cal5);
	debugfs_create_file("ts_coeff_j", 0644, pvt->dbgfs_dir, pvt,
			    &pvt_ts_coeff_j_fops);

	return devm_add_action_or_reset(dev, devm_pvt_ts_dbgfs_remove, pvt);
}

static umode_t pvt_is_visible(const void *data, enum hwmon_sensor_types type,
			      u32 attr, int channel)
{
	switch (type) {
	case hwmon_temp:
		if (attr == hwmon_temp_input)
			return 0444;
		break;
	case hwmon_in:
		if (attr == hwmon_in_input)
			return 0444;
		break;
	default:
		break;
	}
	return 0;
}

static long pvt_calc_temp(struct pvt_device *pvt, u32 nbs)
{
	/*
	 * Convert the register value to degrees centigrade temperature:
	 * T = G + H * (n / cal5 - 0.5) + J * F
	 */
	struct temp_coeff *ts_coeff = &pvt->ts_coeff;

	s64 tmp = ts_coeff->g +
		div_s64(ts_coeff->h * (s64)nbs, ts_coeff->cal5) -
		ts_coeff->h / 2 +
		div_s64(ts_coeff->j * (s64)pvt->ip_freq, HZ_PER_MHZ);

	return clamp_val(tmp, PVT_TEMP_MIN_mC, PVT_TEMP_MAX_mC);
}

static int pvt_read_temp(struct device *dev, u32 attr, int channel, long *val)
{
	struct pvt_device *pvt = dev_get_drvdata(dev);
	struct regmap *t_map = pvt->t_map;
	u32 stat, nbs;
	int ret;

	switch (attr) {
	case hwmon_temp_input:
		ret = regmap_read_poll_timeout(t_map, SDIF_DONE(channel),
					       stat, stat & SDIF_SMPL_DONE,
					       PVT_POLL_DELAY_US,
					       PVT_POLL_TIMEOUT_US);
		if (ret)
			return ret;

		ret = regmap_read(t_map, SDIF_DATA(channel), &nbs);
		if (ret < 0)
			return ret;

		nbs &= SAMPLE_DATA_MSK;

		/*
		 * Convert the register value to

Annotation

Implementation Notes