Hi Simon,

On Sun, Dec 22, 2019 at 2:16 AM Simon Glass <s...@chromium.org> wrote:
>
> There can be different types of interrupt controllers in a system and some
> drivers may need to distinguish between these. In general this can be
> handled using the device tree by adding the interrupt information to
> device nodes.
>
> However on x86 devices we have interrupt controllers which are not tied
> to any particular device and not really used in U-Boot. These still need
> to be inited, so a convenient method is to give each controller a type
> and allow a particular controller type to be probed.
>
> Add support for this in sandbox along with a test.
>
> Signed-off-by: Simon Glass <s...@chromium.org>
> ---
>
> Changes in v2: None
>
>  arch/sandbox/include/asm/test.h |  4 ++++
>  drivers/misc/irq-uclass.c       | 24 +++++++++++++++++++++++-
>  drivers/misc/irq_sandbox.c      |  2 +-
>  include/irq.h                   | 21 +++++++++++++++++++++
>  test/dm/irq.c                   | 14 ++++++++++++++
>  5 files changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
> index fdb0ecfed1..0a11dfeefb 100644
> --- a/arch/sandbox/include/asm/test.h
> +++ b/arch/sandbox/include/asm/test.h
> @@ -45,6 +45,10 @@
>  #define PCI_EA_BAR2_MAGIC              0x72727272
>  #define PCI_EA_BAR4_MAGIC              0x74747474
>
> +enum {
> +       SANDBOX_IRQN_PEND = 1,  /* Interrupt number for 'pending' test */
> +};
> +
>  /* System controller driver data */
>  enum {
>         SYSCON0         = 32,
> diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
> index d5182cf149..38498a66a4 100644
> --- a/drivers/misc/irq-uclass.c
> +++ b/drivers/misc/irq-uclass.c
> @@ -1,11 +1,13 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> - * Copyright (C) 2015, Bin Meng <bmeng...@gmail.com>
> + * Copyright 2019 Google, LLC
> + * Written by Simon Glass <s...@chromium.org>
>   */
>
>  #include <common.h>
>  #include <dm.h>
>  #include <irq.h>
> +#include <dm/device-internal.h>
>
>  int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
>  {
> @@ -47,6 +49,26 @@ int irq_restore_polarities(struct udevice *dev)
>         return ops->restore_polarities(dev);
>  }
>
> +int irq_first_device_type(enum irq_dev_t type, struct udevice **devp)
> +{
> +       struct udevice *dev;
> +       struct uclass *uc;
> +       int ret;
> +
> +       ret = uclass_get(UCLASS_IRQ, &uc);
> +       if (ret)
> +               return ret;
> +       uclass_foreach_dev(dev, uc) {
> +               if (dev_get_driver_data(dev) == type) {
> +                       *devp = dev;
> +
> +                       return device_probe(dev);

The logic is generic and should not be limited to IRQ uclass. Maybe we
should put this API in DM core, and name it as something like
uclass_first_device_drvdata()?

> +               }
> +       }
> +
> +       return -ENODEV;
> +}
> +
>  UCLASS_DRIVER(irq) = {
>         .id             = UCLASS_IRQ,
>         .name           = "irq",
> diff --git a/drivers/misc/irq_sandbox.c b/drivers/misc/irq_sandbox.c
> index 6dda1a4c44..011022ac62 100644
> --- a/drivers/misc/irq_sandbox.c
> +++ b/drivers/misc/irq_sandbox.c
> @@ -43,7 +43,7 @@ static const struct irq_ops sandbox_irq_ops = {
>  };
>
>  static const struct udevice_id sandbox_irq_ids[] = {
> -       { .compatible = "sandbox,irq"},
> +       { .compatible = "sandbox,irq", SANDBOX_IRQT_BASE },
>         { }
>  };
>
> diff --git a/include/irq.h b/include/irq.h
> index 01ded64f16..1db97b5c3f 100644
> --- a/include/irq.h
> +++ b/include/irq.h
> @@ -8,6 +8,17 @@
>  #ifndef __irq_H
>  #define __irq_H
>
> +/*
> + * Interrupt controller types available. You can find a particular one with
> + * irq_first_device_type()
> + */
> +enum irq_dev_t {
> +       X86_IRQT_BASE,          /* Base controller */
> +       X86_IRQT_ITSS,          /* ITSS controller, e.g. on APL */
> +       X86_IRQT_ACPI_GPE,      /* ACPI General-Purpose Events controller */
> +       SANDBOX_IRQT_BASE,      /* Sandbox testing */
> +};
> +
>  /**
>   * struct irq_ops - Operations for the IRQ
>   */
> @@ -85,4 +96,14 @@ int irq_snapshot_polarities(struct udevice *dev);
>   */
>  int irq_restore_polarities(struct udevice *dev);
>
> +/**
> + * irq_first_device_type() - Get a particular interrupt controller
> + *
> + * @type: Type to find
> + * @devp: Returns the device, if found
> + * @return 0 if OK, -ENODEV if not found, other -ve error if uclass failed to
> + *     probe
> + */
> +int irq_first_device_type(enum irq_dev_t type, struct udevice **devp);
> +
>  #endif
> diff --git a/test/dm/irq.c b/test/dm/irq.c
> index 726189c59f..0f23f108a7 100644
> --- a/test/dm/irq.c
> +++ b/test/dm/irq.c
> @@ -8,6 +8,7 @@
>  #include <common.h>
>  #include <dm.h>
>  #include <irq.h>
> +#include <asm/test.h>
>  #include <dm/test.h>
>  #include <test/ut.h>
>
> @@ -30,3 +31,16 @@ static int dm_test_irq_base(struct unit_test_state *uts)
>         return 0;
>  }
>  DM_TEST(dm_test_irq_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
> +
> +/* Test of irq_first_device_type() */
> +static int dm_test_irq_type(struct unit_test_state *uts)
> +{
> +       struct udevice *dev;
> +
> +       ut_assertok(irq_first_device_type(SANDBOX_IRQT_BASE, &dev));
> +       ut_asserteq(-ENODEV, irq_first_device_type(X86_IRQT_BASE, &dev));
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_irq_type, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
> +
> --

Regards,
Bin

Reply via email to