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#include <platsupport/irq.h> 17#include <platsupport/io.h> 18#include <platsupport/pmem.h> 19 20/* We make an assumption that the size of the address/size cells are no larger than 2 21 * RISCV does have 128 bits but there are no platforms that use that bit length (yet) */ 22#define READ_CELL32(addr) fdt32_ld(addr) 23#define READ_CELL64(addr) fdt64_ld(addr) 24#define READ_CELL(size, addr, offset) (size == 2 ? READ_CELL64(addr + (offset * sizeof(uint32_t))) : \ 25 READ_CELL32(addr + (offset * sizeof(uint32_t)))) 26 27/* 28 * Type of the callback function that is called for each device register instance 29 * during a call to ps_fdt_walk_registers. 30 * 31 * @param pmem Description of the device register instance. 32 * @param curr_num A number indicating the current register instance that we are currently at. 33 * @param num_regs The total number of register instances that the device that we are walking through has. 34 * 35 * @return 0 on success, otherwise an error code 36 */ 37typedef int (*reg_walk_cb_fn_t)(pmem_region_t pmem, unsigned curr_num, size_t num_regs, void *token); 38 39/* 40 * Type of the callback function that is called for each device interrupt 41 * instance during a call to ps_fdt_walk_irqs. 42 * 43 * @param irq Description of the device interrupt instance. 44 * @param curr_num A number indicating the current interrupt instance that we are currently at. 45 * @param num_irqs The total number of interrupt instances that the device that we are walking through has. 46 * 47 * @return 0 on success, otherwise an error code 48 */ 49typedef int (*irq_walk_cb_fn_t)(ps_irq_t irq, unsigned curr_num, size_t num_irqs, void *token); 50 51/* An internal private struct used by the utility functions in this library. */ 52typedef struct ps_fdt_cookie ps_fdt_cookie_t; 53 54/* 55 * Given a devicetree path, this function will return a cookie that can be used in 56 * the other functions in this library. 57 * 58 * @param io_fdt An initialised IO FDT interface. 59 * @param malloc_ops An initialised malloc interface. 60 * @param path Devicetree path to the device for which you want to use the utility functions on. 61 * @param ret_cookie Storage that will have the pointer to the corresponding cookie written to. 62 * 63 * @returns 0 on success, otherwise -EINVAL, -ENOMEM, or one of the error codes in libfdt 64 */ 65int ps_fdt_read_path(ps_io_fdt_t *io_fdt, ps_malloc_ops_t *malloc_ops, const char *path, ps_fdt_cookie_t **ret_cookie); 66 67/* 68 * Cleans up a cookie that was initialised by ps_fdt_read_path. 69 * 70 * @param malloc_ops An initialised malloc interface. 71 * @param cookie A pointer to a initialised cookie. 72 * 73 * @returns 0 on success, otherwise -EINVAL 74 */ 75int ps_fdt_cleanup_cookie(ps_malloc_ops_t *malloc_ops, ps_fdt_cookie_t *cookie); 76 77/* 78 * Walks the registers property of the device node (if any) corresponding to the 79 * cookie passed in and calls a callback function at each register instance of 80 * the field. 81 * 82 * @param io_fdt An initialised IO FDT interface. 83 * @param cookie A pointer to a initialised cookie. 84 * @param callback Pointer to a callback function that is called at each register instance of the property. 85 * @param token Pointer to be passed into the callback function when it is called. 86 * 87 * @returns 0 on success, otherwise: 88 * - one of the error codes in libfdt 89 * - -EINVAL 90 * - the error returned by the callback function 91 */ 92 93int ps_fdt_walk_registers(ps_io_fdt_t *io_fdt, ps_fdt_cookie_t *cookie, reg_walk_cb_fn_t callback, void *token); 94 95/* 96 * Walks the interrupts/interrupts-extended field of the device node (if any) 97 * corresponding to the cookie passed in and calls a callback function at each 98 * interrupt instance of the field. Note that depending on the interrupt parser 99 * modules available, this function may fail to parse the interrupt property. 100 * 101 * The modules can checked by looking inside the libplatsupport/src/arch/arm/irqchip/ folder. 102 * 103 * @param io_fdt An initialised IO FDT interface. 104 * @param cookie A pointer to a initialised cookie. 105 * @param callback Pointer to a callback function that is called at each interrupt instance of the property. 106 * @param token Pointer to be passed into the callback function when it is called. 107 * 108 * @returns 0 on success, otherwise: 109 * - one of the error codes in libfdt 110 * - -EINVAL or -ENOENT for no suitable interrupt parsing module 111 * - the error returned by the callback function 112 */ 113int ps_fdt_walk_irqs(ps_io_fdt_t *io_fdt, ps_fdt_cookie_t *cookie, irq_walk_cb_fn_t callback, void *token); 114 115/* 116 * Convenience function for ps_fdt_walk_registers which does not require a callback but instead 117 * uses an offset to map in the desired registers from a device's registers property. Useful 118 * for when you know the exact structure of the devicetree blob. 119 * @param io_ops An initialised IO ops interface. 120 * @param cookie A pointer to an initialised FDT interface cookie. 121 * @param offset The offset to the desired registers in the device's (that the cookie points to) 122 * registers property. 123 * @param ret_pmem A pointer that will have the details of the mapped registered block written to. 124 * Can be NULL. 125 * 126 * @returns The virtual address of the registers that were mapped in, NULL on error. 127 */ 128void *ps_fdt_index_map_register(ps_io_ops_t *io_ops, ps_fdt_cookie_t *cookie, unsigned offset, 129 pmem_region_t *ret_pmem); 130 131/* 132 * Convenience function for ps_fdt_walk_irqs which does not require a callback but instead 133 * uses an offset to map in the desired interrupt from a device's interrupts property. Useful 134 * for when you know the exact structure of the devicetree blob. 135 * @param io_ops An initialised IO ops interface. 136 * @param cookie A pointer to an initialised FDT interface cookie. 137 * @param offset The offset to the desired interrupt in the device's (that the cookie points to) 138 * interrupt property. 139 * @param irq_callback Callback function that will be associated with the registered interrupt. 140 * @param irq_callback_data Token that will be passed to the callback function. 141 * 142 * @returns The IRQ ID of the registered interrupt, a negative error code on error. 143 */ 144irq_id_t ps_fdt_index_register_irq(ps_io_ops_t *io_ops, ps_fdt_cookie_t *cookie, unsigned offset, 145 irq_callback_fn_t irq_callback, void *irq_callback_data); 146