blob: 35e8a3e20fca74613d8770bde0e2dd397baba60a [file] [log] [blame]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <utils/util.h>
#include "../../../irqchip.h"
/* Force the _allocated_irqs section to be created even if no modules are defined. */
static USED SECTION("_ps_irqchips") struct {} dummy_ps_irqchips;
/* Definitions so that we can find the exposed IRQ information */
extern ps_irqchip_t *__start__ps_irqchips[];
extern ps_irqchip_t *__stop__ps_irqchips[];
#define ARM_GIC_COMPAT_STRING "arm,cortex-a9-gic"
#define ARM_GIC_COMPAT_STRLEN sizeof(ARM_GIC_COMPAT_STRING)
static int parse_tegra_ictlr_interrupts(char *dtb_blob, int node_offset, int intr_controller_phandle,
irq_walk_cb_fn_t callback, void *token)
{
/* Look for the ARM GIC parser module and call their function.
*
* The tegra interrupt controllers have the same encodings as the ARM GIC, they just forward any
* interrupts to the GIC. */
for (ps_irqchip_t **irqchip = __start__ps_irqchips; irqchip < __stop__ps_irqchips; irqchip++) {
for (char **compatible_str = (*irqchip)->compatible_list; *compatible_str != NULL; compatible_str++) {
/* To account for the NULL byte */
size_t compat_str_len = strlen(*compatible_str) + 1;
size_t compare_length = (compat_str_len < ARM_GIC_COMPAT_STRLEN) ? compat_str_len
: ARM_GIC_COMPAT_STRLEN;
if (strncmp(ARM_GIC_COMPAT_STRING, *compatible_str, compare_length)) {
return (*irqchip)->parser_fn(dtb_blob, node_offset, intr_controller_phandle, callback, token);
}
}
}
ZF_LOGE("Couldn't find the ARM GIC parser module!");
return -EINVAL;
}
char *tegra_ictlr_compatible_list[] = {
"nvidia,tegra210-ictlr",
"nvidia,tegra124-ictlr",
"nvidia,tegra30-ictlr",
NULL
};
DEFINE_IRQCHIP_PARSER(tegra_ictlr, tegra_ictlr_compatible_list, parse_tegra_ictlr_interrupts);