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*9e3c57c8SEtienne Carriere #ifdef CFG_DT 77a4f139d7SJerome Forissier /* 78a4f139d7SJerome Forissier * Find a driver that is suitable for the given DT node, that is, with 79a4f139d7SJerome Forissier * a matching "compatible" property. 80a4f139d7SJerome Forissier * 81a4f139d7SJerome Forissier * @fdt: pointer to the device tree 82a4f139d7SJerome Forissier * @offs: node offset 83a4f139d7SJerome Forissier */ 84a4f139d7SJerome Forissier const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 85a4f139d7SJerome Forissier 869fe4c797SJerome Forissier /* 877ba16abbSJerome Forissier * Map a device into secure or non-secure memory and return the base VA and 887ba16abbSJerome Forissier * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 897ba16abbSJerome Forissier * MEM_AREA_IO_NSEC, depending on the device status. 907ba16abbSJerome Forissier * If the mapping already exists, the function simply returns the @vbase and 917ba16abbSJerome Forissier * @size information. 927ba16abbSJerome Forissier * 937ba16abbSJerome Forissier * @offs is the offset of the node that describes the device in @fdt. 947ba16abbSJerome Forissier * @base receives the base virtual address corresponding to the base physical 957ba16abbSJerome Forissier * address of the "reg" property 967ba16abbSJerome Forissier * @size receives the size of the mapping 97a5d5bbc8SVesa Jääskeläinen * @mapping what kind of mapping is done for memory. 987ba16abbSJerome Forissier * 997ba16abbSJerome Forissier * Returns 0 on success or -1 in case of error. 1007ba16abbSJerome Forissier */ 101a5d5bbc8SVesa Jääskeläinen int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 102a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping); 1037ba16abbSJerome Forissier 1047ba16abbSJerome Forissier /* 10550f3b323SPeng Fan * Check whether the node at @offs contains the property with propname or not. 10650f3b323SPeng Fan * 10750f3b323SPeng Fan * @offs is the offset of the node that describes the device in @fdt. 10850f3b323SPeng Fan * @propname is the property that need to check 10950f3b323SPeng Fan * 11050f3b323SPeng Fan * Returns true on success or false if no propname. 11150f3b323SPeng Fan */ 11250f3b323SPeng Fan bool dt_have_prop(const void *fdt, int offs, const char *propname); 11350f3b323SPeng Fan 11450f3b323SPeng Fan /* 11595cdc5e0SCedric Neveux * Modify or add "status" property to "disabled" 11695cdc5e0SCedric Neveux * 11795cdc5e0SCedric Neveux * @fdt reference to the Device Tree 11895cdc5e0SCedric Neveux * @node is the node offset to modify 11995cdc5e0SCedric Neveux * 12095cdc5e0SCedric Neveux * Returns 0 on success or -1 on failure 12195cdc5e0SCedric Neveux */ 12295cdc5e0SCedric Neveux int dt_disable_status(void *fdt, int node); 12395cdc5e0SCedric Neveux 12495cdc5e0SCedric Neveux /* 12595cdc5e0SCedric Neveux * Force secure-status = "okay" and status="disabled" for the target node. 12695cdc5e0SCedric Neveux * 12795cdc5e0SCedric Neveux * @fdt reference to the Device Tree 12895cdc5e0SCedric Neveux * @node is the node offset to modify 12995cdc5e0SCedric Neveux * 13095cdc5e0SCedric Neveux * Returns 0 on success or -1 on failure 13195cdc5e0SCedric Neveux */ 13295cdc5e0SCedric Neveux int dt_enable_secure_status(void *fdt, int node); 13395cdc5e0SCedric Neveux 13495cdc5e0SCedric Neveux /* 1359fe4c797SJerome Forissier * FDT manipulation functions, not provided by <libfdt.h> 1369fe4c797SJerome Forissier */ 1379fe4c797SJerome Forissier 1389fe4c797SJerome Forissier /* 1399fe4c797SJerome Forissier * Return the base address for the "reg" property of the specified node or 1409fe4c797SJerome Forissier * (paddr_t)-1 in case of error 1419fe4c797SJerome Forissier */ 142f354a5d8SGatien Chevallier paddr_t fdt_reg_base_address(const void *fdt, int offs); 1439fe4c797SJerome Forissier 1449fe4c797SJerome Forissier /* 1459fe4c797SJerome Forissier * Return the reg size for the reg property of the specified node or -1 in case 1469fe4c797SJerome Forissier * of error 1479fe4c797SJerome Forissier */ 148f354a5d8SGatien Chevallier size_t fdt_reg_size(const void *fdt, int offs); 1499fe4c797SJerome Forissier 1509fe4c797SJerome Forissier /* 1519fe4c797SJerome Forissier * Read the status and secure-status properties into a bitfield. 152c020046dSEtienne Carriere * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, 153c020046dSEtienne Carriere * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. 1549fe4c797SJerome Forissier */ 155f354a5d8SGatien Chevallier int fdt_get_status(const void *fdt, int offs); 1569fe4c797SJerome Forissier 157c0cfb36cSEtienne Carriere /* 158c0cfb36cSEtienne Carriere * fdt_fill_device_info - Get generic device info from a node 159c0cfb36cSEtienne Carriere * 160c0cfb36cSEtienne Carriere * This function fills the generic information from a given node. 161c0cfb36cSEtienne Carriere * Currently supports a single base register, a single clock, 162c0cfb36cSEtienne Carriere * a single reset ID line and a single interrupt ID. 163c0cfb36cSEtienne Carriere * Default DT_INFO_* macros are used when the relate property is not found. 164c0cfb36cSEtienne Carriere */ 165f354a5d8SGatien Chevallier void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, 166df45c114SEtienne Carriere int node); 167876826f3SGabriel Fernandez /* 168876826f3SGabriel Fernandez * Read cells from a given property of the given node. Any number of 32-bit 169876826f3SGabriel Fernandez * cells of the property can be read. Returns 0 on success, or a negative 170876826f3SGabriel Fernandez * FDT error value otherwise. 171876826f3SGabriel Fernandez */ 172f354a5d8SGatien Chevallier int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 173876826f3SGabriel Fernandez uint32_t *array, size_t count); 174876826f3SGabriel Fernandez 175876826f3SGabriel Fernandez /* 1767c3a6b7bSGatien Chevallier * Read one cell from a given multi-value property of the given node. 1777c3a6b7bSGatien Chevallier * Returns 0 on success, or a negative FDT error value otherwise. 1787c3a6b7bSGatien Chevallier */ 1797c3a6b7bSGatien Chevallier int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 1807c3a6b7bSGatien Chevallier int index, uint32_t *value); 1817c3a6b7bSGatien Chevallier 1827c3a6b7bSGatien Chevallier /* 183876826f3SGabriel Fernandez * Read one cell from a given property of the given node. 184876826f3SGabriel Fernandez * Returns 0 on success, or a negative FDT error value otherwise. 185876826f3SGabriel Fernandez */ 186f354a5d8SGatien Chevallier int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 187876826f3SGabriel Fernandez uint32_t *value); 188876826f3SGabriel Fernandez 189876826f3SGabriel Fernandez /* 190876826f3SGabriel Fernandez * Read one cell from a property of a cell or default to a given value 191876826f3SGabriel Fernandez * Returns the 32bit cell value or @dflt_value on failure. 192876826f3SGabriel Fernandez */ 193f354a5d8SGatien Chevallier uint32_t fdt_read_uint32_default(const void *fdt, int node, 194876826f3SGabriel Fernandez const char *prop_name, uint32_t dflt_value); 195876826f3SGabriel Fernandez 196876826f3SGabriel Fernandez /* 19707ced948SGatien Chevallier * This function fills reg node info (base & size) with an index. 19807ced948SGatien Chevallier * 19907ced948SGatien Chevallier * Returns 0 on success and a negative FDT error code on failure. 20007ced948SGatien Chevallier */ 20107ced948SGatien Chevallier int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 20207ced948SGatien Chevallier paddr_t *base, size_t *size); 20307ced948SGatien Chevallier 20407ced948SGatien Chevallier /* 20507ced948SGatien Chevallier * This function fills reg node info (base & size) with an index found by 20607ced948SGatien Chevallier * checking the reg-names node. 20707ced948SGatien Chevallier * 20807ced948SGatien Chevallier * Returns 0 on success and a negative FDT error code on failure. 20907ced948SGatien Chevallier */ 21007ced948SGatien Chevallier int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 21107ced948SGatien Chevallier paddr_t *base, size_t *size); 21207ced948SGatien Chevallier 2139fe4c797SJerome Forissier #else /* !CFG_DT */ 214a4f139d7SJerome Forissier 215a4f139d7SJerome Forissier static inline const struct dt_driver *dt_find_compatible_driver( 216a4f139d7SJerome Forissier const void *fdt __unused, 217a4f139d7SJerome Forissier int offs __unused) 218a4f139d7SJerome Forissier { 219a4f139d7SJerome Forissier return NULL; 220a4f139d7SJerome Forissier } 221a4f139d7SJerome Forissier 2227ba16abbSJerome Forissier static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 223a5d5bbc8SVesa Jääskeläinen vaddr_t *vbase __unused, size_t *size __unused, 224a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping __unused) 2257ba16abbSJerome Forissier { 2267ba16abbSJerome Forissier return -1; 2277ba16abbSJerome Forissier } 2287ba16abbSJerome Forissier 229f354a5d8SGatien Chevallier static inline paddr_t fdt_reg_base_address(const void *fdt __unused, 2309fe4c797SJerome Forissier int offs __unused) 2319fe4c797SJerome Forissier { 2329fe4c797SJerome Forissier return (paddr_t)-1; 2339fe4c797SJerome Forissier } 2349fe4c797SJerome Forissier 235f354a5d8SGatien Chevallier static inline size_t fdt_reg_size(const void *fdt __unused, 2369fe4c797SJerome Forissier int offs __unused) 2379fe4c797SJerome Forissier { 238df7cecc0SLionel Debieve return (size_t)-1; 2399fe4c797SJerome Forissier } 2409fe4c797SJerome Forissier 241f354a5d8SGatien Chevallier static inline int fdt_get_status(const void *fdt __unused, int offs __unused) 2429fe4c797SJerome Forissier { 2439fe4c797SJerome Forissier return -1; 2449fe4c797SJerome Forissier } 2459fe4c797SJerome Forissier 2461e866588SJerome Forissier __noreturn 247f354a5d8SGatien Chevallier static inline void fdt_fill_device_info(const void *fdt __unused, 248c0cfb36cSEtienne Carriere struct dt_node_info *info __unused, 249c0cfb36cSEtienne Carriere int node __unused) 250c0cfb36cSEtienne Carriere { 251c0cfb36cSEtienne Carriere panic(); 252c0cfb36cSEtienne Carriere } 253876826f3SGabriel Fernandez 254f354a5d8SGatien Chevallier static inline int fdt_read_uint32_array(const void *fdt __unused, 255876826f3SGabriel Fernandez int node __unused, 256876826f3SGabriel Fernandez const char *prop_name __unused, 257876826f3SGabriel Fernandez uint32_t *array __unused, 258876826f3SGabriel Fernandez size_t count __unused) 259876826f3SGabriel Fernandez { 260876826f3SGabriel Fernandez return -1; 261876826f3SGabriel Fernandez } 262876826f3SGabriel Fernandez 263f354a5d8SGatien Chevallier static inline int fdt_read_uint32(const void *fdt __unused, 264876826f3SGabriel Fernandez int node __unused, 265876826f3SGabriel Fernandez const char *prop_name __unused, 266876826f3SGabriel Fernandez uint32_t *value __unused) 267876826f3SGabriel Fernandez { 268876826f3SGabriel Fernandez return -1; 269876826f3SGabriel Fernandez } 270876826f3SGabriel Fernandez 271f354a5d8SGatien Chevallier static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, 272876826f3SGabriel Fernandez int node __unused, 273876826f3SGabriel Fernandez const char *prop_name __unused, 274876826f3SGabriel Fernandez uint32_t dflt_value __unused) 275876826f3SGabriel Fernandez { 276876826f3SGabriel Fernandez return dflt_value; 277876826f3SGabriel Fernandez } 278876826f3SGabriel Fernandez 2797c3a6b7bSGatien Chevallier static inline int fdt_read_uint32_index(const void *fdt __unused, 2807c3a6b7bSGatien Chevallier int node __unused, 2817c3a6b7bSGatien Chevallier const char *prop_name __unused, 2827c3a6b7bSGatien Chevallier int index __unused, 2837c3a6b7bSGatien Chevallier uint32_t *value __unused) 2847c3a6b7bSGatien Chevallier { 2857c3a6b7bSGatien Chevallier return -1; 2867c3a6b7bSGatien Chevallier } 2877c3a6b7bSGatien Chevallier 28807ced948SGatien Chevallier static inline int fdt_get_reg_props_by_index(const void *fdt __unused, 28907ced948SGatien Chevallier int node __unused, 29007ced948SGatien Chevallier int index __unused, 29107ced948SGatien Chevallier paddr_t *base __unused, 29207ced948SGatien Chevallier size_t *size __unused) 29307ced948SGatien Chevallier { 29407ced948SGatien Chevallier return -1; 29507ced948SGatien Chevallier } 29607ced948SGatien Chevallier 29707ced948SGatien Chevallier static inline int fdt_get_reg_props_by_name(const void *fdt __unused, 29807ced948SGatien Chevallier int node __unused, 29907ced948SGatien Chevallier const char *name __unused, 30007ced948SGatien Chevallier paddr_t *base __unused, 30107ced948SGatien Chevallier size_t *size __unused) 30207ced948SGatien Chevallier { 30307ced948SGatien Chevallier return -1; 30407ced948SGatien Chevallier } 30507ced948SGatien Chevallier 306a4f139d7SJerome Forissier #endif /* !CFG_DT */ 307a4f139d7SJerome Forissier #endif /* KERNEL_DT_H */ 308