drivers/hwmon/g762.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/g762.c
Extension
.c
Size
28485 bytes
Lines
1124
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 g762_data {
	struct i2c_client *client;
	bool internal_clock;
	struct clk *clk;

	/* update mutex */
	struct mutex update_lock;

	/* board specific parameters. */
	u32 clk_freq;

	/* g762 register cache */
	bool valid;
	unsigned long last_updated; /* in jiffies */

	u8 set_cnt;  /* controls fan rotation speed in closed-loop mode */
	u8 act_cnt;  /* provides access to current fan RPM value */
	u8 fan_sta;  /* bit 0: set when actual fan speed is more than
		      *        25% outside requested fan speed
		      * bit 1: set when no transition occurs on fan
		      *        pin for 0.7s
		      */
	u8 set_out;  /* controls fan rotation speed in open-loop mode */
	u8 fan_cmd1; /*   0: FG_PLS_ID0 FG pulses count per revolution
		      *      0: 2 counts per revolution
		      *      1: 4 counts per revolution
		      *   1: PWM_POLARITY 1: negative_duty
		      *                   0: positive_duty
		      * 2,3: [FG_CLOCK_ID0, FG_CLK_ID1]
		      *         00: Divide fan clock by 1
		      *         01: Divide fan clock by 2
		      *         10: Divide fan clock by 4
		      *         11: Divide fan clock by 8
		      *   4: FAN_MODE 1:closed-loop, 0:open-loop
		      *   5: OUT_MODE 1:PWM, 0:DC
		      *   6: DET_FAN_OOC enable "fan ooc" status
		      *   7: DET_FAN_FAIL enable "fan fail" status
		      */
	u8 fan_cmd2; /* 0,1: FAN_STARTV 0,1,2,3 -> 0,32,64,96 dac_code
		      * 2,3: FG_GEAR_MODE
		      *         00: multiplier = 1
		      *         01: multiplier = 2
		      *         10: multiplier = 4
		      *   4: Mask ALERT# (g763 only)
		      */
};

/*
 * Convert count value from fan controller register (FAN_SET_CNT) into fan
 * speed RPM value. Note that the datasheet documents a basic formula;
 * influence of additional parameters (fan clock divisor, fan gear mode)
 * have been infered from examples in the datasheet and tests.
 */
static inline unsigned int rpm_from_cnt(u8 cnt, u32 clk_freq, u16 p,
					u8 clk_div, u8 gear_mult)
{
	if (cnt == 0xff)  /* setting cnt to 255 stops the fan */
		return 0;

	return (clk_freq * 30 * gear_mult) / ((cnt ? cnt : 1) * p * clk_div);
}

/*
 * Convert fan RPM value from sysfs into count value for fan controller
 * register (FAN_SET_CNT).
 */
static inline unsigned char cnt_from_rpm(unsigned long rpm, u32 clk_freq, u16 p,
					 u8 clk_div, u8 gear_mult)
{
	unsigned long f1 = clk_freq * 30 * gear_mult;
	unsigned long f2 = p * clk_div;

	if (!rpm)	/* to stop the fan, set cnt to 255 */
		return 0xff;

	rpm = clamp_val(rpm, f1 / (255 * f2), ULONG_MAX / f2);
	return DIV_ROUND_CLOSEST(f1, rpm * f2);
}

/* helper to grab and cache data, at most one time per second */
static struct g762_data *g762_update_client(struct device *dev)
{
	struct g762_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	int ret = 0;

	mutex_lock(&data->update_lock);
	if (time_before(jiffies, data->last_updated + G762_UPDATE_INTERVAL) &&
	    likely(data->valid))
		goto out;

Annotation

Implementation Notes