1/*
2 * Copyright 2019, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#pragma once
14
15#include <libfdt.h>
16
17#include <platsupport/irq.h>
18#include <platsupport/fdt.h>
19#include <utils/util.h>
20
21/* Macro to streamline process of declaring new interrupt parsing modules */
22#define DEFINE_IRQCHIP_PARSER(instance, compatible_strings, parser_func)  \
23    static ps_irqchip_t instance = {                                      \
24        .compatible_list = compatible_strings,                            \
25        .parser_fn = parser_func                                          \
26    };                                                                    \
27    USED SECTION("_ps_irqchips") ps_irqchip_t *instance##_ptr = &instance
28
29/*
30 * Expected function type of the interrupt parsing functions.
31 *
32 * Given offset of the device node in the FDT, this should read the interrupts
33 * property, parse it and call the callback function on each interrupt instance
34 * of the property.
35 *
36 * @param dtb_blob A blob of a platform's FDT.
37 * @param node_offset Offset to the device node to be parsed.
38 * @param intr_controller_phandle Phandle to the interrupt controller that handles the interrupts of the device.
39 * @param callback Pointer to a callback function that is called at each interrupt instance in the property.
40 * @param token Pointer to a token that is passed into the callback each time it is called.
41 *
42 * @returns 0 on success, otherwise an error code
43 */
44typedef int (*ps_irqchip_parse_fn_t)(char *dtb_blob, int node_offset, int intr_controller_phandle,
45                                     irq_walk_cb_fn_t callback, void *token);
46
47/*
48 * Struct describing a IRQ parser module.
49 */
50typedef struct ps_irqchip {
51    /* Array of compatibility strings for interrupt
52     * controllers that the module can handle, should be NULL terminated, e.g.
53     * foo = { "abc", NULL } */
54    char **compatible_list;
55    /* Pointer to the parser function for this module */
56    ps_irqchip_parse_fn_t parser_fn;
57} ps_irqchip_t;
58
59/*
60 * Helper function that retrieves a pointer to the interrupts property of a device.
61 *
62 * @param dtb_blob A blob of a platform's FDT.
63 * @param node_offset Offset to the desired device node.
64 * @param is_extended Pointer to a boolean that will have true written to it if the 'interrupts-extended' property was found, false otherwise
65 * @param prop_len Pointer to an int that will have the total length of the interrupts property written to it
66 */
67static inline const void *get_interrupts_prop(char *dtb_blob, int node_offset, bool *is_extended, int *prop_len)
68{
69    ZF_LOGF_IF(!is_extended || !prop_len, "Ret args are NULL!");
70    const void *interrupts_prop = fdt_getprop(dtb_blob, node_offset, "interrupts-extended", prop_len);
71    if (interrupts_prop) {
72        *is_extended = true;
73        return interrupts_prop;
74    }
75
76    interrupts_prop = fdt_getprop(dtb_blob, node_offset, "interrupts", prop_len);
77    if (interrupts_prop) {
78        *is_extended = false;
79        return interrupts_prop;
80    }
81
82    return NULL;
83}
84