drivers/counter/microchip-tcb-capture.c

Source file repositories/reference/linux-study-clean/drivers/counter/microchip-tcb-capture.c

File Facts

System
Linux kernel
Corpus path
drivers/counter/microchip-tcb-capture.c
Extension
.c
Size
16082 bytes
Lines
609
Domain
Driver Families
Bucket
drivers/counter
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 mchp_tc_data {
	const struct atmel_tcb_config *tc_cfg;
	struct regmap *regmap;
	int qdec_mode;
	int num_channels;
	int channel[2];
};

static const enum counter_function mchp_tc_count_functions[] = {
	COUNTER_FUNCTION_INCREASE,
	COUNTER_FUNCTION_QUADRATURE_X4,
};

static const enum counter_synapse_action mchp_tc_synapse_actions[] = {
	COUNTER_SYNAPSE_ACTION_NONE,
	COUNTER_SYNAPSE_ACTION_RISING_EDGE,
	COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
	COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
};

static struct counter_signal mchp_tc_count_signals[] = {
	{
		.id = 0,
		.name = "Channel A",
	},
	{
		.id = 1,
		.name = "Channel B",
	}
};

static struct counter_synapse mchp_tc_count_synapses[] = {
	{
		.actions_list = mchp_tc_synapse_actions,
		.num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
		.signal = &mchp_tc_count_signals[0]
	},
	{
		.actions_list = mchp_tc_synapse_actions,
		.num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
		.signal = &mchp_tc_count_signals[1]
	}
};

static int mchp_tc_count_function_read(struct counter_device *counter,
				       struct counter_count *count,
				       enum counter_function *function)
{
	struct mchp_tc_data *const priv = counter_priv(counter);

	if (priv->qdec_mode)
		*function = COUNTER_FUNCTION_QUADRATURE_X4;
	else
		*function = COUNTER_FUNCTION_INCREASE;

	return 0;
}

static int mchp_tc_count_function_write(struct counter_device *counter,
					struct counter_count *count,
					enum counter_function function)
{
	struct mchp_tc_data *const priv = counter_priv(counter);
	u32 bmr, cmr;

	regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr);
	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);

	/* Set capture mode */
	cmr &= ~ATMEL_TC_WAVE;

	switch (function) {
	case COUNTER_FUNCTION_INCREASE:
		priv->qdec_mode = 0;
		/* Set highest rate based on whether soc has gclk or not */
		bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN);
		if (!priv->tc_cfg->has_gclk)
			cmr |= ATMEL_TC_TIMER_CLOCK2;
		else
			cmr |= ATMEL_TC_TIMER_CLOCK1;
		/* Setup the period capture mode */
		cmr |=  ATMEL_TC_CMR_MASK;
		cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0);
		break;
	case COUNTER_FUNCTION_QUADRATURE_X4:
		if (!priv->tc_cfg->has_qdec)
			return -EINVAL;
		/* In QDEC mode settings both channels 0 and 1 are required */
		if (priv->num_channels < 2 || priv->channel[0] != 0 ||
		    priv->channel[1] != 1) {

Annotation

Implementation Notes