drivers/hwmon/amc6821.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/amc6821.c
Extension
.c
Size
28000 bytes
Lines
1121
Domain
Driver Families
Bucket
drivers/hwmon
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 amc6821_data {
	struct regmap *regmap;
	struct mutex update_lock;
	unsigned long fan_state;
	unsigned long fan_max_state;
	unsigned int *fan_cooling_levels;
	enum pwm_polarity pwm_polarity;
};

/*
 * Return 0 on success or negative error code.
 *
 * temps returns set of three temperatures, in °C:
 * temps[0]: Passive cooling temperature, applies to both channels
 * temps[1]: Low temperature, start slope calculations
 * temps[2]: High temperature
 *
 * Channel 0: local, channel 1: remote.
 */
static int amc6821_get_auto_point_temps(struct regmap *regmap, int channel, u8 *temps)
{
	u32 regs[] = {
		AMC6821_REG_DCY_LOW_TEMP,
		AMC6821_REG_PSV_TEMP,
		channel ? AMC6821_REG_RTEMP_FAN_CTRL : AMC6821_REG_LTEMP_FAN_CTRL
	};
	u8 regvals[3];
	int slope;
	int err;

	err = regmap_multi_reg_read(regmap, regs, regvals, 3);
	if (err)
		return err;
	temps[0] = regvals[1];
	temps[1] = FIELD_GET(AMC6821_TEMP_LIMIT_MASK, regvals[2]) * 4;

	/* slope is 32 >> <slope bits> in °C */
	slope = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regvals[2]);
	if (slope)
		temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - regvals[0], slope);
	else
		temps[2] = 255;

	return 0;
}

static int amc6821_temp_read_values(struct regmap *regmap, u32 attr, int channel, long *val)
{
	int reg, err;
	u32 regval;

	switch (attr) {
	case hwmon_temp_input:
		reg = channel ? AMC6821_REG_RTEMP_HI : AMC6821_REG_LTEMP_HI;
		break;
	case hwmon_temp_min:
		reg = channel ? AMC6821_REG_RTEMP_LIMIT_MIN : AMC6821_REG_LTEMP_LIMIT_MIN;
		break;
	case hwmon_temp_max:
		reg = channel ? AMC6821_REG_RTEMP_LIMIT_MAX : AMC6821_REG_LTEMP_LIMIT_MAX;
		break;
	case hwmon_temp_crit:
		reg = channel ? AMC6821_REG_RTEMP_CRIT : AMC6821_REG_LTEMP_CRIT;
		break;
	default:
		return -EOPNOTSUPP;
	}
	err = regmap_read(regmap, reg, &regval);
	if (err)
		return err;
	*val = sign_extend32(regval, 7) * 1000;
	return 0;
}

static int amc6821_read_alarms(struct regmap *regmap, enum hwmon_sensor_types type,
			       u32 attr, int channel, long *val)
{
	int reg, mask, err;
	u32 regval;

	switch (type) {
	case hwmon_temp:
		switch (attr) {
		case hwmon_temp_min_alarm:
			reg = AMC6821_REG_STAT1;
			mask = channel ? AMC6821_STAT1_RTL : AMC6821_STAT1_LTL;
			break;
		case hwmon_temp_max_alarm:
			reg = AMC6821_REG_STAT1;
			mask = channel ? AMC6821_STAT1_RTH : AMC6821_STAT1_LTH;

Annotation

Implementation Notes