drivers/hwmon/mlxreg-fan.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/mlxreg-fan.c
Extension
.c
Size
16855 bytes
Lines
650
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 mlxreg_fan_tacho {
	bool connected;
	u32 reg;
	u32 mask;
	u32 prsnt;
	u32 shift;
};

/*
 * struct mlxreg_fan_pwm - PWM data (internal use):
 *
 * @fan: private data;
 * @connected: indicates if PWM is connected;
 * @reg: register offset;
 * @cooling: cooling device levels;
 * @last_hwmon_state: last cooling state set by hwmon subsystem;
 * @last_thermal_state: last cooling state set by thermal subsystem;
 * @cdev: cooling device;
 */
struct mlxreg_fan_pwm {
	struct mlxreg_fan *fan;
	bool connected;
	u32 reg;
	unsigned long last_hwmon_state;
	unsigned long last_thermal_state;
	struct thermal_cooling_device *cdev;
};

/*
 * struct mlxreg_fan - private data (internal use):
 *
 * @dev: basic device;
 * @regmap: register map of parent device;
 * @tacho: tachometer data;
 * @pwm: PWM data;
 * @tachos_per_drwr - number of tachometers per drawer;
 * @samples: minimum allowed samples per pulse;
 * @divider: divider value for tachometer RPM calculation;
 */
struct mlxreg_fan {
	struct device *dev;
	void *regmap;
	struct mlxreg_core_platform_data *pdata;
	struct mlxreg_fan_tacho tacho[MLXREG_FAN_MAX_TACHO];
	struct mlxreg_fan_pwm pwm[MLXREG_FAN_MAX_PWM];
	int tachos_per_drwr;
	int samples;
	int divider;
};

static int _mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
				     unsigned long state, bool thermal);

static int
mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
		int channel, long *val)
{
	struct mlxreg_fan *fan = dev_get_drvdata(dev);
	struct mlxreg_fan_tacho *tacho;
	struct mlxreg_fan_pwm *pwm;
	u32 regval;
	int err;

	switch (type) {
	case hwmon_fan:
		tacho = &fan->tacho[channel];
		switch (attr) {
		case hwmon_fan_input:
			/*
			 * Check FAN presence: FAN related bit in presence register is one,
			 * if FAN is physically connected, zero - otherwise.
			 */
			if (tacho->prsnt && fan->tachos_per_drwr) {
				err = regmap_read(fan->regmap, tacho->prsnt, &regval);
				if (err)
					return err;

				/*
				 * Map channel to presence bit - drawer can be equipped with
				 * one or few FANs, while presence is indicated per drawer.
				 * Shift channel value if necessary to align with register value.
				 */
				if (BIT(rol32(channel, tacho->shift) / fan->tachos_per_drwr) &
					regval) {
					/* FAN is not connected - return zero for FAN speed. */
					*val = 0;
					return 0;
				}
			}

Annotation

Implementation Notes