11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */ 2a4f139d7SJerome Forissier /* 301254f1dSEtienne Carriere * Copyright (c) 2016-2021, Linaro Limited 4a4f139d7SJerome Forissier */ 5a4f139d7SJerome Forissier 6a4f139d7SJerome Forissier #ifndef KERNEL_DT_H 7a4f139d7SJerome Forissier #define KERNEL_DT_H 8a4f139d7SJerome Forissier 9a4f139d7SJerome Forissier #include <compiler.h> 10702fe5a7SClément Léger #include <kernel/interrupt.h> 11c0cfb36cSEtienne Carriere #include <kernel/panic.h> 1261bdedeaSJerome Forissier #include <scattered_array.h> 13a4f139d7SJerome Forissier #include <stdint.h> 1401254f1dSEtienne Carriere #include <tee_api_types.h> 15a4f139d7SJerome Forissier #include <types_ext.h> 169fe4c797SJerome Forissier #include <util.h> 179fe4c797SJerome Forissier 189fe4c797SJerome Forissier /* 1923b1daf4SPeng Fan * Bitfield to reflect status and secure-status values ("okay", "disabled" 2023b1daf4SPeng Fan * or not present) 219fe4c797SJerome Forissier */ 22b4bfc9a9SJens Wiklander #define DT_STATUS_DISABLED U(0) 239fe4c797SJerome Forissier #define DT_STATUS_OK_NSEC BIT(0) 249fe4c797SJerome Forissier #define DT_STATUS_OK_SEC BIT(1) 25a4f139d7SJerome Forissier 26c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_REG ((paddr_t)-1) 27df7cecc0SLionel Debieve #define DT_INFO_INVALID_REG_SIZE ((size_t)-1) 28c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_CLOCK -1 29c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_RESET -1 3095cdc5e0SCedric Neveux #define DT_INFO_INVALID_INTERRUPT -1 3195cdc5e0SCedric Neveux 32c0cfb36cSEtienne Carriere /* 33c0cfb36cSEtienne Carriere * @status: Bit mask for DT_STATUS_* 34c0cfb36cSEtienne Carriere * @reg: Device register physical base address or DT_INFO_INVALID_REG 3506fd21ddSLionel Debieve * @reg_size: Device register size or DT_INFO_INVALID_REG_SIZE 36c0cfb36cSEtienne Carriere * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK 37c0cfb36cSEtienne Carriere * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK 387acb3a47SLudovic Barre * @interrupt: Device interrupt identifier (positive value) or 397acb3a47SLudovic Barre * DT_INFO_INVALID_INTERRUPT 40702fe5a7SClément Léger * @type: IRQ_TYPE_* value parsed from interrupts properties or IRQ_TYPE_NONE if 41702fe5a7SClément Léger * not present 42702fe5a7SClément Léger * @prio: interrupt priority parsed from interrupts properties or 0 if not 43702fe5a7SClément Léger * present 44c0cfb36cSEtienne Carriere */ 45c0cfb36cSEtienne Carriere struct dt_node_info { 46c0cfb36cSEtienne Carriere unsigned int status; 47c0cfb36cSEtienne Carriere paddr_t reg; 4806fd21ddSLionel Debieve size_t reg_size; 49c0cfb36cSEtienne Carriere int clock; 50c0cfb36cSEtienne Carriere int reset; 517acb3a47SLudovic Barre int interrupt; 52702fe5a7SClément Léger uint32_t type; 53702fe5a7SClément Léger uint32_t prio; 54c0cfb36cSEtienne Carriere }; 55c0cfb36cSEtienne Carriere 56a4f139d7SJerome Forissier /* 57a4f139d7SJerome Forissier * DT-aware drivers 58a4f139d7SJerome Forissier */ 59a4f139d7SJerome Forissier 60a4f139d7SJerome Forissier struct dt_device_match { 61a4f139d7SJerome Forissier const char *compatible; 627e6a39feSEtienne Carriere const void *compat_data; 63a4f139d7SJerome Forissier }; 64a4f139d7SJerome Forissier 6501254f1dSEtienne Carriere /* 66a5d5bbc8SVesa Jääskeläinen * DT_MAP_AUTO: Uses status properties from device tree to determine mapping. 67a5d5bbc8SVesa Jääskeläinen * DT_MAP_SECURE: Force mapping for device to be secure. 68a5d5bbc8SVesa Jääskeläinen * DT_MAP_NON_SECURE: Force mapping for device to be non-secure. 69a5d5bbc8SVesa Jääskeläinen */ 70a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive { 71a5d5bbc8SVesa Jääskeläinen DT_MAP_AUTO, 72a5d5bbc8SVesa Jääskeläinen DT_MAP_SECURE, 73a5d5bbc8SVesa Jääskeläinen DT_MAP_NON_SECURE 74a5d5bbc8SVesa Jääskeläinen }; 75a5d5bbc8SVesa Jääskeläinen 76*4e45454aSJens Wiklander /* 77*4e45454aSJens Wiklander * dt_getprop_as_number() - get a DT property a unsigned number 78*4e45454aSJens Wiklander * @fdt: DT base address 79*4e45454aSJens Wiklander * @nodeoffset: node offset 80*4e45454aSJens Wiklander * @name: property string name 81*4e45454aSJens Wiklander * @num: output number read 82*4e45454aSJens Wiklander * Return 0 on success and a negative FDT error value on error 83*4e45454aSJens Wiklander * 84*4e45454aSJens Wiklander * The size of the property determines if it is read as an unsigned 32-bit 85*4e45454aSJens Wiklander * or 64-bit integer. 86*4e45454aSJens Wiklander */ 87*4e45454aSJens Wiklander int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, 88*4e45454aSJens Wiklander uint64_t *num); 89*4e45454aSJens Wiklander 909e3c57c8SEtienne Carriere #ifdef CFG_DT 91a4f139d7SJerome Forissier /* 92a4f139d7SJerome Forissier * Find a driver that is suitable for the given DT node, that is, with 93a4f139d7SJerome Forissier * a matching "compatible" property. 94a4f139d7SJerome Forissier * 95a4f139d7SJerome Forissier * @fdt: pointer to the device tree 96a4f139d7SJerome Forissier * @offs: node offset 97a4f139d7SJerome Forissier */ 98a4f139d7SJerome Forissier const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 99a4f139d7SJerome Forissier 1009fe4c797SJerome Forissier /* 1017ba16abbSJerome Forissier * Map a device into secure or non-secure memory and return the base VA and 1027ba16abbSJerome Forissier * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 1037ba16abbSJerome Forissier * MEM_AREA_IO_NSEC, depending on the device status. 1047ba16abbSJerome Forissier * If the mapping already exists, the function simply returns the @vbase and 1057ba16abbSJerome Forissier * @size information. 1067ba16abbSJerome Forissier * 1077ba16abbSJerome Forissier * @offs is the offset of the node that describes the device in @fdt. 1087ba16abbSJerome Forissier * @base receives the base virtual address corresponding to the base physical 1097ba16abbSJerome Forissier * address of the "reg" property 1107ba16abbSJerome Forissier * @size receives the size of the mapping 111a5d5bbc8SVesa Jääskeläinen * @mapping what kind of mapping is done for memory. 1127ba16abbSJerome Forissier * 1137ba16abbSJerome Forissier * Returns 0 on success or -1 in case of error. 1147ba16abbSJerome Forissier */ 115a5d5bbc8SVesa Jääskeläinen int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 116a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping); 1177ba16abbSJerome Forissier 1187ba16abbSJerome Forissier /* 11950f3b323SPeng Fan * Check whether the node at @offs contains the property with propname or not. 12050f3b323SPeng Fan * 12150f3b323SPeng Fan * @offs is the offset of the node that describes the device in @fdt. 12250f3b323SPeng Fan * @propname is the property that need to check 12350f3b323SPeng Fan * 12450f3b323SPeng Fan * Returns true on success or false if no propname. 12550f3b323SPeng Fan */ 12650f3b323SPeng Fan bool dt_have_prop(const void *fdt, int offs, const char *propname); 12750f3b323SPeng Fan 12850f3b323SPeng Fan /* 12995cdc5e0SCedric Neveux * Modify or add "status" property to "disabled" 13095cdc5e0SCedric Neveux * 13195cdc5e0SCedric Neveux * @fdt reference to the Device Tree 13295cdc5e0SCedric Neveux * @node is the node offset to modify 13395cdc5e0SCedric Neveux * 13495cdc5e0SCedric Neveux * Returns 0 on success or -1 on failure 13595cdc5e0SCedric Neveux */ 13695cdc5e0SCedric Neveux int dt_disable_status(void *fdt, int node); 13795cdc5e0SCedric Neveux 13895cdc5e0SCedric Neveux /* 13995cdc5e0SCedric Neveux * Force secure-status = "okay" and status="disabled" for the target node. 14095cdc5e0SCedric Neveux * 14195cdc5e0SCedric Neveux * @fdt reference to the Device Tree 14295cdc5e0SCedric Neveux * @node is the node offset to modify 14395cdc5e0SCedric Neveux * 14495cdc5e0SCedric Neveux * Returns 0 on success or -1 on failure 14595cdc5e0SCedric Neveux */ 14695cdc5e0SCedric Neveux int dt_enable_secure_status(void *fdt, int node); 14795cdc5e0SCedric Neveux 14895cdc5e0SCedric Neveux /* 1499fe4c797SJerome Forissier * FDT manipulation functions, not provided by <libfdt.h> 1509fe4c797SJerome Forissier */ 1519fe4c797SJerome Forissier 1529fe4c797SJerome Forissier /* 1539fe4c797SJerome Forissier * Return the base address for the "reg" property of the specified node or 1549fe4c797SJerome Forissier * (paddr_t)-1 in case of error 1559fe4c797SJerome Forissier */ 156f354a5d8SGatien Chevallier paddr_t fdt_reg_base_address(const void *fdt, int offs); 1579fe4c797SJerome Forissier 1589fe4c797SJerome Forissier /* 1599fe4c797SJerome Forissier * Return the reg size for the reg property of the specified node or -1 in case 1609fe4c797SJerome Forissier * of error 1619fe4c797SJerome Forissier */ 162f354a5d8SGatien Chevallier size_t fdt_reg_size(const void *fdt, int offs); 1639fe4c797SJerome Forissier 1649fe4c797SJerome Forissier /* 1659fe4c797SJerome Forissier * Read the status and secure-status properties into a bitfield. 166c020046dSEtienne Carriere * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, 167c020046dSEtienne Carriere * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. 1689fe4c797SJerome Forissier */ 169f354a5d8SGatien Chevallier int fdt_get_status(const void *fdt, int offs); 1709fe4c797SJerome Forissier 171c0cfb36cSEtienne Carriere /* 172c0cfb36cSEtienne Carriere * fdt_fill_device_info - Get generic device info from a node 173c0cfb36cSEtienne Carriere * 174c0cfb36cSEtienne Carriere * This function fills the generic information from a given node. 175c0cfb36cSEtienne Carriere * Currently supports a single base register, a single clock, 176c0cfb36cSEtienne Carriere * a single reset ID line and a single interrupt ID. 177c0cfb36cSEtienne Carriere * Default DT_INFO_* macros are used when the relate property is not found. 178c0cfb36cSEtienne Carriere */ 179f354a5d8SGatien Chevallier void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, 180df45c114SEtienne Carriere int node); 181876826f3SGabriel Fernandez /* 182876826f3SGabriel Fernandez * Read cells from a given property of the given node. Any number of 32-bit 183876826f3SGabriel Fernandez * cells of the property can be read. Returns 0 on success, or a negative 184876826f3SGabriel Fernandez * FDT error value otherwise. 185876826f3SGabriel Fernandez */ 186f354a5d8SGatien Chevallier int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 187876826f3SGabriel Fernandez uint32_t *array, size_t count); 188876826f3SGabriel Fernandez 189876826f3SGabriel Fernandez /* 1907c3a6b7bSGatien Chevallier * Read one cell from a given multi-value property of the given node. 1917c3a6b7bSGatien Chevallier * Returns 0 on success, or a negative FDT error value otherwise. 1927c3a6b7bSGatien Chevallier */ 1937c3a6b7bSGatien Chevallier int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 1947c3a6b7bSGatien Chevallier int index, uint32_t *value); 1957c3a6b7bSGatien Chevallier 1967c3a6b7bSGatien Chevallier /* 197876826f3SGabriel Fernandez * Read one cell from a given property of the given node. 198876826f3SGabriel Fernandez * Returns 0 on success, or a negative FDT error value otherwise. 199876826f3SGabriel Fernandez */ 200f354a5d8SGatien Chevallier int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 201876826f3SGabriel Fernandez uint32_t *value); 202876826f3SGabriel Fernandez 203876826f3SGabriel Fernandez /* 204876826f3SGabriel Fernandez * Read one cell from a property of a cell or default to a given value 205876826f3SGabriel Fernandez * Returns the 32bit cell value or @dflt_value on failure. 206876826f3SGabriel Fernandez */ 207f354a5d8SGatien Chevallier uint32_t fdt_read_uint32_default(const void *fdt, int node, 208876826f3SGabriel Fernandez const char *prop_name, uint32_t dflt_value); 209876826f3SGabriel Fernandez 210876826f3SGabriel Fernandez /* 21107ced948SGatien Chevallier * This function fills reg node info (base & size) with an index. 21207ced948SGatien Chevallier * 21307ced948SGatien Chevallier * Returns 0 on success and a negative FDT error code on failure. 21407ced948SGatien Chevallier */ 21507ced948SGatien Chevallier int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 21607ced948SGatien Chevallier paddr_t *base, size_t *size); 21707ced948SGatien Chevallier 21807ced948SGatien Chevallier /* 21907ced948SGatien Chevallier * This function fills reg node info (base & size) with an index found by 22007ced948SGatien Chevallier * checking the reg-names node. 22107ced948SGatien Chevallier * 22207ced948SGatien Chevallier * Returns 0 on success and a negative FDT error code on failure. 22307ced948SGatien Chevallier */ 22407ced948SGatien Chevallier int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 22507ced948SGatien Chevallier paddr_t *base, size_t *size); 22607ced948SGatien Chevallier 2279fe4c797SJerome Forissier #else /* !CFG_DT */ 228a4f139d7SJerome Forissier 229a4f139d7SJerome Forissier static inline const struct dt_driver *dt_find_compatible_driver( 230a4f139d7SJerome Forissier const void *fdt __unused, 231a4f139d7SJerome Forissier int offs __unused) 232a4f139d7SJerome Forissier { 233a4f139d7SJerome Forissier return NULL; 234a4f139d7SJerome Forissier } 235a4f139d7SJerome Forissier 2367ba16abbSJerome Forissier static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 237a5d5bbc8SVesa Jääskeläinen vaddr_t *vbase __unused, size_t *size __unused, 238a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping __unused) 2397ba16abbSJerome Forissier { 2407ba16abbSJerome Forissier return -1; 2417ba16abbSJerome Forissier } 2427ba16abbSJerome Forissier 243f354a5d8SGatien Chevallier static inline paddr_t fdt_reg_base_address(const void *fdt __unused, 2449fe4c797SJerome Forissier int offs __unused) 2459fe4c797SJerome Forissier { 2469fe4c797SJerome Forissier return (paddr_t)-1; 2479fe4c797SJerome Forissier } 2489fe4c797SJerome Forissier 249f354a5d8SGatien Chevallier static inline size_t fdt_reg_size(const void *fdt __unused, 2509fe4c797SJerome Forissier int offs __unused) 2519fe4c797SJerome Forissier { 252df7cecc0SLionel Debieve return (size_t)-1; 2539fe4c797SJerome Forissier } 2549fe4c797SJerome Forissier 255f354a5d8SGatien Chevallier static inline int fdt_get_status(const void *fdt __unused, int offs __unused) 2569fe4c797SJerome Forissier { 2579fe4c797SJerome Forissier return -1; 2589fe4c797SJerome Forissier } 2599fe4c797SJerome Forissier 2601e866588SJerome Forissier __noreturn 261f354a5d8SGatien Chevallier static inline void fdt_fill_device_info(const void *fdt __unused, 262c0cfb36cSEtienne Carriere struct dt_node_info *info __unused, 263c0cfb36cSEtienne Carriere int node __unused) 264c0cfb36cSEtienne Carriere { 265c0cfb36cSEtienne Carriere panic(); 266c0cfb36cSEtienne Carriere } 267876826f3SGabriel Fernandez 268f354a5d8SGatien Chevallier static inline int fdt_read_uint32_array(const void *fdt __unused, 269876826f3SGabriel Fernandez int node __unused, 270876826f3SGabriel Fernandez const char *prop_name __unused, 271876826f3SGabriel Fernandez uint32_t *array __unused, 272876826f3SGabriel Fernandez size_t count __unused) 273876826f3SGabriel Fernandez { 274876826f3SGabriel Fernandez return -1; 275876826f3SGabriel Fernandez } 276876826f3SGabriel Fernandez 277f354a5d8SGatien Chevallier static inline int fdt_read_uint32(const void *fdt __unused, 278876826f3SGabriel Fernandez int node __unused, 279876826f3SGabriel Fernandez const char *prop_name __unused, 280876826f3SGabriel Fernandez uint32_t *value __unused) 281876826f3SGabriel Fernandez { 282876826f3SGabriel Fernandez return -1; 283876826f3SGabriel Fernandez } 284876826f3SGabriel Fernandez 285f354a5d8SGatien Chevallier static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, 286876826f3SGabriel Fernandez int node __unused, 287876826f3SGabriel Fernandez const char *prop_name __unused, 288876826f3SGabriel Fernandez uint32_t dflt_value __unused) 289876826f3SGabriel Fernandez { 290876826f3SGabriel Fernandez return dflt_value; 291876826f3SGabriel Fernandez } 292876826f3SGabriel Fernandez 2937c3a6b7bSGatien Chevallier static inline int fdt_read_uint32_index(const void *fdt __unused, 2947c3a6b7bSGatien Chevallier int node __unused, 2957c3a6b7bSGatien Chevallier const char *prop_name __unused, 2967c3a6b7bSGatien Chevallier int index __unused, 2977c3a6b7bSGatien Chevallier uint32_t *value __unused) 2987c3a6b7bSGatien Chevallier { 2997c3a6b7bSGatien Chevallier return -1; 3007c3a6b7bSGatien Chevallier } 3017c3a6b7bSGatien Chevallier 30207ced948SGatien Chevallier static inline int fdt_get_reg_props_by_index(const void *fdt __unused, 30307ced948SGatien Chevallier int node __unused, 30407ced948SGatien Chevallier int index __unused, 30507ced948SGatien Chevallier paddr_t *base __unused, 30607ced948SGatien Chevallier size_t *size __unused) 30707ced948SGatien Chevallier { 30807ced948SGatien Chevallier return -1; 30907ced948SGatien Chevallier } 31007ced948SGatien Chevallier 31107ced948SGatien Chevallier static inline int fdt_get_reg_props_by_name(const void *fdt __unused, 31207ced948SGatien Chevallier int node __unused, 31307ced948SGatien Chevallier const char *name __unused, 31407ced948SGatien Chevallier paddr_t *base __unused, 31507ced948SGatien Chevallier size_t *size __unused) 31607ced948SGatien Chevallier { 31707ced948SGatien Chevallier return -1; 31807ced948SGatien Chevallier } 31907ced948SGatien Chevallier 320a4f139d7SJerome Forissier #endif /* !CFG_DT */ 321a4f139d7SJerome Forissier #endif /* KERNEL_DT_H */ 322