blob: f0cc9500ebac266f023706f77252a6d0efeac0fc [file] [log] [blame] [edit]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <libfdt.h>
#include <platsupport/irq.h>
#include <platsupport/fdt.h>
#include <utils/util.h>
/* Macro to streamline process of declaring new interrupt parsing modules */
#define DEFINE_IRQCHIP_PARSER(instance, compatible_strings, parser_func) \
static ps_irqchip_t instance = { \
.compatible_list = compatible_strings, \
.parser_fn = parser_func \
}; \
USED SECTION("_ps_irqchips") ps_irqchip_t *instance##_ptr = &instance
/*
* Expected function type of the interrupt parsing functions.
*
* Given offset of the device node in the FDT, this should read the interrupts
* property, parse it and call the callback function on each interrupt instance
* of the property.
*
* @param dtb_blob A blob of a platform's FDT.
* @param node_offset Offset to the device node to be parsed.
* @param intr_controller_phandle Phandle to the interrupt controller that handles the interrupts of the device.
* @param callback Pointer to a callback function that is called at each interrupt instance in the property.
* @param token Pointer to a token that is passed into the callback each time it is called.
*
* @returns 0 on success, otherwise an error code
*/
typedef int (*ps_irqchip_parse_fn_t)(char *dtb_blob, int node_offset, int intr_controller_phandle,
irq_walk_cb_fn_t callback, void *token);
/*
* Struct describing a IRQ parser module.
*/
typedef struct ps_irqchip {
/* Array of compatibility strings for interrupt
* controllers that the module can handle, should be NULL terminated, e.g.
* foo = { "abc", NULL } */
char **compatible_list;
/* Pointer to the parser function for this module */
ps_irqchip_parse_fn_t parser_fn;
} ps_irqchip_t;
/*
* Helper function that retrieves a pointer to the interrupts property of a device.
*
* @param dtb_blob A blob of a platform's FDT.
* @param node_offset Offset to the desired device node.
* @param is_extended Pointer to a boolean that will have true written to it if the 'interrupts-extended' property was found, false otherwise
* @param prop_len Pointer to an int that will have the total length of the interrupts property written to it
*/
static inline const void *get_interrupts_prop(char *dtb_blob, int node_offset, bool *is_extended, int *prop_len)
{
ZF_LOGF_IF(!is_extended || !prop_len, "Ret args are NULL!");
const void *interrupts_prop = fdt_getprop(dtb_blob, node_offset, "interrupts-extended", prop_len);
if (interrupts_prop) {
*is_extended = true;
return interrupts_prop;
}
interrupts_prop = fdt_getprop(dtb_blob, node_offset, "interrupts", prop_len);
if (interrupts_prop) {
*is_extended = false;
return interrupts_prop;
}
return NULL;
}