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