1 /* 2 * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <errno.h> 8 9 #include <libfdt.h> 10 11 #include <platform_def.h> 12 13 #include <drivers/st/stm32_gpio.h> 14 #include <drivers/st/stm32mp_clkfunc.h> 15 16 #define DT_STGEN_COMPAT "st,stm32-stgen" 17 18 /* 19 * Get the RCC node offset from the device tree 20 * @param fdt: Device tree reference 21 * @return: Node offset or a negative value on error 22 */ 23 int fdt_get_rcc_node(void *fdt) 24 { 25 return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); 26 } 27 28 /* 29 * Get the RCC base address from the device tree 30 * @return: RCC address or 0 on error 31 */ 32 uint32_t fdt_rcc_read_addr(void) 33 { 34 int node; 35 void *fdt; 36 const fdt32_t *cuint; 37 38 if (fdt_get_address(&fdt) == 0) { 39 return 0; 40 } 41 42 node = fdt_get_rcc_node(fdt); 43 if (node < 0) { 44 return 0; 45 } 46 47 cuint = fdt_getprop(fdt, node, "reg", NULL); 48 if (cuint == NULL) { 49 return 0; 50 } 51 52 return fdt32_to_cpu(*cuint); 53 } 54 55 /* 56 * Read a series of parameters in rcc-clk section in device tree 57 * @param prop_name: Name of the RCC property to be read 58 * @param array: the array to store the property parameters 59 * @param count: number of parameters to be read 60 * @return: 0 on succes or a negative value on error 61 */ 62 int fdt_rcc_read_uint32_array(const char *prop_name, 63 uint32_t *array, uint32_t count) 64 { 65 int node; 66 void *fdt; 67 68 if (fdt_get_address(&fdt) == 0) { 69 return -ENOENT; 70 } 71 72 node = fdt_get_rcc_node(fdt); 73 if (node < 0) { 74 return -FDT_ERR_NOTFOUND; 75 } 76 77 return fdt_read_uint32_array(node, prop_name, array, count); 78 } 79 80 /* 81 * Get the subnode offset in rcc-clk section from its name in device tree 82 * @param name: name of the RCC property 83 * @return: offset on success, and a negative FDT/ERRNO error code on failure. 84 */ 85 int fdt_rcc_subnode_offset(const char *name) 86 { 87 int node, subnode; 88 void *fdt; 89 90 if (fdt_get_address(&fdt) == 0) { 91 return -ENOENT; 92 } 93 94 node = fdt_get_rcc_node(fdt); 95 if (node < 0) { 96 return -FDT_ERR_NOTFOUND; 97 } 98 99 subnode = fdt_subnode_offset(fdt, node, name); 100 if (subnode <= 0) { 101 return -FDT_ERR_NOTFOUND; 102 } 103 104 return subnode; 105 } 106 107 /* 108 * Get the pointer to a rcc-clk property from its name. 109 * @param name: name of the RCC property 110 * @param lenp: stores the length of the property. 111 * @return: pointer to the property on success, and NULL value on failure. 112 */ 113 const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) 114 { 115 const fdt32_t *cuint; 116 int node, len; 117 void *fdt; 118 119 if (fdt_get_address(&fdt) == 0) { 120 return NULL; 121 } 122 123 node = fdt_get_rcc_node(fdt); 124 if (node < 0) { 125 return NULL; 126 } 127 128 cuint = fdt_getprop(fdt, node, prop_name, &len); 129 if (cuint == NULL) { 130 return NULL; 131 } 132 133 *lenp = len; 134 return cuint; 135 } 136 137 /* 138 * Get the secure status for rcc node in device tree. 139 * @return: true if rcc is available from secure world, false if not. 140 */ 141 bool fdt_get_rcc_secure_status(void) 142 { 143 int node; 144 void *fdt; 145 146 if (fdt_get_address(&fdt) == 0) { 147 return false; 148 } 149 150 node = fdt_get_rcc_node(fdt); 151 if (node < 0) { 152 return false; 153 } 154 155 return !!(fdt_get_status(node) & DT_SECURE); 156 } 157 158 /* 159 * Get the stgen base address. 160 * @return: address of stgen on success, and NULL value on failure. 161 */ 162 uintptr_t fdt_get_stgen_base(void) 163 { 164 int node; 165 const fdt32_t *cuint; 166 void *fdt; 167 168 if (fdt_get_address(&fdt) == 0) { 169 return 0; 170 } 171 172 node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); 173 if (node < 0) { 174 return 0; 175 } 176 177 cuint = fdt_getprop(fdt, node, "reg", NULL); 178 if (cuint == NULL) { 179 return 0; 180 } 181 182 return fdt32_to_cpu(*cuint); 183 } 184 185 /* 186 * Get the clock ID of the given node in device tree. 187 * @param node: node offset 188 * @return: Clock ID on success, and a negative FDT/ERRNO error code on failure. 189 */ 190 int fdt_get_clock_id(int node) 191 { 192 const fdt32_t *cuint; 193 void *fdt; 194 195 if (fdt_get_address(&fdt) == 0) { 196 return -ENOENT; 197 } 198 199 cuint = fdt_getprop(fdt, node, "clocks", NULL); 200 if (cuint == NULL) { 201 return -FDT_ERR_NOTFOUND; 202 } 203 204 cuint++; 205 return (int)fdt32_to_cpu(*cuint); 206 } 207