drivers/pinctrl/qcom/tlmm-test.c

Source file repositories/reference/linux-study-clean/drivers/pinctrl/qcom/tlmm-test.c

File Facts

System
Linux kernel
Corpus path
drivers/pinctrl/qcom/tlmm-test.c
Extension
.c
Size
17903 bytes
Lines
709
Domain
Driver Families
Bucket
drivers/pinctrl
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 tlmm_test_priv {
	atomic_t intr_count;
	atomic_t thread_count;

	unsigned int intr_op;
	atomic_t intr_op_remain;

	unsigned int thread_op;
	atomic_t thread_op_remain;
};

/* Operation masks for @intr_op and @thread_op */
#define TLMM_TEST_COUNT		BIT(0)
#define TLMM_TEST_OUTPUT_LOW	BIT(1)
#define TLMM_TEST_OUTPUT_HIGH	BIT(2)
#define TLMM_TEST_THEN_HIGH	BIT(3)
#define TLMM_TEST_THEN_LOW	BIT(4)
#define TLMM_TEST_WAKE_THREAD	BIT(5)

static void tlmm_output_low(void)
{
	writel(tlmm_suite.low_val, tlmm_suite.reg);
	readl(tlmm_suite.reg);
}

static void tlmm_output_high(void)
{
	writel(tlmm_suite.high_val, tlmm_suite.reg);
	readl(tlmm_suite.reg);
}

static irqreturn_t tlmm_test_intr_fn(int irq, void *dev_id)
{
	struct tlmm_test_priv *priv = dev_id;

	if (priv->intr_op & TLMM_TEST_COUNT)
		atomic_inc(&priv->intr_count);

	if (priv->intr_op & TLMM_TEST_OUTPUT_LOW)
		tlmm_output_low();
	if (priv->intr_op & TLMM_TEST_OUTPUT_HIGH)
		tlmm_output_high();

	if (atomic_dec_if_positive(&priv->intr_op_remain) > 0) {
		udelay(1);

		if (priv->intr_op & TLMM_TEST_THEN_LOW)
			tlmm_output_low();
		if (priv->intr_op & TLMM_TEST_THEN_HIGH)
			tlmm_output_high();
	}

	return priv->intr_op & TLMM_TEST_WAKE_THREAD ? IRQ_WAKE_THREAD : IRQ_HANDLED;
}

static irqreturn_t tlmm_test_intr_thread_fn(int irq, void *dev_id)
{
	struct tlmm_test_priv *priv = dev_id;

	if (priv->thread_op & TLMM_TEST_COUNT)
		atomic_inc(&priv->thread_count);

	if (priv->thread_op & TLMM_TEST_OUTPUT_LOW)
		tlmm_output_low();
	if (priv->thread_op & TLMM_TEST_OUTPUT_HIGH)
		tlmm_output_high();

	if (atomic_dec_if_positive(&priv->thread_op_remain) > 0) {
		udelay(1);
		if (priv->thread_op & TLMM_TEST_THEN_LOW)
			tlmm_output_low();
		if (priv->thread_op & TLMM_TEST_THEN_HIGH)
			tlmm_output_high();
	}

	return IRQ_HANDLED;
}

static void tlmm_test_request_hard_irq(struct kunit *test, unsigned long irqflags)
{
	struct tlmm_test_priv *priv = test->priv;
	int ret;

	ret = request_irq(tlmm_suite.irq, tlmm_test_intr_fn, irqflags, test->name, priv);
	KUNIT_EXPECT_EQ(test, ret, 0);
}

static void tlmm_test_request_threaded_irq(struct kunit *test, unsigned long irqflags)
{
	struct tlmm_test_priv *priv = test->priv;

Annotation

Implementation Notes