On Sat, 29 Aug 2026 at 13:56, Strahinja Jankovic
<[email protected]> wrote:
>
> Add Allwinner GPIO set of qtests to validate functionality.
> Tests cover input and output port setting, as well as interrupt
> functionality.
>
> Signed-off-by: Strahinja Jankovic <[email protected]>
> ---


> +static void test_irq_pin_rising(const void *data)
> +{
> +    PortPinTestParam *param = (PortPinTestParam *)data;
> +    QTestState *s = qtest_init("-machine cubieboard");
> +    const int gpio_port = param->port;
> +    const int port_pin = param->pin;
> +    g_autofree char *in_name = portname_in(gpio_port);
> +    int irq_pin = irq_nr(gpio_port, port_pin);
> +    unsigned int irq_mask = 1u << irq_pin;
> +
> +    qtest_irq_intercept_in(s, "/machine/soc");
> +
> +    /* Configure as input and set pin low */
> +    update_cfg_reg(s, gpio_port, port_pin, AW_GPIO_CFG_IN);
> +    assert_cfg_regval(s, gpio_port, port_pin, AW_GPIO_CFG_IN);
> +    qtest_set_irq_in(
> +        s, "/machine/soc/gpio", in_name, port_pin, AW_GPIO_LEVEL_LOW);

Breaking the line immediately after the opening "(" looks odd;
generally put the first parameter there and break the line
after that where it makes sense.

> +
> +    /* Enable interrupt */
> +    update_int_cfg_reg(s, irq_pin, AW_GPIO_IRQ_CFG_RISING_EDGE);
> +    assert_int_cfg_regval(s, irq_pin, AW_GPIO_IRQ_CFG_RISING_EDGE);
> +    qtest_writel(s, GPIO_INT_CTL_ADDR, irq_mask);
> +
> +    /* Raise interrupt */
> +    qtest_set_irq_in(
> +        s, "/machine/soc/gpio", in_name, port_pin, AW_GPIO_LEVEL_HIGH);
> +    /* Check that value is written */
> +    assert_data_reg(s, gpio_port, port_pin, AW_GPIO_LEVEL_HIGH);
> +    /* Check interrupt status */
> +    g_assert_cmphex(qtest_readl(s, GPIO_INT_STA_ADDR), ==, irq_mask);
> +    g_assert_true(qtest_get_irq(s, AW_A10_IRQ_LINE));
> +
> +    /* Clear interrupt */
> +    qtest_writel(s, GPIO_INT_STA_ADDR, irq_mask);
> +
> +    /* Check that IRQ line is low */
> +    g_assert_cmphex(qtest_readl(s, GPIO_INT_STA_ADDR) & irq_mask, ==, 0);
> +    g_assert_false(qtest_get_irq(s, AW_A10_IRQ_LINE));
> +
> +    qtest_quit(s);
> +}



> +int main(int argc, char **argv)
> +{
> +  int r;
> +
> +  g_test_init(&argc, &argv, NULL);
> +
> +  for (int i = 0; i < G_N_ELEMENTS(in_out_test_parameters); i++) {

Prefer ARRAY_SIZE() over G_N_ELEMENTS().

> +    g_autofree char *out_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/set_output_pins/%s%d",
> +    portname(in_out_test_parameters[i].port), in_out_test_parameters[i].pin);
> +    g_autofree char *in_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/set_input_pins/%s%d",
> +    portname(in_out_test_parameters[i].port), in_out_test_parameters[i].pin);

This has turned into an unreadable lump especially given the
lack of indentation. I suggest factoring out the creation of the
test:

static char *add_test(const char *type, const PortPinTestParam *p,
                      void (*testfn)(const void *))
{
    g_autofree char *name =
         g_strdup_printf("/allwinner-cubieboard/gpio/%s/%s%d",
                         type, portname(p->port), p->pin);

    qtest_add_data_func(name, p, testfn);
}

Then you in your loop you can do:

    PortPinTestParam *p = &in_out_test_parameters[i];

    add_test("set_output_pins", p, test_set_output_pins);
    add_test("set_input_pins", p, test_set_input_pins);


> +    qtest_add_data_func(out_name, &in_out_test_parameters[i],
> +                        test_set_output_pins);
> +    qtest_add_data_func(in_name, &in_out_test_parameters[i],
> +                        test_set_input_pins);
> +  }
> +  qtest_add_func("/allwinner-cubieboard/gpio/reset_values",
> +                      test_reset_values);
> +  for (int i = 0; i < G_N_ELEMENTS(irq_test_parameters); i++) {
> +    g_autofree char *rising_edge_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/irq_pin_rising/%s%d",
> +    portname(irq_test_parameters[i].port), irq_test_parameters[i].pin);
> +    qtest_add_data_func(
> +            rising_edge_name, &irq_test_parameters[i], test_irq_pin_rising);
> +    g_autofree char *falling_edge_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/irq_pin_falling/%s%d",
> +    portname(irq_test_parameters[i].port), irq_test_parameters[i].pin);

add_test() should make this loop more readable too.

> +    qtest_add_data_func(
> +            falling_edge_name, &irq_test_parameters[i], 
> test_irq_pin_falling);
> +    g_autofree char *high_level_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/irq_pin_high_level/%s%d",
> +    portname(irq_test_parameters[i].port), irq_test_parameters[i].pin);
> +    qtest_add_data_func(
> +            high_level_name, &irq_test_parameters[i], 
> test_irq_pin_high_level);
> +    g_autofree char *low_level_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/irq_pin_low_level/%s%d",
> +    portname(irq_test_parameters[i].port), irq_test_parameters[i].pin);
> +    qtest_add_data_func(
> +            low_level_name, &irq_test_parameters[i], test_irq_pin_low_level);
> +    g_autofree char *both_edge_name = g_strdup_printf(
> +    "/allwinner-cubieboard/gpio/irq_pin_both_edge/%s%d",
> +    portname(irq_test_parameters[i].port), irq_test_parameters[i].pin);
> +    qtest_add_data_func(
> +            both_edge_name, &irq_test_parameters[i], test_irq_pin_both_edge);
> +
> +  }
> +  r = g_test_run();
> +
> +  return r;
> +}

thanks
-- PMM

Reply via email to