11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */ 2a4f139d7SJerome Forissier /* 3a4f139d7SJerome Forissier * Copyright (c) 2016, 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> 10*c0cfb36cSEtienne Carriere #include <kernel/panic.h> 11a4f139d7SJerome Forissier #include <stdint.h> 12a4f139d7SJerome Forissier #include <types_ext.h> 139fe4c797SJerome Forissier #include <util.h> 149fe4c797SJerome Forissier 159fe4c797SJerome Forissier /* 1623b1daf4SPeng Fan * Bitfield to reflect status and secure-status values ("okay", "disabled" 1723b1daf4SPeng Fan * or not present) 189fe4c797SJerome Forissier */ 199fe4c797SJerome Forissier #define DT_STATUS_DISABLED 0 209fe4c797SJerome Forissier #define DT_STATUS_OK_NSEC BIT(0) 219fe4c797SJerome Forissier #define DT_STATUS_OK_SEC BIT(1) 22a4f139d7SJerome Forissier 23*c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_REG ((paddr_t)-1) 24*c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_CLOCK -1 25*c0cfb36cSEtienne Carriere #define DT_INFO_INVALID_RESET -1 26*c0cfb36cSEtienne Carriere /* 27*c0cfb36cSEtienne Carriere * @status: Bit mask for DT_STATUS_* 28*c0cfb36cSEtienne Carriere * @reg: Device register physical base address or DT_INFO_INVALID_REG 29*c0cfb36cSEtienne Carriere * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK 30*c0cfb36cSEtienne Carriere * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK 31*c0cfb36cSEtienne Carriere */ 32*c0cfb36cSEtienne Carriere struct dt_node_info { 33*c0cfb36cSEtienne Carriere unsigned int status; 34*c0cfb36cSEtienne Carriere paddr_t reg; 35*c0cfb36cSEtienne Carriere int clock; 36*c0cfb36cSEtienne Carriere int reset; 37*c0cfb36cSEtienne Carriere }; 38*c0cfb36cSEtienne Carriere 39a4f139d7SJerome Forissier #if defined(CFG_DT) 40a4f139d7SJerome Forissier 41a4f139d7SJerome Forissier /* 42a4f139d7SJerome Forissier * DT-aware drivers 43a4f139d7SJerome Forissier */ 44a4f139d7SJerome Forissier 45a4f139d7SJerome Forissier struct dt_device_match { 46a4f139d7SJerome Forissier const char *compatible; 47a4f139d7SJerome Forissier }; 48a4f139d7SJerome Forissier 49a4f139d7SJerome Forissier struct dt_driver { 50a4f139d7SJerome Forissier const char *name; 51a4f139d7SJerome Forissier const struct dt_device_match *match_table; /* null-terminated */ 52a4f139d7SJerome Forissier const void *driver; 53a4f139d7SJerome Forissier }; 54a4f139d7SJerome Forissier 55fd118772SJerome Forissier #define __dt_driver __section(".rodata.dtdrv" __SECTION_FLAGS_RODATA) 56a4f139d7SJerome Forissier 57a4f139d7SJerome Forissier /* 58a4f139d7SJerome Forissier * Find a driver that is suitable for the given DT node, that is, with 59a4f139d7SJerome Forissier * a matching "compatible" property. 60a4f139d7SJerome Forissier * 61a4f139d7SJerome Forissier * @fdt: pointer to the device tree 62a4f139d7SJerome Forissier * @offs: node offset 63a4f139d7SJerome Forissier */ 64a4f139d7SJerome Forissier const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 65a4f139d7SJerome Forissier 66a4f139d7SJerome Forissier const struct dt_driver *__dt_driver_start(void); 67a4f139d7SJerome Forissier 68a4f139d7SJerome Forissier const struct dt_driver *__dt_driver_end(void); 69a4f139d7SJerome Forissier 709fe4c797SJerome Forissier /* 717ba16abbSJerome Forissier * Map a device into secure or non-secure memory and return the base VA and 727ba16abbSJerome Forissier * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 737ba16abbSJerome Forissier * MEM_AREA_IO_NSEC, depending on the device status. 747ba16abbSJerome Forissier * If the mapping already exists, the function simply returns the @vbase and 757ba16abbSJerome Forissier * @size information. 767ba16abbSJerome Forissier * 777ba16abbSJerome Forissier * @offs is the offset of the node that describes the device in @fdt. 787ba16abbSJerome Forissier * @base receives the base virtual address corresponding to the base physical 797ba16abbSJerome Forissier * address of the "reg" property 807ba16abbSJerome Forissier * @size receives the size of the mapping 817ba16abbSJerome Forissier * 827ba16abbSJerome Forissier * Returns 0 on success or -1 in case of error. 837ba16abbSJerome Forissier */ 847ba16abbSJerome Forissier int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size); 857ba16abbSJerome Forissier 867ba16abbSJerome Forissier /* 8750f3b323SPeng Fan * Check whether the node at @offs contains the property with propname or not. 8850f3b323SPeng Fan * 8950f3b323SPeng Fan * @offs is the offset of the node that describes the device in @fdt. 9050f3b323SPeng Fan * @propname is the property that need to check 9150f3b323SPeng Fan * 9250f3b323SPeng Fan * Returns true on success or false if no propname. 9350f3b323SPeng Fan */ 9450f3b323SPeng Fan bool dt_have_prop(const void *fdt, int offs, const char *propname); 9550f3b323SPeng Fan 9650f3b323SPeng Fan /* 979fe4c797SJerome Forissier * FDT manipulation functions, not provided by <libfdt.h> 989fe4c797SJerome Forissier */ 999fe4c797SJerome Forissier 1009fe4c797SJerome Forissier /* 1019fe4c797SJerome Forissier * Return the base address for the "reg" property of the specified node or 1029fe4c797SJerome Forissier * (paddr_t)-1 in case of error 1039fe4c797SJerome Forissier */ 1049fe4c797SJerome Forissier paddr_t _fdt_reg_base_address(const void *fdt, int offs); 1059fe4c797SJerome Forissier 1069fe4c797SJerome Forissier /* 1079fe4c797SJerome Forissier * Return the reg size for the reg property of the specified node or -1 in case 1089fe4c797SJerome Forissier * of error 1099fe4c797SJerome Forissier */ 1109fe4c797SJerome Forissier ssize_t _fdt_reg_size(const void *fdt, int offs); 1119fe4c797SJerome Forissier 1129fe4c797SJerome Forissier /* 1139fe4c797SJerome Forissier * Read the status and secure-status properties into a bitfield. 1149fe4c797SJerome Forissier * @status is set to DT_STATUS_DISABLED or a combination of DT_STATUS_OK_NSEC 1159fe4c797SJerome Forissier * and DT_STATUS_OK_SEC 1169fe4c797SJerome Forissier * Returns 0 on success or -1 in case of error. 1179fe4c797SJerome Forissier */ 1189fe4c797SJerome Forissier int _fdt_get_status(const void *fdt, int offs); 1199fe4c797SJerome Forissier 120*c0cfb36cSEtienne Carriere /* 121*c0cfb36cSEtienne Carriere * fdt_fill_device_info - Get generic device info from a node 122*c0cfb36cSEtienne Carriere * 123*c0cfb36cSEtienne Carriere * This function fills the generic information from a given node. 124*c0cfb36cSEtienne Carriere * Currently supports a single base register, a single clock, 125*c0cfb36cSEtienne Carriere * a single reset ID line and a single interrupt ID. 126*c0cfb36cSEtienne Carriere * Default DT_INFO_* macros are used when the relate property is not found. 127*c0cfb36cSEtienne Carriere */ 128*c0cfb36cSEtienne Carriere void _fdt_fill_device_info(void *fdt, struct dt_node_info *info, int node); 129*c0cfb36cSEtienne Carriere 1309fe4c797SJerome Forissier #else /* !CFG_DT */ 131a4f139d7SJerome Forissier 132a4f139d7SJerome Forissier static inline const struct dt_driver *__dt_driver_start(void) 133a4f139d7SJerome Forissier { 134a4f139d7SJerome Forissier return NULL; 135a4f139d7SJerome Forissier } 136a4f139d7SJerome Forissier 137a4f139d7SJerome Forissier static inline const struct dt_driver *__dt_driver_end(void) 138a4f139d7SJerome Forissier { 139a4f139d7SJerome Forissier return NULL; 140a4f139d7SJerome Forissier } 141a4f139d7SJerome Forissier 142a4f139d7SJerome Forissier static inline const struct dt_driver *dt_find_compatible_driver( 143a4f139d7SJerome Forissier const void *fdt __unused, 144a4f139d7SJerome Forissier int offs __unused) 145a4f139d7SJerome Forissier { 146a4f139d7SJerome Forissier return NULL; 147a4f139d7SJerome Forissier } 148a4f139d7SJerome Forissier 1497ba16abbSJerome Forissier static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 1507ba16abbSJerome Forissier vaddr_t *vbase __unused, size_t *size __unused) 1517ba16abbSJerome Forissier { 1527ba16abbSJerome Forissier return -1; 1537ba16abbSJerome Forissier } 1547ba16abbSJerome Forissier 1559fe4c797SJerome Forissier static inline paddr_t _fdt_reg_base_address(const void *fdt __unused, 1569fe4c797SJerome Forissier int offs __unused) 1579fe4c797SJerome Forissier { 1589fe4c797SJerome Forissier return (paddr_t)-1; 1599fe4c797SJerome Forissier } 1609fe4c797SJerome Forissier 1619fe4c797SJerome Forissier static inline ssize_t _fdt_reg_size(const void *fdt __unused, 1629fe4c797SJerome Forissier int offs __unused) 1639fe4c797SJerome Forissier { 1649fe4c797SJerome Forissier return -1; 1659fe4c797SJerome Forissier } 1669fe4c797SJerome Forissier 1679fe4c797SJerome Forissier static inline int _fdt_get_status(const void *fdt __unused, int offs __unused) 1689fe4c797SJerome Forissier { 1699fe4c797SJerome Forissier return -1; 1709fe4c797SJerome Forissier } 1719fe4c797SJerome Forissier 172*c0cfb36cSEtienne Carriere static inline void _fdt_fill_device_info(void *fdt __unused, 173*c0cfb36cSEtienne Carriere struct dt_node_info *info __unused, 174*c0cfb36cSEtienne Carriere int node __unused) 175*c0cfb36cSEtienne Carriere { 176*c0cfb36cSEtienne Carriere panic(); 177*c0cfb36cSEtienne Carriere } 178a4f139d7SJerome Forissier #endif /* !CFG_DT */ 179a4f139d7SJerome Forissier 180a4f139d7SJerome Forissier #define for_each_dt_driver(drv) \ 181a4f139d7SJerome Forissier for (drv = __dt_driver_start(); drv < __dt_driver_end(); drv++) 182a4f139d7SJerome Forissier 183a4f139d7SJerome Forissier #endif /* KERNEL_DT_H */ 184