/* * This TLMM test module serves the purpose of validating that the TLMM driver * (pinctrl-msm) delivers expected number of interrupts in response to changing * GPIO state. * * To achieve this without external equipment the test takes a module parameter * "gpio", which the tester is expected to specify an unused and non-connected * pin. The GPIO state is then driven by adjusting the bias of the pin, at * suitable times through the different test cases. * * Upon execution, the test initialization will find the TLMM node (subject to * tlmm_of_match[] allow listing) and create the necessary references * dynamically, rather then relying on e.g. Devicetree and phandles.
*/
staticstruct { void __iomem *base; void __iomem *reg; int irq;
u32 low_val;
u32 high_val;
} tlmm_suite;
/** * struct tlmm_test_priv - Per-test context * @intr_count: number of times hard handler was hit with TLMM_TEST_COUNT op set * @thread_count: number of times thread handler was hit with TLMM_TEST_COUNT op set * @intr_op: operations to be performed by the hard IRQ handler * @intr_op_remain: number of times the TLMM_TEST_THEN_* operations should be * performed by the hard IRQ handler * @thread_op: operations to be performed by the threaded IRQ handler * @thread_op_remain: number of times the TLMM_TEST_THEN_* operations should * be performed by the threaded IRQ handler
*/ struct tlmm_test_priv {
atomic_t intr_count;
atomic_t thread_count;
/* * Test that no RISING interrupts are triggered on a silent pin
*/ staticvoid tlmm_test_silent_rising(struct kunit *test)
{
tlmm_test_silent(test, IRQF_TRIGGER_RISING);
}
/* * Test that no FALLING interrupts are triggered on a silent pin
*/ staticvoid tlmm_test_silent_falling(struct kunit *test)
{
tlmm_test_silent(test, IRQF_TRIGGER_FALLING);
}
/* * Test that no LOW interrupts are triggered on a silent pin
*/ staticvoid tlmm_test_silent_low(struct kunit *test)
{
tlmm_test_silent(test, IRQF_TRIGGER_LOW);
}
/* * Test that no HIGH interrupts are triggered on a silent pin
*/ staticvoid tlmm_test_silent_high(struct kunit *test)
{
tlmm_test_silent(test, IRQF_TRIGGER_HIGH);
}
/* * Square wave with 10 high pulses, assert that we get 10 rising interrupts
*/ staticvoid tlmm_test_rising(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
priv->intr_op = TLMM_TEST_COUNT;
tlmm_output_low();
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING); for (i = 0; i < 10; i++) {
tlmm_output_low();
msleep(20);
tlmm_output_high();
msleep(20);
}
/* * Drive line low 10 times, handler drives it high to "clear the interrupt * source", assert we get 10 interrupts
*/ staticvoid tlmm_test_low(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
/* * Drive line high 10 times, handler drives it low to "clear the interrupt * source", assert we get 10 interrupts
*/ staticvoid tlmm_test_high(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
/* * Handler drives GPIO high to "clear the interrupt source", then low to * simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
*/ staticvoid tlmm_test_falling_in_handler(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv;
/* * Handler drives GPIO low to "clear the interrupt source", then high to * simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
*/ staticvoid tlmm_test_rising_in_handler(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv;
/* * Square wave with 10 high pulses, assert that we get 10 rising hard and * 10 threaded interrupts
*/ staticvoid tlmm_test_thread_rising(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
/* * Drive line high 10 times, threaded handler drives it low to "clear the * interrupt source", assert we get 10 interrupts
*/ staticvoid tlmm_test_thread_high(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
/* * Drive line low 10 times, threaded handler drives it high to "clear the * interrupt source", assert we get 10 interrupts
*/ staticvoid tlmm_test_thread_low(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; int i;
/* * Handler drives GPIO low to "clear the interrupt source", then high in the * threaded handler to simulate a new interrupt, repeated 10 times, assert we * get 10 interrupts
*/ staticvoid tlmm_test_thread_rising_in_handler(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv;
/* * Handler drives GPIO high to "clear the interrupt source", then low in the * threaded handler to simulate a new interrupt, repeated 10 times, assert we * get 10 interrupts
*/ staticvoid tlmm_test_thread_falling_in_handler(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv;
/* * Validate that edge interrupts occurring while irq is disabled is delivered * once the interrupt is reenabled.
*/ staticvoid tlmm_test_rising_while_disabled(struct kunit *test)
{ struct tlmm_test_priv *priv = test->priv; unsignedint after_edge; unsignedint before_edge;
/* * NOTE: When adding compatibles to this list, ensure that TLMM_REG_SIZE and * pull configuration values are supported and correct.
*/ staticconststruct of_device_id tlmm_of_match[] = {
{ .compatible = "qcom,sc8280xp-tlmm" },
{ .compatible = "qcom,x1e80100-tlmm" },
{}
};
staticint tlmm_reg_base(struct device_node *tlmm, struct resource *res)
{ constchar **reg_names; int count; int ret; int i;
count = of_property_count_strings(tlmm, "reg-names"); if (count <= 0) {
pr_err("failed to find tlmm reg name\n"); return count;
}
reg_names = kcalloc(count, sizeof(char *), GFP_KERNEL); if (!reg_names) return -ENOMEM;
ret = of_property_read_string_array(tlmm, "reg-names", reg_names, count); if (ret != count) {
kfree(reg_names); return -EINVAL;
}
if (!strcmp(tlmm_reg_name, "default_region")) {
ret = of_address_to_resource(tlmm, 0, res);
} else { for (i = 0; i < count; i++) { if (!strcmp(reg_names[i], tlmm_reg_name)) {
ret = of_address_to_resource(tlmm, i, res); break;
}
} if (i == count)
ret = -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.