drivers/iio/adc/pac1921.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/pac1921.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/pac1921.c
Extension
.c
Size
35610 bytes
Lines
1346
Domain
Driver Families
Bucket
drivers/iio
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 pac1921_priv {
	struct i2c_client *client;
	struct regmap *regmap;
	struct regulator *vdd;
	struct iio_info iio_info;

	/*
	 * Synchronize access to private members, and ensure atomicity of
	 * consecutive regmap operations.
	 */
	struct mutex lock;

	u32 rshunt_uohm; /* uOhm */
	u8 dv_gain;
	u8 di_gain;
	u8 n_samples;
	u8 prev_ovf_flags;
	u8 ovf_enabled_events;

	bool first_integr_started;
	bool first_integr_done;
	unsigned long integr_started_time_jiffies;
	unsigned int integr_period_usecs;

	int current_scales[ARRAY_SIZE(pac1921_vsense_scales)][2];

	struct {
		u16 chan[PAC1921_NUM_MEAS_CHANS];
		aligned_s64 timestamp;
	} scan;
};

/*
 * Check if first integration after configuration update has completed.
 *
 * Must be called with lock held.
 */
static bool pac1921_data_ready(struct pac1921_priv *priv)
{
	if (!priv->first_integr_started)
		return false;

	if (!priv->first_integr_done) {
		unsigned long t_ready;

		/*
		 * Data valid after the device entered into integration state,
		 * considering worst case where the device was in sleep state,
		 * and completed the first integration period.
		 */
		t_ready = priv->integr_started_time_jiffies +
			  usecs_to_jiffies(PAC1921_SLEEP_TO_INT_TIME_US) +
			  usecs_to_jiffies(priv->integr_period_usecs);

		if (time_before(jiffies, t_ready))
			return false;

		priv->first_integr_done = true;
	}

	return true;
}

static inline void pac1921_calc_scale(int dividend, int divisor, int *val,
				      int *val2)
{
	s64 tmp;

	tmp = div_s64(dividend * (s64)NANO, divisor);
	*val = div_s64_rem(tmp, NANO, val2);
}

/*
 * Fill the table of scale factors for current
 * format: IIO_VAL_INT_PLUS_NANO
 * unit: mA
 *
 * Vsense LSB (nV) = max_vsense (nV) * di_gain / resolution
 * Current scale (mA) = Vsense LSB (nV) / shunt (uOhm)
 *
 * Must be called with held lock when updating after first initialization.
 */
static void pac1921_calc_current_scales(struct pac1921_priv *priv)
{
	for (unsigned int i = 0; i < ARRAY_SIZE(priv->current_scales); i++) {
		int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i;
		int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION);

		pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm,
				   &priv->current_scales[i][0],

Annotation

Implementation Notes